From f8f9148016662578804479180a70e3732b08c11c Mon Sep 17 00:00:00 2001 From: Quan Anh Mai Date: Tue, 4 Jan 2022 22:59:33 +0000 Subject: [PATCH 001/564] 8278948: compiler/vectorapi/reshape/TestVectorCastAVX1.java crashes in assembler Reviewed-by: kvn, sviswanathan --- src/hotspot/cpu/x86/x86.ad | 25 +++--- .../jtreg/compiler/vectorapi/Test8278948.java | 82 +++++++++++++++++++ 2 files changed, 92 insertions(+), 15 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/vectorapi/Test8278948.java diff --git a/src/hotspot/cpu/x86/x86.ad b/src/hotspot/cpu/x86/x86.ad index 298e874e331..8b36de39cdc 100644 --- a/src/hotspot/cpu/x86/x86.ad +++ b/src/hotspot/cpu/x86/x86.ad @@ -1,5 +1,5 @@ // -// Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2011, 2022, 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 @@ -1783,17 +1783,9 @@ const bool Matcher::match_rule_supported_vector(int opcode, int vlen, BasicType } break; case Op_VectorCastB2X: - if (size_in_bits == 256 && UseAVX < 2) { - return false; // Implementation limitation - } - break; case Op_VectorCastS2X: - if (is_integral_type(bt) && size_in_bits == 256 && UseAVX < 2) { - return false; - } - break; case Op_VectorCastI2X: - if (is_integral_type(bt) && size_in_bits == 256 && UseAVX < 2) { + if (bt != T_DOUBLE && size_in_bits == 256 && UseAVX < 2) { return false; } break; @@ -6906,11 +6898,12 @@ instruct vcastBtoX(vec dst, vec src) %{ case T_LONG: __ vpmovsxbq($dst$$XMMRegister, $src$$XMMRegister, vlen_enc); break; - case T_DOUBLE: - __ vpmovsxbd($dst$$XMMRegister, $src$$XMMRegister, vlen_enc); + case T_DOUBLE: { + int mid_vlen_enc = (vlen_enc == Assembler::AVX_512bit) ? Assembler::AVX_256bit : Assembler::AVX_128bit; + __ vpmovsxbd($dst$$XMMRegister, $src$$XMMRegister, mid_vlen_enc); __ vcvtdq2pd($dst$$XMMRegister, $dst$$XMMRegister, vlen_enc); break; - + } default: assert(false, "%s", type2name(to_elem_bt)); } %} @@ -6977,10 +6970,12 @@ instruct vcastStoX_evex(vec dst, vec src) %{ case T_LONG: __ vpmovsxwq($dst$$XMMRegister, $src$$XMMRegister, vlen_enc); break; - case T_DOUBLE: - __ vpmovsxwd($dst$$XMMRegister, $src$$XMMRegister, vlen_enc); + case T_DOUBLE: { + int mid_vlen_enc = (vlen_enc == Assembler::AVX_512bit) ? Assembler::AVX_256bit : Assembler::AVX_128bit; + __ vpmovsxwd($dst$$XMMRegister, $src$$XMMRegister, mid_vlen_enc); __ vcvtdq2pd($dst$$XMMRegister, $dst$$XMMRegister, vlen_enc); break; + } default: ShouldNotReachHere(); } diff --git a/test/hotspot/jtreg/compiler/vectorapi/Test8278948.java b/test/hotspot/jtreg/compiler/vectorapi/Test8278948.java new file mode 100644 index 00000000000..5218e10c4af --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorapi/Test8278948.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2022, 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 compiler.vectorapi; + +import java.util.Random; +import jdk.incubator.vector.ByteVector; +import jdk.incubator.vector.DoubleVector; +import jdk.incubator.vector.ShortVector; +import jdk.test.lib.Asserts; +import jdk.test.lib.Utils; + +/* + * @test + * @bug 8278948 + * @summary Intermediate integer promotion vector length encoding is calculated incorrectly on x86 + * @modules jdk.incubator.vector + * @library /test/lib + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:CompileThreshold=100 -XX:UseAVX=1 + * compiler.vectorapi.Test8278948 + */ +public class Test8278948 { + static final int INVOCATIONS = 10000; + + static final Random random = Utils.getRandomInstance(); + static final byte[] BYTES = new byte[8]; + static final short[] SHORTS = new short[4]; + static final double[] DOUBLES = new double[4]; + + + public static void main(String[] args) { + for (int i = 0; i < INVOCATIONS; i++) { + for (int j = 0; j < DOUBLES.length; j++) { + BYTES[j] = (byte)random.nextInt(); + } + bytesToDoubles(); + for (int j = 0; j < DOUBLES.length; j++) { + Asserts.assertEquals((double)BYTES[j], DOUBLES[j]); + } + + for (int j = 0; j < DOUBLES.length; j++) { + SHORTS[j] = (short)random.nextInt(); + } + shortsToDoubles(); + for (int j = 0; j < DOUBLES.length; j++) { + Asserts.assertEquals((double)SHORTS[j], DOUBLES[j]); + } + } + } + + static void bytesToDoubles() { + ((DoubleVector)ByteVector.fromArray(ByteVector.SPECIES_64, BYTES, 0) + .castShape(DoubleVector.SPECIES_256, 0)) + .intoArray(DOUBLES, 0); + } + + static void shortsToDoubles() { + ((DoubleVector)ShortVector.fromArray(ShortVector.SPECIES_64, SHORTS, 0) + .castShape(DoubleVector.SPECIES_256, 0)) + .intoArray(DOUBLES, 0); + } +} -- GitLab From 8b5de27ce1e4fe664e08879c2ca89d08db710c9d Mon Sep 17 00:00:00 2001 From: bobpengxie Date: Wed, 5 Jan 2022 02:22:26 +0000 Subject: [PATCH 002/564] 8279485: Incorrect copyright year in compiler/lib/ir_framework/IRNode.java after JDK-8278114 Reviewed-by: haosun, jiefu --- test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java index 87a7825e682..783319445eb 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022, 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 -- GitLab From 0f4807e8fe2468f303b32a6f2dc9ccc7ecad82a1 Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Wed, 5 Jan 2022 07:29:17 +0000 Subject: [PATCH 003/564] 8279222: Incorrect legacyMap.get in java.security.Provider after JDK-8276660 Co-authored-by: Valerie Peng Reviewed-by: alanb, valeriep --- .../share/classes/java/security/Provider.java | 4 ++-- .../Provider/CaseSensitiveServices.java | 20 +++++++++++++++---- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/java.base/share/classes/java/security/Provider.java b/src/java.base/share/classes/java/security/Provider.java index c6c3d63c61f..c1c4bea90cd 100644 --- a/src/java.base/share/classes/java/security/Provider.java +++ b/src/java.base/share/classes/java/security/Provider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2022, 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 @@ -1149,7 +1149,7 @@ public abstract class Provider extends Properties { switch (opType) { case ADD: // clean up old alias if present - Service prevAliasService = legacyMap.get(aliasAlg); + Service prevAliasService = legacyMap.get(aliasKey); if (prevAliasService != null) { prevAliasService.removeAlias(aliasAlg); } diff --git a/test/jdk/java/security/Provider/CaseSensitiveServices.java b/test/jdk/java/security/Provider/CaseSensitiveServices.java index 2a6676b4f58..d9b8d315bd0 100644 --- a/test/jdk/java/security/Provider/CaseSensitiveServices.java +++ b/test/jdk/java/security/Provider/CaseSensitiveServices.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2022, 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 5097015 8130181 + * @bug 5097015 8130181 8279222 * @summary make sure we correctly treat Provider string entries as case insensitive * @author Andreas Sterbenz */ @@ -36,9 +36,12 @@ public class CaseSensitiveServices extends Provider { super("Foo", "1.0", null); put("MessageDigest.Foo", "com.Foo"); put("mESSAGEdIGEST.fOO xYz", "aBc"); - put("ALg.aliaS.MESSAGEdigest.Fu", "FoO"); + // first assign the DEF alias to algorithm Foo + put("ALg.aliaS.MESSAGEdigest.DEF", "FoO"); put("messageDigest.Bar", "com.Bar"); put("MESSAGEDIGEST.BAZ", "com.Baz"); + // reassign the DEF alias to algorithm Bar + put("ALg.aliaS.MESSAGEdigest.DEF", "Bar"); } public static void main(String[] args) throws Exception { @@ -47,12 +50,21 @@ public class CaseSensitiveServices extends Provider { if (p.getServices().size() != 3) { throw new Exception("services.size() should be 3"); } + Service s = testService(p, "MessageDigest", "fOO"); String val = s.getAttribute("Xyz"); if ("aBc".equals(val) == false) { throw new Exception("Wrong value: " + val); } - testService(p, "MessageDigest", "fU"); + if (s.toString().indexOf("DEF") != -1) { + throw new Exception("Old alias DEF should be removed"); + } + + // test Service alias DEF and its associated impl is Bar + s = testService(p, "MessageDigest", "DeF"); + if (s.getAttribute("Xyz") != null) { + throw new Exception("DEF mapped to the wrong impl"); + } testService(p, "MessageDigest", "BAR"); testService(p, "MessageDigest", "baz"); System.out.println("OK"); -- GitLab From 9d43d25da8bcfff425a795dcc230914a384a5c82 Mon Sep 17 00:00:00 2001 From: Maurizio Cimadamore Date: Wed, 5 Jan 2022 10:47:34 +0000 Subject: [PATCH 004/564] 8278897: Alignment of heap segments is not enforced correctly Reviewed-by: jvernee --- .../invoke/MemoryAccessVarHandleBase.java | 4 +- .../X-VarHandleMemoryAccess.java.template | 11 +- .../access/foreign/MemorySegmentProxy.java | 1 + .../jdk/incubator/foreign/MemoryAddress.java | 78 ++++++++ .../jdk/incubator/foreign/MemorySegment.java | 182 ++++++++++++++++-- .../foreign/AbstractMemorySegmentImpl.java | 15 +- .../foreign/HeapMemorySegmentImpl.java | 40 ++++ .../jdk/internal/foreign/LayoutPath.java | 4 +- .../internal/foreign/MemoryAddressImpl.java | 14 ++ .../foreign/NativeMemorySegmentImpl.java | 5 + .../classes/jdk/internal/foreign/Utils.java | 14 +- test/jdk/java/foreign/TestArrayCopy.java | 12 ++ test/jdk/java/foreign/TestHeapAlignment.java | 131 +++++++++++++ .../foreign/TestMemoryAccessInstance.java | 46 ++++- .../jdk/java/foreign/TestMemoryAlignment.java | 2 +- test/jdk/java/foreign/TestSegmentCopy.java | 13 +- test/jdk/java/foreign/TestSpliterator.java | 5 + .../foreign/TestVarHandleCombinators.java | 2 +- .../foreign/LoopOverNonConstant.java | 23 +++ .../foreign/LoopOverNonConstantHeap.java | 32 ++- 20 files changed, 600 insertions(+), 34 deletions(-) create mode 100644 test/jdk/java/foreign/TestHeapAlignment.java diff --git a/src/java.base/share/classes/java/lang/invoke/MemoryAccessVarHandleBase.java b/src/java.base/share/classes/java/lang/invoke/MemoryAccessVarHandleBase.java index 59098e9fa74..7703c997fc3 100644 --- a/src/java.base/share/classes/java/lang/invoke/MemoryAccessVarHandleBase.java +++ b/src/java.base/share/classes/java/lang/invoke/MemoryAccessVarHandleBase.java @@ -50,7 +50,7 @@ abstract class MemoryAccessVarHandleBase extends VarHandle { this.alignmentMask = alignmentMask; } - static IllegalStateException newIllegalStateExceptionForMisalignedAccess(long address) { - return new IllegalStateException("Misaligned access at address: " + address); + static IllegalArgumentException newIllegalArgumentExceptionForMisalignedAccess(long address) { + return new IllegalArgumentException("Misaligned access at address: " + address); } } diff --git a/src/java.base/share/classes/java/lang/invoke/X-VarHandleMemoryAccess.java.template b/src/java.base/share/classes/java/lang/invoke/X-VarHandleMemoryAccess.java.template index 0bdfd212e07..bdb4904d994 100644 --- a/src/java.base/share/classes/java/lang/invoke/X-VarHandleMemoryAccess.java.template +++ b/src/java.base/share/classes/java/lang/invoke/X-VarHandleMemoryAccess.java.template @@ -106,7 +106,7 @@ final class MemoryAccessVarHandle$Type$Helper extends MemoryAccessVarHandleBase static long offset(boolean skipAlignmentMaskCheck, MemorySegmentProxy bb, long offset, long alignmentMask) { long address = offsetNoVMAlignCheck(skipAlignmentMaskCheck, bb, offset, alignmentMask); if ((address & VM_ALIGN) != 0) { - throw MemoryAccessVarHandleBase.newIllegalStateExceptionForMisalignedAccess(address); + throw MemoryAccessVarHandleBase.newIllegalArgumentExceptionForMisalignedAccess(address); } return address; } @@ -115,14 +115,15 @@ final class MemoryAccessVarHandle$Type$Helper extends MemoryAccessVarHandleBase static long offsetNoVMAlignCheck(boolean skipAlignmentMaskCheck, MemorySegmentProxy bb, long offset, long alignmentMask) { long base = bb.unsafeGetOffset(); long address = base + offset; + long maxAlignMask = bb.maxAlignMask(); if (skipAlignmentMaskCheck) { //note: the offset portion has already been aligned-checked, by construction - if ((base & alignmentMask) != 0) { - throw MemoryAccessVarHandleBase.newIllegalStateExceptionForMisalignedAccess(address); + if (((base | maxAlignMask) & alignmentMask) != 0) { + throw MemoryAccessVarHandleBase.newIllegalArgumentExceptionForMisalignedAccess(address); } } else { - if ((address & alignmentMask) != 0) { - throw MemoryAccessVarHandleBase.newIllegalStateExceptionForMisalignedAccess(address); + if (((address | maxAlignMask) & alignmentMask) != 0) { + throw MemoryAccessVarHandleBase.newIllegalArgumentExceptionForMisalignedAccess(address); } } return address; diff --git a/src/java.base/share/classes/jdk/internal/access/foreign/MemorySegmentProxy.java b/src/java.base/share/classes/jdk/internal/access/foreign/MemorySegmentProxy.java index a00b6516a55..068fcfa1a6b 100644 --- a/src/java.base/share/classes/jdk/internal/access/foreign/MemorySegmentProxy.java +++ b/src/java.base/share/classes/jdk/internal/access/foreign/MemorySegmentProxy.java @@ -44,6 +44,7 @@ public abstract class MemorySegmentProxy { public abstract Object unsafeGetBase(); public abstract boolean isSmall(); public abstract ScopedMemoryAccess.Scope scope(); + public abstract long maxAlignMask(); /* Helper functions for offset computations. These are required so that we can avoid issuing long opcodes * (e.g. LMUL, LADD) when we're operating on 'small' segments (segments whose length can be expressed with an int). diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryAddress.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryAddress.java index 7e94d63014c..47a17799700 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryAddress.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryAddress.java @@ -174,6 +174,8 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI * @param layout the layout of the memory region to be read. * @param offset offset in bytes (relative to this address). The final address of this read operation can be expressed as {@code toRowLongValue() + offset}. * @return a byte value read from this address. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout. * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. @@ -192,6 +194,8 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI * @param layout the layout of the memory region to be written. * @param offset offset in bytes (relative to this address). The final address of this write operation can be expressed as {@code toRowLongValue() + offset}. * @param value the byte value to be written. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout. * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. @@ -210,6 +214,8 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI * @param layout the layout of the memory region to be read. * @param offset offset in bytes (relative to this address). The final address of this read operation can be expressed as {@code toRowLongValue() + offset}. * @return a boolean value read from this address. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout. * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. @@ -228,6 +234,8 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI * @param layout the layout of the memory region to be written. * @param offset offset in bytes (relative to this address). The final address of this write operation can be expressed as {@code toRowLongValue() + offset}. * @param value the boolean value to be written. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout. * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. @@ -246,6 +254,8 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI * @param layout the layout of the memory region to be read. * @param offset offset in bytes (relative to this address). The final address of this read operation can be expressed as {@code toRowLongValue() + offset}. * @return a char value read from this address. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout. * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. @@ -264,6 +274,8 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI * @param layout the layout of the memory region to be written. * @param offset offset in bytes (relative to this address). The final address of this write operation can be expressed as {@code toRowLongValue() + offset}. * @param value the char value to be written. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout. * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. @@ -282,6 +294,8 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI * @param layout the layout of the memory region to be read. * @param offset offset in bytes (relative to this address). The final address of this read operation can be expressed as {@code toRowLongValue() + offset}. * @return a short value read from this address. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout. * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. @@ -300,6 +314,8 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI * @param layout the layout of the memory region to be written. * @param offset offset in bytes (relative to this address). The final address of this write operation can be expressed as {@code toRowLongValue() + offset}. * @param value the short value to be written. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout. * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. @@ -318,6 +334,8 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI * @param layout the layout of the memory region to be read. * @param offset offset in bytes (relative to this address). The final address of this read operation can be expressed as {@code toRowLongValue() + offset}. * @return an int value read from this address. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout. * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. @@ -336,6 +354,8 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI * @param layout the layout of the memory region to be written. * @param offset offset in bytes (relative to this address). The final address of this write operation can be expressed as {@code toRowLongValue() + offset}. * @param value the int value to be written. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout. * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. @@ -354,6 +374,8 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI * @param layout the layout of the memory region to be read. * @param offset offset in bytes (relative to this address). The final address of this read operation can be expressed as {@code toRowLongValue() + offset}. * @return a float value read from this address. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout. * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. @@ -372,6 +394,8 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI * @param layout the layout of the memory region to be written. * @param offset offset in bytes (relative to this address). The final address of this write operation can be expressed as {@code toRowLongValue() + offset}. * @param value the float value to be written. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout. * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. @@ -390,6 +414,8 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI * @param layout the layout of the memory region to be read. * @param offset offset in bytes (relative to this address). The final address of this read operation can be expressed as {@code toRowLongValue() + offset}. * @return a long value read from this address. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout. * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. @@ -408,6 +434,8 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI * @param layout the layout of the memory region to be written. * @param offset offset in bytes (relative to this address). The final address of this write operation can be expressed as {@code toRowLongValue() + offset}. * @param value the long value to be written. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout. * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. @@ -426,6 +454,8 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI * @param layout the layout of the memory region to be read. * @param offset offset in bytes (relative to this address). The final address of this read operation can be expressed as {@code toRowLongValue() + offset}. * @return a double value read from this address. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout. * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. @@ -444,6 +474,8 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI * @param layout the layout of the memory region to be written. * @param offset offset in bytes (relative to this address). The final address of this write operation can be expressed as {@code toRowLongValue() + offset}. * @param value the double value to be written. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout. * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. @@ -462,6 +494,8 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI * @param layout the layout of the memory region to be read. * @param offset offset in bytes (relative to this address). The final address of this read operation can be expressed as {@code toRowLongValue() + offset}. * @return an address value read from this address. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout. * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. @@ -480,6 +514,8 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI * @param layout the layout of the memory region to be written. * @param offset offset in bytes (relative to this address). The final address of this write operation can be expressed as {@code toRowLongValue() + offset}. * @param value the address value to be written. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout. * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. @@ -498,6 +534,9 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI * @param layout the layout of the memory region to be read. * @param index index in bytes (relative to this address). The final address of this read operation can be expressed as {@code toRowLongValue() + (index * layout.byteSize())}. * @return a char value read from this address. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout, + * or if the layout alignment is greater than its size. * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. @@ -516,6 +555,9 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI * @param layout the layout of the memory region to be written. * @param index index in bytes (relative to this address). The final address of this write operation can be expressed as {@code toRowLongValue() + (index * layout.byteSize())}. * @param value the char value to be written. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout, + * or if the layout alignment is greater than its size. * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. @@ -534,6 +576,9 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI * @param layout the layout of the memory region to be read. * @param index index in bytes (relative to this address). The final address of this read operation can be expressed as {@code toRowLongValue() + (index * layout.byteSize())}. * @return a short value read from this address. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout, + * or if the layout alignment is greater than its size. * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. @@ -552,6 +597,9 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI * @param layout the layout of the memory region to be written. * @param index index in bytes (relative to this address). The final address of this write operation can be expressed as {@code toRowLongValue() + (index * layout.byteSize())}. * @param value the short value to be written. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout, + * or if the layout alignment is greater than its size. * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. @@ -570,6 +618,9 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI * @param layout the layout of the memory region to be read. * @param index index in bytes (relative to this address). The final address of this read operation can be expressed as {@code toRowLongValue() + (index * layout.byteSize())}. * @return an int value read from this address. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout, + * or if the layout alignment is greater than its size. * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. @@ -588,6 +639,9 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI * @param layout the layout of the memory region to be written. * @param index index in bytes (relative to this address). The final address of this write operation can be expressed as {@code toRowLongValue() + (index * layout.byteSize())}. * @param value the int value to be written. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout, + * or if the layout alignment is greater than its size. * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. @@ -606,6 +660,9 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI * @param layout the layout of the memory region to be read. * @param index index in bytes (relative to this address). The final address of this read operation can be expressed as {@code toRowLongValue() + (index * layout.byteSize())}. * @return a float value read from this address. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout, + * or if the layout alignment is greater than its size. * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. @@ -624,6 +681,9 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI * @param layout the layout of the memory region to be written. * @param index index in bytes (relative to this address). The final address of this write operation can be expressed as {@code toRowLongValue() + (index * layout.byteSize())}. * @param value the float value to be written. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout, + * or if the layout alignment is greater than its size. * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. @@ -642,6 +702,9 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI * @param layout the layout of the memory region to be read. * @param index index in bytes (relative to this address). The final address of this read operation can be expressed as {@code toRowLongValue() + (index * layout.byteSize())}. * @return a long value read from this address. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout, + * or if the layout alignment is greater than its size. * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. @@ -660,6 +723,9 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI * @param layout the layout of the memory region to be written. * @param index index in bytes (relative to this address). The final address of this write operation can be expressed as {@code toRowLongValue() + (index * layout.byteSize())}. * @param value the long value to be written. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout, + * or if the layout alignment is greater than its size. * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. @@ -678,6 +744,9 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI * @param layout the layout of the memory region to be read. * @param index index in bytes (relative to this address). The final address of this read operation can be expressed as {@code toRowLongValue() + (index * layout.byteSize())}. * @return a double value read from this address. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout, + * or if the layout alignment is greater than its size. * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. @@ -696,6 +765,9 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI * @param layout the layout of the memory region to be written. * @param index index in bytes (relative to this address). The final address of this write operation can be expressed as {@code toRowLongValue() + (index * layout.byteSize())}. * @param value the double value to be written. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout, + * or if the layout alignment is greater than its size. * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. @@ -714,6 +786,9 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI * @param layout the layout of the memory region to be read. * @param index index in bytes (relative to this address). The final address of this read operation can be expressed as {@code toRowLongValue() + (index * layout.byteSize())}. * @return an address value read from this address. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout, + * or if the layout alignment is greater than its size. * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. @@ -732,6 +807,9 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI * @param layout the layout of the memory region to be written. * @param index index in bytes (relative to this address). The final address of this write operation can be expressed as {@code toRowLongValue() + (index * layout.byteSize())}. * @param value the address value to be written. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout, + * or if the layout alignment is greater than its size. * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemorySegment.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemorySegment.java index de974fa2e80..40cee4cf7d7 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemorySegment.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemorySegment.java @@ -139,6 +139,56 @@ import java.util.stream.Stream; * {@linkplain MemoryHandles#varHandle(ValueLayout) value layout}, and then adapt it using the var handle combinator * functions defined in the {@link MemoryHandles} class. * + *

Alignment

+ * + * When dereferencing a memory segment using a layout, the runtime must check that the segment address being dereferenced + * matches the layout's {@linkplain MemoryLayout#byteAlignment() alignment constraints}. If the segment being + * dereferenced is a native segment, then it has a concrete {@linkplain #address() base address}, which can + * be used to perform the alignment check. The pseudo-function below demonstrates this: + * + *
{@code
+boolean isAligned(MemorySegment segment, long offset, MemoryLayout layout) {
+   return ((segment.address().toRawLongValue() + offset) % layout.byteAlignment()) == 0
+}
+ * }
+ * + * If, however, the segment being dereferenced is a heap segment, the above function will not work: a heap + * segment's base address is virtualized and, as such, cannot be used to construct an alignment check. Instead, + * heap segments are assumed to produce addresses which are never more aligned than the element size of the Java array from which + * they have originated from, as shown in the following table: + * + *
+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Array type of an array backing a segment and its address alignment
Array typeAlignment
{@code boolean[]}{@code 1}
{@code byte[]}{@code 1}
{@code char[]}{@code 2}
{@code short[]}{@code 2}
{@code int[]}{@code 4}
{@code float[]}{@code 4}
{@code long[]}{@code 8}
{@code double[]}{@code 8}
+ * + * Note that the above definition is conservative: it might be possible, for instance, that a heap segment + * constructed from a {@code byte[]} might have a subset of addresses {@code S} which happen to be 8-byte aligned. But determining + * which segment addresses belong to {@code S} requires reasoning about details which are ultimately implementation-dependent. + * *

Lifecycle and confinement

* * Memory segments are associated with a resource scope (see {@link ResourceScope}), which can be accessed using @@ -226,7 +276,9 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory * @param elementLayout the layout to be used for splitting. * @return the element spliterator for this segment * @throws IllegalArgumentException if the {@code elementLayout} size is zero, or the segment size modulo the - * {@code elementLayout} size is greater than zero. + * {@code elementLayout} size is greater than zero, if this segment is + * incompatible with the alignment constraints in the provided layout, + * or if the {@code elementLayout} alignment is greater than its size. */ Spliterator spliterator(MemoryLayout elementLayout); @@ -240,7 +292,9 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory * @param elementLayout the layout to be used for splitting. * @return a sequential {@code Stream} over disjoint slices in this segment. * @throws IllegalArgumentException if the {@code elementLayout} size is zero, or the segment size modulo the - * {@code elementLayout} size is greater than zero. + * {@code elementLayout} size is greater than zero, if this segment is + * incompatible with the alignment constraints in the provided layout, + * or if the {@code elementLayout} alignment is greater than its size. */ Stream elements(MemoryLayout elementLayout); @@ -982,9 +1036,9 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory * @param dstElementLayout the element layout associated with the destination segment. * @param dstOffset the starting offset, in bytes, of the destination segment. * @param elementCount the number of elements to be copied. - * @throws IllegalArgumentException if the element layouts have different sizes, if the source offset is incompatible - * with the alignment constraints in the source element layout, or if the destination offset is incompatible with the - * alignment constraints in the destination element layout. + * @throws IllegalArgumentException if the element layouts have different sizes, if the source (resp. destination) segment/offset are + * incompatible with the alignment constraints in the source + * (resp. destination) element layout, or if the source (resp. destination) element layout alignment is greater than its size. * @throws IllegalStateException if either the scope associated with the source segment or the scope associated * with the destination segment have been already closed, or if access occurs from a thread other than the thread * owning either scopes. @@ -1003,13 +1057,15 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory AbstractMemorySegmentImpl srcImpl = (AbstractMemorySegmentImpl)srcSegment; AbstractMemorySegmentImpl dstImpl = (AbstractMemorySegmentImpl)dstSegment; if (srcElementLayout.byteSize() != dstElementLayout.byteSize()) { - throw new IllegalArgumentException("Source and destination layouts must have same sizes"); + throw new IllegalArgumentException("Source and destination layouts must have same size"); } - if (srcOffset % srcElementLayout.byteAlignment() != 0) { + Utils.checkElementAlignment(srcElementLayout, "Source layout alignment greater than its size"); + Utils.checkElementAlignment(dstElementLayout, "Destination layout alignment greater than its size"); + if (!srcImpl.isAlignedForElement(srcOffset, srcElementLayout)) { throw new IllegalArgumentException("Source segment incompatible with alignment constraints"); } - if (dstOffset % dstElementLayout.byteAlignment() != 0) { - throw new IllegalArgumentException("Target segment incompatible with alignment constraints"); + if (!dstImpl.isAlignedForElement(dstOffset, dstElementLayout)) { + throw new IllegalArgumentException("Destination segment incompatible with alignment constraints"); } long size = elementCount * srcElementLayout.byteSize(); srcImpl.checkAccess(srcOffset, size, true); @@ -1034,6 +1090,8 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory * @return a byte value read from this address. * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from * a thread other than the thread owning that scope. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout. * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the * memory segment. */ @@ -1051,6 +1109,8 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory * @param value the byte value to be written. * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from * a thread other than the thread owning that scope. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout. * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the * memory segment. * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. @@ -1069,6 +1129,8 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory * @return a boolean value read from this address. * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from * a thread other than the thread owning that scope. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout. * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the * memory segment. */ @@ -1086,6 +1148,8 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory * @param value the boolean value to be written. * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from * a thread other than the thread owning that scope. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout. * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the * memory segment. * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. @@ -1104,6 +1168,8 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory * @return a char value read from this address. * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from * a thread other than the thread owning that scope. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout. * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the * memory segment. */ @@ -1121,6 +1187,8 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory * @param value the char value to be written. * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from * a thread other than the thread owning that scope. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout. * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the * memory segment. * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. @@ -1139,6 +1207,8 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory * @return a short value read from this address. * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from * a thread other than the thread owning that scope. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout. * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the * memory segment. */ @@ -1156,6 +1226,8 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory * @param value the short value to be written. * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from * a thread other than the thread owning that scope. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout. * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the * memory segment. * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. @@ -1174,6 +1246,8 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory * @return an int value read from this address. * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from * a thread other than the thread owning that scope. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout. * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the * memory segment. */ @@ -1191,6 +1265,8 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory * @param value the int value to be written. * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from * a thread other than the thread owning that scope. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout. * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the * memory segment. * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. @@ -1209,6 +1285,8 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory * @return a float value read from this address. * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from * a thread other than the thread owning that scope. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout. * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the * memory segment. */ @@ -1226,6 +1304,8 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory * @param value the float value to be written. * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from * a thread other than the thread owning that scope. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout. * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the * memory segment. * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. @@ -1244,6 +1324,8 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory * @return a long value read from this address. * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from * a thread other than the thread owning that scope. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout. * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the * memory segment. */ @@ -1261,6 +1343,8 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory * @param value the long value to be written. * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from * a thread other than the thread owning that scope. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout. * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the * memory segment. * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. @@ -1279,6 +1363,8 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory * @return a double value read from this address. * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from * a thread other than the thread owning that scope. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout. * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the * memory segment. */ @@ -1296,6 +1382,8 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory * @param value the double value to be written. * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from * a thread other than the thread owning that scope. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout. * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the * memory segment. * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. @@ -1314,6 +1402,8 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory * @return an address value read from this address. * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from * a thread other than the thread owning that scope. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout. * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the * memory segment. */ @@ -1331,6 +1421,8 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory * @param value the address value to be written. * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from * a thread other than the thread owning that scope. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout. * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the * memory segment. * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. @@ -1349,11 +1441,15 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory * @return a char value read from this address. * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from * a thread other than the thread owning that scope. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout, + * or if the layout alignment is greater than its size. * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the * memory segment. */ @ForceInline default char getAtIndex(ValueLayout.OfChar layout, long index) { + Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); return (char)layout.accessHandle().get(this, Utils.scaleOffset(this, index, layout.byteSize())); } @@ -1366,12 +1462,16 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory * @param value the char value to be written. * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from * a thread other than the thread owning that scope. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout, + * or if the layout alignment is greater than its size. * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the * memory segment. * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. */ @ForceInline default void setAtIndex(ValueLayout.OfChar layout, long index, char value) { + Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); layout.accessHandle().set(this, Utils.scaleOffset(this, index, layout.byteSize()), value); } @@ -1384,11 +1484,15 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory * @return a short value read from this address. * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from * a thread other than the thread owning that scope. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout, + * or if the layout alignment is greater than its size. * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the * memory segment. */ @ForceInline default short getAtIndex(ValueLayout.OfShort layout, long index) { + Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); return (short)layout.accessHandle().get(this, Utils.scaleOffset(this, index, layout.byteSize())); } @@ -1401,12 +1505,16 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory * @param value the short value to be written. * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from * a thread other than the thread owning that scope. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout, + * or if the layout alignment is greater than its size. * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the * memory segment. * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. */ @ForceInline default void setAtIndex(ValueLayout.OfShort layout, long index, short value) { + Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); layout.accessHandle().set(this, Utils.scaleOffset(this, index, layout.byteSize()), value); } @@ -1419,11 +1527,15 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory * @return an int value read from this address. * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from * a thread other than the thread owning that scope. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout, + * or if the layout alignment is greater than its size. * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the * memory segment. */ @ForceInline default int getAtIndex(ValueLayout.OfInt layout, long index) { + Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); return (int)layout.accessHandle().get(this, Utils.scaleOffset(this, index, layout.byteSize())); } @@ -1436,12 +1548,16 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory * @param value the int value to be written. * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from * a thread other than the thread owning that scope. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout, + * or if the layout alignment is greater than its size. * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the * memory segment. * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. */ @ForceInline default void setAtIndex(ValueLayout.OfInt layout, long index, int value) { + Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); layout.accessHandle().set(this, Utils.scaleOffset(this, index, layout.byteSize()), value); } @@ -1454,11 +1570,15 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory * @return a float value read from this address. * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from * a thread other than the thread owning that scope. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout, + * or if the layout alignment is greater than its size. * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the * memory segment. */ @ForceInline default float getAtIndex(ValueLayout.OfFloat layout, long index) { + Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); return (float)layout.accessHandle().get(this, Utils.scaleOffset(this, index, layout.byteSize())); } @@ -1471,12 +1591,16 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory * @param value the float value to be written. * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from * a thread other than the thread owning that scope. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout, + * or if the layout alignment is greater than its size. * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the * memory segment. * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. */ @ForceInline default void setAtIndex(ValueLayout.OfFloat layout, long index, float value) { + Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); layout.accessHandle().set(this, Utils.scaleOffset(this, index, layout.byteSize()), value); } @@ -1489,11 +1613,15 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory * @return a long value read from this address. * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from * a thread other than the thread owning that scope. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout, + * or if the layout alignment is greater than its size. * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the * memory segment. */ @ForceInline default long getAtIndex(ValueLayout.OfLong layout, long index) { + Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); return (long)layout.accessHandle().get(this, Utils.scaleOffset(this, index, layout.byteSize())); } @@ -1506,12 +1634,16 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory * @param value the long value to be written. * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from * a thread other than the thread owning that scope. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout, + * or if the layout alignment is greater than its size. * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the * memory segment. * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. */ @ForceInline default void setAtIndex(ValueLayout.OfLong layout, long index, long value) { + Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); layout.accessHandle().set(this, Utils.scaleOffset(this, index, layout.byteSize()), value); } @@ -1524,11 +1656,15 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory * @return a double value read from this address. * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from * a thread other than the thread owning that scope. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout, + * or if the layout alignment is greater than its size. * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the * memory segment. */ @ForceInline default double getAtIndex(ValueLayout.OfDouble layout, long index) { + Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); return (double)layout.accessHandle().get(this, Utils.scaleOffset(this, index, layout.byteSize())); } @@ -1541,12 +1677,16 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory * @param value the double value to be written. * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from * a thread other than the thread owning that scope. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout, + * or if the layout alignment is greater than its size. * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the * memory segment. * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. */ @ForceInline default void setAtIndex(ValueLayout.OfDouble layout, long index, double value) { + Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); layout.accessHandle().set(this, Utils.scaleOffset(this, index, layout.byteSize()), value); } @@ -1559,11 +1699,15 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory * @return an address value read from this address. * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from * a thread other than the thread owning that scope. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout, + * or if the layout alignment is greater than its size. * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the * memory segment. */ @ForceInline default MemoryAddress getAtIndex(ValueLayout.OfAddress layout, long index) { + Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); return (MemoryAddress)layout.accessHandle().get(this, Utils.scaleOffset(this, index, layout.byteSize())); } @@ -1576,12 +1720,16 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory * @param value the address value to be written. * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from * a thread other than the thread owning that scope. + * @throws IllegalArgumentException if the dereference operation is + * incompatible with the alignment constraints in the provided layout, + * or if the layout alignment is greater than its size. * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the * memory segment. * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. */ @ForceInline default void setAtIndex(ValueLayout.OfAddress layout, long index, Addressable value) { + Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); layout.accessHandle().set(this, Utils.scaleOffset(this, index, layout.byteSize()), value.address()); } @@ -1598,7 +1746,9 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory * @param dstIndex the starting index of the destination array. * @param elementCount the number of array elements to be copied. * @throws IllegalArgumentException if {@code dstArray} is not an array, or if it is an array but whose type is not supported, - * or if the destination array component type does not match the carrier of the source element layout. + * if the destination array component type does not match the carrier of the source element layout, if the source + * segment/offset are incompatible with the alignment constraints in the source element layout, + * or if the destination element layout alignment is greater than its size. */ @ForceInline static void copy( @@ -1614,6 +1764,10 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory int dstBase = (int)baseAndScale; int dstWidth = (int)(baseAndScale >> 32); AbstractMemorySegmentImpl srcImpl = (AbstractMemorySegmentImpl)srcSegment; + Utils.checkElementAlignment(srcLayout, "Source layout alignment greater than its size"); + if (!srcImpl.isAlignedForElement(srcOffset, srcLayout)) { + throw new IllegalArgumentException("Source segment incompatible with alignment constraints"); + } srcImpl.checkAccess(srcOffset, elementCount * dstWidth, true); Objects.checkFromIndexSize(dstIndex, elementCount, Array.getLength(dstArray)); if (dstWidth == 1 || srcLayout.order() == ByteOrder.nativeOrder()) { @@ -1639,7 +1793,9 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory * @param dstOffset the starting offset, in bytes, of the destination segment. * @param elementCount the number of array elements to be copied. * @throws IllegalArgumentException if {@code srcArray} is not an array, or if it is an array but whose type is not supported, - * or if the source array component type does not match the carrier of the destination element layout. + * if the source array component type does not match the carrier of the destination element layout, if the destination + * segment/offset are incompatible with the alignment constraints in the destination element layout, + * or if the destination element layout alignment is greater than its size. */ @ForceInline static void copy( @@ -1656,6 +1812,10 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory int srcWidth = (int)(baseAndScale >> 32); Objects.checkFromIndexSize(srcIndex, elementCount, Array.getLength(srcArray)); AbstractMemorySegmentImpl destImpl = (AbstractMemorySegmentImpl)dstSegment; + Utils.checkElementAlignment(dstLayout, "Destination layout alignment greater than its size"); + if (!destImpl.isAlignedForElement(dstOffset, dstLayout)) { + throw new IllegalArgumentException("Destination segment incompatible with alignment constraints"); + } destImpl.checkAccess(dstOffset, elementCount * srcWidth, false); if (srcWidth == 1 || dstLayout.order() == ByteOrder.nativeOrder()) { ScopedMemoryAccess.getScopedMemoryAccess().copyMemory(null, destImpl.scope(), diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java index eacbeb26a51..5744d8556b1 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java @@ -124,8 +124,12 @@ public abstract non-sealed class AbstractMemorySegmentImpl extends MemorySegment if (elementLayout.byteSize() == 0) { throw new IllegalArgumentException("Element layout size cannot be zero"); } - if (byteSize() % elementLayout.byteSize() != 0) { - throw new IllegalArgumentException("Segment size is no a multiple of layout size"); + Utils.checkElementAlignment(elementLayout, "Element layout alignment greater than its size"); + if (!isAlignedForElement(0, elementLayout)) { + throw new IllegalArgumentException("Incompatible alignment constraints"); + } + if (!Utils.isAligned(byteSize(), elementLayout.byteSize())) { + throw new IllegalArgumentException("Segment size is not a multiple of layout size"); } return new SegmentSplitter(elementLayout.byteSize(), byteSize() / elementLayout.byteSize(), this); @@ -383,8 +387,13 @@ public abstract non-sealed class AbstractMemorySegmentImpl extends MemorySegment return (this.mask & mask) != 0; } + @ForceInline + public final boolean isAlignedForElement(long offset, MemoryLayout layout) { + return (((unsafeGetOffset() + offset) | maxAlignMask()) & (layout.byteAlignment() - 1)) == 0; + } + private int checkArraySize(String typeName, int elemSize) { - if (length % elemSize != 0) { + if (!Utils.isAligned(length, elemSize)) { throw new IllegalStateException(String.format("Segment size is not a multiple of %d. Size: %d", elemSize, length)); } long arraySize = length / elemSize; diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/HeapMemorySegmentImpl.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/HeapMemorySegmentImpl.java index 755d6cb14dc..b10b278c0ca 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/HeapMemorySegmentImpl.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/HeapMemorySegmentImpl.java @@ -47,6 +47,11 @@ public abstract class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl private static final Unsafe UNSAFE = Unsafe.getUnsafe(); private static final int BYTE_ARR_BASE = UNSAFE.arrayBaseOffset(byte[].class); + private static final long MAX_ALIGN_1 = 1; + private static final long MAX_ALIGN_2 = 2; + private static final long MAX_ALIGN_4 = 4; + private static final long MAX_ALIGN_8 = 8; + final long offset; final H base; @@ -100,6 +105,11 @@ public abstract class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl long byteSize = (long)arr.length * Unsafe.ARRAY_BYTE_INDEX_SCALE; return new OfByte(Unsafe.ARRAY_BYTE_BASE_OFFSET, arr, byteSize, defaultAccessModes(byteSize)); } + + @Override + public long maxAlignMask() { + return MAX_ALIGN_1; + } } public static class OfChar extends HeapMemorySegmentImpl { @@ -123,6 +133,11 @@ public abstract class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl long byteSize = (long)arr.length * Unsafe.ARRAY_CHAR_INDEX_SCALE; return new OfChar(Unsafe.ARRAY_CHAR_BASE_OFFSET, arr, byteSize, defaultAccessModes(byteSize)); } + + @Override + public long maxAlignMask() { + return MAX_ALIGN_2; + } } public static class OfShort extends HeapMemorySegmentImpl { @@ -146,6 +161,11 @@ public abstract class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl long byteSize = (long)arr.length * Unsafe.ARRAY_SHORT_INDEX_SCALE; return new OfShort(Unsafe.ARRAY_SHORT_BASE_OFFSET, arr, byteSize, defaultAccessModes(byteSize)); } + + @Override + public long maxAlignMask() { + return MAX_ALIGN_2; + } } public static class OfInt extends HeapMemorySegmentImpl { @@ -169,6 +189,11 @@ public abstract class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl long byteSize = (long)arr.length * Unsafe.ARRAY_INT_INDEX_SCALE; return new OfInt(Unsafe.ARRAY_INT_BASE_OFFSET, arr, byteSize, defaultAccessModes(byteSize)); } + + @Override + public long maxAlignMask() { + return MAX_ALIGN_4; + } } public static class OfLong extends HeapMemorySegmentImpl { @@ -192,6 +217,11 @@ public abstract class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl long byteSize = (long)arr.length * Unsafe.ARRAY_LONG_INDEX_SCALE; return new OfLong(Unsafe.ARRAY_LONG_BASE_OFFSET, arr, byteSize, defaultAccessModes(byteSize)); } + + @Override + public long maxAlignMask() { + return MAX_ALIGN_8; + } } public static class OfFloat extends HeapMemorySegmentImpl { @@ -215,6 +245,11 @@ public abstract class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl long byteSize = (long)arr.length * Unsafe.ARRAY_FLOAT_INDEX_SCALE; return new OfFloat(Unsafe.ARRAY_FLOAT_BASE_OFFSET, arr, byteSize, defaultAccessModes(byteSize)); } + + @Override + public long maxAlignMask() { + return MAX_ALIGN_4; + } } public static class OfDouble extends HeapMemorySegmentImpl { @@ -238,6 +273,11 @@ public abstract class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl long byteSize = (long)arr.length * Unsafe.ARRAY_DOUBLE_INDEX_SCALE; return new OfDouble(Unsafe.ARRAY_DOUBLE_BASE_OFFSET, arr, byteSize, defaultAccessModes(byteSize)); } + + @Override + public long maxAlignMask() { + return MAX_ALIGN_8; + } } } diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/LayoutPath.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/LayoutPath.java index 1d8bb265c83..dbe52a69799 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/LayoutPath.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/LayoutPath.java @@ -282,11 +282,11 @@ public class LayoutPath { private static void checkAlignment(LayoutPath path) { MemoryLayout layout = path.layout; long alignment = layout.bitAlignment(); - if (path.offset % alignment != 0) { + if (!Utils.isAligned(path.offset, alignment)) { throw new UnsupportedOperationException("Invalid alignment requirements for layout " + layout); } for (long stride : path.strides) { - if (stride % alignment != 0) { + if (!Utils.isAligned(stride, alignment)) { throw new UnsupportedOperationException("Alignment requirements for layout " + layout + " do not match stride " + stride); } } diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/MemoryAddressImpl.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/MemoryAddressImpl.java index 59d7105082c..7bb55907571 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/MemoryAddressImpl.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/MemoryAddressImpl.java @@ -267,6 +267,7 @@ public final class MemoryAddressImpl implements MemoryAddress, Scoped { @CallerSensitive public char getAtIndex(ValueLayout.OfChar layout, long index) { Reflection.ensureNativeAccess(Reflection.getCallerClass()); + Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); return NativeMemorySegmentImpl.EVERYTHING.get(layout, toRawLongValue() + (index * layout.byteSize())); } @@ -275,6 +276,7 @@ public final class MemoryAddressImpl implements MemoryAddress, Scoped { @CallerSensitive public void setAtIndex(ValueLayout.OfChar layout, long index, char value) { Reflection.ensureNativeAccess(Reflection.getCallerClass()); + Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); NativeMemorySegmentImpl.EVERYTHING.set(layout, toRawLongValue() + (index * layout.byteSize()), value); } @@ -283,6 +285,7 @@ public final class MemoryAddressImpl implements MemoryAddress, Scoped { @CallerSensitive public short getAtIndex(ValueLayout.OfShort layout, long index) { Reflection.ensureNativeAccess(Reflection.getCallerClass()); + Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); return NativeMemorySegmentImpl.EVERYTHING.get(layout, toRawLongValue() + (index * layout.byteSize())); } @@ -291,6 +294,7 @@ public final class MemoryAddressImpl implements MemoryAddress, Scoped { @CallerSensitive public void setAtIndex(ValueLayout.OfShort layout, long index, short value) { Reflection.ensureNativeAccess(Reflection.getCallerClass()); + Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); NativeMemorySegmentImpl.EVERYTHING.set(layout, toRawLongValue() + (index * layout.byteSize()), value); } @@ -299,6 +303,7 @@ public final class MemoryAddressImpl implements MemoryAddress, Scoped { @CallerSensitive public int getAtIndex(ValueLayout.OfInt layout, long index) { Reflection.ensureNativeAccess(Reflection.getCallerClass()); + Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); return NativeMemorySegmentImpl.EVERYTHING.get(layout, toRawLongValue() + (index * layout.byteSize())); } @@ -307,6 +312,7 @@ public final class MemoryAddressImpl implements MemoryAddress, Scoped { @CallerSensitive public void setAtIndex(ValueLayout.OfInt layout, long index, int value) { Reflection.ensureNativeAccess(Reflection.getCallerClass()); + Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); NativeMemorySegmentImpl.EVERYTHING.set(layout, toRawLongValue() + (index * layout.byteSize()), value); } @@ -315,6 +321,7 @@ public final class MemoryAddressImpl implements MemoryAddress, Scoped { @CallerSensitive public float getAtIndex(ValueLayout.OfFloat layout, long index) { Reflection.ensureNativeAccess(Reflection.getCallerClass()); + Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); return NativeMemorySegmentImpl.EVERYTHING.get(layout, toRawLongValue() + (index * layout.byteSize())); } @@ -323,6 +330,7 @@ public final class MemoryAddressImpl implements MemoryAddress, Scoped { @CallerSensitive public void setAtIndex(ValueLayout.OfFloat layout, long index, float value) { Reflection.ensureNativeAccess(Reflection.getCallerClass()); + Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); NativeMemorySegmentImpl.EVERYTHING.set(layout, toRawLongValue() + (index * layout.byteSize()), value); } @@ -331,6 +339,7 @@ public final class MemoryAddressImpl implements MemoryAddress, Scoped { @CallerSensitive public long getAtIndex(ValueLayout.OfLong layout, long index) { Reflection.ensureNativeAccess(Reflection.getCallerClass()); + Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); return NativeMemorySegmentImpl.EVERYTHING.get(layout, toRawLongValue() + (index * layout.byteSize())); } @@ -339,6 +348,7 @@ public final class MemoryAddressImpl implements MemoryAddress, Scoped { @CallerSensitive public void setAtIndex(ValueLayout.OfLong layout, long index, long value) { Reflection.ensureNativeAccess(Reflection.getCallerClass()); + Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); NativeMemorySegmentImpl.EVERYTHING.set(layout, toRawLongValue() + (index * layout.byteSize()), value); } @@ -347,6 +357,7 @@ public final class MemoryAddressImpl implements MemoryAddress, Scoped { @CallerSensitive public double getAtIndex(ValueLayout.OfDouble layout, long index) { Reflection.ensureNativeAccess(Reflection.getCallerClass()); + Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); return NativeMemorySegmentImpl.EVERYTHING.get(layout, toRawLongValue() + (index * layout.byteSize())); } @@ -355,6 +366,7 @@ public final class MemoryAddressImpl implements MemoryAddress, Scoped { @CallerSensitive public void setAtIndex(ValueLayout.OfDouble layout, long index, double value) { Reflection.ensureNativeAccess(Reflection.getCallerClass()); + Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); NativeMemorySegmentImpl.EVERYTHING.set(layout, toRawLongValue() + (index * layout.byteSize()), value); } @@ -363,6 +375,7 @@ public final class MemoryAddressImpl implements MemoryAddress, Scoped { @CallerSensitive public MemoryAddress getAtIndex(ValueLayout.OfAddress layout, long index) { Reflection.ensureNativeAccess(Reflection.getCallerClass()); + Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); return NativeMemorySegmentImpl.EVERYTHING.get(layout, toRawLongValue() + (index * layout.byteSize())); } @@ -371,6 +384,7 @@ public final class MemoryAddressImpl implements MemoryAddress, Scoped { @CallerSensitive public void setAtIndex(ValueLayout.OfAddress layout, long index, Addressable value) { Reflection.ensureNativeAccess(Reflection.getCallerClass()); + Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); NativeMemorySegmentImpl.EVERYTHING.set(layout, toRawLongValue() + (index * layout.byteSize()), value.address()); } } diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/NativeMemorySegmentImpl.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/NativeMemorySegmentImpl.java index 11f795a2f84..bd06223b6ce 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/NativeMemorySegmentImpl.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/NativeMemorySegmentImpl.java @@ -92,6 +92,11 @@ public class NativeMemorySegmentImpl extends AbstractMemorySegmentImpl { return null; } + @Override + public long maxAlignMask() { + return 0; + } + // factories public static MemorySegment makeNativeSegment(long bytesSize, long alignmentBytes, ResourceScopeImpl scope) { diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/Utils.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/Utils.java index 6272e6e3100..bb9db16eff2 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/Utils.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/Utils.java @@ -98,7 +98,7 @@ public final class Utils { } public static long bitsToBytesOrThrow(long bits, Supplier exFactory) { - if (bits % 8 == 0) { + if (Utils.isAligned(bits, 8)) { return bits / 8; } else { throw exFactory.get(); @@ -173,4 +173,16 @@ public final class Utils { // note: we know size is a small value (as it comes from ValueLayout::byteSize()) return MemorySegmentProxy.multiplyOffsets(index, (int)size, (AbstractMemorySegmentImpl)segment); } + + @ForceInline + public static boolean isAligned(long offset, long align) { + return (offset & (align - 1)) == 0; + } + + @ForceInline + public static void checkElementAlignment(MemoryLayout layout, String msg) { + if (layout.byteAlignment() > layout.byteSize()) { + throw new IllegalArgumentException(msg); + } + } } diff --git a/test/jdk/java/foreign/TestArrayCopy.java b/test/jdk/java/foreign/TestArrayCopy.java index b8a36307fde..e45fcf395f7 100644 --- a/test/jdk/java/foreign/TestArrayCopy.java +++ b/test/jdk/java/foreign/TestArrayCopy.java @@ -253,6 +253,18 @@ public class TestArrayCopy { MemorySegment.copy(new byte[] { 1, 2, 3, 4 }, 0, segment, JAVA_INT, 0, 4); } + @Test(expectedExceptions = IllegalArgumentException.class) + public void testHyperAlignedSrc() { + MemorySegment segment = MemorySegment.ofArray(new byte[] {1, 2, 3, 4}); + MemorySegment.copy(new byte[] { 1, 2, 3, 4 }, 0, segment, JAVA_BYTE.withBitAlignment(16), 0, 4); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void testHyperAlignedDst() { + MemorySegment segment = MemorySegment.ofArray(new byte[] {1, 2, 3, 4}); + MemorySegment.copy(segment, JAVA_BYTE.withBitAlignment(16), 0, new byte[] { 1, 2, 3, 4 }, 0, 4); + } + /***** Utilities *****/ public static MemorySegment srcSegment(int bytesLength) { diff --git a/test/jdk/java/foreign/TestHeapAlignment.java b/test/jdk/java/foreign/TestHeapAlignment.java new file mode 100644 index 00000000000..3395a686f38 --- /dev/null +++ b/test/jdk/java/foreign/TestHeapAlignment.java @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2021, 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 + * @requires ((os.arch == "amd64" | os.arch == "x86_64") & sun.arch.data.model == "64") | os.arch == "aarch64" + * @run testng/othervm --enable-native-access=ALL-UNNAMED TestHeapAlignment + */ + +import jdk.incubator.foreign.MemoryAddress; +import jdk.incubator.foreign.MemoryLayout; +import jdk.incubator.foreign.MemorySegment; +import jdk.incubator.foreign.ResourceScope; +import jdk.incubator.foreign.ValueLayout; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; + +import static org.testng.Assert.fail; + +public class TestHeapAlignment { + + @Test(dataProvider = "layouts") + public void testHeapAlignment(MemorySegment segment, int align, Object val, Object arr, ValueLayout layout, Function segmentFactory) { + assertAligned(align, layout, () -> layout.varHandle().get(segment)); + assertAligned(align, layout, () -> layout.varHandle().set(segment, val)); + MemoryLayout seq = MemoryLayout.sequenceLayout(10, layout); + assertAligned(align, layout, () -> seq.varHandle(MemoryLayout.PathElement.sequenceElement()).get(segment, 0L)); + assertAligned(align, layout, () -> seq.varHandle(MemoryLayout.PathElement.sequenceElement()).set(segment, 0L, val)); + assertAligned(align, layout, () -> segment.spliterator(layout)); + if (arr != null) { + assertAligned(align, layout, () -> MemorySegment.copy(arr, 0, segment, layout, 0, 1)); + assertAligned(align, layout, () -> MemorySegment.copy(segment, layout, 0, arr, 0, 1)); + assertAligned(align, layout, () -> { + MemorySegment other = segmentFactory.apply(arr); + MemorySegment.copy(other, layout, 0, segment, layout, 0, 1); + }); + MemorySegment other = segmentFactory.apply(arr); + assertAligned(align, layout, () -> { + MemorySegment.copy(segment, layout, 0, other, layout, 0, 1); + }); + assertAligned(align, layout, () -> { + MemorySegment.copy(other, layout, 0, segment, layout, 0, 1); + }); + } + } + + static void assertAligned(int align, ValueLayout layout, Runnable runnable) { + boolean shouldFail = layout.byteAlignment() > align && align != -1; + try { + runnable.run(); + if (shouldFail) { + fail("Should not get here!"); + } + } catch (IllegalArgumentException ex) { + if (!shouldFail) { + fail("Should not get here!"); + } else if (!ex.getMessage().contains("alignment") && !ex.getMessage().contains("Misaligned")) { + fail("Unexpected exception: " + ex); + } + } + } + + static final ValueLayout.OfChar JAVA_CHAR_ALIGNED = ValueLayout.JAVA_CHAR.withBitAlignment(16); + static final ValueLayout.OfShort JAVA_SHORT_ALIGNED = ValueLayout.JAVA_SHORT.withBitAlignment(16); + static final ValueLayout.OfInt JAVA_INT_ALIGNED = ValueLayout.JAVA_INT.withBitAlignment(32); + static final ValueLayout.OfFloat JAVA_FLOAT_ALIGNED = ValueLayout.JAVA_FLOAT.withBitAlignment(32); + static final ValueLayout.OfLong JAVA_LONG_ALIGNED = ValueLayout.JAVA_LONG.withBitAlignment(64); + static final ValueLayout.OfDouble JAVA_DOUBLE_ALIGNED = ValueLayout.JAVA_DOUBLE.withBitAlignment(64); + static final ValueLayout.OfAddress ADDRESS_ALIGNED = ValueLayout.ADDRESS.withBitAlignment(ValueLayout.ADDRESS.bitSize()); + + enum SegmentAndAlignment { + HEAP_BYTE(MemorySegment.ofArray(new byte[8]), 1), + HEAP_SHORT(MemorySegment.ofArray(new short[4]), 2), + HEAP_CHAR(MemorySegment.ofArray(new char[4]), 2), + HEAP_INT(MemorySegment.ofArray(new int[2]), 4), + HEAP_FLOAT(MemorySegment.ofArray(new float[2]), 4), + HEAP_LONG(MemorySegment.ofArray(new long[1]), 8), + HEAP_DOUBLE(MemorySegment.ofArray(new double[1]), 8), + NATIVE(MemorySegment.allocateNative(8, ResourceScope.newImplicitScope()), -1); + + final MemorySegment segment; + final int align; + + SegmentAndAlignment(MemorySegment segment, int align) { + this.segment = segment; + this.align = align; + } + } + + @DataProvider + public static Object[][] layouts() { + List layouts = new ArrayList<>(); + for (SegmentAndAlignment testCase : SegmentAndAlignment.values()) { + layouts.add(new Object[] { testCase.segment, testCase.align, (byte) 42, new byte[]{42}, ValueLayout.JAVA_BYTE, (Function)MemorySegment::ofArray }); + layouts.add(new Object[] { testCase.segment, testCase.align, true, null, ValueLayout.JAVA_BOOLEAN, null }); + layouts.add(new Object[] { testCase.segment, testCase.align, (char) 42, new char[]{42}, JAVA_CHAR_ALIGNED, (Function)MemorySegment::ofArray }); + layouts.add(new Object[] { testCase.segment, testCase.align, (short) 42, new short[]{42}, JAVA_SHORT_ALIGNED, (Function)MemorySegment::ofArray }); + layouts.add(new Object[] { testCase.segment, testCase.align, 42, new int[]{42}, JAVA_INT_ALIGNED, (Function)MemorySegment::ofArray }); + layouts.add(new Object[] { testCase.segment, testCase.align, 42f, new float[]{42}, JAVA_FLOAT_ALIGNED, (Function)MemorySegment::ofArray }); + layouts.add(new Object[] { testCase.segment, testCase.align, 42L, new long[]{42}, JAVA_LONG_ALIGNED, (Function)MemorySegment::ofArray }); + layouts.add(new Object[] { testCase.segment, testCase.align, 42d, new double[]{42}, JAVA_DOUBLE_ALIGNED, (Function)MemorySegment::ofArray }); + layouts.add(new Object[] { testCase.segment, testCase.align, MemoryAddress.ofLong(42), null, ADDRESS_ALIGNED, null }); + } + return layouts.toArray(new Object[0][]); + } +} diff --git a/test/jdk/java/foreign/TestMemoryAccessInstance.java b/test/jdk/java/foreign/TestMemoryAccessInstance.java index 702e95bf8da..83daa11ce4e 100644 --- a/test/jdk/java/foreign/TestMemoryAccessInstance.java +++ b/test/jdk/java/foreign/TestMemoryAccessInstance.java @@ -35,12 +35,13 @@ import java.util.function.Function; import jdk.incubator.foreign.ResourceScope; import jdk.incubator.foreign.ValueLayout; +import org.testng.SkipException; import org.testng.annotations.*; import static org.testng.Assert.*; public class TestMemoryAccessInstance { - static class Accessor { + static class Accessor { interface SegmentGetter { X get(T buffer, L layout, long offset); @@ -90,13 +91,34 @@ public class TestMemoryAccessInstance { } } - static Accessor ofSegment(L layout, X value, + @SuppressWarnings("unchecked") + void testHyperAligned() { + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemorySegment segment = MemorySegment.allocateNative(64, scope); + T t = transform.apply(segment); + L alignedLayout = (L)layout.withBitAlignment(layout.byteSize() * 8 * 2); + try { + segmentSetter.set(t, alignedLayout, 0, value); + fail(); + } catch (IllegalArgumentException exception) { + assertTrue(exception.getMessage().contains("greater")); + } + try { + segmentGetter.get(t, alignedLayout, 0); + fail(); + } catch (IllegalArgumentException exception) { + assertTrue(exception.getMessage().contains("greater")); + } + } + } + + static Accessor ofSegment(L layout, X value, SegmentGetter segmentGetter, SegmentSetter segmentSetter, BufferGetter bufferGetter, BufferSetter bufferSetter) { return new Accessor<>(Function.identity(), layout, value, segmentGetter, segmentSetter, bufferGetter, bufferSetter); } - static Accessor ofAddress(L layout, X value, + static Accessor ofAddress(L layout, X value, SegmentGetter segmentGetter, SegmentSetter segmentSetter, BufferGetter bufferGetter, BufferSetter bufferSetter) { return new Accessor<>(MemorySegment::address, layout, value, segmentGetter, segmentSetter, bufferGetter, bufferSetter); @@ -113,6 +135,24 @@ public class TestMemoryAccessInstance { accessor.test(); } + @Test(dataProvider = "segmentAccessors") + public void testSegmentAccessHyper(String testName, Accessor accessor) { + if (testName.contains("index")) { + accessor.testHyperAligned(); + } else { + throw new SkipException("Skipping"); + } + } + + @Test(dataProvider = "addressAccessors") + public void testAddressAccessHyper(String testName, Accessor accessor) { + if (testName.contains("index")) { + accessor.testHyperAligned(); + } else { + throw new SkipException("Skipping"); + } + } + static final ByteOrder NE = ByteOrder.nativeOrder(); @DataProvider(name = "segmentAccessors") diff --git a/test/jdk/java/foreign/TestMemoryAlignment.java b/test/jdk/java/foreign/TestMemoryAlignment.java index d486581435a..2726fd6d91e 100644 --- a/test/jdk/java/foreign/TestMemoryAlignment.java +++ b/test/jdk/java/foreign/TestMemoryAlignment.java @@ -74,7 +74,7 @@ public class TestMemoryAlignment { MemorySegment segment = MemorySegment.allocateNative(alignedGroup, scope); vh.set(segment.asSlice(1L), -42); assertEquals(align, 8); //this is the only case where access is aligned - } catch (IllegalStateException ex) { + } catch (IllegalArgumentException ex) { assertNotEquals(align, 8); //if align != 8, access is always unaligned } } diff --git a/test/jdk/java/foreign/TestSegmentCopy.java b/test/jdk/java/foreign/TestSegmentCopy.java index de2dba08483..1185f436027 100644 --- a/test/jdk/java/foreign/TestSegmentCopy.java +++ b/test/jdk/java/foreign/TestSegmentCopy.java @@ -40,6 +40,7 @@ import java.util.ArrayList; import java.util.List; import java.util.function.IntFunction; +import static jdk.incubator.foreign.ValueLayout.JAVA_BYTE; import static org.testng.Assert.*; public class TestSegmentCopy { @@ -81,12 +82,16 @@ public class TestSegmentCopy { } } - interface Getter { - X get(MemorySegment segment, ValueLayout layout, long index); + @Test(expectedExceptions = IllegalArgumentException.class) + public void testHyperAlignedSrc() { + MemorySegment segment = MemorySegment.ofArray(new byte[] {1, 2, 3, 4}); + MemorySegment.copy(segment, 0, segment, JAVA_BYTE.withBitAlignment(16), 0, 4); } - interface Setter { - void set(MemorySegment segment, ValueLayout layout, long index, X val); + @Test(expectedExceptions = IllegalArgumentException.class) + public void testHyperAlignedDst() { + MemorySegment segment = MemorySegment.ofArray(new byte[] {1, 2, 3, 4}); + MemorySegment.copy(segment, JAVA_BYTE.withBitAlignment(16), 0, segment, 0, 4); } enum Type { diff --git a/test/jdk/java/foreign/TestSpliterator.java b/test/jdk/java/foreign/TestSpliterator.java index 17f4ef39259..7fcd6a16d36 100644 --- a/test/jdk/java/foreign/TestSpliterator.java +++ b/test/jdk/java/foreign/TestSpliterator.java @@ -127,6 +127,11 @@ public class TestSpliterator { MemorySegment.ofArray(new byte[7]).elements(MemoryLayout.sequenceLayout(0, ValueLayout.JAVA_INT)); } + @Test(expectedExceptions = IllegalArgumentException.class) + public void testHyperAligned() { + MemorySegment.ofArray(new byte[8]).elements(MemoryLayout.sequenceLayout(2, ValueLayout.JAVA_INT.withBitAlignment(64))); + } + static long sumSingle(long acc, MemorySegment segment) { return acc + (int)INT_HANDLE.get(segment, 0L); } diff --git a/test/jdk/java/foreign/TestVarHandleCombinators.java b/test/jdk/java/foreign/TestVarHandleCombinators.java index e9beaebafa8..e2c9d0bcfc2 100644 --- a/test/jdk/java/foreign/TestVarHandleCombinators.java +++ b/test/jdk/java/foreign/TestVarHandleCombinators.java @@ -51,7 +51,7 @@ public class TestVarHandleCombinators { assertEquals((byte) vh.get(segment, 2), (byte) -1); } - @Test(expectedExceptions = IllegalStateException.class) + @Test(expectedExceptions = IllegalArgumentException.class) public void testUnalignedElement() { VarHandle vh = MemoryHandles.varHandle(ValueLayout.JAVA_BYTE.withBitAlignment(32)); MemorySegment segment = MemorySegment.ofArray(new byte[4]); diff --git a/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverNonConstant.java b/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverNonConstant.java index ada578b09ba..1029acf7c2e 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverNonConstant.java +++ b/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverNonConstant.java @@ -26,6 +26,7 @@ import jdk.incubator.foreign.MemoryAddress; import jdk.incubator.foreign.MemoryLayout; import jdk.incubator.foreign.MemorySegment; import jdk.incubator.foreign.ResourceScope; +import jdk.incubator.foreign.ValueLayout; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; @@ -61,6 +62,10 @@ public class LoopOverNonConstant { static final int ALLOC_SIZE = ELEM_SIZE * CARRIER_SIZE; static final VarHandle VH_int = MemoryLayout.sequenceLayout(JAVA_INT).varHandle(sequenceElement()); + + static final ValueLayout.OfInt JAVA_INT_ALIGNED = JAVA_INT.withBitAlignment(32); + static final VarHandle VH_int_aligned = MemoryLayout.sequenceLayout(JAVA_INT_ALIGNED).varHandle(sequenceElement()); + MemorySegment segment; long unsafe_addr; @@ -125,6 +130,15 @@ public class LoopOverNonConstant { return sum; } + @Benchmark + public int segment_loop_aligned() { + int sum = 0; + for (int i = 0; i < ELEM_SIZE; i++) { + sum += (int) VH_int_aligned.get(segment, (long) i); + } + return sum; + } + @Benchmark public int segment_loop_instance() { int sum = 0; @@ -145,6 +159,15 @@ public class LoopOverNonConstant { return sum; } + @Benchmark + public int segment_loop_instance_aligned() { + int res = 0; + for (int i = 0; i < ELEM_SIZE; i ++) { + res += segment.get(JAVA_INT_ALIGNED, i * CARRIER_SIZE); + } + return res; + } + @Benchmark public int segment_loop_instance_address() { int sum = 0; diff --git a/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverNonConstantHeap.java b/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverNonConstantHeap.java index 5b51db08c00..2d6b605c2c5 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverNonConstantHeap.java +++ b/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverNonConstantHeap.java @@ -25,6 +25,7 @@ package org.openjdk.bench.jdk.incubator.foreign; import jdk.incubator.foreign.MemoryLayout; import jdk.incubator.foreign.MemorySegment; import jdk.incubator.foreign.ResourceScope; +import jdk.incubator.foreign.ValueLayout; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; @@ -66,8 +67,14 @@ public class LoopOverNonConstantHeap { static final int UNSAFE_BYTE_BASE = unsafe.arrayBaseOffset(byte[].class); static final VarHandle VH_int = MemoryLayout.sequenceLayout(JAVA_INT).varHandle(sequenceElement()); - MemorySegment segment; + + static final ValueLayout.OfInt JAVA_INT_ALIGNED = JAVA_INT.withBitAlignment(32); + static final VarHandle VH_int_aligned = MemoryLayout.sequenceLayout(JAVA_INT_ALIGNED).varHandle(sequenceElement()); + static final int UNSAFE_INT_BASE = unsafe.arrayBaseOffset(int[].class); + + MemorySegment segment, alignedSegment; byte[] base; + int[] alignedBase; ByteBuffer byteBuffer; @@ -95,7 +102,12 @@ public class LoopOverNonConstantHeap { for (int i = 0; i < ELEM_SIZE; i++) { unsafe.putInt(base, UNSAFE_BYTE_BASE + (i * CARRIER_SIZE) , i); } + alignedBase = new int[ELEM_SIZE]; + for (int i = 0; i < ELEM_SIZE; i++) { + unsafe.putInt(base, UNSAFE_INT_BASE + (i * CARRIER_SIZE) , i); + } segment = MemorySegment.ofArray(base); + alignedSegment = MemorySegment.ofArray(alignedBase); byteBuffer = ByteBuffer.wrap(base).order(ByteOrder.nativeOrder()); } @@ -135,6 +147,15 @@ public class LoopOverNonConstantHeap { return sum; } + @Benchmark + public int segment_loop_aligned() { + int sum = 0; + for (int i = 0; i < ELEM_SIZE; i++) { + sum += (int) VH_int_aligned.get(alignedSegment, (long) i); + } + return sum; + } + @Benchmark public int segment_loop_instance() { int res = 0; @@ -144,6 +165,15 @@ public class LoopOverNonConstantHeap { return res; } + @Benchmark + public int segment_loop_instance_aligned() { + int res = 0; + for (int i = 0; i < ELEM_SIZE; i ++) { + res += alignedSegment.get(JAVA_INT_ALIGNED, i * CARRIER_SIZE); + } + return res; + } + @Benchmark public int segment_loop_slice() { int sum = 0; -- GitLab From 0f98efbf2f0e47bb398fe7ca5235853e1d98df3a Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Wed, 5 Jan 2022 12:04:09 +0000 Subject: [PATCH 005/564] 8279445: Update JMH devkit to 1.34 Reviewed-by: aph, erikj --- make/devkit/createJMHBundle.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make/devkit/createJMHBundle.sh b/make/devkit/createJMHBundle.sh index d34c9939ff0..059fb7acb6f 100644 --- a/make/devkit/createJMHBundle.sh +++ b/make/devkit/createJMHBundle.sh @@ -26,7 +26,7 @@ # Create a bundle in the build directory, containing what's needed to # build and run JMH microbenchmarks from the OpenJDK build. -JMH_VERSION=1.33 +JMH_VERSION=1.34 COMMONS_MATH3_VERSION=3.2 JOPT_SIMPLE_VERSION=4.6 -- GitLab From b6ec39cc84cfc845b09c0f851a24751c4abf6e1c Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Wed, 5 Jan 2022 15:36:16 +0000 Subject: [PATCH 006/564] 8279510: Parallel: Remove unused PSScavenge::_consecutive_skipped_scavenges Reviewed-by: kbarrett --- src/hotspot/share/gc/parallel/psScavenge.cpp | 7 +------ src/hotspot/share/gc/parallel/psScavenge.hpp | 6 ------ 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/src/hotspot/share/gc/parallel/psScavenge.cpp b/src/hotspot/share/gc/parallel/psScavenge.cpp index e3b3e76ca47..0f4540223c9 100644 --- a/src/hotspot/share/gc/parallel/psScavenge.cpp +++ b/src/hotspot/share/gc/parallel/psScavenge.cpp @@ -71,7 +71,6 @@ #include "utilities/stack.inline.hpp" HeapWord* PSScavenge::_to_space_top_before_gc = NULL; -int PSScavenge::_consecutive_skipped_scavenges = 0; SpanSubjectToDiscoveryClosure PSScavenge::_span_based_discoverer; ReferenceProcessor* PSScavenge::_ref_processor = NULL; PSCardTable* PSScavenge::_card_table = NULL; @@ -729,7 +728,6 @@ bool PSScavenge::should_attempt_scavenge() { // Do not attempt to promote unless to_space is empty if (!young_gen->to_space()->is_empty()) { - _consecutive_skipped_scavenges++; if (UsePerfData) { counters->update_scavenge_skipped(to_space_not_empty); } @@ -753,10 +751,7 @@ bool PSScavenge::should_attempt_scavenge() { log_trace(ergo)(" padded_promoted_average is greater than maximum promotion = " SIZE_FORMAT, young_gen->used_in_bytes()); } - if (result) { - _consecutive_skipped_scavenges = 0; - } else { - _consecutive_skipped_scavenges++; + if (!result) { if (UsePerfData) { counters->update_scavenge_skipped(promoted_too_large); } diff --git a/src/hotspot/share/gc/parallel/psScavenge.hpp b/src/hotspot/share/gc/parallel/psScavenge.hpp index 440519ff707..d15b39c68b5 100644 --- a/src/hotspot/share/gc/parallel/psScavenge.hpp +++ b/src/hotspot/share/gc/parallel/psScavenge.hpp @@ -57,10 +57,6 @@ class PSScavenge: AllStatic { // being rescanned. static HeapWord* _to_space_top_before_gc; - // Number of consecutive attempts to scavenge that were skipped - static int _consecutive_skipped_scavenges; - - protected: // Flags/counters static SpanSubjectToDiscoveryClosure _span_based_discoverer; @@ -95,8 +91,6 @@ class PSScavenge: AllStatic { // Accessors static uint tenuring_threshold() { return _tenuring_threshold; } static elapsedTimer* accumulated_time() { return &_accumulated_time; } - static int consecutive_skipped_scavenges() - { return _consecutive_skipped_scavenges; } // Performance Counters static CollectorCounters* counters() { return _counters; } -- GitLab From a741b927a3cdc8e339ae557c77886ea850aa06b6 Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Wed, 5 Jan 2022 16:19:00 +0000 Subject: [PATCH 007/564] 8279453: Disable tools/jar/ReproducibleJar.java on 32-bit platforms Reviewed-by: alanb, bpb --- test/jdk/tools/jar/ReproducibleJar.java | 1 + 1 file changed, 1 insertion(+) diff --git a/test/jdk/tools/jar/ReproducibleJar.java b/test/jdk/tools/jar/ReproducibleJar.java index 5fb46def40d..ed5e2ed2ae3 100644 --- a/test/jdk/tools/jar/ReproducibleJar.java +++ b/test/jdk/tools/jar/ReproducibleJar.java @@ -23,6 +23,7 @@ /* * @test + * @requires vm.bits == 64 * @bug 8276766 * @summary Test jar --date source date of entries and that jars are * reproducible -- GitLab From 5cd95153331860f990c268bd28e4cd38f3ce6d4a Mon Sep 17 00:00:00 2001 From: "Daniel D. Daugherty" Date: Wed, 5 Jan 2022 16:37:42 +0000 Subject: [PATCH 008/564] 8279525: ProblemList java/awt/GraphicsDevice/CheckDisplayModes.java on macosx-aarch64 Reviewed-by: ccheung --- test/jdk/ProblemList.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 35d3b832729..8a7a913749f 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -517,6 +517,7 @@ java/awt/KeyboardFocusmanager/TypeAhead/ButtonActionKeyTest/ButtonActionKeyTest. java/awt/Window/GetScreenLocation/GetScreenLocationTest.java 8225787 linux-x64 java/awt/Dialog/MakeWindowAlwaysOnTop/MakeWindowAlwaysOnTop.java 8266243 macosx-aarch64 java/awt/dnd/BadSerializationTest/BadSerializationTest.java 8277817 linux-x64,windows-x64 +java/awt/GraphicsDevice/CheckDisplayModes.java 8266242 macosx-aarch64 ############################################################################ -- GitLab From 590fa9d8d75b4cf401fe5a1556f4f0b7145a77ab Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Wed, 5 Jan 2022 18:37:00 +0000 Subject: [PATCH 009/564] 8278612: [macos] test/jdk/java/awt/dnd/RemoveDropTargetCrashTest crashes with VoiceOver on macOS Reviewed-by: serb, kizune --- .../awt/a11y/CommonComponentAccessibility.h | 1 + .../awt/a11y/CommonComponentAccessibility.m | 22 ++++++++++++++++--- .../awt/a11y/TabButtonAccessibility.m | 13 ++++++----- 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CommonComponentAccessibility.h b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CommonComponentAccessibility.h index 33ab5c5fd2e..be0169a064d 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CommonComponentAccessibility.h +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CommonComponentAccessibility.h @@ -83,6 +83,7 @@ - (NSView* _Nonnull)view; - (NSWindow* _Nonnull)window; - (id _Nonnull)parent; +- (CommonComponentAccessibility* _Nullable)typeSafeParent; - (NSString* _Nonnull)javaRole; - (BOOL)isMenu; diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CommonComponentAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CommonComponentAccessibility.m index 69fc9908fd5..d53d0350abf 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CommonComponentAccessibility.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CommonComponentAccessibility.m @@ -95,7 +95,11 @@ static jobject sAccessibilityClass = NULL; return NO; } - return isChildSelected(env, ((CommonComponentAccessibility *)[self parent])->fAccessible, fIndex, fComponent); + CommonComponentAccessibility* parent = [self typeSafeParent]; + if (parent != nil) { + return isChildSelected(env, parent->fAccessible, fIndex, fComponent); + } + return NO; } - (BOOL)isSelectable:(JNIEnv *)env @@ -708,6 +712,15 @@ static jobject sAccessibilityClass = NULL; return fParent; } +- (CommonComponentAccessibility *)typeSafeParent +{ + id parent = [self parent]; + if ([parent isKindOfClass:[CommonComponentAccessibility class]]) { + return (CommonComponentAccessibility*)parent; + } + return nil; +} + - (NSString *)javaRole { if(fJavaRole == nil) { @@ -824,11 +837,13 @@ static jobject sAccessibilityClass = NULL; if (fNSRole == nil) { NSString *javaRole = [self javaRole]; fNSRole = [sRoles objectForKey:javaRole]; + CommonComponentAccessibility* parent = [self typeSafeParent]; // The sRoles NSMutableDictionary maps popupmenu to Mac's popup button. // JComboBox behavior currently relies on this. However this is not the // proper mapping for a JPopupMenu so fix that. if ( [javaRole isEqualToString:@"popupmenu"] && - ![[[self parent] javaRole] isEqualToString:@"combobox"] ) { + parent != nil && + ![[parent javaRole] isEqualToString:@"combobox"] ) { fNSRole = NSAccessibilityMenuRole; } if (fNSRole == nil) { @@ -1025,8 +1040,9 @@ static jobject sAccessibilityClass = NULL; // This may change when later fixing issues which currently // exist for combo boxes, but for now the following is only // for JPopupMenus, not for combobox menus. - id parent = [self parent]; + id parent = [self typeSafeParent]; if ( [[self javaRole] isEqualToString:@"popupmenu"] && + parent != nil && ![[parent javaRole] isEqualToString:@"combobox"] ) { NSArray *children = [CommonComponentAccessibility childrenOfParent:self diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabButtonAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabButtonAccessibility.m index 4caf97c21cb..538240028b8 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabButtonAccessibility.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabButtonAccessibility.m @@ -59,11 +59,14 @@ - (jobject)tabGroup { if (fTabGroupAxContext == NULL) { - JNIEnv* env = [ThreadUtilities getJNIEnv]; - jobject tabGroupAxContext = [(CommonComponentAccessibility *)[self parent] axContextWithEnv:env]; - fTabGroupAxContext = (*env)->NewWeakGlobalRef(env, tabGroupAxContext); - CHECK_EXCEPTION(); - (*env)->DeleteLocalRef(env, tabGroupAxContext); + CommonComponentAccessibility* parent = [self typeSafeParent]; + if (parent != nil) { + JNIEnv *env = [ThreadUtilities getJNIEnv]; + jobject tabGroupAxContext = [parent axContextWithEnv:env]; + fTabGroupAxContext = (*env)->NewWeakGlobalRef(env, tabGroupAxContext); + CHECK_EXCEPTION(); + (*env)->DeleteLocalRef(env, tabGroupAxContext); + } } return fTabGroupAxContext; } -- GitLab From 9a0e890056fb8ae4e28e656118e73fae33ba5e2a Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Wed, 5 Jan 2022 18:55:49 +0000 Subject: [PATCH 010/564] 8277515: Update --release 18 symbol information for JDK 18 build 29 Reviewed-by: iris --- make/data/symbols/java.base-I.sym.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/make/data/symbols/java.base-I.sym.txt b/make/data/symbols/java.base-I.sym.txt index 4657f5cfcfe..35fe19bb6e5 100644 --- a/make/data/symbols/java.base-I.sym.txt +++ b/make/data/symbols/java.base-I.sym.txt @@ -1,5 +1,5 @@ # -# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2021, 2022, 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 @@ -284,6 +284,10 @@ innerclass innerClass java/security/KeyStore$Entry outerClass java/security/KeyS innerclass innerClass java/security/KeyStore$Entry$Attribute outerClass java/security/KeyStore$Entry innerClassName Attribute flags 609 method name engineGetAttributes descriptor (Ljava/lang/String;)Ljava/util/Set; flags 1 signature (Ljava/lang/String;)Ljava/util/Set; +class name java/security/Provider +-method name getServices descriptor ()Ljava/util/Set; +method name getServices descriptor ()Ljava/util/Set; flags 1 signature ()Ljava/util/Set; + class name java/security/SecureRandomParameters header extends java/lang/Object flags 601 -- GitLab From 564c8c6390ee380ab2e2eb73ef22c3184c369f9f Mon Sep 17 00:00:00 2001 From: "Daniel D. Daugherty" Date: Wed, 5 Jan 2022 19:01:11 +0000 Subject: [PATCH 011/564] 8279529: ProblemList java/nio/channels/DatagramChannel/ManySourcesAndTargets.java on macosx-aarch64 8279532: ProblemList sun/security/ssl/SSLSessionImpl/NoInvalidateSocketException.java Reviewed-by: jnimeh --- test/jdk/ProblemList.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 8a7a913749f..dec007c4896 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -607,6 +607,8 @@ java/nio/channels/DatagramChannel/Unref.java 8233519 generic- java/nio/channels/AsynchronousSocketChannel/StressLoopback.java 8211851 aix-ppc64 +java/nio/channels/DatagramChannel/ManySourcesAndTargets.java 8264385 macosx-aarch64 + ############################################################################ # jdk_rmi @@ -672,6 +674,7 @@ javax/security/auth/kerberos/KerberosTixDateTest.java 8039280 generic- sun/security/provider/PolicyFile/GrantAllPermToExtWhenNoPolicy.java 8039280 generic-all sun/security/provider/PolicyParser/ExtDirsChange.java 8039280 generic-all sun/security/provider/PolicyParser/PrincipalExpansionError.java 8039280 generic-all +sun/security/ssl/SSLSessionImpl/NoInvalidateSocketException.java 8277970 linux-all,macosx-x64 ############################################################################ -- GitLab From 7b429a64ce7def84833de9e95217f303d9a7629d Mon Sep 17 00:00:00 2001 From: Zhengyu Gu Date: Wed, 5 Jan 2022 19:12:41 +0000 Subject: [PATCH 012/564] 8279168: Shenandoah: Remove unused always_true in ShenandoahRootAdjuster::roots_do() Reviewed-by: shade --- src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp index b134e4da146..21a21053c89 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp @@ -209,7 +209,6 @@ void ShenandoahRootAdjuster::roots_do(uint worker_id, OopClosure* oops) { static_cast(&blobs_and_disarm_Cl) : static_cast(&code_blob_cl); CLDToOopClosure adjust_cld_closure(oops, ClassLoaderData::_claim_strong); - AlwaysTrueClosure always_true; // Process light-weight/limited parallel roots then _vm_roots.oops_do(oops, worker_id); -- GitLab From 523300e7968b28ade4bbfe004030227a224ab2dc Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Wed, 5 Jan 2022 19:45:27 +0000 Subject: [PATCH 013/564] 8279526: Exceptions::count_out_of_memory_exceptions miscounts class metaspace OOMEs Reviewed-by: zgu, coleenp --- src/hotspot/share/utilities/exceptions.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/utilities/exceptions.cpp b/src/hotspot/share/utilities/exceptions.cpp index d7de88b9c50..4ddc8e18ae6 100644 --- a/src/hotspot/share/utilities/exceptions.cpp +++ b/src/hotspot/share/utilities/exceptions.cpp @@ -463,7 +463,7 @@ volatile int Exceptions::_out_of_memory_error_class_metaspace_errors = 0; void Exceptions::count_out_of_memory_exceptions(Handle exception) { if (Universe::is_out_of_memory_error_metaspace(exception())) { Atomic::inc(&_out_of_memory_error_metaspace_errors, memory_order_relaxed); - } else if (Universe::is_out_of_memory_error_metaspace(exception())) { + } else if (Universe::is_out_of_memory_error_class_metaspace(exception())) { Atomic::inc(&_out_of_memory_error_class_metaspace_errors, memory_order_relaxed); } else { // everything else reported as java heap OOM -- GitLab From ab490534a1d14ad48ceb532ec1673ca9636f552d Mon Sep 17 00:00:00 2001 From: Ludvig Janiuk Date: Wed, 5 Jan 2022 20:09:32 +0000 Subject: [PATCH 014/564] 8279533: Bad indentation and missing curly braces in BlockBegin::set_end Reviewed-by: shade --- src/hotspot/share/c1/c1_Instruction.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/hotspot/share/c1/c1_Instruction.cpp b/src/hotspot/share/c1/c1_Instruction.cpp index 790c35e5020..4b66796a543 100644 --- a/src/hotspot/share/c1/c1_Instruction.cpp +++ b/src/hotspot/share/c1/c1_Instruction.cpp @@ -529,9 +529,10 @@ void BlockBegin::set_end(BlockEnd* new_end) { // Assumes that no predecessor of if (new_end == _end) return; // Remove this block as predecessor of its current successors - if (_end != NULL) - for (int i = 0; i < number_of_sux(); i++) { - sux_at(i)->remove_predecessor(this); + if (_end != NULL) { + for (int i = 0; i < number_of_sux(); i++) { + sux_at(i)->remove_predecessor(this); + } } _end = new_end; -- GitLab From 456bd1ed1cbfedc225194e9afb917b913e5bc9d5 Mon Sep 17 00:00:00 2001 From: Vicente Romero Date: Thu, 6 Jan 2022 05:58:17 +0000 Subject: [PATCH 015/564] 8211004: javac is complaining about non-denotable types and refusing to generate the class file Reviewed-by: jlahoda --- .../share/classes/com/sun/tools/javac/comp/Attr.java | 8 ++++++++ .../com/sun/tools/javac/resources/compiler.properties | 5 +++++ test/langtools/tools/javac/8203436/T8203436a.java | 2 +- test/langtools/tools/javac/8203436/T8203436a.out | 2 +- test/langtools/tools/javac/8203436/T8203436b.out | 2 +- test/langtools/tools/javac/diags/examples.not-yet.txt | 1 + .../tools/javac/diags/examples/IllegalSignature.java | 3 +-- test/langtools/tools/javac/generics/diamond/neg/Neg21.out | 3 ++- 8 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java index 7bd813cddb7..ae489536ec4 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java @@ -50,9 +50,11 @@ import com.sun.tools.javac.comp.Check.CheckContext; import com.sun.tools.javac.comp.DeferredAttr.AttrMode; import com.sun.tools.javac.comp.MatchBindingsComputer.MatchBindings; import com.sun.tools.javac.jvm.*; + import static com.sun.tools.javac.resources.CompilerProperties.Fragments.Diamond; import static com.sun.tools.javac.resources.CompilerProperties.Fragments.DiamondInvalidArg; import static com.sun.tools.javac.resources.CompilerProperties.Fragments.DiamondInvalidArgs; + import com.sun.tools.javac.resources.CompilerProperties.Errors; import com.sun.tools.javac.resources.CompilerProperties.Fragments; import com.sun.tools.javac.resources.CompilerProperties.Warnings; @@ -2909,6 +2911,12 @@ public class Attr extends JCTree.Visitor { // ... // } InferenceContext inferenceContext = resultInfo.checkContext.inferenceContext(); + Type enclType = clazztype.getEnclosingType(); + if (enclType != null && + enclType.hasTag(CLASS) && + !chk.checkDenotable((ClassType)enclType)) { + log.error(tree.encl, Errors.EnclosingClassTypeNonDenotable(enclType)); + } final boolean isDiamond = TreeInfo.isDiamond(tree); if (isDiamond && ((tree.constructorType != null && inferenceContext.free(tree.constructorType)) diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties index 3fd713fabfc..ae2f1f8c6fc 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties @@ -3912,3 +3912,8 @@ compiler.warn.declared.using.preview=\ compiler.warn.attempt.to.synchronize.on.instance.of.value.based.class=\ attempt to synchronize on an instance of a value-based class + +# 0: type +compiler.err.enclosing.class.type.non.denotable=\ + enclosing class type: {0}\n\ + is non-denotable, try casting to a denotable type diff --git a/test/langtools/tools/javac/8203436/T8203436a.java b/test/langtools/tools/javac/8203436/T8203436a.java index eba0f827c86..db47a62e672 100644 --- a/test/langtools/tools/javac/8203436/T8203436a.java +++ b/test/langtools/tools/javac/8203436/T8203436a.java @@ -1,6 +1,6 @@ /* * @test /nodynamiccopyright/ - * @bug 8203436 + * @bug 8203436 8211004 * @summary javac should fail early when emitting illegal signature attributes * @compile/fail/ref=T8203436a.out -XDrawDiagnostics T8203436a.java */ diff --git a/test/langtools/tools/javac/8203436/T8203436a.out b/test/langtools/tools/javac/8203436/T8203436a.out index 71b7e687166..e076a20a2a8 100644 --- a/test/langtools/tools/javac/8203436/T8203436a.out +++ b/test/langtools/tools/javac/8203436/T8203436a.out @@ -1,2 +1,2 @@ -- compiler.err.cannot.generate.class: compiler.misc.anonymous.class: T8203436a$1, (compiler.misc.illegal.signature: compiler.misc.anonymous.class: T8203436a$1, compiler.misc.type.captureof: 1, ?) +T8203436a.java:12:7: compiler.err.enclosing.class.type.non.denotable: T8203436a 1 error diff --git a/test/langtools/tools/javac/8203436/T8203436b.out b/test/langtools/tools/javac/8203436/T8203436b.out index 979e550fff6..48eb947cecf 100644 --- a/test/langtools/tools/javac/8203436/T8203436b.out +++ b/test/langtools/tools/javac/8203436/T8203436b.out @@ -1,2 +1,2 @@ -- compiler.err.cannot.generate.class: compiler.misc.anonymous.class: T8203436b$1, (compiler.misc.illegal.signature: compiler.misc.anonymous.class: T8203436b$1, java.lang.Object&T8203436b.A&T8203436b.B) +T8203436b.java:17:10: compiler.err.enclosing.class.type.non.denotable: T8203436b 1 error diff --git a/test/langtools/tools/javac/diags/examples.not-yet.txt b/test/langtools/tools/javac/diags/examples.not-yet.txt index f257b7df8e0..9f9f8f78014 100644 --- a/test/langtools/tools/javac/diags/examples.not-yet.txt +++ b/test/langtools/tools/javac/diags/examples.not-yet.txt @@ -206,3 +206,4 @@ compiler.warn.source.target.conflict compiler.warn.target.default.source.conflict compiler.err.preview.not.latest compiler.err.preview.without.source.or.release +compiler.misc.illegal.signature # the compiler can now detect more non-denotable types before class writing diff --git a/test/langtools/tools/javac/diags/examples/IllegalSignature.java b/test/langtools/tools/javac/diags/examples/IllegalSignature.java index a9b64b41afa..96b93b6bdab 100644 --- a/test/langtools/tools/javac/diags/examples/IllegalSignature.java +++ b/test/langtools/tools/javac/diags/examples/IllegalSignature.java @@ -21,8 +21,7 @@ * questions. */ -// key: compiler.err.cannot.generate.class -// key: compiler.misc.illegal.signature +// key: compiler.err.enclosing.class.type.non.denotable class IllegalSignature { class Inner { } diff --git a/test/langtools/tools/javac/generics/diamond/neg/Neg21.out b/test/langtools/tools/javac/generics/diamond/neg/Neg21.out index 35e1a94cc15..d273f7ae713 100644 --- a/test/langtools/tools/javac/generics/diamond/neg/Neg21.out +++ b/test/langtools/tools/javac/generics/diamond/neg/Neg21.out @@ -1,2 +1,3 @@ +Neg21.java:13:9: compiler.err.enclosing.class.type.non.denotable: Neg21 Neg21.java:13:28: compiler.err.cant.apply.diamond.1: (compiler.misc.diamond: Neg21.A), (compiler.misc.diamond.invalid.arg: java.lang.Object&java.io.Serializable&java.lang.Cloneable, (compiler.misc.diamond: Neg21.A)) -1 error +2 errors -- GitLab From 2dbb936da91a875a5a88da5d4c0b4956b9c6368f Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Thu, 6 Jan 2022 08:12:53 +0000 Subject: [PATCH 016/564] 8279339: (ch) Input/Output streams returned by Channels factory methods don't support concurrent read/write ops Reviewed-by: lancea, bpb --- .../classes/java/nio/channels/Channels.java | 8 +- .../sun/nio/ch/ChannelInputStream.java | 118 +++-- .../sun/nio/ch/ChannelOutputStream.java | 89 ++-- .../classes/sun/nio/ch/SocketAdaptor.java | 45 +- .../classes/sun/nio/ch/SocketInputStream.java | 83 +++ .../sun/nio/ch/SocketOutputStream.java | 65 +++ .../share/classes/sun/nio/ch/Streams.java | 59 +++ .../Channels/SocketChannelStreams.java | 480 ++++++++++++++++++ 8 files changed, 791 insertions(+), 156 deletions(-) create mode 100644 src/java.base/share/classes/sun/nio/ch/SocketInputStream.java create mode 100644 src/java.base/share/classes/sun/nio/ch/SocketOutputStream.java create mode 100644 src/java.base/share/classes/sun/nio/ch/Streams.java create mode 100644 test/jdk/java/nio/channels/Channels/SocketChannelStreams.java diff --git a/src/java.base/share/classes/java/nio/channels/Channels.java b/src/java.base/share/classes/java/nio/channels/Channels.java index 3e68d49b2b7..1d2ccaa7788 100644 --- a/src/java.base/share/classes/java/nio/channels/Channels.java +++ b/src/java.base/share/classes/java/nio/channels/Channels.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2022, 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,8 +40,6 @@ import java.nio.charset.UnsupportedCharsetException; import java.nio.channels.spi.AbstractInterruptibleChannel; import java.util.Objects; import java.util.concurrent.ExecutionException; -import sun.nio.ch.ChannelInputStream; -import sun.nio.ch.ChannelOutputStream; import sun.nio.cs.StreamDecoder; import sun.nio.cs.StreamEncoder; @@ -87,7 +85,7 @@ public final class Channels { */ public static InputStream newInputStream(ReadableByteChannel ch) { Objects.requireNonNull(ch, "ch"); - return new ChannelInputStream(ch); + return sun.nio.ch.Streams.of(ch); } /** @@ -106,7 +104,7 @@ public final class Channels { */ public static OutputStream newOutputStream(WritableByteChannel ch) { Objects.requireNonNull(ch, "ch"); - return new ChannelOutputStream(ch); + return sun.nio.ch.Streams.of(ch); } /** diff --git a/src/java.base/share/classes/sun/nio/ch/ChannelInputStream.java b/src/java.base/share/classes/sun/nio/ch/ChannelInputStream.java index 4ddd30485af..6397eda0c93 100644 --- a/src/java.base/share/classes/sun/nio/ch/ChannelInputStream.java +++ b/src/java.base/share/classes/sun/nio/ch/ChannelInputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2022, 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,58 +40,52 @@ import java.util.Objects; import jdk.internal.util.ArraysSupport; /** - * This class is defined here rather than in java.nio.channels.Channels - * so that code can be shared with SocketAdaptor. + * An InputStream that reads bytes from a channel. * * @author Mike McCloskey * @author Mark Reinhold - * @since 1.4 */ - -public class ChannelInputStream - extends InputStream -{ +class ChannelInputStream extends InputStream { private static final int DEFAULT_BUFFER_SIZE = 8192; - public static int read(ReadableByteChannel ch, ByteBuffer bb, - boolean block) - throws IOException - { + private final ReadableByteChannel ch; + private ByteBuffer bb; + private byte[] bs; // Invoker's previous array + private byte[] b1; + + /** + * Initialize a ChannelInputStream that reads from the given channel. + */ + ChannelInputStream(ReadableByteChannel ch) { + this.ch = ch; + } + + /** + * Reads a sequence of bytes from the channel into the given buffer. + */ + private int read(ByteBuffer bb) throws IOException { if (ch instanceof SelectableChannel sc) { synchronized (sc.blockingLock()) { - boolean bm = sc.isBlocking(); - if (!bm) + if (!sc.isBlocking()) throw new IllegalBlockingModeException(); - if (bm != block) - sc.configureBlocking(block); - int n = ch.read(bb); - if (bm != block) - sc.configureBlocking(bm); - return n; + return ch.read(bb); } } else { return ch.read(bb); } } - protected final ReadableByteChannel ch; - private ByteBuffer bb = null; - private byte[] bs = null; // Invoker's previous array - private byte[] b1 = null; - - public ChannelInputStream(ReadableByteChannel ch) { - this.ch = ch; - } - + @Override public synchronized int read() throws IOException { if (b1 == null) b1 = new byte[1]; - int n = this.read(b1); + int n = read(b1); if (n == 1) return b1[0] & 0xff; return -1; } + @Override public synchronized int read(byte[] bs, int off, int len) throws IOException { @@ -109,12 +103,6 @@ public class ChannelInputStream return read(bb); } - protected int read(ByteBuffer bb) - throws IOException - { - return ChannelInputStream.read(ch, bb, true); - } - @Override public byte[] readAllBytes() throws IOException { if (!(ch instanceof SeekableByteChannel sbc)) @@ -201,6 +189,7 @@ public class ChannelInputStream return (capacity == nread) ? buf : Arrays.copyOf(buf, nread); } + @Override public int available() throws IOException { // special case where the channel is to a file if (ch instanceof SeekableByteChannel sbc) { @@ -210,6 +199,7 @@ public class ChannelInputStream return 0; } + @Override public synchronized long skip(long n) throws IOException { // special case where the channel is to a file if (ch instanceof SeekableByteChannel sbc) { @@ -230,46 +220,62 @@ public class ChannelInputStream return super.skip(n); } - public void close() throws IOException { - ch.close(); - } - @Override public long transferTo(OutputStream out) throws IOException { Objects.requireNonNull(out, "out"); - if (out instanceof ChannelOutputStream cos - && ch instanceof FileChannel fc) { - WritableByteChannel wbc = cos.channel(); - - if (wbc instanceof FileChannel dst) { - return transfer(fc, dst); - } - - if (wbc instanceof SelectableChannel sc) { + if (ch instanceof FileChannel fc) { + // FileChannel -> SocketChannel + if (out instanceof SocketOutputStream sos) { + SocketChannelImpl sc = sos.channel(); synchronized (sc.blockingLock()) { if (!sc.isBlocking()) throw new IllegalBlockingModeException(); - return transfer(fc, wbc); + return transfer(fc, sc); } } - return transfer(fc, wbc); + // FileChannel -> WritableByteChannel + if (out instanceof ChannelOutputStream cos) { + WritableByteChannel wbc = cos.channel(); + + if (wbc instanceof SelectableChannel sc) { + synchronized (sc.blockingLock()) { + if (!sc.isBlocking()) + throw new IllegalBlockingModeException(); + return transfer(fc, wbc); + } + } + + return transfer(fc, wbc); + } } return super.transferTo(out); } - private static long transfer(FileChannel src, WritableByteChannel dst) throws IOException { - long initialPos = src.position(); + /** + * Transfers all bytes from a channel's file to a target writeable byte channel. + * If the writeable byte channel is a selectable channel then it must be in + * blocking mode. + */ + private static long transfer(FileChannel fc, WritableByteChannel target) + throws IOException + { + long initialPos = fc.position(); long pos = initialPos; try { - while (pos < src.size()) { - pos += src.transferTo(pos, Long.MAX_VALUE, dst); + while (pos < fc.size()) { + pos += fc.transferTo(pos, Long.MAX_VALUE, target); } } finally { - src.position(pos); + fc.position(pos); } return pos - initialPos; } + + @Override + public void close() throws IOException { + ch.close(); + } } diff --git a/src/java.base/share/classes/sun/nio/ch/ChannelOutputStream.java b/src/java.base/share/classes/sun/nio/ch/ChannelOutputStream.java index a1e838efab4..dff8af9ebaf 100644 --- a/src/java.base/share/classes/sun/nio/ch/ChannelOutputStream.java +++ b/src/java.base/share/classes/sun/nio/ch/ChannelOutputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022, 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,68 +25,30 @@ package sun.nio.ch; -import java.io.*; -import java.nio.*; -import java.nio.channels.*; -import java.nio.channels.spi.*; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.ByteBuffer; +import java.nio.channels.IllegalBlockingModeException; +import java.nio.channels.SelectableChannel; +import java.nio.channels.WritableByteChannel; import java.util.Objects; /** - * This class is defined here rather than in java.nio.channels.Channels - * so that it will be accessible from java.nio.channels.Channels and - * sun.nio.ch.ChannelInputStream. - * + * An OutputStream that writes bytes to a channel. * * @author Mark Reinhold * @author Mike McCloskey - * @author JSR-51 Expert Group - * @since 18 */ -public class ChannelOutputStream extends OutputStream { - +class ChannelOutputStream extends OutputStream { private final WritableByteChannel ch; private ByteBuffer bb; private byte[] bs; // Invoker's previous array private byte[] b1; /** - * Write all remaining bytes in buffer to the given channel. - * If the channel is selectable then it must be configured blocking. - */ - private static void writeFullyImpl(WritableByteChannel ch, ByteBuffer bb) - throws IOException - { - while (bb.remaining() > 0) { - int n = ch.write(bb); - if (n <= 0) - throw new RuntimeException("no bytes written"); - } - } - - /** - * Write all remaining bytes in buffer to the given channel. - * - * @throws IllegalBlockingModeException - * If the channel is selectable and configured non-blocking. - */ - private static void writeFully(WritableByteChannel ch, ByteBuffer bb) - throws IOException - { - if (ch instanceof SelectableChannel sc) { - synchronized (sc.blockingLock()) { - if (!sc.isBlocking()) - throw new IllegalBlockingModeException(); - writeFullyImpl(ch, bb); - } - } else { - writeFullyImpl(ch, bb); - } - } - - /** - * @param ch The channel wrapped by this stream. + * Initialize a ChannelOutputStream that writes to the given channel. */ - public ChannelOutputStream(WritableByteChannel ch) { + ChannelOutputStream(WritableByteChannel ch) { this.ch = ch; } @@ -97,17 +59,30 @@ public class ChannelOutputStream extends OutputStream { return ch; } + /** + * Write all remaining bytes in buffer to the channel. + * If the channel is selectable then it must be configured blocking. + */ + private void writeFully(ByteBuffer bb) throws IOException { + while (bb.remaining() > 0) { + int n = ch.write(bb); + if (n <= 0) + throw new RuntimeException("no bytes written"); + } + } + @Override public synchronized void write(int b) throws IOException { if (b1 == null) b1 = new byte[1]; b1[0] = (byte) b; - this.write(b1); + write(b1); } @Override public synchronized void write(byte[] bs, int off, int len) - throws IOException { + throws IOException + { Objects.checkFromIndexSize(off, len, bs.length); if (len == 0) { return; @@ -119,12 +94,20 @@ public class ChannelOutputStream extends OutputStream { bb.position(off); this.bb = bb; this.bs = bs; - writeFully(ch, bb); + + if (ch instanceof SelectableChannel sc) { + synchronized (sc.blockingLock()) { + if (!sc.isBlocking()) + throw new IllegalBlockingModeException(); + writeFully(bb); + } + } else { + writeFully(bb); + } } @Override public void close() throws IOException { ch.close(); } - } diff --git a/src/java.base/share/classes/sun/nio/ch/SocketAdaptor.java b/src/java.base/share/classes/sun/nio/ch/SocketAdaptor.java index bcab4b67a75..745d8d7f1f8 100644 --- a/src/java.base/share/classes/sun/nio/ch/SocketAdaptor.java +++ b/src/java.base/share/classes/sun/nio/ch/SocketAdaptor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -177,32 +177,7 @@ class SocketAdaptor throw new SocketException("Socket is not connected"); if (!sc.isInputOpen()) throw new SocketException("Socket input is shutdown"); - return new InputStream() { - @Override - public int read() throws IOException { - byte[] a = new byte[1]; - int n = read(a, 0, 1); - return (n > 0) ? (a[0] & 0xff) : -1; - } - @Override - public int read(byte[] b, int off, int len) throws IOException { - int timeout = SocketAdaptor.this.timeout; - if (timeout > 0) { - long nanos = MILLISECONDS.toNanos(timeout); - return sc.blockingRead(b, off, len, nanos); - } else { - return sc.blockingRead(b, off, len, 0); - } - } - @Override - public int available() throws IOException { - return sc.available(); - } - @Override - public void close() throws IOException { - sc.close(); - } - }; + return new SocketInputStream(sc, () -> timeout); } @Override @@ -213,21 +188,7 @@ class SocketAdaptor throw new SocketException("Socket is not connected"); if (!sc.isOutputOpen()) throw new SocketException("Socket output is shutdown"); - return new OutputStream() { - @Override - public void write(int b) throws IOException { - byte[] a = new byte[]{(byte) b}; - write(a, 0, 1); - } - @Override - public void write(byte[] b, int off, int len) throws IOException { - sc.blockingWriteFully(b, off, len); - } - @Override - public void close() throws IOException { - sc.close(); - } - }; + return new SocketOutputStream(sc); } private void setBooleanOption(SocketOption name, boolean value) diff --git a/src/java.base/share/classes/sun/nio/ch/SocketInputStream.java b/src/java.base/share/classes/sun/nio/ch/SocketInputStream.java new file mode 100644 index 00000000000..6c69eaf5214 --- /dev/null +++ b/src/java.base/share/classes/sun/nio/ch/SocketInputStream.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.nio.ch; + +import java.io.IOException; +import java.io.InputStream; +import java.util.function.IntSupplier; +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +/** + * An InputStream that reads bytes from a socket channel. + */ +class SocketInputStream extends InputStream { + private final SocketChannelImpl sc; + private final IntSupplier timeoutSupplier; + + /** + * Initialize a SocketInputStream that reads from the given socket channel. + * @param sc the socket channel + * @param timeoutSupplier supplies the read timeout, in milliseconds + */ + SocketInputStream(SocketChannelImpl sc, IntSupplier timeoutSupplier) { + this.sc = sc; + this.timeoutSupplier = timeoutSupplier; + } + + /** + * Initialize a SocketInputStream that reads from the given socket channel. + */ + SocketInputStream(SocketChannelImpl sc) { + this(sc, () -> 0); + } + + @Override + public int read() throws IOException { + byte[] a = new byte[1]; + int n = read(a, 0, 1); + return (n > 0) ? (a[0] & 0xff) : -1; + } + + @Override + public int read(byte[] b, int off, int len) throws IOException { + int timeout = timeoutSupplier.getAsInt(); + if (timeout > 0) { + long nanos = MILLISECONDS.toNanos(timeout); + return sc.blockingRead(b, off, len, nanos); + } else { + return sc.blockingRead(b, off, len, 0); + } + } + + @Override + public int available() throws IOException { + return sc.available(); + } + + @Override + public void close() throws IOException { + sc.close(); + } +} diff --git a/src/java.base/share/classes/sun/nio/ch/SocketOutputStream.java b/src/java.base/share/classes/sun/nio/ch/SocketOutputStream.java new file mode 100644 index 00000000000..78d0dce46fa --- /dev/null +++ b/src/java.base/share/classes/sun/nio/ch/SocketOutputStream.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.nio.ch; + +import java.io.IOException; +import java.io.OutputStream; + +/** + * An OutputStream that writes bytes to a socket channel. + */ +class SocketOutputStream extends OutputStream { + private final SocketChannelImpl sc; + + /** + * Initialize a SocketOutputStream that writes to the given socket channel. + */ + SocketOutputStream(SocketChannelImpl sc) { + this.sc = sc; + } + + /** + * Returns the socket channel. + */ + SocketChannelImpl channel() { + return sc; + } + + @Override + public void write(int b) throws IOException { + byte[] a = new byte[]{(byte) b}; + write(a, 0, 1); + } + + @Override + public void write(byte[] b, int off, int len) throws IOException { + sc.blockingWriteFully(b, off, len); + } + + @Override + public void close() throws IOException { + sc.close(); + } +} diff --git a/src/java.base/share/classes/sun/nio/ch/Streams.java b/src/java.base/share/classes/sun/nio/ch/Streams.java new file mode 100644 index 00000000000..4326c9e2e0b --- /dev/null +++ b/src/java.base/share/classes/sun/nio/ch/Streams.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.nio.ch; + +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.WritableByteChannel; + +/** + * Factory methods for input/output streams based on channels. + */ +public class Streams { + private Streams() { } + + /** + * Return an input stream that reads bytes from the given channel. + */ + public static InputStream of(ReadableByteChannel ch) { + if (ch instanceof SocketChannelImpl sc) { + return new SocketInputStream(sc); + } else { + return new ChannelInputStream(ch); + } + } + + /** + * Return an output stream that writes bytes to the given channel. + */ + public static OutputStream of(WritableByteChannel ch) { + if (ch instanceof SocketChannelImpl sc) { + return new SocketOutputStream(sc); + } else { + return new ChannelOutputStream(ch); + } + } +} diff --git a/test/jdk/java/nio/channels/Channels/SocketChannelStreams.java b/test/jdk/java/nio/channels/Channels/SocketChannelStreams.java new file mode 100644 index 00000000000..57142fb03d7 --- /dev/null +++ b/test/jdk/java/nio/channels/Channels/SocketChannelStreams.java @@ -0,0 +1,480 @@ +/* + * Copyright (c) 2022, 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 8279339 + * @run testng SocketChannelStreams + * @summary Exercise InputStream/OutputStream returned by Channels.newXXXStream + * when channel is a SocketChannel + */ + +import java.io.Closeable; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.nio.channels.Channels; +import java.nio.channels.IllegalBlockingModeException; +import java.nio.channels.ServerSocketChannel; +import java.nio.channels.SocketChannel; +import java.util.Objects; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +import org.testng.annotations.*; +import static org.testng.Assert.*; + +@Test +public class SocketChannelStreams { + private ScheduledExecutorService executor; + + @BeforeClass() + public void init() { + executor = Executors.newSingleThreadScheduledExecutor(); + } + + @AfterClass + public void finish() { + executor.shutdown(); + } + + /** + * Test read when bytes are available. + */ + public void testRead1() throws Exception { + withConnection((sc, peer) -> { + write(peer, 99); + int n = Channels.newInputStream(sc).read(); + assertEquals(n, 99); + }); + } + + /** + * Test read blocking before bytes are available. + */ + public void testRead2() throws Exception { + withConnection((sc, peer) -> { + scheduleWrite(peer, 99, 1000); + int n = Channels.newInputStream(sc).read(); + assertEquals(n, 99); + }); + } + + /** + * Test read after peer has closed connection. + */ + public void testRead3() throws Exception { + withConnection((sc, peer) -> { + peer.close(); + int n = Channels.newInputStream(sc).read(); + assertEquals(n, -1); + }); + } + + /** + * Test read blocking before peer closes connection. + */ + public void testRead4() throws Exception { + withConnection((sc, peer) -> { + scheduleClose(peer, 1000); + int n = Channels.newInputStream(sc).read(); + assertEquals(n, -1); + }); + } + + /** + * Test async close of channel when thread blocked in read. + */ + public void testRead5() throws Exception { + withConnection((sc, peer) -> { + scheduleClose(sc, 2000); + InputStream in = Channels.newInputStream(sc); + expectThrows(IOException.class, () -> in.read()); + }); + } + + /** + * Test async close of input stream, when thread blocked in read. + */ + public void testRead6() throws Exception { + withConnection((sc, peer) -> { + InputStream in = Channels.newInputStream(sc); + scheduleClose(in, 2000); + expectThrows(IOException.class, () -> in.read()); + }); + } + + /** + * Test interrupt status set before read. + */ + public void testRead7() throws Exception { + withConnection((sc, peer) -> { + Thread.currentThread().interrupt(); + try { + InputStream in = Channels.newInputStream(sc); + expectThrows(IOException.class, () -> in.read()); + } finally { + Thread.interrupted(); // clear interrupt + } + assertFalse(sc.isOpen()); + }); + } + + /** + * Test interrupt of thread blocked in read. + */ + public void testRead8() throws Exception { + withConnection((sc, peer) -> { + Future interrupter = scheduleInterrupt(Thread.currentThread(), 2000); + try { + InputStream in = Channels.newInputStream(sc); + expectThrows(IOException.class, () -> in.read()); + } finally { + interrupter.cancel(true); + Thread.interrupted(); // clear interrupt + } + assertFalse(sc.isOpen()); + }); + } + + /** + * Test that read is untimed when SO_TIMEOUT is set on the Socket adaptor. + */ + public void testRead9() throws Exception { + withConnection((sc, peer) -> { + sc.socket().setSoTimeout(100); + scheduleWrite(peer, 99, 2000); + // read should block until bytes are available + int b = Channels.newInputStream(sc).read(); + assertTrue(b == 99); + }); + } + + /** + * Test write. + */ + public void testWrite1() throws Exception { + withConnection((sc, peer) -> { + OutputStream out = Channels.newOutputStream(sc); + out.write(99); + int n = read(peer); + assertEquals(n, 99); + }); + } + + /** + * Test async close of channel when thread blocked in write. + */ + public void testWrite2() throws Exception { + withConnection((sc, peer) -> { + scheduleClose(sc, 2000); + expectThrows(IOException.class, () -> { + OutputStream out = Channels.newOutputStream(sc); + byte[] data = new byte[64*1000]; + while (true) { + out.write(data); + } + }); + }); + } + + /** + * Test async close of output stream when thread blocked in write. + */ + public void testWrite3() throws Exception { + withConnection((sc, peer) -> { + OutputStream out = Channels.newOutputStream(sc); + scheduleClose(out, 2000); + expectThrows(IOException.class, () -> { + byte[] data = new byte[64*1000]; + while (true) { + out.write(data); + } + }); + }); + } + + /** + * Test interrupt status set before write. + */ + public void testWrite4() throws Exception { + withConnection((sc, peer) -> { + Thread.currentThread().interrupt(); + try { + OutputStream out = Channels.newOutputStream(sc); + expectThrows(IOException.class, () -> out.write(99)); + } finally { + Thread.interrupted(); // clear interrupt + } + assertFalse(sc.isOpen()); + }); + } + + /** + * Test interrupt of thread blocked in write. + */ + public void testWrite5() throws Exception { + withConnection((sc, peer) -> { + Future interrupter = scheduleInterrupt(Thread.currentThread(), 2000); + try { + expectThrows(IOException.class, () -> { + OutputStream out = Channels.newOutputStream(sc); + byte[] data = new byte[64*1000]; + while (true) { + out.write(data); + } + }); + } finally { + interrupter.cancel(true); + Thread.interrupted(); // clear interrupt + } + assertFalse(sc.isOpen()); + }); + } + + /** + * Test read when another thread is blocked in write. The read should + * complete immediately. + */ + public void testConcurrentReadWrite1() throws Exception { + withConnection((sc, peer) -> { + InputStream in = Channels.newInputStream(sc); + OutputStream out = Channels.newOutputStream(sc); + + // block thread in write + fork(() -> { + var data = new byte[64*1024]; + for (;;) { + out.write(data); + } + }); + Thread.sleep(1000); // give writer time to block + + // test read, should not be blocked by writer thread + write(peer, 99); + int n = in.read(); + assertEquals(n, 99); + }); + } + + /** + * Test read when another thread is blocked in write. The read should + * block until bytes are available. + */ + public void testConcurrentReadWrite2() throws Exception { + withConnection((sc, peer) -> { + InputStream in = Channels.newInputStream(sc); + OutputStream out = Channels.newOutputStream(sc); + + // block thread in write + fork(() -> { + var data = new byte[64*1024]; + for (;;) { + out.write(data); + } + }); + Thread.sleep(1000); // give writer time to block + + // test read, should not be blocked by writer thread + scheduleWrite(peer, 99, 500); + int n = in.read(); + assertEquals(n, 99); + }); + } + + /** + * Test writing when another thread is blocked in read. + */ + public void testConcurrentReadWrite3() throws Exception { + withConnection((sc, peer) -> { + InputStream in = Channels.newInputStream(sc); + OutputStream out = Channels.newOutputStream(sc); + + // block thread in read + fork(() -> { + in.read(); + }); + Thread.sleep(100); // give reader time to block + + // test write, should not be blocked by reader thread + out.write(99); + int n = read(peer); + assertEquals(n, 99); + }); + } + + /** + * Test read/write when channel configured non-blocking. + */ + public void testIllegalBlockingMode() throws Exception { + withConnection((sc, peer) -> { + InputStream in = Channels.newInputStream(sc); + OutputStream out = Channels.newOutputStream(sc); + + sc.configureBlocking(false); + expectThrows(IllegalBlockingModeException.class, () -> in.read()); + expectThrows(IllegalBlockingModeException.class, () -> out.write(99)); + }); + } + + /** + * Test NullPointerException. + */ + public void testNullPointerException() throws Exception { + withConnection((sc, peer) -> { + InputStream in = Channels.newInputStream(sc); + OutputStream out = Channels.newOutputStream(sc); + + expectThrows(NullPointerException.class, () -> in.read(null)); + expectThrows(NullPointerException.class, () -> in.read(null, 0, 0)); + + expectThrows(NullPointerException.class, () -> out.write(null)); + expectThrows(NullPointerException.class, () -> out.write(null, 0, 0)); + }); + } + + /** + * Test IndexOutOfBoundsException. + */ + public void testIndexOutOfBoundsException() throws Exception { + withConnection((sc, peer) -> { + InputStream in = Channels.newInputStream(sc); + OutputStream out = Channels.newOutputStream(sc); + byte[] ba = new byte[100]; + + expectThrows(IndexOutOfBoundsException.class, () -> in.read(ba, -1, 1)); + expectThrows(IndexOutOfBoundsException.class, () -> in.read(ba, 0, -1)); + expectThrows(IndexOutOfBoundsException.class, () -> in.read(ba, 0, 1000)); + expectThrows(IndexOutOfBoundsException.class, () -> in.read(ba, 1, 100)); + + expectThrows(IndexOutOfBoundsException.class, () -> out.write(ba, -1, 1)); + expectThrows(IndexOutOfBoundsException.class, () -> out.write(ba, 0, -1)); + expectThrows(IndexOutOfBoundsException.class, () -> out.write(ba, 0, 1000)); + expectThrows(IndexOutOfBoundsException.class, () -> out.write(ba, 1, 100)); + }); + } + + // -- test infrastructure -- + + private interface ThrowingTask { + void run() throws Exception; + } + + private interface ThrowingBiConsumer { + void accept(T t, U u) throws Exception; + } + + /** + * Invokes the consumer with a connected pair of socket channels. + */ + private static void withConnection(ThrowingBiConsumer consumer) + throws Exception + { + var loopback = InetAddress.getLoopbackAddress(); + try (ServerSocketChannel listener = ServerSocketChannel.open()) { + listener.bind(new InetSocketAddress(loopback, 0)); + try (SocketChannel sc = SocketChannel.open(listener.getLocalAddress())) { + try (SocketChannel peer = listener.accept()) { + consumer.accept(sc, peer); + } + } + } + } + + /** + * Forks a thread to execute the given task. + */ + private Future fork(ThrowingTask task) { + ExecutorService pool = Executors.newFixedThreadPool(1); + try { + return pool.submit(() -> { + task.run(); + return null; + }); + } finally { + pool.shutdown(); + } + } + + /** + * Read a byte from the given socket channel. + */ + private int read(SocketChannel sc) throws IOException { + return sc.socket().getInputStream().read(); + } + + /** + * Write a byte to the given socket channel. + */ + private void write(SocketChannel sc, int b) throws IOException { + sc.socket().getOutputStream().write(b); + } + + /** + * Writes the given data to the socket channel after a delay. + */ + private Future scheduleWrite(SocketChannel sc, byte[] data, long delay) { + return schedule(() -> { + try { + sc.socket().getOutputStream().write(data); + } catch (IOException ioe) { } + }, delay); + } + + /** + * Writes a byte to the socket channel after a delay. + */ + private Future scheduleWrite(SocketChannel sc, int b, long delay) { + return scheduleWrite(sc, new byte[] { (byte)b }, delay); + } + + /** + * Closes the given object after a delay. + */ + private Future scheduleClose(Closeable c, long delay) { + return schedule(() -> { + try { + c.close(); + } catch (IOException ioe) { } + }, delay); + } + + /** + * Interrupts the given Thread after a delay. + */ + private Future scheduleInterrupt(Thread t, long delay) { + return schedule(() -> t.interrupt(), delay); + } + + /** + * Schedules the given task to run after a delay. + */ + private Future schedule(Runnable task, long delay) { + return executor.schedule(task, delay, TimeUnit.MILLISECONDS); + } +} -- GitLab From bc12381105ef5ba14f99304a220817e97c9a99b5 Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Thu, 6 Jan 2022 08:27:54 +0000 Subject: [PATCH 017/564] 8279505: Update documentation for RETRY_COUNT and REPEAT_COUNT Reviewed-by: erikj, serb --- doc/testing.html | 4 ++-- doc/testing.md | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/doc/testing.html b/doc/testing.html index f647af91934..213e23664c3 100644 --- a/doc/testing.html +++ b/doc/testing.html @@ -193,9 +193,9 @@ TEST FAILURE

AOT_MODULES

Generate AOT modules before testing for the specified module, or set of modules. If multiple modules are specified, they should be separated by space (or, to help avoid quoting issues, the special value %20).

RETRY_COUNT

-

Retry failed tests up to a set number of times. Defaults to 0.

+

Retry failed tests up to a set number of times, until they pass. This allows to pass the tests with intermittent failures. Defaults to 0.

REPEAT_COUNT

-

Repeat the tests for a set number of times. Defaults to 0.

+

Repeat the tests up to a set number of times, stopping at first failure. This helps to reproduce intermittent test failures. Defaults to 0.

Gtest keywords

REPEAT

The number of times to repeat the tests (--gtest_repeat).

diff --git a/doc/testing.md b/doc/testing.md index bba5ae0941c..3ab7079ea07 100644 --- a/doc/testing.md +++ b/doc/testing.md @@ -419,11 +419,15 @@ modules. If multiple modules are specified, they should be separated by space #### RETRY_COUNT -Retry failed tests up to a set number of times. Defaults to 0. +Retry failed tests up to a set number of times, until they pass. +This allows to pass the tests with intermittent failures. +Defaults to 0. #### REPEAT_COUNT -Repeat the tests for a set number of times. Defaults to 0. +Repeat the tests up to a set number of times, stopping at first failure. +This helps to reproduce intermittent test failures. +Defaults to 0. ### Gtest keywords -- GitLab From 7c792f27a8f6ccf87922cc5f2768946e55e33816 Mon Sep 17 00:00:00 2001 From: Fairoz Matte Date: Thu, 6 Jan 2022 14:20:45 +0000 Subject: [PATCH 018/564] 8279333: Some JFR tests do not accept 'GCLocker Initiated GC' as a valid GC Cause Reviewed-by: egahlin --- .../event/gc/collection/TestGCCauseWithG1ConcurrentMark.java | 5 +++-- .../event/gc/collection/TestGCCauseWithG1FullCollection.java | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/test/jdk/jdk/jfr/event/gc/collection/TestGCCauseWithG1ConcurrentMark.java b/test/jdk/jdk/jfr/event/gc/collection/TestGCCauseWithG1ConcurrentMark.java index 730a3b700c6..d98fdb76e92 100644 --- a/test/jdk/jdk/jfr/event/gc/collection/TestGCCauseWithG1ConcurrentMark.java +++ b/test/jdk/jdk/jfr/event/gc/collection/TestGCCauseWithG1ConcurrentMark.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,7 +40,8 @@ public class TestGCCauseWithG1ConcurrentMark { String testID = "G1ConcurrentMark"; String[] vmFlags = {"-XX:+UseG1GC", "-XX:+ExplicitGCInvokesConcurrent"}; String[] gcNames = {GCHelper.gcG1New, GCHelper.gcG1Old, GCHelper.gcG1Full}; - String[] gcCauses = {"G1 Evacuation Pause", "G1 Preventive Collection", "G1 Compaction Pause", "System.gc()"}; + String[] gcCauses = {"GCLocker Initiated GC", "G1 Evacuation Pause", "G1 Preventive Collection", + "G1 Compaction Pause", "System.gc()"}; GCGarbageCollectionUtil.test(testID, vmFlags, gcNames, gcCauses); } } diff --git a/test/jdk/jdk/jfr/event/gc/collection/TestGCCauseWithG1FullCollection.java b/test/jdk/jdk/jfr/event/gc/collection/TestGCCauseWithG1FullCollection.java index 67650dc3ba8..737b94aa197 100644 --- a/test/jdk/jdk/jfr/event/gc/collection/TestGCCauseWithG1FullCollection.java +++ b/test/jdk/jdk/jfr/event/gc/collection/TestGCCauseWithG1FullCollection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,7 +40,8 @@ public class TestGCCauseWithG1FullCollection { String testID = "G1FullCollection"; String[] vmFlags = {"-XX:+UseG1GC"}; String[] gcNames = {GCHelper.gcG1New, GCHelper.gcG1Old, GCHelper.gcG1Full}; - String[] gcCauses = {"G1 Evacuation Pause", "G1 Preventive Collection", "G1 Compaction Pause", "System.gc()"}; + String[] gcCauses = {"GCLocker Initiated GC", "G1 Evacuation Pause", "G1 Preventive Collection", + "G1 Compaction Pause", "System.gc()"}; GCGarbageCollectionUtil.test(testID, vmFlags, gcNames, gcCauses); } } -- GitLab From 8703f14808d7256d4b07e7ea8a232889bbca4894 Mon Sep 17 00:00:00 2001 From: Jatin Bhateja Date: Thu, 6 Jan 2022 18:41:06 +0000 Subject: [PATCH 019/564] 8273322: Enhance macro logic optimization for masked logic operations. Reviewed-by: kvn, sviswanathan --- src/hotspot/cpu/x86/assembler_x86.cpp | 64 +- src/hotspot/cpu/x86/assembler_x86.hpp | 8 +- src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp | 22 +- src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp | 9 +- src/hotspot/cpu/x86/x86.ad | 29 + src/hotspot/share/opto/compile.cpp | 122 ++- src/hotspot/share/opto/matcher.cpp | 10 +- src/hotspot/share/opto/vectornode.cpp | 7 +- src/hotspot/share/opto/vectornode.hpp | 14 +- .../vectorapi/TestMaskedMacroLogicVector.java | 844 ++++++++++++++++++ .../jdk/incubator/vector/MaskedLogicOpts.java | 331 +++++++ .../bench/vm/compiler/MacroLogicOpt.java | 4 +- 12 files changed, 1413 insertions(+), 51 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/vectorapi/TestMaskedMacroLogicVector.java create mode 100644 test/micro/org/openjdk/bench/jdk/incubator/vector/MaskedLogicOpts.java diff --git a/src/hotspot/cpu/x86/assembler_x86.cpp b/src/hotspot/cpu/x86/assembler_x86.cpp index 26d58624b12..d0753f0de11 100644 --- a/src/hotspot/cpu/x86/assembler_x86.cpp +++ b/src/hotspot/cpu/x86/assembler_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -9725,6 +9725,68 @@ void Assembler::evpmaxsq(XMMRegister dst, KRegister mask, XMMRegister nds, Addre emit_operand(dst, src); } +void Assembler::evpternlogd(XMMRegister dst, int imm8, KRegister mask, XMMRegister src2, XMMRegister src3, bool merge, int vector_len) { + assert(VM_Version::supports_evex(), "requires EVEX support"); + assert(vector_len == Assembler::AVX_512bit || VM_Version::supports_avx512vl(), "requires VL support"); + InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true); + attributes.set_is_evex_instruction(); + attributes.set_embedded_opmask_register_specifier(mask); + if (merge) { + attributes.reset_is_clear_context(); + } + int encode = vex_prefix_and_encode(dst->encoding(), src2->encoding(), src3->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); + emit_int24(0x25, (unsigned char)(0xC0 | encode), imm8); +} + +void Assembler::evpternlogd(XMMRegister dst, int imm8, KRegister mask, XMMRegister src2, Address src3, bool merge, int vector_len) { + assert(VM_Version::supports_evex(), "requires EVEX support"); + assert(vector_len == Assembler::AVX_512bit || VM_Version::supports_avx512vl(), "requires VL support"); + assert(dst != xnoreg, "sanity"); + InstructionMark im(this); + InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true); + attributes.set_is_evex_instruction(); + attributes.set_embedded_opmask_register_specifier(mask); + attributes.set_address_attributes(/* tuple_type */ EVEX_FV, /* input_size_in_bits */ EVEX_64bit); + if (merge) { + attributes.reset_is_clear_context(); + } + vex_prefix(src3, src2->encoding(), dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); + emit_int8(0x25); + emit_operand(dst, src3); + emit_int8(imm8); +} + +void Assembler::evpternlogq(XMMRegister dst, int imm8, KRegister mask, XMMRegister src2, XMMRegister src3, bool merge, int vector_len) { + assert(VM_Version::supports_evex(), "requires EVEX support"); + assert(vector_len == Assembler::AVX_512bit || VM_Version::supports_avx512vl(), "requires VL support"); + InstructionAttr attributes(vector_len, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true); + attributes.set_is_evex_instruction(); + attributes.set_embedded_opmask_register_specifier(mask); + if (merge) { + attributes.reset_is_clear_context(); + } + int encode = vex_prefix_and_encode(dst->encoding(), src2->encoding(), src3->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); + emit_int24(0x25, (unsigned char)(0xC0 | encode), imm8); +} + +void Assembler::evpternlogq(XMMRegister dst, int imm8, KRegister mask, XMMRegister src2, Address src3, bool merge, int vector_len) { + assert(VM_Version::supports_evex(), "requires EVEX support"); + assert(vector_len == Assembler::AVX_512bit || VM_Version::supports_avx512vl(), "requires VL support"); + assert(dst != xnoreg, "sanity"); + InstructionMark im(this); + InstructionAttr attributes(vector_len, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true); + attributes.set_is_evex_instruction(); + attributes.set_embedded_opmask_register_specifier(mask); + attributes.set_address_attributes(/* tuple_type */ EVEX_FV, /* input_size_in_bits */ EVEX_64bit); + if (merge) { + attributes.reset_is_clear_context(); + } + vex_prefix(src3, src2->encoding(), dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); + emit_int8(0x25); + emit_operand(dst, src3); + emit_int8(imm8); +} + // duplicate 4-byte integer data from src into programmed locations in dest : requires AVX512VL void Assembler::vpbroadcastd(XMMRegister dst, XMMRegister src, int vector_len) { assert(UseAVX >= 2, ""); diff --git a/src/hotspot/cpu/x86/assembler_x86.hpp b/src/hotspot/cpu/x86/assembler_x86.hpp index dd0aae12526..92d04d21839 100644 --- a/src/hotspot/cpu/x86/assembler_x86.hpp +++ b/src/hotspot/cpu/x86/assembler_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -2413,6 +2413,12 @@ private: void evprorvd(XMMRegister dst, KRegister mask, XMMRegister nds, XMMRegister src, bool merge, int vector_len); void evprorvq(XMMRegister dst, KRegister mask, XMMRegister nds, XMMRegister src, bool merge, int vector_len); + void evpternlogd(XMMRegister dst, int imm8, KRegister mask, XMMRegister src2, XMMRegister src3, bool merge, int vector_len); + void evpternlogd(XMMRegister dst, int imm8, KRegister mask, XMMRegister src2, Address src3, bool merge, int vector_len); + void evpternlogq(XMMRegister dst, int imm8, KRegister mask, XMMRegister src2, XMMRegister src3, bool merge, int vector_len); + void evpternlogq(XMMRegister dst, int imm8, KRegister mask, XMMRegister src2, Address src3, bool merge, int vector_len); + + // Sub packed integers void psubb(XMMRegister dst, XMMRegister src); void psubw(XMMRegister dst, XMMRegister src); diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp index a601f35f1c1..7405e73d4f7 100644 --- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, 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 @@ -4152,6 +4152,26 @@ void C2_MacroAssembler::vector_castF2I_evex(XMMRegister dst, XMMRegister src, XM bind(done); } +void C2_MacroAssembler::evpternlog(XMMRegister dst, int func, KRegister mask, XMMRegister src2, XMMRegister src3, + bool merge, BasicType bt, int vlen_enc) { + if (bt == T_INT) { + evpternlogd(dst, func, mask, src2, src3, merge, vlen_enc); + } else { + assert(bt == T_LONG, ""); + evpternlogq(dst, func, mask, src2, src3, merge, vlen_enc); + } +} + +void C2_MacroAssembler::evpternlog(XMMRegister dst, int func, KRegister mask, XMMRegister src2, Address src3, + bool merge, BasicType bt, int vlen_enc) { + if (bt == T_INT) { + evpternlogd(dst, func, mask, src2, src3, merge, vlen_enc); + } else { + assert(bt == T_LONG, ""); + evpternlogq(dst, func, mask, src2, src3, merge, vlen_enc); + } +} + #ifdef _LP64 void C2_MacroAssembler::vector_long_to_maskvec(XMMRegister dst, Register src, Register rtmp1, Register rtmp2, XMMRegister xtmp, int mask_len, diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp index a9ff6455853..3a1ad1d27e0 100644 --- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, 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 @@ -311,4 +311,11 @@ public: void vector_castD2L_evex(XMMRegister dst, XMMRegister src, XMMRegister xtmp1, XMMRegister xtmp2, KRegister ktmp1, KRegister ktmp2, AddressLiteral double_sign_flip, Register scratch, int vec_enc); + + void evpternlog(XMMRegister dst, int func, KRegister mask, XMMRegister src2, XMMRegister src3, + bool merge, BasicType bt, int vlen_enc); + + void evpternlog(XMMRegister dst, int func, KRegister mask, XMMRegister src2, Address src3, + bool merge, BasicType bt, int vlen_enc); + #endif // CPU_X86_C2_MACROASSEMBLER_X86_HPP diff --git a/src/hotspot/cpu/x86/x86.ad b/src/hotspot/cpu/x86/x86.ad index 023ef62ceea..8d5ba613b28 100644 --- a/src/hotspot/cpu/x86/x86.ad +++ b/src/hotspot/cpu/x86/x86.ad @@ -1888,6 +1888,12 @@ const bool Matcher::match_rule_supported_vector_masked(int opcode, int vlen, Bas case Op_FmaVD: return true; + case Op_MacroLogicV: + if(bt != T_INT && bt != T_LONG) { + return false; + } + return true; + // Binary masked operations case Op_AddVB: case Op_AddVS: @@ -9560,6 +9566,29 @@ instruct mask_opers_evex(kReg dst, kReg src1, kReg src2, kReg kscratch) %{ ins_pipe( pipe_slow ); %} +instruct vternlog_reg_masked(vec dst, vec src2, vec src3, immU8 func, kReg mask) %{ + match(Set dst (MacroLogicV dst (Binary src2 (Binary src3 (Binary func mask))))); + format %{ "vternlog_masked $dst,$src2,$src3,$func,$mask\t! vternlog masked operation" %} + ins_encode %{ + int vlen_enc = vector_length_encoding(this); + BasicType bt = Matcher::vector_element_basic_type(this); + __ evpternlog($dst$$XMMRegister, $func$$constant, $mask$$KRegister, + $src2$$XMMRegister, $src3$$XMMRegister, true, bt, vlen_enc); + %} + ins_pipe( pipe_slow ); +%} + +instruct vternlogd_mem_masked(vec dst, vec src2, memory src3, immU8 func, kReg mask) %{ + match(Set dst (MacroLogicV dst (Binary src2 (Binary src3 (Binary func mask))))); + format %{ "vternlog_masked $dst,$src2,$src3,$func,$mask\t! vternlog masked operation" %} + ins_encode %{ + int vlen_enc = vector_length_encoding(this); + BasicType bt = Matcher::vector_element_basic_type(this); + __ evpternlog($dst$$XMMRegister, $func$$constant, $mask$$KRegister, + $src2$$XMMRegister, $src3$$Address, true, bt, vlen_enc); + %} + ins_pipe( pipe_slow ); +%} instruct castMM(kReg dst) %{ diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index 2e74da81fbb..8e184164b77 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -2375,7 +2375,6 @@ bool Compile::has_vbox_nodes() { static bool is_vector_unary_bitwise_op(Node* n) { return n->Opcode() == Op_XorV && - n->req() == 2 && VectorNode::is_vector_bitwise_not_pattern(n); } @@ -2383,7 +2382,7 @@ static bool is_vector_binary_bitwise_op(Node* n) { switch (n->Opcode()) { case Op_AndV: case Op_OrV: - return n->req() == 2; + return true; case Op_XorV: return !is_vector_unary_bitwise_op(n); @@ -2415,11 +2414,12 @@ static bool is_vector_bitwise_cone_root(Node* n) { return true; } -static uint collect_unique_inputs(Node* n, Unique_Node_List& partition, Unique_Node_List& inputs) { +static uint collect_unique_inputs(Node* n, Unique_Node_List& inputs) { uint cnt = 0; if (is_vector_bitwise_op(n)) { + uint inp_cnt = n->is_predicated_vector() ? n->req()-1 : n->req(); if (VectorNode::is_vector_bitwise_not_pattern(n)) { - for (uint i = 1; i < n->req(); i++) { + for (uint i = 1; i < inp_cnt; i++) { Node* in = n->in(i); bool skip = VectorNode::is_all_ones_vector(in); if (!skip && !inputs.member(in)) { @@ -2429,9 +2429,9 @@ static uint collect_unique_inputs(Node* n, Unique_Node_List& partition, Unique_N } assert(cnt <= 1, "not unary"); } else { - uint last_req = n->req(); + uint last_req = inp_cnt; if (is_vector_ternary_bitwise_op(n)) { - last_req = n->req() - 1; // skip last input + last_req = inp_cnt - 1; // skip last input } for (uint i = 1; i < last_req; i++) { Node* def = n->in(i); @@ -2441,7 +2441,6 @@ static uint collect_unique_inputs(Node* n, Unique_Node_List& partition, Unique_N } } } - partition.push(n); } else { // not a bitwise operations if (!inputs.member(n)) { inputs.push(n); @@ -2476,7 +2475,10 @@ Node* Compile::xform_to_MacroLogicV(PhaseIterGVN& igvn, Node* in3 = (inputs.size() == 3 ? inputs.at(2) : in2); uint func = compute_truth_table(partition, inputs); - return igvn.transform(MacroLogicVNode::make(igvn, in3, in2, in1, func, vt)); + + Node* pn = partition.at(partition.size() - 1); + Node* mask = pn->is_predicated_vector() ? pn->in(pn->req()-1) : NULL; + return igvn.transform(MacroLogicVNode::make(igvn, in1, in2, in3, mask, func, vt)); } static uint extract_bit(uint func, uint pos) { @@ -2556,11 +2558,11 @@ uint Compile::compute_truth_table(Unique_Node_List& partition, Unique_Node_List& // Populate precomputed functions for inputs. // Each input corresponds to one column of 3 input truth-table. - uint input_funcs[] = { 0xAA, // (_, _, a) -> a + uint input_funcs[] = { 0xAA, // (_, _, c) -> c 0xCC, // (_, b, _) -> b - 0xF0 }; // (c, _, _) -> c + 0xF0 }; // (a, _, _) -> a for (uint i = 0; i < inputs.size(); i++) { - eval_map.put(inputs.at(i), input_funcs[i]); + eval_map.put(inputs.at(i), input_funcs[2-i]); } for (uint i = 0; i < partition.size(); i++) { @@ -2603,6 +2605,14 @@ uint Compile::compute_truth_table(Unique_Node_List& partition, Unique_Node_List& return res; } +// Criteria under which nodes gets packed into a macro logic node:- +// 1) Parent and both child nodes are all unmasked or masked with +// same predicates. +// 2) Masked parent can be packed with left child if it is predicated +// and both have same predicates. +// 3) Masked parent can be packed with right child if its un-predicated +// or has matching predication condition. +// 4) An unmasked parent can be packed with an unmasked child. bool Compile::compute_logic_cone(Node* n, Unique_Node_List& partition, Unique_Node_List& inputs) { assert(partition.size() == 0, "not empty"); assert(inputs.size() == 0, "not empty"); @@ -2612,37 +2622,65 @@ bool Compile::compute_logic_cone(Node* n, Unique_Node_List& partition, Unique_No bool is_unary_op = is_vector_unary_bitwise_op(n); if (is_unary_op) { - assert(collect_unique_inputs(n, partition, inputs) == 1, "not unary"); + assert(collect_unique_inputs(n, inputs) == 1, "not unary"); return false; // too few inputs } - assert(is_vector_binary_bitwise_op(n), "not binary"); - Node* in1 = n->in(1); - Node* in2 = n->in(2); + bool pack_left_child = true; + bool pack_right_child = true; + + bool left_child_LOP = is_vector_bitwise_op(n->in(1)); + bool right_child_LOP = is_vector_bitwise_op(n->in(2)); + + int left_child_input_cnt = 0; + int right_child_input_cnt = 0; - int in1_unique_inputs_cnt = collect_unique_inputs(in1, partition, inputs); - int in2_unique_inputs_cnt = collect_unique_inputs(in2, partition, inputs); - partition.push(n); + bool parent_is_predicated = n->is_predicated_vector(); + bool left_child_predicated = n->in(1)->is_predicated_vector(); + bool right_child_predicated = n->in(2)->is_predicated_vector(); - // Too many inputs? - if (inputs.size() > 3) { - partition.clear(); - inputs.clear(); - { // Recompute in2 inputs - Unique_Node_List not_used; - in2_unique_inputs_cnt = collect_unique_inputs(in2, not_used, not_used); + Node* parent_pred = parent_is_predicated ? n->in(n->req()-1) : NULL; + Node* left_child_pred = left_child_predicated ? n->in(1)->in(n->in(1)->req()-1) : NULL; + Node* right_child_pred = right_child_predicated ? n->in(1)->in(n->in(1)->req()-1) : NULL; + + do { + if (pack_left_child && left_child_LOP && + ((!parent_is_predicated && !left_child_predicated) || + ((parent_is_predicated && left_child_predicated && + parent_pred == left_child_pred)))) { + partition.push(n->in(1)); + left_child_input_cnt = collect_unique_inputs(n->in(1), inputs); + } else { + inputs.push(n->in(1)); + left_child_input_cnt = 1; } - // Pick the node with minimum number of inputs. - if (in1_unique_inputs_cnt >= 3 && in2_unique_inputs_cnt >= 3) { - return false; // still too many inputs + + if (pack_right_child && right_child_LOP && + (!right_child_predicated || + (right_child_predicated && parent_is_predicated && + parent_pred == right_child_pred))) { + partition.push(n->in(2)); + right_child_input_cnt = collect_unique_inputs(n->in(2), inputs); + } else { + inputs.push(n->in(2)); + right_child_input_cnt = 1; } - // Recompute partition & inputs. - Node* child = (in1_unique_inputs_cnt < in2_unique_inputs_cnt ? in1 : in2); - collect_unique_inputs(child, partition, inputs); - Node* other_input = (in1_unique_inputs_cnt < in2_unique_inputs_cnt ? in2 : in1); - inputs.push(other_input); + if (inputs.size() > 3) { + assert(partition.size() > 0, ""); + inputs.clear(); + partition.clear(); + if (left_child_input_cnt > right_child_input_cnt) { + pack_left_child = false; + } else { + pack_right_child = false; + } + } else { + break; + } + } while(true); + if(partition.size()) { partition.push(n); } @@ -2650,7 +2688,6 @@ bool Compile::compute_logic_cone(Node* n, Unique_Node_List& partition, Unique_No (inputs.size() == 2 || inputs.size() == 3); } - void Compile::process_logic_cone_root(PhaseIterGVN &igvn, Node *n, VectorSet &visited) { assert(is_vector_bitwise_op(n), "not a root"); @@ -2670,8 +2707,19 @@ void Compile::process_logic_cone_root(PhaseIterGVN &igvn, Node *n, VectorSet &vi Unique_Node_List inputs; if (compute_logic_cone(n, partition, inputs)) { const TypeVect* vt = n->bottom_type()->is_vect(); - Node* macro_logic = xform_to_MacroLogicV(igvn, vt, partition, inputs); - igvn.replace_node(n, macro_logic); + Node* pn = partition.at(partition.size() - 1); + Node* mask = pn->is_predicated_vector() ? pn->in(pn->req()-1) : NULL; + if (mask == NULL || + Matcher::match_rule_supported_vector_masked(Op_MacroLogicV, vt->length(), vt->element_basic_type())) { + Node* macro_logic = xform_to_MacroLogicV(igvn, vt, partition, inputs); +#ifdef ASSERT + if (TraceNewVectors) { + tty->print("new Vector node: "); + macro_logic->dump(); + } +#endif + igvn.replace_node(n, macro_logic); + } } } diff --git a/src/hotspot/share/opto/matcher.cpp b/src/hotspot/share/opto/matcher.cpp index 21198087fd9..ca5c8d03380 100644 --- a/src/hotspot/share/opto/matcher.cpp +++ b/src/hotspot/share/opto/matcher.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -2320,6 +2320,14 @@ void Matcher::find_shared_post_visit(Node* n, uint opcode) { n->set_req(2, new BinaryNode(n->in(3), n->in(4))); n->del_req(4); n->del_req(3); + } else if (n->req() == 6) { + Node* b3 = new BinaryNode(n->in(4), n->in(5)); + Node* b2 = new BinaryNode(n->in(3), b3); + Node* b1 = new BinaryNode(n->in(2), b2); + n->set_req(2, b1); + n->del_req(5); + n->del_req(4); + n->del_req(3); } return; } diff --git a/src/hotspot/share/opto/vectornode.cpp b/src/hotspot/share/opto/vectornode.cpp index d7ffa81c48b..51db711dc38 100644 --- a/src/hotspot/share/opto/vectornode.cpp +++ b/src/hotspot/share/opto/vectornode.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2022, 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 @@ -1201,13 +1201,14 @@ bool ReductionNode::implemented(int opc, uint vlen, BasicType bt) { } MacroLogicVNode* MacroLogicVNode::make(PhaseGVN& gvn, Node* in1, Node* in2, Node* in3, - uint truth_table, const TypeVect* vt) { + Node* mask, uint truth_table, const TypeVect* vt) { assert(truth_table <= 0xFF, "invalid"); assert(in1->bottom_type()->is_vect()->length_in_bytes() == vt->length_in_bytes(), "mismatch"); assert(in2->bottom_type()->is_vect()->length_in_bytes() == vt->length_in_bytes(), "mismatch"); assert(in3->bottom_type()->is_vect()->length_in_bytes() == vt->length_in_bytes(), "mismatch"); + assert(!mask || mask->bottom_type()->isa_vectmask(), "predicated register type expected"); Node* fn = gvn.intcon(truth_table); - return new MacroLogicVNode(in1, in2, in3, fn, vt); + return new MacroLogicVNode(in1, in2, in3, fn, mask, vt); } Node* VectorNode::degenerate_vector_rotate(Node* src, Node* cnt, bool is_rotate_left, diff --git a/src/hotspot/share/opto/vectornode.hpp b/src/hotspot/share/opto/vectornode.hpp index e52d4928a88..5e2d0eaf946 100644 --- a/src/hotspot/share/opto/vectornode.hpp +++ b/src/hotspot/share/opto/vectornode.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2022, 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 @@ -1275,13 +1275,19 @@ public: // Vector logical operations packing node. class MacroLogicVNode : public VectorNode { private: - MacroLogicVNode(Node* in1, Node* in2, Node* in3, Node* fn, const TypeVect* vt) - : VectorNode(in1, in2, in3, fn, vt) {} + MacroLogicVNode(Node* in1, Node* in2, Node* in3, Node* fn, Node* mask, const TypeVect* vt) + : VectorNode(in1, in2, in3, fn, vt) { + if (mask) { + this->add_req(mask); + this->add_flag(Node::Flag_is_predicated_vector); + } + } public: virtual int Opcode() const; - static MacroLogicVNode* make(PhaseGVN& igvn, Node* in1, Node* in2, Node* in3, uint truth_table, const TypeVect* vt); + static MacroLogicVNode* make(PhaseGVN& igvn, Node* in1, Node* in2, Node* in3, + Node* mask, uint truth_table, const TypeVect* vt); }; class VectorMaskCmpNode : public VectorNode { diff --git a/test/hotspot/jtreg/compiler/vectorapi/TestMaskedMacroLogicVector.java b/test/hotspot/jtreg/compiler/vectorapi/TestMaskedMacroLogicVector.java new file mode 100644 index 00000000000..e5f2e34040d --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorapi/TestMaskedMacroLogicVector.java @@ -0,0 +1,844 @@ +/* + * Copyright (c) 2022, 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 8273322 + * @key randomness + * @summary Enhance macro logic optimization for masked logic operations. + * @modules jdk.incubator.vector + * @requires vm.compiler2.enabled + * @requires os.simpleArch == "x64" + * @library /test/lib / + * @run driver compiler.vectorapi.TestMaskedMacroLogicVector + */ + +package compiler.vectorapi; + +import java.util.concurrent.Callable; +import compiler.lib.ir_framework.*; +import compiler.lib.ir_framework.driver.IRViolationException; +import jdk.test.lib.Asserts; +import jdk.test.lib.Asserts; +import jdk.test.lib.Utils; +import java.util.Random; + +import jdk.incubator.vector.*; + +public class TestMaskedMacroLogicVector { + boolean [] br; + boolean [] ba; + boolean [] bb; + + short [] sr; + char [] ca; + char [] cb; + + int [] r; + int [] a; + int [] b; + int [] c; + int [] d; + int [] e; + int [] f; + + long [] rl; + long [] al; + long [] bl; + long [] cl; + + boolean [] mask; + + static boolean booleanFunc1(boolean a, boolean b) { + return a & b; + } + + @Test + @IR(applyIf = {"UseAVX", "3"}, counts = {"MacroLogicV" , " > 0 "}) + public void testSubWordBoolean(boolean[] r, boolean[] a, boolean[] b) { + for (int i = 0; i < r.length; i++) { + r[i] = booleanFunc1(a[i], b[i]); + } + } + public void verifySubWordBoolean(boolean[] r, boolean[] a, boolean[] b) { + for (int i = 0; i < r.length; i++) { + boolean expected = booleanFunc1(a[i], b[i]); + if (r[i] != expected) { + throw new AssertionError( + String.format("at #%d: r=%b, expected = %b = booleanFunc1(%b,%b)", + i, r[i], expected, a[i], b[i])); + } + } + } + + + static short charFunc1(char a, char b) { + return (short)((a & b) & 1); + } + + @Test + @IR(applyIf = {"UseAVX", "3"}, counts = {"MacroLogicV" , " > 0 "}) + public void testSubWordChar(short[] r, char[] a, char[] b) { + for (int i = 0; i < r.length; i++) { + r[i] = charFunc1(a[i], b[i]); + } + } + public void verifySubWordChar(short[] r, char[] a, char[] b) { + for (int i = 0; i < r.length; i++) { + short expected = charFunc1(a[i], b[i]); + if (r[i] != expected) { + throw new AssertionError( + String.format("testSubWordChar: at #%d: r=%d, expected = %d = booleanFunc1(%d,%d)", + i, r[i], expected, (int)a[i], (int)b[i])); + } + } + } + + // Case 1): Unmasked expression tree. + // P_LOP + // L_LOP R_LOP + + static int intFunc1(int a, int b, int c) { + return (a & b) ^ (a & c); + } + + @ForceInline + public void testInt1Kernel(VectorSpecies SPECIES, int [] r, int [] a, int [] b, int [] c) { + for (int i = 0; i < SPECIES.loopBound(r.length); i += SPECIES.length()) { + IntVector va = IntVector.fromArray(SPECIES, a, i); + IntVector vb = IntVector.fromArray(SPECIES, b, i); + IntVector vc = IntVector.fromArray(SPECIES, c, i); + va.lanewise(VectorOperators.AND, vc) + .lanewise(VectorOperators.XOR, va.lanewise(VectorOperators.AND, vb)) + .intoArray(r, i); + } + } + + @Test + @IR(applyIf = {"UseAVX", "3"}, counts = {"MacroLogicV", " > 0 "}) + public void testInt1_Int128(int[] r, int[] a, int[] b, int[] c) { + testInt1Kernel(IntVector.SPECIES_128, r, a, b, c); + } + + @Test + @IR(applyIf = {"UseAVX", "3"}, counts = {"MacroLogicV", " > 0 "}) + public void testInt1_Int256(int[] r, int[] a, int[] b, int[] c) { + testInt1Kernel(IntVector.SPECIES_256, r, a, b, c); + } + + @Test + @IR(applyIf = {"UseAVX", "3"}, counts = {"MacroLogicV", " > 0 "}) + public void testInt1_Int512(int[] r, int[] a, int[] b, int[] c) { + testInt1Kernel(IntVector.SPECIES_512, r, a, b, c); + } + + public void verifyInt1(int[] r, int[] a, int[] b, int[] c) { + for (int i = 0; i < r.length; i++) { + int expected = intFunc1(a[i], b[i], c[i]); + if (r[i] != expected) { + throw new AssertionError(String.format("testInt1: at #%d: r=%d, expected = %d = intFunc1(%d,%d,%d)", + i, r[i], expected, a[i], b[i], c[i])); + } + } + } + + // Case 2): Only right child is masked. + // P_LOP + // L_LOP R_LOP(mask) + + static int intFunc2(int a, int b, int c, boolean mask) { + return (a & b) ^ (mask == true ? a & c : a); + } + + @ForceInline + public void testInt2Kernel(VectorSpecies SPECIES, int[] r, int[] a, int[] b, int[] c, boolean [] mask) { + for (int i = 0; i < SPECIES.loopBound(r.length); i += SPECIES.length()) { + VectorMask vmask = VectorMask.fromArray(SPECIES, mask , i); + IntVector va = IntVector.fromArray(SPECIES, a, i); + IntVector vb = IntVector.fromArray(SPECIES, b, i); + IntVector vc = IntVector.fromArray(SPECIES, c, i); + va.lanewise(VectorOperators.AND, vb) + .lanewise(VectorOperators.XOR, + va.lanewise(VectorOperators.AND, vc, vmask)) + .intoArray(r, i); + } + } + + @Test + @IR(applyIf = {"UseAVX", "3"}, counts = {"MacroLogicV", " > 0 "}) + public void testInt2_Int128(int[] r, int[] a, int[] b, int[] c, boolean [] mask) { + testInt2Kernel(IntVector.SPECIES_128, r, a, b, c, mask); + } + @Test + @IR(applyIf = {"UseAVX", "3"}, counts = {"MacroLogicV", " > 0 "}) + public void testInt2_Int256(int[] r, int[] a, int[] b, int[] c, boolean [] mask) { + testInt2Kernel(IntVector.SPECIES_256, r, a, b, c, mask); + } + @Test + @IR(applyIf = {"UseAVX", "3"}, counts = {"MacroLogicV", " > 0 "}) + public void testInt2_Int512(int[] r, int[] a, int[] b, int[] c, boolean [] mask) { + testInt2Kernel(IntVector.SPECIES_512, r, a, b, c, mask); + } + + public void verifyInt2(int[] r, int[] a, int[] b, int[] c, boolean [] mask) { + for (int i = 0; i < r.length; i++) { + int expected = intFunc2(a[i], b[i], c[i], mask[i]); + if (r[i] != expected) { + throw new AssertionError(String.format("testInt2: at #%d: r=%d, expected = %d = intFunc2(%d,%d,%d,%b)", + i, r[i], expected, a[i], b[i], c[i], mask[i])); + } + } + } + + // Case 3): Only left child is masked. + // P_LOP + // L_LOP(mask) R_LOP + + static int intFunc3(int a, int b, int c, boolean mask) { + return (mask == true ? a & b : a) ^ (a & c); + } + + @ForceInline + public void testInt3Kernel(VectorSpecies SPECIES, int[] r, int[] a, int[] b, int[] c, boolean [] mask) { + for (int i = 0; i < SPECIES.loopBound(r.length); i += SPECIES.length()) { + VectorMask vmask = VectorMask.fromArray(SPECIES, mask , i); + IntVector va = IntVector.fromArray(SPECIES, a, i); + IntVector vb = IntVector.fromArray(SPECIES, b, i); + IntVector vc = IntVector.fromArray(SPECIES, c, i); + va.lanewise(VectorOperators.AND, vb, vmask) + .lanewise(VectorOperators.XOR, + va.lanewise(VectorOperators.AND, vc)) + .intoArray(r, i); + } + } + + @Test + @IR(applyIf = {"UseAVX", "3"}, counts = {"MacroLogicV", " > 0 "}) + public void testInt3_Int128(int[] r, int[] a, int[] b, int[] c, boolean [] mask) { + testInt3Kernel(IntVector.SPECIES_128, r, a, b, c, mask); + } + @Test + @IR(applyIf = {"UseAVX", "3"}, counts = {"MacroLogicV", " > 0 "}) + public void testInt3_Int256(int[] r, int[] a, int[] b, int[] c, boolean [] mask) { + testInt3Kernel(IntVector.SPECIES_256, r, a, b, c, mask); + } + @Test + @IR(applyIf = {"UseAVX", "3"}, counts = {"MacroLogicV", " > 0 "}) + public void testInt3_Int512(int[] r, int[] a, int[] b, int[] c, boolean [] mask) { + testInt3Kernel(IntVector.SPECIES_512, r, a, b, c, mask); + } + + + @ForceInline + public void verifyInt3(int[] r, int[] a, int[] b, int[] c, boolean [] mask) { + for (int i = 0; i < r.length; i++) { + int expected = intFunc3(a[i], b[i], c[i], mask[i]); + if (r[i] != expected) { + throw new AssertionError(String.format("testInt3: at #%d: r=%d, expected = %d = intFunc3(%d,%d,%d,%b)", + i, r[i], expected, a[i], b[i], c[i], mask[i])); + } + } + } + + // Case 4): Both child nodes are masked. + // P_LOP + // L_LOP(mask) R_LOP(mask) + + static int intFunc4(int a, int b, int c, boolean mask) { + return (mask == true ? b & a : b) ^ (mask == true ? c & a : c); + } + + @ForceInline + public void testInt4Kernel(VectorSpecies SPECIES, int[] r, int[] a, int[] b, int[] c, boolean [] mask) { + for (int i = 0; i < SPECIES.loopBound(r.length); i += SPECIES.length()) { + VectorMask vmask = VectorMask.fromArray(SPECIES, mask , i); + IntVector va = IntVector.fromArray(SPECIES, a, i); + IntVector vb = IntVector.fromArray(SPECIES, b, i); + IntVector vc = IntVector.fromArray(SPECIES, c, i); + vb.lanewise(VectorOperators.AND, va, vmask) + .lanewise(VectorOperators.XOR, + vc.lanewise(VectorOperators.AND, va, vmask)) + .intoArray(r, i); + } + } + + @Test + @IR(applyIf = {"UseAVX", "3"}, counts = {"AndV", " > 0 ", "XorV", " > 0 "}) + public void testInt4_Int128(int[] r, int[] a, int[] b, int[] c, boolean [] mask) { + testInt4Kernel(IntVector.SPECIES_128, r, a, b, c, mask); + } + @Test + @IR(applyIf = {"UseAVX", "3"}, counts = {"AndV", " > 0 ", "XorV", " > 0 "}) + public void testInt4_Int256(int[] r, int[] a, int[] b, int[] c, boolean [] mask) { + testInt4Kernel(IntVector.SPECIES_256, r, a, b, c, mask); + } + @Test + @IR(applyIf = {"UseAVX", "3"}, counts = {"AndV", " > 0 ", "XorV", " > 0 "}) + public void testInt4_Int512(int[] r, int[] a, int[] b, int[] c, boolean [] mask) { + testInt4Kernel(IntVector.SPECIES_512, r, a, b, c, mask); + } + + public void verifyInt4(int[] r, int[] a, int[] b, int[] c, boolean [] mask) { + for (int i = 0; i < r.length; i++) { + int expected = intFunc4(a[i], b[i], c[i], mask[i]); + if (r[i] != expected) { + throw new AssertionError(String.format("testInt4: at #%d: r=%d, expected = %d = intFunc4(%d,%d,%d,%b)", + i, r[i], expected, a[i], b[i], c[i], mask[i])); + } + } + } + + // Case 5): Parent is masked with unmasked child expressions. + // P_LOP(mask) + // L_LOP R_LOP + + static int intFunc5(int a, int b, int c, boolean mask) { + return mask == true ? ((a & b) ^ (a & c)) : (a & b); + } + + @ForceInline + public void testInt5Kernel(VectorSpecies SPECIES, int[] r, int[] a, int[] b, int[] c, boolean [] mask) { + for (int i = 0; i < SPECIES.loopBound(r.length); i += SPECIES.length()) { + VectorMask vmask = VectorMask.fromArray(SPECIES, mask , i); + IntVector va = IntVector.fromArray(SPECIES, a, i); + IntVector vb = IntVector.fromArray(SPECIES, b, i); + IntVector vc = IntVector.fromArray(SPECIES, c, i); + va.lanewise(VectorOperators.AND, vb) + .lanewise(VectorOperators.XOR, + va.lanewise(VectorOperators.AND, vc), vmask) + .intoArray(r, i); + } + } + + @Test + @IR(applyIf = {"UseAVX", "3"}, counts = {"MacroLogicV", " > 0 "}) + public void testInt5_Int128(int[] r, int[] a, int[] b, int[] c, boolean [] mask) { + testInt5Kernel(IntVector.SPECIES_128, r, a, b, c, mask); + } + @Test + @IR(applyIf = {"UseAVX", "3"}, counts = {"MacroLogicV", " > 0 "}) + public void testInt5_Int256(int[] r, int[] a, int[] b, int[] c, boolean [] mask) { + testInt5Kernel(IntVector.SPECIES_256, r, a, b, c, mask); + } + @Test + @IR(applyIf = {"UseAVX", "3"}, counts = {"MacroLogicV", " > 0 "}) + public void testInt5_Int512(int[] r, int[] a, int[] b, int[] c, boolean [] mask) { + testInt5Kernel(IntVector.SPECIES_512, r, a, b, c, mask); + } + + @ForceInline + public void verifyInt5(int[] r, int[] a, int[] b, int[] c, boolean [] mask) { + for (int i = 0; i < r.length; i++) { + int expected = intFunc5(a[i], b[i], c[i], mask[i]); + if (r[i] != expected) { + throw new AssertionError(String.format("testInt5: at #%d: r=%d, expected = %d = intFunc5(%d,%d,%d,%b)", + i, r[i], expected, a[i], b[i], c[i], mask[i])); + } + } + } + + // Case 6): Parent and right child are masked. + // P_LOP(mask) + // L_LOP R_LOP(mask) + + static int intFunc6(int a, int b, int c, boolean mask) { + return mask == true ? ((a & b) ^ (mask == true ? a & c : a)) : (a & b); + } + + @ForceInline + public void testInt6Kernel(VectorSpecies SPECIES, int[] r, int[] a, int[] b, int[] c, boolean [] mask) { + for (int i = 0; i < SPECIES.loopBound(r.length); i += SPECIES.length()) { + VectorMask vmask = VectorMask.fromArray(SPECIES, mask , i); + IntVector va = IntVector.fromArray(SPECIES, a, i); + IntVector vb = IntVector.fromArray(SPECIES, b, i); + IntVector vc = IntVector.fromArray(SPECIES, c, i); + va.lanewise(VectorOperators.AND, vb) + .lanewise(VectorOperators.XOR, + va.lanewise(VectorOperators.AND, vc, vmask), vmask) + .intoArray(r, i); + } + } + @Test + @IR(applyIf = {"UseAVX", "3"}, counts = {"MacroLogicV", " > 0 "}) + public void testInt6_Int128(int[] r, int[] a, int[] b, int[] c, boolean [] mask) { + testInt6Kernel(IntVector.SPECIES_128, r, a, b, c, mask); + } + @Test + @IR(applyIf = {"UseAVX", "3"}, counts = {"MacroLogicV", " > 0 "}) + public void testInt6_Int256(int[] r, int[] a, int[] b, int[] c, boolean [] mask) { + testInt6Kernel(IntVector.SPECIES_256, r, a, b, c, mask); + } + @Test + @IR(applyIf = {"UseAVX", "3"}, counts = {"MacroLogicV", " > 0 "}) + public void testInt6_Int512(int[] r, int[] a, int[] b, int[] c, boolean [] mask) { + testInt6Kernel(IntVector.SPECIES_512, r, a, b, c, mask); + } + + + public void verifyInt6(int[] r, int[] a, int[] b, int[] c, boolean [] mask) { + for (int i = 0; i < r.length; i++) { + int expected = intFunc6(a[i], b[i], c[i], mask[i]); + if (r[i] != expected) { + throw new AssertionError(String.format("testInt6: at #%d: r=%d, expected = %d = intFunc6(%d,%d,%d,%b)", + i, r[i], expected, a[i], b[i], c[i], mask[i])); + } + } + } + + // Case 7): Parent and left child are masked. + // P_LOP(mask) + // L_LOP(mask) R_LOP + + static int intFunc7(int a, int b, int c, boolean mask) { + return mask == true ? ((mask == true ? a & b : a) ^ (a & c)) : a; + } + + @ForceInline + public void testInt7Kernel(VectorSpecies SPECIES, int[] r, int[] a, int[] b, int[] c, boolean [] mask) { + for (int i = 0; i < SPECIES.loopBound(r.length); i += SPECIES.length()) { + VectorMask vmask = VectorMask.fromArray(SPECIES, mask , i); + IntVector va = IntVector.fromArray(SPECIES, a, i); + IntVector vb = IntVector.fromArray(SPECIES, b, i); + IntVector vc = IntVector.fromArray(SPECIES, c, i); + va.lanewise(VectorOperators.AND, vb, vmask) + .lanewise(VectorOperators.XOR, + va.lanewise(VectorOperators.AND, vc), vmask) + .intoArray(r, i); + } + } + + @Test + @IR(applyIf = {"UseAVX", "3"}, counts = {"MacroLogicV", " > 0 "}) + public void testInt7_Int128(int[] r, int[] a, int[] b, int[] c, boolean [] mask) { + testInt7Kernel(IntVector.SPECIES_128, r, a, b, c, mask); + } + @Test + @IR(applyIf = {"UseAVX", "3"}, counts = {"MacroLogicV", " > 0 "}) + public void testInt7_Int256(int[] r, int[] a, int[] b, int[] c, boolean [] mask) { + testInt7Kernel(IntVector.SPECIES_256, r, a, b, c, mask); + } + @Test + @IR(applyIf = {"UseAVX", "3"}, counts = {"MacroLogicV", " > 0 "}) + public void testInt7_Int512(int[] r, int[] a, int[] b, int[] c, boolean [] mask) { + testInt7Kernel(IntVector.SPECIES_512, r, a, b, c, mask); + } + + public void verifyInt7(int[] r, int[] a, int[] b, int[] c, boolean [] mask) { + for (int i = 0; i < r.length; i++) { + int expected = intFunc7(a[i], b[i], c[i], mask[i]); + if (r[i] != expected) { + throw new AssertionError(String.format("testInt7: at #%d: r=%d, expected = %d = intFunc7(%d,%d,%d,%b)", + i, r[i], expected, a[i], b[i], c[i], mask[i])); + } + } + } + + // Case 8): Parent and both child expressions are masked. + // P_LOP(mask) + // L_LOP(mask) R_LOP (mask) + + static int intFunc8(int a, int b, int c, boolean mask) { + return mask == true ? ((mask == true ? b & a : b) ^ (mask == true ? c & a : c)) : b; + } + + @ForceInline + public void testInt8Kernel(VectorSpecies SPECIES, int[] r, int[] a, int[] b, int[] c, boolean [] mask) { + for (int i = 0; i < SPECIES.loopBound(r.length); i += SPECIES.length()) { + VectorMask vmask = VectorMask.fromArray(SPECIES, mask , i); + IntVector va = IntVector.fromArray(SPECIES, a, i); + IntVector vb = IntVector.fromArray(SPECIES, b, i); + IntVector vc = IntVector.fromArray(SPECIES, c, i); + vb.lanewise(VectorOperators.AND, va, vmask) + .lanewise(VectorOperators.XOR, + vc.lanewise(VectorOperators.AND, va, vmask), vmask) + .intoArray(r, i); + } + } + + @Test + @IR(applyIf = {"UseAVX", "3"}, counts = {"MacroLogicV", " > 0 "}) + public void testInt8_Int128(int[] r, int[] a, int[] b, int[] c, boolean [] mask) { + testInt8Kernel(IntVector.SPECIES_128, r, a, b, c, mask); + } + @Test + @IR(applyIf = {"UseAVX", "3"}, counts = {"MacroLogicV", " > 0 "}) + public void testInt8_Int256(int[] r, int[] a, int[] b, int[] c, boolean [] mask) { + testInt8Kernel(IntVector.SPECIES_256, r, a, b, c, mask); + } + @Test + @IR(applyIf = {"UseAVX", "3"}, counts = {"MacroLogicV", " > 0 "}) + public void testInt8_Int512(int[] r, int[] a, int[] b, int[] c, boolean [] mask) { + testInt8Kernel(IntVector.SPECIES_512, r, a, b, c, mask); + } + + public void verifyInt8(int[] r, int[] a, int[] b, int[] c, boolean [] mask) { + for (int i = 0; i < r.length; i++) { + int expected = intFunc8(a[i], b[i], c[i], mask[i]); + if (r[i] != expected) { + throw new AssertionError(String.format("testInt8: at #%d: r=%d, expected = %d = intFunc8(%d,%d,%d,%b)", + i, r[i], expected, a[i], b[i], c[i], mask[i])); + } + } + } + + + // ===================================================== // + + static long longFunc(long a, long b, long c) { + long v1 = (a & b) ^ (a & c) ^ (b & c); + long v2 = (~a & b) | (~b & c) | (~c & a); + return v1 & v2; + } + + @ForceInline + public void testLongKernel(VectorSpecies SPECIES, long[] r, long[] a, long[] b, long[] c) { + for (int i = 0; i < SPECIES.loopBound(r.length); i += SPECIES.length()) { + LongVector va = LongVector.fromArray(SPECIES, a, i); + LongVector vb = LongVector.fromArray(SPECIES, b, i); + LongVector vc = LongVector.fromArray(SPECIES, c, i); + + va.lanewise(VectorOperators.AND, vb) + .lanewise(VectorOperators.XOR, va.lanewise(VectorOperators.AND, vc)) + .lanewise(VectorOperators.XOR, vb.lanewise(VectorOperators.AND, vc)) + .lanewise(VectorOperators.AND, + va.lanewise(VectorOperators.NOT).lanewise(VectorOperators.AND, vb) + .lanewise(VectorOperators.OR, vb.lanewise(VectorOperators.NOT).lanewise(VectorOperators.AND, vc)) + .lanewise(VectorOperators.OR, vc.lanewise(VectorOperators.NOT).lanewise(VectorOperators.AND, va))) + .intoArray(r, i); + } + } + + @Test + @IR(applyIf = {"UseAVX", "3"}, counts = {"MacroLogicV", " > 0 "}) + public void testLong_Long256(long[] r, long[] a, long[] b, long[] c) { + testLongKernel(LongVector.SPECIES_256, r, a, b, c); + } + @Test + @IR(applyIf = {"UseAVX", "3"}, counts = {"MacroLogicV", " > 0 "}) + public void testLong_Long512(long[] r, long[] a, long[] b, long[] c) { + testLongKernel(LongVector.SPECIES_512, r, a, b, c); + } + + public void verifyLong(long[] r, long[] a, long[] b, long[] c) { + for (int i = 0; i < r.length; i++) { + long expected = longFunc(a[i], b[i], c[i]); + if (r[i] != expected) { + throw new AssertionError( + String.format("testLong: at #%d: r=%d, expected = %d = longFunc(%d,%d,%d)", + i, r[i], expected, a[i], b[i], c[i])); + } + } + } + + // ===================================================== // + + private static final Random R = Utils.getRandomInstance(); + + static boolean[] fillBooleanRandom(Callable factory) { + try { + boolean[] arr = factory.call(); + for (int i = 0; i < arr.length; i++) { + arr[i] = R.nextBoolean(); + } + return arr; + } catch (Exception e) { + throw new InternalError(e); + } + } + static char[] fillCharRandom(Callable factory) { + try { + char[] arr = factory.call(); + for (int i = 0; i < arr.length; i++) { + arr[i] = (char)R.nextInt(); + } + return arr; + } catch (Exception e) { + throw new InternalError(e); + } + } + static int[] fillIntRandom(Callable factory) { + try { + int[] arr = factory.call(); + for (int i = 0; i < arr.length; i++) { + arr[i] = R.nextInt(); + } + return arr; + } catch (Exception e) { + throw new InternalError(e); + } + } + static long[] fillLongRandom(Callable factory) { + try { + long[] arr = factory.call(); + for (int i = 0; i < arr.length; i++) { + arr[i] = R.nextLong(); + } + return arr; + } catch (Exception e) { + throw new InternalError(e); + } + } + + // ===================================================== // + + static final int SIZE = 512; + + @Run(test = {"testInt4_Int128"}, mode = RunMode.STANDALONE) + public void kernel_testInt4_Int128() { + for (int i = 0; i < 10000; i++) { + testInt4_Int128(r, a, b, c, mask); + verifyInt4(r, a, b, c, mask); + } + } + @Run(test = {"testInt4_Int256"}, mode = RunMode.STANDALONE) + public void kernel_testInt4_Int256() { + for (int i = 0; i < 10000; i++) { + testInt4_Int256(r, a, b, c, mask); + verifyInt4(r, a, b, c, mask); + } + } + @Run(test = {"testInt4_Int512"}, mode = RunMode.STANDALONE) + public void kernel_testInt4_Int512() { + for (int i = 0; i < 10000; i++) { + testInt4_Int512(r, a, b, c, mask); + verifyInt4(r, a, b, c, mask); + } + } + + @Run(test = {"testSubWordBoolean"}, mode = RunMode.STANDALONE) + public void kernel_test_SubWordBoolean() { + for (int i = 0; i < 10000; i++) { + testSubWordBoolean(br, ba, bb); + verifySubWordBoolean(br, ba, bb); + } + } + + @Run(test = {"testSubWordChar"}, mode = RunMode.STANDALONE) + public void kernel_test_SubWordChar() { + for (int i = 0; i < 10000; i++) { + testSubWordChar(sr, ca, cb); + verifySubWordChar(sr, ca, cb); + } + } + + @Run(test = {"testInt1_Int128"}, mode = RunMode.STANDALONE) + public void kernel_testInt1_Int128() { + for (int i = 0; i < 10000; i++) { + testInt1_Int128(r, a, b, c); + verifyInt1(r, a, b, c); + } + } + @Run(test = {"testInt1_Int256"}, mode = RunMode.STANDALONE) + public void kernel_testInt1_Int256() { + for (int i = 0; i < 10000; i++) { + testInt1_Int256(r, a, b, c); + verifyInt1(r, a, b, c); + } + } + @Run(test = {"testInt1_Int512"}, mode = RunMode.STANDALONE) + public void kernel_testInt1_Int512() { + for (int i = 0; i < 10000; i++) { + testInt1_Int512(r, a, b, c); + verifyInt1(r, a, b, c); + } + } + + @Run(test = {"testInt2_Int128"}, mode = RunMode.STANDALONE) + public void kernel_testInt2_Int128() { + for (int i = 0; i < 10000; i++) { + testInt2_Int128(r, a, b, c, mask); + verifyInt2(r, a, b, c, mask); + } + } + @Run(test = {"testInt2_Int256"}, mode = RunMode.STANDALONE) + public void kernel_testInt2_Int256() { + for (int i = 0; i < 10000; i++) { + testInt2_Int256(r, a, b, c, mask); + verifyInt2(r, a, b, c, mask); + } + } + @Run(test = {"testInt2_Int512"}, mode = RunMode.STANDALONE) + public void kernel_testInt2_Int512() { + for (int i = 0; i < 10000; i++) { + testInt2_Int512(r, a, b, c, mask); + verifyInt2(r, a, b, c, mask); + } + } + + @Run(test = {"testInt3_Int128"}, mode = RunMode.STANDALONE) + public void kernel_testInt3_Int128() { + for (int i = 0; i < 10000; i++) { + testInt3_Int128(r, a, b, c, mask); + verifyInt3(r, a, b, c, mask); + } + } + @Run(test = {"testInt3_Int256"}, mode = RunMode.STANDALONE) + public void kernel_testInt3_Int256() { + for (int i = 0; i < 10000; i++) { + testInt3_Int256(r, a, b, c, mask); + verifyInt3(r, a, b, c, mask); + } + } + @Run(test = {"testInt3_Int512"}, mode = RunMode.STANDALONE) + public void kernel_testInt3_Int512() { + for (int i = 0; i < 10000; i++) { + testInt3_Int512(r, a, b, c, mask); + verifyInt3(r, a, b, c, mask); + } + } + + @Run(test = {"testInt5_Int128"}, mode = RunMode.STANDALONE) + public void kernel_testInt5_128() { + for (int i = 0; i < 10000; i++) { + testInt5_Int128(r, a, b, c, mask); + verifyInt5(r, a, b, c, mask); + } + } + @Run(test = {"testInt5_Int256"}, mode = RunMode.STANDALONE) + public void kernel_testInt5_256() { + for (int i = 0; i < 10000; i++) { + testInt5_Int256(r, a, b, c, mask); + verifyInt5(r, a, b, c, mask); + } + } + @Run(test = {"testInt5_Int512"}, mode = RunMode.STANDALONE) + public void kernel_testInt5_Int512() { + for (int i = 0; i < 10000; i++) { + testInt5_Int512(r, a, b, c, mask); + verifyInt5(r, a, b, c, mask); + } + } + + @Run(test = {"testInt6_Int128"}, mode = RunMode.STANDALONE) + public void kernel_testInt6_Int128() { + for (int i = 0; i < 10000; i++) { + testInt6_Int128(r, a, b, c, mask); + verifyInt6(r, a, b, c, mask); + } + } + @Run(test = {"testInt6_Int256"}, mode = RunMode.STANDALONE) + public void kernel_testInt6_Int256() { + for (int i = 0; i < 10000; i++) { + testInt6_Int256(r, a, b, c, mask); + verifyInt6(r, a, b, c, mask); + } + } + @Run(test = {"testInt6_Int512"}, mode = RunMode.STANDALONE) + public void kernel_testInt6_Int512() { + for (int i = 0; i < 10000; i++) { + testInt6_Int512(r, a, b, c, mask); + verifyInt6(r, a, b, c, mask); + } + } + + @Run(test = {"testInt7_Int128"}, mode = RunMode.STANDALONE) + public void kernel_testInt7_Int128() { + for (int i = 0; i < 10000; i++) { + testInt7_Int128(r, a, b, c, mask); + verifyInt7(r, a, b, c, mask); + } + } + @Run(test = {"testInt7_Int256"}, mode = RunMode.STANDALONE) + public void kernel_testInt7_Int256() { + for (int i = 0; i < 10000; i++) { + testInt7_Int256(r, a, b, c, mask); + verifyInt7(r, a, b, c, mask); + } + } + @Run(test = {"testInt7_Int512"}, mode = RunMode.STANDALONE) + public void kernel_testInt7_Int512() { + for (int i = 0; i < 10000; i++) { + testInt7_Int512(r, a, b, c, mask); + verifyInt7(r, a, b, c, mask); + } + } + + @Run(test = {"testInt8_Int128"}, mode = RunMode.STANDALONE) + public void kernel_testInt8_Int128() { + for (int i = 0; i < 10000; i++) { + testInt8_Int128(r, a, b, c, mask); + verifyInt8(r, a, b, c, mask); + } + } + @Run(test = {"testInt8_Int256"}, mode = RunMode.STANDALONE) + public void kernel_testInt8_Int256() { + for (int i = 0; i < 10000; i++) { + testInt8_Int256(r, a, b, c, mask); + verifyInt8(r, a, b, c, mask); + } + } + @Run(test = {"testInt8_Int512"}, mode = RunMode.STANDALONE) + public void kernel_testInt8_Int512() { + for (int i = 0; i < 10000; i++) { + testInt8_Int512(r, a, b, c, mask); + verifyInt8(r, a, b, c, mask); + } + } + + @Run(test = {"testLong_Long256"}, mode = RunMode.STANDALONE) + public void kernel_testLong_Long256() { + for (int i = 0; i < 10000; i++) { + testLong_Long256(rl, al, bl, cl); + verifyLong(rl, al, bl, cl); + } + } + @Run(test = {"testLong_Long512"}, mode = RunMode.STANDALONE) + public void kernel_testLong_Long512() { + for (int i = 0; i < 10000; i++) { + testLong_Long512(rl, al, bl, cl); + verifyLong(rl, al, bl, cl); + } + } + + public TestMaskedMacroLogicVector() { + br = new boolean[SIZE]; + ba = fillBooleanRandom((()-> new boolean[SIZE])); + bb = fillBooleanRandom((()-> new boolean[SIZE])); + + sr = new short[SIZE]; + ca = fillCharRandom((()-> new char[SIZE])); + cb = fillCharRandom((()-> new char[SIZE])); + + r = new int[SIZE]; + a = fillIntRandom(()-> new int[SIZE]); + b = fillIntRandom(()-> new int[SIZE]); + c = fillIntRandom(()-> new int[SIZE]); + d = fillIntRandom(()-> new int[SIZE]); + e = fillIntRandom(()-> new int[SIZE]); + f = fillIntRandom(()-> new int[SIZE]); + + rl = new long[SIZE]; + al = fillLongRandom(() -> new long[SIZE]); + bl = fillLongRandom(() -> new long[SIZE]); + cl = fillLongRandom(() -> new long[SIZE]); + + mask = fillBooleanRandom((()-> new boolean[SIZE])); + } + + public static void main(String[] args) { + TestFramework.runWithFlags("-XX:-TieredCompilation", + "-XX:UseAVX=3", + "--add-modules=jdk.incubator.vector", + "-XX:CompileThresholdScaling=0.3"); + } +} diff --git a/test/micro/org/openjdk/bench/jdk/incubator/vector/MaskedLogicOpts.java b/test/micro/org/openjdk/bench/jdk/incubator/vector/MaskedLogicOpts.java new file mode 100644 index 00000000000..97bfc526808 --- /dev/null +++ b/test/micro/org/openjdk/bench/jdk/incubator/vector/MaskedLogicOpts.java @@ -0,0 +1,331 @@ +/* + * Copyright (c) 2022, 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.jdk.incubator.vector; + +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.infra.*; + +import jdk.incubator.vector.*; +import java.util.concurrent.TimeUnit; +import java.util.Random; + +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Thread) +public class MaskedLogicOpts { + @Param({"256","512","1024"}) + private int ARRAYLEN; + + boolean [] mask_arr = { + false, false, false, true, false, false, false, false, + false, false, false, true, false, false, false, false, + false, false, false, true, false, false, false, false, + true, true, true, true, true, true, true, true, + true, true, true, true, true, true, true, true, + false, false, false, true, false, false, false, false, + false, false, false, true, false, false, false, false, + false, false, false, true, false, false, false, false + }; + + int INVOC_COUNTER = 4096; + + int [] i1 = new int[ARRAYLEN]; + int [] i2 = new int[ARRAYLEN]; + int [] i3 = new int[ARRAYLEN]; + int [] i4 = new int[ARRAYLEN]; + int [] i5 = new int[ARRAYLEN]; + + long [] l1 = new long[ARRAYLEN]; + long [] l2 = new long[ARRAYLEN]; + long [] l3 = new long[ARRAYLEN]; + long [] l4 = new long[ARRAYLEN]; + long [] l5 = new long[ARRAYLEN]; + + Vector iv1; + Vector iv2; + Vector iv3; + Vector iv4; + Vector iv5; + + Vector lv1; + Vector lv2; + Vector lv3; + Vector lv4; + Vector lv5; + + VectorMask imask; + VectorMask lmask; + + VectorSpecies ispecies; + VectorSpecies lspecies; + + int int512_arr_idx; + int int256_arr_idx; + int int128_arr_idx; + int long256_arr_idx; + int long512_arr_idx; + + private Random r = new Random(); + + @Setup(Level.Trial) + public void init() { + int512_arr_idx = 0; + int256_arr_idx = 0; + int128_arr_idx = 0; + long256_arr_idx = 0; + long512_arr_idx = 0; + i1 = new int[ARRAYLEN]; + i2 = new int[ARRAYLEN]; + i3 = new int[ARRAYLEN]; + i4 = new int[ARRAYLEN]; + i5 = new int[ARRAYLEN]; + + l1 = new long[ARRAYLEN]; + l2 = new long[ARRAYLEN]; + l3 = new long[ARRAYLEN]; + l4 = new long[ARRAYLEN]; + l5 = new long[ARRAYLEN]; + + for (int i=0; i SPECIES) { + imask = VectorMask.fromArray(SPECIES, mask_arr, 0); + iv2 = IntVector.fromArray(SPECIES, i2, int512_arr_idx); + iv3 = IntVector.fromArray(SPECIES, i3, int512_arr_idx); + iv4 = IntVector.fromArray(SPECIES, i4, int512_arr_idx); + iv5 = IntVector.fromArray(SPECIES, i5, int512_arr_idx); + for(int i = 0; i < INVOC_COUNTER; i++) { + for(int j = 0 ; j < ARRAYLEN; j+= SPECIES.length()) { + IntVector.fromArray(SPECIES, i1, j) + .lanewise(VectorOperators.AND, iv2, imask) + .lanewise(VectorOperators.OR, iv2, imask) + .lanewise(VectorOperators.AND, iv3, imask) + .lanewise(VectorOperators.OR, iv3, imask) + .lanewise(VectorOperators.AND, iv4, imask) + .lanewise(VectorOperators.OR, iv4, imask) + .lanewise(VectorOperators.AND, iv5, imask) + .lanewise(VectorOperators.XOR, iv5, imask) + .intoArray(i1, j); + } + } + } + + @Benchmark + public void maskedLogicOperationsInt512() { + maskedLogicKernel(IntVector.SPECIES_512); + } + + @Benchmark + public void maskedLogicOperationsInt256() { + maskedLogicKernel(IntVector.SPECIES_256); + } + + @Benchmark + public void maskedLogicOperationsInt128() { + maskedLogicKernel(IntVector.SPECIES_128); + } + + @CompilerControl(CompilerControl.Mode.INLINE) + public void partiallyMaskedLogicOperationsIntKernel(VectorSpecies SPECIES) { + imask = VectorMask.fromArray(SPECIES, mask_arr, 0); + iv2 = IntVector.fromArray(SPECIES, i2, int512_arr_idx); + iv3 = IntVector.fromArray(SPECIES, i3, int512_arr_idx); + iv4 = IntVector.fromArray(SPECIES, i4, int512_arr_idx); + iv5 = IntVector.fromArray(SPECIES, i5, int512_arr_idx); + for(int i = 0; i < INVOC_COUNTER; i++) { + for(int j = 0 ; j < ARRAYLEN; j+= SPECIES.length()) { + IntVector.fromArray(SPECIES, i1, j) + .lanewise(VectorOperators.AND, iv2, imask) + .lanewise(VectorOperators.OR, iv2, imask) + .lanewise(VectorOperators.AND, iv3) + .lanewise(VectorOperators.OR, iv3) + .lanewise(VectorOperators.OR, iv4, imask) + .lanewise(VectorOperators.AND, iv4, imask) + .lanewise(VectorOperators.XOR, iv5, imask) + .intoArray(i1, j); + } + } + } + + @Benchmark + public void partiallyMaskedLogicOperationsInt512() { + partiallyMaskedLogicOperationsIntKernel(IntVector.SPECIES_512); + } + + @Benchmark + public void partiallyMaskedLogicOperationsInt256() { + partiallyMaskedLogicOperationsIntKernel(IntVector.SPECIES_256); + } + + @Benchmark + public void partiallyMaskedLogicOperationsInt128() { + partiallyMaskedLogicOperationsIntKernel(IntVector.SPECIES_128); + } + + @CompilerControl(CompilerControl.Mode.INLINE) + public void bitwiseBlendOperationIntKernel(VectorSpecies SPECIES) { + imask = VectorMask.fromArray(SPECIES, mask_arr, 0); + iv2 = IntVector.fromArray(SPECIES, i2, int512_arr_idx); + iv3 = IntVector.fromArray(SPECIES, i3, int512_arr_idx); + iv4 = IntVector.fromArray(SPECIES, i4, int512_arr_idx); + iv5 = IntVector.fromArray(SPECIES, i5, int512_arr_idx); + for(int i = 0; i < INVOC_COUNTER; i++) { + for(int j = 0 ; j < ARRAYLEN; j+= SPECIES.length()) { + IntVector.fromArray(SPECIES, i1, j) + .lanewise(VectorOperators.BITWISE_BLEND, iv2, iv3, imask) + .lanewise(VectorOperators.BITWISE_BLEND, iv3, iv4, imask) + .lanewise(VectorOperators.BITWISE_BLEND, iv4, iv5, imask) + .intoArray(i1, j); + } + } + } + + @Benchmark + public void bitwiseBlendOperationInt512() { + bitwiseBlendOperationIntKernel(IntVector.SPECIES_512); + } + + @Benchmark + public void bitwiseBlendOperationInt256() { + bitwiseBlendOperationIntKernel(IntVector.SPECIES_256); + } + + @Benchmark + public void bitwiseBlendOperationInt128() { + bitwiseBlendOperationIntKernel(IntVector.SPECIES_128); + } + + @CompilerControl(CompilerControl.Mode.INLINE) + public void maskedLogicOperationsLongKernel(VectorSpecies SPECIES) { + lmask = VectorMask.fromArray(SPECIES, mask_arr, 0); + lv2 = LongVector.fromArray(SPECIES, l2, long256_arr_idx); + lv3 = LongVector.fromArray(SPECIES, l3, long256_arr_idx); + lv4 = LongVector.fromArray(SPECIES, l4, long256_arr_idx); + lv5 = LongVector.fromArray(SPECIES, l5, long256_arr_idx); + for(int i = 0; i < INVOC_COUNTER; i++) { + for(int j = 0 ; j < ARRAYLEN; j+= SPECIES.length()) { + LongVector.fromArray(SPECIES, l1, j) + .lanewise(VectorOperators.AND, lv2, lmask) + .lanewise(VectorOperators.OR, lv3, lmask) + .lanewise(VectorOperators.AND, lv3, lmask) + .lanewise(VectorOperators.OR, lv4, lmask) + .lanewise(VectorOperators.AND, lv4, lmask) + .lanewise(VectorOperators.XOR, lv5, lmask) + .intoArray(l1, j); + } + } + } + + @Benchmark + public void maskedLogicOperationsLong512() { + maskedLogicOperationsLongKernel(LongVector.SPECIES_512); + } + @Benchmark + public void maskedLogicOperationsLong256() { + maskedLogicOperationsLongKernel(LongVector.SPECIES_256); + } + + @CompilerControl(CompilerControl.Mode.INLINE) + public void partiallyMaskedLogicOperationsLongKernel(VectorSpecies SPECIES) { + lmask = VectorMask.fromArray(SPECIES, mask_arr, 0); + lv2 = LongVector.fromArray(SPECIES, l2, long512_arr_idx); + lv3 = LongVector.fromArray(SPECIES, l3, long512_arr_idx); + lv4 = LongVector.fromArray(SPECIES, l4, long512_arr_idx); + lv5 = LongVector.fromArray(SPECIES, l5, long512_arr_idx); + for(int i = 0; i < INVOC_COUNTER; i++) { + for(int j = 0 ; j < ARRAYLEN; j+= SPECIES.length()) { + LongVector.fromArray(SPECIES, l1, j) + .lanewise(VectorOperators.AND, lv2, lmask) + .lanewise(VectorOperators.OR, lv2, lmask) + .lanewise(VectorOperators.AND, lv3) + .lanewise(VectorOperators.OR, lv3) + .lanewise(VectorOperators.AND, lv4) + .lanewise(VectorOperators.OR, lv4, lmask) + .lanewise(VectorOperators.XOR, lv5, lmask) + .intoArray(l1, j); + } + } + } + + @Benchmark + public void partiallyMaskedLogicOperationsLong512() { + partiallyMaskedLogicOperationsLongKernel(LongVector.SPECIES_512); + } + + @Benchmark + public void partiallyMaskedLogicOperationsLong256() { + partiallyMaskedLogicOperationsLongKernel(LongVector.SPECIES_256); + } + + @CompilerControl(CompilerControl.Mode.INLINE) + public void bitwiseBlendOperationLongKernel(VectorSpecies SPECIES) { + lmask = VectorMask.fromArray(SPECIES, mask_arr, 0); + lv2 = LongVector.fromArray(SPECIES, l2, long512_arr_idx); + lv3 = LongVector.fromArray(SPECIES, l3, long512_arr_idx); + lv4 = LongVector.fromArray(SPECIES, l4, long512_arr_idx); + lv5 = LongVector.fromArray(SPECIES, l5, long512_arr_idx); + for(int i = 0; i < INVOC_COUNTER; i++) { + for(int j = 0 ; j < ARRAYLEN; j+= SPECIES.length()) { + LongVector.fromArray(SPECIES, l1, j) + .lanewise(VectorOperators.BITWISE_BLEND, lv2, lv3, lmask) + .lanewise(VectorOperators.BITWISE_BLEND, lv3, lv4, lmask) + .lanewise(VectorOperators.BITWISE_BLEND, lv4, lv5, lmask) + .intoArray(l1, j); + } + } + } + + @Benchmark + public void bitwiseBlendOperationLong512() { + bitwiseBlendOperationLongKernel(LongVector.SPECIES_512); + } + + @Benchmark + public void bitwiseBlendOperationLong256() { + bitwiseBlendOperationLongKernel(LongVector.SPECIES_256); + } +} diff --git a/test/micro/org/openjdk/bench/vm/compiler/MacroLogicOpt.java b/test/micro/org/openjdk/bench/vm/compiler/MacroLogicOpt.java index 58400cadf68..40c3ba1b2ba 100644 --- a/test/micro/org/openjdk/bench/vm/compiler/MacroLogicOpt.java +++ b/test/micro/org/openjdk/bench/vm/compiler/MacroLogicOpt.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,7 @@ import java.util.Random; @OutputTimeUnit(TimeUnit.SECONDS) @State(Scope.Thread) public class MacroLogicOpt { - @Param({"64","128","256","512","1024","2048","4096"}) private int VECLEN; + @Param({"64","128","256","512","1024"}) private int VECLEN; private int [] ai = new int[VECLEN]; private int [] bi = new int[VECLEN]; -- GitLab From b3dbfc645283cb315016ec531ec41570ab3f75f1 Mon Sep 17 00:00:00 2001 From: Phil Race Date: Thu, 6 Jan 2022 19:06:33 +0000 Subject: [PATCH 020/564] 4884570: StreamPrintService.isAttributeValueSupported does not work properly for SheetCollate Reviewed-by: serb --- .../sun/print/PSStreamPrintService.java | 14 ++- .../attribute/StreamServiceAttributeTest.java | 94 +++++++++++++++++++ 2 files changed, 106 insertions(+), 2 deletions(-) create mode 100644 test/jdk/javax/print/attribute/StreamServiceAttributeTest.java diff --git a/src/java.desktop/share/classes/sun/print/PSStreamPrintService.java b/src/java.desktop/share/classes/sun/print/PSStreamPrintService.java index 62a28e05052..e1594e051f5 100644 --- a/src/java.desktop/share/classes/sun/print/PSStreamPrintService.java +++ b/src/java.desktop/share/classes/sun/print/PSStreamPrintService.java @@ -427,7 +427,17 @@ public class PSStreamPrintService extends StreamPrintService if (attr == OrientationRequested.REVERSE_PORTRAIT || (flavor != null) && !(flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) || - flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE))) { + flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE) || + flavor.equals(DocFlavor.INPUT_STREAM.GIF) || + flavor.equals(DocFlavor.INPUT_STREAM.JPEG) || + flavor.equals(DocFlavor.INPUT_STREAM.PNG) || + flavor.equals(DocFlavor.BYTE_ARRAY.GIF) || + flavor.equals(DocFlavor.BYTE_ARRAY.JPEG) || + flavor.equals(DocFlavor.BYTE_ARRAY.PNG) || + flavor.equals(DocFlavor.URL.GIF) || + flavor.equals(DocFlavor.URL.JPEG) || + flavor.equals(DocFlavor.URL.PNG))) + { return false; } } else if (attr.getCategory() == PageRanges.class) { @@ -440,7 +450,7 @@ public class PSStreamPrintService extends StreamPrintService if (flavor != null && !(flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) || flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE))) { - return false; + return attr == SheetCollate.UNCOLLATED; } } else if (attr.getCategory() == Sides.class) { if (flavor != null && diff --git a/test/jdk/javax/print/attribute/StreamServiceAttributeTest.java b/test/jdk/javax/print/attribute/StreamServiceAttributeTest.java new file mode 100644 index 00000000000..093bbfd747c --- /dev/null +++ b/test/jdk/javax/print/attribute/StreamServiceAttributeTest.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2022, 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 4884570 + * @summary Attribute support reporting should be consistent +*/ + +import java.io.ByteArrayOutputStream; +import java.io.OutputStream; + +import javax.print.DocFlavor; +import javax.print.StreamPrintService; +import javax.print.StreamPrintServiceFactory; +import javax.print.attribute.Attribute; +import javax.print.attribute.standard.Chromaticity; +import javax.print.attribute.standard.Media; +import javax.print.attribute.standard.OrientationRequested; +import javax.print.attribute.standard.SheetCollate; +import javax.print.attribute.standard.Sides; + +public class StreamServiceAttributeTest { + + private static boolean allSupported = true; + private static Class[] attrClasses = { + Chromaticity.class, + Media.class, + OrientationRequested.class, + SheetCollate.class, + Sides.class, + }; + + public static void main(String args[]) { + + StreamPrintServiceFactory[] fact = + StreamPrintServiceFactory.lookupStreamPrintServiceFactories( + null, null); + + if (fact.length == 0) { + return; + } + OutputStream out = new ByteArrayOutputStream(); + StreamPrintService sps = fact[0].getPrintService(out); + for (Class ac : attrClasses) { + test(sps, ac); + } + + if (!allSupported) { + throw new RuntimeException("Inconsistent support reported"); + } + } + + private static void test(StreamPrintService sps, + Class ac) { + if (!sps.isAttributeCategorySupported(ac)) { + return; + } + DocFlavor[] dfs = sps.getSupportedDocFlavors(); + for (DocFlavor f : dfs) { + Attribute[] attrs = (Attribute[]) + sps.getSupportedAttributeValues(ac, f, null); + if (attrs == null) { + continue; + } + for (Attribute a : attrs) { + if (!sps.isAttributeValueSupported(a, f, null)) { + allSupported = false; + System.out.println("Unsupported : " + f + " " + a); + } + } + } + } +} -- GitLab From 8d0f385fd0243c3e38b400f463b8d9727b0a5956 Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Thu, 6 Jan 2022 22:02:55 +0000 Subject: [PATCH 021/564] 8279520: SPNEGO has not passed channel binding info into the underlying mechanism Reviewed-by: mullan, valeriep --- .../security/jgss/spnego/SpNegoContext.java | 4 ++- .../krb5/auto/IgnoreChannelBinding.java | 30 +++++++++++-------- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/java.security.jgss/share/classes/sun/security/jgss/spnego/SpNegoContext.java b/src/java.security.jgss/share/classes/sun/security/jgss/spnego/SpNegoContext.java index 311dfadbdd7..61a5d34186d 100644 --- a/src/java.security.jgss/share/classes/sun/security/jgss/spnego/SpNegoContext.java +++ b/src/java.security.jgss/share/classes/sun/security/jgss/spnego/SpNegoContext.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2021, 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 @@ -866,6 +866,7 @@ public class SpNegoContext implements GSSContextSpi { mechContext.requestMutualAuth(mutualAuthState); mechContext.requestReplayDet(replayDetState); mechContext.requestSequenceDet(sequenceDetState); + mechContext.setChannelBinding(channelBinding); if (mechContext instanceof GSSContextImpl) { ((GSSContextImpl)mechContext).requestDelegPolicy( delegPolicyState); @@ -899,6 +900,7 @@ public class SpNegoContext implements GSSContextSpi { myCred.getInternalCred()); } mechContext = factory.manager.createContext(cred); + mechContext.setChannelBinding(channelBinding); } // pass token to mechanism acceptSecContext diff --git a/test/jdk/sun/security/krb5/auto/IgnoreChannelBinding.java b/test/jdk/sun/security/krb5/auto/IgnoreChannelBinding.java index a9760dae9ad..a393c299b70 100644 --- a/test/jdk/sun/security/krb5/auto/IgnoreChannelBinding.java +++ b/test/jdk/sun/security/krb5/auto/IgnoreChannelBinding.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2021, 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 6851973 8194486 + * @bug 6851973 8194486 8279520 * @summary ignore incoming channel binding if acceptor does not set one * @library /test/lib * @run main jdk.test.lib.FileInstaller TestHosts TestHosts @@ -33,6 +33,7 @@ import java.net.InetAddress; import org.ietf.jgss.ChannelBinding; import org.ietf.jgss.GSSException; +import org.ietf.jgss.Oid; import sun.security.jgss.GSSUtil; public class IgnoreChannelBinding { @@ -41,33 +42,38 @@ public class IgnoreChannelBinding { throws Exception { new OneKDC(null).writeJAASConf(); + test(GSSUtil.GSS_KRB5_MECH_OID); + test(GSSUtil.GSS_SPNEGO_MECH_OID); + } + + static void test(Oid mech) throws Exception { Context c = Context.fromJAAS("client"); Context s = Context.fromJAAS("server"); // All silent - c.startAsClient(OneKDC.SERVER, GSSUtil.GSS_KRB5_MECH_OID); - s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID); + c.startAsClient(OneKDC.SERVER, mech); + s.startAsServer(mech); Context.handshake(c, s); // Initiator req, acceptor ignore - c.startAsClient(OneKDC.SERVER, GSSUtil.GSS_KRB5_MECH_OID); + c.startAsClient(OneKDC.SERVER, mech); c.x().setChannelBinding(new ChannelBinding( InetAddress.getByName("client.rabbit.hole"), InetAddress.getByName("host.rabbit.hole"), new byte[0] )); - s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID); + s.startAsServer(mech); Context.handshake(c, s); // Both req, and match - c.startAsClient(OneKDC.SERVER, GSSUtil.GSS_KRB5_MECH_OID); + c.startAsClient(OneKDC.SERVER, mech); c.x().setChannelBinding(new ChannelBinding( InetAddress.getByName("client.rabbit.hole"), InetAddress.getByName("host.rabbit.hole"), new byte[0] )); - s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID); + s.startAsServer(mech); s.x().setChannelBinding(new ChannelBinding( InetAddress.getByName("client.rabbit.hole"), InetAddress.getByName("host.rabbit.hole"), @@ -76,13 +82,13 @@ public class IgnoreChannelBinding { Context.handshake(c, s); // Both req, NOT match - c.startAsClient(OneKDC.SERVER, GSSUtil.GSS_KRB5_MECH_OID); + c.startAsClient(OneKDC.SERVER, mech); c.x().setChannelBinding(new ChannelBinding( InetAddress.getByName("client.rabbit.hole"), InetAddress.getByName("host.rabbit.hole"), new byte[0] )); - s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID); + s.startAsServer(mech); s.x().setChannelBinding(new ChannelBinding( InetAddress.getByName("client.rabbit.hole"), InetAddress.getByName("host.rabbit.hole"), @@ -96,8 +102,8 @@ public class IgnoreChannelBinding { } // Acceptor req, reject - c.startAsClient(OneKDC.SERVER, GSSUtil.GSS_KRB5_MECH_OID); - s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID); + c.startAsClient(OneKDC.SERVER, mech); + s.startAsServer(mech); s.x().setChannelBinding(new ChannelBinding( InetAddress.getByName("client.rabbit.hole"), InetAddress.getByName("host.rabbit.hole"), -- GitLab From 6a42fbaf9b87c69e72fd1a8053431c3f24e8875e Mon Sep 17 00:00:00 2001 From: Jie Fu Date: Fri, 7 Jan 2022 00:04:51 +0000 Subject: [PATCH 022/564] 8279258: Auto-vectorization enhancement for two-dimensional array operations Reviewed-by: neliasso, kvn --- src/hotspot/share/opto/loopTransform.cpp | 28 +++- src/hotspot/share/opto/loopnode.hpp | 9 +- .../irTests/TestAutoVectorization2DArray.java | 63 +++++++++ .../compiler/lib/ir_framework/IRNode.java | 3 + .../vm/compiler/AutoVectorization2DArray.java | 123 ++++++++++++++++++ 5 files changed, 218 insertions(+), 8 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/c2/irTests/TestAutoVectorization2DArray.java create mode 100644 test/micro/org/openjdk/bench/vm/compiler/AutoVectorization2DArray.java diff --git a/src/hotspot/share/opto/loopTransform.cpp b/src/hotspot/share/opto/loopTransform.cpp index 30562826eac..7663ce82c0d 100644 --- a/src/hotspot/share/opto/loopTransform.cpp +++ b/src/hotspot/share/opto/loopTransform.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2022, 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 @@ -899,15 +899,27 @@ bool IdealLoopTree::policy_unroll(PhaseIdealLoop *phase) { return false; } + bool should_unroll = true; + // When unroll count is greater than LoopUnrollMin, don't unroll if: // the residual iterations are more than 10% of the trip count // and rounds of "unroll,optimize" are not making significant progress // Progress defined as current size less than 20% larger than previous size. if (UseSuperWord && cl->node_count_before_unroll() > 0 && future_unroll_cnt > LoopUnrollMin && - (future_unroll_cnt - 1) * (100.0 / LoopPercentProfileLimit) > cl->profile_trip_cnt() && + is_residual_iters_large(future_unroll_cnt, cl) && 1.2 * cl->node_count_before_unroll() < (double)_body.size()) { - return false; + if ((cl->slp_max_unroll() == 0) && !is_residual_iters_large(cl->unrolled_count(), cl)) { + // cl->slp_max_unroll() = 0 means that the previous slp analysis never passed. + // slp analysis may fail due to the loop IR is too complicated especially during the early stage + // of loop unrolling analysis. But after several rounds of loop unrolling and other optimizations, + // it's possible that the loop IR becomes simple enough to pass the slp analysis. + // So we don't return immediately in hoping that the next slp analysis can succeed. + should_unroll = false; + future_unroll_cnt = cl->unrolled_count(); + } else { + return false; + } } Node *init_n = cl->init_trip(); @@ -985,7 +997,7 @@ bool IdealLoopTree::policy_unroll(PhaseIdealLoop *phase) { } // Only attempt slp analysis when user controls do not prohibit it - if (LoopMaxUnroll > _local_loop_unroll_factor) { + if (!cl->range_checks_present() && (LoopMaxUnroll > _local_loop_unroll_factor)) { // Once policy_slp_analysis succeeds, mark the loop with the // maximal unroll factor so that we minimize analysis passes if (future_unroll_cnt >= _local_loop_unroll_factor) { @@ -1003,7 +1015,7 @@ bool IdealLoopTree::policy_unroll(PhaseIdealLoop *phase) { if (cl->has_passed_slp()) { if (slp_max_unroll_factor >= future_unroll_cnt) { - return phase->may_require_nodes(estimate); + return should_unroll && phase->may_require_nodes(estimate); } return false; // Loop too big. } @@ -1011,7 +1023,7 @@ bool IdealLoopTree::policy_unroll(PhaseIdealLoop *phase) { // Check for being too big if (body_size > (uint)_local_loop_unroll_limit) { if ((cl->is_subword_loop() || xors_in_loop >= 4) && body_size < 4u * LoopUnrollLimit) { - return phase->may_require_nodes(estimate); + return should_unroll && phase->may_require_nodes(estimate); } return false; // Loop too big. } @@ -1024,7 +1036,7 @@ bool IdealLoopTree::policy_unroll(PhaseIdealLoop *phase) { } // Unroll once! (Each trip will soon do double iterations) - return phase->may_require_nodes(estimate); + return should_unroll && phase->may_require_nodes(estimate); } void IdealLoopTree::policy_unroll_slp_analysis(CountedLoopNode *cl, PhaseIdealLoop *phase, int future_unroll_cnt) { @@ -3528,6 +3540,8 @@ bool IdealLoopTree::iteration_split_impl(PhaseIdealLoop *phase, Node_List &old_n if (should_rce) { if (phase->do_range_check(this, old_new) != 0) { cl->mark_has_range_checks(); + } else { + cl->clear_has_range_checks(); } } else if (PostLoopMultiversioning) { phase->has_range_checks(this); diff --git a/src/hotspot/share/opto/loopnode.hpp b/src/hotspot/share/opto/loopnode.hpp index b156ceb95b4..18145a51839 100644 --- a/src/hotspot/share/opto/loopnode.hpp +++ b/src/hotspot/share/opto/loopnode.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2022, 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 @@ -114,6 +114,7 @@ public: void mark_loop_vectorized() { _loop_flags |= VectorizedLoop; } void mark_has_atomic_post_loop() { _loop_flags |= HasAtomicPostLoop; } void mark_has_range_checks() { _loop_flags |= HasRangeChecks; } + void clear_has_range_checks() { _loop_flags &= ~HasRangeChecks; } void mark_is_multiversioned() { _loop_flags |= IsMultiversioned; } void mark_strip_mined() { _loop_flags |= StripMined; } void clear_strip_mined() { _loop_flags &= ~StripMined; } @@ -773,6 +774,12 @@ public: // Estimate the number of nodes resulting from control and data flow merge. uint est_loop_flow_merge_sz() const; + + // Check if the number of residual iterations is large with unroll_cnt. + // Return true if the residual iterations are more than 10% of the trip count. + bool is_residual_iters_large(int unroll_cnt, CountedLoopNode *cl) const { + return (unroll_cnt - 1) * (100.0 / LoopPercentProfileLimit) > cl->profile_trip_cnt(); + } }; // -----------------------------PhaseIdealLoop--------------------------------- diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestAutoVectorization2DArray.java b/test/hotspot/jtreg/compiler/c2/irTests/TestAutoVectorization2DArray.java new file mode 100644 index 00000000000..c79fbf993db --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/irTests/TestAutoVectorization2DArray.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2022 THL A29 Limited, a Tencent company. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package compiler.c2.irTests; + +import compiler.lib.ir_framework.*; + +/* + * @test + * @bug 8279258 + * @summary Auto-vectorization enhancement for two-dimensional array operations + * @library /test/lib / + * @run driver compiler.c2.irTests.TestAutoVectorization2DArray + */ + +public class TestAutoVectorization2DArray { + final private static int NUM = 64; + + private static double[][] a = new double[NUM][NUM]; + private static double[][] b = new double[NUM][NUM]; + private static double[][] c = new double[NUM][NUM]; + + public static void main(String[] args) { + TestFramework.run(); + } + + @Test + @IR(counts = { IRNode.LOAD_VECTOR, " >0 " }) + @IR(counts = { IRNode.ADD_VD, " >0 " }) + @IR(counts = { IRNode.STORE_VECTOR, " >0 " }) + private static void testDouble(double[][] a , double[][] b, double[][] c) { + for(int i = 0; i < a.length; i++) { + for (int j = 0; j < a[0].length; j++) { + a[i][j] = b[i][j] + c[i][j]; + } + } + } + + @Run(test = "testDouble") + private void testDouble_runner() { + testDouble(a, b, c); + } +} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java index 783319445eb..b4737490652 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java @@ -74,6 +74,7 @@ public class IRNode { public static final String STORE_D = START + "StoreD" + MID + END; public static final String STORE_P = START + "StoreP" + MID + END; public static final String STORE_N = START + "StoreN" + MID + END; + public static final String STORE_VECTOR = START + "StoreVector" + MID + END; public static final String STORE_OF_CLASS = COMPOSITE_PREFIX + START + "Store(B|C|S|I|L|F|D|P|N)" + MID + "@\\S*" + IS_REPLACED + STORE_OF_CLASS_POSTFIX; public static final String STORE_B_OF_CLASS = COMPOSITE_PREFIX + START + "StoreB" + MID + "@\\S*" + IS_REPLACED + STORE_OF_CLASS_POSTFIX; public static final String STORE_C_OF_CLASS = COMPOSITE_PREFIX + START + "StoreC" + MID + "@\\S*" + IS_REPLACED + STORE_OF_CLASS_POSTFIX; @@ -96,6 +97,7 @@ public class IRNode { public static final String LOAD_D = START + "LoadD" + MID + END; public static final String LOAD_P = START + "LoadP" + MID + END; public static final String LOAD_N = START + "LoadN" + MID + END; + public static final String LOAD_VECTOR = START + "LoadVector" + MID + END; public static final String LOAD_OF_CLASS = COMPOSITE_PREFIX + START + "Load(B|UB|S|US|I|L|F|D|P|N)" + MID + "@\\S*"+ IS_REPLACED + LOAD_OF_CLASS_POSTFIX; public static final String LOAD_B_OF_CLASS = COMPOSITE_PREFIX + START + "LoadB" + MID + "@\\S*" + IS_REPLACED + LOAD_OF_CLASS_POSTFIX; public static final String LOAD_UB_OF_CLASS = COMPOSITE_PREFIX + START + "LoadUB" + MID + "@\\S*" + IS_REPLACED + LOAD_OF_CLASS_POSTFIX; @@ -139,6 +141,7 @@ public class IRNode { public static final String LSHIFT_L = START + "LShiftL" + MID + END; public static final String ADD_I = START + "AddI" + MID + END; public static final String ADD_L = START + "AddL" + MID + END; + public static final String ADD_VD = START + "AddVD" + MID + END; public static final String SUB_I = START + "SubI" + MID + END; public static final String SUB_L = START + "SubL" + MID + END; public static final String MUL_I = START + "MulI" + MID + END; diff --git a/test/micro/org/openjdk/bench/vm/compiler/AutoVectorization2DArray.java b/test/micro/org/openjdk/bench/vm/compiler/AutoVectorization2DArray.java new file mode 100644 index 00000000000..9155bfbd3de --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/compiler/AutoVectorization2DArray.java @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2022 THL A29 Limited, a Tencent company. 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.*; +import org.openjdk.jmh.infra.*; +import java.util.concurrent.TimeUnit; + +@Warmup(iterations = 3, time = 5, timeUnit = TimeUnit.SECONDS) +@Measurement(iterations = 3, time = 5, timeUnit = TimeUnit.SECONDS) +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Thread) +@Fork(value=1) +public class AutoVectorization2DArray { + @Param({"16", "32", "64"}) + private int LEN; + + private byte[][] a_byte; + private byte[][] b_byte; + private byte[][] c_byte; + + private int[][] a_int; + private int[][] b_int; + private int[][] c_int; + + private double[][] a_double; + private double[][] b_double; + private double[][] c_double; + + @Setup + public void init() { + a_byte = new byte[LEN][LEN]; + b_byte = new byte[LEN][LEN]; + c_byte = new byte[LEN][LEN]; + + a_int = new int[LEN][LEN]; + b_int = new int[LEN][LEN]; + c_int = new int[LEN][LEN]; + + a_double = new double[LEN][LEN]; + b_double = new double[LEN][LEN]; + c_double = new double[LEN][LEN]; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private int run_byte(int count, byte[][] a , byte[][] b, byte[][] c) { + for(int i = 0; i < a.length; i++) { + for (int j = 0; j < a[0].length; j++) { + a[i][j] = (byte)(b[i][j] + c[i][j]); + } + } + return a[count][count]; + } + + @Benchmark + public void test_run_byte(Blackhole bh) { + int r = 0; + for(int i = 0 ; i < 100; i++) { + r += run_byte(i % a_byte.length, a_byte, b_byte, c_byte); + } + bh.consume(r); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private int run_int(int count, int[][] a, int[][] b, int[][] c) { + for(int i = 0; i < a.length; i++) { + for (int j = 0; j < a[0].length; j++) { + a[i][j] = b[i][j] + c[i][j]; + } + } + return a[count][count]; + } + + @Benchmark + public void test_run_int(Blackhole bh) { + int r = 0; + for(int i = 0 ; i < 100; i++) { + r += run_int(i % a_int.length, a_int, b_int, c_int); + } + bh.consume(r); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private double run_double(int count, double[][] a, double[][] b, double[][] c) { + for(int i = 0; i < a.length; i++) { + for (int j = 0; j < a[0].length; j++) { + a[i][j] = b[i][j] + c[i][j]; + } + } + return a[count][count]; + } + + @Benchmark + public void test_run_double(Blackhole bh) { + double r = 0; + for(int i = 0 ; i < 100; i++) { + r += run_double(i % a_double.length, a_double, b_double, c_double); + } + bh.consume(r); + } +} -- GitLab From 62d03c283667c4122130ec9bbeec623e6a2840e5 Mon Sep 17 00:00:00 2001 From: Quan Anh Mai Date: Fri, 7 Jan 2022 03:22:34 +0000 Subject: [PATCH 023/564] 8279547: [vectorapi] Enable vector cast tests after JDK-8278948 Reviewed-by: kvn --- .../vectorapi/reshape/utils/TestCastMethods.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/test/hotspot/jtreg/compiler/vectorapi/reshape/utils/TestCastMethods.java b/test/hotspot/jtreg/compiler/vectorapi/reshape/utils/TestCastMethods.java index d6a4c6cdd19..4bf1c9799f1 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/reshape/utils/TestCastMethods.java +++ b/test/hotspot/jtreg/compiler/vectorapi/reshape/utils/TestCastMethods.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,8 +30,7 @@ import static compiler.vectorapi.reshape.utils.VectorReshapeHelper.*; import static compiler.vectorapi.reshape.utils.VectorSpeciesPair.makePair; /** - * The cast intrinsics implemented on each platform, commented out tests are the ones that are - * supposed to work but currently don't. + * The cast intrinsics implemented on each platform. */ public class TestCastMethods { public static final List AVX1_CAST_TESTS = List.of( @@ -39,7 +38,7 @@ public class TestCastMethods { makePair(BSPEC64, SSPEC128), makePair(BSPEC64, ISPEC128), makePair(BSPEC64, FSPEC128), -// makePair(BSPEC64, DSPEC256), + makePair(BSPEC64, DSPEC256), makePair(SSPEC64, BSPEC64), makePair(SSPEC128, BSPEC64), makePair(SSPEC64, ISPEC64), @@ -48,7 +47,7 @@ public class TestCastMethods { makePair(SSPEC64, FSPEC64), makePair(SSPEC64, FSPEC128), makePair(SSPEC64, DSPEC128), -// makePair(SSPEC64, DSPEC256), + makePair(SSPEC64, DSPEC256), makePair(ISPEC128, BSPEC64), makePair(ISPEC64, SSPEC64), makePair(ISPEC128, SSPEC64), -- GitLab From 967ef0c48252957f9bec42965fe02414fd2c77cb Mon Sep 17 00:00:00 2001 From: Ioi Lam Date: Fri, 7 Jan 2022 05:30:20 +0000 Subject: [PATCH 024/564] 8278020: ~13% variation in Renaissance-Scrabble Backport-of: 4ba980ba439f94a6b5015e64382a6c308476d63f --- src/hotspot/share/oops/klass.hpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/hotspot/share/oops/klass.hpp b/src/hotspot/share/oops/klass.hpp index d72d1c71103..7bbff72e25a 100644 --- a/src/hotspot/share/oops/klass.hpp +++ b/src/hotspot/share/oops/klass.hpp @@ -117,8 +117,8 @@ class Klass : public Metadata { // Klass identifier used to implement devirtualized oop closure dispatching. const KlassID _id; - // vtable length - int _vtable_len; + // Processed access flags, for use by Class.getModifiers. + jint _modifier_flags; // The fields _super_check_offset, _secondary_super_cache, _secondary_supers // and _primary_supers all help make fast subtype checks. See big discussion @@ -154,7 +154,10 @@ class Klass : public Metadata { // Provide access the corresponding instance java.lang.ClassLoader. ClassLoaderData* _class_loader_data; - jint _modifier_flags; // Processed access flags, for use by Class.getModifiers. + int _vtable_len; // vtable length. This field may be read very often when we + // have lots of itable dispatches (e.g., lambdas and streams). + // Keep it away from the beginning of a Klass to avoid cacheline + // contention that may happen when a nearby object is modified. AccessFlags _access_flags; // Access flags. The class/interface distinction is stored here. JFR_ONLY(DEFINE_TRACE_ID_FIELD;) -- GitLab From 4243f4c998344e77dccd4d5605e56e869bc8af89 Mon Sep 17 00:00:00 2001 From: Zhengyu Gu Date: Fri, 7 Jan 2022 13:33:43 +0000 Subject: [PATCH 025/564] 8279540: Shenandoah: Should only clear CLD::_claim_strong mark for strong CLD iterations Reviewed-by: shade --- .../share/gc/shenandoah/shenandoahRootProcessor.inline.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.inline.hpp index e499c3543ff..5677f3daa60 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.inline.hpp @@ -82,7 +82,7 @@ ShenandoahClassLoaderDataRoots::ShenandoahClassLoaderDataRoots(Shena if (heap_iteration) { ClassLoaderDataGraph::clear_claimed_marks(ClassLoaderData::_claim_other); } else { - ClassLoaderDataGraph::clear_claimed_marks(); + ClassLoaderDataGraph::clear_claimed_marks(ClassLoaderData::_claim_strong); } if (CONCURRENT) { -- GitLab From d65c665839c0a564c422ef685f2673fac37315d7 Mon Sep 17 00:00:00 2001 From: Maurizio Cimadamore Date: Fri, 7 Jan 2022 13:41:29 +0000 Subject: [PATCH 026/564] 8279527: Dereferencing segments backed by different scopes leads to pollution Reviewed-by: psandoz, jvernee --- .../share/classes/java/nio/Buffer.java | 6 ++- .../foreign/AbstractMemorySegmentImpl.java | 6 +-- .../jdk/internal/foreign/ConfinedScope.java | 39 ++++----------- .../internal/foreign/NativeSymbolImpl.java | 3 +- .../internal/foreign/ResourceScopeImpl.java | 47 +++++++++++++++---- .../jdk/internal/foreign/SharedScope.java | 30 +----------- test/jdk/java/foreign/TestByteBuffer.java | 4 +- .../foreign/LoopOverPollutedSegments.java | 5 +- 8 files changed, 64 insertions(+), 76 deletions(-) diff --git a/src/java.base/share/classes/java/nio/Buffer.java b/src/java.base/share/classes/java/nio/Buffer.java index 92c9f80dca8..a452b1a28dd 100644 --- a/src/java.base/share/classes/java/nio/Buffer.java +++ b/src/java.base/share/classes/java/nio/Buffer.java @@ -767,7 +767,11 @@ public abstract class Buffer { final void checkScope() { ScopedMemoryAccess.Scope scope = scope(); if (scope != null) { - scope.checkValidState(); + try { + scope.checkValidState(); + } catch (ScopedMemoryAccess.Scope.ScopedAccessError e) { + throw new IllegalStateException("This segment is already closed"); + } } } diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java index 5744d8556b1..6ced72bc1af 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java @@ -364,11 +364,7 @@ public abstract non-sealed class AbstractMemorySegmentImpl extends MemorySegment } void checkValidState() { - try { - scope.checkValidState(); - } catch (ScopedMemoryAccess.Scope.ScopedAccessError ex) { - throw new IllegalStateException("This segment is already closed"); - } + scope.checkValidStateSlow(); } @Override diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/ConfinedScope.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/ConfinedScope.java index ac8850258c1..a0a7d01cea6 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/ConfinedScope.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/ConfinedScope.java @@ -39,10 +39,7 @@ import java.lang.ref.Cleaner; */ final class ConfinedScope extends ResourceScopeImpl { - private boolean closed; // = false - private int lockCount = 0; private int asyncReleaseCount = 0; - private final Thread owner; static final VarHandle ASYNC_RELEASE_COUNT; @@ -55,40 +52,29 @@ final class ConfinedScope extends ResourceScopeImpl { } public ConfinedScope(Thread owner, Cleaner cleaner) { - super(new ConfinedResourceList(), cleaner); - this.owner = owner; - } - - @ForceInline - public final void checkValidState() { - if (owner != Thread.currentThread()) { - throw new IllegalStateException("Attempted access outside owning thread"); - } - if (closed) { - throw new IllegalStateException("Already closed"); - } + super(owner, new ConfinedResourceList(), cleaner); } @Override public boolean isAlive() { - return !closed; + return state != CLOSED; } @Override @ForceInline public void acquire0() { - checkValidState(); - if (lockCount == MAX_FORKS) { + checkValidStateSlow(); + if (state == MAX_FORKS) { throw new IllegalStateException("Scope keep alive limit exceeded"); } - lockCount++; + state++; } @Override @ForceInline public void release0() { if (Thread.currentThread() == owner) { - lockCount--; + state--; } else { // It is possible to end up here in two cases: this scope was kept alive by some other confined scope // which is implicitly released (in which case the release call comes from the cleaner thread). Or, @@ -99,19 +85,14 @@ final class ConfinedScope extends ResourceScopeImpl { } void justClose() { - this.checkValidState(); - if (lockCount == 0 || lockCount - ((int)ASYNC_RELEASE_COUNT.getVolatile(this)) == 0) { - closed = true; + checkValidStateSlow(); + if (state == 0 || state - ((int)ASYNC_RELEASE_COUNT.getVolatile(this)) == 0) { + state = CLOSED; } else { - throw new IllegalStateException("Scope is kept alive by " + lockCount + " scopes"); + throw new IllegalStateException("Scope is kept alive by " + state + " scopes"); } } - @Override - public Thread ownerThread() { - return owner; - } - /** * A confined resource list; no races are possible here. */ diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/NativeSymbolImpl.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/NativeSymbolImpl.java index ede6a7ad5f8..cb62a2c240f 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/NativeSymbolImpl.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/NativeSymbolImpl.java @@ -28,11 +28,12 @@ package jdk.internal.foreign; import jdk.incubator.foreign.MemoryAddress; import jdk.incubator.foreign.NativeSymbol; import jdk.incubator.foreign.ResourceScope; +import jdk.internal.misc.ScopedMemoryAccess; public record NativeSymbolImpl(String name, MemoryAddress address, ResourceScope scope) implements NativeSymbol, Scoped { @Override public MemoryAddress address() { - ((ResourceScopeImpl)scope).checkValidState(); + ((ResourceScopeImpl)scope).checkValidStateSlow(); return address; } } diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/ResourceScopeImpl.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/ResourceScopeImpl.java index ab47db827e7..173753b1586 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/ResourceScopeImpl.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/ResourceScopeImpl.java @@ -32,6 +32,8 @@ import jdk.incubator.foreign.SegmentAllocator; import jdk.internal.misc.ScopedMemoryAccess; import jdk.internal.vm.annotation.ForceInline; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.VarHandle; import java.lang.ref.Cleaner; import java.lang.ref.Reference; import java.util.Objects; @@ -53,6 +55,23 @@ public abstract non-sealed class ResourceScopeImpl implements ResourceScope, Seg final ResourceList resourceList; final Cleaner.Cleanable cleanable; + final Thread owner; + + static final int ALIVE = 0; + static final int CLOSING = -1; + static final int CLOSED = -2; + + int state = ALIVE; + + static final VarHandle STATE; + + static { + try { + STATE = MethodHandles.lookup().findVarHandle(ResourceScopeImpl.class, "state", int.class); + } catch (Throwable ex) { + throw new ExceptionInInitializerError(ex); + } + } static final int MAX_FORKS = Integer.MAX_VALUE; @@ -89,7 +108,8 @@ public abstract non-sealed class ResourceScopeImpl implements ResourceScope, Seg } } - protected ResourceScopeImpl(ResourceList resourceList, Cleaner cleaner) { + protected ResourceScopeImpl(Thread owner, ResourceList resourceList, Cleaner cleaner) { + this.owner = owner; this.resourceList = resourceList; cleanable = (cleaner != null) ? cleaner.register(this, resourceList) : null; @@ -147,7 +167,9 @@ public abstract non-sealed class ResourceScopeImpl implements ResourceScope, Seg * Returns "owner" thread of this scope. * @return owner thread (or null for a shared scope) */ - public abstract Thread ownerThread(); + public final Thread ownerThread() { + return owner; + } /** * Returns true, if this scope is still alive. This method may be called in any thread. @@ -155,14 +177,23 @@ public abstract non-sealed class ResourceScopeImpl implements ResourceScope, Seg */ public abstract boolean isAlive(); - /** * This is a faster version of {@link #checkValidStateSlow()}, which is called upon memory access, and which - * relies on invariants associated with the memory scope implementations (typically, volatile access - * to the closed state bit is replaced with plain access, and ownership check is removed where not needed. - * Should be used with care. + * relies on invariants associated with the memory scope implementations (volatile access + * to the closed state bit is replaced with plain access). This method should be monomorphic, + * to avoid virtual calls in the memory access hot path. This method is not intended as general purpose method + * and should only be used in the memory access handle hot path; for liveness checks triggered by other API methods, + * please use {@link #checkValidStateSlow()}. */ - public abstract void checkValidState(); + @ForceInline + public final void checkValidState() { + if (owner != null && owner != Thread.currentThread()) { + throw new IllegalStateException("Attempted access outside owning thread"); + } + if (state < ALIVE) { + throw ScopedAccessError.INSTANCE; + } + } /** * Checks that this scope is still alive (see {@link #isAlive()}). @@ -170,7 +201,7 @@ public abstract non-sealed class ResourceScopeImpl implements ResourceScope, Seg * a confined scope and this method is called outside of the owner thread. */ public final void checkValidStateSlow() { - if (ownerThread() != null && Thread.currentThread() != ownerThread()) { + if (owner != null && Thread.currentThread() != owner) { throw new IllegalStateException("Attempted access outside owning thread"); } else if (!isAlive()) { throw new IllegalStateException("Already closed"); diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/SharedScope.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/SharedScope.java index 93ecf08d468..4d80eb9bbe5 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/SharedScope.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/SharedScope.java @@ -45,36 +45,8 @@ class SharedScope extends ResourceScopeImpl { private static final ScopedMemoryAccess SCOPED_MEMORY_ACCESS = ScopedMemoryAccess.getScopedMemoryAccess(); - private static final int ALIVE = 0; - private static final int CLOSING = -1; - private static final int CLOSED = -2; - - private int state = ALIVE; - - private static final VarHandle STATE; - - static { - try { - STATE = MethodHandles.lookup().findVarHandle(jdk.internal.foreign.SharedScope.class, "state", int.class); - } catch (Throwable ex) { - throw new ExceptionInInitializerError(ex); - } - } - SharedScope(Cleaner cleaner) { - super(new SharedResourceList(), cleaner); - } - - @Override - public Thread ownerThread() { - return null; - } - - @Override - public void checkValidState() { - if (state < ALIVE) { - throw ScopedAccessError.INSTANCE; - } + super(null, new SharedResourceList(), cleaner); } @Override diff --git a/test/jdk/java/foreign/TestByteBuffer.java b/test/jdk/java/foreign/TestByteBuffer.java index 57d953f771d..ce5f55efb0d 100644 --- a/test/jdk/java/foreign/TestByteBuffer.java +++ b/test/jdk/java/foreign/TestByteBuffer.java @@ -369,7 +369,7 @@ public class TestByteBuffer { Throwable cause = ex.getCause(); if (cause instanceof IllegalStateException) { //all get/set buffer operation should fail because of the scope check - assertTrue(ex.getCause().getMessage().contains("Already closed")); + assertTrue(ex.getCause().getMessage().contains("already closed")); } else { //all other exceptions were unexpected - fail fail("Unexpected exception", cause); @@ -406,7 +406,7 @@ public class TestByteBuffer { handle.invoke(e.getValue()); fail(); } catch (IllegalStateException ex) { - assertTrue(ex.getMessage().contains("Already closed")); + assertTrue(ex.getMessage().contains("already closed")); } catch (UnsupportedOperationException ex) { //skip } catch (Throwable ex) { diff --git a/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverPollutedSegments.java b/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverPollutedSegments.java index 4cb01f091f1..d2803d9d793 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverPollutedSegments.java +++ b/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverPollutedSegments.java @@ -58,7 +58,7 @@ public class LoopOverPollutedSegments { static final Unsafe unsafe = Utils.unsafe; - MemorySegment nativeSegment, heapSegmentBytes, heapSegmentFloats; + MemorySegment nativeSegment, nativeSharedSegment, heapSegmentBytes, heapSegmentFloats; byte[] arr; long addr; @@ -73,6 +73,7 @@ public class LoopOverPollutedSegments { } arr = new byte[ALLOC_SIZE]; nativeSegment = MemorySegment.allocateNative(ALLOC_SIZE, 4, ResourceScope.newConfinedScope()); + nativeSharedSegment = MemorySegment.allocateNative(ALLOC_SIZE, 4, ResourceScope.newSharedScope()); heapSegmentBytes = MemorySegment.ofArray(new byte[ALLOC_SIZE]); heapSegmentFloats = MemorySegment.ofArray(new float[ELEM_SIZE]); @@ -81,6 +82,8 @@ public class LoopOverPollutedSegments { unsafe.putInt(arr, Unsafe.ARRAY_BYTE_BASE_OFFSET + (i * 4), i); nativeSegment.setAtIndex(JAVA_INT, i, i); nativeSegment.setAtIndex(JAVA_FLOAT, i, i); + nativeSharedSegment.setAtIndex(JAVA_INT, i, i); + nativeSharedSegment.setAtIndex(JAVA_FLOAT, i, i); intHandle.set(nativeSegment, (long)i, i); heapSegmentBytes.setAtIndex(JAVA_INT, i, i); heapSegmentBytes.setAtIndex(JAVA_FLOAT, i, i); -- GitLab From d47af74e4c98c9fc4aef537c6d8eeb66a1621586 Mon Sep 17 00:00:00 2001 From: Ioi Lam Date: Fri, 7 Jan 2022 18:38:47 +0000 Subject: [PATCH 027/564] 8279500: Remove FileMapHeader::_heap_obj_roots Reviewed-by: minqi, ccheung --- src/hotspot/share/cds/filemap.cpp | 4 +--- src/hotspot/share/cds/filemap.hpp | 7 +----- src/hotspot/share/cds/heapShared.cpp | 29 ++++++++++++++--------- src/hotspot/share/cds/heapShared.hpp | 6 ++--- src/hotspot/share/cds/metaspaceShared.cpp | 4 ++-- src/hotspot/share/include/cds.h | 4 ++-- 6 files changed, 26 insertions(+), 28 deletions(-) diff --git a/src/hotspot/share/cds/filemap.cpp b/src/hotspot/share/cds/filemap.cpp index 090f60c8aa5..7bd31310db6 100644 --- a/src/hotspot/share/cds/filemap.cpp +++ b/src/hotspot/share/cds/filemap.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, 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 @@ -273,7 +273,6 @@ void FileMapHeader::populate(FileMapInfo *info, size_t core_region_alignment, if (!DynamicDumpSharedSpaces) { set_shared_path_table(info->_shared_path_table); - CDS_JAVA_HEAP_ONLY(_heap_obj_roots = CompressedOops::encode(HeapShared::roots());) } } @@ -2097,7 +2096,6 @@ void FileMapInfo::map_heap_regions_impl() { /*is_open_archive=*/ true, &open_heap_regions, &num_open_heap_regions)) { HeapShared::set_open_regions_mapped(); - HeapShared::set_roots(header()->heap_obj_roots()); } } } diff --git a/src/hotspot/share/cds/filemap.hpp b/src/hotspot/share/cds/filemap.hpp index 816ac5469dc..a8afe5dbdfd 100644 --- a/src/hotspot/share/cds/filemap.hpp +++ b/src/hotspot/share/cds/filemap.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, 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 @@ -232,7 +232,6 @@ private: // some expensive operations. bool _use_full_module_graph; // Can we use the full archived module graph? size_t _ptrmap_size_in_bits; // Size of pointer relocation bitmap - narrowOop _heap_obj_roots; // An objArray that stores all the roots of archived heap objects char* from_mapped_offset(size_t offset) const { return mapped_base_address() + offset; } @@ -279,14 +278,12 @@ public: jshort app_module_paths_start_index() const { return _app_module_paths_start_index; } jshort app_class_paths_start_index() const { return _app_class_paths_start_index; } jshort num_module_paths() const { return _num_module_paths; } - narrowOop heap_obj_roots() const { return _heap_obj_roots; } void set_has_platform_or_app_classes(bool v) { _has_platform_or_app_classes = v; } void set_cloned_vtables(char* p) { set_as_offset(p, &_cloned_vtables_offset); } void set_serialized_data(char* p) { set_as_offset(p, &_serialized_data_offset); } void set_ptrmap_size_in_bits(size_t s) { _ptrmap_size_in_bits = s; } void set_mapped_base_address(char* p) { _mapped_base_address = p; } - void set_heap_obj_roots(narrowOop r) { _heap_obj_roots = r; } void copy_base_archive_name(const char* name); void set_shared_path_table(SharedPathTable table) { @@ -413,8 +410,6 @@ public: void set_requested_base(char* b) { header()->set_requested_base(b); } char* requested_base_address() const { return header()->requested_base_address(); } - narrowOop heap_obj_roots() const { return header()->heap_obj_roots(); } - class DynamicArchiveHeader* dynamic_header() const { assert(!is_static(), "must be"); return (DynamicArchiveHeader*)header(); diff --git a/src/hotspot/share/cds/heapShared.cpp b/src/hotspot/share/cds/heapShared.cpp index 2ae72ffb5ed..a224db848bb 100644 --- a/src/hotspot/share/cds/heapShared.cpp +++ b/src/hotspot/share/cds/heapShared.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2022, 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 @@ -128,7 +128,6 @@ const static int num_fmg_open_archive_subgraph_entry_fields = sizeof(fmg_open_archive_subgraph_entry_fields) / sizeof(ArchivableStaticFieldInfo); GrowableArrayCHeap* HeapShared::_pending_roots = NULL; -narrowOop HeapShared::_roots_narrow; OopHandle HeapShared::_roots; #ifdef ASSERT @@ -152,7 +151,6 @@ void HeapShared::fixup_regions() { fill_failed_loaded_region(); } if (is_fully_available()) { - _roots = OopHandle(Universe::vm_global(), decode_from_archive(_roots_narrow)); if (!MetaspaceShared::use_full_module_graph()) { // Need to remove all the archived java.lang.Module objects from HeapShared::roots(). ClassLoaderDataShared::clear_archived_oops(); @@ -236,12 +234,6 @@ objArrayOop HeapShared::roots() { return roots; } -void HeapShared::set_roots(narrowOop roots) { - assert(UseSharedSpaces, "runtime only"); - assert(is_fully_available(), "must be"); - _roots_narrow = roots; -} - // Returns an objArray that contains all the roots of the archived objects oop HeapShared::get_root(int index, bool clear) { assert(index >= 0, "sanity"); @@ -670,7 +662,23 @@ void HeapShared::write_subgraph_info_table() { writer.dump(&_run_time_subgraph_info_table, "subgraphs"); } -void HeapShared::serialize_subgraph_info_table_header(SerializeClosure* soc) { +void HeapShared::serialize(SerializeClosure* soc) { + oop roots_oop = NULL; + + if (soc->reading()) { + soc->do_oop(&roots_oop); // read from archive + assert(oopDesc::is_oop_or_null(roots_oop), "is oop"); + // Create an OopHandle only if we have actually mapped or loaded the roots + if (roots_oop != NULL) { + assert(HeapShared::is_fully_available(), "must be"); + _roots = OopHandle(Universe::vm_global(), roots_oop); + } + } else { + // writing + roots_oop = roots(); + soc->do_oop(&roots_oop); // write to archive + } + _run_time_subgraph_info_table.serialize_header(soc); } @@ -1695,7 +1703,6 @@ bool HeapShared::load_heap_regions(FileMapInfo* mapinfo) { init_loaded_heap_relocation(loaded_regions, num_loaded_regions); _is_loaded = true; - set_roots(mapinfo->heap_obj_roots()); return true; } diff --git a/src/hotspot/share/cds/heapShared.hpp b/src/hotspot/share/cds/heapShared.hpp index 52a8de9ad46..6447b124d2f 100644 --- a/src/hotspot/share/cds/heapShared.hpp +++ b/src/hotspot/share/cds/heapShared.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2022, 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 @@ -310,7 +310,6 @@ private: static SeenObjectsTable *_seen_objects_table; static GrowableArrayCHeap* _pending_roots; - static narrowOop _roots_narrow; static OopHandle _roots; static void init_seen_objects_table() { @@ -418,7 +417,6 @@ private: static oop get_root(int index, bool clear=false); // Run-time only - static void set_roots(narrowOop roots); static void clear_root(int index); #endif // INCLUDE_CDS_JAVA_HEAP @@ -468,7 +466,7 @@ private: static void init_for_dumping(TRAPS) NOT_CDS_JAVA_HEAP_RETURN; static void write_subgraph_info_table() NOT_CDS_JAVA_HEAP_RETURN; - static void serialize_subgraph_info_table_header(SerializeClosure* soc) NOT_CDS_JAVA_HEAP_RETURN; + static void serialize(SerializeClosure* soc) NOT_CDS_JAVA_HEAP_RETURN; }; #if INCLUDE_CDS_JAVA_HEAP diff --git a/src/hotspot/share/cds/metaspaceShared.cpp b/src/hotspot/share/cds/metaspaceShared.cpp index f714ce790b2..c56680997c2 100644 --- a/src/hotspot/share/cds/metaspaceShared.cpp +++ b/src/hotspot/share/cds/metaspaceShared.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022, 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 @@ -384,7 +384,7 @@ void MetaspaceShared::serialize(SerializeClosure* soc) { // Dump/restore the symbol/string/subgraph_info tables SymbolTable::serialize_shared_table_header(soc); StringTable::serialize_shared_table_header(soc); - HeapShared::serialize_subgraph_info_table_header(soc); + HeapShared::serialize(soc); SystemDictionaryShared::serialize_dictionary_headers(soc); InstanceMirrorKlass::serialize_offsets(soc); diff --git a/src/hotspot/share/include/cds.h b/src/hotspot/share/include/cds.h index 0c020e43696..1c8640ec0b2 100644 --- a/src/hotspot/share/include/cds.h +++ b/src/hotspot/share/include/cds.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,7 +39,7 @@ #define CDS_ARCHIVE_MAGIC 0xf00baba2 #define CDS_DYNAMIC_ARCHIVE_MAGIC 0xf00baba8 #define CDS_GENERIC_HEADER_SUPPORTED_MIN_VERSION 13 -#define CURRENT_CDS_ARCHIVE_VERSION 13 +#define CURRENT_CDS_ARCHIVE_VERSION 14 typedef struct CDSFileMapRegion { int _crc; // CRC checksum of this region. -- GitLab From f203723fc72c5d92c8745d4c595f360a9b50c512 Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Sat, 8 Jan 2022 01:02:37 +0000 Subject: [PATCH 028/564] 8279337: The MToolkit is still referenced in a few places Reviewed-by: prr --- .../classes/sun/lwawt/macosx/LWCToolkit.java | 4 +- .../share/classes/sun/awt/SunToolkit.java | 4 +- .../sun/awt/X11GraphicsEnvironment.java | 4 +- .../sun/java2d/opengl/GLXGraphicsConfig.java | 4 +- src/java.desktop/unix/native/common/awt/awt.h | 4 +- .../ChoiceKeyEventReaction.java | 4 +- .../ActualFocusedWindowBlockingTest.java | 7 +-- .../AutoRequestFocusSetVisibleTest.java | 56 +++++++++---------- .../AutoRequestFocusToFrontTest.java | 23 +++----- .../ModalBlockedStealsFocusTest.java | 7 +-- .../ModalExcludedWindowClickTest.java | 8 +-- .../NonFocusableBlockedOwnerTest.java | 8 +-- .../SimpleWindowActivationTest.java | 8 +-- .../WindowUpdateFocusabilityTest.java | 7 +-- .../ExtraButtonDrag.java | 5 +- .../AcceptExtraMouseButtons.java | 4 +- .../awt/Window/GrabSequence/GrabSequence.java | 7 +-- test/jdk/java/awt/regtesthelpers/Util.java | 8 +-- 18 files changed, 60 insertions(+), 112 deletions(-) diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java index 4a8f5bafe85..2362b68c41c 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2022, 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 @@ -453,7 +453,7 @@ public final class LWCToolkit extends LWToolkit { desktopProperties.put("awt.multiClickInterval", getMultiClickTime()); // These DnD properties must be set, otherwise Swing ends up spewing NPEs - // all over the place. The values came straight off of MToolkit. + // all over the place. The values came straight off of XToolkit. desktopProperties.put("DnD.Autoscroll.initialDelay", Integer.valueOf(50)); desktopProperties.put("DnD.Autoscroll.interval", Integer.valueOf(50)); desktopProperties.put("DnD.Autoscroll.cursorHysteresis", Integer.valueOf(5)); diff --git a/src/java.desktop/share/classes/sun/awt/SunToolkit.java b/src/java.desktop/share/classes/sun/awt/SunToolkit.java index dfc3d24c579..380a5e4db01 100644 --- a/src/java.desktop/share/classes/sun/awt/SunToolkit.java +++ b/src/java.desktop/share/classes/sun/awt/SunToolkit.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -204,7 +204,7 @@ public abstract class SunToolkit extends Toolkit * access to Xlib, OpenGL, etc. However, these methods are implemented * in SunToolkit so that they can be called from shared code (e.g. * from the OGL pipeline) or from the X11 pipeline regardless of whether - * XToolkit or MToolkit is currently in use. There are native macros + * XToolkit is currently in use. There are native macros * (such as AWT_LOCK) defined in awt.h, so if the implementation of these * methods is changed, make sure it is compatible with the native macros. * diff --git a/src/java.desktop/unix/classes/sun/awt/X11GraphicsEnvironment.java b/src/java.desktop/unix/classes/sun/awt/X11GraphicsEnvironment.java index e8cff0a28e9..5c9d2a1b695 100644 --- a/src/java.desktop/unix/classes/sun/awt/X11GraphicsEnvironment.java +++ b/src/java.desktop/unix/classes/sun/awt/X11GraphicsEnvironment.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -67,7 +67,7 @@ public final class X11GraphicsEnvironment extends SunGraphicsEnvironment { System.loadLibrary("awt"); /* - * Note: The MToolkit object depends on the static initializer + * Note: The XToolkit object depends on the static initializer * of X11GraphicsEnvironment to initialize the connection to * the X11 server. */ diff --git a/src/java.desktop/unix/classes/sun/java2d/opengl/GLXGraphicsConfig.java b/src/java.desktop/unix/classes/sun/java2d/opengl/GLXGraphicsConfig.java index 536962bd820..588dfbf882a 100644 --- a/src/java.desktop/unix/classes/sun/java2d/opengl/GLXGraphicsConfig.java +++ b/src/java.desktop/unix/classes/sun/java2d/opengl/GLXGraphicsConfig.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, 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 @@ -216,7 +216,7 @@ public final class GLXGraphicsConfig } /** - * The following methods are invoked from MToolkit or XToolkit.java and + * The following methods are invoked from XToolkit.java and * X11ComponentPeer.java rather than having the X11-dependent * implementations hardcoded in those classes. This way the appropriate * actions are taken based on the peer's GraphicsConfig, whether it is diff --git a/src/java.desktop/unix/native/common/awt/awt.h b/src/java.desktop/unix/native/common/awt/awt.h index 18a6dee275b..5c71431f033 100644 --- a/src/java.desktop/unix/native/common/awt/awt.h +++ b/src/java.desktop/unix/native/common/awt/awt.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,7 +41,7 @@ typedef char Boolean; #endif /* !HEADLESS && !MACOSX */ -/* The JVM instance: defined in awt_MToolkit.c */ +/* The JVM instance: defined in awt_LoadLibrary.c */ extern JavaVM *jvm; extern jclass tkClass; diff --git a/test/jdk/java/awt/Choice/ChoiceKeyEventReaction/ChoiceKeyEventReaction.java b/test/jdk/java/awt/Choice/ChoiceKeyEventReaction/ChoiceKeyEventReaction.java index 4b835b11063..84e5b4d62e4 100644 --- a/test/jdk/java/awt/Choice/ChoiceKeyEventReaction/ChoiceKeyEventReaction.java +++ b/test/jdk/java/awt/Choice/ChoiceKeyEventReaction/ChoiceKeyEventReaction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2022, 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 @@ -131,7 +131,7 @@ public class ChoiceKeyEventReaction if (toolkit.equals("sun.awt.X11.XToolkit") && keyTypedOnTextField) { - throw new RuntimeException("Test failed. (XToolkit/MToolkit). KeyEvent was addressed to TextField."); + throw new RuntimeException("Test failed. (XToolkit). KeyEvent was addressed to TextField."); } System.out.println("Test passed. Unfocusable Choice doesn't react on keys."); diff --git a/test/jdk/java/awt/Focus/ActualFocusedWindowTest/ActualFocusedWindowBlockingTest.java b/test/jdk/java/awt/Focus/ActualFocusedWindowTest/ActualFocusedWindowBlockingTest.java index a87b59a9388..1e5b2789208 100644 --- a/test/jdk/java/awt/Focus/ActualFocusedWindowTest/ActualFocusedWindowBlockingTest.java +++ b/test/jdk/java/awt/Focus/ActualFocusedWindowTest/ActualFocusedWindowBlockingTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2022, 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 @@ -69,11 +69,6 @@ public class ActualFocusedWindowBlockingTest { } public void start() { - if ("sun.awt.motif.MToolkit".equals(Toolkit.getDefaultToolkit().getClass().getName())) { - System.out.println("No testing on Motif. Test passed."); - return; - } - System.out.println("\nTest started:\n"); // Test 1. diff --git a/test/jdk/java/awt/Focus/AutoRequestFocusTest/AutoRequestFocusSetVisibleTest.java b/test/jdk/java/awt/Focus/AutoRequestFocusTest/AutoRequestFocusSetVisibleTest.java index 0a7a1afff61..45914e0670b 100644 --- a/test/jdk/java/awt/Focus/AutoRequestFocusTest/AutoRequestFocusSetVisibleTest.java +++ b/test/jdk/java/awt/Focus/AutoRequestFocusTest/AutoRequestFocusSetVisibleTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2022, 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 @@ -293,43 +293,39 @@ public class AutoRequestFocusSetVisibleTest { // 6. Show unblocking modal Dialog. /////////////////////////////////// - if ("sun.awt.motif.MToolkit".equals(toolkitClassName)) { - System.out.println("Stage 6 - Skiping."); - } else { - System.out.println("Stage 6 in progress..."); + System.out.println("Stage 6 in progress..."); - // --- - // Testing the bug of activating invisible modal Dialog (awt_Window::SetAndActivateModalBlocker). - // Having some window not excluded from modality, so that it would be blocked. - Frame f = new Frame("Aux. Frame"); - f.setSize(100, 100); - setVisible(f, true); - // --- + // --- + // Testing the bug of activating invisible modal Dialog (awt_Window::SetAndActivateModalBlocker). + // Having some window not excluded from modality, so that it would be blocked. + Frame f = new Frame("Aux. Frame"); + f.setSize(100, 100); + setVisible(f, true); + // --- - setVisible(focusedFrame, true); + setVisible(focusedFrame, true); + if (!focusOwner.hasFocus()) { + Util.clickOnComp(focusOwner, robot); + Util.waitForIdle(robot); if (!focusOwner.hasFocus()) { - Util.clickOnComp(focusOwner, robot); - Util.waitForIdle(robot); - if (!focusOwner.hasFocus()) { - throw new Error("Test error: the frame couldn't be focused."); - } + throw new Error("Test error: the frame couldn't be focused."); } + } - dialog.setModal(true); - dialog.setAutoRequestFocus(false); - focusedFrame.setModalExclusionType(Dialog.ModalExclusionType.APPLICATION_EXCLUDE); + dialog.setModal(true); + dialog.setAutoRequestFocus(false); + focusedFrame.setModalExclusionType(Dialog.ModalExclusionType.APPLICATION_EXCLUDE); - TestHelper.invokeLaterAndWait(new Runnable() { - public void run() { - dialog.setVisible(true); - } - }, robot); + TestHelper.invokeLaterAndWait(new Runnable() { + public void run() { + dialog.setVisible(true); + } + }, robot); - if (dialog.isFocused()) { - throw new TestFailedException("the unblocking dialog shouldn't gain focus but it did!"); - } - setVisible(dialog, false); + if (dialog.isFocused()) { + throw new TestFailedException("the unblocking dialog shouldn't gain focus but it did!"); } + setVisible(dialog, false); System.out.println("Test passed."); } diff --git a/test/jdk/java/awt/Focus/AutoRequestFocusTest/AutoRequestFocusToFrontTest.java b/test/jdk/java/awt/Focus/AutoRequestFocusTest/AutoRequestFocusToFrontTest.java index 8ca4d4d6f7b..b1b8b8458ff 100644 --- a/test/jdk/java/awt/Focus/AutoRequestFocusTest/AutoRequestFocusToFrontTest.java +++ b/test/jdk/java/awt/Focus/AutoRequestFocusTest/AutoRequestFocusToFrontTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2022, 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 @@ -202,26 +202,22 @@ public class AutoRequestFocusToFrontTest { // Focused frame is excluded from modality. //////////////////////////////////////////////// - if (!"sun.awt.motif.MToolkit".equals(toolkitClassName)) { - recreateGUI(); - auxFrame.setModalExclusionType(Dialog.ModalExclusionType.APPLICATION_EXCLUDE); + recreateGUI(); + auxFrame.setModalExclusionType(Dialog.ModalExclusionType.APPLICATION_EXCLUDE); - Test.setWindows(modalDialog, modalDialog, new Window[] {modalDialog, frame3}); - Test.test("Test stage 6.1 in progress", modalDlgButton); - } + Test.setWindows(modalDialog, modalDialog, new Window[] {modalDialog, frame3}); + Test.test("Test stage 6.1 in progress", modalDlgButton); // 6.2. Owner Frame (with owned modal Dialog). // Focused frame is excluded from modality. //////////////////////////////////////////////// - if (!"sun.awt.motif.MToolkit".equals(toolkitClassName)) { - recreateGUI(); - auxFrame.setModalExclusionType(Dialog.ModalExclusionType.APPLICATION_EXCLUDE); + recreateGUI(); + auxFrame.setModalExclusionType(Dialog.ModalExclusionType.APPLICATION_EXCLUDE); - Test.setWindows(frame3, modalDialog, new Window[] {modalDialog, frame3}); - Test.test("Test stage 6.2 in progress", modalDlgButton, true); - } + Test.setWindows(frame3, modalDialog, new Window[] {modalDialog, frame3}); + Test.test("Test stage 6.2 in progress", modalDlgButton, true); /////////////////////////////////////////////////// // 7. Calling setVisible(true) for the shown Frame. @@ -422,4 +418,3 @@ class TestFailedException extends RuntimeException { super("Test failed: " + msg); } } - diff --git a/test/jdk/java/awt/Focus/ModalBlockedStealsFocusTest/ModalBlockedStealsFocusTest.java b/test/jdk/java/awt/Focus/ModalBlockedStealsFocusTest/ModalBlockedStealsFocusTest.java index 9a0d476133b..27be25773f2 100644 --- a/test/jdk/java/awt/Focus/ModalBlockedStealsFocusTest/ModalBlockedStealsFocusTest.java +++ b/test/jdk/java/awt/Focus/ModalBlockedStealsFocusTest/ModalBlockedStealsFocusTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2022, 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,11 +47,6 @@ public class ModalBlockedStealsFocusTest { } public void start() { - if ("sun.awt.motif.MToolkit".equals(Toolkit.getDefaultToolkit().getClass().getName())) { - System.out.println("The test is not for MToolkit."); - return; - } - dialog.setBounds(800, 0, 200, 100); frame.setBounds(800, 150, 200, 100); diff --git a/test/jdk/java/awt/Focus/ModalExcludedWindowClickTest/ModalExcludedWindowClickTest.java b/test/jdk/java/awt/Focus/ModalExcludedWindowClickTest/ModalExcludedWindowClickTest.java index 0ee37cbce69..7cfe66834bc 100644 --- a/test/jdk/java/awt/Focus/ModalExcludedWindowClickTest/ModalExcludedWindowClickTest.java +++ b/test/jdk/java/awt/Focus/ModalExcludedWindowClickTest/ModalExcludedWindowClickTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,12 +57,6 @@ public class ModalExcludedWindowClickTest { } public void start() { - - if ("sun.awt.motif.MToolkit".equals(Toolkit.getDefaultToolkit().getClass().getName())) { - System.out.println("No testing on MToolkit."); - return; - } - button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { actionPerformed = true; diff --git a/test/jdk/java/awt/Focus/NonFocusableBlockedOwnerTest/NonFocusableBlockedOwnerTest.java b/test/jdk/java/awt/Focus/NonFocusableBlockedOwnerTest/NonFocusableBlockedOwnerTest.java index b6d4c962efa..abf8d57cecd 100644 --- a/test/jdk/java/awt/Focus/NonFocusableBlockedOwnerTest/NonFocusableBlockedOwnerTest.java +++ b/test/jdk/java/awt/Focus/NonFocusableBlockedOwnerTest/NonFocusableBlockedOwnerTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2022, 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 @@ -56,12 +56,6 @@ public class NonFocusableBlockedOwnerTest { } public void start() { - - if ("sun.awt.motif.MToolkit".equals(Toolkit.getDefaultToolkit().getClass().getName())) { - System.out.println("No testing on MToolkit."); - return; - } - try { EventQueue.invokeLater(new Runnable() { public void run() { diff --git a/test/jdk/java/awt/Focus/SimpleWindowActivationTest/SimpleWindowActivationTest.java b/test/jdk/java/awt/Focus/SimpleWindowActivationTest/SimpleWindowActivationTest.java index a63d8194714..212d5274a89 100644 --- a/test/jdk/java/awt/Focus/SimpleWindowActivationTest/SimpleWindowActivationTest.java +++ b/test/jdk/java/awt/Focus/SimpleWindowActivationTest/SimpleWindowActivationTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022, 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,12 +47,6 @@ public class SimpleWindowActivationTest { private static Robot robot; public static void main(String[] args) throws Exception { - - if ("sun.awt.motif.MToolkit".equals(Toolkit.getDefaultToolkit().getClass().getName())) { - System.out.println("No testing on Motif. Test passed."); - return; - } - robot = new Robot(); robot.setAutoDelay(50); diff --git a/test/jdk/java/awt/Focus/WindowUpdateFocusabilityTest/WindowUpdateFocusabilityTest.java b/test/jdk/java/awt/Focus/WindowUpdateFocusabilityTest/WindowUpdateFocusabilityTest.java index 962f6b4665c..6a6cfc93939 100644 --- a/test/jdk/java/awt/Focus/WindowUpdateFocusabilityTest/WindowUpdateFocusabilityTest.java +++ b/test/jdk/java/awt/Focus/WindowUpdateFocusabilityTest/WindowUpdateFocusabilityTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -63,11 +63,6 @@ public class WindowUpdateFocusabilityTest { } public void start() { - if ("sun.awt.motif.MToolkit".equals(Toolkit.getDefaultToolkit().getClass().getName())) { - System.out.println("No testing on Motif."); - return; - } - test(new Frame("Frame owner")); Frame dialog_owner = new Frame("dialog's owner"); test(new Dialog(dialog_owner)); diff --git a/test/jdk/java/awt/Mouse/MouseModifiersUnitTest/ExtraButtonDrag.java b/test/jdk/java/awt/Mouse/MouseModifiersUnitTest/ExtraButtonDrag.java index 29b90c9d430..3f8eeb17b38 100644 --- a/test/jdk/java/awt/Mouse/MouseModifiersUnitTest/ExtraButtonDrag.java +++ b/test/jdk/java/awt/Mouse/MouseModifiersUnitTest/ExtraButtonDrag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -105,7 +105,7 @@ public class ExtraButtonDrag extends Frame { //XToolkit: extra buttons should report MOVED events only //WToolkit: extra buttons should report DRAGGED events only if (i > 2){ //extra buttons only - if (tk.equals("sun.awt.X11.XToolkit") || tk.equals("sun.awt.motif.MToolkit")) { + if (tk.equals("sun.awt.X11.XToolkit")) { if (!moved || dragged) { throw new RuntimeException("Test failed."+ tk +" Button = " +(i+1) + " moved = "+moved +" : dragged = " +dragged); } @@ -152,4 +152,3 @@ public class ExtraButtonDrag extends Frame { } } - diff --git a/test/jdk/java/awt/Robot/AcceptExtraMouseButtons/AcceptExtraMouseButtons.java b/test/jdk/java/awt/Robot/AcceptExtraMouseButtons/AcceptExtraMouseButtons.java index 3ab3ba3ff87..ee83a328f0f 100644 --- a/test/jdk/java/awt/Robot/AcceptExtraMouseButtons/AcceptExtraMouseButtons.java +++ b/test/jdk/java/awt/Robot/AcceptExtraMouseButtons/AcceptExtraMouseButtons.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,7 +57,7 @@ public class AcceptExtraMouseButtons extends Frame { //MouseInfo.getNumberOfButtons() reports two more buttons on XToolkit //as they reserved for wheel (both directions). - if (tk.equals("sun.awt.X11.XToolkit") || tk.equals("sun.awt.motif.MToolkit")) { + if (tk.equals("sun.awt.X11.XToolkit")) { buttonsNum = buttonsNum - 2; } System.out.println("Number Of Buttons = "+ buttonsNum); diff --git a/test/jdk/java/awt/Window/GrabSequence/GrabSequence.java b/test/jdk/java/awt/Window/GrabSequence/GrabSequence.java index 686cae28010..da419e10ef1 100644 --- a/test/jdk/java/awt/Window/GrabSequence/GrabSequence.java +++ b/test/jdk/java/awt/Window/GrabSequence/GrabSequence.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,11 +40,6 @@ public class GrabSequence { private static void init() { - String toolkit = Toolkit.getDefaultToolkit().getClass().getName(); - if ( toolkit.equals("sun.awt.motif.MToolkit")){ - System.out.println("This test is for XToolkit and WToolkit only. Now using " + toolkit + ". Automatically passed."); - return; - } Frame frame = new Frame("Frame"); frame.setBackground(Color.green); frame.setForeground(Color.green); diff --git a/test/jdk/java/awt/regtesthelpers/Util.java b/test/jdk/java/awt/regtesthelpers/Util.java index dde65574460..af1cafe4297 100644 --- a/test/jdk/java/awt/regtesthelpers/Util.java +++ b/test/jdk/java/awt/regtesthelpers/Util.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2022, 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 @@ -405,8 +405,7 @@ public final class Util { } /* - * The values directly map to the ones of - * sun.awt.X11.XWM & sun.awt.motif.MToolkit classes. + * The values directly map to the ones of sun.awt.X11.XWM class. */ public final static int UNDETERMINED_WM = 1, @@ -433,8 +432,6 @@ public final class Util { try { if ("sun.awt.X11.XToolkit".equals(Toolkit.getDefaultToolkit().getClass().getName())) { clazz = Class.forName("sun.awt.X11.XWM"); - } else if ("sun.awt.motif.MToolkit".equals(Toolkit.getDefaultToolkit().getClass().getName())) { - clazz = Class.forName("sun.awt.motif.MToolkit"); } } catch (ClassNotFoundException cnfe) { cnfe.printStackTrace(); @@ -446,7 +443,6 @@ public final class Util { try { final Class _clazz = clazz; Method m_addExports = Class.forName("java.awt.Helper").getDeclaredMethod("addExports", String.class, java.lang.Module.class); - // No MToolkit anymore: nothing to do about it. // We may be called from non-X11 system, and this permission cannot be delegated to a test. m_addExports.invoke(null, "sun.awt.X11", Util.class.getModule()); Method m_getWMID = (Method)AccessController.doPrivileged(new PrivilegedAction() { -- GitLab From 77757ba974239b558e29c7adc551dfa04b9baa48 Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Sat, 8 Jan 2022 01:03:34 +0000 Subject: [PATCH 029/564] 8225122: Test AncestorResized.java fails when Windows desktop is scaled. Reviewed-by: kizune, aivanov --- .../AncestorResized/AncestorResized.java | 229 +++--------------- 1 file changed, 28 insertions(+), 201 deletions(-) diff --git a/test/jdk/java/awt/event/HierarchyEvent/AncestorResized/AncestorResized.java b/test/jdk/java/awt/event/HierarchyEvent/AncestorResized/AncestorResized.java index dafa0ead939..156f3f75db5 100644 --- a/test/jdk/java/awt/event/HierarchyEvent/AncestorResized/AncestorResized.java +++ b/test/jdk/java/awt/event/HierarchyEvent/AncestorResized/AncestorResized.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,37 +21,30 @@ * questions. */ -/* - @test - @key headful - @bug 6533330 - @summary ANCESTOR_RESIZED is not sent while resizing a frame. Regression caused by 6500477. - @author anthony.petrov: area=awt.toplevel - @library ../../../regtesthelpers - @build Util - @run main AncestorResized -*/ - +import java.awt.Button; +import java.awt.Component; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.Insets; +import java.awt.Label; +import java.awt.Panel; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.event.HierarchyBoundsListener; +import java.awt.event.HierarchyEvent; +import java.awt.event.InputEvent; /** - * AncestorResized.java - * - * summary: After fixing the 6500477, the ANCESTOR_RESIZED event stoped - * firing while resizing a frame. This was a regression. - * The test checks whether the event starts dispatching as it - * was before fixing the 6500477. + * @test + * @key headful + * @bug 6533330 + * @summary ANCESTOR_RESIZED is not sent while resizing a frame. Regression + * caused by 6500477. */ +public class AncestorResized { -import java.awt.*; -import java.awt.event.*; -import test.java.awt.regtesthelpers.Util; - - -public class AncestorResized -{ public static volatile int ancestorResizedCounter = 0; - static class HierarchyBoundsListenerImpl implements HierarchyBoundsListener { public void ancestorMoved(HierarchyEvent ce) { // ANCESTOR_MOVED seems to work OK. @@ -61,8 +54,7 @@ public class AncestorResized } } - private static void init() - { + public static void main(String[] args) throws Exception { Frame frame; Panel panel; Button button; @@ -83,17 +75,17 @@ public class AncestorResized frame.setSize(300, 300); frame.setVisible(true); - Robot robot = Util.createRobot(); - robot.setAutoDelay(20); + Robot robot = new Robot(); + robot.setAutoDelay(50); // To ensure the window is shown and packed - Util.waitForIdle(robot); + robot.waitForIdle(); Insets insets = frame.getInsets(); if (insets.right == 0 || insets.bottom == 0) { + frame.dispose(); // Because we want to catch the "size-grip" of the frame. System.out.println("The test environment must have non-zero right & bottom insets! The current insets are: " + insets); - pass(); return; } @@ -112,177 +104,12 @@ public class AncestorResized // ... and start resizing robot.mousePress( InputEvent.BUTTON1_MASK ); robot.mouseMove(bounds.x + bounds.width + 20, bounds.y + bounds.height + 15); - Util.waitForIdle(robot); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + robot.waitForIdle(); + frame.dispose(); if (ancestorResizedCounter == 0) { - robot.mouseRelease( InputEvent.BUTTON1_MASK ); - AncestorResized.fail("No ANCESTOR_RESIZED events received."); - return; - } - - robot.mouseRelease( InputEvent.BUTTON1_MASK ); - - AncestorResized.pass(); - }//End init() - - - - /***************************************************** - * Standard Test Machinery Section - * DO NOT modify anything in this section -- it's a - * standard chunk of code which has all of the - * synchronisation necessary for the test harness. - * By keeping it the same in all tests, it is easier - * to read and understand someone else's test, as - * well as insuring that all tests behave correctly - * with the test harness. - * There is a section following this for test- - * classes - ******************************************************/ - private static boolean theTestPassed = false; - private static boolean testGeneratedInterrupt = false; - private static String failureMessage = ""; - - private static Thread mainThread = null; - - private static int sleepTime = 300000; - - // Not sure about what happens if multiple of this test are - // instantiated in the same VM. Being static (and using - // static vars), it aint gonna work. Not worrying about - // it for now. - public static void main( String args[] ) throws InterruptedException - { - mainThread = Thread.currentThread(); - try - { - init(); - } - catch( TestPassedException e ) - { - //The test passed, so just return from main and harness will - // interepret this return as a pass - return; + throw new RuntimeException("No ANCESTOR_RESIZED events received."); } - //At this point, neither test pass nor test fail has been - // called -- either would have thrown an exception and ended the - // test, so we know we have multiple threads. - - //Test involves other threads, so sleep and wait for them to - // called pass() or fail() - try - { - Thread.sleep( sleepTime ); - //Timed out, so fail the test - throw new RuntimeException( "Timed out after " + sleepTime/1000 + " seconds" ); - } - catch (InterruptedException e) - { - //The test harness may have interrupted the test. If so, rethrow the exception - // so that the harness gets it and deals with it. - if( ! testGeneratedInterrupt ) throw e; - - //reset flag in case hit this code more than once for some reason (just safety) - testGeneratedInterrupt = false; - - if ( theTestPassed == false ) - { - throw new RuntimeException( failureMessage ); - } - } - - }//main - - public static synchronized void setTimeoutTo( int seconds ) - { - sleepTime = seconds * 1000; - } - - public static synchronized void pass() - { - System.out.println( "The test passed." ); - System.out.println( "The test is over, hit Ctl-C to stop Java VM" ); - //first check if this is executing in main thread - if ( mainThread == Thread.currentThread() ) - { - //Still in the main thread, so set the flag just for kicks, - // and throw a test passed exception which will be caught - // and end the test. - theTestPassed = true; - throw new TestPassedException(); - } - theTestPassed = true; - testGeneratedInterrupt = true; - mainThread.interrupt(); - }//pass() - - public static synchronized void fail() - { - //test writer didn't specify why test failed, so give generic - fail( "it just plain failed! :-)" ); } - - public static synchronized void fail( String whyFailed ) - { - System.out.println( "The test failed: " + whyFailed ); - System.out.println( "The test is over, hit Ctl-C to stop Java VM" ); - //check if this called from main thread - if ( mainThread == Thread.currentThread() ) - { - //If main thread, fail now 'cause not sleeping - throw new RuntimeException( whyFailed ); - } - theTestPassed = false; - testGeneratedInterrupt = true; - failureMessage = whyFailed; - mainThread.interrupt(); - }//fail() - -}// class AncestorResized - -//This exception is used to exit from any level of call nesting -// when it's determined that the test has passed, and immediately -// end the test. -class TestPassedException extends RuntimeException -{ } - -//*********** End Standard Test Machinery Section ********** - - -//************ Begin classes defined for the test **************** - -// if want to make listeners, here is the recommended place for them, then instantiate -// them in init() - -/* Example of a class which may be written as part of a test -class NewClass implements anInterface - { - static int newVar = 0; - - public void eventDispatched(AWTEvent e) - { - //Counting events to see if we get enough - eventCount++; - - if( eventCount == 20 ) - { - //got enough events, so pass - - AncestorResized.pass(); - } - else if( tries == 20 ) - { - //tried too many times without getting enough events so fail - - AncestorResized.fail(); - } - - }// eventDispatched() - - }// NewClass class - -*/ - - -//************** End classes defined for the test ******************* -- GitLab From e14fb4f4aa9c4569615005e474f897c54094f024 Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Sat, 8 Jan 2022 21:47:54 +0000 Subject: [PATCH 030/564] 8279437: [JVMCI] exception in HotSpotJVMCIRuntime.translate can exit the VM Reviewed-by: kvn --- src/hotspot/share/jvmci/jvmciCompilerToVM.cpp | 17 +- src/hotspot/share/jvmci/jvmciEnv.cpp | 173 ++++++++++++++--- src/hotspot/share/jvmci/jvmciEnv.hpp | 23 ++- src/hotspot/share/jvmci/jvmciJavaClasses.cpp | 2 +- src/hotspot/share/jvmci/jvmciJavaClasses.hpp | 5 +- src/hotspot/share/jvmci/vmSymbols_jvmci.hpp | 8 +- .../src/jdk/vm/ci/hotspot/CompilerToVM.java | 4 +- .../vm/ci/hotspot/HotSpotJVMCIRuntime.java | 130 ++++++++++++- .../vm/ci/hotspot/TranslatedException.java | 180 ++++++++++-------- .../hotspot/test/TestTranslatedException.java | 51 ++++- 10 files changed, 460 insertions(+), 133 deletions(-) diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index 4368e1fb536..6f7269193f6 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2022, 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 @@ -2376,7 +2376,7 @@ C2V_VMENTRY_PREFIX(void, detachCurrentThread, (JNIEnv* env, jobject c2vm)) } C2V_END -C2V_VMENTRY_0(jlong, translate, (JNIEnv* env, jobject, jobject obj_handle)) +C2V_VMENTRY_0(jlong, translate, (JNIEnv* env, jobject, jobject obj_handle, jboolean callPostTranslation)) requireJVMCINativeLibrary(JVMCI_CHECK_0); if (obj_handle == NULL) { return 0L; @@ -2427,7 +2427,9 @@ C2V_VMENTRY_0(jlong, translate, (JNIEnv* env, jobject, jobject obj_handle)) const char* cstring = name_string.is_null() ? NULL : thisEnv->as_utf8_string(name_string); // Create a new HotSpotNmethod instance in the peer runtime result = peerEnv->new_HotSpotNmethod(mh, cstring, isDefault, compileIdSnapshot, JVMCI_CHECK_0); - if (nm == NULL) { + if (result.is_null()) { + // exception occurred (e.g. OOME) creating a new HotSpotNmethod + } else if (nm == NULL) { // nmethod must have been unloaded } else { // Link the new HotSpotNmethod to the nmethod @@ -2450,6 +2452,13 @@ C2V_VMENTRY_0(jlong, translate, (JNIEnv* env, jobject, jobject obj_handle)) JVMCI_THROW_MSG_0(IllegalArgumentException, err_msg("Cannot translate object of type: %s", thisEnv->klass_name(obj))); } + if (callPostTranslation) { + peerEnv->call_HotSpotJVMCIRuntime_postTranslation(result, JVMCI_CHECK_0); + } + // Propagate any exception that occurred while creating the translated object + if (peerEnv->transfer_pending_exception(thread, thisEnv)) { + return 0L; + } return (jlong) peerEnv->make_global(result).as_jobject(); } @@ -2790,7 +2799,7 @@ JNINativeMethod CompilerToVM::methods[] = { {CC "getCurrentJavaThread", CC "()J", FN_PTR(getCurrentJavaThread)}, {CC "attachCurrentThread", CC "([BZ)Z", FN_PTR(attachCurrentThread)}, {CC "detachCurrentThread", CC "()V", FN_PTR(detachCurrentThread)}, - {CC "translate", CC "(" OBJECT ")J", FN_PTR(translate)}, + {CC "translate", CC "(" OBJECT "Z)J", FN_PTR(translate)}, {CC "unhand", CC "(J)" OBJECT, FN_PTR(unhand)}, {CC "updateHotSpotNmethod", CC "(" HS_NMETHOD ")V", FN_PTR(updateHotSpotNmethod)}, {CC "getCode", CC "(" HS_INSTALLED_CODE ")[B", FN_PTR(getCode)}, diff --git a/src/hotspot/share/jvmci/jvmciEnv.cpp b/src/hotspot/share/jvmci/jvmciEnv.cpp index aaebf8dc111..aa4989acf28 100644 --- a/src/hotspot/share/jvmci/jvmciEnv.cpp +++ b/src/hotspot/share/jvmci/jvmciEnv.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2022, 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,35 +278,141 @@ void JVMCIEnv::describe_pending_exception(bool clear) { } } -void JVMCIEnv::translate_hotspot_exception_to_jni_exception(JavaThread* THREAD, const Handle& throwable) { - assert(!is_hotspot(), "must_be"); - // Resolve HotSpotJVMCIRuntime class explicitly as HotSpotJVMCI::compute_offsets - // may not have been called. - Klass* runtimeKlass = SystemDictionary::resolve_or_fail(vmSymbols::jdk_vm_ci_hotspot_HotSpotJVMCIRuntime(), true, CHECK); - JavaCallArguments jargs; - jargs.push_oop(throwable); - JavaValue result(T_OBJECT); - JavaCalls::call_static(&result, - runtimeKlass, - vmSymbols::encodeThrowable_name(), - vmSymbols::encodeThrowable_signature(), &jargs, THREAD); - if (HAS_PENDING_EXCEPTION) { - JVMCIRuntime::fatal_exception(this, "HotSpotJVMCIRuntime.encodeThrowable should not throw an exception"); +// Shared code for translating an exception from HotSpot to libjvmci or vice versa. +class ExceptionTranslation: public StackObj { + protected: + JVMCIEnv* _from_env; // Source of translation. Can be nullptr. + JVMCIEnv* _to_env; // Destination of translation. Never nullptr. + + ExceptionTranslation(JVMCIEnv* from_env, JVMCIEnv* to_env) : _from_env(from_env), _to_env(to_env) {} + + // Encodes the exception in `_from_env` into `buffer`. + // Where N is the number of bytes needed for the encoding, returns N if N <= `buffer_size` + // and the encoding was written to `buffer` otherwise returns -N. + virtual int encode(JavaThread* THREAD, Klass* runtimeKlass, jlong buffer, int buffer_size) = 0; + + // Decodes the exception in `buffer` in `_to_env` and throws it. + virtual void decode(JavaThread* THREAD, Klass* runtimeKlass, jlong buffer) = 0; + + public: + void doit(JavaThread* THREAD) { + // Resolve HotSpotJVMCIRuntime class explicitly as HotSpotJVMCI::compute_offsets + // may not have been called. + Klass* runtimeKlass = SystemDictionary::resolve_or_fail(vmSymbols::jdk_vm_ci_hotspot_HotSpotJVMCIRuntime(), true, CHECK); + + int buffer_size = 2048; + while (true) { + ResourceMark rm; + jlong buffer = (jlong) NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, jbyte, buffer_size); + int res = encode(THREAD, runtimeKlass, buffer, buffer_size); + if ((_from_env != nullptr && _from_env->has_pending_exception()) || HAS_PENDING_EXCEPTION) { + JVMCIRuntime::fatal_exception(_from_env, "HotSpotJVMCIRuntime.encodeThrowable should not throw an exception"); + } + if (res < 0) { + int required_buffer_size = -res; + if (required_buffer_size > buffer_size) { + buffer_size = required_buffer_size; + } + } else { + decode(THREAD, runtimeKlass, buffer); + if (!_to_env->has_pending_exception()) { + JVMCIRuntime::fatal_exception(_to_env, "HotSpotJVMCIRuntime.decodeAndThrowThrowable should throw an exception"); + } + return; + } + } } +}; - oop encoded_throwable_string = result.get_oop(); +// Translates an exception on the HotSpot heap to an exception on the shared library heap. +class HotSpotToSharedLibraryExceptionTranslation : public ExceptionTranslation { + private: + const Handle& _throwable; - ResourceMark rm; - const char* encoded_throwable_chars = java_lang_String::as_utf8_string(encoded_throwable_string); + int encode(JavaThread* THREAD, Klass* runtimeKlass, jlong buffer, int buffer_size) { + JavaCallArguments jargs; + jargs.push_oop(_throwable); + jargs.push_long(buffer); + jargs.push_int(buffer_size); + JavaValue result(T_INT); + JavaCalls::call_static(&result, + runtimeKlass, + vmSymbols::encodeThrowable_name(), + vmSymbols::encodeThrowable_signature(), &jargs, THREAD); + return result.get_jint(); + } - JNIAccessMark jni(this, THREAD); - jobject jni_encoded_throwable_string = jni()->NewStringUTF(encoded_throwable_chars); - jthrowable jni_throwable = (jthrowable) jni()->CallStaticObjectMethod(JNIJVMCI::HotSpotJVMCIRuntime::clazz(), - JNIJVMCI::HotSpotJVMCIRuntime::decodeThrowable_method(), - jni_encoded_throwable_string); - jni()->Throw(jni_throwable); + void decode(JavaThread* THREAD, Klass* runtimeKlass, jlong buffer) { + JNIAccessMark jni(_to_env, THREAD); + jni()->CallStaticVoidMethod(JNIJVMCI::HotSpotJVMCIRuntime::clazz(), + JNIJVMCI::HotSpotJVMCIRuntime::decodeAndThrowThrowable_method(), + buffer); + } + public: + HotSpotToSharedLibraryExceptionTranslation(JVMCIEnv* hotspot_env, JVMCIEnv* jni_env, const Handle& throwable) : + ExceptionTranslation(hotspot_env, jni_env), _throwable(throwable) {} +}; + +// Translates an exception on the shared library heap to an exception on the HotSpot heap. +class SharedLibraryToHotSpotExceptionTranslation : public ExceptionTranslation { + private: + jthrowable _throwable; + + int encode(JavaThread* THREAD, Klass* runtimeKlass, jlong buffer, int buffer_size) { + JNIAccessMark jni(_from_env, THREAD); + return jni()->CallStaticIntMethod(JNIJVMCI::HotSpotJVMCIRuntime::clazz(), + JNIJVMCI::HotSpotJVMCIRuntime::encodeThrowable_method(), + _throwable, buffer, buffer_size); + } + + void decode(JavaThread* THREAD, Klass* runtimeKlass, jlong buffer) { + JavaCallArguments jargs; + jargs.push_long(buffer); + JavaValue result(T_VOID); + JavaCalls::call_static(&result, + runtimeKlass, + vmSymbols::decodeAndThrowThrowable_name(), + vmSymbols::long_void_signature(), &jargs, THREAD); + } + public: + SharedLibraryToHotSpotExceptionTranslation(JVMCIEnv* hotspot_env, JVMCIEnv* jni_env, jthrowable throwable) : + ExceptionTranslation(jni_env, hotspot_env), _throwable(throwable) {} +}; + +void JVMCIEnv::translate_to_jni_exception(JavaThread* THREAD, const Handle& throwable, JVMCIEnv* hotspot_env, JVMCIEnv* jni_env) { + HotSpotToSharedLibraryExceptionTranslation(hotspot_env, jni_env, throwable).doit(THREAD); } +void JVMCIEnv::translate_from_jni_exception(JavaThread* THREAD, jthrowable throwable, JVMCIEnv* hotspot_env, JVMCIEnv* jni_env) { + SharedLibraryToHotSpotExceptionTranslation(hotspot_env, jni_env, throwable).doit(THREAD); +} + +jboolean JVMCIEnv::transfer_pending_exception(JavaThread* THREAD, JVMCIEnv* peer_env) { + if (is_hotspot()) { + if (HAS_PENDING_EXCEPTION) { + Handle throwable = Handle(THREAD, PENDING_EXCEPTION); + CLEAR_PENDING_EXCEPTION; + translate_to_jni_exception(THREAD, throwable, this, peer_env); + return true; + } + } else { + jthrowable ex = nullptr; + { + JNIAccessMark jni(this, THREAD); + ex = jni()->ExceptionOccurred(); + if (ex != nullptr) { + jni()->ExceptionClear(); + } + } + if (ex != nullptr) { + translate_from_jni_exception(THREAD, ex, peer_env, this); + return true; + } + } + return false; +} + + JVMCIEnv::~JVMCIEnv() { if (_throw_to_caller) { if (is_hotspot()) { @@ -318,7 +424,7 @@ JVMCIEnv::~JVMCIEnv() { if (HAS_PENDING_EXCEPTION) { Handle throwable = Handle(THREAD, PENDING_EXCEPTION); CLEAR_PENDING_EXCEPTION; - translate_hotspot_exception_to_jni_exception(THREAD, throwable); + translate_to_jni_exception(THREAD, throwable, nullptr, this); } } } @@ -801,6 +907,23 @@ JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_callToString(JVMCIObject object, } } +void JVMCIEnv::call_HotSpotJVMCIRuntime_postTranslation(JVMCIObject object, JVMCIEnv* JVMCIENV) { + JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); // For exception macros. + if (is_hotspot()) { + JavaCallArguments jargs; + jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(object))); + JavaValue result(T_VOID); + JavaCalls::call_static(&result, + HotSpotJVMCI::HotSpotJVMCIRuntime::klass(), + vmSymbols::postTranslation_name(), + vmSymbols::object_void_signature(), &jargs, CHECK); + } else { + JNIAccessMark jni(this, THREAD); + jni()->CallStaticVoidMethod(JNIJVMCI::HotSpotJVMCIRuntime::clazz(), + JNIJVMCI::HotSpotJVMCIRuntime::postTranslation_method(), + object.as_jobject()); + } +} JVMCIObject JVMCIEnv::call_JavaConstant_forPrimitive(JVMCIObject kind, jlong value, JVMCI_TRAPS) { JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); // For exception macros. diff --git a/src/hotspot/share/jvmci/jvmciEnv.hpp b/src/hotspot/share/jvmci/jvmciEnv.hpp index 521da004b7c..18a80accd8b 100644 --- a/src/hotspot/share/jvmci/jvmciEnv.hpp +++ b/src/hotspot/share/jvmci/jvmciEnv.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2022, 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 @@ -171,11 +171,15 @@ class JVMCIEnv : public ResourceObj { const char* _file; // The file and ... int _line; // ... line where this JNIEnv was created - // Translates an exception on the HotSpot heap to an exception on - // the shared library heap. The translation includes the stack and - // causes of `throwable`. The translated exception is pending in the - // shared library thread upon returning. - void translate_hotspot_exception_to_jni_exception(JavaThread* THREAD, const Handle& throwable); + // Translates an exception on the HotSpot heap (i.e., hotspot_env) to an exception on + // the shared library heap (i.e., jni_env). The translation includes the stack and cause(s) of `throwable`. + // The translated exception is pending in jni_env upon returning. + static void translate_to_jni_exception(JavaThread* THREAD, const Handle& throwable, JVMCIEnv* hotspot_env, JVMCIEnv* jni_env); + + // Translates an exception on the shared library heap (i.e., jni_env) to an exception on + // the HotSpot heap (i.e., hotspot_env). The translation includes the stack and cause(s) of `throwable`. + // The translated exception is pending in hotspot_env upon returning. + static void translate_from_jni_exception(JavaThread* THREAD, jthrowable throwable, JVMCIEnv* hotspot_env, JVMCIEnv* jni_env); public: // Opens a JVMCIEnv scope for a Java to VM call (e.g., via CompilerToVM). @@ -225,6 +229,11 @@ public: jboolean has_pending_exception(); void clear_pending_exception(); + // If this env has a pending exception, it is translated to be a pending + // exception in `peer_env` and is cleared from this env. Returns true + // if a pending exception was transferred, false otherwise. + jboolean transfer_pending_exception(JavaThread* THREAD, JVMCIEnv* peer_env); + // Prints an exception and stack trace of a pending exception. void describe_pending_exception(bool clear); @@ -311,6 +320,8 @@ public: jboolean call_HotSpotJVMCIRuntime_isGCSupported(JVMCIObject runtime, jint gcIdentifier); + void call_HotSpotJVMCIRuntime_postTranslation(JVMCIObject object, JVMCI_TRAPS); + BasicType kindToBasicType(JVMCIObject kind, JVMCI_TRAPS); #define DO_THROW(name) \ diff --git a/src/hotspot/share/jvmci/jvmciJavaClasses.cpp b/src/hotspot/share/jvmci/jvmciJavaClasses.cpp index 32b1fdfcaab..286751b14c0 100644 --- a/src/hotspot/share/jvmci/jvmciJavaClasses.cpp +++ b/src/hotspot/share/jvmci/jvmciJavaClasses.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2022, 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 diff --git a/src/hotspot/share/jvmci/jvmciJavaClasses.hpp b/src/hotspot/share/jvmci/jvmciJavaClasses.hpp index bb951be4b19..eb21225335e 100644 --- a/src/hotspot/share/jvmci/jvmciJavaClasses.hpp +++ b/src/hotspot/share/jvmci/jvmciJavaClasses.hpp @@ -349,13 +349,14 @@ objectarray_field(HotSpotJVMCIRuntime, excludeFromJVMCICompilation, "[Ljava/lang/Module;") \ jvmci_method(CallNonvirtualObjectMethod, GetMethodID, call_special, JVMCIObject, HotSpotJVMCIRuntime, compileMethod, compileMethod_signature, (JVMCIObject runtime, JVMCIObject method, int entry_bci, jlong env, int id)) \ jvmci_method(CallNonvirtualObjectMethod, GetMethodID, call_special, JVMCIObject, HotSpotJVMCIRuntime, isGCSupported, int_bool_signature, (JVMCIObject runtime, int gcIdentifier)) \ - jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, HotSpotJVMCIRuntime, encodeThrowable, encodeThrowable_signature, (JVMCIObject throwable)) \ - jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, HotSpotJVMCIRuntime, decodeThrowable, decodeThrowable_signature, (JVMCIObject encodedThrowable)) \ + jvmci_method(CallStaticBooleanMethod, GetStaticMethodID, call_static, bool, HotSpotJVMCIRuntime, encodeThrowable, encodeThrowable_signature, (JVMCIObject throwable, jlong buffer, int buffer_size)) \ + jvmci_method(CallStaticVoidMethod, GetStaticMethodID, call_static, void, HotSpotJVMCIRuntime, decodeAndThrowThrowable, long_void_signature, (jlong buffer)) \ jvmci_method(CallNonvirtualVoidMethod, GetMethodID, call_special, void, HotSpotJVMCIRuntime, bootstrapFinished, void_method_signature, (JVMCIObject runtime, JVMCI_TRAPS)) \ jvmci_method(CallNonvirtualVoidMethod, GetMethodID, call_special, void, HotSpotJVMCIRuntime, shutdown, void_method_signature, (JVMCIObject runtime)) \ jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, HotSpotJVMCIRuntime, runtime, runtime_signature, (JVMCI_TRAPS)) \ jvmci_method(CallObjectMethod, GetMethodID, call_virtual, JVMCIObject, HotSpotJVMCIRuntime, getCompiler, getCompiler_signature, (JVMCIObject runtime, JVMCI_TRAPS)) \ jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, HotSpotJVMCIRuntime, callToString, callToString_signature, (JVMCIObject object, JVMCI_TRAPS)) \ + jvmci_method(CallStaticVoidMethod, GetStaticMethodID, call_static, void, HotSpotJVMCIRuntime, postTranslation, object_void_signature, (JVMCIObject object, JVMCI_TRAPS)) \ end_class \ start_class(JVMCIError, jdk_vm_ci_common_JVMCIError) \ jvmci_constructor(JVMCIError, "(Ljava/lang/String;)V") \ diff --git a/src/hotspot/share/jvmci/vmSymbols_jvmci.hpp b/src/hotspot/share/jvmci/vmSymbols_jvmci.hpp index 5db71140976..f88f65bf69d 100644 --- a/src/hotspot/share/jvmci/vmSymbols_jvmci.hpp +++ b/src/hotspot/share/jvmci/vmSymbols_jvmci.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -105,9 +105,8 @@ template(compileMethod_signature, "(Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethod;IJI)Ljdk/vm/ci/hotspot/HotSpotCompilationRequestResult;") \ template(isGCSupported_name, "isGCSupported") \ template(encodeThrowable_name, "encodeThrowable") \ - template(encodeThrowable_signature, "(Ljava/lang/Throwable;)Ljava/lang/String;") \ - template(decodeThrowable_name, "decodeThrowable") \ - template(decodeThrowable_signature, "(Ljava/lang/String;)Ljava/lang/Throwable;") \ + template(encodeThrowable_signature, "(Ljava/lang/Throwable;JI)I") \ + template(decodeAndThrowThrowable_name, "decodeAndThrowThrowable") \ template(fromMetaspace_name, "fromMetaspace") \ template(method_fromMetaspace_signature, "(J)Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethod;") \ template(constantPool_fromMetaspace_signature, "(J)Ljdk/vm/ci/hotspot/HotSpotConstantPool;") \ @@ -123,6 +122,7 @@ template(getCompiler_signature, "()Ljdk/vm/ci/runtime/JVMCICompiler;") \ template(callToString_name, "callToString") \ template(callToString_signature, "(Ljava/lang/Object;)Ljava/lang/String;") \ + template(postTranslation_name, "postTranslation") \ template(getName_name, "getName") \ template(bootstrapFinished_name, "bootstrapFinished") \ template(forPrimitive_name, "forPrimitive") \ diff --git a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java index 50f35021ac8..2c9097839b6 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2022, 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 @@ -849,7 +849,7 @@ final class CompilerToVM { /** * @see HotSpotJVMCIRuntime#translate(Object) */ - native long translate(Object obj); + native long translate(Object obj, boolean callPostTranslation); /** * @see HotSpotJVMCIRuntime#unhand(Class, long) diff --git a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java index c7bfc83401c..b15035dd5cc 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, 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 @@ -46,6 +46,8 @@ import java.util.Map; import java.util.Objects; import java.util.ServiceLoader; import java.util.function.Predicate; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import jdk.internal.misc.Unsafe; import jdk.vm.ci.code.Architecture; @@ -66,6 +68,7 @@ import jdk.vm.ci.runtime.JVMCICompiler; import jdk.vm.ci.runtime.JVMCICompilerFactory; import jdk.vm.ci.runtime.JVMCIRuntime; import jdk.vm.ci.services.JVMCIServiceLocator; +import jdk.vm.ci.services.Services; /** * HotSpot implementation of a JVMCI runtime. @@ -199,14 +202,44 @@ public final class HotSpotJVMCIRuntime implements JVMCIRuntime { return result; } + /** + * Decodes the exception encoded in {@code buffer} and throws it. + * + * @param buffer a native byte buffer containing an exception encoded by + * {@link #encodeThrowable} + */ @VMEntryPoint - static Throwable decodeThrowable(String encodedThrowable) throws Throwable { - return TranslatedException.decodeThrowable(encodedThrowable); + static void decodeAndThrowThrowable(long buffer) throws Throwable { + Unsafe unsafe = UnsafeAccess.UNSAFE; + int encodingLength = unsafe.getInt(buffer); + byte[] encoding = new byte[encodingLength]; + unsafe.copyMemory(null, buffer + 4, encoding, Unsafe.ARRAY_BYTE_BASE_OFFSET, encodingLength); + throw TranslatedException.decodeThrowable(encoding); } + /** + * If {@code bufferSize} is large enough, encodes {@code throwable} into a byte array and writes + * it to {@code buffer}. The encoding in {@code buffer} can be decoded by + * {@link #decodeAndThrowThrowable}. + * + * @param throwable the exception to encode + * @param buffer a native byte buffer + * @param bufferSize the size of {@code buffer} in bytes + * @return the number of bytes written into {@code buffer} if {@code bufferSize} is large + * enough, otherwise {@code -N} where {@code N} is the value {@code bufferSize} needs to + * be to fit the encoding + */ @VMEntryPoint - static String encodeThrowable(Throwable throwable) throws Throwable { - return TranslatedException.encodeThrowable(throwable); + static int encodeThrowable(Throwable throwable, long buffer, int bufferSize) throws Throwable { + byte[] encoding = TranslatedException.encodeThrowable(throwable); + int requiredSize = 4 + encoding.length; + if (bufferSize < requiredSize) { + return -requiredSize; + } + Unsafe unsafe = UnsafeAccess.UNSAFE; + unsafe.putInt(buffer, encoding.length); + unsafe.copyMemory(encoding, Unsafe.ARRAY_BYTE_BASE_OFFSET, null, buffer + 4, encoding.length); + return requiredSize; } @VMEntryPoint @@ -235,6 +268,10 @@ public final class HotSpotJVMCIRuntime implements JVMCIRuntime { // Note: The following one is not used (see InitTimer.ENABLED). It is added here // so that -XX:+JVMCIPrintProperties shows the option. InitTimer(Boolean.class, false, "Specifies if initialization timing is enabled."), + ForceTranslateFailure(String.class, null, "Forces HotSpotJVMCIRuntime.translate to throw an exception in the context " + + "of the peer runtime. The value is a filter that can restrict the forced failure to matching translated " + + "objects. See HotSpotJVMCIRuntime.postTranslation for more details. This option exists soley to test " + + "correct handling of translation failure."), PrintConfig(Boolean.class, false, "Prints VM configuration available via JVMCI."), AuditHandles(Boolean.class, false, "Record stack trace along with scoped foreign object reference wrappers " + "to debug issue with a wrapper being used after its scope has closed."), @@ -1180,7 +1217,88 @@ public final class HotSpotJVMCIRuntime implements JVMCIRuntime { * @see "https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/design.html#global_and_local_references" */ public long translate(Object obj) { - return compilerToVm.translate(obj); + return compilerToVm.translate(obj, Option.ForceTranslateFailure.getString() != null); + } + + private static final Pattern FORCE_TRANSLATE_FAILURE_FILTER_RE = Pattern.compile("(?:(method|type|nmethod)/)?([^:]+)(?::(hotspot|native))?"); + + /** + * Forces translation failure based on {@code translatedObject} and the value of + * {@link Option#ForceTranslateFailure}. The value is zero or more filters separated by a comma. + * The syntax for a filter is: + * + *
+     *   Filter = [ TypeSelector "/" ] Substring [ ":" JVMCIEnvSelector ] .
+     *   TypeSelector = "type" | "method" | "nmethod"
+     *   JVMCIEnvSelector = "native" | "hotspot"
+     * 
+ * + * For example: + * + *
+     *   -Djvmci.ForceTranslateFailure=nmethod/StackOverflowError:native,method/computeHash,execute
+     * 
+ * + * will cause failure of: + *
    + *
  • translating a {@link HotSpotNmethod} to the libjvmci heap whose fully qualified name + * contains "StackOverflowError"
  • + *
  • translating a {@link HotSpotResolvedJavaMethodImpl} to the libjvmci or HotSpot heap whose + * fully qualified name contains "computeHash"
  • + *
  • translating a {@link HotSpotNmethod}, {@link HotSpotResolvedJavaMethodImpl} or + * {@link HotSpotResolvedObjectTypeImpl} to the libjvmci or HotSpot heap whose fully qualified + * name contains "execute"
  • + *
+ */ + @VMEntryPoint + static void postTranslation(Object translatedObject) { + String value = Option.ForceTranslateFailure.getString(); + String toMatch; + String type; + if (translatedObject instanceof HotSpotResolvedJavaMethodImpl) { + toMatch = ((HotSpotResolvedJavaMethodImpl) translatedObject).format("%H.%n"); + type = "method"; + } else if (translatedObject instanceof HotSpotResolvedObjectTypeImpl) { + toMatch = ((HotSpotResolvedObjectTypeImpl) translatedObject).toJavaName(); + type = "type"; + } else if (translatedObject instanceof HotSpotNmethod) { + HotSpotNmethod nmethod = (HotSpotNmethod) translatedObject; + if (nmethod.getMethod() != null) { + toMatch = nmethod.getMethod().format("%H.%n"); + } else { + toMatch = String.valueOf(nmethod.getName()); + } + type = "nmethod"; + } else { + return; + } + String[] filters = value.split(","); + for (String filter : filters) { + Matcher m = FORCE_TRANSLATE_FAILURE_FILTER_RE.matcher(filter); + if (!m.matches()) { + throw new JVMCIError(Option.ForceTranslateFailure + " filter does not match " + FORCE_TRANSLATE_FAILURE_FILTER_RE + ": " + filter); + } + String typeSelector = m.group(1); + String substring = m.group(2); + String jvmciEnvSelector = m.group(3); + if (jvmciEnvSelector != null) { + if (jvmciEnvSelector.equals("native")) { + if (!Services.IS_IN_NATIVE_IMAGE) { + continue; + } + } else { + if (Services.IS_IN_NATIVE_IMAGE) { + continue; + } + } + } + if (typeSelector != null && !typeSelector.equals(type)) { + continue; + } + if (toMatch.contains(substring)) { + throw new JVMCIError("translation of " + translatedObject + " failed due to matching " + Option.ForceTranslateFailure + " filter \"" + filter + "\""); + } + } } /** diff --git a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/TranslatedException.java b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/TranslatedException.java index a47735faf80..53f99733ba9 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/TranslatedException.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/TranslatedException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,13 +22,20 @@ */ package jdk.vm.ci.hotspot; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; -import java.util.Formatter; import java.util.List; -import java.util.Objects; +import java.util.zip.GZIPInputStream; +import java.util.zip.GZIPOutputStream; + +import jdk.vm.ci.common.JVMCIError; /** * Support for translating exceptions between different runtime heaps. @@ -36,6 +43,26 @@ import java.util.Objects; @SuppressWarnings("serial") final class TranslatedException extends Exception { + /** + * The value returned by {@link #encodeThrowable(Throwable)} when encoding fails due to an + * {@link OutOfMemoryError}. + */ + private static final byte[] FALLBACK_ENCODED_OUTOFMEMORYERROR_BYTES; + + /** + * The value returned by {@link #encodeThrowable(Throwable)} when encoding fails for any reason + * other than {@link OutOfMemoryError}. + */ + private static final byte[] FALLBACK_ENCODED_THROWABLE_BYTES; + static { + try { + FALLBACK_ENCODED_THROWABLE_BYTES = encodeThrowable(new TranslatedException("error during encoding", ""), false); + FALLBACK_ENCODED_OUTOFMEMORYERROR_BYTES = encodeThrowable(new OutOfMemoryError(), false); + } catch (IOException e) { + throw new JVMCIError(e); + } + } + /** * Class name of exception that could not be instantiated. */ @@ -110,83 +137,74 @@ final class TranslatedException extends Exception { } } - /** - * Encodes an exception message to distinguish a null message from an empty message. - * - * @return {@code value} with a space prepended iff {@code value != null} - */ - private static String encodeMessage(String value) { - return value != null ? ' ' + value : value; - } - - private static String decodeMessage(String value) { - if (value.length() == 0) { - return null; - } - return value.substring(1); + private static String emptyIfNull(String value) { + return value == null ? "" : value; } - private static String encodedString(String value) { - return Objects.toString(value, "").replace('|', '_'); + private static String emptyAsNull(String value) { + return value.isEmpty() ? null : value; } /** - * Encodes {@code throwable} including its stack and causes as a string. The encoding format of - * a single exception is: - * - *
-     *  '|'  '|'  '|' [  '|'  '|'  '|'  '|'  '|'  '|'  '|' ]*
-     * 
- * - * Each exception is encoded before the exception it causes. + * Encodes {@code throwable} including its stack and causes as a {@linkplain GZIPOutputStream + * compressed} byte array that can be decoded by {@link #decodeThrowable}. */ @VMEntryPoint - static String encodeThrowable(Throwable throwable) throws Throwable { + static byte[] encodeThrowable(Throwable throwable) throws Throwable { try { - Formatter enc = new Formatter(); + return encodeThrowable(throwable, true); + } catch (OutOfMemoryError e) { + return FALLBACK_ENCODED_OUTOFMEMORYERROR_BYTES; + } catch (Throwable e) { + return FALLBACK_ENCODED_THROWABLE_BYTES; + } + } + + private static byte[] encodeThrowable(Throwable throwable, boolean withCauseAndStack) throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try (DataOutputStream dos = new DataOutputStream(new GZIPOutputStream(baos))) { List throwables = new ArrayList<>(); for (Throwable current = throwable; current != null; current = current.getCause()) { throwables.add(current); + if (!withCauseAndStack) { + break; + } } // Encode from inner most cause outwards Collections.reverse(throwables); for (Throwable current : throwables) { - enc.format("%s|%s|", current.getClass().getName(), encodedString(encodeMessage(current.getMessage()))); - StackTraceElement[] stackTrace = current.getStackTrace(); + dos.writeUTF(current.getClass().getName()); + dos.writeUTF(emptyIfNull(current.getMessage())); + StackTraceElement[] stackTrace = withCauseAndStack ? current.getStackTrace() : null; if (stackTrace == null) { stackTrace = new StackTraceElement[0]; } - enc.format("%d|", stackTrace.length); + dos.writeInt(stackTrace.length); for (int i = 0; i < stackTrace.length; i++) { StackTraceElement frame = stackTrace[i]; if (frame != null) { - enc.format("%s|%s|%s|%s|%s|%s|%d|", encodedString(frame.getClassLoaderName()), - encodedString(frame.getModuleName()), encodedString(frame.getModuleVersion()), - frame.getClassName(), frame.getMethodName(), - encodedString(frame.getFileName()), frame.getLineNumber()); + dos.writeUTF(emptyIfNull(frame.getClassLoaderName())); + dos.writeUTF(emptyIfNull(frame.getModuleName())); + dos.writeUTF(emptyIfNull(frame.getModuleVersion())); + dos.writeUTF(emptyIfNull(frame.getClassName())); + dos.writeUTF(emptyIfNull(frame.getMethodName())); + dos.writeUTF(emptyIfNull(frame.getFileName())); + dos.writeInt(frame.getLineNumber()); } } } - return enc.toString(); - } catch (Throwable e) { - assert printStackTrace(e); - try { - return e.getClass().getName() + "|" + encodedString(e.getMessage()) + "|0|"; - } catch (Throwable e2) { - assert printStackTrace(e2); - return "java.lang.Throwable|too many errors during encoding|0|"; - } } + return baos.toByteArray(); } /** * Gets the stack of the current thread without the frames between this call and the one just - * below the frame of the first method in {@link CompilerToVM}. The chopped frames are specific - * to the implementation of {@link HotSpotJVMCIRuntime#decodeThrowable(String)}. + * below the frame of the first method in {@link CompilerToVM}. The chopped frames are for the + * VM call to {@link HotSpotJVMCIRuntime#decodeAndThrowThrowable}. */ - private static StackTraceElement[] getStackTraceSuffix() { + private static StackTraceElement[] getMyStackTrace() { StackTraceElement[] stack = new Exception().getStackTrace(); for (int i = 0; i < stack.length; i++) { StackTraceElement e = stack[i]; @@ -206,43 +224,47 @@ final class TranslatedException extends Exception { * {@link #encodeThrowable} */ @VMEntryPoint - static Throwable decodeThrowable(String encodedThrowable) { - try { - int i = 0; - String[] parts = encodedThrowable.split("\\|"); + static Throwable decodeThrowable(byte[] encodedThrowable) { + try (DataInputStream dis = new DataInputStream(new GZIPInputStream(new ByteArrayInputStream(encodedThrowable)))) { Throwable cause = null; Throwable throwable = null; - while (i != parts.length) { - String exceptionClassName = parts[i++]; - String exceptionMessage = decodeMessage(parts[i++]); + StackTraceElement[] myStack = getMyStackTrace(); + while (dis.available() != 0) { + String exceptionClassName = dis.readUTF(); + String exceptionMessage = emptyAsNull(dis.readUTF()); throwable = create(exceptionClassName, exceptionMessage, cause); - int stackTraceDepth = Integer.parseInt(parts[i++]); - - StackTraceElement[] suffix = getStackTraceSuffix(); - StackTraceElement[] stackTrace = new StackTraceElement[stackTraceDepth + suffix.length]; + int stackTraceDepth = dis.readInt(); + StackTraceElement[] stackTrace = new StackTraceElement[stackTraceDepth + myStack.length]; + int stackTraceIndex = 0; + int myStackIndex = 0; for (int j = 0; j < stackTraceDepth; j++) { - String classLoaderName = parts[i++]; - String moduleName = parts[i++]; - String moduleVersion = parts[i++]; - String className = parts[i++]; - String methodName = parts[i++]; - String fileName = parts[i++]; - int lineNumber = Integer.parseInt(parts[i++]); - if (classLoaderName.isEmpty()) { - classLoaderName = null; - } - if (moduleName.isEmpty()) { - moduleName = null; - } - if (moduleVersion.isEmpty()) { - moduleVersion = null; - } - if (fileName.isEmpty()) { - fileName = null; + String classLoaderName = emptyAsNull(dis.readUTF()); + String moduleName = emptyAsNull(dis.readUTF()); + String moduleVersion = emptyAsNull(dis.readUTF()); + String className = emptyAsNull(dis.readUTF()); + String methodName = emptyAsNull(dis.readUTF()); + String fileName = emptyAsNull(dis.readUTF()); + int lineNumber = dis.readInt(); + StackTraceElement ste = new StackTraceElement(classLoaderName, moduleName, moduleVersion, className, methodName, fileName, lineNumber); + + if (ste.isNativeMethod()) { + // Best effort attempt to weave stack traces from two heaps into + // a single stack trace using native method frames as stitching points. + // This is not 100% reliable as there's no guarantee that native method + // frames only exist for calls between HotSpot and libjvmci. + while (myStackIndex < myStack.length) { + StackTraceElement suffixSTE = myStack[myStackIndex++]; + if (suffixSTE.isNativeMethod()) { + break; + } + stackTrace[stackTraceIndex++] = suffixSTE; + } } - stackTrace[j] = new StackTraceElement(classLoaderName, moduleName, moduleVersion, className, methodName, fileName, lineNumber); + stackTrace[stackTraceIndex++] = ste; + } + while (myStackIndex < myStack.length) { + stackTrace[stackTraceIndex++] = myStack[myStackIndex++]; } - System.arraycopy(suffix, 0, stackTrace, stackTraceDepth, suffix.length); throwable.setStackTrace(stackTrace); cause = throwable; } diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/TestTranslatedException.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/TestTranslatedException.java index ac2c220adb5..57a505901a5 100644 --- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/TestTranslatedException.java +++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/TestTranslatedException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,8 @@ /* * @test * @requires vm.jvmci - * @modules jdk.internal.vm.ci/jdk.vm.ci.hotspot:open + * @modules jdk.internal.vm.ci/jdk.vm.ci.hotspot:+open + * java.base/jdk.internal.misc * @library /compiler/jvmci/jdk.vm.ci.hotspot.test/src * @run testng/othervm * -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -XX:-UseJVMCICompiler @@ -41,6 +42,9 @@ import java.lang.reflect.Method; import org.testng.Assert; import org.testng.annotations.Test; +import jdk.internal.misc.Unsafe; +import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; + public class TestTranslatedException { @SuppressWarnings("serial") public static class Untranslatable extends RuntimeException { @@ -56,7 +60,7 @@ public class TestTranslatedException { Class translatedExceptionClass = Class.forName("jdk.vm.ci.hotspot.TranslatedException"); Method encode = translatedExceptionClass.getDeclaredMethod("encodeThrowable", Throwable.class); - Method decode = translatedExceptionClass.getDeclaredMethod("decodeThrowable", String.class); + Method decode = translatedExceptionClass.getDeclaredMethod("decodeThrowable", byte[].class); encode.setAccessible(true); decode.setAccessible(true); @@ -64,11 +68,50 @@ public class TestTranslatedException { for (int i = 0; i < 10; i++) { throwable = new ExceptionInInitializerError(new InvocationTargetException(new RuntimeException(String.valueOf(i), throwable), "invoke")); } - String encoding = (String) encode.invoke(null, throwable); + byte[] encoding = (byte[]) encode.invoke(null, throwable); Throwable decoded = (Throwable) decode.invoke(null, encoding); assertThrowableEquals(throwable, decoded); } + @SuppressWarnings("unchecked") + @Test + public void encodeDecodeTest2() throws Exception { + Unsafe unsafe = Unsafe.getUnsafe(); + int bufferSize = 512; + long buffer = 0L; + while (true) { + buffer = unsafe.allocateMemory(bufferSize); + try { + Throwable throwable = new ExceptionInInitializerError(new InvocationTargetException(new Untranslatable("test exception", new NullPointerException()), "invoke")); + for (int i = 0; i < 10; i++) { + throwable = new ExceptionInInitializerError(new InvocationTargetException(new RuntimeException(String.valueOf(i), throwable), "invoke")); + } + + Method encode = HotSpotJVMCIRuntime.class.getDeclaredMethod("encodeThrowable", Throwable.class, long.class, int.class); + Method decode = HotSpotJVMCIRuntime.class.getDeclaredMethod("decodeAndThrowThrowable", long.class); + encode.setAccessible(true); + decode.setAccessible(true); + + int res = (Integer) encode.invoke(null, throwable, buffer, bufferSize); + + if (res < 0) { + bufferSize = -res; + } else { + try { + decode.invoke(null, buffer); + throw new AssertionError("expected decodeAndThrowThrowable to throw an exception"); + } catch (InvocationTargetException e) { + Throwable decoded = e.getCause(); + assertThrowableEquals(throwable, decoded); + } + return; + } + } finally { + unsafe.freeMemory(buffer); + } + } + } + private static void assertThrowableEquals(Throwable original, Throwable decoded) { try { Assert.assertEquals(original == null, decoded == null); -- GitLab From 8d1a1e83f40f7a147e033be6b2221c1bb1abd8ab Mon Sep 17 00:00:00 2001 From: Roland Westrelin Date: Mon, 10 Jan 2022 07:52:18 +0000 Subject: [PATCH 031/564] 8278228: C2: Improve identical back-to-back if elimination Reviewed-by: chagedorn, kvn --- src/hotspot/share/opto/loopPredicate.cpp | 2 +- src/hotspot/share/opto/loopTransform.cpp | 2 +- src/hotspot/share/opto/loopUnswitch.cpp | 4 +- src/hotspot/share/opto/loopnode.hpp | 9 +- src/hotspot/share/opto/loopopts.cpp | 153 +++++++++++++----- src/hotspot/share/opto/split_if.cpp | 48 +++--- .../c2/irTests/TestBackToBackIfs.java | 65 ++++++++ .../compiler/lib/ir_framework/IRNode.java | 1 + 8 files changed, 221 insertions(+), 63 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/c2/irTests/TestBackToBackIfs.java diff --git a/src/hotspot/share/opto/loopPredicate.cpp b/src/hotspot/share/opto/loopPredicate.cpp index c0396bbe95d..d190b3db759 100644 --- a/src/hotspot/share/opto/loopPredicate.cpp +++ b/src/hotspot/share/opto/loopPredicate.cpp @@ -1367,7 +1367,7 @@ bool PhaseIdealLoop::loop_predication_impl_helper(IdealLoopTree *loop, ProjNode* invar.map_ctrl(proj, new_predicate_proj); // so that invariance test can be appropriate // Eliminate the old If in the loop body - dominated_by( new_predicate_proj, iff, proj->_con != new_predicate_proj->_con ); + dominated_by( new_predicate_proj->as_IfProj(), iff, proj->_con != new_predicate_proj->_con ); C->set_major_progress(); return true; diff --git a/src/hotspot/share/opto/loopTransform.cpp b/src/hotspot/share/opto/loopTransform.cpp index 7663ce82c0d..36f9ce11f35 100644 --- a/src/hotspot/share/opto/loopTransform.cpp +++ b/src/hotspot/share/opto/loopTransform.cpp @@ -532,7 +532,7 @@ void PhaseIdealLoop::peeled_dom_test_elim(IdealLoopTree* loop, Node_List& old_ne if (n->is_If() && n->in(1) == test_cond) { // IfNode was dominated by version in peeled loop body progress = true; - dominated_by(old_new[prev->_idx], n); + dominated_by(old_new[prev->_idx]->as_IfProj(), n->as_If()); } } } diff --git a/src/hotspot/share/opto/loopUnswitch.cpp b/src/hotspot/share/opto/loopUnswitch.cpp index abdc7e66a49..a141b8e15aa 100644 --- a/src/hotspot/share/opto/loopUnswitch.cpp +++ b/src/hotspot/share/opto/loopUnswitch.cpp @@ -213,11 +213,11 @@ void PhaseIdealLoop::do_unswitching(IdealLoopTree *loop, Node_List &old_new) { // Hardwire the control paths in the loops into if(true) and if(false) _igvn.rehash_node_delayed(unswitch_iff); - dominated_by(proj_true, unswitch_iff, false, false); + dominated_by(proj_true->as_IfProj(), unswitch_iff, false, false); IfNode* unswitch_iff_clone = old_new[unswitch_iff->_idx]->as_If(); _igvn.rehash_node_delayed(unswitch_iff_clone); - dominated_by(proj_false, unswitch_iff_clone, false, false); + dominated_by(proj_false->as_IfProj(), unswitch_iff_clone, false, false); // Reoptimize loops loop->record_for_igvn(); diff --git a/src/hotspot/share/opto/loopnode.hpp b/src/hotspot/share/opto/loopnode.hpp index 18145a51839..533c93d30d5 100644 --- a/src/hotspot/share/opto/loopnode.hpp +++ b/src/hotspot/share/opto/loopnode.hpp @@ -1471,15 +1471,15 @@ public: Node *has_local_phi_input( Node *n ); // Mark an IfNode as being dominated by a prior test, // without actually altering the CFG (and hence IDOM info). - void dominated_by( Node *prevdom, Node *iff, bool flip = false, bool exclude_loop_predicate = false ); + void dominated_by(IfProjNode* prevdom, IfNode* iff, bool flip = false, bool exclude_loop_predicate = false); // Split Node 'n' through merge point - Node *split_thru_region( Node *n, Node *region ); + RegionNode* split_thru_region(Node* n, RegionNode* region); // Split Node 'n' through merge point if there is enough win. Node *split_thru_phi( Node *n, Node *region, int policy ); // Found an If getting its condition-code input from a Phi in the // same block. Split thru the Region. - void do_split_if( Node *iff ); + void do_split_if(Node *iff, RegionNode** new_false_region = NULL, RegionNode** new_true_region = NULL); // Conversion of fill/copy patterns into intrinsic versions bool do_intrinsify_fill(); @@ -1654,6 +1654,9 @@ public: void strip_mined_nest_back_to_counted_loop(IdealLoopTree* loop, const BaseCountedLoopNode* head, Node* back_control, IfNode*&exit_test, SafePointNode*&safepoint); + void push_pinned_nodes_thru_region(IfNode* dom_if, Node* region); + + bool try_merge_identical_ifs(Node* n); }; diff --git a/src/hotspot/share/opto/loopopts.cpp b/src/hotspot/share/opto/loopopts.cpp index 65bb4f663a8..7e4b7254e23 100644 --- a/src/hotspot/share/opto/loopopts.cpp +++ b/src/hotspot/share/opto/loopopts.cpp @@ -229,11 +229,10 @@ Node* PhaseIdealLoop::split_thru_phi(Node* n, Node* region, int policy) { // Replace the dominated test with an obvious true or false. Place it on the // IGVN worklist for later cleanup. Move control-dependent data Nodes on the // live path up to the dominating control. -void PhaseIdealLoop::dominated_by( Node *prevdom, Node *iff, bool flip, bool exclude_loop_predicate ) { +void PhaseIdealLoop::dominated_by(IfProjNode* prevdom, IfNode* iff, bool flip, bool exclude_loop_predicate) { if (VerifyLoopOptimizations && PrintOpto) { tty->print_cr("dominating test"); } // prevdom is the dominating projection of the dominating test. - assert(iff->is_If(), "must be"); assert(iff->Opcode() == Op_If || iff->Opcode() == Op_CountedLoopEnd || iff->Opcode() == Op_LongCountedLoopEnd || @@ -263,7 +262,7 @@ void PhaseIdealLoop::dominated_by( Node *prevdom, Node *iff, bool flip, bool exc // Make control-dependent data Nodes on the live path (path that will remain // once the dominated IF is removed) become control-dependent on the // dominating projection. - Node* dp = iff->as_If()->proj_out_or_null(pop == Op_IfTrue); + Node* dp = iff->proj_out_or_null(pop == Op_IfTrue); // Loop predicates may have depending checks which should not // be skipped. For example, range check predicate has two checks @@ -272,7 +271,7 @@ void PhaseIdealLoop::dominated_by( Node *prevdom, Node *iff, bool flip, bool exc return; ProjNode* dp_proj = dp->as_Proj(); - ProjNode* unc_proj = iff->as_If()->proj_out(1 - dp_proj->_con)->as_Proj(); + ProjNode* unc_proj = iff->proj_out(1 - dp_proj->_con)->as_Proj(); if (exclude_loop_predicate && (unc_proj->is_uncommon_trap_proj(Deoptimization::Reason_predicate) != NULL || unc_proj->is_uncommon_trap_proj(Deoptimization::Reason_profile_predicate) != NULL || @@ -1175,15 +1174,6 @@ bool PhaseIdealLoop::identical_backtoback_ifs(Node *n) { return false; } - IfNode* n_if = n->as_If(); - if (n_if->proj_out(0)->outcnt() > 1 || n_if->proj_out(1)->outcnt() > 1) { - // Removing the dominated If node by using the split-if optimization does not work if there are data dependencies. - // Some data dependencies depend on its immediate dominator If node and should not be separated from it (e.g. null - // checks, division by zero checks etc.). Bail out for now until data dependencies are correctly handled when - // optimizing back-to-back ifs. - return false; - } - Node* region = n->in(0); Node* dom = idom(region); if (!dom->is_If() || dom->in(1) != n->in(1)) { @@ -1359,28 +1349,7 @@ void PhaseIdealLoop::split_if_with_blocks_post(Node *n) { } // Two identical ifs back to back can be merged - if (identical_backtoback_ifs(n) && can_split_if(n->in(0))) { - Node *n_ctrl = n->in(0); - PhiNode* bolphi = PhiNode::make_blank(n_ctrl, n->in(1)); - IfNode* dom_if = idom(n_ctrl)->as_If(); - Node* proj_true = dom_if->proj_out(1); - Node* proj_false = dom_if->proj_out(0); - Node* con_true = _igvn.makecon(TypeInt::ONE); - Node* con_false = _igvn.makecon(TypeInt::ZERO); - - for (uint i = 1; i < n_ctrl->req(); i++) { - if (is_dominator(proj_true, n_ctrl->in(i))) { - bolphi->init_req(i, con_true); - } else { - assert(is_dominator(proj_false, n_ctrl->in(i)), "bad if"); - bolphi->init_req(i, con_false); - } - } - register_new_node(bolphi, n_ctrl); - _igvn.replace_input_of(n, 1, bolphi); - - // Now split the IF - do_split_if(n); + if (try_merge_identical_ifs(n)) { return; } @@ -1416,7 +1385,7 @@ void PhaseIdealLoop::split_if_with_blocks_post(Node *n) { // Replace the dominated test with an obvious true or false. // Place it on the IGVN worklist for later cleanup. C->set_major_progress(); - dominated_by(prevdom, n, false, true); + dominated_by(prevdom->as_IfProj(), n->as_If(), false, true); #ifndef PRODUCT if( VerifyLoopOptimizations ) verify(); #endif @@ -1441,6 +1410,118 @@ void PhaseIdealLoop::split_if_with_blocks_post(Node *n) { } } +// Tranform: +// +// if (some_condition) { +// // body 1 +// } else { +// // body 2 +// } +// if (some_condition) { +// // body 3 +// } else { +// // body 4 +// } +// +// into: +// +// +// if (some_condition) { +// // body 1 +// // body 3 +// } else { +// // body 2 +// // body 4 +// } +bool PhaseIdealLoop::try_merge_identical_ifs(Node* n) { + if (identical_backtoback_ifs(n) && can_split_if(n->in(0))) { + Node *n_ctrl = n->in(0); + IfNode* dom_if = idom(n_ctrl)->as_If(); + ProjNode* dom_proj_true = dom_if->proj_out(1); + ProjNode* dom_proj_false = dom_if->proj_out(0); + + // Now split the IF + RegionNode* new_false_region; + RegionNode* new_true_region; + do_split_if(n, &new_false_region, &new_true_region); + assert(new_false_region->req() == new_true_region->req(), ""); +#ifdef ASSERT + for (uint i = 1; i < new_false_region->req(); ++i) { + assert(new_false_region->in(i)->in(0) == new_true_region->in(i)->in(0), "unexpected shape following split if"); + assert(i == new_false_region->req() - 1 || new_false_region->in(i)->in(0)->in(1) == new_false_region->in(i + 1)->in(0)->in(1), "unexpected shape following split if"); + } +#endif + assert(new_false_region->in(1)->in(0)->in(1) == dom_if->in(1), "dominating if and dominated if after split must share test"); + + // We now have: + // if (some_condition) { + // // body 1 + // if (some_condition) { + // body3: // new_true_region + // // body3 + // } else { + // goto body4; + // } + // } else { + // // body 2 + // if (some_condition) { + // goto body3; + // } else { + // body4: // new_false_region + // // body4; + // } + // } + // + + // clone pinned nodes thru the resulting regions + push_pinned_nodes_thru_region(dom_if, new_true_region); + push_pinned_nodes_thru_region(dom_if, new_false_region); + + // Optimize out the cloned ifs. Because pinned nodes were cloned, this also allows a CastPP that would be dependent + // on a projection of n to have the dom_if as a control dependency. We don't want the CastPP to end up with an + // unrelated control dependency. + for (uint i = 1; i < new_false_region->req(); i++) { + if (is_dominator(dom_proj_true, new_false_region->in(i))) { + dominated_by(dom_proj_true->as_IfProj(), new_false_region->in(i)->in(0)->as_If(), false, false); + } else { + assert(is_dominator(dom_proj_false, new_false_region->in(i)), "bad if"); + dominated_by(dom_proj_false->as_IfProj(), new_false_region->in(i)->in(0)->as_If(), false, false); + } + } + return true; + } + return false; +} + +void PhaseIdealLoop::push_pinned_nodes_thru_region(IfNode* dom_if, Node* region) { + for (DUIterator i = region->outs(); region->has_out(i); i++) { + Node* u = region->out(i); + if (!has_ctrl(u) || u->is_Phi() || !u->depends_only_on_test() || !_igvn.no_dependent_zero_check(u)) { + continue; + } + assert(u->in(0) == region, "not a control dependent node?"); + uint j = 1; + for (; j < u->req(); ++j) { + Node* in = u->in(j); + if (!is_dominator(ctrl_or_self(in), dom_if)) { + break; + } + } + if (j == u->req()) { + Node *phi = PhiNode::make_blank(region, u); + for (uint k = 1; k < region->req(); ++k) { + Node* clone = u->clone(); + clone->set_req(0, region->in(k)); + register_new_node(clone, region->in(k)); + phi->init_req(k, clone); + } + register_new_node(phi, region); + _igvn.replace_node(u, phi); + --i; + } + } +} + bool PhaseIdealLoop::safe_for_if_replacement(const Node* dom) const { if (!dom->is_CountedLoopEnd()) { return true; diff --git a/src/hotspot/share/opto/split_if.cpp b/src/hotspot/share/opto/split_if.cpp index 6bf835926e5..060d3464514 100644 --- a/src/hotspot/share/opto/split_if.cpp +++ b/src/hotspot/share/opto/split_if.cpp @@ -31,20 +31,19 @@ //------------------------------split_thru_region------------------------------ // Split Node 'n' through merge point. -Node *PhaseIdealLoop::split_thru_region( Node *n, Node *region ) { - uint wins = 0; - assert( n->is_CFG(), "" ); - assert( region->is_Region(), "" ); - Node *r = new RegionNode( region->req() ); - IdealLoopTree *loop = get_loop( n ); - for( uint i = 1; i < region->req(); i++ ) { - Node *x = n->clone(); - Node *in0 = n->in(0); - if( in0->in(0) == region ) x->set_req( 0, in0->in(i) ); - for( uint j = 1; j < n->req(); j++ ) { - Node *in = n->in(j); - if( get_ctrl(in) == region ) - x->set_req( j, in->in(i) ); +RegionNode* PhaseIdealLoop::split_thru_region(Node* n, RegionNode* region) { + assert(n->is_CFG(), ""); + RegionNode* r = new RegionNode(region->req()); + IdealLoopTree* loop = get_loop(n); + for (uint i = 1; i < region->req(); i++) { + Node* x = n->clone(); + Node* in0 = n->in(0); + if (in0->in(0) == region) x->set_req(0, in0->in(i)); + for (uint j = 1; j < n->req(); j++) { + Node* in = n->in(j); + if (get_ctrl(in) == region) { + x->set_req(j, in->in(i)); + } } _igvn.register_new_node_with_optimizer(x); set_loop(x, loop); @@ -56,8 +55,9 @@ Node *PhaseIdealLoop::split_thru_region( Node *n, Node *region ) { r->set_req(0,region); // Not a TRUE RegionNode _igvn.register_new_node_with_optimizer(r); set_loop(r, loop); - if( !loop->_child ) + if (!loop->_child) { loop->_body.push(r); + } return r; } @@ -433,7 +433,7 @@ void PhaseIdealLoop::handle_use( Node *use, Node *def, small_cache *cache, Node //------------------------------do_split_if------------------------------------ // Found an If getting its condition-code input from a Phi in the same block. // Split thru the Region. -void PhaseIdealLoop::do_split_if( Node *iff ) { +void PhaseIdealLoop::do_split_if(Node* iff, RegionNode** new_false_region, RegionNode** new_true_region) { if (PrintOpto && VerifyLoopOptimizations) { tty->print_cr("Split-if"); } @@ -442,7 +442,7 @@ void PhaseIdealLoop::do_split_if( Node *iff ) { } C->set_major_progress(); - Node *region = iff->in(0); + RegionNode *region = iff->in(0)->as_Region(); Node *region_dom = idom(region); // We are going to clone this test (and the control flow with it) up through @@ -491,17 +491,18 @@ void PhaseIdealLoop::do_split_if( Node *iff ) { // Now we have no instructions in the block containing the IF. // Split the IF. - Node *new_iff = split_thru_region( iff, region ); + RegionNode *new_iff = split_thru_region(iff, region); // Replace both uses of 'new_iff' with Regions merging True/False // paths. This makes 'new_iff' go dead. Node *old_false = NULL, *old_true = NULL; - Node *new_false = NULL, *new_true = NULL; + RegionNode* new_false = NULL; + RegionNode* new_true = NULL; for (DUIterator_Last j2min, j2 = iff->last_outs(j2min); j2 >= j2min; --j2) { Node *ifp = iff->last_out(j2); assert( ifp->Opcode() == Op_IfFalse || ifp->Opcode() == Op_IfTrue, "" ); ifp->set_req(0, new_iff); - Node *ifpx = split_thru_region( ifp, region ); + RegionNode* ifpx = split_thru_region(ifp, region); // Replace 'If' projection of a Region with a Region of // 'If' projections. @@ -577,6 +578,13 @@ void PhaseIdealLoop::do_split_if( Node *iff ) { _igvn.remove_dead_node(region); + if (new_false_region != NULL) { + *new_false_region = new_false; + } + if (new_true_region != NULL) { + *new_true_region = new_true; + } + #ifndef PRODUCT if( VerifyLoopOptimizations ) verify(); #endif diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestBackToBackIfs.java b/test/hotspot/jtreg/compiler/c2/irTests/TestBackToBackIfs.java new file mode 100644 index 00000000000..207b16a8062 --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/irTests/TestBackToBackIfs.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2022, Red Hat, Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package compiler.c2.irTests; + +import compiler.lib.ir_framework.*; +import jdk.test.lib.Utils; +import java.util.Random; + +/* + * @test + * @bug 8278228 + * @summary C2: Improve identical back-to-back if elimination + * @library /test/lib / + * @run driver compiler.c2.irTests.TestBackToBackIfs + */ + +public class TestBackToBackIfs { + public static void main(String[] args) { + TestFramework.run(); + } + + static private int int_field; + + @Test + @IR(counts = { IRNode.IF, "1" }) + public static void test(int a, int b) { + if (a == b) { + int_field = 0x42; + } else { + int_field = 42; + } + if (a == b) { + int_field = 0x42; + } else { + int_field = 42; + } + } + + @Run(test = "test") + public static void test_runner() { + test(42, 0x42); + test(0x42, 0x42); + } +} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java index b4737490652..46428c2a05f 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java @@ -115,6 +115,7 @@ public class IRNode { public static final String LOOP = START + "Loop" + MID + END; public static final String COUNTEDLOOP = START + "CountedLoop\\b" + MID + END; public static final String COUNTEDLOOP_MAIN = START + "CountedLoop\\b" + MID + "main" + END; + public static final String IF = START + "If\\b" + MID + END; public static final String CALL = START + "Call.*Java" + MID + END; public static final String CALL_OF_METHOD = COMPOSITE_PREFIX + START + "Call.*Java" + MID + IS_REPLACED + " " + END; -- GitLab From 2f8a2fd077a2b9c88ab1823b52715278e26bbff1 Mon Sep 17 00:00:00 2001 From: Christian Hagedorn Date: Mon, 10 Jan 2022 08:17:36 +0000 Subject: [PATCH 032/564] 8279568: IGV: Add bci and line number property for OSR compilations Reviewed-by: kvn, roland --- src/hotspot/share/opto/idealGraphPrinter.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/opto/idealGraphPrinter.cpp b/src/hotspot/share/opto/idealGraphPrinter.cpp index cb403853f33..d80f6eec3f3 100644 --- a/src/hotspot/share/opto/idealGraphPrinter.cpp +++ b/src/hotspot/share/opto/idealGraphPrinter.cpp @@ -316,7 +316,9 @@ void IdealGraphPrinter::begin_method() { } if (C->is_osr_compilation()) { - print_prop(COMPILATION_OSR_PROPERTY, TRUE_VALUE); + stringStream ss; + ss.print("bci: %d, line: %d", C->entry_bci(), method->line_number_from_bci(C->entry_bci())); + print_prop(COMPILATION_OSR_PROPERTY, ss.as_string()); } print_prop(COMPILATION_ID_PROPERTY, C->compile_id()); -- GitLab From 4aefd8b8b6cd76137e3bc51a84d1182fde22ba02 Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Mon, 10 Jan 2022 08:30:39 +0000 Subject: [PATCH 033/564] 8279528: Unused TypeEnter.diag after JDK-8205187 Reviewed-by: vromero --- .../share/classes/com/sun/tools/javac/comp/TypeEnter.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java index 3a763cbe034..c5df4f9ff3c 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java @@ -109,7 +109,6 @@ public class TypeEnter implements Completer { private final Annotate annotate; private final TypeAnnotations typeAnnotations; private final Types types; - private final JCDiagnostic.Factory diags; private final DeferredLintHandler deferredLintHandler; private final Lint lint; private final TypeEnvs typeEnvs; @@ -137,7 +136,6 @@ public class TypeEnter implements Completer { annotate = Annotate.instance(context); typeAnnotations = TypeAnnotations.instance(context); types = Types.instance(context); - diags = JCDiagnostic.Factory.instance(context); deferredLintHandler = DeferredLintHandler.instance(context); lint = Lint.instance(context); typeEnvs = TypeEnvs.instance(context); -- GitLab From 642ab34a60172f4b629f953e146b54b9c7269033 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Mon, 10 Jan 2022 08:33:46 +0000 Subject: [PATCH 034/564] 8278373: JavacTrees.searchMethod finds incorrect match Reviewed-by: vromero, jjg --- .../com/sun/tools/javac/api/JavacTrees.java | 35 ++++++---- .../tools/javac/doctree/ReferenceTest.java | 70 +++++++++++++++++-- 2 files changed, 87 insertions(+), 18 deletions(-) diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java index 3b189799368..f5ff32ffd9a 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java @@ -507,10 +507,16 @@ public class JavacTrees extends DocTrees { } ClassSymbol sym = (ClassSymbol) types.skipTypeVars(tsym.type, false).tsym; - Symbol msym = (memberName == sym.name) - ? findConstructor(sym, paramTypes) - : findMethod(sym, memberName, paramTypes); + ? findConstructor(sym, paramTypes, true) + : findMethod(sym, memberName, paramTypes, true); + + if (msym == null) { + msym = (memberName == sym.name) + ? findConstructor(sym, paramTypes, false) + : findMethod(sym, memberName, paramTypes, false); + } + if (paramTypes != null) { // explicit (possibly empty) arg list given, so cannot be a field return msym; @@ -608,10 +614,10 @@ public class JavacTrees extends DocTrees { return null; } - MethodSymbol findConstructor(ClassSymbol tsym, List paramTypes) { + MethodSymbol findConstructor(ClassSymbol tsym, List paramTypes, boolean strict) { for (Symbol sym : tsym.members().getSymbolsByName(names.init)) { if (sym.kind == MTH) { - if (hasParameterTypes((MethodSymbol) sym, paramTypes)) { + if (hasParameterTypes((MethodSymbol) sym, paramTypes, strict)) { return (MethodSymbol) sym; } } @@ -619,12 +625,13 @@ public class JavacTrees extends DocTrees { return null; } - private MethodSymbol findMethod(ClassSymbol tsym, Name methodName, List paramTypes) { - return searchMethod(tsym, methodName, paramTypes, new HashSet<>()); + private MethodSymbol findMethod(ClassSymbol tsym, Name methodName, List paramTypes, boolean strict) { + return searchMethod(tsym, methodName, paramTypes, strict, new HashSet<>()); } private MethodSymbol searchMethod(ClassSymbol tsym, Name methodName, - List paramTypes, Set searched) { + List paramTypes, boolean strict, + Set searched) { //### Note that this search is not necessarily what the compiler would do! // do not match constructors @@ -662,7 +669,7 @@ public class JavacTrees extends DocTrees { for (Symbol sym : tsym.members().getSymbolsByName(methodName)) { if (sym != null && sym.kind == MTH) { - if (hasParameterTypes((MethodSymbol) sym, paramTypes)) { + if (hasParameterTypes((MethodSymbol) sym, paramTypes, strict)) { return (MethodSymbol) sym; } } @@ -675,7 +682,7 @@ public class JavacTrees extends DocTrees { // search superclass Type superclass = tsym.getSuperclass(); if (superclass.tsym != null) { - MethodSymbol msym = searchMethod((ClassSymbol) superclass.tsym, methodName, paramTypes, searched); + MethodSymbol msym = searchMethod((ClassSymbol) superclass.tsym, methodName, paramTypes, strict, searched); if (msym != null) { return msym; } @@ -686,7 +693,7 @@ public class JavacTrees extends DocTrees { for (List l = intfs; l.nonEmpty(); l = l.tail) { Type intf = l.head; if (intf.isErroneous()) continue; - MethodSymbol msym = searchMethod((ClassSymbol) intf.tsym, methodName, paramTypes, searched); + MethodSymbol msym = searchMethod((ClassSymbol) intf.tsym, methodName, paramTypes, strict, searched); if (msym != null) { return msym; } @@ -695,7 +702,7 @@ public class JavacTrees extends DocTrees { // search enclosing class ClassSymbol encl = tsym.owner.enclClass(); if (encl != null) { - MethodSymbol msym = searchMethod(encl, methodName, paramTypes, searched); + MethodSymbol msym = searchMethod(encl, methodName, paramTypes, strict, searched); if (msym != null) { return msym; } @@ -704,7 +711,7 @@ public class JavacTrees extends DocTrees { return null; } - private boolean hasParameterTypes(MethodSymbol method, List paramTypes) { + private boolean hasParameterTypes(MethodSymbol method, List paramTypes, boolean strict) { if (paramTypes == null) return true; @@ -712,7 +719,7 @@ public class JavacTrees extends DocTrees { return false; List methodParamTypes = method.asType().getParameterTypes(); - if (!Type.isErroneous(paramTypes) && types.isSubtypes(paramTypes, methodParamTypes)) { + if (!strict && !Type.isErroneous(paramTypes) && types.isSubtypes(paramTypes, methodParamTypes)) { return true; } diff --git a/test/langtools/tools/javac/doctree/ReferenceTest.java b/test/langtools/tools/javac/doctree/ReferenceTest.java index 128d3e158b1..eb635650b76 100644 --- a/test/langtools/tools/javac/doctree/ReferenceTest.java +++ b/test/langtools/tools/javac/doctree/ReferenceTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 7021614 + * @bug 7021614 8278373 * @summary extend com.sun.source API to support parsing javadoc comments * @summary check references in at-see and {at-link} tags * @modules jdk.compiler @@ -39,19 +39,23 @@ import com.sun.source.doctree.SeeTree; import com.sun.source.doctree.TextTree; import com.sun.source.util.DocTreePath; import com.sun.source.util.DocTreePathScanner; -import com.sun.source.util.DocTreeScanner; import com.sun.source.util.DocTrees; import com.sun.source.util.TreePath; import java.util.List; import java.util.Set; +import java.util.stream.Collectors; import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.ProcessingEnvironment; import javax.annotation.processing.RoundEnvironment; import javax.annotation.processing.SupportedAnnotationTypes; import javax.lang.model.SourceVersion; import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.QualifiedNameable; import javax.lang.model.element.TypeElement; +import javax.lang.model.type.DeclaredType; +import javax.lang.model.type.TypeMirror; import javax.tools.Diagnostic.Kind; /** @@ -174,8 +178,18 @@ public class ReferenceTest extends AbstractProcessor { if (label.size() > 0 && label.get(0) instanceof TextTree) expect = ((TextTree) label.get(0)).getBody(); - if (!expect.equalsIgnoreCase(found == null ? "bad" : found.getKind().name())) { - error(tree, "Unexpected value found: " + found +", expected: " + expect); + if (expect.startsWith("signature:")) { + expect = expect.substring("signature:".length()); + + String signature = found.getKind().name() + ":" + elementSignature(found); + + if (!expect.equalsIgnoreCase(signature)) { + error(tree, "Unexpected value found: " + signature +", expected: " + expect); + } + } else { + if (!expect.equalsIgnoreCase(found == null ? "bad" : found.getKind().name())) { + error(tree, "Unexpected value found: " + found +", expected: " + expect); + } } } @@ -183,6 +197,29 @@ public class ReferenceTest extends AbstractProcessor { trees.printMessage(Kind.ERROR, msg, tree, dc, path.getCompilationUnit()); } } + + String elementSignature(Element el) { + return switch (el.getKind()) { + case METHOD -> elementSignature(el.getEnclosingElement()) + "." + el.getSimpleName() + "(" + executableParamNames((ExecutableElement) el) + ")"; + case CLASS, INTERFACE -> ((QualifiedNameable) el).getQualifiedName().toString(); + default -> throw new AssertionError("Unhandled Element kind: " + el.getKind()); + }; + } + + String executableParamNames(ExecutableElement ee) { + return ee.getParameters() + .stream() + .map(p -> type2Name(p.asType())) + .collect(Collectors.joining(", ")); + } + + String type2Name(TypeMirror type) { + return switch (type.getKind()) { + case DECLARED -> elementSignature(((DeclaredType) type).asElement()); + case INT, LONG -> type.toString(); + default -> throw new AssertionError("Unhandled type kind: " + type.getKind()); + }; + } } /** @@ -199,6 +236,17 @@ public class ReferenceTest extends AbstractProcessor { * @see #varargs(int... args) Method * @see #varargs(int[]) Method * @see #varargs(int[] args) Method + * + * @see #methodSearch(String) signature:METHOD:ReferenceTestExtras.methodSearch(java.lang.String) + * @see #methodSearch(StringBuilder) signature:METHOD:ReferenceTestExtras.methodSearch(java.lang.CharSequence) + * @see #methodSearchPrimitive1(int, int) signature:METHOD:ReferenceTestExtras.methodSearchPrimitive1(int, int) + * @see #methodSearchPrimitive1(long, int) signature:METHOD:ReferenceTestExtras.methodSearchPrimitive1(long, int) + * @see #methodSearchPrimitive1(int, long) signature:METHOD:ReferenceTestExtras.methodSearchPrimitive1(int, long) + * @see #methodSearchPrimitive1(long, long) signature:METHOD:ReferenceTestExtras.methodSearchPrimitive1(long, long) + * @see #methodSearchPrimitive2(int, int) signature:METHOD:ReferenceTestExtras.methodSearchPrimitive2(int, int) + * @see #methodSearchPrimitive2(long, int) signature:METHOD:ReferenceTestExtras.methodSearchPrimitive2(long, int) + * @see #methodSearchPrimitive2(int, long) signature:METHOD:ReferenceTestExtras.methodSearchPrimitive2(int, long) + * @see #methodSearchPrimitive2(long, long) signature:METHOD:ReferenceTestExtras.methodSearchPrimitive2(long, long) */ class ReferenceTestExtras { int ReferenceTestExtras; // field @@ -214,6 +262,20 @@ class ReferenceTestExtras { void m(int i, int j) { } void varargs(int... args) { } + + void methodSearch(Object o) {} + void methodSearch(String s) {} + void methodSearch(CharSequence cs) {} + + void methodSearchPrimitive1(int i, int j) {} + void methodSearchPrimitive1(long i, int j) {} + void methodSearchPrimitive1(int i, long j) {} + void methodSearchPrimitive1(long i, long j) {} + + void methodSearchPrimitive2(long i, long j) {} + void methodSearchPrimitive2(int i, long j) {} + void methodSearchPrimitive2(long i, int j) {} + void methodSearchPrimitive2(int i, int j) {} } -- GitLab From 5fa13bb4a39225c4345ee129b30fb08ad5fdff6d Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Mon, 10 Jan 2022 08:56:34 +0000 Subject: [PATCH 035/564] 8279522: Serial: Remove unused Generation::clear_remembered_set Reviewed-by: iwalulya, mli --- src/hotspot/share/gc/shared/cardGeneration.cpp | 5 ----- src/hotspot/share/gc/shared/cardGeneration.hpp | 2 -- src/hotspot/share/gc/shared/generation.hpp | 5 ----- 3 files changed, 12 deletions(-) diff --git a/src/hotspot/share/gc/shared/cardGeneration.cpp b/src/hotspot/share/gc/shared/cardGeneration.cpp index 8f691c3c46c..1ba0ecc5ad5 100644 --- a/src/hotspot/share/gc/shared/cardGeneration.cpp +++ b/src/hotspot/share/gc/shared/cardGeneration.cpp @@ -174,11 +174,6 @@ void CardGeneration::shrink(size_t bytes) { name(), old_mem_size/K, new_mem_size/K); } -// No young generation references, clear this generation's cards. -void CardGeneration::clear_remembered_set() { - _rs->clear(reserved()); -} - // Objects in this generation may have moved, invalidate this // generation's cards. void CardGeneration::invalidate_remembered_set() { diff --git a/src/hotspot/share/gc/shared/cardGeneration.hpp b/src/hotspot/share/gc/shared/cardGeneration.hpp index 7ad58cf2b69..82c5fa5acb5 100644 --- a/src/hotspot/share/gc/shared/cardGeneration.hpp +++ b/src/hotspot/share/gc/shared/cardGeneration.hpp @@ -71,8 +71,6 @@ class CardGeneration: public Generation { virtual void compute_new_size(); - virtual void clear_remembered_set(); - virtual void invalidate_remembered_set(); virtual void prepare_for_verify(); diff --git a/src/hotspot/share/gc/shared/generation.hpp b/src/hotspot/share/gc/shared/generation.hpp index 216b38d38b7..7f8a82e4939 100644 --- a/src/hotspot/share/gc/shared/generation.hpp +++ b/src/hotspot/share/gc/shared/generation.hpp @@ -422,11 +422,6 @@ class Generation: public CHeapObj { // each. virtual void object_iterate(ObjectClosure* cl); - // Inform a generation that it longer contains references to objects - // in any younger generation. [e.g. Because younger gens are empty, - // clear the card table.] - virtual void clear_remembered_set() { } - // Inform a generation that some of its objects have moved. [e.g. The // generation's spaces were compacted, invalidating the card table.] virtual void invalidate_remembered_set() { } -- GitLab From 79b614cc19454765eba17acd27d9772e7eaae1ee Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Mon, 10 Jan 2022 08:57:23 +0000 Subject: [PATCH 036/564] 8279523: Parallel: Remove unnecessary PSScavenge::_to_space_top_before_gc Reviewed-by: kbarrett, mli --- src/hotspot/share/gc/parallel/psScavenge.cpp | 3 --- src/hotspot/share/gc/parallel/psScavenge.hpp | 7 ------- src/hotspot/share/gc/parallel/psScavenge.inline.hpp | 7 +------ 3 files changed, 1 insertion(+), 16 deletions(-) diff --git a/src/hotspot/share/gc/parallel/psScavenge.cpp b/src/hotspot/share/gc/parallel/psScavenge.cpp index 0f4540223c9..2cee28eef42 100644 --- a/src/hotspot/share/gc/parallel/psScavenge.cpp +++ b/src/hotspot/share/gc/parallel/psScavenge.cpp @@ -70,7 +70,6 @@ #include "services/memoryService.hpp" #include "utilities/stack.inline.hpp" -HeapWord* PSScavenge::_to_space_top_before_gc = NULL; SpanSubjectToDiscoveryClosure PSScavenge::_span_based_discoverer; ReferenceProcessor* PSScavenge::_ref_processor = NULL; PSCardTable* PSScavenge::_card_table = NULL; @@ -443,8 +442,6 @@ bool PSScavenge::invoke_no_policy() { "Attempt to scavenge with live objects in to_space"); young_gen->to_space()->clear(SpaceDecorator::Mangle); - save_to_space_top_before_gc(); - #if COMPILER2_OR_JVMCI DerivedPointerTable::clear(); #endif diff --git a/src/hotspot/share/gc/parallel/psScavenge.hpp b/src/hotspot/share/gc/parallel/psScavenge.hpp index d15b39c68b5..80f41a99934 100644 --- a/src/hotspot/share/gc/parallel/psScavenge.hpp +++ b/src/hotspot/share/gc/parallel/psScavenge.hpp @@ -53,10 +53,6 @@ class PSScavenge: AllStatic { full_follows_scavenge }; - // Saved value of to_space->top(), used to prevent objects in to_space from - // being rescanned. - static HeapWord* _to_space_top_before_gc; - protected: // Flags/counters static SpanSubjectToDiscoveryClosure _span_based_discoverer; @@ -80,9 +76,6 @@ class PSScavenge: AllStatic { static bool should_attempt_scavenge(); - static HeapWord* to_space_top_before_gc() { return _to_space_top_before_gc; } - static inline void save_to_space_top_before_gc(); - // Private accessors static PSCardTable* const card_table() { assert(_card_table != NULL, "Sanity"); return _card_table; } static const ParallelScavengeTracer* gc_tracer() { return &_gc_tracer; } diff --git a/src/hotspot/share/gc/parallel/psScavenge.inline.hpp b/src/hotspot/share/gc/parallel/psScavenge.inline.hpp index 1fee9f08339..af3ff4c6165 100644 --- a/src/hotspot/share/gc/parallel/psScavenge.inline.hpp +++ b/src/hotspot/share/gc/parallel/psScavenge.inline.hpp @@ -35,11 +35,6 @@ #include "oops/oop.inline.hpp" #include "utilities/globalDefinitions.hpp" -inline void PSScavenge::save_to_space_top_before_gc() { - ParallelScavengeHeap* heap = ParallelScavengeHeap::heap(); - _to_space_top_before_gc = heap->young_gen()->to_space()->top(); -} - template inline bool PSScavenge::should_scavenge(T* p) { T heap_oop = RawAccess<>::oop_load(p); return PSScavenge::is_obj_in_young(heap_oop); @@ -51,7 +46,7 @@ inline bool PSScavenge::should_scavenge(T* p, MutableSpace* to_space) { oop obj = RawAccess::oop_load(p); // Skip objects copied to to_space since the scavenge started. HeapWord* const addr = cast_from_oop(obj); - return addr < to_space_top_before_gc() || addr >= to_space->end(); + return addr < to_space->bottom() || addr >= to_space->end(); } return false; } -- GitLab From 8f969a1362343df8592046a838436f41894ee471 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Mon, 10 Jan 2022 09:30:55 +0000 Subject: [PATCH 037/564] 8278930: javac tries to compile a file twice via PackageElement.getEnclosedElements Reviewed-by: vromero --- .../com/sun/tools/javac/code/ClassFinder.java | 12 +- .../model/element/TestListPackageFromAPI.java | 149 ++++++++++++++++++ 2 files changed, 158 insertions(+), 3 deletions(-) create mode 100644 test/langtools/tools/javac/processing/model/element/TestListPackageFromAPI.java diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java index fa67ff3a7ca..ab7582e7ced 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2022, 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 @@ -292,10 +292,16 @@ public class ClassFinder { ClassSymbol c = (ClassSymbol) sym; dependencies.push(c, CompletionCause.CLASS_READER); annotate.blockAnnotations(); - c.members_field = new Scope.ErrorScope(c); // make sure it's always defined + Scope.ErrorScope members = new Scope.ErrorScope(c); + c.members_field = members; // make sure it's always defined completeOwners(c.owner); completeEnclosing(c); - fillIn(c); + //if an enclosing class is completed from the source, + //this class might have been completed already as well, + //avoid attempts to re-complete it: + if (c.members_field == members) { + fillIn(c); + } } finally { annotate.unblockAnnotationsNoFlush(); dependencies.pop(); diff --git a/test/langtools/tools/javac/processing/model/element/TestListPackageFromAPI.java b/test/langtools/tools/javac/processing/model/element/TestListPackageFromAPI.java new file mode 100644 index 00000000000..358be012617 --- /dev/null +++ b/test/langtools/tools/javac/processing/model/element/TestListPackageFromAPI.java @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2022, 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 8278930 + * @summary Check that when a package has Elements listed from both from classes and sources, + * and then a nested class is completed, it is not first completed from source via + * its enclosing class, and then again for itself. + * @library /tools/javac/lib + * @modules java.compiler + * jdk.compiler + * @run main TestListPackageFromAPI + */ + +import com.sun.source.util.JavacTask; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import javax.lang.model.element.PackageElement; +import javax.tools.DiagnosticListener; +import javax.tools.ForwardingJavaFileManager; +import javax.tools.JavaFileManager; +import javax.tools.JavaFileObject; +import javax.tools.JavaFileObject.Kind; +import javax.tools.SimpleJavaFileObject; +import javax.tools.StandardLocation; +import javax.tools.ToolProvider; + +public class TestListPackageFromAPI { + + public static void main(String... args) throws IOException, URISyntaxException, InterruptedException { + try (JavaFileManager fm = ToolProvider.getSystemJavaCompiler().getStandardFileManager(null, null, null)) { + List testClasses = List.of( + new TestFileObject("Test"), + new TestFileObject("Test$Nested") + ); + List testSources = List.of( + new TestFileObject("Test", + """ + class Test { + public static class Nested {} + } + """) + ); + JavaFileManager testFM = new ForwardingJavaFileManagerImpl(fm, testClasses, testSources); + DiagnosticListener noErrors = d -> { throw new AssertionError("Should not happen: " + d); }; + JavacTask task = (JavacTask) ToolProvider.getSystemJavaCompiler().getTask(null, testFM, noErrors, null, null, List.of(new TestFileObject("Input", ""))); + PackageElement pack = task.getElements().getPackageElement(""); + pack.getEnclosedElements().forEach(e -> System.err.println(e)); + } + } + + private static class TestFileObject extends SimpleJavaFileObject { + + private final String className; + private final String code; + + public TestFileObject(String className) throws URISyntaxException { + super(new URI("mem://" + className + ".class"), Kind.CLASS); + this.className = className; + this.code = null; + } + + public TestFileObject(String className, String code) throws URISyntaxException { + super(new URI("mem://" + className + ".java"), Kind.SOURCE); + this.className = className; + this.code = code; + } + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { + if (code == null) { + throw new UnsupportedOperationException(); + } + return code; + } + + @Override + public long getLastModified() { + return getKind() == Kind.CLASS ? 0 : 1000; + } + + } + + private static class ForwardingJavaFileManagerImpl extends ForwardingJavaFileManager { + + private final List testClasses; + private final List testSources; + + public ForwardingJavaFileManagerImpl(JavaFileManager fileManager, List testClasses, List testSources) { + super(fileManager); + this.testClasses = testClasses; + this.testSources = testSources; + } + + @Override + public Iterable list(JavaFileManager.Location location, String packageName, Set kinds, boolean recurse) throws IOException { + if (packageName.isEmpty()) { + List result = new ArrayList<>(); + if (location == StandardLocation.CLASS_PATH && kinds.contains(Kind.CLASS)) { + result.addAll(testClasses); + } else if (location == StandardLocation.SOURCE_PATH && kinds.contains(Kind.SOURCE)) { + result.addAll(testSources); + } + return result; + } + return super.list(location, packageName, kinds, recurse); + } + + @Override + public boolean hasLocation(Location location) { + return location == StandardLocation.CLASS_PATH || + location == StandardLocation.SOURCE_PATH || + super.hasLocation(location); + } + + @Override + public String inferBinaryName(JavaFileManager.Location location, JavaFileObject file) { + if (file instanceof TestFileObject testFO) { + return testFO.className; + } + return super.inferBinaryName(location, file); + } + } +} -- GitLab From 1f101b04f4d7c166cc0a830383e4e08025df5c74 Mon Sep 17 00:00:00 2001 From: Tobias Holenstein Date: Mon, 10 Jan 2022 10:50:07 +0000 Subject: [PATCH 038/564] 8278329: some TraceDeoptimization code not included in PRODUCT build Reviewed-by: dnsimon, kvn, never, thartmann --- src/hotspot/share/runtime/deoptimization.cpp | 124 ++++++++----------- src/hotspot/share/runtime/frame.cpp | 13 +- src/hotspot/share/runtime/vframe.cpp | 2 - src/hotspot/share/runtime/vframeArray.cpp | 80 ++++++++---- 4 files changed, 111 insertions(+), 108 deletions(-) diff --git a/src/hotspot/share/runtime/deoptimization.cpp b/src/hotspot/share/runtime/deoptimization.cpp index 7a89069a025..206e5951304 100644 --- a/src/hotspot/share/runtime/deoptimization.cpp +++ b/src/hotspot/share/runtime/deoptimization.cpp @@ -165,9 +165,6 @@ JRT_BLOCK_ENTRY(Deoptimization::UnrollBlock*, Deoptimization::fetch_unroll_info( // handler. Note this fact before we start generating temporary frames // that can confuse an asynchronous stack walker. This counter is // decremented at the end of unpack_frames(). - if (TraceDeoptimization) { - tty->print_cr("Deoptimizing thread " INTPTR_FORMAT, p2i(current)); - } current->inc_in_deopt_handler(); if (exec_mode == Unpack_exception) { @@ -181,7 +178,6 @@ JRT_BLOCK_ENTRY(Deoptimization::UnrollBlock*, Deoptimization::fetch_unroll_info( JRT_END #if COMPILER2_OR_JVMCI -#ifndef PRODUCT // print information about reallocated objects static void print_objects(JavaThread* deoptee_thread, GrowableArray* objects, bool realloc_failures) { @@ -211,7 +207,6 @@ static void print_objects(JavaThread* deoptee_thread, } tty->print_raw(st.as_string()); } -#endif static bool rematerialize_objects(JavaThread* thread, int exec_mode, CompiledMethod* compiled_method, frame& deoptee, RegisterMap& map, GrowableArray* chunk, @@ -245,6 +240,7 @@ static bool rematerialize_objects(JavaThread* thread, int exec_mode, CompiledMet assert(Universe::heap()->is_in_or_null(result), "must be heap pointer"); if (TraceDeoptimization) { tty->print_cr("SAVED OOP RESULT " INTPTR_FORMAT " in thread " INTPTR_FORMAT, p2i(result), p2i(thread)); + tty->cr(); } } if (objects != NULL) { @@ -262,11 +258,9 @@ static bool rematerialize_objects(JavaThread* thread, int exec_mode, CompiledMet } bool skip_internal = (compiled_method != NULL) && !compiled_method->is_compiled_by_jvmci(); Deoptimization::reassign_fields(&deoptee, &map, objects, realloc_failures, skip_internal); -#ifndef PRODUCT if (TraceDeoptimization) { print_objects(deoptee_thread, objects, realloc_failures); } -#endif } if (save_oop_result) { // Restore result. @@ -283,7 +277,7 @@ static void restore_eliminated_locks(JavaThread* thread, GrowableArraylength(); i++) { compiledVFrame* cvf = chunk->at(i); assert (cvf->scope() != NULL,"expect only compiled java frames"); @@ -429,9 +423,12 @@ Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread ScopeDesc* trap_scope = chunk->at(0)->scope(); Handle exceptionObject; if (trap_scope->rethrow_exception()) { +#ifndef PRODUCT if (PrintDeoptimizationDetails) { tty->print_cr("Exception to be rethrown in the interpreter for method %s::%s at bci %d", trap_scope->method()->method_holder()->name()->as_C_string(), trap_scope->method()->name()->as_C_string(), trap_scope->bci()); } +#endif // !PRODUCT + GrowableArray* expressions = trap_scope->expressions(); guarantee(expressions != NULL && expressions->length() > 0, "must have exception to throw"); ScopeValue* topOfStack = expressions->top(); @@ -727,16 +724,6 @@ JRT_LEAF(BasicType, Deoptimization::unpack_frames(JavaThread* thread, int exec_m // Since the frame to unpack is the top frame of this thread, the vframe_array_head // must point to the vframeArray for the unpack frame. vframeArray* array = thread->vframe_array_head(); - -#ifndef PRODUCT - if (TraceDeoptimization) { - tty->print_cr("DEOPT UNPACKING thread " INTPTR_FORMAT " vframeArray " INTPTR_FORMAT " mode %d", - p2i(thread), p2i(array), exec_mode); - } -#endif - Events::log_deopt_message(thread, "DEOPT UNPACKING pc=" INTPTR_FORMAT " sp=" INTPTR_FORMAT " mode %d", - p2i(stub_frame.pc()), p2i(stub_frame.sp()), exec_mode); - UnrollBlock* info = array->unroll_block(); // We set the last_Java frame. But the stack isn't really parsable here. So we @@ -886,7 +873,7 @@ JRT_LEAF(BasicType, Deoptimization::unpack_frames(JavaThread* thread, int exec_m is_top_frame = false; } } -#endif /* !PRODUCT */ +#endif // !PRODUCT return bt; JRT_END @@ -1413,9 +1400,12 @@ void Deoptimization::reassign_fields(frame* fr, RegisterMap* reg_map, GrowableAr Klass* k = java_lang_Class::as_Klass(sv->klass()->as_ConstantOopReadValue()->value()()); Handle obj = sv->value(); assert(obj.not_null() || realloc_failures, "reallocation was missed"); +#ifndef PRODUCT if (PrintDeoptimizationDetails) { tty->print_cr("reassign fields for object of type %s!", k->name()->as_C_string()); } +#endif // !PRODUCT + if (obj.is_null()) { continue; } @@ -1430,6 +1420,7 @@ void Deoptimization::reassign_fields(frame* fr, RegisterMap* reg_map, GrowableAr ScopeValue* payload = sv->field_at(0); if (payload->is_location() && payload->as_LocationValue()->location().type() == Location::vector) { +#ifndef PRODUCT if (PrintDeoptimizationDetails) { tty->print_cr("skip field reassignment for this vector - it should be assigned already"); if (Verbose) { @@ -1437,12 +1428,13 @@ void Deoptimization::reassign_fields(frame* fr, RegisterMap* reg_map, GrowableAr k->oop_print_on(obj(), tty); } } +#endif // !PRODUCT continue; // Such vector's value was already restored in VectorSupport::allocate_vector(). } // Else fall-through to do assignment for scalar-replaced boxed vector representation // which could be restored after vector object allocation. } -#endif +#endif /* !COMPILER2 */ if (k->is_instance_klass()) { InstanceKlass* ik = InstanceKlass::cast(k); reassign_fields_by_klass(ik, fr, reg_map, sv, 0, obj(), skip_internal); @@ -1500,36 +1492,6 @@ bool Deoptimization::relock_objects(JavaThread* thread, GrowableArray* chunk, bool realloc_failures) { Events::log_deopt_message(thread, "DEOPT PACKING pc=" INTPTR_FORMAT " sp=" INTPTR_FORMAT, p2i(fr.pc()), p2i(fr.sp())); -#ifndef PRODUCT - if (PrintDeoptimizationDetails) { - ResourceMark rm; - stringStream st; - st.print("DEOPT PACKING thread " INTPTR_FORMAT " ", p2i(thread)); - fr.print_on(&st); - st.print_cr(" Virtual frames (innermost first):"); - for (int index = 0; index < chunk->length(); index++) { - compiledVFrame* vf = chunk->at(index); - st.print(" %2d - ", index); - vf->print_value_on(&st); - int bci = chunk->at(index)->raw_bci(); - const char* code_name; - if (bci == SynchronizationEntryBCI) { - code_name = "sync entry"; - } else { - Bytecodes::Code code = vf->method()->code_at(bci); - code_name = Bytecodes::name(code); - } - st.print(" - %s", code_name); - st.print_cr(" @ bci %d ", bci); - if (Verbose) { - vf->print_on(&st); - st.cr(); - } - } - tty->print_raw(st.as_string()); - } -#endif - // Register map for next frame (used for stack crawl). We capture // the state of the deopt'ing frame's caller. Thus if we need to // stuff a C2I adapter we can properly fill in the callee-save @@ -1547,11 +1509,32 @@ vframeArray* Deoptimization::create_vframeArray(JavaThread* thread, frame fr, Re // Compare the vframeArray to the collected vframes assert(array->structural_compare(thread, chunk), "just checking"); -#ifndef PRODUCT - if (PrintDeoptimizationDetails) { - tty->print_cr(" Created vframeArray " INTPTR_FORMAT, p2i(array)); + if (TraceDeoptimization) { + ResourceMark rm; + stringStream st; + st.print_cr("DEOPT PACKING thread=" INTPTR_FORMAT " vframeArray=" INTPTR_FORMAT, p2i(thread), p2i(array)); + st.print(" "); + fr.print_on(&st); + st.print_cr(" Virtual frames (innermost/newest first):"); + for (int index = 0; index < chunk->length(); index++) { + compiledVFrame* vf = chunk->at(index); + int bci = vf->raw_bci(); + const char* code_name; + if (bci == SynchronizationEntryBCI) { + code_name = "sync entry"; + } else { + Bytecodes::Code code = vf->method()->code_at(bci); + code_name = Bytecodes::name(code); + } + + st.print(" VFrame %d (" INTPTR_FORMAT ")", index, p2i(vf)); + st.print(" - %s", vf->method()->name_and_sig_as_C_string()); + st.print(" - %s", code_name); + st.print_cr(" @ bci=%d ", bci); + } + tty->print_raw(st.as_string()); + tty->cr(); } -#endif // PRODUCT return array; } @@ -1818,6 +1801,7 @@ JRT_ENTRY(void, Deoptimization::uncommon_trap_inner(JavaThread* current, jint tr // handler. Note this fact before we start generating temporary frames // that can confuse an asynchronous stack walker. This counter is // decremented at the end of unpack_frames(). + current->inc_in_deopt_handler(); #if INCLUDE_JVMCI @@ -1855,12 +1839,10 @@ JRT_ENTRY(void, Deoptimization::uncommon_trap_inner(JavaThread* current, jint tr bool is_receiver_constraint_failure = COMPILER2_PRESENT(VerifyReceiverTypes &&) (reason == Deoptimization::Reason_receiver_constraint); - if (TraceDeoptimization || is_receiver_constraint_failure) { - tty->print_cr(" bci=%d pc=" INTPTR_FORMAT ", relative_pc=" INTPTR_FORMAT ", method=%s" JVMCI_ONLY(", debug_id=%d"), trap_scope->bci(), p2i(fr.pc()), fr.pc() - nm->code_begin(), trap_scope->method()->name_and_sig_as_C_string() -#if INCLUDE_JVMCI - , debug_id -#endif - ); + if (is_receiver_constraint_failure) { + tty->print_cr(" bci=%d pc=" INTPTR_FORMAT ", relative_pc=" INTPTR_FORMAT ", method=%s" JVMCI_ONLY(", debug_id=%d"), + trap_scope->bci(), p2i(fr.pc()), fr.pc() - nm->code_begin(), trap_scope->method()->name_and_sig_as_C_string() + JVMCI_ONLY(COMMA debug_id)); } methodHandle trap_method(current, trap_scope->method()); @@ -1966,18 +1948,20 @@ JRT_ENTRY(void, Deoptimization::uncommon_trap_inner(JavaThread* current, jint tr xtty->end_head(); } if (TraceDeoptimization) { // make noise on the tty - tty->print("Uncommon trap occurred in"); - nm->method()->print_short_name(tty); - tty->print(" compiler=%s compile_id=%d", nm->compiler_name(), nm->compile_id()); + stringStream st; + st.print("UNCOMMON TRAP method=%s", trap_scope->method()->name_and_sig_as_C_string()); + st.print(" bci=%d pc=" INTPTR_FORMAT ", relative_pc=" INTPTR_FORMAT JVMCI_ONLY(", debug_id=%d"), + trap_scope->bci(), p2i(fr.pc()), fr.pc() - nm->code_begin() JVMCI_ONLY(COMMA debug_id)); + st.print(" compiler=%s compile_id=%d", nm->compiler_name(), nm->compile_id()); #if INCLUDE_JVMCI if (nm->is_nmethod()) { const char* installed_code_name = nm->as_nmethod()->jvmci_name(); if (installed_code_name != NULL) { - tty->print(" (JVMCI: installed code name=%s) ", installed_code_name); + st.print(" (JVMCI: installed code name=%s) ", installed_code_name); } } #endif - tty->print(" (@" INTPTR_FORMAT ") thread=" UINTX_FORMAT " reason=%s action=%s unloaded_class_index=%d" JVMCI_ONLY(" debug_id=%d"), + st.print(" (@" INTPTR_FORMAT ") thread=" UINTX_FORMAT " reason=%s action=%s unloaded_class_index=%d" JVMCI_ONLY(" debug_id=%d"), p2i(fr.pc()), os::current_thread_id(), trap_reason_name(reason), @@ -1988,10 +1972,11 @@ JRT_ENTRY(void, Deoptimization::uncommon_trap_inner(JavaThread* current, jint tr #endif ); if (class_name != NULL) { - tty->print(unresolved ? " unresolved class: " : " symbol: "); - class_name->print_symbol_on(tty); + st.print(unresolved ? " unresolved class: " : " symbol: "); + class_name->print_symbol_on(&st); } - tty->cr(); + st.cr(); + tty->print_raw(st.as_string()); } if (xtty != NULL) { // Log the precise location of the trap. @@ -2370,9 +2355,6 @@ Deoptimization::UnrollBlock* Deoptimization::uncommon_trap(JavaThread* current, // Enable WXWrite: current function is called from methods compiled by C2 directly MACOS_AARCH64_ONLY(ThreadWXEnable wx(WXWrite, current)); - if (TraceDeoptimization) { - tty->print("Uncommon trap "); - } // Still in Java no safepoints { // This enters VM and may safepoint diff --git a/src/hotspot/share/runtime/frame.cpp b/src/hotspot/share/runtime/frame.cpp index 528fb904c3a..7a6456ef658 100644 --- a/src/hotspot/share/runtime/frame.cpp +++ b/src/hotspot/share/runtime/frame.cpp @@ -442,16 +442,13 @@ void frame::print_value_on(outputStream* st, JavaThread *thread) const { if (sp() != NULL) st->print(", fp=" INTPTR_FORMAT ", real_fp=" INTPTR_FORMAT ", pc=" INTPTR_FORMAT, p2i(fp()), p2i(real_fp()), p2i(pc())); + st->print_cr(")"); if (StubRoutines::contains(pc())) { - st->print_cr(")"); - st->print("("); StubCodeDesc* desc = StubCodeDesc::desc_for(pc()); st->print("~Stub::%s", desc->name()); NOT_PRODUCT(begin = desc->begin(); end = desc->end();) } else if (Interpreter::contains(pc())) { - st->print_cr(")"); - st->print("("); InterpreterCodelet* desc = Interpreter::codelet_containing(pc()); if (desc != NULL) { st->print("~"); @@ -461,20 +458,18 @@ void frame::print_value_on(outputStream* st, JavaThread *thread) const { st->print("~interpreter"); } } - st->print_cr(")"); +#ifndef PRODUCT if (_cb != NULL) { st->print(" "); _cb->print_value_on(st); - st->cr(); -#ifndef PRODUCT if (end == NULL) { begin = _cb->code_begin(); end = _cb->code_end(); } -#endif } - NOT_PRODUCT(if (WizardMode && Verbose) Disassembler::decode(begin, end);) + if (WizardMode && Verbose) Disassembler::decode(begin, end); +#endif } diff --git a/src/hotspot/share/runtime/vframe.cpp b/src/hotspot/share/runtime/vframe.cpp index adf3c938d8d..14f4ee3a28c 100644 --- a/src/hotspot/share/runtime/vframe.cpp +++ b/src/hotspot/share/runtime/vframe.cpp @@ -608,13 +608,11 @@ javaVFrame* vframeStreamCommon::asJavaVFrame() { return result; } - #ifndef PRODUCT void vframe::print() { if (WizardMode) _fr.print_value_on(tty,NULL); } - void vframe::print_value() const { ((vframe*)this)->print(); } diff --git a/src/hotspot/share/runtime/vframeArray.cpp b/src/hotspot/share/runtime/vframeArray.cpp index 0d6417037c6..2106ed7ef7c 100644 --- a/src/hotspot/share/runtime/vframeArray.cpp +++ b/src/hotspot/share/runtime/vframeArray.cpp @@ -324,9 +324,11 @@ void vframeArrayElement::unpack_on_stack(int caller_actual_parameters, } } +#ifndef PRODUCT if (PrintDeoptimizationDetails) { tty->print_cr("Expressions size: %d", expressions()->size()); } +#endif // !PRODUCT // Unpack expression stack // If this is an intermediate frame (i.e. not top frame) then this @@ -343,15 +345,15 @@ void vframeArrayElement::unpack_on_stack(int caller_actual_parameters, *addr = value->get_int(); #ifndef PRODUCT if (PrintDeoptimizationDetails) { - tty->print_cr("Reconstructed expression %d (INT): %d", i, (int)(*addr)); + tty->print_cr(" - Reconstructed expression %d (INT): %d", i, (int)(*addr)); } -#endif +#endif // !PRODUCT break; case T_OBJECT: *addr = value->get_int(T_OBJECT); #ifndef PRODUCT if (PrintDeoptimizationDetails) { - tty->print("Reconstructed expression %d (OBJECT): ", i); + tty->print(" - Reconstructed expression %d (OBJECT): ", i); oop o = cast_to_oop((address)(*addr)); if (o == NULL) { tty->print_cr("NULL"); @@ -360,7 +362,7 @@ void vframeArrayElement::unpack_on_stack(int caller_actual_parameters, tty->print_raw_cr(o->klass()->name()->as_C_string()); } } -#endif +#endif // !PRODUCT break; case T_CONFLICT: // A dead stack slot. Initialize to null in case it is an oop. @@ -371,6 +373,11 @@ void vframeArrayElement::unpack_on_stack(int caller_actual_parameters, } } +#ifndef PRODUCT + if (PrintDeoptimizationDetails) { + tty->print_cr("Locals size: %d", locals()->size()); + } +#endif // !PRODUCT // Unpack the locals for(i = 0; i < locals()->size(); i++) { @@ -382,15 +389,15 @@ void vframeArrayElement::unpack_on_stack(int caller_actual_parameters, *addr = value->get_int(); #ifndef PRODUCT if (PrintDeoptimizationDetails) { - tty->print_cr("Reconstructed local %d (INT): %d", i, (int)(*addr)); + tty->print_cr(" - Reconstructed local %d (INT): %d", i, (int)(*addr)); } -#endif +#endif // !PRODUCT break; case T_OBJECT: *addr = value->get_int(T_OBJECT); #ifndef PRODUCT if (PrintDeoptimizationDetails) { - tty->print("Reconstructed local %d (OBJECT): ", i); + tty->print(" - Reconstructed local %d (OBJECT): ", i); oop o = cast_to_oop((address)(*addr)); if (o == NULL) { tty->print_cr("NULL"); @@ -399,7 +406,7 @@ void vframeArrayElement::unpack_on_stack(int caller_actual_parameters, tty->print_raw_cr(o->klass()->name()->as_C_string()); } } -#endif +#endif // !PRODUCT break; case T_CONFLICT: // A dead location. If it is an oop then we need a NULL to prevent GC from following it @@ -443,28 +450,15 @@ void vframeArrayElement::unpack_on_stack(int caller_actual_parameters, #ifndef PRODUCT if (PrintDeoptimizationDetails) { ttyLocker ttyl; - tty->print_cr("[%d Interpreted Frame]", ++unpack_counter); + tty->print_cr("[%d. Interpreted Frame]", ++unpack_counter); iframe()->print_on(tty); RegisterMap map(thread); vframe* f = vframe::new_vframe(iframe(), &map, thread); f->print(); - - tty->print_cr("locals size %d", locals()->size()); - tty->print_cr("expression size %d", expressions()->size()); - - method()->print_value(); + if (WizardMode && Verbose) method()->print_codes(); tty->cr(); - // method()->print_codes(); - } else if (TraceDeoptimization) { - tty->print(" "); - method()->print_value(); - Bytecodes::Code code = Bytecodes::java_code_at(method(), bcp); - int bci = method()->bci_from(bcp); - tty->print(" - %s", Bytecodes::name(code)); - tty->print(" @ bci %d ", bci); - tty->print_cr("sp = " PTR_FORMAT, p2i(iframe()->sp())); } -#endif // PRODUCT +#endif // !PRODUCT // The expression stack and locals are in the resource area don't leave // a dangling pointer in the vframeArray we leave around for debug @@ -571,6 +565,7 @@ void vframeArray::unpack_to_stack(frame &unpack_frame, int exec_mode, int caller // Find the skeletal interpreter frames to unpack into JavaThread* current = JavaThread::current(); + RegisterMap map(current, false); // Get the youngest frame we will unpack (last to be unpacked) frame me = unpack_frame.sender(&map); @@ -581,6 +576,18 @@ void vframeArray::unpack_to_stack(frame &unpack_frame, int exec_mode, int caller me = me.sender(&map); } + Events::log_deopt_message(current, "DEOPT UNPACKING pc=" INTPTR_FORMAT " sp=" INTPTR_FORMAT " mode %d", + p2i(unpack_frame.pc()), p2i(unpack_frame.sp()), exec_mode); + + if (TraceDeoptimization) { + ResourceMark rm; + stringStream st; + st.print_cr("DEOPT UNPACKING thread=" INTPTR_FORMAT " vframeArray=" INTPTR_FORMAT " mode=%d", + p2i(current), p2i(this), exec_mode); + st.print_cr(" Virtual frames (outermost/oldest first):"); + tty->print_raw(st.as_string()); + } + // Do the unpacking of interpreter frames; the frame at index 0 represents the top activation, so it has no callee // Unpack the frames from the oldest (frames() -1) to the youngest (0) frame* caller_frame = &me; @@ -600,6 +607,24 @@ void vframeArray::unpack_to_stack(frame &unpack_frame, int exec_mode, int caller callee_parameters = callee->size_of_parameters() + (has_member_arg ? 1 : 0); callee_locals = callee->max_locals(); } + if (TraceDeoptimization) { + ResourceMark rm; + stringStream st; + st.print(" VFrame %d (" INTPTR_FORMAT ")", index, p2i(elem)); + st.print(" - %s", elem->method()->name_and_sig_as_C_string()); + int bci = elem->raw_bci(); + const char* code_name; + if (bci == SynchronizationEntryBCI) { + code_name = "sync entry"; + } else { + Bytecodes::Code code = elem->method()->code_at(bci); + code_name = Bytecodes::name(code); + } + st.print(" - %s", code_name); + st.print(" @ bci=%d ", bci); + st.print_cr("sp=" PTR_FORMAT, p2i(elem->iframe()->sp())); + tty->print_raw(st.as_string()); + } elem->unpack_on_stack(caller_actual_parameters, callee_parameters, callee_locals, @@ -614,6 +639,9 @@ void vframeArray::unpack_to_stack(frame &unpack_frame, int exec_mode, int caller caller_actual_parameters = callee_parameters; } deallocate_monitor_chunks(); + if (TraceDeoptimization) { + tty->cr(); + } } void vframeArray::deallocate_monitor_chunks() { @@ -641,7 +669,7 @@ bool vframeArray::structural_compare(JavaThread* thread, GrowableArray Date: Mon, 10 Jan 2022 11:41:14 +0000 Subject: [PATCH 039/564] 8278344: sun/security/pkcs12/KeytoolOpensslInteropTest.java test fails because of different openssl output Backport-of: 8b5ff4bdffc8f32317d67b00c085071d6c772b30 --- test/jdk/sun/security/pkcs12/KeytoolOpensslInteropTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/jdk/sun/security/pkcs12/KeytoolOpensslInteropTest.java b/test/jdk/sun/security/pkcs12/KeytoolOpensslInteropTest.java index da655c90a49..7fcbd95ca7d 100644 --- a/test/jdk/sun/security/pkcs12/KeytoolOpensslInteropTest.java +++ b/test/jdk/sun/security/pkcs12/KeytoolOpensslInteropTest.java @@ -462,7 +462,7 @@ public class KeytoolOpensslInteropTest { "pkcs12", "-in", "ksnormal", "-passin", "pass:changeit", "-info", "-nokeys", "-nocerts"); output1.shouldHaveExitValue(0) - .shouldContain("MAC: sha256, Iteration 10000") + .shouldContain("MAC:").shouldContain("sha256").shouldContain("Iteration 10000") .shouldContain("Shrouded Keybag: PBES2, PBKDF2, AES-256-CBC," + " Iteration 10000, PRF hmacWithSHA256") .shouldContain("PKCS7 Encrypted data: PBES2, PBKDF2, AES-256-CBC," @@ -505,7 +505,7 @@ public class KeytoolOpensslInteropTest { "ksnewic", "-passin", "pass:changeit", "-info", "-nokeys", "-nocerts"); output1.shouldHaveExitValue(0) - .shouldContain("MAC: sha256, Iteration 5555") + .shouldContain("MAC:").shouldContain("sha256").shouldContain("Iteration 5555") .shouldContain("Shrouded Keybag: PBES2, PBKDF2, AES-256-CBC," + " Iteration 7777, PRF hmacWithSHA256") .shouldContain("Shrouded Keybag: pbeWithSHA1And128BitRC4," -- GitLab From 6613ce64d76a6cc40fd933b022834098721b8d23 Mon Sep 17 00:00:00 2001 From: Sergey Nazarkin Date: Mon, 10 Jan 2022 11:54:15 +0000 Subject: [PATCH 040/564] 8279300: [arm32] SIGILL when running GetObjectSizeIntrinsicsTest Reviewed-by: shade --- src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp b/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp index 920e6c87c4f..f7ffe84618d 100644 --- a/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp +++ b/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp @@ -1680,6 +1680,9 @@ void LIR_Assembler::logic_op(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr } else { assert(right->is_constant(), "must be"); const uint c = (uint)right->as_constant_ptr()->as_jint(); + if (!Assembler::is_arith_imm_in_range(c)) { + BAILOUT("illegal arithmetic operand"); + } switch (code) { case lir_logic_and: __ and_32(res, lreg, c); break; case lir_logic_or: __ orr_32(res, lreg, c); break; -- GitLab From 354c9047987c0837d95440780993a0aa84551ea1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Walln=C3=B6fer?= Date: Mon, 10 Jan 2022 12:04:01 +0000 Subject: [PATCH 041/564] 8273452: DocTrees.getDocCommentTree should be specified as idempotent Reviewed-by: jjg --- .../classes/com/sun/source/util/DocTrees.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/jdk.compiler/share/classes/com/sun/source/util/DocTrees.java b/src/jdk.compiler/share/classes/com/sun/source/util/DocTrees.java index a1344aff555..5a9aee518a1 100644 --- a/src/jdk.compiler/share/classes/com/sun/source/util/DocTrees.java +++ b/src/jdk.compiler/share/classes/com/sun/source/util/DocTrees.java @@ -87,6 +87,11 @@ public abstract class DocTrees extends Trees { /** * Returns the doc comment tree, if any, for the Tree node identified by a given TreePath. * Returns {@code null} if no doc comment was found. + * + * @implNote The default implementation of this method returns the same + * {@code DocCommentTree} instance for repeated invocations + * with the same argument. + * * @param path the path for the tree node * @return the doc comment tree */ @@ -95,6 +100,11 @@ public abstract class DocTrees extends Trees { /** * Returns the doc comment tree of the given element. * Returns {@code null} if no doc comment was found. + * + * @implNote The default implementation of this method returns the same + * {@code DocCommentTree} instance for repeated invocations + * with the same argument. + * * @param e an element whose documentation is required * @return the doc comment tree * @@ -109,6 +119,9 @@ public abstract class DocTrees extends Trees { * Returns {@code null} if no doc comment was found. * Future releases may support additional file types. * + * @implNote The default implementation of this method returns a + * new {@code DocCommentTree} instance for each invocation. + * * @param fileObject the content container * @return the doc comment tree * @since 9 @@ -123,6 +136,9 @@ public abstract class DocTrees extends Trees { * Returns {@code null} if no doc comment was found. * Future releases may support additional file types. * + * @implNote The default implementation of this method returns a + * new {@code DocCommentTree} instance for each invocation. + * * @param e an element whose path is used as a reference * @param relativePath the relative path from the Element * @return the doc comment tree -- GitLab From 928e34773694dda5373027848a3363887bcaf4f4 Mon Sep 17 00:00:00 2001 From: Fairoz Matte Date: Mon, 10 Jan 2022 12:36:05 +0000 Subject: [PATCH 042/564] 8279032: compiler/loopopts/TestSkeletonPredicateNegation.java times out with -XX:TieredStopAtLevel < 4 Reviewed-by: chagedorn, thartmann --- .../jtreg/compiler/loopopts/TestSkeletonPredicateNegation.java | 1 + 1 file changed, 1 insertion(+) diff --git a/test/hotspot/jtreg/compiler/loopopts/TestSkeletonPredicateNegation.java b/test/hotspot/jtreg/compiler/loopopts/TestSkeletonPredicateNegation.java index cbb82a07ea0..e7fb0be85ea 100644 --- a/test/hotspot/jtreg/compiler/loopopts/TestSkeletonPredicateNegation.java +++ b/test/hotspot/jtreg/compiler/loopopts/TestSkeletonPredicateNegation.java @@ -24,6 +24,7 @@ /** * @test + * @requires vm.compiler2.enabled * @bug 8273277 * @summary Skeleton predicates sometimes need to be negated * @run main compiler.loopopts.TestSkeletonPredicateNegation -- GitLab From 4ff6720573f9b55eb397d1aac9b398228faf2ceb Mon Sep 17 00:00:00 2001 From: Harold Seigel Date: Mon, 10 Jan 2022 13:18:41 +0000 Subject: [PATCH 043/564] 8183227: read/write APIs in class os shall return ssize_t Reviewed-by: fparain, rehn --- src/hotspot/os/linux/attachListener_linux.cpp | 4 +-- src/hotspot/os/posix/os_posix.cpp | 8 ++--- src/hotspot/os/posix/perfMemory_posix.cpp | 30 +++++++++---------- src/hotspot/os/windows/os_windows.cpp | 4 +-- src/hotspot/share/cds/filemap.cpp | 4 +-- .../writers/jfrStreamWriterHost.inline.hpp | 4 +-- src/hotspot/share/prims/jvm.cpp | 4 +-- src/hotspot/share/runtime/os.hpp | 4 +-- .../share/services/heapDumperCompression.cpp | 3 +- src/hotspot/share/utilities/ostream.cpp | 4 +-- 10 files changed, 34 insertions(+), 35 deletions(-) diff --git a/src/hotspot/os/linux/attachListener_linux.cpp b/src/hotspot/os/linux/attachListener_linux.cpp index 628c3f1c462..eb723603b5f 100644 --- a/src/hotspot/os/linux/attachListener_linux.cpp +++ b/src/hotspot/os/linux/attachListener_linux.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2022, 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 @@ -385,7 +385,7 @@ LinuxAttachOperation* LinuxAttachListener::dequeue() { // write the given buffer to the socket int LinuxAttachListener::write_fully(int s, char* buf, int len) { do { - int n = ::write(s, buf, len); + ssize_t n = ::write(s, buf, len); if (n == -1) { if (errno != EINTR) return -1; } else { diff --git a/src/hotspot/os/posix/os_posix.cpp b/src/hotspot/os/posix/os_posix.cpp index 3c990588562..02681662efb 100644 --- a/src/hotspot/os/posix/os_posix.cpp +++ b/src/hotspot/os/posix/os_posix.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2022, 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 @@ -679,9 +679,9 @@ FILE* os::open(int fd, const char* mode) { return ::fdopen(fd, mode); } -size_t os::write(int fd, const void *buf, unsigned int nBytes) { - size_t res; - RESTARTABLE((size_t) ::write(fd, buf, (size_t) nBytes), res); +ssize_t os::write(int fd, const void *buf, unsigned int nBytes) { + ssize_t res; + RESTARTABLE(::write(fd, buf, (size_t) nBytes), res); return res; } diff --git a/src/hotspot/os/posix/perfMemory_posix.cpp b/src/hotspot/os/posix/perfMemory_posix.cpp index 5d0448246bf..1a9a315042e 100644 --- a/src/hotspot/os/posix/perfMemory_posix.cpp +++ b/src/hotspot/os/posix/perfMemory_posix.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2021 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -98,21 +98,20 @@ static void save_memory_to_file(char* addr, size_t size) { const char* destfile = PerfMemory::get_perfdata_file_path(); assert(destfile[0] != '\0', "invalid PerfData file path"); - int result; + int fd; - RESTARTABLE(os::open(destfile, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR|S_IWUSR), - result); - if (result == OS_ERR) { + RESTARTABLE(os::open(destfile, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR|S_IWUSR), fd); + if (fd == OS_ERR) { if (PrintMiscellaneous && Verbose) { warning("Could not create Perfdata save file: %s: %s\n", destfile, os::strerror(errno)); } } else { - int fd = result; + ssize_t result; for (size_t remaining = size; remaining > 0;) { - RESTARTABLE(::write(fd, addr, remaining), result); + result = os::write(fd, addr, remaining); if (result == OS_ERR) { if (PrintMiscellaneous && Verbose) { warning("Could not write Perfdata save file: %s: %s\n", @@ -125,7 +124,7 @@ static void save_memory_to_file(char* addr, size_t size) { addr += result; } - result = ::close(fd); + result = os::close(fd); if (PrintMiscellaneous && Verbose) { if (result == OS_ERR) { warning("Could not close %s: %s\n", destfile, os::strerror(errno)); @@ -842,9 +841,9 @@ static int create_sharedmem_resources(const char* dirname, const char* filename, // Open the filename in the current directory. // Cannot use O_TRUNC here; truncation of an existing file has to happen // after the is_file_secure() check below. - int result; - RESTARTABLE(os::open(filename, O_RDWR|O_CREAT|O_NOFOLLOW, S_IRUSR|S_IWUSR), result); - if (result == OS_ERR) { + int fd; + RESTARTABLE(os::open(filename, O_RDWR|O_CREAT|O_NOFOLLOW, S_IRUSR|S_IWUSR), fd); + if (fd == OS_ERR) { if (PrintMiscellaneous && Verbose) { if (errno == ELOOP) { warning("file %s is a symlink and is not secure\n", filename); @@ -860,15 +859,14 @@ static int create_sharedmem_resources(const char* dirname, const char* filename, // close the directory and reset the current working directory close_directory_secure_cwd(dirp, saved_cwd_fd); - // save the file descriptor - int fd = result; - // check to see if the file is secure if (!is_file_secure(fd, filename)) { ::close(fd); return -1; } + ssize_t result; + // truncate the file to get rid of any existing data RESTARTABLE(::ftruncate(fd, (off_t)0), result); if (result == OS_ERR) { @@ -895,7 +893,7 @@ static int create_sharedmem_resources(const char* dirname, const char* filename, int zero_int = 0; result = (int)os::seek_to_file_offset(fd, (jlong)(seekpos)); if (result == -1 ) break; - RESTARTABLE(::write(fd, &zero_int, 1), result); + result = os::write(fd, &zero_int, 1); if (result != 1) { if (errno == ENOSPC) { warning("Insufficient space for shared memory file:\n %s\nTry using the -Djava.io.tmpdir= option to select an alternate temp location.\n", filename); @@ -907,7 +905,7 @@ static int create_sharedmem_resources(const char* dirname, const char* filename, if (result != -1) { return fd; } else { - ::close(fd); + os::close(fd); return -1; } } diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index e129b447cfd..93cd4be53af 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -4758,7 +4758,7 @@ FILE* os::open(int fd, const char* mode) { return ::_fdopen(fd, mode); } -size_t os::write(int fd, const void *buf, unsigned int nBytes) { +ssize_t os::write(int fd, const void *buf, unsigned int nBytes) { return ::write(fd, buf, nBytes); } diff --git a/src/hotspot/share/cds/filemap.cpp b/src/hotspot/share/cds/filemap.cpp index 7bd31310db6..f4a9b8dec03 100644 --- a/src/hotspot/share/cds/filemap.cpp +++ b/src/hotspot/share/cds/filemap.cpp @@ -1613,8 +1613,8 @@ size_t FileMapInfo::write_heap_regions(GrowableArray* regions, void FileMapInfo::write_bytes(const void* buffer, size_t nbytes) { assert(_file_open, "must be"); - size_t n = os::write(_fd, buffer, (unsigned int)nbytes); - if (n != nbytes) { + ssize_t n = os::write(_fd, buffer, (unsigned int)nbytes); + if (n < 0 || (size_t)n != nbytes) { // If the shared archive is corrupted, close it and remove it. close(); remove(_full_path); diff --git a/src/hotspot/share/jfr/writers/jfrStreamWriterHost.inline.hpp b/src/hotspot/share/jfr/writers/jfrStreamWriterHost.inline.hpp index dd232fdd026..ceb5e7fe027 100644 --- a/src/hotspot/share/jfr/writers/jfrStreamWriterHost.inline.hpp +++ b/src/hotspot/share/jfr/writers/jfrStreamWriterHost.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -76,7 +76,7 @@ inline void StreamWriterHost::write_bytes(const u1* buf, intptr_t l assert(len >= 0, "invariant"); while (len > 0) { const unsigned int nBytes = len > INT_MAX ? INT_MAX : (unsigned int)len; - const ssize_t num_written = (ssize_t)os::write(_fd, buf, nBytes); + const ssize_t num_written = os::write(_fd, buf, nBytes); guarantee(num_written > 0, "Nothing got written, or os::write() failed"); _stream_pos += num_written; len -= num_written; diff --git a/src/hotspot/share/prims/jvm.cpp b/src/hotspot/share/prims/jvm.cpp index a5c7e2ee582..776e1d10011 100644 --- a/src/hotspot/share/prims/jvm.cpp +++ b/src/hotspot/share/prims/jvm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -2836,7 +2836,7 @@ void jio_print(const char* s, size_t len) { jio_fprintf(defaultStream::output_stream(), "%.*s", (int)len, s); } else { // Make an unused local variable to avoid warning from gcc compiler. - size_t count = ::write(defaultStream::output_fd(), s, (int)len); + ssize_t count = os::write(defaultStream::output_fd(), s, (int)len); } } diff --git a/src/hotspot/share/runtime/os.hpp b/src/hotspot/share/runtime/os.hpp index 45ed150ec7a..2070318c031 100644 --- a/src/hotspot/share/runtime/os.hpp +++ b/src/hotspot/share/runtime/os.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -565,7 +565,7 @@ class os: AllStatic { static ssize_t read(int fd, void *buf, unsigned int nBytes); static ssize_t read_at(int fd, void *buf, unsigned int nBytes, jlong offset); - static size_t write(int fd, const void *buf, unsigned int nBytes); + static ssize_t write(int fd, const void *buf, unsigned int nBytes); // Reading directories. static DIR* opendir(const char* dirname); diff --git a/src/hotspot/share/services/heapDumperCompression.cpp b/src/hotspot/share/services/heapDumperCompression.cpp index 0d642601797..b341a6366ef 100644 --- a/src/hotspot/share/services/heapDumperCompression.cpp +++ b/src/hotspot/share/services/heapDumperCompression.cpp @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -54,7 +55,7 @@ char const* FileWriter::write_buf(char* buf, ssize_t size) { assert(_fd >= 0, "Must be open"); assert(size > 0, "Must write at least one byte"); - ssize_t n = (ssize_t) os::write(_fd, buf, (uint) size); + ssize_t n = os::write(_fd, buf, (uint) size); if (n <= 0) { return os::strerror(errno); diff --git a/src/hotspot/share/utilities/ostream.cpp b/src/hotspot/share/utilities/ostream.cpp index 04995064fe3..6b3a9465d0c 100644 --- a/src/hotspot/share/utilities/ostream.cpp +++ b/src/hotspot/share/utilities/ostream.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -614,7 +614,7 @@ void fileStream::flush() { void fdStream::write(const char* s, size_t len) { if (_fd != -1) { // Make an unused local variable to avoid warning from gcc compiler. - size_t count = ::write(_fd, s, (int)len); + ssize_t count = ::write(_fd, s, (int)len); update_position(s, len); } } -- GitLab From ad34f03b549e6f37825efc3e554d2232b557611a Mon Sep 17 00:00:00 2001 From: Vladimir Ivanov Date: Mon, 10 Jan 2022 13:56:01 +0000 Subject: [PATCH 044/564] 8279515: C1: No inlining through invokedynamic and invokestatic call sites when resolved class is not linked Reviewed-by: kvn, dlong --- src/hotspot/share/c1/c1_GraphBuilder.cpp | 6 +- src/hotspot/share/ci/ciStreams.cpp | 5 +- .../lang/invoke/InvokerBytecodeGenerator.java | 1 + .../compiler/inlining/ResolvedClassTest.java | 158 ++++++++++++++++++ 4 files changed, 166 insertions(+), 4 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/inlining/ResolvedClassTest.java diff --git a/src/hotspot/share/c1/c1_GraphBuilder.cpp b/src/hotspot/share/c1/c1_GraphBuilder.cpp index 2f9355f1099..0274505f8fe 100644 --- a/src/hotspot/share/c1/c1_GraphBuilder.cpp +++ b/src/hotspot/share/c1/c1_GraphBuilder.cpp @@ -2072,9 +2072,11 @@ void GraphBuilder::invoke(Bytecodes::Code code) { } // check if we could do inlining - if (!PatchALot && Inline && target->is_loaded() && callee_holder->is_linked() && !patch_for_appendix) { + if (!PatchALot && Inline && target->is_loaded() && !patch_for_appendix && + callee_holder->is_loaded()) { // the effect of symbolic reference resolution + // callee is known => check if we have static binding - if ((code == Bytecodes::_invokestatic && callee_holder->is_initialized()) || // invokestatic involves an initialization barrier on resolved klass + if ((code == Bytecodes::_invokestatic && klass->is_initialized()) || // invokestatic involves an initialization barrier on declaring class code == Bytecodes::_invokespecial || (code == Bytecodes::_invokevirtual && target->is_final_method()) || code == Bytecodes::_invokedynamic) { diff --git a/src/hotspot/share/ci/ciStreams.cpp b/src/hotspot/share/ci/ciStreams.cpp index 4e9895bfaed..a1e6c5bffe8 100644 --- a/src/hotspot/share/ci/ciStreams.cpp +++ b/src/hotspot/share/ci/ciStreams.cpp @@ -476,8 +476,9 @@ ciKlass* ciBytecodeStream::get_declared_method_holder() { constantPoolHandle cpool(THREAD, _method->get_Method()->constants()); bool ignore; // report as MethodHandle for invokedynamic, which is syntactically classless - if (cur_bc() == Bytecodes::_invokedynamic) - return CURRENT_ENV->get_klass_by_name(_holder, ciSymbols::java_lang_invoke_MethodHandle(), false); + if (cur_bc() == Bytecodes::_invokedynamic) { + return CURRENT_ENV->MethodHandle_klass(); + } return CURRENT_ENV->get_klass_by_index(cpool, get_method_holder_index(), ignore, _holder); } diff --git a/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java b/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java index c687916dde4..ca5bf8a7656 100644 --- a/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java +++ b/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java @@ -683,6 +683,7 @@ class InvokerBytecodeGenerator { } private static MemberName resolveFrom(String name, MethodType type, Class holder) { + assert(!UNSAFE.shouldBeInitialized(holder)) : holder + "not initialized"; MemberName member = new MemberName(holder, name, type, REF_invokeStatic); MemberName resolvedMember = MemberName.getFactory().resolveOrNull(REF_invokeStatic, member, holder, LM_TRUSTED); traceLambdaForm(name, type, holder, resolvedMember); diff --git a/test/hotspot/jtreg/compiler/inlining/ResolvedClassTest.java b/test/hotspot/jtreg/compiler/inlining/ResolvedClassTest.java new file mode 100644 index 00000000000..dfeee6cdd7b --- /dev/null +++ b/test/hotspot/jtreg/compiler/inlining/ResolvedClassTest.java @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2022, 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 8279515 + * + * @requires vm.flagless + * @modules java.base/jdk.internal.misc + * @library /test/lib / + * + * @run driver compiler.jsr292.ResolvedClassTest + */ + +package compiler.jsr292; + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +import java.io.IOException; + +public class ResolvedClassTest { + /* ======================================================================== */ + static void testStatic() throws IOException { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:+IgnoreUnrecognizedVMOptions", "-showversion", + "-XX:+PrintCompilation", "-XX:+UnlockDiagnosticVMOptions", "-XX:+PrintInlining", + "-Xbatch", "-XX:CompileCommand=quiet", "-XX:CompileCommand=compileonly," + TestStatic.class.getName() + "::test", + TestStatic.class.getName()); + + OutputAnalyzer analyzer = new OutputAnalyzer(pb.start()); + + analyzer.shouldHaveExitValue(0); + + analyzer.shouldNotContain("TestStatic$A::m (1 bytes) not inlineable"); + analyzer.shouldNotContain("TestStatic$A::m (1 bytes) no static binding"); + + analyzer.shouldContain("TestStatic$A::m (1 bytes) inline"); + } + + static class TestStatic { + static class A { + static void m() {} + } + static class B extends A {} + + // @DontInline + static void test() { + B.m(); // invokestatic B "m" => A::m + } + + public static void main(String[] args) { + for (int i = 0; i < 20_000; i++) { + test(); + } + } + } + + /* ======================================================================== */ + static void testStaticInit() throws IOException { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:+IgnoreUnrecognizedVMOptions", "-showversion", + "-XX:+PrintCompilation", "-XX:+UnlockDiagnosticVMOptions", "-XX:+PrintInlining", + "-Xbatch", "-XX:CompileCommand=quiet", "-XX:CompileCommand=compileonly," + TestStaticInit.class.getName() + "::test", + TestStaticInit.class.getName()); + + OutputAnalyzer analyzer = new OutputAnalyzer(pb.start()); + + analyzer.shouldHaveExitValue(0); + + analyzer.shouldContain("TestStaticInit$A::m (1 bytes) no static binding"); + } + + static class TestStaticInit { + static class A { + static { + for (int i = 0; i < 20_000; i++) { + TestStaticInit.test(); + } + } + + static void m() {} + } + static class B extends A {} + + // @DontInline + static void test() { + B.m(); // A:: => test() => A::m() + } + + public static void main(String[] args) { + A.m(); // trigger initialization of A + } + } + + /* ======================================================================== */ + static void testIndy() throws IOException { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:+IgnoreUnrecognizedVMOptions", "-showversion", + "-XX:+PrintCompilation", "-XX:+UnlockDiagnosticVMOptions", "-XX:+PrintInlining", + "-Xbatch", "-XX:CompileCommand=quiet", "-XX:CompileCommand=compileonly," + TestIndy.class.getName() + "::test", + TestIndy.class.getName()); + + OutputAnalyzer analyzer = new OutputAnalyzer(pb.start()); + + analyzer.shouldHaveExitValue(0); + + analyzer.shouldNotContain("java.lang.invoke.Invokers$Holder::linkToTargetMethod (9 bytes) not inlineable"); + + analyzer.shouldContain("java.lang.invoke.Invokers$Holder::linkToTargetMethod (9 bytes) force inline by annotation"); + analyzer.shouldContain("java/lang/invoke/MethodHandle::invokeBasic (not loaded) not inlineable"); + } + + static class TestIndy { + static String str = ""; + + // @DontInline + static void test() { + String s1 = "" + str; // indy (linked) + + for (int i = 0; i < 200_000; i++) {} // trigger OSR compilation + + String s2 = "" + str; // indy (not linked) + } + + public static void main(String[] args) { + test(); + } + } + + /* ======================================================================== */ + + public static void main(String[] args) throws IOException { + testStatic(); + testStaticInit(); + testIndy(); + } +} -- GitLab From 11d88ce82efd72d3d63f7c7271c285cd21b01217 Mon Sep 17 00:00:00 2001 From: Harold Seigel Date: Mon, 10 Jan 2022 13:57:45 +0000 Subject: [PATCH 045/564] 8218857: Confusing overloads for os::open Reviewed-by: kbarrett, rehn --- src/hotspot/os/posix/os_posix.cpp | 2 +- src/hotspot/os/windows/os_windows.cpp | 2 +- src/hotspot/share/cds/classListParser.cpp | 4 ++-- src/hotspot/share/ci/ciEnv.cpp | 6 +++--- src/hotspot/share/runtime/os.hpp | 2 +- src/hotspot/share/utilities/vmError.cpp | 4 ++-- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/hotspot/os/posix/os_posix.cpp b/src/hotspot/os/posix/os_posix.cpp index 02681662efb..3c32ec718a3 100644 --- a/src/hotspot/os/posix/os_posix.cpp +++ b/src/hotspot/os/posix/os_posix.cpp @@ -675,7 +675,7 @@ const char* os::get_current_directory(char *buf, size_t buflen) { return getcwd(buf, buflen); } -FILE* os::open(int fd, const char* mode) { +FILE* os::fdopen(int fd, const char* mode) { return ::fdopen(fd, mode); } diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index 93cd4be53af..b31f08e5ec2 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -4754,7 +4754,7 @@ int os::open(const char *path, int oflag, int mode) { return fd; } -FILE* os::open(int fd, const char* mode) { +FILE* os::fdopen(int fd, const char* mode) { return ::_fdopen(fd, mode); } diff --git a/src/hotspot/share/cds/classListParser.cpp b/src/hotspot/share/cds/classListParser.cpp index 66e346b1944..1da5e79377b 100644 --- a/src/hotspot/share/cds/classListParser.cpp +++ b/src/hotspot/share/cds/classListParser.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, 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 @@ -64,7 +64,7 @@ ClassListParser::ClassListParser(const char* file) : _id2klass_table(INITIAL_TAB if (fd != -1) { // Obtain a File* from the file descriptor so that fgets() // can be used in parse_one_line() - _file = os::open(fd, "r"); + _file = os::fdopen(fd, "r"); } if (_file == NULL) { char errmsg[JVM_MAXPATHLEN]; diff --git a/src/hotspot/share/ci/ciEnv.cpp b/src/hotspot/share/ci/ciEnv.cpp index e29b56a3f27..323d67c986f 100644 --- a/src/hotspot/share/ci/ciEnv.cpp +++ b/src/hotspot/share/ci/ciEnv.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2022, 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 @@ -1688,7 +1688,7 @@ void ciEnv::dump_replay_data(int compile_id) { if (ret > 0) { int fd = os::open(buffer, O_RDWR | O_CREAT | O_TRUNC, 0666); if (fd != -1) { - FILE* replay_data_file = os::open(fd, "w"); + FILE* replay_data_file = os::fdopen(fd, "w"); if (replay_data_file != NULL) { fileStream replay_data_stream(replay_data_file, /*need_close=*/true); dump_replay_data(&replay_data_stream); @@ -1706,7 +1706,7 @@ void ciEnv::dump_inline_data(int compile_id) { if (ret > 0) { int fd = os::open(buffer, O_RDWR | O_CREAT | O_TRUNC, 0666); if (fd != -1) { - FILE* inline_data_file = os::open(fd, "w"); + FILE* inline_data_file = os::fdopen(fd, "w"); if (inline_data_file != NULL) { fileStream replay_data_stream(inline_data_file, /*need_close=*/true); GUARDED_VM_ENTRY( diff --git a/src/hotspot/share/runtime/os.hpp b/src/hotspot/share/runtime/os.hpp index 2070318c031..67e427fd947 100644 --- a/src/hotspot/share/runtime/os.hpp +++ b/src/hotspot/share/runtime/os.hpp @@ -541,7 +541,7 @@ class os: AllStatic { // File i/o operations static int open(const char *path, int oflag, int mode); - static FILE* open(int fd, const char* mode); + static FILE* fdopen(int fd, const char* mode); static FILE* fopen(const char* path, const char* mode); static int close(int fd); static jlong lseek(int fd, jlong offset, int whence); diff --git a/src/hotspot/share/utilities/vmError.cpp b/src/hotspot/share/utilities/vmError.cpp index 4ae43cedf52..3fa50cc8ccb 100644 --- a/src/hotspot/share/utilities/vmError.cpp +++ b/src/hotspot/share/utilities/vmError.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2017, 2020 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -1676,7 +1676,7 @@ void VMError::report_and_die(int id, const char* message, const char* detail_fmt const bool overwrite = false; // We do not overwrite an existing replay file. int fd = prepare_log_file(ReplayDataFile, "replay_pid%p.log", overwrite, buffer, sizeof(buffer)); if (fd != -1) { - FILE* replay_data_file = os::open(fd, "w"); + FILE* replay_data_file = os::fdopen(fd, "w"); if (replay_data_file != NULL) { fileStream replay_data_stream(replay_data_file, /*need_close=*/true); env->dump_replay_data_unsafe(&replay_data_stream); -- GitLab From 76477f8cdbc012f7ff0670ad57067ebf304612a0 Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Mon, 10 Jan 2022 14:34:04 +0000 Subject: [PATCH 046/564] 8142362: Lots of code duplication in Copy class Reviewed-by: kvn, hseigel --- src/hotspot/cpu/aarch64/copy_aarch64.hpp | 164 +++++++++- src/hotspot/cpu/x86/copy_x86.hpp | 291 +++++++++++++++++- .../os_cpu/bsd_aarch64/copy_bsd_aarch64.hpp | 161 +--------- src/hotspot/os_cpu/bsd_x86/bsd_x86_32.S | 110 +------ src/hotspot/os_cpu/bsd_x86/copy_bsd_x86.hpp | 283 +---------------- .../linux_aarch64/copy_linux_aarch64.hpp | 161 +--------- src/hotspot/os_cpu/linux_arm/linux_arm_32.S | 8 +- .../os_cpu/linux_x86/copy_linux_x86.hpp | 283 +---------------- src/hotspot/os_cpu/linux_x86/linux_x86_32.S | 110 +------ .../os_cpu/windows_x86/copy_windows_x86.hpp | 60 +--- src/hotspot/share/utilities/copy.hpp | 12 +- 11 files changed, 466 insertions(+), 1177 deletions(-) diff --git a/src/hotspot/cpu/aarch64/copy_aarch64.hpp b/src/hotspot/cpu/aarch64/copy_aarch64.hpp index 3912ee086cf..0ff9ace59cc 100644 --- a/src/hotspot/cpu/aarch64/copy_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/copy_aarch64.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -52,4 +52,166 @@ static void pd_zero_to_bytes(void* to, size_t count) { (void)memset(to, 0, count); } +#ifndef _WINDOWS + +#define COPY_SMALL(from, to, count) \ +{ \ + long tmp0, tmp1, tmp2, tmp3; \ + long tmp4, tmp5, tmp6, tmp7; \ + __asm volatile( \ +" adr %[t0], 0f;\n" \ +" add %[t0], %[t0], %[cnt], lsl #5;\n" \ +" br %[t0];\n" \ +" .align 5;\n" \ +"0:" \ +" b 1f;\n" \ +" .align 5;\n" \ +" ldr %[t0], [%[s], #0];\n" \ +" str %[t0], [%[d], #0];\n" \ +" b 1f;\n" \ +" .align 5;\n" \ +" ldp %[t0], %[t1], [%[s], #0];\n" \ +" stp %[t0], %[t1], [%[d], #0];\n" \ +" b 1f;\n" \ +" .align 5;\n" \ +" ldp %[t0], %[t1], [%[s], #0];\n" \ +" ldr %[t2], [%[s], #16];\n" \ +" stp %[t0], %[t1], [%[d], #0];\n" \ +" str %[t2], [%[d], #16];\n" \ +" b 1f;\n" \ +" .align 5;\n" \ +" ldp %[t0], %[t1], [%[s], #0];\n" \ +" ldp %[t2], %[t3], [%[s], #16];\n" \ +" stp %[t0], %[t1], [%[d], #0];\n" \ +" stp %[t2], %[t3], [%[d], #16];\n" \ +" b 1f;\n" \ +" .align 5;\n" \ +" ldp %[t0], %[t1], [%[s], #0];\n" \ +" ldp %[t2], %[t3], [%[s], #16];\n" \ +" ldr %[t4], [%[s], #32];\n" \ +" stp %[t0], %[t1], [%[d], #0];\n" \ +" stp %[t2], %[t3], [%[d], #16];\n" \ +" str %[t4], [%[d], #32];\n" \ +" b 1f;\n" \ +" .align 5;\n" \ +" ldp %[t0], %[t1], [%[s], #0];\n" \ +" ldp %[t2], %[t3], [%[s], #16];\n" \ +" ldp %[t4], %[t5], [%[s], #32];\n" \ +"2:" \ +" stp %[t0], %[t1], [%[d], #0];\n" \ +" stp %[t2], %[t3], [%[d], #16];\n" \ +" stp %[t4], %[t5], [%[d], #32];\n" \ +" b 1f;\n" \ +" .align 5;\n" \ +" ldr %[t6], [%[s], #0];\n" \ +" ldp %[t0], %[t1], [%[s], #8];\n" \ +" ldp %[t2], %[t3], [%[s], #24];\n" \ +" ldp %[t4], %[t5], [%[s], #40];\n" \ +" str %[t6], [%[d]], #8;\n" \ +" b 2b;\n" \ +" .align 5;\n" \ +" ldp %[t0], %[t1], [%[s], #0];\n" \ +" ldp %[t2], %[t3], [%[s], #16];\n" \ +" ldp %[t4], %[t5], [%[s], #32];\n" \ +" ldp %[t6], %[t7], [%[s], #48];\n" \ +" stp %[t0], %[t1], [%[d], #0];\n" \ +" stp %[t2], %[t3], [%[d], #16];\n" \ +" stp %[t4], %[t5], [%[d], #32];\n" \ +" stp %[t6], %[t7], [%[d], #48];\n" \ +"1:" \ + \ + : [s]"+r"(from), [d]"+r"(to), [cnt]"+r"(count), \ + [t0]"=&r"(tmp0), [t1]"=&r"(tmp1), [t2]"=&r"(tmp2), [t3]"=&r"(tmp3), \ + [t4]"=&r"(tmp4), [t5]"=&r"(tmp5), [t6]"=&r"(tmp6), [t7]"=&r"(tmp7) \ + : \ + : "memory", "cc"); \ +} + +static void pd_conjoint_words(const HeapWord* from, HeapWord* to, size_t count) { + __asm volatile( "prfm pldl1strm, [%[s], #0];" :: [s]"r"(from) : "memory"); + if (__builtin_expect(count <= 8, 1)) { + COPY_SMALL(from, to, count); + return; + } + _Copy_conjoint_words(from, to, count); +} + +static void pd_disjoint_words(const HeapWord* from, HeapWord* to, size_t count) { + if (__builtin_constant_p(count)) { + memcpy(to, from, count * sizeof(HeapWord)); + return; + } + __asm volatile( "prfm pldl1strm, [%[s], #0];" :: [s]"r"(from) : "memory"); + if (__builtin_expect(count <= 8, 1)) { + COPY_SMALL(from, to, count); + return; + } + _Copy_disjoint_words(from, to, count); +} + +static void pd_disjoint_words_atomic(const HeapWord* from, HeapWord* to, size_t count) { + __asm volatile( "prfm pldl1strm, [%[s], #0];" :: [s]"r"(from) : "memory"); + if (__builtin_expect(count <= 8, 1)) { + COPY_SMALL(from, to, count); + return; + } + _Copy_disjoint_words(from, to, count); +} + +static void pd_aligned_conjoint_words(const HeapWord* from, HeapWord* to, size_t count) { + pd_conjoint_words(from, to, count); +} + +static void pd_aligned_disjoint_words(const HeapWord* from, HeapWord* to, size_t count) { + pd_disjoint_words(from, to, count); +} + +static void pd_conjoint_bytes(const void* from, void* to, size_t count) { + (void)memmove(to, from, count); +} + +static void pd_conjoint_bytes_atomic(const void* from, void* to, size_t count) { + pd_conjoint_bytes(from, to, count); +} + +static void pd_conjoint_jshorts_atomic(const jshort* from, jshort* to, size_t count) { + _Copy_conjoint_jshorts_atomic(from, to, count); +} + +static void pd_conjoint_jints_atomic(const jint* from, jint* to, size_t count) { + _Copy_conjoint_jints_atomic(from, to, count); +} + +static void pd_conjoint_jlongs_atomic(const jlong* from, jlong* to, size_t count) { + _Copy_conjoint_jlongs_atomic(from, to, count); +} + +static void pd_conjoint_oops_atomic(const oop* from, oop* to, size_t count) { + assert(BytesPerLong == BytesPerOop, "jlongs and oops must be the same size"); + _Copy_conjoint_jlongs_atomic((const jlong*)from, (jlong*)to, count); +} + +static void pd_arrayof_conjoint_bytes(const HeapWord* from, HeapWord* to, size_t count) { + _Copy_arrayof_conjoint_bytes(from, to, count); +} + +static void pd_arrayof_conjoint_jshorts(const HeapWord* from, HeapWord* to, size_t count) { + _Copy_arrayof_conjoint_jshorts(from, to, count); +} + +static void pd_arrayof_conjoint_jints(const HeapWord* from, HeapWord* to, size_t count) { + _Copy_arrayof_conjoint_jints(from, to, count); +} + +static void pd_arrayof_conjoint_jlongs(const HeapWord* from, HeapWord* to, size_t count) { + _Copy_arrayof_conjoint_jlongs(from, to, count); +} + +static void pd_arrayof_conjoint_oops(const HeapWord* from, HeapWord* to, size_t count) { + assert(!UseCompressedOops, "foo!"); + assert(BytesPerLong == BytesPerOop, "jlongs and oops must be the same size"); + _Copy_arrayof_conjoint_jlongs(from, to, count); +} +#endif // _WINDOWS + #endif // CPU_AARCH64_COPY_AARCH64_HPP diff --git a/src/hotspot/cpu/x86/copy_x86.hpp b/src/hotspot/cpu/x86/copy_x86.hpp index dc150a568af..74228b57f6c 100644 --- a/src/hotspot/cpu/x86/copy_x86.hpp +++ b/src/hotspot/cpu/x86/copy_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, 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 @@ -59,4 +59,293 @@ static void pd_zero_to_bytes(void* to, size_t count) { (void)memset(to, 0, count); } +static void pd_conjoint_words(const HeapWord* from, HeapWord* to, size_t count) { +#if defined AMD64 || defined _WINDOWS + (void)memmove(to, from, count * HeapWordSize); +#else + // Includes a zero-count check. + intx temp = 0; + __asm__ volatile(" testl %6,%6 ;" + " jz 7f ;" + " cmpl %4,%5 ;" + " leal -4(%4,%6,4),%3;" + " jbe 1f ;" + " cmpl %7,%5 ;" + " jbe 4f ;" + "1: cmpl $32,%6 ;" + " ja 3f ;" + " subl %4,%1 ;" + "2: movl (%4),%3 ;" + " movl %7,(%5,%4,1) ;" + " addl $4,%0 ;" + " subl $1,%2 ;" + " jnz 2b ;" + " jmp 7f ;" + "3: rep; smovl ;" + " jmp 7f ;" + "4: cmpl $32,%2 ;" + " movl %7,%0 ;" + " leal -4(%5,%6,4),%1;" + " ja 6f ;" + " subl %4,%1 ;" + "5: movl (%4),%3 ;" + " movl %7,(%5,%4,1) ;" + " subl $4,%0 ;" + " subl $1,%2 ;" + " jnz 5b ;" + " jmp 7f ;" + "6: std ;" + " rep; smovl ;" + " cld ;" + "7: nop " + : "=S" (from), "=D" (to), "=c" (count), "=r" (temp) + : "0" (from), "1" (to), "2" (count), "3" (temp) + : "memory", "flags"); +#endif // AMD64 +} + +static void pd_disjoint_words(const HeapWord* from, HeapWord* to, size_t count) { +#ifdef AMD64 + switch (count) { + case 8: to[7] = from[7]; + case 7: to[6] = from[6]; + case 6: to[5] = from[5]; + case 5: to[4] = from[4]; + case 4: to[3] = from[3]; + case 3: to[2] = from[2]; + case 2: to[1] = from[1]; + case 1: to[0] = from[0]; + case 0: break; + default: + (void)memcpy(to, from, count * HeapWordSize); + break; + } +#else +#if defined _WINDOWS + (void)memcpy(to, from, count * HeapWordSize); +#else + // Includes a zero-count check. + intx temp = 0; + __asm__ volatile(" testl %6,%6 ;" + " jz 3f ;" + " cmpl $32,%6 ;" + " ja 2f ;" + " subl %4,%1 ;" + "1: movl (%4),%3 ;" + " movl %7,(%5,%4,1);" + " addl $4,%0 ;" + " subl $1,%2 ;" + " jnz 1b ;" + " jmp 3f ;" + "2: rep; smovl ;" + "3: nop " + : "=S" (from), "=D" (to), "=c" (count), "=r" (temp) + : "0" (from), "1" (to), "2" (count), "3" (temp) + : "memory", "cc"); +#endif // _WINDOWS +#endif // AMD64 +} + +static void pd_disjoint_words_atomic(const HeapWord* from, HeapWord* to, size_t count) { +#ifdef AMD64 + switch (count) { + case 8: to[7] = from[7]; + case 7: to[6] = from[6]; + case 6: to[5] = from[5]; + case 5: to[4] = from[4]; + case 4: to[3] = from[3]; + case 3: to[2] = from[2]; + case 2: to[1] = from[1]; + case 1: to[0] = from[0]; + case 0: break; + default: + while (count-- > 0) { + *to++ = *from++; + } + break; + } +#else + // pd_disjoint_words is word-atomic in this implementation. + pd_disjoint_words(from, to, count); +#endif // AMD64 +} + +static void pd_aligned_conjoint_words(const HeapWord* from, HeapWord* to, size_t count) { + pd_conjoint_words(from, to, count); +} + +static void pd_aligned_disjoint_words(const HeapWord* from, HeapWord* to, size_t count) { + pd_disjoint_words(from, to, count); +} + +static void pd_conjoint_bytes(const void* from, void* to, size_t count) { +#if defined AMD64 || defined _WINDOWS + (void)memmove(to, from, count); +#else + // Includes a zero-count check. + intx temp = 0; + __asm__ volatile(" testl %6,%6 ;" + " jz 13f ;" + " cmpl %4,%5 ;" + " leal -1(%4,%6),%3 ;" + " jbe 1f ;" + " cmpl %7,%5 ;" + " jbe 8f ;" + "1: cmpl $3,%6 ;" + " jbe 6f ;" + " movl %6,%3 ;" + " movl $4,%2 ;" + " subl %4,%2 ;" + " andl $3,%2 ;" + " jz 2f ;" + " subl %6,%3 ;" + " rep; smovb ;" + "2: movl %7,%2 ;" + " shrl $2,%2 ;" + " jz 5f ;" + " cmpl $32,%2 ;" + " ja 4f ;" + " subl %4,%1 ;" + "3: movl (%4),%%edx ;" + " movl %%edx,(%5,%4,1);" + " addl $4,%0 ;" + " subl $1,%2 ;" + " jnz 3b ;" + " addl %4,%1 ;" + " jmp 5f ;" + "4: rep; smovl ;" + "5: movl %7,%2 ;" + " andl $3,%2 ;" + " jz 13f ;" + "6: xorl %7,%3 ;" + "7: movb (%4,%7,1),%%dl ;" + " movb %%dl,(%5,%7,1) ;" + " addl $1,%3 ;" + " subl $1,%2 ;" + " jnz 7b ;" + " jmp 13f ;" + "8: std ;" + " cmpl $12,%2 ;" + " ja 9f ;" + " movl %7,%0 ;" + " leal -1(%6,%5),%1 ;" + " jmp 11f ;" + "9: xchgl %3,%2 ;" + " movl %6,%0 ;" + " addl $1,%2 ;" + " leal -1(%7,%5),%1 ;" + " andl $3,%2 ;" + " jz 10f ;" + " subl %6,%3 ;" + " rep; smovb ;" + "10: movl %7,%2 ;" + " subl $3,%0 ;" + " shrl $2,%2 ;" + " subl $3,%1 ;" + " rep; smovl ;" + " andl $3,%3 ;" + " jz 12f ;" + " movl %7,%2 ;" + " addl $3,%0 ;" + " addl $3,%1 ;" + "11: rep; smovb ;" + "12: cld ;" + "13: nop ;" + : "=S" (from), "=D" (to), "=c" (count), "=r" (temp) + : "0" (from), "1" (to), "2" (count), "3" (temp) + : "memory", "flags", "%edx"); +#endif // AMD64 +} + +static void pd_conjoint_bytes_atomic(const void* from, void* to, size_t count) { + pd_conjoint_bytes(from, to, count); +} + +// Windows has a different implementation +#ifndef _WINDOWS +static void pd_conjoint_jshorts_atomic(const jshort* from, jshort* to, size_t count) { + _Copy_conjoint_jshorts_atomic(from, to, count); +} + +static void pd_conjoint_jints_atomic(const jint* from, jint* to, size_t count) { +#ifdef AMD64 + _Copy_conjoint_jints_atomic(from, to, count); +#else + assert(HeapWordSize == BytesPerInt, "heapwords and jints must be the same size"); + // pd_conjoint_words is word-atomic in this implementation. + pd_conjoint_words((const HeapWord*)from, (HeapWord*)to, count); +#endif // AMD64 +} + +static void pd_conjoint_jlongs_atomic(const jlong* from, jlong* to, size_t count) { +#ifdef AMD64 + _Copy_conjoint_jlongs_atomic(from, to, count); +#else + // Guarantee use of fild/fistp or xmm regs via some asm code, because compilers won't. + if (from > to) { + while (count-- > 0) { + __asm__ volatile("fildll (%0); fistpll (%1)" + : + : "r" (from), "r" (to) + : "memory" ); + ++from; + ++to; + } + } else { + while (count-- > 0) { + __asm__ volatile("fildll (%0,%2,8); fistpll (%1,%2,8)" + : + : "r" (from), "r" (to), "r" (count) + : "memory" ); + } + } +#endif // AMD64 +} + +static void pd_conjoint_oops_atomic(const oop* from, oop* to, size_t count) { +#ifdef AMD64 + assert(BytesPerLong == BytesPerOop, "jlongs and oops must be the same size"); + _Copy_conjoint_jlongs_atomic((const jlong*)from, (jlong*)to, count); +#else + assert(HeapWordSize == BytesPerOop, "heapwords and oops must be the same size"); + // pd_conjoint_words is word-atomic in this implementation. + pd_conjoint_words((const HeapWord*)from, (HeapWord*)to, count); +#endif // AMD64 +} + +static void pd_arrayof_conjoint_bytes(const HeapWord* from, HeapWord* to, size_t count) { + _Copy_arrayof_conjoint_bytes(from, to, count); +} + +static void pd_arrayof_conjoint_jshorts(const HeapWord* from, HeapWord* to, size_t count) { + _Copy_arrayof_conjoint_jshorts(from, to, count); +} + +static void pd_arrayof_conjoint_jints(const HeapWord* from, HeapWord* to, size_t count) { +#ifdef AMD64 + _Copy_arrayof_conjoint_jints(from, to, count); +#else + pd_conjoint_jints_atomic((const jint*)from, (jint*)to, count); +#endif // AMD64 +} + +static void pd_arrayof_conjoint_jlongs(const HeapWord* from, HeapWord* to, size_t count) { +#ifdef AMD64 + _Copy_arrayof_conjoint_jlongs(from, to, count); +#else + pd_conjoint_jlongs_atomic((const jlong*)from, (jlong*)to, count); +#endif // AMD64 +} + +static void pd_arrayof_conjoint_oops(const HeapWord* from, HeapWord* to, size_t count) { +#ifdef AMD64 + assert(BytesPerLong == BytesPerOop, "jlongs and oops must be the same size"); + _Copy_arrayof_conjoint_jlongs(from, to, count); +#else + pd_conjoint_oops_atomic((const oop*)from, (oop*)to, count); +#endif // AMD64 +} + +#endif // _WINDOWS + #endif // CPU_X86_COPY_X86_HPP diff --git a/src/hotspot/os_cpu/bsd_aarch64/copy_bsd_aarch64.hpp b/src/hotspot/os_cpu/bsd_aarch64/copy_bsd_aarch64.hpp index 6f08cb35125..580daec9ebf 100644 --- a/src/hotspot/os_cpu/bsd_aarch64/copy_bsd_aarch64.hpp +++ b/src/hotspot/os_cpu/bsd_aarch64/copy_bsd_aarch64.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * Copyright (c) 2021, Azul Systems, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -27,163 +27,6 @@ #ifndef OS_CPU_BSD_AARCH64_COPY_BSD_AARCH64_HPP #define OS_CPU_BSD_AARCH64_COPY_BSD_AARCH64_HPP -#define COPY_SMALL(from, to, count) \ -{ \ - long tmp0, tmp1, tmp2, tmp3; \ - long tmp4, tmp5, tmp6, tmp7; \ - __asm volatile( \ -" adr %[t0], 0f;\n" \ -" add %[t0], %[t0], %[cnt], lsl #5;\n" \ -" br %[t0];\n" \ -" .align 5;\n" \ -"0:" \ -" b 1f;\n" \ -" .align 5;\n" \ -" ldr %[t0], [%[s], #0];\n" \ -" str %[t0], [%[d], #0];\n" \ -" b 1f;\n" \ -" .align 5;\n" \ -" ldp %[t0], %[t1], [%[s], #0];\n" \ -" stp %[t0], %[t1], [%[d], #0];\n" \ -" b 1f;\n" \ -" .align 5;\n" \ -" ldp %[t0], %[t1], [%[s], #0];\n" \ -" ldr %[t2], [%[s], #16];\n" \ -" stp %[t0], %[t1], [%[d], #0];\n" \ -" str %[t2], [%[d], #16];\n" \ -" b 1f;\n" \ -" .align 5;\n" \ -" ldp %[t0], %[t1], [%[s], #0];\n" \ -" ldp %[t2], %[t3], [%[s], #16];\n" \ -" stp %[t0], %[t1], [%[d], #0];\n" \ -" stp %[t2], %[t3], [%[d], #16];\n" \ -" b 1f;\n" \ -" .align 5;\n" \ -" ldp %[t0], %[t1], [%[s], #0];\n" \ -" ldp %[t2], %[t3], [%[s], #16];\n" \ -" ldr %[t4], [%[s], #32];\n" \ -" stp %[t0], %[t1], [%[d], #0];\n" \ -" stp %[t2], %[t3], [%[d], #16];\n" \ -" str %[t4], [%[d], #32];\n" \ -" b 1f;\n" \ -" .align 5;\n" \ -" ldp %[t0], %[t1], [%[s], #0];\n" \ -" ldp %[t2], %[t3], [%[s], #16];\n" \ -" ldp %[t4], %[t5], [%[s], #32];\n" \ -"2:" \ -" stp %[t0], %[t1], [%[d], #0];\n" \ -" stp %[t2], %[t3], [%[d], #16];\n" \ -" stp %[t4], %[t5], [%[d], #32];\n" \ -" b 1f;\n" \ -" .align 5;\n" \ -" ldr %[t6], [%[s], #0];\n" \ -" ldp %[t0], %[t1], [%[s], #8];\n" \ -" ldp %[t2], %[t3], [%[s], #24];\n" \ -" ldp %[t4], %[t5], [%[s], #40];\n" \ -" str %[t6], [%[d]], #8;\n" \ -" b 2b;\n" \ -" .align 5;\n" \ -" ldp %[t0], %[t1], [%[s], #0];\n" \ -" ldp %[t2], %[t3], [%[s], #16];\n" \ -" ldp %[t4], %[t5], [%[s], #32];\n" \ -" ldp %[t6], %[t7], [%[s], #48];\n" \ -" stp %[t0], %[t1], [%[d], #0];\n" \ -" stp %[t2], %[t3], [%[d], #16];\n" \ -" stp %[t4], %[t5], [%[d], #32];\n" \ -" stp %[t6], %[t7], [%[d], #48];\n" \ -"1:" \ - \ - : [s]"+r"(from), [d]"+r"(to), [cnt]"+r"(count), \ - [t0]"=&r"(tmp0), [t1]"=&r"(tmp1), [t2]"=&r"(tmp2), [t3]"=&r"(tmp3), \ - [t4]"=&r"(tmp4), [t5]"=&r"(tmp5), [t6]"=&r"(tmp6), [t7]"=&r"(tmp7) \ - : \ - : "memory", "cc"); \ -} - -static void pd_conjoint_words(const HeapWord* from, HeapWord* to, size_t count) { - __asm volatile( "prfm pldl1strm, [%[s], #0];" :: [s]"r"(from) : "memory"); - if (__builtin_expect(count <= 8, 1)) { - COPY_SMALL(from, to, count); - return; - } - _Copy_conjoint_words(from, to, count); -} - -static void pd_disjoint_words(const HeapWord* from, HeapWord* to, size_t count) { - if (__builtin_constant_p(count)) { - memcpy(to, from, count * sizeof(HeapWord)); - return; - } - __asm volatile( "prfm pldl1strm, [%[s], #0];" :: [s]"r"(from) : "memory"); - if (__builtin_expect(count <= 8, 1)) { - COPY_SMALL(from, to, count); - return; - } - _Copy_disjoint_words(from, to, count); -} - -static void pd_disjoint_words_atomic(const HeapWord* from, HeapWord* to, size_t count) { - __asm volatile( "prfm pldl1strm, [%[s], #0];" :: [s]"r"(from) : "memory"); - if (__builtin_expect(count <= 8, 1)) { - COPY_SMALL(from, to, count); - return; - } - _Copy_disjoint_words(from, to, count); -} - -static void pd_aligned_conjoint_words(const HeapWord* from, HeapWord* to, size_t count) { - pd_conjoint_words(from, to, count); -} - -static void pd_aligned_disjoint_words(const HeapWord* from, HeapWord* to, size_t count) { - pd_disjoint_words(from, to, count); -} - -static void pd_conjoint_bytes(const void* from, void* to, size_t count) { - (void)memmove(to, from, count); -} - -static void pd_conjoint_bytes_atomic(const void* from, void* to, size_t count) { - pd_conjoint_bytes(from, to, count); -} - -static void pd_conjoint_jshorts_atomic(const jshort* from, jshort* to, size_t count) { - _Copy_conjoint_jshorts_atomic(from, to, count); -} - -static void pd_conjoint_jints_atomic(const jint* from, jint* to, size_t count) { - _Copy_conjoint_jints_atomic(from, to, count); -} - -static void pd_conjoint_jlongs_atomic(const jlong* from, jlong* to, size_t count) { - _Copy_conjoint_jlongs_atomic(from, to, count); -} - -static void pd_conjoint_oops_atomic(const oop* from, oop* to, size_t count) { - assert(BytesPerLong == BytesPerOop, "jlongs and oops must be the same size"); - _Copy_conjoint_jlongs_atomic((const jlong*)from, (jlong*)to, count); -} - -static void pd_arrayof_conjoint_bytes(const HeapWord* from, HeapWord* to, size_t count) { - _Copy_arrayof_conjoint_bytes(from, to, count); -} - -static void pd_arrayof_conjoint_jshorts(const HeapWord* from, HeapWord* to, size_t count) { - _Copy_arrayof_conjoint_jshorts(from, to, count); -} - -static void pd_arrayof_conjoint_jints(const HeapWord* from, HeapWord* to, size_t count) { - _Copy_arrayof_conjoint_jints(from, to, count); -} - -static void pd_arrayof_conjoint_jlongs(const HeapWord* from, HeapWord* to, size_t count) { - _Copy_arrayof_conjoint_jlongs(from, to, count); -} - -static void pd_arrayof_conjoint_oops(const HeapWord* from, HeapWord* to, size_t count) { - assert(!UseCompressedOops, "foo!"); - assert(BytesPerLong == BytesPerOop, "jlongs and oops must be the same size"); - _Copy_arrayof_conjoint_jlongs(from, to, count); -} +// Empty for build system #endif // OS_CPU_BSD_AARCH64_COPY_BSD_AARCH64_HPP diff --git a/src/hotspot/os_cpu/bsd_x86/bsd_x86_32.S b/src/hotspot/os_cpu/bsd_x86/bsd_x86_32.S index 0d22a6a6790..02231040e15 100644 --- a/src/hotspot/os_cpu/bsd_x86/bsd_x86_32.S +++ b/src/hotspot/os_cpu/bsd_x86/bsd_x86_32.S @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2017, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2022, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -39,7 +39,6 @@ # point or use it in the same manner as does the server # compiler. - .globl SYMBOL(_Copy_conjoint_bytes) .globl SYMBOL(_Copy_arrayof_conjoint_bytes) .globl SYMBOL(_Copy_conjoint_jshorts_atomic) .globl SYMBOL(_Copy_arrayof_conjoint_jshorts) @@ -72,117 +71,10 @@ SYMBOL(SpinPause): movl $1, %eax ret - # Support for void Copy::conjoint_bytes(void* from, - # void* to, - # size_t count) - .p2align 4,,15 - ELF_TYPE(_Copy_conjoint_bytes,@function) -SYMBOL(_Copy_conjoint_bytes): - pushl %esi - movl 4+12(%esp),%ecx # count - pushl %edi - movl 8+ 4(%esp),%esi # from - movl 8+ 8(%esp),%edi # to - cmpl %esi,%edi - leal -1(%esi,%ecx),%eax # from + count - 1 - jbe cb_CopyRight - cmpl %eax,%edi - jbe cb_CopyLeft - # copy from low to high -cb_CopyRight: - cmpl $3,%ecx - jbe 5f # <= 3 bytes - # align source address at dword address boundary - movl %ecx,%eax # original count - movl $4,%ecx - subl %esi,%ecx - andl $3,%ecx # prefix byte count - jz 1f # no prefix - subl %ecx,%eax # byte count less prefix - # copy prefix - subl %esi,%edi -0: movb (%esi),%dl - movb %dl,(%edi,%esi,1) - addl $1,%esi - subl $1,%ecx - jnz 0b - addl %esi,%edi -1: movl %eax,%ecx # byte count less prefix - shrl $2,%ecx # dword count - jz 4f # no dwords to move - cmpl $32,%ecx - jbe 2f # <= 32 dwords - # copy aligned dwords - rep; smovl - jmp 4f - # copy aligned dwords -2: subl %esi,%edi - .p2align 4,,15 -3: movl (%esi),%edx - movl %edx,(%edi,%esi,1) - addl $4,%esi - subl $1,%ecx - jnz 3b - addl %esi,%edi -4: movl %eax,%ecx # byte count less prefix -5: andl $3,%ecx # suffix byte count - jz 7f # no suffix - # copy suffix - xorl %eax,%eax -6: movb (%esi,%eax,1),%dl - movb %dl,(%edi,%eax,1) - addl $1,%eax - subl $1,%ecx - jnz 6b -7: popl %edi - popl %esi - ret - # copy from high to low -cb_CopyLeft: - std - leal -4(%edi,%ecx),%edi # to + count - 4 - movl %eax,%esi # from + count - 1 - movl %ecx,%eax - subl $3,%esi # from + count - 4 - cmpl $3,%ecx - jbe 5f # <= 3 bytes -1: shrl $2,%ecx # dword count - jz 4f # no dwords to move - cmpl $32,%ecx - ja 3f # > 32 dwords - # copy dwords, aligned or not - subl %esi,%edi - .p2align 4,,15 -2: movl (%esi),%edx - movl %edx,(%edi,%esi,1) - subl $4,%esi - subl $1,%ecx - jnz 2b - addl %esi,%edi - jmp 4f - # copy dwords, aligned or not -3: rep; smovl -4: movl %eax,%ecx # byte count -5: andl $3,%ecx # suffix byte count - jz 7f # no suffix - # copy suffix - subl %esi,%edi - addl $3,%esi -6: movb (%esi),%dl - movb %dl,(%edi,%esi,1) - subl $1,%esi - subl $1,%ecx - jnz 6b -7: cld - popl %edi - popl %esi - ret - # Support for void Copy::arrayof_conjoint_bytes(void* from, # void* to, # size_t count) # - # Same as _Copy_conjoint_bytes, except no source alignment check. .p2align 4,,15 ELF_TYPE(_Copy_arrayof_conjoint_bytes,@function) SYMBOL(_Copy_arrayof_conjoint_bytes): diff --git a/src/hotspot/os_cpu/bsd_x86/copy_bsd_x86.hpp b/src/hotspot/os_cpu/bsd_x86/copy_bsd_x86.hpp index 2a5498d8541..e95c18c48a2 100644 --- a/src/hotspot/os_cpu/bsd_x86/copy_bsd_x86.hpp +++ b/src/hotspot/os_cpu/bsd_x86/copy_bsd_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, 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,285 +25,6 @@ #ifndef OS_CPU_BSD_X86_COPY_BSD_X86_HPP #define OS_CPU_BSD_X86_COPY_BSD_X86_HPP -static void pd_conjoint_words(const HeapWord* from, HeapWord* to, size_t count) { -#ifdef AMD64 - (void)memmove(to, from, count * HeapWordSize); -#else - // Includes a zero-count check. - intx temp; - __asm__ volatile(" testl %6,%6 ;" - " jz 7f ;" - " cmpl %4,%5 ;" - " leal -4(%4,%6,4),%3;" - " jbe 1f ;" - " cmpl %7,%5 ;" - " jbe 4f ;" - "1: cmpl $32,%6 ;" - " ja 3f ;" - " subl %4,%1 ;" - "2: movl (%4),%3 ;" - " movl %7,(%5,%4,1) ;" - " addl $4,%0 ;" - " subl $1,%2 ;" - " jnz 2b ;" - " jmp 7f ;" - "3: rep; smovl ;" - " jmp 7f ;" - "4: cmpl $32,%2 ;" - " movl %7,%0 ;" - " leal -4(%5,%6,4),%1;" - " ja 6f ;" - " subl %4,%1 ;" - "5: movl (%4),%3 ;" - " movl %7,(%5,%4,1) ;" - " subl $4,%0 ;" - " subl $1,%2 ;" - " jnz 5b ;" - " jmp 7f ;" - "6: std ;" - " rep; smovl ;" - " cld ;" - "7: nop " - : "=S" (from), "=D" (to), "=c" (count), "=r" (temp) - : "0" (from), "1" (to), "2" (count), "3" (temp) - : "memory", "flags"); -#endif // AMD64 -} - -static void pd_disjoint_words(const HeapWord* from, HeapWord* to, size_t count) { -#ifdef AMD64 - switch (count) { - case 8: to[7] = from[7]; - case 7: to[6] = from[6]; - case 6: to[5] = from[5]; - case 5: to[4] = from[4]; - case 4: to[3] = from[3]; - case 3: to[2] = from[2]; - case 2: to[1] = from[1]; - case 1: to[0] = from[0]; - case 0: break; - default: - (void)memcpy(to, from, count * HeapWordSize); - break; - } -#else - // Includes a zero-count check. - intx temp; - __asm__ volatile(" testl %6,%6 ;" - " jz 3f ;" - " cmpl $32,%6 ;" - " ja 2f ;" - " subl %4,%1 ;" - "1: movl (%4),%3 ;" - " movl %7,(%5,%4,1);" - " addl $4,%0 ;" - " subl $1,%2 ;" - " jnz 1b ;" - " jmp 3f ;" - "2: rep; smovl ;" - "3: nop " - : "=S" (from), "=D" (to), "=c" (count), "=r" (temp) - : "0" (from), "1" (to), "2" (count), "3" (temp) - : "memory", "cc"); -#endif // AMD64 -} - -static void pd_disjoint_words_atomic(const HeapWord* from, HeapWord* to, size_t count) { -#ifdef AMD64 - switch (count) { - case 8: to[7] = from[7]; - case 7: to[6] = from[6]; - case 6: to[5] = from[5]; - case 5: to[4] = from[4]; - case 4: to[3] = from[3]; - case 3: to[2] = from[2]; - case 2: to[1] = from[1]; - case 1: to[0] = from[0]; - case 0: break; - default: - while (count-- > 0) { - *to++ = *from++; - } - break; - } -#else - // pd_disjoint_words is word-atomic in this implementation. - pd_disjoint_words(from, to, count); -#endif // AMD64 -} - -static void pd_aligned_conjoint_words(const HeapWord* from, HeapWord* to, size_t count) { - pd_conjoint_words(from, to, count); -} - -static void pd_aligned_disjoint_words(const HeapWord* from, HeapWord* to, size_t count) { - pd_disjoint_words(from, to, count); -} - -static void pd_conjoint_bytes(const void* from, void* to, size_t count) { -#ifdef AMD64 - (void)memmove(to, from, count); -#else - // Includes a zero-count check. - intx temp; - __asm__ volatile(" testl %6,%6 ;" - " jz 13f ;" - " cmpl %4,%5 ;" - " leal -1(%4,%6),%3 ;" - " jbe 1f ;" - " cmpl %7,%5 ;" - " jbe 8f ;" - "1: cmpl $3,%6 ;" - " jbe 6f ;" - " movl %6,%3 ;" - " movl $4,%2 ;" - " subl %4,%2 ;" - " andl $3,%2 ;" - " jz 2f ;" - " subl %6,%3 ;" - " rep; smovb ;" - "2: movl %7,%2 ;" - " shrl $2,%2 ;" - " jz 5f ;" - " cmpl $32,%2 ;" - " ja 4f ;" - " subl %4,%1 ;" - "3: movl (%4),%%edx ;" - " movl %%edx,(%5,%4,1);" - " addl $4,%0 ;" - " subl $1,%2 ;" - " jnz 3b ;" - " addl %4,%1 ;" - " jmp 5f ;" - "4: rep; smovl ;" - "5: movl %7,%2 ;" - " andl $3,%2 ;" - " jz 13f ;" - "6: xorl %7,%3 ;" - "7: movb (%4,%7,1),%%dl ;" - " movb %%dl,(%5,%7,1) ;" - " addl $1,%3 ;" - " subl $1,%2 ;" - " jnz 7b ;" - " jmp 13f ;" - "8: std ;" - " cmpl $12,%2 ;" - " ja 9f ;" - " movl %7,%0 ;" - " leal -1(%6,%5),%1 ;" - " jmp 11f ;" - "9: xchgl %3,%2 ;" - " movl %6,%0 ;" - " addl $1,%2 ;" - " leal -1(%7,%5),%1 ;" - " andl $3,%2 ;" - " jz 10f ;" - " subl %6,%3 ;" - " rep; smovb ;" - "10: movl %7,%2 ;" - " subl $3,%0 ;" - " shrl $2,%2 ;" - " subl $3,%1 ;" - " rep; smovl ;" - " andl $3,%3 ;" - " jz 12f ;" - " movl %7,%2 ;" - " addl $3,%0 ;" - " addl $3,%1 ;" - "11: rep; smovb ;" - "12: cld ;" - "13: nop ;" - : "=S" (from), "=D" (to), "=c" (count), "=r" (temp) - : "0" (from), "1" (to), "2" (count), "3" (temp) - : "memory", "flags", "%edx"); -#endif // AMD64 -} - -static void pd_conjoint_bytes_atomic(const void* from, void* to, size_t count) { - pd_conjoint_bytes(from, to, count); -} - -static void pd_conjoint_jshorts_atomic(const jshort* from, jshort* to, size_t count) { - _Copy_conjoint_jshorts_atomic(from, to, count); -} - -static void pd_conjoint_jints_atomic(const jint* from, jint* to, size_t count) { -#ifdef AMD64 - _Copy_conjoint_jints_atomic(from, to, count); -#else - assert(HeapWordSize == BytesPerInt, "heapwords and jints must be the same size"); - // pd_conjoint_words is word-atomic in this implementation. - pd_conjoint_words((const HeapWord*)from, (HeapWord*)to, count); -#endif // AMD64 -} - -static void pd_conjoint_jlongs_atomic(const jlong* from, jlong* to, size_t count) { -#ifdef AMD64 - _Copy_conjoint_jlongs_atomic(from, to, count); -#else - // Guarantee use of fild/fistp or xmm regs via some asm code, because compilers won't. - if (from > to) { - while (count-- > 0) { - __asm__ volatile("fildll (%0); fistpll (%1)" - : - : "r" (from), "r" (to) - : "memory" ); - ++from; - ++to; - } - } else { - while (count-- > 0) { - __asm__ volatile("fildll (%0,%2,8); fistpll (%1,%2,8)" - : - : "r" (from), "r" (to), "r" (count) - : "memory" ); - } - } -#endif // AMD64 -} - -static void pd_conjoint_oops_atomic(const oop* from, oop* to, size_t count) { -#ifdef AMD64 - assert(BytesPerLong == BytesPerOop, "jlongs and oops must be the same size"); - _Copy_conjoint_jlongs_atomic((const jlong*)from, (jlong*)to, count); -#else - assert(HeapWordSize == BytesPerOop, "heapwords and oops must be the same size"); - // pd_conjoint_words is word-atomic in this implementation. - pd_conjoint_words((const HeapWord*)from, (HeapWord*)to, count); -#endif // AMD64 -} - -static void pd_arrayof_conjoint_bytes(const HeapWord* from, HeapWord* to, size_t count) { - _Copy_arrayof_conjoint_bytes(from, to, count); -} - -static void pd_arrayof_conjoint_jshorts(const HeapWord* from, HeapWord* to, size_t count) { - _Copy_arrayof_conjoint_jshorts(from, to, count); -} - -static void pd_arrayof_conjoint_jints(const HeapWord* from, HeapWord* to, size_t count) { -#ifdef AMD64 - _Copy_arrayof_conjoint_jints(from, to, count); -#else - pd_conjoint_jints_atomic((const jint*)from, (jint*)to, count); -#endif // AMD64 -} - -static void pd_arrayof_conjoint_jlongs(const HeapWord* from, HeapWord* to, size_t count) { -#ifdef AMD64 - _Copy_arrayof_conjoint_jlongs(from, to, count); -#else - pd_conjoint_jlongs_atomic((const jlong*)from, (jlong*)to, count); -#endif // AMD64 -} - -static void pd_arrayof_conjoint_oops(const HeapWord* from, HeapWord* to, size_t count) { -#ifdef AMD64 - assert(BytesPerLong == BytesPerOop, "jlongs and oops must be the same size"); - _Copy_arrayof_conjoint_jlongs(from, to, count); -#else - pd_conjoint_oops_atomic((const oop*)from, (oop*)to, count); -#endif // AMD64 -} +// Empty for build system #endif // OS_CPU_BSD_X86_COPY_BSD_X86_HPP diff --git a/src/hotspot/os_cpu/linux_aarch64/copy_linux_aarch64.hpp b/src/hotspot/os_cpu/linux_aarch64/copy_linux_aarch64.hpp index f50d80022ae..302929d8575 100644 --- a/src/hotspot/os_cpu/linux_aarch64/copy_linux_aarch64.hpp +++ b/src/hotspot/os_cpu/linux_aarch64/copy_linux_aarch64.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -26,163 +26,6 @@ #ifndef OS_CPU_LINUX_AARCH64_COPY_LINUX_AARCH64_HPP #define OS_CPU_LINUX_AARCH64_COPY_LINUX_AARCH64_HPP -#define COPY_SMALL(from, to, count) \ -{ \ - long tmp0, tmp1, tmp2, tmp3; \ - long tmp4, tmp5, tmp6, tmp7; \ - __asm volatile( \ -" adr %[t0], 0f;" \ -" add %[t0], %[t0], %[cnt], lsl #5;" \ -" br %[t0];" \ -" .align 5;" \ -"0:" \ -" b 1f;" \ -" .align 5;" \ -" ldr %[t0], [%[s], #0];" \ -" str %[t0], [%[d], #0];" \ -" b 1f;" \ -" .align 5;" \ -" ldp %[t0], %[t1], [%[s], #0];" \ -" stp %[t0], %[t1], [%[d], #0];" \ -" b 1f;" \ -" .align 5;" \ -" ldp %[t0], %[t1], [%[s], #0];" \ -" ldr %[t2], [%[s], #16];" \ -" stp %[t0], %[t1], [%[d], #0];" \ -" str %[t2], [%[d], #16];" \ -" b 1f;" \ -" .align 5;" \ -" ldp %[t0], %[t1], [%[s], #0];" \ -" ldp %[t2], %[t3], [%[s], #16];" \ -" stp %[t0], %[t1], [%[d], #0];" \ -" stp %[t2], %[t3], [%[d], #16];" \ -" b 1f;" \ -" .align 5;" \ -" ldp %[t0], %[t1], [%[s], #0];" \ -" ldp %[t2], %[t3], [%[s], #16];" \ -" ldr %[t4], [%[s], #32];" \ -" stp %[t0], %[t1], [%[d], #0];" \ -" stp %[t2], %[t3], [%[d], #16];" \ -" str %[t4], [%[d], #32];" \ -" b 1f;" \ -" .align 5;" \ -" ldp %[t0], %[t1], [%[s], #0];" \ -" ldp %[t2], %[t3], [%[s], #16];" \ -" ldp %[t4], %[t5], [%[s], #32];" \ -"2:" \ -" stp %[t0], %[t1], [%[d], #0];" \ -" stp %[t2], %[t3], [%[d], #16];" \ -" stp %[t4], %[t5], [%[d], #32];" \ -" b 1f;" \ -" .align 5;" \ -" ldr %[t6], [%[s], #0];" \ -" ldp %[t0], %[t1], [%[s], #8];" \ -" ldp %[t2], %[t3], [%[s], #24];" \ -" ldp %[t4], %[t5], [%[s], #40];" \ -" str %[t6], [%[d]], #8;" \ -" b 2b;" \ -" .align 5;" \ -" ldp %[t0], %[t1], [%[s], #0];" \ -" ldp %[t2], %[t3], [%[s], #16];" \ -" ldp %[t4], %[t5], [%[s], #32];" \ -" ldp %[t6], %[t7], [%[s], #48];" \ -" stp %[t0], %[t1], [%[d], #0];" \ -" stp %[t2], %[t3], [%[d], #16];" \ -" stp %[t4], %[t5], [%[d], #32];" \ -" stp %[t6], %[t7], [%[d], #48];" \ -"1:" \ - \ - : [s]"+r"(from), [d]"+r"(to), [cnt]"+r"(count), \ - [t0]"=&r"(tmp0), [t1]"=&r"(tmp1), [t2]"=&r"(tmp2), [t3]"=&r"(tmp3), \ - [t4]"=&r"(tmp4), [t5]"=&r"(tmp5), [t6]"=&r"(tmp6), [t7]"=&r"(tmp7) \ - : \ - : "memory", "cc"); \ -} - -static void pd_conjoint_words(const HeapWord* from, HeapWord* to, size_t count) { - __asm volatile( "prfm pldl1strm, [%[s], #0];" :: [s]"r"(from) : "memory"); - if (__builtin_expect(count <= 8, 1)) { - COPY_SMALL(from, to, count); - return; - } - _Copy_conjoint_words(from, to, count); -} - -static void pd_disjoint_words(const HeapWord* from, HeapWord* to, size_t count) { - if (__builtin_constant_p(count)) { - memcpy(to, from, count * sizeof(HeapWord)); - return; - } - __asm volatile( "prfm pldl1strm, [%[s], #0];" :: [s]"r"(from) : "memory"); - if (__builtin_expect(count <= 8, 1)) { - COPY_SMALL(from, to, count); - return; - } - _Copy_disjoint_words(from, to, count); -} - -static void pd_disjoint_words_atomic(const HeapWord* from, HeapWord* to, size_t count) { - __asm volatile( "prfm pldl1strm, [%[s], #0];" :: [s]"r"(from) : "memory"); - if (__builtin_expect(count <= 8, 1)) { - COPY_SMALL(from, to, count); - return; - } - _Copy_disjoint_words(from, to, count); -} - -static void pd_aligned_conjoint_words(const HeapWord* from, HeapWord* to, size_t count) { - pd_conjoint_words(from, to, count); -} - -static void pd_aligned_disjoint_words(const HeapWord* from, HeapWord* to, size_t count) { - pd_disjoint_words(from, to, count); -} - -static void pd_conjoint_bytes(const void* from, void* to, size_t count) { - (void)memmove(to, from, count); -} - -static void pd_conjoint_bytes_atomic(const void* from, void* to, size_t count) { - pd_conjoint_bytes(from, to, count); -} - -static void pd_conjoint_jshorts_atomic(const jshort* from, jshort* to, size_t count) { - _Copy_conjoint_jshorts_atomic(from, to, count); -} - -static void pd_conjoint_jints_atomic(const jint* from, jint* to, size_t count) { - _Copy_conjoint_jints_atomic(from, to, count); -} - -static void pd_conjoint_jlongs_atomic(const jlong* from, jlong* to, size_t count) { - _Copy_conjoint_jlongs_atomic(from, to, count); -} - -static void pd_conjoint_oops_atomic(const oop* from, oop* to, size_t count) { - assert(BytesPerLong == BytesPerOop, "jlongs and oops must be the same size"); - _Copy_conjoint_jlongs_atomic((const jlong*)from, (jlong*)to, count); -} - -static void pd_arrayof_conjoint_bytes(const HeapWord* from, HeapWord* to, size_t count) { - _Copy_arrayof_conjoint_bytes(from, to, count); -} - -static void pd_arrayof_conjoint_jshorts(const HeapWord* from, HeapWord* to, size_t count) { - _Copy_arrayof_conjoint_jshorts(from, to, count); -} - -static void pd_arrayof_conjoint_jints(const HeapWord* from, HeapWord* to, size_t count) { - _Copy_arrayof_conjoint_jints(from, to, count); -} - -static void pd_arrayof_conjoint_jlongs(const HeapWord* from, HeapWord* to, size_t count) { - _Copy_arrayof_conjoint_jlongs(from, to, count); -} - -static void pd_arrayof_conjoint_oops(const HeapWord* from, HeapWord* to, size_t count) { - assert(!UseCompressedOops, "foo!"); - assert(BytesPerLong == BytesPerOop, "jlongs and oops must be the same size"); - _Copy_arrayof_conjoint_jlongs(from, to, count); -} +// Empty for build system #endif // OS_CPU_LINUX_AARCH64_COPY_LINUX_AARCH64_HPP diff --git a/src/hotspot/os_cpu/linux_arm/linux_arm_32.S b/src/hotspot/os_cpu/linux_arm/linux_arm_32.S index c1c8fd42815..eb560d8f0c7 100644 --- a/src/hotspot/os_cpu/linux_arm/linux_arm_32.S +++ b/src/hotspot/os_cpu/linux_arm/linux_arm_32.S @@ -1,5 +1,5 @@ # -# Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -58,12 +58,6 @@ to .req r1 SpinPause: bx LR - # Support for void Copy::conjoint_bytes(void* from, - # void* to, - # size_t count) -_Copy_conjoint_bytes: - swi 0x9f0001 - # Support for void Copy::arrayof_conjoint_bytes(void* from, # void* to, # size_t count) diff --git a/src/hotspot/os_cpu/linux_x86/copy_linux_x86.hpp b/src/hotspot/os_cpu/linux_x86/copy_linux_x86.hpp index de43d12f4a7..ed25d38cbff 100644 --- a/src/hotspot/os_cpu/linux_x86/copy_linux_x86.hpp +++ b/src/hotspot/os_cpu/linux_x86/copy_linux_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, 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,285 +25,6 @@ #ifndef OS_CPU_LINUX_X86_COPY_LINUX_X86_HPP #define OS_CPU_LINUX_X86_COPY_LINUX_X86_HPP -static void pd_conjoint_words(const HeapWord* from, HeapWord* to, size_t count) { -#ifdef AMD64 - (void)memmove(to, from, count * HeapWordSize); -#else - // Includes a zero-count check. - intx temp = 0; - __asm__ volatile(" testl %6,%6 ;" - " jz 7f ;" - " cmpl %4,%5 ;" - " leal -4(%4,%6,4),%3;" - " jbe 1f ;" - " cmpl %7,%5 ;" - " jbe 4f ;" - "1: cmpl $32,%6 ;" - " ja 3f ;" - " subl %4,%1 ;" - "2: movl (%4),%3 ;" - " movl %7,(%5,%4,1) ;" - " addl $4,%0 ;" - " subl $1,%2 ;" - " jnz 2b ;" - " jmp 7f ;" - "3: rep; smovl ;" - " jmp 7f ;" - "4: cmpl $32,%2 ;" - " movl %7,%0 ;" - " leal -4(%5,%6,4),%1;" - " ja 6f ;" - " subl %4,%1 ;" - "5: movl (%4),%3 ;" - " movl %7,(%5,%4,1) ;" - " subl $4,%0 ;" - " subl $1,%2 ;" - " jnz 5b ;" - " jmp 7f ;" - "6: std ;" - " rep; smovl ;" - " cld ;" - "7: nop " - : "=S" (from), "=D" (to), "=c" (count), "=r" (temp) - : "0" (from), "1" (to), "2" (count), "3" (temp) - : "memory", "flags"); -#endif // AMD64 -} - -static void pd_disjoint_words(const HeapWord* from, HeapWord* to, size_t count) { -#ifdef AMD64 - switch (count) { - case 8: to[7] = from[7]; - case 7: to[6] = from[6]; - case 6: to[5] = from[5]; - case 5: to[4] = from[4]; - case 4: to[3] = from[3]; - case 3: to[2] = from[2]; - case 2: to[1] = from[1]; - case 1: to[0] = from[0]; - case 0: break; - default: - (void)memcpy(to, from, count * HeapWordSize); - break; - } -#else - // Includes a zero-count check. - intx temp = 0; - __asm__ volatile(" testl %6,%6 ;" - " jz 3f ;" - " cmpl $32,%6 ;" - " ja 2f ;" - " subl %4,%1 ;" - "1: movl (%4),%3 ;" - " movl %7,(%5,%4,1);" - " addl $4,%0 ;" - " subl $1,%2 ;" - " jnz 1b ;" - " jmp 3f ;" - "2: rep; smovl ;" - "3: nop " - : "=S" (from), "=D" (to), "=c" (count), "=r" (temp) - : "0" (from), "1" (to), "2" (count), "3" (temp) - : "memory", "cc"); -#endif // AMD64 -} - -static void pd_disjoint_words_atomic(const HeapWord* from, HeapWord* to, size_t count) { -#ifdef AMD64 - switch (count) { - case 8: to[7] = from[7]; - case 7: to[6] = from[6]; - case 6: to[5] = from[5]; - case 5: to[4] = from[4]; - case 4: to[3] = from[3]; - case 3: to[2] = from[2]; - case 2: to[1] = from[1]; - case 1: to[0] = from[0]; - case 0: break; - default: - while (count-- > 0) { - *to++ = *from++; - } - break; - } -#else - // pd_disjoint_words is word-atomic in this implementation. - pd_disjoint_words(from, to, count); -#endif // AMD64 -} - -static void pd_aligned_conjoint_words(const HeapWord* from, HeapWord* to, size_t count) { - pd_conjoint_words(from, to, count); -} - -static void pd_aligned_disjoint_words(const HeapWord* from, HeapWord* to, size_t count) { - pd_disjoint_words(from, to, count); -} - -static void pd_conjoint_bytes(const void* from, void* to, size_t count) { -#ifdef AMD64 - (void)memmove(to, from, count); -#else - // Includes a zero-count check. - intx temp = 0; - __asm__ volatile(" testl %6,%6 ;" - " jz 13f ;" - " cmpl %4,%5 ;" - " leal -1(%4,%6),%3 ;" - " jbe 1f ;" - " cmpl %7,%5 ;" - " jbe 8f ;" - "1: cmpl $3,%6 ;" - " jbe 6f ;" - " movl %6,%3 ;" - " movl $4,%2 ;" - " subl %4,%2 ;" - " andl $3,%2 ;" - " jz 2f ;" - " subl %6,%3 ;" - " rep; smovb ;" - "2: movl %7,%2 ;" - " shrl $2,%2 ;" - " jz 5f ;" - " cmpl $32,%2 ;" - " ja 4f ;" - " subl %4,%1 ;" - "3: movl (%4),%%edx ;" - " movl %%edx,(%5,%4,1);" - " addl $4,%0 ;" - " subl $1,%2 ;" - " jnz 3b ;" - " addl %4,%1 ;" - " jmp 5f ;" - "4: rep; smovl ;" - "5: movl %7,%2 ;" - " andl $3,%2 ;" - " jz 13f ;" - "6: xorl %7,%3 ;" - "7: movb (%4,%7,1),%%dl ;" - " movb %%dl,(%5,%7,1) ;" - " addl $1,%3 ;" - " subl $1,%2 ;" - " jnz 7b ;" - " jmp 13f ;" - "8: std ;" - " cmpl $12,%2 ;" - " ja 9f ;" - " movl %7,%0 ;" - " leal -1(%6,%5),%1 ;" - " jmp 11f ;" - "9: xchgl %3,%2 ;" - " movl %6,%0 ;" - " addl $1,%2 ;" - " leal -1(%7,%5),%1 ;" - " andl $3,%2 ;" - " jz 10f ;" - " subl %6,%3 ;" - " rep; smovb ;" - "10: movl %7,%2 ;" - " subl $3,%0 ;" - " shrl $2,%2 ;" - " subl $3,%1 ;" - " rep; smovl ;" - " andl $3,%3 ;" - " jz 12f ;" - " movl %7,%2 ;" - " addl $3,%0 ;" - " addl $3,%1 ;" - "11: rep; smovb ;" - "12: cld ;" - "13: nop ;" - : "=S" (from), "=D" (to), "=c" (count), "=r" (temp) - : "0" (from), "1" (to), "2" (count), "3" (temp) - : "memory", "flags", "%edx"); -#endif // AMD64 -} - -static void pd_conjoint_bytes_atomic(const void* from, void* to, size_t count) { - pd_conjoint_bytes(from, to, count); -} - -static void pd_conjoint_jshorts_atomic(const jshort* from, jshort* to, size_t count) { - _Copy_conjoint_jshorts_atomic(from, to, count); -} - -static void pd_conjoint_jints_atomic(const jint* from, jint* to, size_t count) { -#ifdef AMD64 - _Copy_conjoint_jints_atomic(from, to, count); -#else - assert(HeapWordSize == BytesPerInt, "heapwords and jints must be the same size"); - // pd_conjoint_words is word-atomic in this implementation. - pd_conjoint_words((const HeapWord*)from, (HeapWord*)to, count); -#endif // AMD64 -} - -static void pd_conjoint_jlongs_atomic(const jlong* from, jlong* to, size_t count) { -#ifdef AMD64 - _Copy_conjoint_jlongs_atomic(from, to, count); -#else - // Guarantee use of fild/fistp or xmm regs via some asm code, because compilers won't. - if (from > to) { - while (count-- > 0) { - __asm__ volatile("fildll (%0); fistpll (%1)" - : - : "r" (from), "r" (to) - : "memory" ); - ++from; - ++to; - } - } else { - while (count-- > 0) { - __asm__ volatile("fildll (%0,%2,8); fistpll (%1,%2,8)" - : - : "r" (from), "r" (to), "r" (count) - : "memory" ); - } - } -#endif // AMD64 -} - -static void pd_conjoint_oops_atomic(const oop* from, oop* to, size_t count) { -#ifdef AMD64 - assert(BytesPerLong == BytesPerOop, "jlongs and oops must be the same size"); - _Copy_conjoint_jlongs_atomic((const jlong*)from, (jlong*)to, count); -#else - assert(HeapWordSize == BytesPerOop, "heapwords and oops must be the same size"); - // pd_conjoint_words is word-atomic in this implementation. - pd_conjoint_words((const HeapWord*)from, (HeapWord*)to, count); -#endif // AMD64 -} - -static void pd_arrayof_conjoint_bytes(const HeapWord* from, HeapWord* to, size_t count) { - _Copy_arrayof_conjoint_bytes(from, to, count); -} - -static void pd_arrayof_conjoint_jshorts(const HeapWord* from, HeapWord* to, size_t count) { - _Copy_arrayof_conjoint_jshorts(from, to, count); -} - -static void pd_arrayof_conjoint_jints(const HeapWord* from, HeapWord* to, size_t count) { -#ifdef AMD64 - _Copy_arrayof_conjoint_jints(from, to, count); -#else - pd_conjoint_jints_atomic((const jint*)from, (jint*)to, count); -#endif // AMD64 -} - -static void pd_arrayof_conjoint_jlongs(const HeapWord* from, HeapWord* to, size_t count) { -#ifdef AMD64 - _Copy_arrayof_conjoint_jlongs(from, to, count); -#else - pd_conjoint_jlongs_atomic((const jlong*)from, (jlong*)to, count); -#endif // AMD64 -} - -static void pd_arrayof_conjoint_oops(const HeapWord* from, HeapWord* to, size_t count) { -#ifdef AMD64 - assert(BytesPerLong == BytesPerOop, "jlongs and oops must be the same size"); - _Copy_arrayof_conjoint_jlongs(from, to, count); -#else - pd_conjoint_oops_atomic((const oop*)from, (oop*)to, count); -#endif // AMD64 -} +// Empty for build system #endif // OS_CPU_LINUX_X86_COPY_LINUX_X86_HPP diff --git a/src/hotspot/os_cpu/linux_x86/linux_x86_32.S b/src/hotspot/os_cpu/linux_x86/linux_x86_32.S index 620179d99dd..344358172de 100644 --- a/src/hotspot/os_cpu/linux_x86/linux_x86_32.S +++ b/src/hotspot/os_cpu/linux_x86/linux_x86_32.S @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2017, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2022, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,6 @@ # point or use it in the same manner as does the server # compiler. - .globl _Copy_conjoint_bytes .globl _Copy_arrayof_conjoint_bytes .globl _Copy_conjoint_jshorts_atomic .globl _Copy_arrayof_conjoint_jshorts @@ -51,117 +50,10 @@ SpinPause: movl $1, %eax ret - # Support for void Copy::conjoint_bytes(void* from, - # void* to, - # size_t count) - .p2align 4,,15 - .type _Copy_conjoint_bytes,@function -_Copy_conjoint_bytes: - pushl %esi - movl 4+12(%esp),%ecx # count - pushl %edi - movl 8+ 4(%esp),%esi # from - movl 8+ 8(%esp),%edi # to - cmpl %esi,%edi - leal -1(%esi,%ecx),%eax # from + count - 1 - jbe cb_CopyRight - cmpl %eax,%edi - jbe cb_CopyLeft - # copy from low to high -cb_CopyRight: - cmpl $3,%ecx - jbe 5f # <= 3 bytes - # align source address at dword address boundary - movl %ecx,%eax # original count - movl $4,%ecx - subl %esi,%ecx - andl $3,%ecx # prefix byte count - jz 1f # no prefix - subl %ecx,%eax # byte count less prefix - # copy prefix - subl %esi,%edi -0: movb (%esi),%dl - movb %dl,(%edi,%esi,1) - addl $1,%esi - subl $1,%ecx - jnz 0b - addl %esi,%edi -1: movl %eax,%ecx # byte count less prefix - shrl $2,%ecx # dword count - jz 4f # no dwords to move - cmpl $32,%ecx - jbe 2f # <= 32 dwords - # copy aligned dwords - rep; smovl - jmp 4f - # copy aligned dwords -2: subl %esi,%edi - .p2align 4,,15 -3: movl (%esi),%edx - movl %edx,(%edi,%esi,1) - addl $4,%esi - subl $1,%ecx - jnz 3b - addl %esi,%edi -4: movl %eax,%ecx # byte count less prefix -5: andl $3,%ecx # suffix byte count - jz 7f # no suffix - # copy suffix - xorl %eax,%eax -6: movb (%esi,%eax,1),%dl - movb %dl,(%edi,%eax,1) - addl $1,%eax - subl $1,%ecx - jnz 6b -7: popl %edi - popl %esi - ret - # copy from high to low -cb_CopyLeft: - std - leal -4(%edi,%ecx),%edi # to + count - 4 - movl %eax,%esi # from + count - 1 - movl %ecx,%eax - subl $3,%esi # from + count - 4 - cmpl $3,%ecx - jbe 5f # <= 3 bytes -1: shrl $2,%ecx # dword count - jz 4f # no dwords to move - cmpl $32,%ecx - ja 3f # > 32 dwords - # copy dwords, aligned or not - subl %esi,%edi - .p2align 4,,15 -2: movl (%esi),%edx - movl %edx,(%edi,%esi,1) - subl $4,%esi - subl $1,%ecx - jnz 2b - addl %esi,%edi - jmp 4f - # copy dwords, aligned or not -3: rep; smovl -4: movl %eax,%ecx # byte count -5: andl $3,%ecx # suffix byte count - jz 7f # no suffix - # copy suffix - subl %esi,%edi - addl $3,%esi -6: movb (%esi),%dl - movb %dl,(%edi,%esi,1) - subl $1,%esi - subl $1,%ecx - jnz 6b -7: cld - popl %edi - popl %esi - ret - # Support for void Copy::arrayof_conjoint_bytes(void* from, # void* to, # size_t count) # - # Same as _Copy_conjoint_bytes, except no source alignment check. .p2align 4,,15 .type _Copy_arrayof_conjoint_bytes,@function _Copy_arrayof_conjoint_bytes: diff --git a/src/hotspot/os_cpu/windows_x86/copy_windows_x86.hpp b/src/hotspot/os_cpu/windows_x86/copy_windows_x86.hpp index 2f0560d8987..820ca46cb25 100644 --- a/src/hotspot/os_cpu/windows_x86/copy_windows_x86.hpp +++ b/src/hotspot/os_cpu/windows_x86/copy_windows_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, 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,64 +25,6 @@ #ifndef OS_CPU_WINDOWS_X86_COPY_WINDOWS_X86_HPP #define OS_CPU_WINDOWS_X86_COPY_WINDOWS_X86_HPP -static void pd_conjoint_words(const HeapWord* from, HeapWord* to, size_t count) { - (void)memmove(to, from, count * HeapWordSize); -} - -static void pd_disjoint_words(const HeapWord* from, HeapWord* to, size_t count) { -#ifdef AMD64 - switch (count) { - case 8: to[7] = from[7]; - case 7: to[6] = from[6]; - case 6: to[5] = from[5]; - case 5: to[4] = from[4]; - case 4: to[3] = from[3]; - case 3: to[2] = from[2]; - case 2: to[1] = from[1]; - case 1: to[0] = from[0]; - case 0: break; - default: - (void)memcpy(to, from, count * HeapWordSize); - break; - } -#else - (void)memcpy(to, from, count * HeapWordSize); -#endif // AMD64 -} - -static void pd_disjoint_words_atomic(const HeapWord* from, HeapWord* to, size_t count) { - switch (count) { - case 8: to[7] = from[7]; - case 7: to[6] = from[6]; - case 6: to[5] = from[5]; - case 5: to[4] = from[4]; - case 4: to[3] = from[3]; - case 3: to[2] = from[2]; - case 2: to[1] = from[1]; - case 1: to[0] = from[0]; - case 0: break; - default: while (count-- > 0) { - *to++ = *from++; - } - break; - } -} - -static void pd_aligned_conjoint_words(const HeapWord* from, HeapWord* to, size_t count) { - (void)memmove(to, from, count * HeapWordSize); -} - -static void pd_aligned_disjoint_words(const HeapWord* from, HeapWord* to, size_t count) { - pd_disjoint_words(from, to, count); -} - -static void pd_conjoint_bytes(const void* from, void* to, size_t count) { - (void)memmove(to, from, count); -} - -static void pd_conjoint_bytes_atomic(const void* from, void* to, size_t count) { - pd_conjoint_bytes(from, to, count); -} static void pd_conjoint_jshorts_atomic(const jshort* from, jshort* to, size_t count) { if (from > to) { diff --git a/src/hotspot/share/utilities/copy.hpp b/src/hotspot/share/utilities/copy.hpp index bd502d5313d..12f59ad1311 100644 --- a/src/hotspot/share/utilities/copy.hpp +++ b/src/hotspot/share/utilities/copy.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,15 +37,6 @@ extern "C" { void _Copy_conjoint_words(const HeapWord* from, HeapWord* to, size_t count); void _Copy_disjoint_words(const HeapWord* from, HeapWord* to, size_t count); - void _Copy_conjoint_words_atomic(const HeapWord* from, HeapWord* to, size_t count); - void _Copy_disjoint_words_atomic(const HeapWord* from, HeapWord* to, size_t count); - - void _Copy_aligned_conjoint_words(const HeapWord* from, HeapWord* to, size_t count); - void _Copy_aligned_disjoint_words(const HeapWord* from, HeapWord* to, size_t count); - - void _Copy_conjoint_bytes(const void* from, void* to, size_t count); - - void _Copy_conjoint_bytes_atomic (const void* from, void* to, size_t count); void _Copy_conjoint_jshorts_atomic(const jshort* from, jshort* to, size_t count); void _Copy_conjoint_jints_atomic (const jint* from, jint* to, size_t count); void _Copy_conjoint_jlongs_atomic (const jlong* from, jlong* to, size_t count); @@ -55,7 +46,6 @@ extern "C" { void _Copy_arrayof_conjoint_jshorts(const HeapWord* from, HeapWord* to, size_t count); void _Copy_arrayof_conjoint_jints (const HeapWord* from, HeapWord* to, size_t count); void _Copy_arrayof_conjoint_jlongs (const HeapWord* from, HeapWord* to, size_t count); - void _Copy_arrayof_conjoint_oops (const HeapWord* from, HeapWord* to, size_t count); } class Copy : AllStatic { -- GitLab From debaa28e9c0bcb01d0551df907a851bd1e1c3e78 Mon Sep 17 00:00:00 2001 From: Andrey Turbanov Date: Mon, 10 Jan 2022 15:02:57 +0000 Subject: [PATCH 047/564] 8274679: Remove unnecessary conversion to String in security code in java.base Reviewed-by: weijun --- .../cert/PKIXCertPathBuilderResult.java | 6 ++--- .../cert/PKIXCertPathValidatorResult.java | 6 ++--- .../java/security/cert/PKIXParameters.java | 15 ++++++------- .../java/security/cert/TrustAnchor.java | 9 ++++---- .../java/security/cert/X509CertSelector.java | 22 +++++++++---------- .../share/classes/javax/crypto/Cipher.java | 2 +- .../javax/crypto/CryptoPolicyParser.java | 2 +- .../sun/security/provider/PolicyParser.java | 8 +++---- .../security/provider/certpath/Builder.java | 5 ++--- .../provider/certpath/ConstraintsChecker.java | 6 ++--- .../provider/certpath/ForwardBuilder.java | 7 +++--- .../provider/certpath/ForwardState.java | 7 +++--- .../x509/CertificateIssuerExtension.java | 4 ++-- .../x509/InvalidityDateExtension.java | 4 ++-- 14 files changed, 48 insertions(+), 55 deletions(-) diff --git a/src/java.base/share/classes/java/security/cert/PKIXCertPathBuilderResult.java b/src/java.base/share/classes/java/security/cert/PKIXCertPathBuilderResult.java index 01cedffe9c8..4812e380bb3 100644 --- a/src/java.base/share/classes/java/security/cert/PKIXCertPathBuilderResult.java +++ b/src/java.base/share/classes/java/security/cert/PKIXCertPathBuilderResult.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2021, 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,8 +110,8 @@ public class PKIXCertPathBuilderResult extends PKIXCertPathValidatorResult StringBuilder sb = new StringBuilder(); sb.append("PKIXCertPathBuilderResult: [\n"); sb.append(" Certification Path: " + certPath + "\n"); - sb.append(" Trust Anchor: " + getTrustAnchor().toString() + "\n"); - sb.append(" Policy Tree: " + String.valueOf(getPolicyTree()) + "\n"); + sb.append(" Trust Anchor: " + getTrustAnchor() + "\n"); + sb.append(" Policy Tree: " + getPolicyTree() + "\n"); sb.append(" Subject Public Key: " + getPublicKey() + "\n"); sb.append("]"); return sb.toString(); diff --git a/src/java.base/share/classes/java/security/cert/PKIXCertPathValidatorResult.java b/src/java.base/share/classes/java/security/cert/PKIXCertPathValidatorResult.java index 3ba1e335a54..5552078ff5c 100644 --- a/src/java.base/share/classes/java/security/cert/PKIXCertPathValidatorResult.java +++ b/src/java.base/share/classes/java/security/cert/PKIXCertPathValidatorResult.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2021, 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 @@ -150,8 +150,8 @@ public class PKIXCertPathValidatorResult implements CertPathValidatorResult { public String toString() { StringBuilder sb = new StringBuilder(); sb.append("PKIXCertPathValidatorResult: [\n"); - sb.append(" Trust Anchor: " + trustAnchor.toString() + "\n"); - sb.append(" Policy Tree: " + String.valueOf(policyTree) + "\n"); + sb.append(" Trust Anchor: " + trustAnchor + "\n"); + sb.append(" Policy Tree: " + policyTree + "\n"); sb.append(" Subject Public Key: " + subjectPublicKey + "\n"); sb.append("]"); return sb.toString(); diff --git a/src/java.base/share/classes/java/security/cert/PKIXParameters.java b/src/java.base/share/classes/java/security/cert/PKIXParameters.java index d29269e9c42..88e77f0b6cf 100644 --- a/src/java.base/share/classes/java/security/cert/PKIXParameters.java +++ b/src/java.base/share/classes/java/security/cert/PKIXParameters.java @@ -696,8 +696,7 @@ public class PKIXParameters implements CertPathParameters { /* start with trusted anchor info */ if (unmodTrustAnchors != null) { - sb.append(" Trust Anchors: " + unmodTrustAnchors.toString() - + "\n"); + sb.append(" Trust Anchors: " + unmodTrustAnchors + "\n"); } /* now, append initial state information */ @@ -706,13 +705,13 @@ public class PKIXParameters implements CertPathParameters { sb.append(" Initial Policy OIDs: any\n"); } else { sb.append(" Initial Policy OIDs: [" - + unmodInitialPolicies.toString() + "]\n"); + + unmodInitialPolicies + "]\n"); } } /* now, append constraints on all certificates in the path */ - sb.append(" Validity Date: " + String.valueOf(date) + "\n"); - sb.append(" Signature Provider: " + String.valueOf(sigProvider) + "\n"); + sb.append(" Validity Date: " + date + "\n"); + sb.append(" Signature Provider: " + sigProvider + "\n"); sb.append(" Default Revocation Enabled: " + revocationEnabled + "\n"); sb.append(" Explicit Policy Required: " + explicitPolicyRequired + "\n"); sb.append(" Policy Mapping Inhibited: " + policyMappingInhibited + "\n"); @@ -720,14 +719,14 @@ public class PKIXParameters implements CertPathParameters { sb.append(" Policy Qualifiers Rejected: " + policyQualifiersRejected + "\n"); /* now, append target cert requirements */ - sb.append(" Target Cert Constraints: " + String.valueOf(certSelector) + "\n"); + sb.append(" Target Cert Constraints: " + certSelector + "\n"); /* finally, append miscellaneous parameters */ if (certPathCheckers != null) sb.append(" Certification Path Checkers: [" - + certPathCheckers.toString() + "]\n"); + + certPathCheckers + "]\n"); if (certStores != null) - sb.append(" CertStores: [" + certStores.toString() + "]\n"); + sb.append(" CertStores: [" + certStores + "]\n"); sb.append("]"); return sb.toString(); } diff --git a/src/java.base/share/classes/java/security/cert/TrustAnchor.java b/src/java.base/share/classes/java/security/cert/TrustAnchor.java index f026bea4179..ab60b5cbd9a 100644 --- a/src/java.base/share/classes/java/security/cert/TrustAnchor.java +++ b/src/java.base/share/classes/java/security/cert/TrustAnchor.java @@ -323,14 +323,13 @@ public class TrustAnchor { StringBuilder sb = new StringBuilder(); sb.append("[\n"); if (pubKey != null) { - sb.append(" Trusted CA Public Key: " + pubKey.toString() + "\n"); - sb.append(" Trusted CA Issuer Name: " - + String.valueOf(caName) + "\n"); + sb.append(" Trusted CA Public Key: " + pubKey + "\n"); + sb.append(" Trusted CA Issuer Name: " + caName + "\n"); } else { - sb.append(" Trusted CA cert: " + trustedCert.toString() + "\n"); + sb.append(" Trusted CA cert: " + trustedCert + "\n"); } if (nc != null) - sb.append(" Name Constraints: " + nc.toString() + "\n"); + sb.append(" Name Constraints: " + nc + "\n"); return sb.toString(); } diff --git a/src/java.base/share/classes/java/security/cert/X509CertSelector.java b/src/java.base/share/classes/java/security/cert/X509CertSelector.java index 86c516191a9..5a25ba5927f 100644 --- a/src/java.base/share/classes/java/security/cert/X509CertSelector.java +++ b/src/java.base/share/classes/java/security/cert/X509CertSelector.java @@ -1763,10 +1763,10 @@ public class X509CertSelector implements CertSelector { StringBuilder sb = new StringBuilder(); sb.append("X509CertSelector: [\n"); if (x509Cert != null) { - sb.append(" Certificate: " + x509Cert.toString() + "\n"); + sb.append(" Certificate: " + x509Cert + "\n"); } if (serialNumber != null) { - sb.append(" Serial Number: " + serialNumber.toString() + "\n"); + sb.append(" Serial Number: " + serialNumber + "\n"); } if (issuer != null) { sb.append(" Issuer: " + getIssuerAsString() + "\n"); @@ -1775,7 +1775,7 @@ public class X509CertSelector implements CertSelector { sb.append(" Subject: " + getSubjectAsString() + "\n"); } sb.append(" matchAllSubjectAltNames flag: " - + String.valueOf(matchAllSubjectAltNames) + "\n"); + + matchAllSubjectAltNames + "\n"); if (subjectAlternativeNames != null) { sb.append(" SubjectAlternativeNames:\n"); for (List list : subjectAlternativeNames) { @@ -1795,29 +1795,29 @@ public class X509CertSelector implements CertSelector { } if (certificateValid != null) { sb.append(" Certificate Valid: " + - certificateValid.toString() + "\n"); + certificateValid + "\n"); } if (privateKeyValid != null) { sb.append(" Private Key Valid: " + - privateKeyValid.toString() + "\n"); + privateKeyValid + "\n"); } if (subjectPublicKeyAlgID != null) { sb.append(" Subject Public Key AlgID: " + - subjectPublicKeyAlgID.toString() + "\n"); + subjectPublicKeyAlgID + "\n"); } if (subjectPublicKey != null) { sb.append(" Subject Public Key: " + - subjectPublicKey.toString() + "\n"); + subjectPublicKey + "\n"); } if (keyUsage != null) { sb.append(" Key Usage: " + keyUsageToString(keyUsage) + "\n"); } if (keyPurposeSet != null) { sb.append(" Extended Key Usage: " + - keyPurposeSet.toString() + "\n"); + keyPurposeSet + "\n"); } if (policy != null) { - sb.append(" Policy: " + policy.toString() + "\n"); + sb.append(" Policy: " + policy + "\n"); } if (pathToGeneralNames != null) { sb.append(" Path to names:\n"); @@ -2145,7 +2145,7 @@ public class X509CertSelector implements CertSelector { debug.println("X509CertSelector.match: private key usage not " + "within validity date; ext.NOT_BEFORE: " + time + "; X509CertSelector: " - + this.toString()); + + this); e2.printStackTrace(); } return false; @@ -2153,7 +2153,7 @@ public class X509CertSelector implements CertSelector { if (debug != null) { debug.println("X509CertSelector.match: IOException in " + "private key usage check; X509CertSelector: " - + this.toString()); + + this); e4.printStackTrace(); } return false; diff --git a/src/java.base/share/classes/javax/crypto/Cipher.java b/src/java.base/share/classes/javax/crypto/Cipher.java index 2daa932498b..a6751e886bd 100644 --- a/src/java.base/share/classes/javax/crypto/Cipher.java +++ b/src/java.base/share/classes/javax/crypto/Cipher.java @@ -2833,7 +2833,7 @@ public class Cipher { break; default: // should never happen - sb.append("error:").append(Integer.toString(opmode)); + sb.append("error:").append(opmode); } sb.append(", algorithm from: ").append(getProviderName()); return sb.toString(); diff --git a/src/java.base/share/classes/javax/crypto/CryptoPolicyParser.java b/src/java.base/share/classes/javax/crypto/CryptoPolicyParser.java index 5ccaa814315..5d53bc112c0 100644 --- a/src/java.base/share/classes/javax/crypto/CryptoPolicyParser.java +++ b/src/java.base/share/classes/javax/crypto/CryptoPolicyParser.java @@ -395,7 +395,7 @@ final class CryptoPolicyParser { switch (lookahead) { case StreamTokenizer.TT_NUMBER: throw new ParsingException(st.lineno(), expect, - "number "+String.valueOf(st.nval)); + "number " + st.nval); case StreamTokenizer.TT_EOF: throw new ParsingException("expected "+expect+", read end of file"); case StreamTokenizer.TT_WORD: diff --git a/src/java.base/share/classes/sun/security/provider/PolicyParser.java b/src/java.base/share/classes/sun/security/provider/PolicyParser.java index cc6a304cb77..347bc8f9b56 100644 --- a/src/java.base/share/classes/sun/security/provider/PolicyParser.java +++ b/src/java.base/share/classes/sun/security/provider/PolicyParser.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2021, 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 @@ -733,8 +733,7 @@ public class PolicyParser { switch (lookahead) { case StreamTokenizer.TT_NUMBER: throw new ParsingException(st.lineno(), expect, - LocalizedMessage.getNonlocalized("number.") + - String.valueOf(st.nval)); + LocalizedMessage.getNonlocalized("number.") + st.nval); case StreamTokenizer.TT_EOF: LocalizedMessage localizedMsg = new LocalizedMessage ("expected.expect.read.end.of.file."); @@ -826,8 +825,7 @@ public class PolicyParser { switch (lookahead) { case StreamTokenizer.TT_NUMBER: throw new ParsingException(st.lineno(), ";", - LocalizedMessage.getNonlocalized("number.") + - String.valueOf(st.nval)); + LocalizedMessage.getNonlocalized("number.") + st.nval); case StreamTokenizer.TT_EOF: throw new ParsingException(LocalizedMessage.getNonlocalized ("expected.read.end.of.file.")); diff --git a/src/java.base/share/classes/sun/security/provider/certpath/Builder.java b/src/java.base/share/classes/sun/security/provider/certpath/Builder.java index 186d1269de3..b5cf0c5e442 100644 --- a/src/java.base/share/classes/sun/security/provider/certpath/Builder.java +++ b/src/java.base/share/classes/sun/security/provider/certpath/Builder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,6 @@ package sun.security.provider.certpath; import java.io.IOException; -import java.security.AccessController; import java.security.GeneralSecurityException; import java.security.cert.*; import java.util.*; @@ -337,7 +336,7 @@ public abstract class Builder { if (debug != null) { debug.println("Builder.targetDistance() merged constraints: " - + String.valueOf(constraints)); + + constraints); } /* reduce permitted by excluded */ GeneralSubtrees permitted = diff --git a/src/java.base/share/classes/sun/security/provider/certpath/ConstraintsChecker.java b/src/java.base/share/classes/sun/security/provider/certpath/ConstraintsChecker.java index 28fb322ddc4..00d67de5a07 100644 --- a/src/java.base/share/classes/sun/security/provider/certpath/ConstraintsChecker.java +++ b/src/java.base/share/classes/sun/security/provider/certpath/ConstraintsChecker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2021, 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 @@ -185,14 +185,14 @@ class ConstraintsChecker extends PKIXCertPathChecker { if (debug != null) { debug.println("prevNC = " + prevNC + - ", newNC = " + String.valueOf(newConstraints)); + ", newNC = " + newConstraints); } // if there are no previous name constraints, we just return the // new name constraints. if (prevNC == null) { if (debug != null) { - debug.println("mergedNC = " + String.valueOf(newConstraints)); + debug.println("mergedNC = " + newConstraints); } if (newConstraints == null) { return newConstraints; diff --git a/src/java.base/share/classes/sun/security/provider/certpath/ForwardBuilder.java b/src/java.base/share/classes/sun/security/provider/certpath/ForwardBuilder.java index 6122fdaa970..19dd5dd8d75 100644 --- a/src/java.base/share/classes/sun/security/provider/certpath/ForwardBuilder.java +++ b/src/java.base/share/classes/sun/security/provider/certpath/ForwardBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2021, 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,7 +34,6 @@ import java.security.cert.CertPathValidatorException; import java.security.cert.PKIXReason; import java.security.cert.CertStore; import java.security.cert.CertStoreException; -import java.security.cert.PKIXBuilderParameters; import java.security.cert.PKIXCertPathChecker; import java.security.cert.TrustAnchor; import java.security.cert.X509Certificate; @@ -598,8 +597,8 @@ class ForwardBuilder extends Builder { X500Name tAo1 = tSubjectName.commonAncestor(cIssuer1Name); X500Name tAo2 = tSubjectName.commonAncestor(cIssuer2Name); if (debug != null) { - debug.println(METHOD_NME +" tAo1: " + String.valueOf(tAo1)); - debug.println(METHOD_NME +" tAo2: " + String.valueOf(tAo2)); + debug.println(METHOD_NME +" tAo1: " + tAo1); + debug.println(METHOD_NME +" tAo2: " + tAo2); } if (tAo1 != null || tAo2 != null) { if (tAo1 != null && tAo2 != null) { diff --git a/src/java.base/share/classes/sun/security/provider/certpath/ForwardState.java b/src/java.base/share/classes/sun/security/provider/certpath/ForwardState.java index 2dc9e208e92..5cbd0d7f404 100644 --- a/src/java.base/share/classes/sun/security/provider/certpath/ForwardState.java +++ b/src/java.base/share/classes/sun/security/provider/certpath/ForwardState.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2021, 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,9 +117,8 @@ class ForwardState implements State { sb.append("State ["); sb.append("\n issuerDN of last cert: ").append(issuerDN); sb.append("\n traversedCACerts: ").append(traversedCACerts); - sb.append("\n init: ").append(String.valueOf(init)); - sb.append("\n keyParamsNeeded: ").append - (String.valueOf(keyParamsNeededFlag)); + sb.append("\n init: ").append(init); + sb.append("\n keyParamsNeeded: ").append(keyParamsNeededFlag); sb.append("\n subjectNamesTraversed: \n").append (subjectNamesTraversed); sb.append("]\n"); diff --git a/src/java.base/share/classes/sun/security/x509/CertificateIssuerExtension.java b/src/java.base/share/classes/sun/security/x509/CertificateIssuerExtension.java index 0dd8f39642a..40eba681244 100644 --- a/src/java.base/share/classes/sun/security/x509/CertificateIssuerExtension.java +++ b/src/java.base/share/classes/sun/security/x509/CertificateIssuerExtension.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2021, 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 @@ -170,7 +170,7 @@ public class CertificateIssuerExtension extends Extension */ public String toString() { return super.toString() + "Certificate Issuer [\n" + - String.valueOf(names) + "]\n"; + names + "]\n"; } /** diff --git a/src/java.base/share/classes/sun/security/x509/InvalidityDateExtension.java b/src/java.base/share/classes/sun/security/x509/InvalidityDateExtension.java index 7fac65f3ee5..b731cba4102 100644 --- a/src/java.base/share/classes/sun/security/x509/InvalidityDateExtension.java +++ b/src/java.base/share/classes/sun/security/x509/InvalidityDateExtension.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2021, 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 @@ -168,7 +168,7 @@ public class InvalidityDateExtension extends Extension * Returns a printable representation of the Invalidity Date. */ public String toString() { - return super.toString() + " Invalidity Date: " + String.valueOf(date); + return super.toString() + " Invalidity Date: " + date; } /** -- GitLab From 40df5df95edb67331d39d829b895094e961fe21f Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Mon, 10 Jan 2022 15:07:49 +0000 Subject: [PATCH 048/564] 8279398: jdk/jfr/api/recording/time/TestTimeMultiple.java failed with "RuntimeException: getStopTime() > afterStop" Reviewed-by: mgronlun --- .../jdk/jfr/internal/MetadataRepository.java | 33 ++++--------------- .../jdk/jfr/internal/PlatformRecorder.java | 6 ++-- .../share/classes/jdk/jfr/internal/Utils.java | 29 +++++++++++++++- 3 files changed, 38 insertions(+), 30 deletions(-) diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataRepository.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataRepository.java index 5a6e12989f9..f76fdc62a74 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataRepository.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataRepository.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, 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 @@ -280,9 +280,12 @@ public final class MetadataRepository { if (staleMetadata) { storeDescriptorInJVM(); } - awaitUniqueTimestamp(); jvm.setOutput(filename); - long nanos = jvm.getChunkStartNanos(); + // Each chunk needs a unique start timestamp and + // if the clock resolution is low, two chunks may + // get the same timestamp. Utils.getChunkStartNanos() + // ensures the timestamp is unique for the next chunk + long chunkStart = Utils.getChunkStartNanos(); if (filename != null) { RepositoryFiles.notifyNewFile(); } @@ -293,29 +296,7 @@ public final class MetadataRepository { } unregistered = false; } - return Utils.epochNanosToInstant(nanos); - } - - // Each chunk needs a unique start timestamp and - // if the clock resolution is low, two chunks may - // get the same timestamp. - private void awaitUniqueTimestamp() { - if (outputChange == null) { - outputChange = Instant.now(); - return; - } - while (true) { - Instant time = Instant.now(); - if (!time.equals(outputChange)) { - outputChange = time; - return; - } - try { - Thread.sleep(0, 100); - } catch (InterruptedException iex) { - // ignore - } - } + return Utils.epochNanosToInstant(chunkStart); } private void unregisterUnloaded() { diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecorder.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecorder.java index 63a4840618f..c0c62c64bb0 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecorder.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecorder.java @@ -248,7 +248,7 @@ public final class PlatformRecorder { } currentChunk = newChunk; jvm.beginRecording(); - startNanos = jvm.getChunkStartNanos(); + startNanos = Utils.getChunkStartNanos(); startTime = Utils.epochNanosToInstant(startNanos); if (currentChunk != null) { currentChunk.setStartTime(startTime); @@ -269,7 +269,7 @@ public final class PlatformRecorder { startTime = MetadataRepository.getInstance().setOutput(p); newChunk.setStartTime(startTime); } - startNanos = jvm.getChunkStartNanos(); + startNanos = Utils.getChunkStartNanos(); startTime = Utils.epochNanosToInstant(startNanos); recording.setStartTime(startTime); recording.setState(RecordingState.RUNNING); @@ -316,7 +316,7 @@ public final class PlatformRecorder { } } OldObjectSample.emit(recording); - recording.setFinalStartnanos(jvm.getChunkStartNanos()); + recording.setFinalStartnanos(Utils.getChunkStartNanos()); if (endPhysical) { RequestEngine.doChunkEnd(); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/Utils.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/Utils.java index 38179ba891b..c0324d2d7f6 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/Utils.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/Utils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, 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 @@ -97,6 +97,7 @@ public final class Utils { * The possible data race is benign and is worth of not introducing any contention here. */ private static Metrics[] metrics; + private static Instant lastTimestamp; public static void checkAccessFlightRecorder() throws SecurityException { @SuppressWarnings("removal") @@ -866,4 +867,30 @@ public final class Utils { throw new IllegalArgumentException("'" + name + "' is not a valid Java identifier"); } } + + public static long getChunkStartNanos() { + long nanos = JVM.getJVM().getChunkStartNanos(); + // JVM::getChunkStartNanos() may return a bumped timestamp, +1 ns or +2 ns. + // Spin here to give Instant.now() a chance to catch up. + awaitUniqueTimestamp(); + return nanos; + } + + private static void awaitUniqueTimestamp() { + if (lastTimestamp == null) { + lastTimestamp = Instant.now(); // lazy initialization + } + while (true) { + Instant time = Instant.now(); + if (!time.equals(lastTimestamp)) { + lastTimestamp = time; + return; + } + try { + Thread.sleep(0, 100); + } catch (InterruptedException iex) { + // ignore + } + } + } } -- GitLab From dee447f8ae788c6c1f6cd1e1fcb93faceab37b6c Mon Sep 17 00:00:00 2001 From: Andrey Turbanov Date: Mon, 10 Jan 2022 16:20:58 +0000 Subject: [PATCH 049/564] 8274809: Update java.base classes to use try-with-resources Reviewed-by: mullan, alanb, dfuchs --- .../classes/javax/crypto/SealedObject.java | 10 ++-------- .../share/classes/sun/net/NetProperties.java | 8 ++++---- .../share/classes/sun/net/www/MimeTable.java | 9 +-------- .../security/timestamp/HttpTimestamper.java | 19 +++---------------- .../sun/security/tools/KeyStoreUtil.java | 6 ++++-- .../classes/sun/security/util/PolicyUtil.java | 18 ++++-------------- .../unix/classes/sun/net/sdp/SdpProvider.java | 8 ++------ 7 files changed, 20 insertions(+), 58 deletions(-) diff --git a/src/java.base/share/classes/javax/crypto/SealedObject.java b/src/java.base/share/classes/javax/crypto/SealedObject.java index 354bc0e8d73..a1242213e44 100644 --- a/src/java.base/share/classes/javax/crypto/SealedObject.java +++ b/src/java.base/share/classes/javax/crypto/SealedObject.java @@ -292,12 +292,9 @@ public class SealedObject implements Serializable { throws IOException, ClassNotFoundException, IllegalBlockSizeException, BadPaddingException { - ObjectInput a = getExtObjectInputStream(c); - try { + try (ObjectInput a = getExtObjectInputStream(c)) { Object obj = a.readObject(); return obj; - } finally { - a.close(); } } @@ -412,12 +409,9 @@ public class SealedObject implements Serializable { throw new RuntimeException(iape.getMessage()); } - ObjectInput a = getExtObjectInputStream(c); - try { + try (ObjectInput a = getExtObjectInputStream(c)) { Object obj = a.readObject(); return obj; - } finally { - a.close(); } } diff --git a/src/java.base/share/classes/sun/net/NetProperties.java b/src/java.base/share/classes/sun/net/NetProperties.java index 5ff150b105a..34c50404eda 100644 --- a/src/java.base/share/classes/sun/net/NetProperties.java +++ b/src/java.base/share/classes/sun/net/NetProperties.java @@ -68,10 +68,10 @@ public class NetProperties { File f = new File(fname, "conf"); f = new File(f, "net.properties"); fname = f.getCanonicalPath(); - InputStream in = new FileInputStream(fname); - BufferedInputStream bin = new BufferedInputStream(in); - props.load(bin); - bin.close(); + try (FileInputStream in = new FileInputStream(fname); + BufferedInputStream bin = new BufferedInputStream(in)) { + props.load(bin); + } } catch (Exception e) { // Do nothing. We couldn't find or access the file // so we won't have default properties... diff --git a/src/java.base/share/classes/sun/net/www/MimeTable.java b/src/java.base/share/classes/sun/net/www/MimeTable.java index fd8c5565dfa..08590b3a9e0 100644 --- a/src/java.base/share/classes/sun/net/www/MimeTable.java +++ b/src/java.base/share/classes/sun/net/www/MimeTable.java @@ -382,9 +382,7 @@ public class MimeTable implements FileNameMap { } protected boolean saveAsProperties(File file) { - FileOutputStream os = null; - try { - os = new FileOutputStream(file); + try (FileOutputStream os = new FileOutputStream(file)) { Properties properties = getAsProperties(); properties.put("temp.file.template", tempFileTemplate); String tag; @@ -407,11 +405,6 @@ public class MimeTable implements FileNameMap { e.printStackTrace(); return false; } - finally { - if (os != null) { - try { os.close(); } catch (IOException e) {} - } - } return true; } diff --git a/src/java.base/share/classes/sun/security/timestamp/HttpTimestamper.java b/src/java.base/share/classes/sun/security/timestamp/HttpTimestamper.java index cba296c6b97..03070fab053 100644 --- a/src/java.base/share/classes/sun/security/timestamp/HttpTimestamper.java +++ b/src/java.base/share/classes/sun/security/timestamp/HttpTimestamper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,6 @@ import java.io.DataOutputStream; import java.io.EOFException; import java.io.IOException; import java.net.URI; -import java.net.URL; import java.net.HttpURLConnection; import java.util.*; @@ -112,9 +111,7 @@ public class HttpTimestamper implements Timestamper { connection.connect(); // No HTTP authentication is performed // Send the request - DataOutputStream output = null; - try { - output = new DataOutputStream(connection.getOutputStream()); + try (var output = new DataOutputStream(connection.getOutputStream())) { byte[] request = tsQuery.encode(); output.write(request, 0, request.length); output.flush(); @@ -122,17 +119,11 @@ public class HttpTimestamper implements Timestamper { debug.println("sent timestamp query (length=" + request.length + ")"); } - } finally { - if (output != null) { - output.close(); - } } // Receive the reply - BufferedInputStream input = null; byte[] replyBuffer = null; - try { - input = new BufferedInputStream(connection.getInputStream()); + try (var input = new BufferedInputStream(connection.getInputStream())) { if (debug != null) { String header = connection.getHeaderField(0); debug.println(header); @@ -157,10 +148,6 @@ public class HttpTimestamper implements Timestamper { debug.println("received timestamp response (length=" + replyBuffer.length + ")"); } - } finally { - if (input != null) { - input.close(); - } } return new TSResponse(replyBuffer); } diff --git a/src/java.base/share/classes/sun/security/tools/KeyStoreUtil.java b/src/java.base/share/classes/sun/security/tools/KeyStoreUtil.java index 6c7cc402bf7..6095bb91472 100644 --- a/src/java.base/share/classes/sun/security/tools/KeyStoreUtil.java +++ b/src/java.base/share/classes/sun/security/tools/KeyStoreUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2021, 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 @@ -225,7 +225,9 @@ public class KeyStoreUtil { List result = new ArrayList<>(); Properties p = new Properties(); - p.load(new FileInputStream(file)); + try (FileInputStream is = new FileInputStream(file)) { + p.load(is); + } String s = p.getProperty(tool + ".all"); if (s != null) { diff --git a/src/java.base/share/classes/sun/security/util/PolicyUtil.java b/src/java.base/share/classes/sun/security/util/PolicyUtil.java index 3bea048f539..b0ce1c49602 100644 --- a/src/java.base/share/classes/sun/security/util/PolicyUtil.java +++ b/src/java.base/share/classes/sun/security/util/PolicyUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2021, 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 @@ -124,14 +124,8 @@ public class PolicyUtil { debug.println("reading password"+passURL); } - InputStream in = null; - try { - in = passURL.openStream(); + try (InputStream in = passURL.openStream()) { keyStorePassword = Password.readPassword(in); - } finally { - if (in != null) { - in.close(); - } } } @@ -159,13 +153,9 @@ public class PolicyUtil { debug.println("reading keystore"+keyStoreUrl); } - InputStream inStream = null; - try { - inStream = - new BufferedInputStream(getInputStream(keyStoreUrl)); + try (InputStream inStream = + new BufferedInputStream(getInputStream(keyStoreUrl))) { ks.load(inStream, keyStorePassword); - } finally { - inStream.close(); } return ks; } diff --git a/src/java.base/unix/classes/sun/net/sdp/SdpProvider.java b/src/java.base/unix/classes/sun/net/sdp/SdpProvider.java index c082bb6f02c..f9530cf7797 100644 --- a/src/java.base/unix/classes/sun/net/sdp/SdpProvider.java +++ b/src/java.base/unix/classes/sun/net/sdp/SdpProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,7 +35,6 @@ import java.io.FileDescriptor; import java.io.IOException; import java.io.PrintStream; -import sun.net.sdp.SdpSupport; import sun.security.action.GetPropertyAction; /** @@ -192,8 +191,7 @@ public class SdpProvider extends NetHooks.Provider { private static List loadRulesFromFile(String file) throws IOException { - Scanner scanner = new Scanner(new File(file)); - try { + try (Scanner scanner = new Scanner(new File(file))) { List result = new ArrayList<>(); while (scanner.hasNextLine()) { String line = scanner.nextLine().trim(); @@ -279,8 +277,6 @@ public class SdpProvider extends NetHooks.Provider { } } return result; - } finally { - scanner.close(); } } -- GitLab From 0d190961f28fb670fab06838dba69ec7a20c2fb9 Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Mon, 10 Jan 2022 18:41:39 +0000 Subject: [PATCH 050/564] 8279642: JFR: Remove unnecessary creation of Duration and Instant objects Reviewed-by: mgronlun --- .../share/classes/jdk/jfr/consumer/RecordedEvent.java | 5 ++++- .../share/classes/jdk/jfr/consumer/RecordedObject.java | 9 ++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedEvent.java b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedEvent.java index 7a9cc510985..b0ffe88b9c7 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedEvent.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, 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 @@ -107,6 +107,9 @@ public final class RecordedEvent extends RecordedObject { * @return the duration in nanoseconds, not {@code null} */ public Duration getDuration() { + if(startTimeTicks == endTimeTicks) { + return Duration.ZERO; + } return Duration.ofNanos(getEndTimeNanos() - getStartTimeNanos()); } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedObject.java b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedObject.java index c366934f23b..a2d2976e125 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedObject.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedObject.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, 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 @@ -827,8 +827,11 @@ public class RecordedObject { throw newIllegalArgumentException(name, "java.time.Duration"); } - private Duration getDuration(long timespan, String name) throws InternalError { + private Duration getDuration(long timespan, String name) { ValueDescriptor v = getValueDescriptor(objectContext.fields, name, null); + if (timespan == 0) { + return Duration.ZERO; + } if (timespan == Long.MIN_VALUE) { return Duration.ofSeconds(Long.MIN_VALUE, 0); } @@ -997,7 +1000,7 @@ public class RecordedObject { if (instant.equals(Instant.MIN)) { return OffsetDateTime.MIN; } - return OffsetDateTime.ofInstant(getInstant(name), objectContext.getZoneOffset()); + return OffsetDateTime.ofInstant(instant, objectContext.getZoneOffset()); } private static IllegalArgumentException newIllegalArgumentException(String name, String typeName) { -- GitLab From d7e6e9bd0b0ed819bf04454397cfb45ee82c3a9f Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Mon, 10 Jan 2022 18:58:16 +0000 Subject: [PATCH 051/564] 8279643: JFR: Explain why path is sometimes missing from FileRead and FileWrite events Reviewed-by: mgronlun --- src/jdk.jfr/share/classes/jdk/jfr/events/FileReadEvent.java | 4 ++-- src/jdk.jfr/share/classes/jdk/jfr/events/FileWriteEvent.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/jdk.jfr/share/classes/jdk/jfr/events/FileReadEvent.java b/src/jdk.jfr/share/classes/jdk/jfr/events/FileReadEvent.java index 703f0d1271c..a3a53c6a7e9 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/events/FileReadEvent.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/events/FileReadEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022, 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 @@ -42,7 +42,7 @@ public final class FileReadEvent extends AbstractJDKEvent { // EventHandler::write(..., String, long, boolean) @Label("Path") - @Description("Full path of the file") + @Description("Full path of the file, or N/A if a file descriptor was used to create the stream, for example System.in") public String path; @Label("Bytes Read") diff --git a/src/jdk.jfr/share/classes/jdk/jfr/events/FileWriteEvent.java b/src/jdk.jfr/share/classes/jdk/jfr/events/FileWriteEvent.java index 7554fee09c2..01ffc5dfa48 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/events/FileWriteEvent.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/events/FileWriteEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022, 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 @@ -42,7 +42,7 @@ public final class FileWriteEvent extends AbstractJDKEvent { // EventHandler::write(..., String, long) @Label("Path") - @Description("Full path of the file") + @Description("Full path of the file, or N/A if a file descriptor was used to create the stream, for example System.out and System.err") public String path; @Label("Bytes Written") -- GitLab From 4471e95174a89d83794ed894c2a1bb3fc9def74d Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Mon, 10 Jan 2022 19:52:26 +0000 Subject: [PATCH 052/564] 8279645: JFR: The cacheEventType in Dispatcher is never assigned Reviewed-by: mgronlun --- .../share/classes/jdk/jfr/internal/consumer/Dispatcher.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/Dispatcher.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/Dispatcher.java index 721d5b190fc..e8a565deb5d 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/Dispatcher.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/Dispatcher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, 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 @@ -160,6 +160,7 @@ final class Dispatcher { dispatcherLookup.put(type.getId(), dispatchers); } cacheDispatchers = dispatchers; + cacheEventType = type; } // Expected behavior if exception occurs in onEvent: // -- GitLab From bbc1ddb4744bfb15c4e3ab0bed14f7ad0d17b7e5 Mon Sep 17 00:00:00 2001 From: Hao Sun Date: Mon, 10 Jan 2022 20:46:28 +0000 Subject: [PATCH 053/564] 8278267: ARM32: several vector test failures for ASHR Reviewed-by: njian, dlong --- src/hotspot/cpu/arm/arm.ad | 431 ++++++++++++++++++++++---- src/hotspot/share/opto/vectornode.hpp | 11 +- 2 files changed, 384 insertions(+), 58 deletions(-) diff --git a/src/hotspot/cpu/arm/arm.ad b/src/hotspot/cpu/arm/arm.ad index 42d6d4151b2..f2ac7b58e73 100644 --- a/src/hotspot/cpu/arm/arm.ad +++ b/src/hotspot/cpu/arm/arm.ad @@ -1,5 +1,5 @@ // -// Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2008, 2022, 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 @@ -123,9 +123,18 @@ public: }; }; +// Assert that the given node is not a var shift. +bool assert_not_var_shift(const Node *n); %} source %{ + +// Assert that the given node is not a var shift. +bool assert_not_var_shift(const Node *n) { + assert(!n->as_ShiftV()->is_var_shift(), "illegal var shift"); + return true; +} + #define __ _masm. static FloatRegister reg_to_FloatRegister_object(int register_encoding); @@ -10591,7 +10600,7 @@ instruct vneg16B_reg(vecX dst, vecX src) %{ ins_pipe( ialu_reg_reg ); // FIXME %} -// ------------------------------ Shift --------------------------------------- +// ------------------------------ ShiftCount ---------------------------------- instruct vslcntD(vecD dst, iRegI cnt) %{ predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd()); @@ -10650,6 +10659,8 @@ instruct vsrcntX(vecX dst, iRegI cnt) %{ ins_pipe( ialu_reg_reg ); // FIXME %} +// ------------------------------ LogicalShift -------------------------------- + // Byte vector logical left/right shift based on sign instruct vsh8B_reg(vecD dst, vecD src, vecD shift) %{ predicate(n->as_Vector()->length() == 8); @@ -10766,9 +10777,9 @@ instruct vsh2L_reg(vecX dst, vecX src, vecX shift) %{ ins_pipe( ialu_reg_reg ); // FIXME %} -// ------------------------------ LeftShift ----------------------------------- +// ------------------------------ LogicalLeftShift ---------------------------- -// Byte vector left shift +// Byte vector logical left shift instruct vsl8B_reg(vecD dst, vecD src, vecD shift) %{ predicate(n->as_Vector()->length() == 8); match(Set dst (LShiftVB src shift)); @@ -10790,7 +10801,7 @@ instruct vsl16B_reg(vecX dst, vecX src, vecX shift) %{ %} instruct vsl8B_immI(vecD dst, vecD src, immI shift) %{ - predicate(n->as_Vector()->length() == 8); + predicate(n->as_Vector()->length() == 8 && assert_not_var_shift(n)); match(Set dst (LShiftVB src (LShiftCntV shift))); size(4); ins_cost(DEFAULT_COST); // FIXME @@ -10806,7 +10817,7 @@ instruct vsl8B_immI(vecD dst, vecD src, immI shift) %{ %} instruct vsl16B_immI(vecX dst, vecX src, immI shift) %{ - predicate(n->as_Vector()->length() == 16); + predicate(n->as_Vector()->length() == 16 && assert_not_var_shift(n)); match(Set dst (LShiftVB src (LShiftCntV shift))); size(4); ins_cost(DEFAULT_COST); // FIXME @@ -10821,11 +10832,10 @@ instruct vsl16B_immI(vecX dst, vecX src, immI shift) %{ ins_pipe( ialu_reg_reg ); // FIXME %} -// Shorts/Chars vector logical left/right shift +// Shorts/Chars vector logical left shift instruct vsl4S_reg(vecD dst, vecD src, vecD shift) %{ predicate(n->as_Vector()->length() == 4); match(Set dst (LShiftVS src shift)); - match(Set dst (URShiftVS src shift)); size(4*1); ins_cost(DEFAULT_COST*1); // FIXME expand %{ @@ -10836,7 +10846,6 @@ instruct vsl4S_reg(vecD dst, vecD src, vecD shift) %{ instruct vsl8S_reg(vecX dst, vecX src, vecX shift) %{ predicate(n->as_Vector()->length() == 8); match(Set dst (LShiftVS src shift)); - match(Set dst (URShiftVS src shift)); size(4*1); ins_cost(DEFAULT_COST*1); // FIXME expand %{ @@ -10845,7 +10854,7 @@ instruct vsl8S_reg(vecX dst, vecX src, vecX shift) %{ %} instruct vsl4S_immI(vecD dst, vecD src, immI shift) %{ - predicate(n->as_Vector()->length() == 4); + predicate(n->as_Vector()->length() == 4 && assert_not_var_shift(n)); match(Set dst (LShiftVS src (LShiftCntV shift))); size(4); ins_cost(DEFAULT_COST); // FIXME @@ -10861,7 +10870,7 @@ instruct vsl4S_immI(vecD dst, vecD src, immI shift) %{ %} instruct vsl8S_immI(vecX dst, vecX src, immI shift) %{ - predicate(n->as_Vector()->length() == 8); + predicate(n->as_Vector()->length() == 8 && assert_not_var_shift(n)); match(Set dst (LShiftVS src shift)); size(4); ins_cost(DEFAULT_COST); // FIXME @@ -10876,11 +10885,10 @@ instruct vsl8S_immI(vecX dst, vecX src, immI shift) %{ ins_pipe( ialu_reg_reg ); // FIXME %} -// Integers vector logical left/right shift +// Integers vector logical left shift instruct vsl2I_reg(vecD dst, vecD src, vecD shift) %{ predicate(n->as_Vector()->length() == 2 && VM_Version::has_simd()); match(Set dst (LShiftVI src shift)); - match(Set dst (URShiftVI src shift)); size(4*1); ins_cost(DEFAULT_COST*1); // FIXME expand %{ @@ -10891,7 +10899,6 @@ instruct vsl2I_reg(vecD dst, vecD src, vecD shift) %{ instruct vsl4I_reg(vecX dst, vecX src, vecX shift) %{ predicate(n->as_Vector()->length() == 4 && VM_Version::has_simd()); match(Set dst (LShiftVI src shift)); - match(Set dst (URShiftVI src shift)); size(4*1); ins_cost(DEFAULT_COST*1); // FIXME expand %{ @@ -10900,7 +10907,9 @@ instruct vsl4I_reg(vecX dst, vecX src, vecX shift) %{ %} instruct vsl2I_immI(vecD dst, vecD src, immI shift) %{ - predicate(n->as_Vector()->length() == 2 && VM_Version::has_simd()); + predicate(n->as_Vector()->length() == 2 && + VM_Version::has_simd() && + assert_not_var_shift(n)); match(Set dst (LShiftVI src (LShiftCntV shift))); size(4); ins_cost(DEFAULT_COST); // FIXME @@ -10916,7 +10925,9 @@ instruct vsl2I_immI(vecD dst, vecD src, immI shift) %{ %} instruct vsl4I_immI(vecX dst, vecX src, immI shift) %{ - predicate(n->as_Vector()->length() == 4 && VM_Version::has_simd()); + predicate(n->as_Vector()->length() == 4 && + VM_Version::has_simd() && + assert_not_var_shift(n)); match(Set dst (LShiftVI src (LShiftCntV shift))); size(4); ins_cost(DEFAULT_COST); // FIXME @@ -10931,11 +10942,10 @@ instruct vsl4I_immI(vecX dst, vecX src, immI shift) %{ ins_pipe( ialu_reg_reg ); // FIXME %} -// Longs vector logical left/right shift +// Longs vector logical left shift instruct vsl2L_reg(vecX dst, vecX src, vecX shift) %{ predicate(n->as_Vector()->length() == 2); match(Set dst (LShiftVL src shift)); - match(Set dst (URShiftVL src shift)); size(4*1); ins_cost(DEFAULT_COST*1); // FIXME expand %{ @@ -10944,7 +10954,7 @@ instruct vsl2L_reg(vecX dst, vecX src, vecX shift) %{ %} instruct vsl2L_immI(vecX dst, vecX src, immI shift) %{ - predicate(n->as_Vector()->length() == 2); + predicate(n->as_Vector()->length() == 2 && assert_not_var_shift(n)); match(Set dst (LShiftVL src (LShiftCntV shift))); size(4); ins_cost(DEFAULT_COST); // FIXME @@ -10965,9 +10975,79 @@ instruct vsl2L_immI(vecX dst, vecX src, immI shift) %{ // for negative data because java code convert short value into int with // sign extension before a shift. +// Right shift with vector shift count on aarch32 SIMD is implemented as left +// shift by negative shift count value. +// +// Method is_var_shift() denotes that vector shift count is a variable shift: +// 1) for this case, vector shift count should be negated before conducting +// right shifts. E.g., vsrl4S_reg_var rule. +// 2) for the opposite case, vector shift count is generated via RShiftCntV +// rules and is already negated there. Hence, no negation is needed. +// E.g., vsrl4S_reg rule. + // Chars vector logical right shift +instruct vsrl4S_reg(vecD dst, vecD src, vecD shift) %{ + predicate(n->as_Vector()->length() == 4 && !n->as_ShiftV()->is_var_shift()); + match(Set dst (URShiftVS src shift)); + size(4); + ins_cost(DEFAULT_COST); + expand %{ + vsh4S_reg(dst, src, shift); + %} +%} + +instruct vsrl4S_reg_var(vecD dst, vecD src, vecD shift, vecD tmp) %{ + predicate(n->as_Vector()->length() == 4 && n->as_ShiftV()->is_var_shift()); + match(Set dst (URShiftVS src shift)); + effect(TEMP tmp); + size(4*2); + ins_cost(DEFAULT_COST*2); + format %{ + "VNEG.S8 $tmp.D,$shift.D\n\t! neg packed8B" + "VSHL.U16 $dst.D,$src.D,$tmp.D\t! logical right shift packed4S" + %} + ins_encode %{ + bool quad = false; + __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister, + MacroAssembler::VELEM_SIZE_8, quad); + __ vshlUI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister, + MacroAssembler::VELEM_SIZE_16, quad); + %} + ins_pipe(ialu_reg_reg); +%} + +instruct vsrl8S_reg(vecX dst, vecX src, vecX shift) %{ + predicate(n->as_Vector()->length() == 8 && !n->as_ShiftV()->is_var_shift()); + match(Set dst (URShiftVS src shift)); + size(4); + ins_cost(DEFAULT_COST); + expand %{ + vsh8S_reg(dst, src, shift); + %} +%} + +instruct vsrl8S_reg_var(vecX dst, vecX src, vecX shift, vecX tmp) %{ + predicate(n->as_Vector()->length() == 8 && n->as_ShiftV()->is_var_shift()); + match(Set dst (URShiftVS src shift)); + effect(TEMP tmp); + size(4*2); + ins_cost(DEFAULT_COST*2); + format %{ + "VNEG.S8 $tmp.Q,$shift.Q\n\t! neg packed16B" + "VSHL.U16 $dst.Q,$src.Q,$tmp.Q\t! logical right shift packed8S" + %} + ins_encode %{ + bool quad = true; + __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister, + MacroAssembler::VELEM_SIZE_8, quad); + __ vshlUI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister, + MacroAssembler::VELEM_SIZE_16, quad); + %} + ins_pipe(ialu_reg_reg); +%} + instruct vsrl4S_immI(vecD dst, vecD src, immI shift) %{ - predicate(n->as_Vector()->length() == 4); + predicate(n->as_Vector()->length() == 4 && assert_not_var_shift(n)); match(Set dst (URShiftVS src (RShiftCntV shift))); size(4); ins_cost(DEFAULT_COST); // FIXME @@ -10983,7 +11063,7 @@ instruct vsrl4S_immI(vecD dst, vecD src, immI shift) %{ %} instruct vsrl8S_immI(vecX dst, vecX src, immI shift) %{ - predicate(n->as_Vector()->length() == 8); + predicate(n->as_Vector()->length() == 8 && assert_not_var_shift(n)); match(Set dst (URShiftVS src (RShiftCntV shift))); size(4); ins_cost(DEFAULT_COST); // FIXME @@ -10999,8 +11079,78 @@ instruct vsrl8S_immI(vecX dst, vecX src, immI shift) %{ %} // Integers vector logical right shift +instruct vsrl2I_reg(vecD dst, vecD src, vecD shift) %{ + predicate(n->as_Vector()->length() == 2 && + VM_Version::has_simd() && + !n->as_ShiftV()->is_var_shift()); + match(Set dst (URShiftVI src shift)); + size(4); + ins_cost(DEFAULT_COST); + expand %{ + vsh2I_reg(dst, src, shift); + %} +%} + +instruct vsrl2I_reg_var(vecD dst, vecD src, vecD shift, vecD tmp) %{ + predicate(n->as_Vector()->length() == 2 && + VM_Version::has_simd() && + n->as_ShiftV()->is_var_shift()); + match(Set dst (URShiftVI src shift)); + effect(TEMP tmp); + size(4*2); + ins_cost(DEFAULT_COST*2); + format %{ + "VNEG.S8 $tmp.D,$shift.D\n\t! neg packed8B" + "VSHL.U32 $dst.D,$src.D,$tmp.D\t! logical right shift packed2I" + %} + ins_encode %{ + bool quad = false; + __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister, + MacroAssembler::VELEM_SIZE_8, quad); + __ vshlUI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister, + MacroAssembler::VELEM_SIZE_32, quad); + %} + ins_pipe(ialu_reg_reg); +%} + +instruct vsrl4I_reg(vecX dst, vecX src, vecX shift) %{ + predicate(n->as_Vector()->length() == 4 && + VM_Version::has_simd() && + !n->as_ShiftV()->is_var_shift()); + match(Set dst (URShiftVI src shift)); + size(4); + ins_cost(DEFAULT_COST); + expand %{ + vsh4I_reg(dst, src, shift); + %} +%} + +instruct vsrl4I_reg_var(vecX dst, vecX src, vecX shift, vecX tmp) %{ + predicate(n->as_Vector()->length() == 4 && + VM_Version::has_simd() && + n->as_ShiftV()->is_var_shift()); + match(Set dst (URShiftVI src shift)); + effect(TEMP tmp); + size(4*2); + ins_cost(DEFAULT_COST*2); + format %{ + "VNEG.S8 $tmp.Q,$shift.Q\n\t! neg packed16B" + "VSHL.U32 $dst.Q,$src.Q,$tmp.Q\t! logical right shift packed4I" + %} + ins_encode %{ + bool quad = true; + __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister, + MacroAssembler::VELEM_SIZE_8, quad); + __ vshlUI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister, + MacroAssembler::VELEM_SIZE_32, quad); + %} + ins_pipe(ialu_reg_reg); +%} + instruct vsrl2I_immI(vecD dst, vecD src, immI shift) %{ - predicate(n->as_Vector()->length() == 2 && VM_Version::has_simd()); + predicate(n->as_Vector()->length() == 2 && + VM_Version::has_simd() && + assert_not_var_shift(n)); match(Set dst (URShiftVI src (RShiftCntV shift))); size(4); ins_cost(DEFAULT_COST); // FIXME @@ -11016,7 +11166,9 @@ instruct vsrl2I_immI(vecD dst, vecD src, immI shift) %{ %} instruct vsrl4I_immI(vecX dst, vecX src, immI shift) %{ - predicate(n->as_Vector()->length() == 4 && VM_Version::has_simd()); + predicate(n->as_Vector()->length() == 4 && + VM_Version::has_simd() && + assert_not_var_shift(n)); match(Set dst (URShiftVI src (RShiftCntV shift))); size(4); ins_cost(DEFAULT_COST); // FIXME @@ -11032,8 +11184,38 @@ instruct vsrl4I_immI(vecX dst, vecX src, immI shift) %{ %} // Longs vector logical right shift +instruct vsrl2L_reg(vecX dst, vecX src, vecX shift) %{ + predicate(n->as_Vector()->length() == 2 && !n->as_ShiftV()->is_var_shift()); + match(Set dst (URShiftVL src shift)); + size(4); + ins_cost(DEFAULT_COST); + expand %{ + vsh2L_reg(dst, src, shift); + %} +%} + +instruct vsrl2L_reg_var(vecX dst, vecX src, vecX shift, vecX tmp) %{ + predicate(n->as_Vector()->length() == 2 && n->as_ShiftV()->is_var_shift()); + match(Set dst (URShiftVL src shift)); + effect(TEMP tmp, DEF dst, USE src, USE shift); + size(4*2); + ins_cost(DEFAULT_COST*2); + format %{ + "VNEG.S8 $tmp.Q,$shift.Q\n\t! neg packed16B" + "VSHL.U64 $dst.Q,$src.Q,$tmp.Q\t! logical right shift packed2L" + %} + ins_encode %{ + bool quad = true; + __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister, + MacroAssembler::VELEM_SIZE_8, quad); + __ vshlUI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister, + MacroAssembler::VELEM_SIZE_64, quad); + %} + ins_pipe(ialu_reg_reg); +%} + instruct vsrl2L_immI(vecX dst, vecX src, immI shift) %{ - predicate(n->as_Vector()->length() == 2); + predicate(n->as_Vector()->length() == 2 && assert_not_var_shift(n)); match(Set dst (URShiftVL src (RShiftCntV shift))); size(4); ins_cost(DEFAULT_COST); // FIXME @@ -11167,9 +11349,8 @@ instruct vsha2L_reg(vecX dst, vecX src, vecX shift) %{ %} // Byte vector arithmetic right shift - instruct vsra8B_reg(vecD dst, vecD src, vecD shift) %{ - predicate(n->as_Vector()->length() == 8); + predicate(n->as_Vector()->length() == 8 && !n->as_ShiftV()->is_var_shift()); match(Set dst (RShiftVB src shift)); size(4); ins_cost(DEFAULT_COST); // FIXME @@ -11178,8 +11359,28 @@ instruct vsra8B_reg(vecD dst, vecD src, vecD shift) %{ %} %} -instruct vsrl16B_reg(vecX dst, vecX src, vecX shift) %{ - predicate(n->as_Vector()->length() == 16); +instruct vsra8B_reg_var(vecD dst, vecD src, vecD shift, vecD tmp) %{ + predicate(n->as_Vector()->length() == 8 && n->as_ShiftV()->is_var_shift()); + match(Set dst (RShiftVB src shift)); + effect(TEMP tmp); + size(4*2); + ins_cost(DEFAULT_COST*2); + format %{ + "VNEG.S8 $tmp.D,$shift.D\n\t! neg packed8B" + "VSHL.S8 $dst.D,$src.D,$tmp.D\t! arithmetic right shift packed8B" + %} + ins_encode %{ + bool quad = false; + __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister, + MacroAssembler::VELEM_SIZE_8, quad); + __ vshlSI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister, + MacroAssembler::VELEM_SIZE_8, quad); + %} + ins_pipe(ialu_reg_reg); +%} + +instruct vsra16B_reg(vecX dst, vecX src, vecX shift) %{ + predicate(n->as_Vector()->length() == 16 && !n->as_ShiftV()->is_var_shift()); match(Set dst (RShiftVB src shift)); size(4); ins_cost(DEFAULT_COST); // FIXME @@ -11188,13 +11389,33 @@ instruct vsrl16B_reg(vecX dst, vecX src, vecX shift) %{ %} %} -instruct vsrl8B_immI(vecD dst, vecD src, immI shift) %{ - predicate(n->as_Vector()->length() == 8); +instruct vsra16B_reg_var(vecX dst, vecX src, vecX shift, vecX tmp) %{ + predicate(n->as_Vector()->length() == 16 && n->as_ShiftV()->is_var_shift()); match(Set dst (RShiftVB src shift)); + effect(TEMP tmp); + size(4*2); + ins_cost(DEFAULT_COST*2); + format %{ + "VNEG.S8 $tmp.Q,$shift.Q\n\t! neg packed16B" + "VSHL.S8 $dst.Q,$src.Q,$tmp.Q\t! arithmetic right shift packed16B" + %} + ins_encode %{ + bool quad = true; + __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister, + MacroAssembler::VELEM_SIZE_8, quad); + __ vshlSI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister, + MacroAssembler::VELEM_SIZE_8, quad); + %} + ins_pipe(ialu_reg_reg); +%} + +instruct vsra8B_immI(vecD dst, vecD src, immI shift) %{ + predicate(n->as_Vector()->length() == 8 && assert_not_var_shift(n)); + match(Set dst (RShiftVB src (RShiftCntV shift))); size(4); ins_cost(DEFAULT_COST); // FIXME format %{ - "VSHR.S8 $dst.D,$src.D,$shift\t! logical right shift packed8B" + "VSHR.S8 $dst.D,$src.D,$shift\t! arithmetic right shift packed8B" %} ins_encode %{ bool quad = false; @@ -11204,13 +11425,13 @@ instruct vsrl8B_immI(vecD dst, vecD src, immI shift) %{ ins_pipe( ialu_reg_reg ); // FIXME %} -instruct vsrl16B_immI(vecX dst, vecX src, immI shift) %{ - predicate(n->as_Vector()->length() == 16); - match(Set dst (RShiftVB src shift)); +instruct vsra16B_immI(vecX dst, vecX src, immI shift) %{ + predicate(n->as_Vector()->length() == 16 && assert_not_var_shift(n)); + match(Set dst (RShiftVB src (RShiftCntV shift))); size(4); ins_cost(DEFAULT_COST); // FIXME format %{ - "VSHR.S8 $dst.Q,$src.Q,$shift\t! logical right shift packed16B" + "VSHR.S8 $dst.Q,$src.Q,$shift\t! arithmetic right shift packed16B" %} ins_encode %{ bool quad = true; @@ -11222,7 +11443,7 @@ instruct vsrl16B_immI(vecX dst, vecX src, immI shift) %{ // Shorts vector arithmetic right shift instruct vsra4S_reg(vecD dst, vecD src, vecD shift) %{ - predicate(n->as_Vector()->length() == 4); + predicate(n->as_Vector()->length() == 4 && !n->as_ShiftV()->is_var_shift()); match(Set dst (RShiftVS src shift)); size(4); ins_cost(DEFAULT_COST); // FIXME @@ -11231,8 +11452,28 @@ instruct vsra4S_reg(vecD dst, vecD src, vecD shift) %{ %} %} +instruct vsra4S_reg_var(vecD dst, vecD src, vecD shift, vecD tmp) %{ + predicate(n->as_Vector()->length() == 4 && n->as_ShiftV()->is_var_shift()); + match(Set dst (RShiftVS src shift)); + effect(TEMP tmp); + size(4*2); + ins_cost(DEFAULT_COST*2); + format %{ + "VNEG.S8 $tmp.D,$shift.D\n\t! neg packed8B" + "VSHL.S16 $dst.D,$src.D,$tmp.D\t! arithmetic right shift packed4S" + %} + ins_encode %{ + bool quad = false; + __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister, + MacroAssembler::VELEM_SIZE_8, quad); + __ vshlSI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister, + MacroAssembler::VELEM_SIZE_16, quad); + %} + ins_pipe(ialu_reg_reg); +%} + instruct vsra8S_reg(vecX dst, vecX src, vecX shift) %{ - predicate(n->as_Vector()->length() == 8); + predicate(n->as_Vector()->length() == 8 && !n->as_ShiftV()->is_var_shift()); match(Set dst (RShiftVS src shift)); size(4); ins_cost(DEFAULT_COST); // FIXME @@ -11241,13 +11482,33 @@ instruct vsra8S_reg(vecX dst, vecX src, vecX shift) %{ %} %} -instruct vsra4S_immI(vecD dst, vecD src, immI shift) %{ - predicate(n->as_Vector()->length() == 4); +instruct vsra8S_reg_var(vecX dst, vecX src, vecX shift, vecX tmp) %{ + predicate(n->as_Vector()->length() == 8 && n->as_ShiftV()->is_var_shift()); match(Set dst (RShiftVS src shift)); + effect(TEMP tmp); + size(4*2); + ins_cost(DEFAULT_COST*2); + format %{ + "VNEG.S8 $tmp.Q,$shift.Q\n\t! neg packed16B" + "VSHL.S16 $dst.Q,$src.Q,$tmp.Q\t! arithmetic right shift packed8S" + %} + ins_encode %{ + bool quad = true; + __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister, + MacroAssembler::VELEM_SIZE_8, quad); + __ vshlSI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister, + MacroAssembler::VELEM_SIZE_16, quad); + %} + ins_pipe(ialu_reg_reg); +%} + +instruct vsra4S_immI(vecD dst, vecD src, immI shift) %{ + predicate(n->as_Vector()->length() == 4 && assert_not_var_shift(n)); + match(Set dst (RShiftVS src (RShiftCntV shift))); size(4); ins_cost(DEFAULT_COST); // FIXME format %{ - "VSHR.S16 $dst.D,$src.D,$shift\t! logical right shift packed4S" + "VSHR.S16 $dst.D,$src.D,$shift\t! arithmetic right shift packed4S" %} ins_encode %{ bool quad = false; @@ -11258,12 +11519,12 @@ instruct vsra4S_immI(vecD dst, vecD src, immI shift) %{ %} instruct vsra8S_immI(vecX dst, vecX src, immI shift) %{ - predicate(n->as_Vector()->length() == 8); - match(Set dst (RShiftVS src shift)); + predicate(n->as_Vector()->length() == 8 && assert_not_var_shift(n)); + match(Set dst (RShiftVS src (RShiftCntV shift))); size(4); ins_cost(DEFAULT_COST); // FIXME format %{ - "VSHR.S16 $dst.Q,$src.Q,$shift\t! logical right shift packed8S" + "VSHR.S16 $dst.Q,$src.Q,$shift\t! arithmetic right shift packed8S" %} ins_encode %{ bool quad = true; @@ -11275,7 +11536,7 @@ instruct vsra8S_immI(vecX dst, vecX src, immI shift) %{ // Integers vector arithmetic right shift instruct vsra2I_reg(vecD dst, vecD src, vecD shift) %{ - predicate(n->as_Vector()->length() == 2); + predicate(n->as_Vector()->length() == 2 && !n->as_ShiftV()->is_var_shift()); match(Set dst (RShiftVI src shift)); size(4); ins_cost(DEFAULT_COST); // FIXME @@ -11284,8 +11545,28 @@ instruct vsra2I_reg(vecD dst, vecD src, vecD shift) %{ %} %} +instruct vsra2I_reg_var(vecD dst, vecD src, vecD shift, vecD tmp) %{ + predicate(n->as_Vector()->length() == 2 && n->as_ShiftV()->is_var_shift()); + match(Set dst (RShiftVI src shift)); + effect(TEMP tmp); + size(4*2); + ins_cost(DEFAULT_COST*2); + format %{ + "VNEG.S8 $tmp.D,$shift.D\n\t! neg packed8B" + "VSHL.S32 $dst.D,$src.D,$tmp.D\t! arithmetic right shift packed2I" + %} + ins_encode %{ + bool quad = false; + __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister, + MacroAssembler::VELEM_SIZE_8, quad); + __ vshlSI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister, + MacroAssembler::VELEM_SIZE_32, quad); + %} + ins_pipe(ialu_reg_reg); +%} + instruct vsra4I_reg(vecX dst, vecX src, vecX shift) %{ - predicate(n->as_Vector()->length() == 4); + predicate(n->as_Vector()->length() == 4 && !n->as_ShiftV()->is_var_shift()); match(Set dst (RShiftVI src shift)); size(4); ins_cost(DEFAULT_COST); // FIXME @@ -11294,13 +11575,33 @@ instruct vsra4I_reg(vecX dst, vecX src, vecX shift) %{ %} %} -instruct vsra2I_immI(vecD dst, vecD src, immI shift) %{ - predicate(n->as_Vector()->length() == 2); +instruct vsra4I_reg_var(vecX dst, vecX src, vecX shift, vecX tmp) %{ + predicate(n->as_Vector()->length() == 4 && n->as_ShiftV()->is_var_shift()); match(Set dst (RShiftVI src shift)); + effect(TEMP tmp); + size(4*2); + ins_cost(DEFAULT_COST*2); + format %{ + "VNEG.S8 $tmp.Q,$shift.Q\n\t! neg packed16B" + "VSHL.S32 $dst.Q,$src.Q,$tmp.Q\t! arithmetic right shift packed4I" + %} + ins_encode %{ + bool quad = true; + __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister, + MacroAssembler::VELEM_SIZE_8, quad); + __ vshlSI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister, + MacroAssembler::VELEM_SIZE_32, quad); + %} + ins_pipe(ialu_reg_reg); +%} + +instruct vsra2I_immI(vecD dst, vecD src, immI shift) %{ + predicate(n->as_Vector()->length() == 2 && assert_not_var_shift(n)); + match(Set dst (RShiftVI src (RShiftCntV shift))); size(4); ins_cost(DEFAULT_COST); // FIXME format %{ - "VSHR.S32 $dst.D,$src.D,$shift\t! logical right shift packed2I" + "VSHR.S32 $dst.D,$src.D,$shift\t! arithmetic right shift packed2I" %} ins_encode %{ bool quad = false; @@ -11311,12 +11612,12 @@ instruct vsra2I_immI(vecD dst, vecD src, immI shift) %{ %} instruct vsra4I_immI(vecX dst, vecX src, immI shift) %{ - predicate(n->as_Vector()->length() == 4); - match(Set dst (RShiftVI src shift)); + predicate(n->as_Vector()->length() == 4 && assert_not_var_shift(n)); + match(Set dst (RShiftVI src (RShiftCntV shift))); size(4); ins_cost(DEFAULT_COST); // FIXME format %{ - "VSHR.S32 $dst.Q,$src.Q,$shift\t! logical right shift packed4I" + "VSHR.S32 $dst.Q,$src.Q,$shift\t! arithmetic right shift packed4I" %} ins_encode %{ bool quad = true; @@ -11328,7 +11629,7 @@ instruct vsra4I_immI(vecX dst, vecX src, immI shift) %{ // Longs vector arithmetic right shift instruct vsra2L_reg(vecX dst, vecX src, vecX shift) %{ - predicate(n->as_Vector()->length() == 2); + predicate(n->as_Vector()->length() == 2 && !n->as_ShiftV()->is_var_shift()); match(Set dst (RShiftVL src shift)); size(4); ins_cost(DEFAULT_COST); // FIXME @@ -11337,13 +11638,33 @@ instruct vsra2L_reg(vecX dst, vecX src, vecX shift) %{ %} %} -instruct vsra2L_immI(vecX dst, vecX src, immI shift) %{ - predicate(n->as_Vector()->length() == 2); +instruct vsra2L_reg_var(vecX dst, vecX src, vecX shift, vecX tmp) %{ + predicate(n->as_Vector()->length() == 2 && n->as_ShiftV()->is_var_shift()); match(Set dst (RShiftVL src shift)); + effect(TEMP tmp); + size(4*2); + ins_cost(DEFAULT_COST*2); + format %{ + "VNEG.S8 $tmp.Q,$shift.Q\n\t! neg packed16B" + "VSHL.S64 $dst.Q,$src.Q,$tmp.Q\t! arithmetic right shift packed2L" + %} + ins_encode %{ + bool quad = true; + __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister, + MacroAssembler::VELEM_SIZE_8, quad); + __ vshlSI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister, + MacroAssembler::VELEM_SIZE_64, quad); + %} + ins_pipe(ialu_reg_reg); +%} + +instruct vsra2L_immI(vecX dst, vecX src, immI shift) %{ + predicate(n->as_Vector()->length() == 2 && assert_not_var_shift(n)); + match(Set dst (RShiftVL src (RShiftCntV shift))); size(4); ins_cost(DEFAULT_COST); // FIXME format %{ - "VSHR.S64 $dst.Q,$src.Q,$shift\t! logical right shift packed2L" + "VSHR.S64 $dst.Q,$src.Q,$shift\t! arithmetic right shift packed2L" %} ins_encode %{ bool quad = true; diff --git a/src/hotspot/share/opto/vectornode.hpp b/src/hotspot/share/opto/vectornode.hpp index fc424f59a3e..062ad947c1f 100644 --- a/src/hotspot/share/opto/vectornode.hpp +++ b/src/hotspot/share/opto/vectornode.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2022, 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 @@ -531,7 +531,8 @@ class SqrtVDNode : public VectorNode { // Class ShiftV functionality. This covers the common behaviors for all kinds // of vector shifts. class ShiftVNode : public VectorNode { - bool _is_var_shift; + private: + bool _is_var_shift; public: ShiftVNode(Node* in1, Node* in2, const TypeVect* vt, bool is_var_shift) : VectorNode(in1,in2,vt), _is_var_shift(is_var_shift) { @@ -539,8 +540,12 @@ class ShiftVNode : public VectorNode { } virtual Node* Identity(PhaseGVN* phase); virtual int Opcode() const = 0; + virtual uint hash() const { return VectorNode::hash() + _is_var_shift; } + virtual bool cmp(const Node& n) const { + return VectorNode::cmp(n) && _is_var_shift == ((ShiftVNode&)n)._is_var_shift; + } bool is_var_shift() { return _is_var_shift;} - virtual uint size_of() const { return sizeof(ShiftVNode); } + virtual uint size_of() const { return sizeof(ShiftVNode); } }; //------------------------------LShiftVBNode----------------------------------- -- GitLab From 92307e5a944f7e995780fc6f5e55713802919dfd Mon Sep 17 00:00:00 2001 From: Roman Kennke Date: Mon, 10 Jan 2022 20:47:23 +0000 Subject: [PATCH 054/564] 8278489: Preserve result in native wrapper with +UseHeavyMonitors Reviewed-by: shade, kvn --- src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp | 11 ++++++----- src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp | 10 ++++++---- src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp | 10 ++++++---- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp index 254cde16e09..08cc2b20a61 100644 --- a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp @@ -1783,13 +1783,14 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // Simple recursive lock? __ ldr(rscratch1, Address(sp, lock_slot_offset * VMRegImpl::stack_slot_size)); __ cbz(rscratch1, done); + } - // Must save r0 if if it is live now because cmpxchg must use it - if (ret_type != T_FLOAT && ret_type != T_DOUBLE && ret_type != T_VOID) { - save_native_result(masm, ret_type, stack_slots); - } - + // Must save r0 if if it is live now because cmpxchg must use it + if (ret_type != T_FLOAT && ret_type != T_DOUBLE && ret_type != T_VOID) { + save_native_result(masm, ret_type, stack_slots); + } + if (!UseHeavyMonitors) { // get address of the stack lock __ lea(r0, Address(sp, lock_slot_offset * VMRegImpl::stack_slot_size)); // get old displaced header diff --git a/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp b/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp index e139b3cf6eb..e5a46138473 100644 --- a/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp +++ b/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp @@ -1862,12 +1862,14 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, __ cmpptr(Address(rbp, lock_slot_rbp_offset), (int32_t)NULL_WORD); __ jcc(Assembler::equal, done); + } - // Must save rax, if if it is live now because cmpxchg must use it - if (ret_type != T_FLOAT && ret_type != T_DOUBLE && ret_type != T_VOID) { - save_native_result(masm, ret_type, stack_slots); - } + // Must save rax, if it is live now because cmpxchg must use it + if (ret_type != T_FLOAT && ret_type != T_DOUBLE && ret_type != T_VOID) { + save_native_result(masm, ret_type, stack_slots); + } + if (!UseHeavyMonitors) { // get old displaced header __ movptr(rbx, Address(rbp, lock_slot_rbp_offset)); diff --git a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp index 9ff40e943ba..cf1e3760a37 100644 --- a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp +++ b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp @@ -2064,13 +2064,15 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // Simple recursive lock? __ cmpptr(Address(rsp, lock_slot_offset * VMRegImpl::stack_slot_size), (int32_t)NULL_WORD); __ jcc(Assembler::equal, done); + } - // Must save rax if if it is live now because cmpxchg must use it - if (ret_type != T_FLOAT && ret_type != T_DOUBLE && ret_type != T_VOID) { - save_native_result(masm, ret_type, stack_slots); - } + // Must save rax if it is live now because cmpxchg must use it + if (ret_type != T_FLOAT && ret_type != T_DOUBLE && ret_type != T_VOID) { + save_native_result(masm, ret_type, stack_slots); + } + if (!UseHeavyMonitors) { // get address of the stack lock __ lea(rax, Address(rsp, lock_slot_offset * VMRegImpl::stack_slot_size)); // get old displaced header -- GitLab From 2f7665b8292cc09574d62fecc3e9619c488ac137 Mon Sep 17 00:00:00 2001 From: Yasumasa Suenaga Date: Tue, 11 Jan 2022 00:21:20 +0000 Subject: [PATCH 055/564] 8279644: hsdis may not work when it was built with --with-binutils=system Reviewed-by: erikj --- make/autoconf/jdk-options.m4 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/make/autoconf/jdk-options.m4 b/make/autoconf/jdk-options.m4 index cc4a44d39c9..0a7145c9116 100644 --- a/make/autoconf/jdk-options.m4 +++ b/make/autoconf/jdk-options.m4 @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2022, 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 @@ -847,6 +847,7 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_HSDIS], AC_CHECK_LIB(opcodes, disassembler, [ HSDIS_LIBS="$HSDIS_LIBS -lopcodes" ], [ binutils_system_error="libopcodes not found" ]) AC_CHECK_LIB(iberty, xmalloc, [ HSDIS_LIBS="$HSDIS_LIBS -liberty" ], [ binutils_system_error="libiberty not found" ]) AC_CHECK_LIB(z, deflate, [ HSDIS_LIBS="$HSDIS_LIBS -lz" ], [ binutils_system_error="libz not found" ]) + HSDIS_CFLAGS="-DLIBARCH_$OPENJDK_TARGET_CPU_LEGACY_LIB" elif test "x$BINUTILS_DIR" != x; then if test -e $BINUTILS_DIR/bfd/libbfd.a && \ test -e $BINUTILS_DIR/opcodes/libopcodes.a && \ @@ -864,7 +865,7 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_HSDIS], AC_MSG_ERROR([binutils on system is supported for Linux only]) elif test "x$binutils_system_error" = x; then AC_MSG_RESULT([system]) - HSDIS_CFLAGS="-DSYSTEM_BINUTILS" + HSDIS_CFLAGS="$HSDIS_CFLAGS -DSYSTEM_BINUTILS" else AC_MSG_RESULT([invalid]) AC_MSG_ERROR([$binutils_system_error]) -- GitLab From 2f13872d5152a7fab122d52ebcfb468dc0db7ac5 Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Tue, 11 Jan 2022 02:51:53 +0000 Subject: [PATCH 056/564] 8279646: JFR: Remove recursive call in jdk.jfr.internal.Control Reviewed-by: mgronlun --- src/jdk.jfr/share/classes/jdk/jfr/internal/Control.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/Control.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/Control.java index 0887d1ce0ed..27281cd5f58 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/Control.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/Control.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, 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,7 @@ public final class Control { public String getValue() { if (context == null) { // VM events requires no access control context - return getValue(); + return delegate.getValue(); } else { return AccessController.doPrivileged(new PrivilegedAction() { @Override -- GitLab From 6504458d87cdf6001f70c354b11942516a457137 Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Tue, 11 Jan 2022 04:39:39 +0000 Subject: [PATCH 057/564] 8279647: JFR: Unclosed directory stream Reviewed-by: mgronlun --- .../classes/jdk/jfr/internal/SecuritySupport.java | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/SecuritySupport.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/SecuritySupport.java index ae03bce313d..d34a09c34d6 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/SecuritySupport.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/SecuritySupport.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, 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 @@ -267,14 +267,11 @@ public final class SecuritySupport { public static List getPredefinedJFCFiles() { List list = new ArrayList<>(); - try { - Iterator pathIterator = doPrivilegedIOWithReturn(() -> { - return Files.newDirectoryStream(JFC_DIRECTORY.toPath(), "*").iterator(); - }); - while (pathIterator.hasNext()) { - Path path = pathIterator.next(); - if (path.toString().endsWith(".jfc")) { - list.add(new SafePath(path)); + try (var ds = doPrivilegedIOWithReturn(() -> Files.newDirectoryStream(JFC_DIRECTORY.toPath(), "*.jfc"))) { + for (Path path : ds) { + SafePath s = new SafePath(path); + if (!SecuritySupport.isDirectory(s)) { + list.add(s); } } } catch (IOException ioe) { -- GitLab From ec5a455efb04a503836f10db214d6b95bf9b4c37 Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Tue, 11 Jan 2022 05:49:21 +0000 Subject: [PATCH 058/564] 8279682: JFR: Remove dead code Reviewed-by: mgronlun --- .../share/classes/jdk/jfr/Recording.java | 19 ------------------- .../jdk/jfr/internal/SecuritySupport.java | 13 ------------- .../jfr/internal/consumer/ChunkHeader.java | 8 -------- .../consumer/EventDirectoryStream.java | 15 ++------------- .../jfr/internal/settings/CutoffSetting.java | 4 ---- .../internal/settings/ThrottleSetting.java | 4 ---- 6 files changed, 2 insertions(+), 61 deletions(-) diff --git a/src/jdk.jfr/share/classes/jdk/jfr/Recording.java b/src/jdk.jfr/share/classes/jdk/jfr/Recording.java index 71ef9cebc25..1dd4b303013 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/Recording.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/Recording.java @@ -424,25 +424,6 @@ public final class Recording implements Closeable { internal.setMaxSize(maxSize); } - /** - * Determines how often events are made available for streaming. - * - * @param interval the interval at which events are made available for streaming. - * - * @throws IllegalArgumentException if {@code interval} is negative - * - * @throws IllegalStateException if the recording is in the {@code CLOSED} state - * - * @since 14 - */ - /*package private*/ void setFlushInterval(Duration interval) { - Objects.requireNonNull(interval); - if (interval.isNegative()) { - throw new IllegalArgumentException("Stream interval can't be negative"); - } - internal.setFlushInterval(interval); - } - /** * Returns how often events are made available for streaming purposes. * diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/SecuritySupport.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/SecuritySupport.java index d34a09c34d6..a3d6f24cd1a 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/SecuritySupport.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/SecuritySupport.java @@ -33,7 +33,6 @@ import java.io.RandomAccessFile; import java.io.Reader; import java.lang.invoke.MethodHandles; import java.lang.reflect.Constructor; -import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.ReflectPermission; import java.nio.channels.FileChannel; @@ -354,10 +353,6 @@ public final class SecuritySupport { doPrivileged(() -> thread.setUncaughtExceptionHandler(eh), new RuntimePermission("modifyThread")); } - static void moveReplace(SafePath from, SafePath to) throws IOException { - doPrivilegedIOWithReturn(() -> Files.move(from.toPath(), to.toPath())); - } - static void clearDirectory(SafePath safePath) throws IOException { doPriviligedIO(() -> Files.walkFileTree(safePath.toPath(), new DirectoryCleaner())); } @@ -404,10 +399,6 @@ public final class SecuritySupport { return doPrivilegedIOWithReturn(() -> Files.isWritable(safePath.toPath())); } - static void deleteOnExit(SafePath safePath) { - doPrivileged(() -> safePath.toPath().toFile().deleteOnExit()); - } - static ReadableByteChannel newFileChannelToRead(SafePath safePath) throws IOException { return doPrivilegedIOWithReturn(() -> FileChannel.open(safePath.toPath(), StandardOpenOption.READ)); } @@ -420,10 +411,6 @@ public final class SecuritySupport { return doPrivilegedIOWithReturn(() -> Files.newBufferedReader(safePath.toPath())); } - static void touch(SafePath path) throws IOException { - doPriviligedIO(() -> new RandomAccessFile(path.toPath().toFile(), "rw").close()); - } - static void setAccessible(Method method) { doPrivileged(() -> method.setAccessible(true), new ReflectPermission("suppressAccessChecks")); } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ChunkHeader.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ChunkHeader.java index 4027f447cf4..95aa47a34bb 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ChunkHeader.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ChunkHeader.java @@ -163,14 +163,6 @@ public final class ChunkHeader { } } - public boolean readHeader(byte[] bytes, int count) throws IOException { - input.position(absoluteChunkStart); - for (int i = 0; i< count; i++) { - bytes[i] = input.readPhysicalByte(); - } - return bytes[(int)FILE_STATE_POSITION] != UPDATING_CHUNK_HEADER; - } - public void awaitFinished() throws IOException { if (finished) { return; diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventDirectoryStream.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventDirectoryStream.java index d5efcb90d3c..37fea4b9439 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventDirectoryStream.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventDirectoryStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,6 @@ package jdk.jfr.internal.consumer; import java.io.IOException; import java.nio.file.Path; import java.security.AccessControlContext; -import java.time.Duration; import java.time.Instant; import java.util.Arrays; import java.util.Comparator; @@ -49,7 +48,7 @@ import jdk.jfr.internal.consumer.ChunkParser.ParserConfiguration; * with chunk files. * */ -public class EventDirectoryStream extends AbstractEventStream { +public final class EventDirectoryStream extends AbstractEventStream { private static final Comparator EVENT_COMPARATOR = JdkJfrConsumer.instance().eventComparator(); @@ -60,8 +59,6 @@ public class EventDirectoryStream extends AbstractEventStream { private long currentChunkStartNanos; private RecordedEvent[] sortedCache; private int threadExclusionLevel = 0; - protected volatile long maxSize; - protected volatile Duration maxAge; private volatile Consumer onCompleteHandler; @@ -259,12 +256,4 @@ public class EventDirectoryStream extends AbstractEventStream { c.dispatch(e); } } - - public void setMaxSize(long maxSize) { - this.maxSize = maxSize; - } - - public void setMaxAge(Duration maxAge) { - this.maxAge = maxAge; - } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/CutoffSetting.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/CutoffSetting.java index 8a35a6b9639..bdbeb4959b3 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/CutoffSetting.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/CutoffSetting.java @@ -78,10 +78,6 @@ public final class CutoffSetting extends JDKSettingControl { return value; } - public static boolean isType(long typeId) { - return CutoffSetting.typeId == typeId; - } - public static long parseValueSafe(String value) { if (value == null) { return 0L; diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/ThrottleSetting.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/ThrottleSetting.java index a05544c25c4..49d676d636a 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/ThrottleSetting.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/ThrottleSetting.java @@ -91,9 +91,5 @@ public final class ThrottleSetting extends JDKSettingControl { public String getValue() { return value; } - - public static boolean isType(long typeId) { - return ThrottleSetting.typeId == typeId; - } } -- GitLab From 126328cb6218a93d23ed6169d7e52fb2719528ed Mon Sep 17 00:00:00 2001 From: Wang Huang Date: Tue, 11 Jan 2022 06:40:46 +0000 Subject: [PATCH 059/564] 8279560: AArch64: generate_compare_long_string_same_encoding and LARGE_LOOP_PREFETCH alignment Co-authored-by: Wang Huang Reviewed-by: shade, aph --- src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp index dbfdae754af..7d7f9b57e8c 100644 --- a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2014, 2021, Red Hat Inc. All rights reserved. + * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2022, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -5337,11 +5337,11 @@ class StubGenerator: public StubCodeGenerator { __ add(str1, str1, wordSize); __ add(str2, str2, wordSize); if (SoftwarePrefetchHintDistance >= 0) { + __ align(OptoLoopAlignment); __ bind(LARGE_LOOP_PREFETCH); __ prfm(Address(str1, SoftwarePrefetchHintDistance)); __ prfm(Address(str2, SoftwarePrefetchHintDistance)); - __ align(OptoLoopAlignment); for (int i = 0; i < 4; i++) { __ ldp(tmp1, tmp1h, Address(str1, i * 16)); __ ldp(tmp2, tmp2h, Address(str2, i * 16)); -- GitLab From 6d7db4b0b3e9172645cef12c36fbeb41a6d38d83 Mon Sep 17 00:00:00 2001 From: Tobias Hartmann Date: Tue, 11 Jan 2022 06:59:26 +0000 Subject: [PATCH 060/564] 8279356: Method linking fails with guarantee(mh->adapter() != NULL) failed: Adapter blob must already exist! Reviewed-by: chagedorn, kvn, coleenp --- src/hotspot/share/oops/method.cpp | 4 +- .../codecache/OverflowCodeCacheTest.java | 57 ++++++++++++++++--- 2 files changed, 51 insertions(+), 10 deletions(-) diff --git a/src/hotspot/share/oops/method.cpp b/src/hotspot/share/oops/method.cpp index 5a503ddf207..04ccc8af829 100644 --- a/src/hotspot/share/oops/method.cpp +++ b/src/hotspot/share/oops/method.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -1198,7 +1198,7 @@ void Method::unlink_method() { void Method::link_method(const methodHandle& h_method, TRAPS) { // If the code cache is full, we may reenter this function for the // leftover methods that weren't linked. - if (_i2i_entry != NULL) { + if (adapter() != NULL) { return; } assert( _code == NULL, "nothing compiled yet" ); diff --git a/test/hotspot/jtreg/compiler/codecache/OverflowCodeCacheTest.java b/test/hotspot/jtreg/compiler/codecache/OverflowCodeCacheTest.java index 1dc02e25312..cd69d0a31da 100644 --- a/test/hotspot/jtreg/compiler/codecache/OverflowCodeCacheTest.java +++ b/test/hotspot/jtreg/compiler/codecache/OverflowCodeCacheTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2022, 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 OverflowCodeCacheTest - * @bug 8059550 + * @bug 8059550 8279356 * @summary testing of code cache segments overflow * @library /test/lib * @modules java.base/jdk.internal.misc @@ -33,11 +33,14 @@ * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI -XX:CompileCommand=compileonly,null::* - * -XX:-SegmentedCodeCache - * compiler.codecache.OverflowCodeCacheTest + * -XX:-SegmentedCodeCache -Xmixed + * compiler.codecache.OverflowCodeCacheTest CompilationDisabled * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI -XX:CompileCommand=compileonly,null::* - * -XX:+SegmentedCodeCache + * -XX:+SegmentedCodeCache -Xmixed + * compiler.codecache.OverflowCodeCacheTest CompilationDisabled + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI -XX:-SegmentedCodeCache -Xmixed * compiler.codecache.OverflowCodeCacheTest */ @@ -49,13 +52,21 @@ import sun.hotspot.code.BlobType; import sun.hotspot.code.CodeBlob; import java.lang.management.MemoryPoolMXBean; +import java.lang.reflect.Method; import java.util.ArrayList; import java.util.EnumSet; +class Helper { + // Uncommon signature to prevent sharing and force creation of a new adapter + public void method(float a, float b, float c, Object o) { } +} + public class OverflowCodeCacheTest { private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); + private static boolean COMPILATION_DISABLED = false; public static void main(String[] args) { + COMPILATION_DISABLED = args.length > 0; EnumSet blobTypes = BlobType.getAvailable(); for (BlobType type : blobTypes) { new OverflowCodeCacheTest(type).test(); @@ -74,6 +85,8 @@ public class OverflowCodeCacheTest { System.out.println("allocating till possible..."); ArrayList blobs = new ArrayList<>(); int compilationActivityMode = -1; + // Lock compilation to be able to better control code cache space + WHITE_BOX.lockCompilation(); try { long addr; int size = (int) (getHeapSize() >> 7); @@ -88,15 +101,43 @@ public class OverflowCodeCacheTest { } } /* now, remember compilationActivityMode to check it later, after freeing, since we - possibly have no free cache for futher work */ + possibly have no free cache for further work */ compilationActivityMode = WHITE_BOX.getCompilationActivityMode(); + + // Use smallest allocation size to make sure all of the available space + // is filled up. Don't free these below to put some pressure on the sweeper. + while ((addr = WHITE_BOX.allocateCodeBlob(1, type.id)) != 0) { } } finally { + try { + // Trigger creation of a new adapter for Helper::method + // which will fail because we are out of code cache space. + Helper helper = new Helper(); + } catch (VirtualMachineError e) { + // Expected + } + // Free code cache space for (Long blob : blobs) { WHITE_BOX.freeCodeBlob(blob); } + + // Convert some nmethods to zombie and then free them to re-enable compilation + WHITE_BOX.unlockCompilation(); + WHITE_BOX.forceNMethodSweep(); + WHITE_BOX.forceNMethodSweep(); + + // Trigger compilation of Helper::method which will hit an assert because + // adapter creation failed above due to a lack of code cache space. + Helper helper = new Helper(); + for (int i = 0; i < 100_000; i++) { + helper.method(0, 0, 0, null); + } + } + // Only check this if compilation is disabled, otherwise the sweeper might have + // freed enough nmethods to allow for re-enabling compilation. + if (COMPILATION_DISABLED) { + Asserts.assertNotEquals(compilationActivityMode, 1 /* run_compilation*/, + "Compilation must be disabled when CodeCache(CodeHeap) overflows"); } - Asserts.assertNotEquals(compilationActivityMode, 1 /* run_compilation*/, - "Compilation must be disabled when CodeCache(CodeHeap) overflows"); } private long getHeapSize() { -- GitLab From bf7bcaacaab12dbba1c2fb010487ed9196cb2fa5 Mon Sep 17 00:00:00 2001 From: Emanuel Peter Date: Tue, 11 Jan 2022 08:32:40 +0000 Subject: [PATCH 061/564] 8277748: Obsolete the MinInliningThreshold flag in JDK 19 Reviewed-by: kvn, thartmann --- src/hotspot/share/opto/bytecodeInfo.cpp | 8 -------- src/hotspot/share/runtime/arguments.cpp | 2 +- src/hotspot/share/runtime/globals.hpp | 5 ----- 3 files changed, 1 insertion(+), 14 deletions(-) diff --git a/src/hotspot/share/opto/bytecodeInfo.cpp b/src/hotspot/share/opto/bytecodeInfo.cpp index 40d09201530..2da95b4edcc 100644 --- a/src/hotspot/share/opto/bytecodeInfo.cpp +++ b/src/hotspot/share/opto/bytecodeInfo.cpp @@ -319,14 +319,6 @@ bool InlineTree::should_not_inline(ciMethod* callee_method, ciMethod* caller_met return true; } } - - if (MinInliningThreshold > 0) { // Deprecated heuristic - intx counter_high_value = TieredCompilation ? InvocationCounter::count_limit / 2 : CompileThreshold / 2; - if (!callee_method->was_executed_more_than(MIN2(MinInliningThreshold, counter_high_value))) { - set_msg("executed < MinInliningThreshold times"); - return true; - } - } } return false; diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index ea5b5d4dfd8..f6983ba5019 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -530,7 +530,6 @@ static SpecialFlag const special_jvm_flags[] = { { "InitialRAMFraction", JDK_Version::jdk(10), JDK_Version::undefined(), JDK_Version::undefined() }, { "AllowRedefinitionToAddDeleteMethods", JDK_Version::jdk(13), JDK_Version::undefined(), JDK_Version::undefined() }, { "FlightRecorder", JDK_Version::jdk(13), JDK_Version::undefined(), JDK_Version::undefined() }, - { "MinInliningThreshold", JDK_Version::jdk(18), JDK_Version::jdk(19), JDK_Version::jdk(20) }, { "DumpSharedSpaces", JDK_Version::jdk(18), JDK_Version::jdk(19), JDK_Version::undefined() }, { "DynamicDumpSharedSpaces", JDK_Version::jdk(18), JDK_Version::jdk(19), JDK_Version::undefined() }, { "RequireSharedSpaces", JDK_Version::jdk(18), JDK_Version::jdk(19), JDK_Version::undefined() }, @@ -547,6 +546,7 @@ static SpecialFlag const special_jvm_flags[] = { // -------------- Obsolete Flags - sorted by expired_in -------------- { "FilterSpuriousWakeups", JDK_Version::jdk(18), JDK_Version::jdk(19), JDK_Version::jdk(20) }, + { "MinInliningThreshold", JDK_Version::jdk(18), JDK_Version::jdk(19), JDK_Version::jdk(20) }, #ifdef ASSERT { "DummyObsoleteTestFlag", JDK_Version::undefined(), JDK_Version::jdk(18), JDK_Version::undefined() }, #endif diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index e6ccef47a82..12df1142ee3 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -1346,11 +1346,6 @@ const intx ObjectAlignmentInBytes = 8; "(using CompileCommand or marked w/ @ForceInline)") \ range(0, max_jint) \ \ - product(intx, MinInliningThreshold, 0, \ - "(Deprecated) The minimum invocation count a method needs to" \ - "have to be inlined") \ - range(0, max_jint) \ - \ develop(intx, MethodHistogramCutoff, 100, \ "The cutoff value for method invocation histogram (+CountCalls)") \ \ -- GitLab From 3121898c33fa3cc5a049977f8677105a84c3e50c Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Tue, 11 Jan 2022 08:39:54 +0000 Subject: [PATCH 062/564] 8279703: G1: Remove unused force_not_compacted local in G1CalculatePointersClosure::do_heap_region Reviewed-by: ayang, mli --- src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp b/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp index ea7f94880c4..883e0a51f86 100644 --- a/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp +++ b/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp @@ -52,7 +52,6 @@ void G1FullGCPrepareTask::G1CalculatePointersClosure::free_pinned_region(HeapReg } bool G1FullGCPrepareTask::G1CalculatePointersClosure::do_heap_region(HeapRegion* hr) { - bool force_not_compacted = false; if (should_compact(hr)) { assert(!hr->is_humongous(), "moving humongous objects not supported."); prepare_for_compaction(hr); -- GitLab From 86d0abb66bd2fe1edd15b81d351ea3b3c90fd256 Mon Sep 17 00:00:00 2001 From: Fairoz Matte Date: Tue, 11 Jan 2022 09:39:39 +0000 Subject: [PATCH 063/564] 8279695: [TESTBUG] modify compiler/loopopts/TestSkeletonPredicateNegation.java to run on C1 also Reviewed-by: neliasso --- .../compiler/loopopts/TestSkeletonPredicateNegation.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/test/hotspot/jtreg/compiler/loopopts/TestSkeletonPredicateNegation.java b/test/hotspot/jtreg/compiler/loopopts/TestSkeletonPredicateNegation.java index e7fb0be85ea..75950300584 100644 --- a/test/hotspot/jtreg/compiler/loopopts/TestSkeletonPredicateNegation.java +++ b/test/hotspot/jtreg/compiler/loopopts/TestSkeletonPredicateNegation.java @@ -1,6 +1,6 @@ /* * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,6 @@ /** * @test - * @requires vm.compiler2.enabled * @bug 8273277 * @summary Skeleton predicates sometimes need to be negated * @run main compiler.loopopts.TestSkeletonPredicateNegation @@ -50,11 +49,11 @@ public class TestSkeletonPredicateNegation { } public void mainTest (String[] args){ - long loa11[] = new long[1987]; + long loa11[] = new long[19]; for (long lo14 : loa11) { TestSkeletonPredicateNegation.in0 = -128; - for (int i18 = 0; i18 < 52; i18++) { + for (int i18 = 0; i18 < 13; i18++) { try { loa11[TestSkeletonPredicateNegation.in0] %= 2275269548L; Math.ceil(1374905370.2785515599); -- GitLab From 2bbeae3f056243a224b0bda021f16cdcbee3b3d6 Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Tue, 11 Jan 2022 10:28:47 +0000 Subject: [PATCH 064/564] 8279668: x86: AVX2 versions of vpxor should be asserted Reviewed-by: kvn, jiefu --- src/hotspot/cpu/x86/assembler_x86.cpp | 6 ++++++ src/hotspot/cpu/x86/macroAssembler_x86.hpp | 12 +++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/hotspot/cpu/x86/assembler_x86.cpp b/src/hotspot/cpu/x86/assembler_x86.cpp index d0753f0de11..fc7b55f5d98 100644 --- a/src/hotspot/cpu/x86/assembler_x86.cpp +++ b/src/hotspot/cpu/x86/assembler_x86.cpp @@ -7594,6 +7594,9 @@ void Assembler::pxor(XMMRegister dst, XMMRegister src) { void Assembler::vpxor(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { assert(UseAVX > 0, "requires some form of AVX"); + assert(vector_len == AVX_128bit ? VM_Version::supports_avx() : + vector_len == AVX_256bit ? VM_Version::supports_avx2() : + vector_len == AVX_512bit ? VM_Version::supports_evex() : 0, ""); InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F, &attributes); emit_int16((unsigned char)0xEF, (0xC0 | encode)); @@ -7601,6 +7604,9 @@ void Assembler::vpxor(XMMRegister dst, XMMRegister nds, XMMRegister src, int vec void Assembler::vpxor(XMMRegister dst, XMMRegister nds, Address src, int vector_len) { assert(UseAVX > 0, "requires some form of AVX"); + assert(vector_len == AVX_128bit ? VM_Version::supports_avx() : + vector_len == AVX_256bit ? VM_Version::supports_avx2() : + vector_len == AVX_512bit ? VM_Version::supports_evex() : 0, ""); InstructionMark im(this); InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); attributes.set_address_attributes(/* tuple_type */ EVEX_FV, /* input_size_in_bits */ EVEX_32bit); diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.hpp b/src/hotspot/cpu/x86/macroAssembler_x86.hpp index 5c101b49687..6a7e714be7f 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -1489,8 +1489,14 @@ public: void vpxor(XMMRegister dst, XMMRegister nds, AddressLiteral src, int vector_len, Register scratch_reg = rscratch1); // Simple version for AVX2 256bit vectors - void vpxor(XMMRegister dst, XMMRegister src) { Assembler::vpxor(dst, dst, src, true); } - void vpxor(XMMRegister dst, Address src) { Assembler::vpxor(dst, dst, src, true); } + void vpxor(XMMRegister dst, XMMRegister src) { + assert(UseAVX >= 2, "Should be at least AVX2"); + Assembler::vpxor(dst, dst, src, AVX_256bit); + } + void vpxor(XMMRegister dst, Address src) { + assert(UseAVX >= 2, "Should be at least AVX2"); + Assembler::vpxor(dst, dst, src, AVX_256bit); + } void vpermd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { Assembler::vpermd(dst, nds, src, vector_len); } void vpermd(XMMRegister dst, XMMRegister nds, AddressLiteral src, int vector_len, Register scratch_reg); -- GitLab From d46410c553293a91405d0f2757b0ac3bbbb157a5 Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Tue, 11 Jan 2022 13:04:20 +0000 Subject: [PATCH 065/564] 8279785: JFR: 'jfr configure' should show default values Reviewed-by: mgronlun --- .../classes/jdk/jfr/internal/jfc/model/XmlFlag.java | 2 +- .../jdk/jfr/internal/jfc/model/XmlSelection.java | 10 +++++++++- .../classes/jdk/jfr/internal/jfc/model/XmlText.java | 8 ++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/model/XmlFlag.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/model/XmlFlag.java index d494d3eb57d..8e3431bc5a3 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/model/XmlFlag.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/model/XmlFlag.java @@ -29,7 +29,7 @@ final class XmlFlag extends XmlInput { @Override public String getOptionSyntax() { - return getName() + "="; + return getName() + "=" + " (" + getContent() + ")"; } @Override diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/model/XmlSelection.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/model/XmlSelection.java index d3bf2240479..c451119fb1a 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/model/XmlSelection.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/model/XmlSelection.java @@ -36,7 +36,15 @@ final class XmlSelection extends XmlInput { for (XmlOption option : getOptions()) { sj.add(option.getName()); } - return getName() + "=" + sj.toString(); + StringBuilder sb = new StringBuilder(); + sb.append(getName()); + sb.append("="); + sb.append(sj.toString()); + XmlOption selected = getSelected(); + if (selected != null) { + sb.append(" (").append(selected.getName()).append(")"); + } + return sb.toString(); } @Override diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/model/XmlText.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/model/XmlText.java index 789243d2d5f..4d90dd3c51c 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/model/XmlText.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/model/XmlText.java @@ -34,6 +34,14 @@ final class XmlText extends XmlInput { sb.append("=<"); sb.append(getContentType().orElse("text")); sb.append(">"); + sb.append(" ("); + String content = getContent(); + if (isTimespan()) { + // "20 ms" becomes "20ms" + content = content.replaceAll("\\s", ""); + } + sb.append(content); + sb.append(")"); return sb.toString(); } -- GitLab From 4c52eb39431c2479b0d140907bdcc0311d30f871 Mon Sep 17 00:00:00 2001 From: Zdenek Zambersky Date: Tue, 11 Jan 2022 13:14:48 +0000 Subject: [PATCH 066/564] 8279669: test/jdk/com/sun/jdi/TestScaffold.java uses wrong condition Reviewed-by: amenkov, sspitsyn --- test/jdk/com/sun/jdi/TestScaffold.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/test/jdk/com/sun/jdi/TestScaffold.java b/test/jdk/com/sun/jdi/TestScaffold.java index 18da0b4e9c7..2d4885c90e7 100644 --- a/test/jdk/com/sun/jdi/TestScaffold.java +++ b/test/jdk/com/sun/jdi/TestScaffold.java @@ -535,16 +535,15 @@ abstract public class TestScaffold extends TargetAdapter { Location loc = ((Locatable)event).location(); ReferenceType rt = loc.declaringType(); String name = rt.name(); - if (name.startsWith("java.") && - !name.startsWith("sun.") && - !name.startsWith("com.")) { + if (name.startsWith("java.") + || name.startsWith("sun.") + || name.startsWith("com.") + || name.startsWith("jdk.")) { if (mainStartClass != null) { redefine(mainStartClass); } } else { - if (!name.startsWith("jdk.")) { - redefine(rt); - } + redefine(rt); } } } -- GitLab From c08b2ac34c436f07f7d43f25ce16c94a137597f5 Mon Sep 17 00:00:00 2001 From: Harold Seigel Date: Tue, 11 Jan 2022 13:43:13 +0000 Subject: [PATCH 067/564] 8225093: Special property jdk.boot.class.path.append should not default to empty string Reviewed-by: dholmes, sspitsyn, alanb --- src/hotspot/share/runtime/arguments.cpp | 2 +- src/hotspot/share/runtime/arguments.hpp | 3 +- .../GetBootClassPathAppendProp.java | 53 ++++++++++++++++ .../libGetBootClassPathAppendProp.c | 62 +++++++++++++++++++ 4 files changed, 118 insertions(+), 2 deletions(-) create mode 100644 test/hotspot/jtreg/runtime/BootClassAppendProp/GetBootClassPathAppendProp.java create mode 100644 test/hotspot/jtreg/runtime/BootClassAppendProp/libGetBootClassPathAppendProp.c diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index f6983ba5019..addff98a3ea 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -412,7 +412,7 @@ void Arguments::init_system_properties() { // It can only be set by either: // - -Xbootclasspath/a: // - AddToBootstrapClassLoaderSearch during JVMTI OnLoad phase - _jdk_boot_class_path_append = new SystemProperty("jdk.boot.class.path.append", "", false, true); + _jdk_boot_class_path_append = new SystemProperty("jdk.boot.class.path.append", NULL, false, true); // Add to System Property list. PropertyList_add(&_system_properties, _sun_boot_library_path); diff --git a/src/hotspot/share/runtime/arguments.hpp b/src/hotspot/share/runtime/arguments.hpp index 40b9308c82b..7b03205cb08 100644 --- a/src/hotspot/share/runtime/arguments.hpp +++ b/src/hotspot/share/runtime/arguments.hpp @@ -109,7 +109,8 @@ class SystemProperty : public PathString { void set_next(SystemProperty* next) { _next = next; } bool is_readable() const { - return !_internal || strcmp(_key, "jdk.boot.class.path.append") == 0; + return !_internal || (strcmp(_key, "jdk.boot.class.path.append") == 0 && + value() != NULL); } // A system property should only have its value set diff --git a/test/hotspot/jtreg/runtime/BootClassAppendProp/GetBootClassPathAppendProp.java b/test/hotspot/jtreg/runtime/BootClassAppendProp/GetBootClassPathAppendProp.java new file mode 100644 index 00000000000..59d62e5615b --- /dev/null +++ b/test/hotspot/jtreg/runtime/BootClassAppendProp/GetBootClassPathAppendProp.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2021, 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 8225093 + * @summary Check that JVMTI GetSystemProperty API returns the right values for + * property jdk.boot.class.path.append. + * @requires vm.jvmti + * @library /test/lib + * @run main/othervm/native -agentlib:GetBootClassPathAppendProp GetBootClassPathAppendProp + * @run main/othervm/native -Xbootclasspath/a:blah -agentlib:GetBootClassPathAppendProp GetBootClassPathAppendProp one_arg + * + */ + +public class GetBootClassPathAppendProp { + private static native String getSystemProperty(); + + public static void main(String[] args) throws Exception { + String path = getSystemProperty(); + if (args.length > 0) { + if (!path.equals("blah")) { + throw new RuntimeException("Wrong value returned for jdk.boot.class.path.append: " + + path); + } + } else { + if (path != null) { + throw new RuntimeException("Null value expected for jdk.boot.class.path.append: " + + path); + } + } + } +} diff --git a/test/hotspot/jtreg/runtime/BootClassAppendProp/libGetBootClassPathAppendProp.c b/test/hotspot/jtreg/runtime/BootClassAppendProp/libGetBootClassPathAppendProp.c new file mode 100644 index 00000000000..07f57cff267 --- /dev/null +++ b/test/hotspot/jtreg/runtime/BootClassAppendProp/libGetBootClassPathAppendProp.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +static jvmtiEnv *jvmti = NULL; + +JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) { + int err = (*jvm)->GetEnv(jvm, (void**) &jvmti, JVMTI_VERSION_9); + if (err != JNI_OK) { + return JNI_ERR; + } + return JNI_OK; +} + +JNIEXPORT jstring JNICALL +Java_GetBootClassPathAppendProp_getSystemProperty(JNIEnv *env, jclass cls) { + jvmtiError err; + char* prop_value; + + err = (*jvmti)->GetSystemProperty(jvmti, "jdk.boot.class.path.append", &prop_value); + if (err == JVMTI_ERROR_NOT_AVAILABLE) { + return NULL; + } + if (err != JVMTI_ERROR_NONE) { + char err_msg[50]; + snprintf(err_msg, 50, "Wrong JVM TI error code: %d", err); + return (*env)->NewStringUTF(env, err_msg); + } + + return (*env)->NewStringUTF(env, prop_value); +} + +#ifdef __cplusplus +} +#endif -- GitLab From 08e14c605e7ecf555feddda59ae842e2af2035ba Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Tue, 11 Jan 2022 14:04:52 +0000 Subject: [PATCH 068/564] 8278207: G1: Tighten verification in G1ResetSkipCompactingClosure Reviewed-by: tschatzl, sjohanss --- .../share/gc/g1/g1FullGCCompactTask.cpp | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1FullGCCompactTask.cpp b/src/hotspot/share/gc/g1/g1FullGCCompactTask.cpp index 054227c214a..f484ee5133c 100644 --- a/src/hotspot/share/gc/g1/g1FullGCCompactTask.cpp +++ b/src/hotspot/share/gc/g1/g1FullGCCompactTask.cpp @@ -46,13 +46,23 @@ public: uint region_index = r->hrm_index(); // Only for skip-compaction regions; early return otherwise. if (!_collector->is_skip_compacting(region_index)) { - return false; } - assert(_collector->live_words(region_index) > _collector->scope()->region_compaction_threshold() || - !r->is_starts_humongous() || - _collector->mark_bitmap()->is_marked(cast_to_oop(r->bottom())), - "must be, otherwise reclaimed earlier"); +#ifdef ASSERT + if (r->is_humongous()) { + oop obj = cast_to_oop(r->humongous_start_region()->bottom()); + assert(_collector->mark_bitmap()->is_marked(obj), "must be live"); + } else if (r->is_open_archive()) { + bool is_empty = (_collector->live_words(r->hrm_index()) == 0); + assert(!is_empty, "should contain at least one live obj"); + } else if (r->is_closed_archive()) { + // should early-return above + ShouldNotReachHere(); + } else { + assert(_collector->live_words(region_index) > _collector->scope()->region_compaction_threshold(), + "should be quite full"); + } +#endif r->reset_skip_compacting_after_full_gc(); return false; } -- GitLab From 9e0244762c0961b1bb3453d294531997b367e757 Mon Sep 17 00:00:00 2001 From: Andrew Leonard Date: Tue, 11 Jan 2022 14:21:31 +0000 Subject: [PATCH 069/564] 8279834: Alpine Linux fails to build when --with-source-date enabled Reviewed-by: erikj --- make/autoconf/basic_tools.m4 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/make/autoconf/basic_tools.m4 b/make/autoconf/basic_tools.m4 index c87c26fe10b..9ce90303d45 100644 --- a/make/autoconf/basic_tools.m4 +++ b/make/autoconf/basic_tools.m4 @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2022, 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 @@ -356,9 +356,9 @@ AC_DEFUN_ONCE([BASIC_SETUP_COMPLEX_TOOLS], fi AC_SUBST(IS_GNU_TIME) - # Check if it's GNU date - AC_MSG_CHECKING([if date is the GNU version]) - check_date=`$DATE --version 2>&1 | $GREP GNU` + # Check if it's a GNU date compatible version + AC_MSG_CHECKING([if date is a GNU compatible version]) + check_date=`$DATE --version 2>&1 | $GREP "GNU\|BusyBox"` if test "x$check_date" != x; then AC_MSG_RESULT([yes]) IS_GNU_DATE=yes -- GitLab From 5aecb37211c2dec475c56dcc354b6bb4f7e3585e Mon Sep 17 00:00:00 2001 From: Pavel Rappo Date: Tue, 11 Jan 2022 14:28:03 +0000 Subject: [PATCH 070/564] 8206181: ExceptionInInitializerError: improve handling of exceptions in user-provided taglets Reviewed-by: jjg --- .../toolkit/taglets/TagletManager.java | 23 +++-- .../ClassCastExceptionTaglet.java | 50 +++++++++++ .../ExceptionInInitializerErrorTaglet.java | 60 +++++++++++++ .../InstantiationExceptionTaglet.java | 54 ++++++++++++ .../InvocationTargetExceptionTaglet.java | 58 +++++++++++++ ...uchMethodExceptionNoNullaryCtorTaglet.java | 56 ++++++++++++ ...oSuchMethodExceptionPrivateCtorTaglet.java | 56 ++++++++++++ .../TestRegistrationErrors.java | 86 +++++++++++++++++++ 8 files changed, 431 insertions(+), 12 deletions(-) create mode 100644 test/langtools/jdk/javadoc/doclet/testCustomTagletRegistration/ClassCastExceptionTaglet.java create mode 100644 test/langtools/jdk/javadoc/doclet/testCustomTagletRegistration/ExceptionInInitializerErrorTaglet.java create mode 100644 test/langtools/jdk/javadoc/doclet/testCustomTagletRegistration/InstantiationExceptionTaglet.java create mode 100644 test/langtools/jdk/javadoc/doclet/testCustomTagletRegistration/InvocationTargetExceptionTaglet.java create mode 100644 test/langtools/jdk/javadoc/doclet/testCustomTagletRegistration/NoSuchMethodExceptionNoNullaryCtorTaglet.java create mode 100644 test/langtools/jdk/javadoc/doclet/testCustomTagletRegistration/NoSuchMethodExceptionPrivateCtorTaglet.java create mode 100644 test/langtools/jdk/javadoc/doclet/testCustomTagletRegistration/TestRegistrationErrors.java diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/TagletManager.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/TagletManager.java index 19928eee306..134d5427634 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/TagletManager.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/TagletManager.java @@ -250,23 +250,22 @@ public class TagletManager { * @param fileManager the file manager to load classes and resources */ public void addCustomTag(String classname, JavaFileManager fileManager) { + ClassLoader tagClassLoader = fileManager.getClassLoader(TAGLET_PATH); + if (configuration.workArounds.accessInternalAPI()) { + Module thisModule = getClass().getModule(); + Module tagletLoaderUnnamedModule = tagClassLoader.getUnnamedModule(); + List pkgs = List.of( + "jdk.javadoc.doclet", + "jdk.javadoc.internal.doclets.toolkit", + "jdk.javadoc.internal.doclets.formats.html"); + pkgs.forEach(p -> thisModule.addOpens(p, tagletLoaderUnnamedModule)); + } try { - ClassLoader tagClassLoader; - tagClassLoader = fileManager.getClassLoader(TAGLET_PATH); - if (configuration.workArounds.accessInternalAPI()) { - Module thisModule = getClass().getModule(); - Module tagletLoaderUnnamedModule = tagClassLoader.getUnnamedModule(); - List pkgs = List.of( - "jdk.javadoc.doclet", - "jdk.javadoc.internal.doclets.toolkit", - "jdk.javadoc.internal.doclets.formats.html"); - pkgs.forEach(p -> thisModule.addOpens(p, tagletLoaderUnnamedModule)); - } Class customTagClass = tagClassLoader.loadClass(classname).asSubclass(jdk.javadoc.doclet.Taglet.class); jdk.javadoc.doclet.Taglet instance = customTagClass.getConstructor().newInstance(); registerTaglet(instance); - } catch (ReflectiveOperationException exc) { + } catch (ReflectiveOperationException | ExceptionInInitializerError | ClassCastException exc) { messages.error("doclet.Error_taglet_not_registered", exc.getClass().getName(), classname); } diff --git a/test/langtools/jdk/javadoc/doclet/testCustomTagletRegistration/ClassCastExceptionTaglet.java b/test/langtools/jdk/javadoc/doclet/testCustomTagletRegistration/ClassCastExceptionTaglet.java new file mode 100644 index 00000000000..3d6cd7392c9 --- /dev/null +++ b/test/langtools/jdk/javadoc/doclet/testCustomTagletRegistration/ClassCastExceptionTaglet.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.EnumSet; +import java.util.List; +import java.util.Set; + +import javax.lang.model.element.Element; + +import com.sun.source.doctree.DocTree; +import jdk.javadoc.doclet.Taglet; + +public class ClassCastExceptionTaglet /* does NOT implement jdk.javadoc.doclet.Taglet */ { + + public Set getAllowedLocations() { + return EnumSet.allOf(Taglet.Location.class); + } + + public boolean isInlineTag() { + return false; + } + + public String getName() { + return "ClassCastExceptionTaglet"; + } + + public String toString(List tags, Element element) { + return ""; + } +} diff --git a/test/langtools/jdk/javadoc/doclet/testCustomTagletRegistration/ExceptionInInitializerErrorTaglet.java b/test/langtools/jdk/javadoc/doclet/testCustomTagletRegistration/ExceptionInInitializerErrorTaglet.java new file mode 100644 index 00000000000..22bd088bbe6 --- /dev/null +++ b/test/langtools/jdk/javadoc/doclet/testCustomTagletRegistration/ExceptionInInitializerErrorTaglet.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.EnumSet; +import java.util.List; +import java.util.Set; + +import javax.lang.model.element.Element; + +import com.sun.source.doctree.DocTree; +import jdk.javadoc.doclet.Taglet; + +public class ExceptionInInitializerErrorTaglet implements Taglet { + + static { + if (true) { + throw new RuntimeException(); + } + } + + @Override + public Set getAllowedLocations() { + return EnumSet.allOf(Taglet.Location.class); + } + + @Override + public boolean isInlineTag() { + return false; + } + + @Override + public String getName() { + return "ExceptionInInitializerErrorTaglet"; + } + + @Override + public String toString(List tags, Element element) { + return ""; + } +} diff --git a/test/langtools/jdk/javadoc/doclet/testCustomTagletRegistration/InstantiationExceptionTaglet.java b/test/langtools/jdk/javadoc/doclet/testCustomTagletRegistration/InstantiationExceptionTaglet.java new file mode 100644 index 00000000000..b3995a03399 --- /dev/null +++ b/test/langtools/jdk/javadoc/doclet/testCustomTagletRegistration/InstantiationExceptionTaglet.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.EnumSet; +import java.util.List; +import java.util.Set; + +import javax.lang.model.element.Element; + +import com.sun.source.doctree.DocTree; +import jdk.javadoc.doclet.Taglet; + +public abstract class InstantiationExceptionTaglet implements Taglet { + + @Override + public Set getAllowedLocations() { + return EnumSet.allOf(Taglet.Location.class); + } + + @Override + public boolean isInlineTag() { + return false; + } + + @Override + public String getName() { + return "InstantiationExceptionTaglet"; + } + + @Override + public String toString(List tags, Element element) { + return ""; + } +} diff --git a/test/langtools/jdk/javadoc/doclet/testCustomTagletRegistration/InvocationTargetExceptionTaglet.java b/test/langtools/jdk/javadoc/doclet/testCustomTagletRegistration/InvocationTargetExceptionTaglet.java new file mode 100644 index 00000000000..37faf0f2ab6 --- /dev/null +++ b/test/langtools/jdk/javadoc/doclet/testCustomTagletRegistration/InvocationTargetExceptionTaglet.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.EnumSet; +import java.util.List; +import java.util.Set; + +import javax.lang.model.element.Element; + +import com.sun.source.doctree.DocTree; +import jdk.javadoc.doclet.Taglet; + +public class InvocationTargetExceptionTaglet implements Taglet { + + public InvocationTargetExceptionTaglet() { + throw new RuntimeException(); + } + + @Override + public Set getAllowedLocations() { + return EnumSet.allOf(Location.class); + } + + @Override + public boolean isInlineTag() { + return false; + } + + @Override + public String getName() { + return "InvocationTargetExceptionTaglet"; + } + + @Override + public String toString(List tags, Element element) { + return ""; + } +} diff --git a/test/langtools/jdk/javadoc/doclet/testCustomTagletRegistration/NoSuchMethodExceptionNoNullaryCtorTaglet.java b/test/langtools/jdk/javadoc/doclet/testCustomTagletRegistration/NoSuchMethodExceptionNoNullaryCtorTaglet.java new file mode 100644 index 00000000000..5f18ed460c0 --- /dev/null +++ b/test/langtools/jdk/javadoc/doclet/testCustomTagletRegistration/NoSuchMethodExceptionNoNullaryCtorTaglet.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.EnumSet; +import java.util.List; +import java.util.Set; + +import javax.lang.model.element.Element; + +import com.sun.source.doctree.DocTree; +import jdk.javadoc.doclet.Taglet; + +public class NoSuchMethodExceptionNoNullaryCtorTaglet implements Taglet { + + public NoSuchMethodExceptionNoNullaryCtorTaglet(Object obj) {} + + @Override + public Set getAllowedLocations() { + return EnumSet.allOf(Taglet.Location.class); + } + + @Override + public boolean isInlineTag() { + return false; + } + + @Override + public String getName() { + return "NoSuchMethodExceptionNoNullaryCtorTaglet"; + } + + @Override + public String toString(List tags, Element element) { + return ""; + } +} diff --git a/test/langtools/jdk/javadoc/doclet/testCustomTagletRegistration/NoSuchMethodExceptionPrivateCtorTaglet.java b/test/langtools/jdk/javadoc/doclet/testCustomTagletRegistration/NoSuchMethodExceptionPrivateCtorTaglet.java new file mode 100644 index 00000000000..cbf71d6021e --- /dev/null +++ b/test/langtools/jdk/javadoc/doclet/testCustomTagletRegistration/NoSuchMethodExceptionPrivateCtorTaglet.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.EnumSet; +import java.util.List; +import java.util.Set; + +import javax.lang.model.element.Element; + +import com.sun.source.doctree.DocTree; +import jdk.javadoc.doclet.Taglet; + +public class NoSuchMethodExceptionPrivateCtorTaglet implements Taglet { + + private NoSuchMethodExceptionPrivateCtorTaglet() {} + + @Override + public Set getAllowedLocations() { + return EnumSet.allOf(Taglet.Location.class); + } + + @Override + public boolean isInlineTag() { + return false; + } + + @Override + public String getName() { + return "NoSuchMethodExceptionPrivateCtorTaglet"; + } + + @Override + public String toString(List tags, Element element) { + return ""; + } +} diff --git a/test/langtools/jdk/javadoc/doclet/testCustomTagletRegistration/TestRegistrationErrors.java b/test/langtools/jdk/javadoc/doclet/testCustomTagletRegistration/TestRegistrationErrors.java new file mode 100644 index 00000000000..8d2d95d6a63 --- /dev/null +++ b/test/langtools/jdk/javadoc/doclet/testCustomTagletRegistration/TestRegistrationErrors.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2021, 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 8206181 + * @library ../../lib + * @modules jdk.javadoc/jdk.javadoc.internal.tool + * @build javadoc.tester.* * + * @run main TestRegistrationErrors + */ + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Stream; + +import javadoc.tester.JavadocTester; + +public class TestRegistrationErrors extends JavadocTester { + + public static void main(String... args) throws Exception { + TestRegistrationErrors tester = new TestRegistrationErrors(); + tester.runTests(); + } + + @Test + public void test() throws Exception { + try (Stream tagletClasses = findTagletClasses()) { + tagletClasses.forEach(p -> { + String tagletName = getTagletName(p); + javadoc("-d", "out-" + tagletName, // a directory per taglet + "-tagletpath", System.getProperty("test.classes"), + "-taglet", tagletName, + testSrc("TestRegistrationErrors.java")); // specify this file + checkExit(Exit.ERROR); + new OutputChecker(Output.OUT).checkUnique(Pattern.compile("thrown while trying to register Taglet")); + checkNoCrashes(); + }); + } + } + + private static Stream findTagletClasses() throws IOException { + var path = Path.of(System.getProperty("test.classes")); + return Files.find(path, Integer.MAX_VALUE, + (p, a) -> a.isRegularFile() && p.toString().endsWith("Taglet.class")); + } + + private static String getTagletName(Path tagletClass) { + Path fileName = tagletClass.getFileName(); + return fileName.toString().substring(0, fileName.toString().lastIndexOf('.')); + } + + protected void checkNoCrashes() { + checking("check crashes"); + Matcher matcher = Pattern.compile("\\s*at.*\\(.*\\.java:\\d+\\)") + .matcher(getOutput(Output.STDERR)); + if (!matcher.find()) { + passed(""); + } else { + failed("Looks like a stacktrace: " + matcher.group()); + } + } +} -- GitLab From c3d0a94040d9bd0f4b99da97b89fbfce252a41c0 Mon Sep 17 00:00:00 2001 From: Claes Redestad Date: Tue, 11 Jan 2022 14:49:03 +0000 Subject: [PATCH 071/564] 8279833: Loop optimization issue in String.encodeUTF8_UTF16 Reviewed-by: shade, alanb --- .../share/classes/java/lang/String.java | 11 +- .../openjdk/bench/java/lang/StringEncode.java | 116 ++++++++++++------ 2 files changed, 84 insertions(+), 43 deletions(-) diff --git a/src/java.base/share/classes/java/lang/String.java b/src/java.base/share/classes/java/lang/String.java index abb35ebaeb1..756b8efacda 100644 --- a/src/java.base/share/classes/java/lang/String.java +++ b/src/java.base/share/classes/java/lang/String.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2022, 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 @@ -1284,14 +1284,17 @@ public final class String int sp = 0; int sl = val.length >> 1; byte[] dst = new byte[sl * 3]; - char c; - while (sp < sl && (c = StringUTF16.getChar(val, sp)) < '\u0080') { + while (sp < sl) { // ascii fast loop; + char c = StringUTF16.getChar(val, sp); + if (c >= '\u0080') { + break; + } dst[dp++] = (byte)c; sp++; } while (sp < sl) { - c = StringUTF16.getChar(val, sp++); + char c = StringUTF16.getChar(val, sp++); if (c < 0x80) { dst[dp++] = (byte)c; } else if (c < 0x800) { diff --git a/test/micro/org/openjdk/bench/java/lang/StringEncode.java b/test/micro/org/openjdk/bench/java/lang/StringEncode.java index 4cf5032a0da..6e67d3e8cee 100644 --- a/test/micro/org/openjdk/bench/java/lang/StringEncode.java +++ b/test/micro/org/openjdk/bench/java/lang/StringEncode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,59 +30,97 @@ import java.util.concurrent.TimeUnit; @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.NANOSECONDS) -@Fork(value = 3, jvmArgs = "-Xmx1g") +@Fork(value = 3) @Warmup(iterations = 5, time = 2) @Measurement(iterations = 5, time = 3) @State(Scope.Thread) public class StringEncode { - @BenchmarkMode(Mode.AverageTime) - @OutputTimeUnit(TimeUnit.NANOSECONDS) - @Fork(value = 3, jvmArgs = "-Xmx1g") - @Warmup(iterations = 5, time = 2) - @Measurement(iterations = 5, time = 2) - @State(Scope.Thread) - public static class WithCharset { + @Param({"US-ASCII", "ISO-8859-1", "UTF-8", "MS932", "ISO-8859-6"}) + private String charsetName; + private Charset charset; + private String asciiString; + private String utf16String; + private String longUtf16String; + private String longUtf16StartString; - @Param({"US-ASCII", "ISO-8859-1", "UTF-8", "MS932", "ISO-8859-6"}) - private String charsetName; + @Setup + public void setup() { + charset = Charset.forName(charsetName); + asciiString = "ascii string"; + utf16String = "UTF-\uFF11\uFF16 string"; + longUtf16String = """ + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam ac sem eu + urna egestas placerat. Etiam finibus ipsum nulla, non mattis dolor cursus a. + Nulla nec nisl consectetur, lacinia neque id, accumsan ante. Curabitur et + sapien in magna porta ultricies. Sed vel pellentesque nibh. Pellentesque dictum + dignissim diam eu ultricies. Class aptent taciti sociosqu ad litora torquent + per conubia nostra, per inceptos himenaeos. Suspendisse erat diam, fringilla + sed massa sed, posuere viverra orci. Suspendisse tempor libero non gravida + efficitur. Vivamus lacinia risus non orci viverra, at consectetur odio laoreet. + Suspendisse potenti. - private Charset charset; - private String asciiString; - private String utf16String; + Phasellus vel nisi iaculis, accumsan quam sed, bibendum eros. Sed venenatis + nulla tortor, et eleifend urna sodales id. Nullam tempus ac metus sit amet + sollicitudin. Nam sed ex diam. Praesent vitae eros et neque condimentum + consectetur eget non tortor. Praesent bibendum vel felis nec dignissim. + Maecenas a enim diam. Suspendisse quis ligula at nisi accumsan lacinia id + hendrerit sapien. Donec aliquam mattis lectus eu ultrices. Duis eu nisl + euismod, blandit mauris vel, placerat urna. Etiam malesuada enim purus, + tristique mollis odio blandit quis. Vivamus posuere. + \uFF11 + """; + longUtf16StartString = """ + \uFF11 + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam ac sem eu + urna egestas placerat. Etiam finibus ipsum nulla, non mattis dolor cursus a. + Nulla nec nisl consectetur, lacinia neque id, accumsan ante. Curabitur et + sapien in magna porta ultricies. Sed vel pellentesque nibh. Pellentesque dictum + dignissim diam eu ultricies. Class aptent taciti sociosqu ad litora torquent + per conubia nostra, per inceptos himenaeos. Suspendisse erat diam, fringilla + sed massa sed, posuere viverra orci. Suspendisse tempor libero non gravida + efficitur. Vivamus lacinia risus non orci viverra, at consectetur odio laoreet. + Suspendisse potenti. - @Setup - public void setup() { - charset = Charset.forName(charsetName); - asciiString = "ascii string"; - utf16String = "UTF-\uFF11\uFF16 string"; - } + Phasellus vel nisi iaculis, accumsan quam sed, bibendum eros. Sed venenatis + nulla tortor, et eleifend urna sodales id. Nullam tempus ac metus sit amet + sollicitudin. Nam sed ex diam. Praesent vitae eros et neque condimentum + consectetur eget non tortor. Praesent bibendum vel felis nec dignissim. + Maecenas a enim diam. Suspendisse quis ligula at nisi accumsan lacinia id + hendrerit sapien. Donec aliquam mattis lectus eu ultrices. Duis eu nisl + euismod, blandit mauris vel, placerat urna. Etiam malesuada enim purus, + tristique mollis odio blandit quis. Vivamus posuere. + """; + } - @Benchmark - public void encodeCharsetName(Blackhole bh) throws Exception { - bh.consume(asciiString.getBytes(charsetName)); - bh.consume(utf16String.getBytes(charsetName)); - } + @Benchmark + public byte[] encodeAsciiCharsetName() throws Exception { + return asciiString.getBytes(charset); + } + + @Benchmark + public byte[] encodeAscii() throws Exception { + return asciiString.getBytes(charset); + } - @Benchmark - public void encodeCharset(Blackhole bh) throws Exception { - bh.consume(asciiString.getBytes(charset)); - bh.consume(utf16String.getBytes(charset)); - } + @Benchmark + public void encodeMix(Blackhole bh) throws Exception { + bh.consume(asciiString.getBytes(charset)); + bh.consume(utf16String.getBytes(charset)); } - private String asciiDefaultString; - private String utf16DefaultString; + @Benchmark + public byte[] encodeUTF16LongEnd() throws Exception { + return longUtf16String.getBytes(charset); + } - @Setup - public void setup() { - asciiDefaultString = "ascii string"; - utf16DefaultString = "UTF-\uFF11\uFF16 string"; + @Benchmark + public byte[] encodeUTF16LongStart() throws Exception { + return longUtf16StartString.getBytes(charset); } @Benchmark - public void encodeDefault(Blackhole bh) throws Exception { - bh.consume(asciiDefaultString.getBytes()); - bh.consume(utf16DefaultString.getBytes()); + public byte[] encodeUTF16() throws Exception { + return utf16String.getBytes(charset); } } -- GitLab From cfee4512f7048e9cf440078e9eb87d37c7ebcdd9 Mon Sep 17 00:00:00 2001 From: Liam Miller-Cushon Date: Tue, 11 Jan 2022 15:45:15 +0000 Subject: [PATCH 072/564] 8273914: Indy string concat changes order of operations Reviewed-by: vromero, jlahoda --- .../com/sun/tools/javac/jvm/StringConcat.java | 46 ++++--- .../AccessCheck/MethodAccessReadTwice.java | 4 +- .../runtime/modules/AccessCheck/p5/c5.jasm | 76 +++++++++++ .../runtime/modules/AccessCheck/p7/c7.jasm | 113 +++++++++++++++++ .../StringAppendEvaluatesInOrder.java | 66 ++++++++++ .../StringConcat/WellKnownTypeSignatures.java | 119 ++++++++++++++++++ .../javac/StringConcat/WellKnownTypes.java | 81 ++++++++++++ .../tools/javac/StringConcat/access/Test.java | 66 +++++----- 8 files changed, 512 insertions(+), 59 deletions(-) create mode 100644 test/hotspot/jtreg/runtime/modules/AccessCheck/p5/c5.jasm create mode 100644 test/hotspot/jtreg/runtime/modules/AccessCheck/p7/c7.jasm create mode 100644 test/langtools/tools/javac/StringConcat/StringAppendEvaluatesInOrder.java create mode 100644 test/langtools/tools/javac/StringConcat/WellKnownTypeSignatures.java create mode 100644 test/langtools/tools/javac/StringConcat/WellKnownTypes.java diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/StringConcat.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/StringConcat.java index 0dddb3e5868..edb41fc2faf 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/StringConcat.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/StringConcat.java @@ -142,25 +142,6 @@ public abstract class StringConcat { return res.append(tree); } - /** - * If the type is not accessible from current context, try to figure out the - * sharpest accessible supertype. - * - * @param originalType type to sharpen - * @return sharped type - */ - Type sharpestAccessible(Type originalType) { - if (originalType.hasTag(ARRAY)) { - return types.makeArrayType(sharpestAccessible(types.elemtype(originalType))); - } - - Type type = originalType; - while (!rs.isAccessible(gen.getAttrEnv(), type.asElement())) { - type = types.supertype(type); - } - return type; - } - /** * "Legacy" bytecode flavor: emit the StringBuilder.append chains for string * concatenation. @@ -305,6 +286,14 @@ public abstract class StringConcat { return splits.toList(); } + + /** + * Returns true if the argument should be converted to a string eagerly, to preserve + * possible side-effects. + */ + protected boolean shouldConvertToStringEagerly(Type argType) { + return !types.unboxedTypeOrType(argType).isPrimitive() && argType.tsym != syms.stringType.tsym; + } } /** @@ -333,14 +322,18 @@ public abstract class StringConcat { for (JCTree arg : t) { Object constVal = arg.type.constValue(); if ("".equals(constVal)) continue; - if (arg.type == syms.botType) { - dynamicArgs.add(types.boxedClass(syms.voidType).type); - } else { - dynamicArgs.add(sharpestAccessible(arg.type)); + Type argType = arg.type; + if (argType == syms.botType) { + argType = types.boxedClass(syms.voidType).type; } if (!first || generateFirstArg) { gen.genExpr(arg, arg.type).load(); } + if (shouldConvertToStringEagerly(argType)) { + gen.callMethod(pos, syms.stringType, names.valueOf, List.of(syms.objectType), true); + argType = syms.stringType; + } + dynamicArgs.add(argType); first = false; } doCall(type, pos, dynamicArgs.toList()); @@ -439,10 +432,15 @@ public abstract class StringConcat { } else { // Ordinary arguments come through the dynamic arguments. recipe.append(TAG_ARG); - dynamicArgs.add(sharpestAccessible(arg.type)); + Type argType = arg.type; if (!first || generateFirstArg) { gen.genExpr(arg, arg.type).load(); } + if (shouldConvertToStringEagerly(argType)) { + gen.callMethod(pos, syms.stringType, names.valueOf, List.of(syms.objectType), true); + argType = syms.stringType; + } + dynamicArgs.add(argType); first = false; } } diff --git a/test/hotspot/jtreg/runtime/modules/AccessCheck/MethodAccessReadTwice.java b/test/hotspot/jtreg/runtime/modules/AccessCheck/MethodAccessReadTwice.java index 29bbe7f39b0..d6b85ced257 100644 --- a/test/hotspot/jtreg/runtime/modules/AccessCheck/MethodAccessReadTwice.java +++ b/test/hotspot/jtreg/runtime/modules/AccessCheck/MethodAccessReadTwice.java @@ -29,8 +29,8 @@ * after the module read edge is added. * @compile ModuleLibrary.java * p2/c2.java - * p5/c5.java - * p7/c7.java + * p5/c5.jasm + * p7/c7.jasm * @run main/othervm MethodAccessReadTwice */ diff --git a/test/hotspot/jtreg/runtime/modules/AccessCheck/p5/c5.jasm b/test/hotspot/jtreg/runtime/modules/AccessCheck/p5/c5.jasm new file mode 100644 index 00000000000..b1178eaab6c --- /dev/null +++ b/test/hotspot/jtreg/runtime/modules/AccessCheck/p5/c5.jasm @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2021, Google LLC. 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 input for the fix for JDK-8174954, which checks for an expected + * IllegalAccessError when the parameter type of an invokedynamic is + * inaccessible. + * + * The test assumes that given the string concatenation expression "" + param, + * javac generates an invokedynamic that uses the specific type of param. The + * fix for JDK-8273914 make javac eagerly convert param to a String before + * passing it to the invokedynamic call, which avoids the accessibility issue + * the test is trying to exercise. + * + * This jasm file contains the bytecode javac generated before the fix for + * JDK-8273914, to continue to exercise the invokedynamic behaviour that + * JDK-8174954 is testing. + */ + +package p5; + +super public class c5 + version 61:0 +{ + public Method "":"()V" + stack 1 locals 1 + { + aload_0; + invokespecial Method java/lang/Object."":"()V"; + return; + } + public Method method5:"(Lp2/c2;)V" + stack 2 locals 2 + { + getstatic Field java/lang/System.out:"Ljava/io/PrintStream;"; + aload_1; + invokedynamic InvokeDynamic REF_invokeStatic:Method java/lang/invoke/StringConcatFactory.makeConcatWithConstants:"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;":makeConcatWithConstants:"(Lp2/c2;)Ljava/lang/String;" { + String "In c5\'s method5 with param = " + }; + invokevirtual Method java/io/PrintStream.println:"(Ljava/lang/String;)V"; + return; + } + public Method methodAddReadEdge:"(Ljava/lang/Module;)V" + stack 2 locals 2 + { + ldc class c5; + invokevirtual Method java/lang/Class.getModule:"()Ljava/lang/Module;"; + aload_1; + invokevirtual Method java/lang/Module.addReads:"(Ljava/lang/Module;)Ljava/lang/Module;"; + pop; + return; + } + + public static final InnerClass Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles; + +} // end Class c5 diff --git a/test/hotspot/jtreg/runtime/modules/AccessCheck/p7/c7.jasm b/test/hotspot/jtreg/runtime/modules/AccessCheck/p7/c7.jasm new file mode 100644 index 00000000000..6ca4e6850e3 --- /dev/null +++ b/test/hotspot/jtreg/runtime/modules/AccessCheck/p7/c7.jasm @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2021, Google LLC. 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 input for the fix for JDK-8174954, which checks for an expected + * IllegalAccessError when the parameter type of an invokedynamic is + * inaccessible. + * + * The test assumes that given the string concatenation expression "" + param, + * javac generates an invokedynamic that uses the specific type of param. The + * fix for JDK-8273914 make javac eagerly convert param to a String before + * passing it to the invokedynamic call, which avoids the accessibility issue + * the test is trying to exercise. + * + * This jasm file contains the bytecode javac generated before the fix for + * JDK-8273914, to continue to exercise the invokedynamic behaviour that + * JDK-8174954 is testing. + */ + +package p7; + +super public class c7 + version 61:0 +{ + public Method "":"()V" + stack 1 locals 1 + { + aload_0; + invokespecial Method java/lang/Object."":"()V"; + return; + } + public Method method7:"(Lp2/c2;Ljava/lang/Module;)V" + stack 3 locals 4 + { + try t0; + getstatic Field java/lang/System.out:"Ljava/io/PrintStream;"; + aload_1; + invokedynamic InvokeDynamic REF_invokeStatic:Method java/lang/invoke/StringConcatFactory.makeConcatWithConstants:"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;":makeConcatWithConstants:"(Lp2/c2;)Ljava/lang/String;" { + String "In c7\'s method7 with param = " + }; + invokevirtual Method java/io/PrintStream.println:"(Ljava/lang/String;)V"; + new class java/lang/RuntimeException; + dup; + ldc String "c7 failed to throw expected IllegalAccessError"; + invokespecial Method java/lang/RuntimeException."":"(Ljava/lang/String;)V"; + athrow; + endtry t0; + catch t0 java/lang/IllegalAccessError; + stack_frame_type stack1; + stack_map class java/lang/IllegalAccessError; + astore_3; + aload_0; + aload_2; + invokevirtual Method methodAddReadEdge:"(Ljava/lang/Module;)V"; + try t1; + getstatic Field java/lang/System.out:"Ljava/io/PrintStream;"; + aload_1; + invokedynamic InvokeDynamic REF_invokeStatic:Method java/lang/invoke/StringConcatFactory.makeConcatWithConstants:"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;":makeConcatWithConstants:"(Lp2/c2;)Ljava/lang/String;" { + String "In c7\'s method7 with param = " + }; + invokevirtual Method java/io/PrintStream.println:"(Ljava/lang/String;)V"; + endtry t1; + goto L61; + catch t1 java/lang/IllegalAccessError; + stack_frame_type stack1; + stack_map class java/lang/IllegalAccessError; + astore_3; + new class java/lang/RuntimeException; + dup; + aload_3; + invokevirtual Method java/lang/IllegalAccessError.getMessage:"()Ljava/lang/String;"; + invokedynamic InvokeDynamic REF_invokeStatic:Method java/lang/invoke/StringConcatFactory.makeConcatWithConstants:"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;":makeConcatWithConstants:"(Ljava/lang/String;)Ljava/lang/String;" { + String "Unexpected IllegalAccessError: " + }; + invokespecial Method java/lang/RuntimeException."":"(Ljava/lang/String;)V"; + athrow; + L61: stack_frame_type same; + return; + } + public Method methodAddReadEdge:"(Ljava/lang/Module;)V" + stack 2 locals 2 + { + ldc class c7; + invokevirtual Method java/lang/Class.getModule:"()Ljava/lang/Module;"; + aload_1; + invokevirtual Method java/lang/Module.addReads:"(Ljava/lang/Module;)Ljava/lang/Module;"; + pop; + return; + } + + public static final InnerClass Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles; + +} // end Class c7 diff --git a/test/langtools/tools/javac/StringConcat/StringAppendEvaluatesInOrder.java b/test/langtools/tools/javac/StringConcat/StringAppendEvaluatesInOrder.java new file mode 100644 index 00000000000..b2bd47acde0 --- /dev/null +++ b/test/langtools/tools/javac/StringConcat/StringAppendEvaluatesInOrder.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2021, Google LLC. 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 8273914 + * @summary Indy string concat changes order of operations + * + * @clean * + * @compile -XDstringConcat=indy StringAppendEvaluatesInOrder.java + * @run main StringAppendEvaluatesInOrder + * + * @clean * + * @compile -XDstringConcat=indyWithConstants StringAppendEvaluatesInOrder.java + * @run main StringAppendEvaluatesInOrder + * + * @clean * + * @compile -XDstringConcat=inline StringAppendEvaluatesInOrder.java + * @run main StringAppendEvaluatesInOrder + */ + +public class StringAppendEvaluatesInOrder { + static String test() { + StringBuilder builder = new StringBuilder("foo"); + int i = 15; + return "Test: " + i + " " + (++i) + builder + builder.append("bar"); + } + + static String compoundAssignment() { + StringBuilder builder2 = new StringBuilder("foo"); + Object oo = builder2; + oo += "" + builder2.append("bar"); + return oo.toString(); + } + + public static void main(String[] args) throws Exception { + assertEquals(test(), "Test: 15 16foofoobar"); + assertEquals(compoundAssignment(), "foofoobar"); + } + + private static void assertEquals(String actual, String expected) { + if (!actual.equals(expected)) { + throw new AssertionError("expected: " + expected + ", actual: " + actual); + } + } +} diff --git a/test/langtools/tools/javac/StringConcat/WellKnownTypeSignatures.java b/test/langtools/tools/javac/StringConcat/WellKnownTypeSignatures.java new file mode 100644 index 00000000000..07cdeef4956 --- /dev/null +++ b/test/langtools/tools/javac/StringConcat/WellKnownTypeSignatures.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2021, Google LLC. 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 com.sun.tools.classfile.*; +import com.sun.tools.classfile.ConstantPool.*; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +/* + * @test + * @bug 8273914 + * @summary Indy string concat changes order of operations + * @modules jdk.jdeps/com.sun.tools.classfile + * + * @clean * + * @compile -XDstringConcat=indy WellKnownTypeSignatures.java + * @run main WellKnownTypeSignatures + * + * @clean * + * @compile -XDstringConcat=indyWithConstants WellKnownTypeSignatures.java + * @run main WellKnownTypeSignatures + */ + +public class WellKnownTypeSignatures { + static List actualTypes; + + static int idx = 0; + + static boolean z = true; + static char c = (char) 42; + static short s = (short) 42; + static byte b = (byte) 42; + static int i = 42; + static long l = 42L; + static float f = 42.0f; + static double d = 42.0; + + public static void main(String[] argv) throws Exception { + readIndyTypes(); + + test("" + WellKnownTypeSignatures.class, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); + test("" + Boolean.valueOf(z), idx++, "(Ljava/lang/Boolean;)Ljava/lang/String;"); + test("" + Character.valueOf(c), idx++, "(Ljava/lang/Character;)Ljava/lang/String;"); + test("" + Byte.valueOf(b), idx++, "(Ljava/lang/Byte;)Ljava/lang/String;"); + test("" + Short.valueOf(s), idx++, "(Ljava/lang/Short;)Ljava/lang/String;"); + test("" + Integer.valueOf(i), idx++, "(Ljava/lang/Integer;)Ljava/lang/String;"); + test("" + Long.valueOf(l), idx++, "(Ljava/lang/Long;)Ljava/lang/String;"); + test("" + Double.valueOf(d), idx++, "(Ljava/lang/Double;)Ljava/lang/String;"); + test("" + Float.valueOf(f), idx++, "(Ljava/lang/Float;)Ljava/lang/String;"); + test("" + z, idx++, "(Z)Ljava/lang/String;"); + test("" + c, idx++, "(C)Ljava/lang/String;"); + test("" + b, idx++, "(B)Ljava/lang/String;"); + test("" + s, idx++, "(S)Ljava/lang/String;"); + test("" + i, idx++, "(I)Ljava/lang/String;"); + test("" + l, idx++, "(J)Ljava/lang/String;"); + test("" + d, idx++, "(D)Ljava/lang/String;"); + test("" + f, idx++, "(F)Ljava/lang/String;"); + } + + public static void test(String actual, int index, String expectedType) { + String actualType = actualTypes.get(index); + if (!actualType.equals(expectedType)) { + throw new IllegalStateException( + index + + " Unexpected type: expected = " + + expectedType + + ", actual = " + + actualType); + } + } + + public static void readIndyTypes() throws Exception { + actualTypes = new ArrayList(); + + ClassFile classFile = + ClassFile.read( + new File( + System.getProperty("test.classes", "."), + WellKnownTypeSignatures.class.getName() + ".class")); + ConstantPool constantPool = classFile.constant_pool; + + for (Method method : classFile.methods) { + if (method.getName(constantPool).equals("main")) { + Code_attribute code = (Code_attribute) method.attributes.get(Attribute.Code); + for (Instruction i : code.getInstructions()) { + if (i.getOpcode() == Opcode.INVOKEDYNAMIC) { + CONSTANT_InvokeDynamic_info indyInfo = + (CONSTANT_InvokeDynamic_info) + constantPool.get(i.getUnsignedShort(1)); + CONSTANT_NameAndType_info natInfo = indyInfo.getNameAndTypeInfo(); + actualTypes.add(natInfo.getType()); + } + } + } + } + } +} diff --git a/test/langtools/tools/javac/StringConcat/WellKnownTypes.java b/test/langtools/tools/javac/StringConcat/WellKnownTypes.java new file mode 100644 index 00000000000..39150cfc4da --- /dev/null +++ b/test/langtools/tools/javac/StringConcat/WellKnownTypes.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2021, Google LLC. 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 com.sun.tools.classfile.*; +import com.sun.tools.classfile.ConstantPool.*; + +/* + * @test + * @bug 8273914 + * @summary Indy string concat changes order of operations + * @modules jdk.jdeps/com.sun.tools.classfile + * + * @compile -XDstringConcat=indy WellKnownTypes.java + * @run main WellKnownTypes + * + * @compile -XDstringConcat=indyWithConstants WellKnownTypes.java + * @run main WellKnownTypes + * + * @compile -XDstringConcat=inline WellKnownTypes.java + * @run main WellKnownTypes + */ + +public class WellKnownTypes { + static int idx = 0; + + static boolean z = true; + static char c = (char) 42; + static byte b = (byte) 43; + static short s = (short) 44; + static int i = 45; + static long l = 46L; + static float f = 47.0f; + static double d = 48.0; + + public static void main(String[] argv) throws Exception { + test("" + WellKnownTypes.class, idx++, "class WellKnownTypes"); + test("" + Boolean.valueOf(z), idx++, "true"); + test("" + Character.valueOf(c), idx++, "*"); + test("" + Byte.valueOf(b), idx++, "43"); + test("" + Short.valueOf(s), idx++, "44"); + test("" + Integer.valueOf(i), idx++, "45"); + test("" + Long.valueOf(l), idx++, "46"); + test("" + Float.valueOf(f), idx++, "47.0"); + test("" + Double.valueOf(d), idx++, "48.0"); + test("" + z, idx++, "true"); + test("" + c, idx++, "*"); + test("" + b, idx++, "43"); + test("" + s, idx++, "44"); + test("" + i, idx++, "45"); + test("" + l, idx++, "46"); + test("" + f, idx++, "47.0"); + test("" + d, idx++, "48.0"); + } + + public static void test(String actual, int index, String expected) { + if (!actual.equals(expected)) { + throw new IllegalStateException( + index + " Unexpected: expected = " + expected + ", actual = " + actual); + } + } +} diff --git a/test/langtools/tools/javac/StringConcat/access/Test.java b/test/langtools/tools/javac/StringConcat/access/Test.java index 72237e8b4ef..578bbddb118 100644 --- a/test/langtools/tools/javac/StringConcat/access/Test.java +++ b/test/langtools/tools/javac/StringConcat/access/Test.java @@ -56,109 +56,109 @@ public class Test { // ---------------------------------------------------------------------------- // public Private_PublicClass c1 = new Private_PublicClass(); - test("" + holder.c1, idx++, "(Lp1/PublicClass;)Ljava/lang/String;"); + test("" + holder.c1, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); // public Private_PublicInterface c2 = new Private_PublicInterface(); - test("" + holder.c2, idx++, "(Ljava/lang/Object;)Ljava/lang/String;"); + test("" + holder.c2, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); // public Private_PrivateInterface1 c3 = new Private_PrivateInterface1(); - test("" + holder.c3, idx++, "(Ljava/lang/Object;)Ljava/lang/String;"); + test("" + holder.c3, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); // public Private_PrivateInterface2 c4 = new Private_PrivateInterface2(); - test("" + holder.c4, idx++, "(Ljava/lang/Object;)Ljava/lang/String;"); + test("" + holder.c4, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); // public Public_PublicClass c5 = new Public_PublicClass(); - test("" + holder.c5, idx++, "(Lp1/Public_PublicClass;)Ljava/lang/String;"); + test("" + holder.c5, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); // public Public_PublicInterface c6 = new Public_PublicInterface(); - test("" + holder.c6, idx++, "(Lp1/Public_PublicInterface;)Ljava/lang/String;"); + test("" + holder.c6, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); // public Public_PrivateInterface1 c7 = new Public_PrivateInterface1(); - test("" + holder.c7, idx++, "(Lp1/Public_PrivateInterface1;)Ljava/lang/String;"); + test("" + holder.c7, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); // public Public_PrivateInterface2 c8 = new Public_PrivateInterface2(); - test("" + holder.c8, idx++, "(Lp1/Public_PrivateInterface2;)Ljava/lang/String;"); + test("" + holder.c8, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); // ---------------------------------------------------------------------------- // public Private_PublicClass[] ac1 = new Private_PublicClass[0]; - test("" + holder.ac1, idx++, "([Lp1/PublicClass;)Ljava/lang/String;"); + test("" + holder.ac1, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); // public Private_PublicInterface[] ac2 = new Private_PublicInterface[0]; - test("" + holder.ac2, idx++, "([Ljava/lang/Object;)Ljava/lang/String;"); + test("" + holder.ac2, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); // public Private_PrivateInterface1[] ac3 = new Private_PrivateInterface1[0]; - test("" + holder.ac3, idx++, "([Ljava/lang/Object;)Ljava/lang/String;"); + test("" + holder.ac3, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); // public Private_PrivateInterface2[] ac4 = new Private_PrivateInterface2[0]; - test("" + holder.ac4, idx++, "([Ljava/lang/Object;)Ljava/lang/String;"); + test("" + holder.ac4, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); // public Public_PublicClass[] ac5 = new Public_PublicClass[0]; - test("" + holder.ac5, idx++, "([Lp1/Public_PublicClass;)Ljava/lang/String;"); + test("" + holder.ac5, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); // public Public_PublicInterface[] ac6 = new Public_PublicInterface[0]; - test("" + holder.ac6, idx++, "([Lp1/Public_PublicInterface;)Ljava/lang/String;"); + test("" + holder.ac6, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); // public Public_PrivateInterface1[] ac7 = new Public_PrivateInterface1[0]; - test("" + holder.ac7, idx++, "([Lp1/Public_PrivateInterface1;)Ljava/lang/String;"); + test("" + holder.ac7, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); // public Public_PrivateInterface2[] ac8 = new Public_PrivateInterface2[0]; - test("" + holder.ac8, idx++, "([Lp1/Public_PrivateInterface2;)Ljava/lang/String;"); + test("" + holder.ac8, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); // ---------------------------------------------------------------------------- // public Private_PublicClass[][] aac1 = new Private_PublicClass[0][]; - test("" + holder.aac1, idx++, "([[Lp1/PublicClass;)Ljava/lang/String;"); + test("" + holder.aac1, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); // public Private_PublicInterface[][] aac2 = new Private_PublicInterface[0][]; - test("" + holder.aac2, idx++, "([[Ljava/lang/Object;)Ljava/lang/String;"); + test("" + holder.aac2, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); // public Private_PrivateInterface1[][] aac3 = new Private_PrivateInterface1[0][]; - test("" + holder.aac3, idx++, "([[Ljava/lang/Object;)Ljava/lang/String;"); + test("" + holder.aac3, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); // public Private_PrivateInterface2[][] aac4 = new Private_PrivateInterface2[0][]; - test("" + holder.aac4, idx++, "([[Ljava/lang/Object;)Ljava/lang/String;"); + test("" + holder.aac4, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); // public Public_PublicClass[][] aac5 = new Public_PublicClass[0][]; - test("" + holder.aac5, idx++, "([[Lp1/Public_PublicClass;)Ljava/lang/String;"); + test("" + holder.aac5, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); // public Public_PublicInterface[][] aac6 = new Public_PublicInterface[0][]; - test("" + holder.aac6, idx++, "([[Lp1/Public_PublicInterface;)Ljava/lang/String;"); + test("" + holder.aac6, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); // public Public_PrivateInterface1[][] aac7 = new Public_PrivateInterface1[0][]; - test("" + holder.aac7, idx++, "([[Lp1/Public_PrivateInterface1;)Ljava/lang/String;"); + test("" + holder.aac7, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); // public Public_PrivateInterface2[][] aac8 = new Public_PrivateInterface2[0][]; - test("" + holder.aac8, idx++, "([[Lp1/Public_PrivateInterface2;)Ljava/lang/String;"); + test("" + holder.aac8, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); // ---------------------------------------------------------------------------- // public PublicInterface i1 = new Private_PublicInterface(); - test("" + holder.i1, idx++, "(Lp1/PublicInterface;)Ljava/lang/String;"); + test("" + holder.i1, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); // public PrivateInterface1 i2 = new Private_PrivateInterface1(); - test("" + holder.i2, idx++, "(Ljava/lang/Object;)Ljava/lang/String;"); + test("" + holder.i2, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); // public PrivateInterface2 i3 = new Private_PrivateInterface2(); - test("" + holder.i3, idx++, "(Ljava/lang/Object;)Ljava/lang/String;"); + test("" + holder.i3, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); // public PublicInterface[] ai1 = new Private_PublicInterface[0]; - test("" + holder.ai1, idx++, "([Lp1/PublicInterface;)Ljava/lang/String;"); + test("" + holder.ai1, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); // public PrivateInterface1[] ai2 = new Private_PrivateInterface1[0]; - test("" + holder.ai2, idx++, "([Ljava/lang/Object;)Ljava/lang/String;"); + test("" + holder.ai2, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); // public PrivateInterface2[] ai3 = new Private_PrivateInterface2[0]; - test("" + holder.ai3, idx++, "([Ljava/lang/Object;)Ljava/lang/String;"); + test("" + holder.ai3, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); // public PublicInterface[][] aai1 = new Private_PublicInterface[0][]; - test("" + holder.aai1, idx++, "([[Lp1/PublicInterface;)Ljava/lang/String;"); + test("" + holder.aai1, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); // public PrivateInterface1[][] aai2 = new Private_PrivateInterface1[0][]; - test("" + holder.aai2, idx++, "([[Ljava/lang/Object;)Ljava/lang/String;"); + test("" + holder.aai2, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); // public PrivateInterface2[][] aai3 = new Private_PrivateInterface2[0][]; - test("" + holder.aai3, idx++, "([[Ljava/lang/Object;)Ljava/lang/String;"); + test("" + holder.aai3, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); } -- GitLab From 67141849d922a3899fcb4429a520b874b7d91b4c Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Tue, 11 Jan 2022 16:18:06 +0000 Subject: [PATCH 073/564] 8279700: Parallel: Simplify ScavengeRootsTask constructor API Reviewed-by: tschatzl, sjohanss --- src/hotspot/share/gc/parallel/psScavenge.cpp | 29 ++++++-------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/src/hotspot/share/gc/parallel/psScavenge.cpp b/src/hotspot/share/gc/parallel/psScavenge.cpp index 2cee28eef42..430e4ccf4ec 100644 --- a/src/hotspot/share/gc/parallel/psScavenge.cpp +++ b/src/hotspot/share/gc/parallel/psScavenge.cpp @@ -283,37 +283,30 @@ class ScavengeRootsTask : public WorkerTask { PSOldGen* _old_gen; HeapWord* _gen_top; uint _active_workers; - bool _is_empty; + bool _is_old_gen_empty; TaskTerminator _terminator; public: ScavengeRootsTask(PSOldGen* old_gen, - HeapWord* gen_top, - uint active_workers, - bool is_empty) : + uint active_workers) : WorkerTask("ScavengeRootsTask"), _strong_roots_scope(active_workers), _subtasks(ParallelRootType::sentinel), _old_gen(old_gen), - _gen_top(gen_top), + _gen_top(old_gen->object_space()->top()), _active_workers(active_workers), - _is_empty(is_empty), + _is_old_gen_empty(old_gen->object_space()->is_empty()), _terminator(active_workers, PSPromotionManager::vm_thread_promotion_manager()->stack_array_depth()) { + assert(_old_gen != NULL, "Sanity"); } virtual void work(uint worker_id) { + assert(worker_id < _active_workers, "Sanity"); ResourceMark rm; - if (!_is_empty) { + if (!_is_old_gen_empty) { // There are only old-to-young pointers if there are objects // in the old gen. - - assert(_old_gen != NULL, "Sanity"); - // There are no old-to-young pointers if the old gen is empty. - assert(!_old_gen->object_space()->is_empty(), "Should not be called is there is no work"); - assert(_old_gen->object_space()->contains(_gen_top) || _gen_top == _old_gen->object_space()->top(), "Sanity"); - assert(worker_id < ParallelGCThreads, "Sanity"); - { PSPromotionManager* pm = PSPromotionManager::gc_thread_promotion_manager(worker_id); PSCardTable* card_table = ParallelScavengeHeap::heap()->card_table(); @@ -453,12 +446,6 @@ bool PSScavenge::invoke_no_policy() { // Reset our survivor overflow. set_survivor_overflow(false); - // We need to save the old top values before - // creating the promotion_manager. We pass the top - // values to the card_table, to prevent it from - // straying into the promotion labs. - HeapWord* old_top = old_gen->object_space()->top(); - const uint active_workers = WorkerPolicy::calc_active_workers(ParallelScavengeHeap::heap()->workers().max_workers(), ParallelScavengeHeap::heap()->workers().active_workers(), @@ -472,7 +459,7 @@ bool PSScavenge::invoke_no_policy() { { GCTraceTime(Debug, gc, phases) tm("Scavenge", &_gc_timer); - ScavengeRootsTask task(old_gen, old_top, active_workers, old_gen->object_space()->is_empty()); + ScavengeRootsTask task(old_gen, active_workers); ParallelScavengeHeap::heap()->workers().run_task(&task); } -- GitLab From c4518e257c1680a6cdb80b7e177d01700ea2c54e Mon Sep 17 00:00:00 2001 From: Vamsi Parasa Date: Tue, 11 Jan 2022 18:47:42 +0000 Subject: [PATCH 074/564] 8278868: Add x86 vectorization support for Long.bitCount() Reviewed-by: jbhateja, sviswanathan, kvn --- src/hotspot/cpu/x86/assembler_x86.cpp | 8 ++ src/hotspot/cpu/x86/assembler_x86.hpp | 1 + src/hotspot/cpu/x86/x86.ad | 15 ++++ src/hotspot/share/adlc/formssel.cpp | 4 +- src/hotspot/share/opto/classes.hpp | 3 +- src/hotspot/share/opto/superword.cpp | 23 ++++- src/hotspot/share/opto/vectornode.cpp | 13 +++ src/hotspot/share/opto/vectornode.hpp | 9 ++ src/hotspot/share/runtime/vmStructs.cpp | 3 +- .../vectorization/TestPopCountVectorLong.java | 77 ++++++++++++++++ .../bench/vm/compiler/VectorBitCount.java | 87 +++++++++++++++++++ 11 files changed, 237 insertions(+), 6 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/vectorization/TestPopCountVectorLong.java create mode 100644 test/micro/org/openjdk/bench/vm/compiler/VectorBitCount.java diff --git a/src/hotspot/cpu/x86/assembler_x86.cpp b/src/hotspot/cpu/x86/assembler_x86.cpp index fc7b55f5d98..a15ce3119f6 100644 --- a/src/hotspot/cpu/x86/assembler_x86.cpp +++ b/src/hotspot/cpu/x86/assembler_x86.cpp @@ -4829,6 +4829,14 @@ void Assembler::vpopcntd(XMMRegister dst, XMMRegister src, int vector_len) { emit_int16(0x55, (0xC0 | encode)); } +void Assembler::vpopcntq(XMMRegister dst, XMMRegister src, int vector_len) { + assert(VM_Version::supports_avx512_vpopcntdq(), "must support vpopcntdq feature"); + InstructionAttr attributes(vector_len, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + attributes.set_is_evex_instruction(); + int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); + emit_int16(0x55, (0xC0 | encode)); +} + void Assembler::popf() { emit_int8((unsigned char)0x9D); } diff --git a/src/hotspot/cpu/x86/assembler_x86.hpp b/src/hotspot/cpu/x86/assembler_x86.hpp index 92d04d21839..aa08e834853 100644 --- a/src/hotspot/cpu/x86/assembler_x86.hpp +++ b/src/hotspot/cpu/x86/assembler_x86.hpp @@ -1869,6 +1869,7 @@ private: void popcntl(Register dst, Register src); void vpopcntd(XMMRegister dst, XMMRegister src, int vector_len); + void vpopcntq(XMMRegister dst, XMMRegister src, int vector_len); #ifdef _LP64 void popcntq(Register dst, Address src); diff --git a/src/hotspot/cpu/x86/x86.ad b/src/hotspot/cpu/x86/x86.ad index 8d5ba613b28..6f38e05b90b 100644 --- a/src/hotspot/cpu/x86/x86.ad +++ b/src/hotspot/cpu/x86/x86.ad @@ -1405,6 +1405,7 @@ const bool Matcher::match_rule_supported(int opcode) { } break; case Op_PopCountVI: + case Op_PopCountVL: if (!UsePopCountInstruction || !VM_Version::supports_avx512_vpopcntdq()) { return false; } @@ -8590,6 +8591,20 @@ instruct vpopcountI(vec dst, vec src) %{ ins_pipe( pipe_slow ); %} +instruct vpopcountL(vec dst, vec src) %{ + match(Set dst (PopCountVL src)); + format %{ "vpopcntq $dst,$src\t! vector popcount packedL" %} + ins_encode %{ + assert(UsePopCountInstruction, "not enabled"); + + int vlen_enc = vector_length_encoding(this, $src); + __ vpopcntq($dst$$XMMRegister, $src$$XMMRegister, vlen_enc); + __ evpmovqd($dst$$XMMRegister, $dst$$XMMRegister, vlen_enc); + + %} + ins_pipe( pipe_slow ); +%} + // --------------------------------- Bitwise Ternary Logic ---------------------------------- instruct vpternlog(vec dst, vec src2, vec src3, immU8 func) %{ diff --git a/src/hotspot/share/adlc/formssel.cpp b/src/hotspot/share/adlc/formssel.cpp index ee528d97b5f..f7ff8ccf40b 100644 --- a/src/hotspot/share/adlc/formssel.cpp +++ b/src/hotspot/share/adlc/formssel.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2022, 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 @@ -4235,7 +4235,7 @@ bool MatchRule::is_vector() const { "VectorCastB2X", "VectorCastS2X", "VectorCastI2X", "VectorCastL2X", "VectorCastF2X", "VectorCastD2X", "VectorMaskWrapper","VectorMaskCmp","VectorReinterpret","LoadVectorMasked","StoreVectorMasked", - "FmaVD","FmaVF","PopCountVI","VectorLongToMask", + "FmaVD","FmaVF","PopCountVI", "PopCountVL", "VectorLongToMask", // Next are vector mask ops. "MaskAll", "AndVMask", "OrVMask", "XorVMask", "VectorMaskCast", // Next are not supported currently. diff --git a/src/hotspot/share/opto/classes.hpp b/src/hotspot/share/opto/classes.hpp index c4b7853d7b1..de6884deb9d 100644 --- a/src/hotspot/share/opto/classes.hpp +++ b/src/hotspot/share/opto/classes.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -272,6 +272,7 @@ macro(Phi) macro(PopCountI) macro(PopCountL) macro(PopCountVI) +macro(PopCountVL) macro(PrefetchAllocation) macro(Proj) macro(RShiftI) diff --git a/src/hotspot/share/opto/superword.cpp b/src/hotspot/share/opto/superword.cpp index d488d0eba5f..1bf4c7a3282 100644 --- a/src/hotspot/share/opto/superword.cpp +++ b/src/hotspot/share/opto/superword.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2022, 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 @@ -2553,7 +2553,7 @@ void SuperWord::output() { opc == Op_AbsF || opc == Op_AbsD || opc == Op_AbsI || opc == Op_AbsL || opc == Op_NegF || opc == Op_NegD || - opc == Op_PopCountI) { + opc == Op_PopCountI || opc == Op_PopCountL) { assert(n->req() == 2, "only one input expected"); Node* in = vector_opd(p, 1); vn = VectorNode::make(opc, in, NULL, vlen, velt_basic_type(n)); @@ -2928,6 +2928,7 @@ bool SuperWord::is_vector_use(Node* use, int u_idx) { } return true; } + if (VectorNode::is_muladds2i(use)) { // MulAddS2I takes shorts and produces ints - hence the special checks // on alignment and size. @@ -2943,6 +2944,24 @@ bool SuperWord::is_vector_use(Node* use, int u_idx) { } return true; } + + if (VectorNode::is_vpopcnt_long(use)) { + // VPOPCNT_LONG takes long and produces int - hence the special checks + // on alignment and size. + if (u_pk->size() != d_pk->size()) { + return false; + } + for (uint i = 0; i < MIN2(d_pk->size(), u_pk->size()); i++) { + Node* ui = u_pk->at(i); + Node* di = d_pk->at(i); + if (alignment(ui) * 2 != alignment(di)) { + return false; + } + } + return true; + } + + if (u_pk->size() != d_pk->size()) return false; for (uint i = 0; i < u_pk->size(); i++) { diff --git a/src/hotspot/share/opto/vectornode.cpp b/src/hotspot/share/opto/vectornode.cpp index 51db711dc38..60415948b8a 100644 --- a/src/hotspot/share/opto/vectornode.cpp +++ b/src/hotspot/share/opto/vectornode.cpp @@ -154,6 +154,8 @@ int VectorNode::opcode(int sopc, BasicType bt) { // Unimplemented for subword types since bit count changes // depending on size of lane (and sign bit). return (bt == T_INT ? Op_PopCountVI : 0); + case Op_PopCountL: + return Op_PopCountVL; case Op_LShiftI: switch (bt) { case T_BOOLEAN: @@ -297,6 +299,16 @@ bool VectorNode::is_muladds2i(Node* n) { return false; } +bool VectorNode::is_vpopcnt_long(Node* n) { + if (n->Opcode() == Op_PopCountL) { + return true; + } + return false; +} + + + + bool VectorNode::is_roundopD(Node* n) { if (n->Opcode() == Op_RoundDoubleMode) { return true; @@ -531,6 +543,7 @@ VectorNode* VectorNode::make(int vopc, Node* n1, Node* n2, const TypeVect* vt, b case Op_SqrtVD: return new SqrtVDNode(n1, vt); case Op_PopCountVI: return new PopCountVINode(n1, vt); + case Op_PopCountVL: return new PopCountVLNode(n1, vt); case Op_RotateLeftV: return new RotateLeftVNode(n1, n2, vt); case Op_RotateRightV: return new RotateRightVNode(n1, n2, vt); diff --git a/src/hotspot/share/opto/vectornode.hpp b/src/hotspot/share/opto/vectornode.hpp index 5e2d0eaf946..b2477f3b586 100644 --- a/src/hotspot/share/opto/vectornode.hpp +++ b/src/hotspot/share/opto/vectornode.hpp @@ -93,6 +93,7 @@ class VectorNode : public TypeNode { static bool is_type_transition_short_to_int(Node* n); static bool is_type_transition_to_int(Node* n); static bool is_muladds2i(Node* n); + static bool is_vpopcnt_long(Node* n); static bool is_roundopD(Node* n); static bool is_scalar_rotate(Node* n); static bool is_vector_rotate_supported(int opc, uint vlen, BasicType bt); @@ -505,6 +506,14 @@ class PopCountVINode : public VectorNode { virtual int Opcode() const; }; +//------------------------------PopCountVLNode--------------------------------- +// Vector popcount long bits +class PopCountVLNode : public VectorNode { + public: + PopCountVLNode(Node* in, const TypeVect* vt) : VectorNode(in,vt) {} + virtual int Opcode() const; +}; + //------------------------------SqrtVFNode-------------------------------------- // Vector Sqrt float class SqrtVFNode : public VectorNode { diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp index 89abff4a0a8..3ec853d38f0 100644 --- a/src/hotspot/share/runtime/vmStructs.cpp +++ b/src/hotspot/share/runtime/vmStructs.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2022, 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 @@ -1767,6 +1767,7 @@ declare_c2_type(DivVFNode, VectorNode) \ declare_c2_type(DivVDNode, VectorNode) \ declare_c2_type(PopCountVINode, VectorNode) \ + declare_c2_type(PopCountVLNode, VectorNode) \ declare_c2_type(LShiftVBNode, VectorNode) \ declare_c2_type(LShiftVSNode, VectorNode) \ declare_c2_type(LShiftVINode, VectorNode) \ diff --git a/test/hotspot/jtreg/compiler/vectorization/TestPopCountVectorLong.java b/test/hotspot/jtreg/compiler/vectorization/TestPopCountVectorLong.java new file mode 100644 index 00000000000..d78b9efa09c --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorization/TestPopCountVectorLong.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2022, 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 +* @summary Test vectorization of popcount for Long +* @requires vm.cpu.features ~= ".*avx512dq.*" +* @requires vm.compiler2.enabled +* @requires os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64" +* @library /test/lib / +* @run driver compiler.vectorization.TestPopCountVectorLong +*/ + +package compiler.vectorization; +import compiler.lib.ir_framework.*; +import java.util.Random; + + +public class TestPopCountVectorLong { + private long[] input; + private int[] output; + private static final int LEN = 1024; + private Random rng; + + public static void main(String args[]) { + TestFramework.run(TestPopCountVectorLong.class); + } + + public TestPopCountVectorLong() { + input = new long[LEN]; + output = new int[LEN]; + rng = new Random(42); + for (int i = 0; i < LEN; ++i) { + input[i] = rng.nextLong(); + } + } + + @Test // needs to be run in (fast) debug mode + @Warmup(10000) + @IR(counts = {"PopCountVL", ">= 1"}) // Atleast one PopCountVL node is generated if vectorization is successful + public void vectorizeBitCount() { + for (int i = 0; i < LEN; ++i) { + output[i] = Long.bitCount(input[i]); + } + checkResult(); + } + + public void checkResult() { + for (int i = 0; i < LEN; ++i) { + int expected = Long.bitCount(input[i]); + if (output[i] != expected) { + throw new RuntimeException("Invalid result: output[" + i + "] = " + output[i] + " != " + expected); + } + } + } +} + diff --git a/test/micro/org/openjdk/bench/vm/compiler/VectorBitCount.java b/test/micro/org/openjdk/bench/vm/compiler/VectorBitCount.java new file mode 100644 index 00000000000..e16cf422a9d --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/compiler/VectorBitCount.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2022, 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.*; +import org.openjdk.jmh.infra.*; +import java.util.concurrent.TimeUnit; +import java.util.random.RandomGenerator; +import java.util.random.RandomGeneratorFactory; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public abstract class VectorBitCount { + @Param({"1024"}) + public int SIZE; + + @Param("0") + private int seed; + private RandomGenerator rng = RandomGeneratorFactory.getDefault().create(seed); + private int[] bufferRandInts; + private long[] bufferRandLongs; + private int[] bitCounts; + @Setup + public void init() { + bufferRandInts = new int[SIZE]; + bufferRandLongs = new long[SIZE]; + bitCounts = new int[SIZE]; + + for (int i = 0; i < SIZE; i++) { + bufferRandInts[i] = rng.nextInt(); + bufferRandLongs[i] = rng.nextLong(); + } + } + + @Benchmark + public int[] intBitCount() { + for (int i = 0; i < SIZE; i++) { + bitCounts[i] = Integer.bitCount(bufferRandInts[i]); + } + return bitCounts; + } + + @Benchmark + public int[] longBitCount() { + for (int i = 0; i < SIZE; i++) { + bitCounts[i] = Long.bitCount(bufferRandLongs[i]); + } + return bitCounts; + } + + + @Fork(value = 1, jvmArgsPrepend = { + "-XX:+UseSuperWord" + }) + public static class WithSuperword extends VectorBitCount { + + } + + @Fork(value = 1, jvmArgsPrepend = { + "-XX:-UseSuperWord" + }) + public static class NoSuperword extends VectorBitCount { + } + +} + -- GitLab From 36f41cbe1126c6d9a00b21a1a68cf5f44e2f443f Mon Sep 17 00:00:00 2001 From: Mikael Vidstedt Date: Tue, 11 Jan 2022 22:34:24 +0000 Subject: [PATCH 075/564] 8279884: Use better file for cygwin source permission check Reviewed-by: erikj --- make/autoconf/basic.m4 | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/make/autoconf/basic.m4 b/make/autoconf/basic.m4 index e7fdab53050..65558e83c72 100644 --- a/make/autoconf/basic.m4 +++ b/make/autoconf/basic.m4 @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2022, 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 @@ -438,7 +438,9 @@ AC_DEFUN([BASIC_CHECK_DIR_ON_LOCAL_DISK], AC_DEFUN_ONCE([BASIC_CHECK_SRC_PERMS], [ if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - file_to_test="$TOPDIR/LICENSE" + # The choice of file here is somewhat arbitrary, it just needs to be there + # in the source tree when configure runs + file_to_test="$TOPDIR/Makefile" if test `$STAT -c '%a' "$file_to_test"` -lt 400; then AC_MSG_ERROR([Bad file permissions on src files. This is usually caused by cloning the repositories with a non cygwin hg in a directory not created in cygwin.]) fi -- GitLab From 3aaa0982d8c1735208a331b0097a5aea4a1fef5a Mon Sep 17 00:00:00 2001 From: Masanori Yano Date: Tue, 11 Jan 2022 22:37:15 +0000 Subject: [PATCH 076/564] 8276694: Pattern trailing unescaped backslash causes internal error Reviewed-by: jlaskey --- .../share/classes/java/util/regex/Pattern.java | 2 ++ test/jdk/java/util/regex/RegExTest.java | 11 ++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/java.base/share/classes/java/util/regex/Pattern.java b/src/java.base/share/classes/java/util/regex/Pattern.java index d52a2b92af9..3c15faf1586 100644 --- a/src/java.base/share/classes/java/util/regex/Pattern.java +++ b/src/java.base/share/classes/java/util/regex/Pattern.java @@ -1795,6 +1795,8 @@ loop: for(int x=0, offset=0; x + Pattern.compile(pattern)); + assertTrue(e.getMessage().contains("Unescaped trailing backslash")); + } } -- GitLab From 1c688f41373e90865b729b5149be2ec010bc9b37 Mon Sep 17 00:00:00 2001 From: Jie Fu Date: Wed, 12 Jan 2022 03:55:00 +0000 Subject: [PATCH 077/564] 8279900: compiler/vectorization/TestPopCountVectorLong.java fails due to vpopcntdq is not supported Reviewed-by: kvn --- .../jtreg/compiler/vectorization/TestPopCountVectorLong.java | 1 + 1 file changed, 1 insertion(+) diff --git a/test/hotspot/jtreg/compiler/vectorization/TestPopCountVectorLong.java b/test/hotspot/jtreg/compiler/vectorization/TestPopCountVectorLong.java index d78b9efa09c..e80c7cfac95 100644 --- a/test/hotspot/jtreg/compiler/vectorization/TestPopCountVectorLong.java +++ b/test/hotspot/jtreg/compiler/vectorization/TestPopCountVectorLong.java @@ -25,6 +25,7 @@ * @test * @summary Test vectorization of popcount for Long * @requires vm.cpu.features ~= ".*avx512dq.*" +* @requires vm.cpu.features ~= ".*vpopcntdq.*" * @requires vm.compiler2.enabled * @requires os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64" * @library /test/lib / -- GitLab From f16f6a95df30fbc720811181f5eca8533730d626 Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Wed, 12 Jan 2022 05:16:36 +0000 Subject: [PATCH 078/564] 8279821: JFR: Log warnings properly when loading a misconfigured .jfc file Reviewed-by: mgronlun --- .../classes/jdk/jfr/internal/dcmd/DCmdStart.java | 2 +- .../jdk/jfr/internal/jfc/model/JFCModel.java | 13 +++++++------ .../classes/jdk/jfr/internal/tool/Configure.java | 4 ++-- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStart.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStart.java index 77b8cccd77a..32b7f670b6f 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStart.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStart.java @@ -240,7 +240,7 @@ final class DCmdStart extends AbstractDCmd { paths.add(JFC.createSafePath(setting)); } try { - JFCModel model = new JFCModel(paths); + JFCModel model = new JFCModel(paths, l -> logWarning(l)); Set jfcOptions = new HashSet<>(); for (XmlInput input : model.getInputs()) { jfcOptions.add(input.getName()); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/model/JFCModel.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/model/JFCModel.java index bf9424265b8..0623b4d25dd 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/model/JFCModel.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/model/JFCModel.java @@ -32,6 +32,7 @@ import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.function.Consumer; import jdk.jfr.internal.SecuritySupport.SafePath; @@ -42,19 +43,19 @@ public final class JFCModel { private final Map> controls = new LinkedHashMap<>(); private final XmlConfiguration configuration; - public JFCModel(SafePath file) throws ParseException, IOException { + public JFCModel(SafePath file, Consumer logger) throws ParseException, IOException { this.configuration = createConfiguration(file); this.configuration.validate(); addControls(); wireConditions(); - wireSettings(); + wireSettings(logger); } - public JFCModel(List files) throws IOException, ParseException { + public JFCModel(List files, Consumer logger) throws IOException, ParseException { this.configuration = new XmlConfiguration(); this.configuration.setAttribute("version", "2.0"); for (SafePath file : files) { - JFCModel model = new JFCModel(file); + JFCModel model = new JFCModel(file, logger); for (var entry : model.controls.entrySet()) { String name = entry.getKey(); // Fail-fast checks that prevents an ambiguous file to be written later @@ -183,14 +184,14 @@ public final class JFCModel { } } - private void wireSettings() { + private void wireSettings(Consumer logger) { for (XmlEvent event : configuration.getEvents()) { for (XmlSetting setting : event.getSettings()) { var controlName = setting.getControl(); if (controlName.isPresent()) { List controls = getControlElements(controlName.get()); if (controls.isEmpty()) { - System.out.println("Warning! Setting '" + setting.getFullName() + "' refers to missing control '" + controlName.get() + "'"); + logger.accept("Setting '" + setting.getFullName() + "' refers to missing control '" + controlName.get() + "'"); } for (ControlElement ce : controls) { XmlElement control = (XmlElement) ce; diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Configure.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Configure.java index 037ad6dbf06..6281b0f1595 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Configure.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Configure.java @@ -127,7 +127,7 @@ final class Configure extends Command { } private void displayParameters(PrintStream stream, SafePath path, String name) throws ParseException, IOException { - JFCModel parameters = new JFCModel(path); + JFCModel parameters = new JFCModel(path, l -> stream.println("Warning! " + l)); stream.println(); stream.println("Options for " + name + ":"); stream.println(); @@ -195,7 +195,7 @@ final class Configure extends Command { output = new SafePath(Path.of("custom.jfc")); } UserInterface ui = new UserInterface(); - JFCModel model = new JFCModel(inputFiles); + JFCModel model = new JFCModel(inputFiles, l -> ui.println("Warning! " + l)); model.setLabel("Custom"); if (log) { SettingsLog.enable(); -- GitLab From 13bfb4972543d87677b693b7a1b82ffdbdb45e00 Mon Sep 17 00:00:00 2001 From: TejeshR13 Date: Wed, 12 Jan 2022 05:38:07 +0000 Subject: [PATCH 079/564] 6496103: isFileHidingEnabled return false by default Reviewed-by: serb, aivanov, prr --- src/java.desktop/share/classes/javax/swing/JFileChooser.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/java.desktop/share/classes/javax/swing/JFileChooser.java b/src/java.desktop/share/classes/javax/swing/JFileChooser.java index 544f4ee953b..8d286e05f3b 100644 --- a/src/java.desktop/share/classes/javax/swing/JFileChooser.java +++ b/src/java.desktop/share/classes/javax/swing/JFileChooser.java @@ -1412,7 +1412,8 @@ public class JFileChooser extends JComponent implements Accessible { /** * Returns true if hidden files are not shown in the file chooser; - * otherwise, returns false. + * otherwise, returns false. The default value of this property may be + * derived from the underlying Operating System. * * @return the status of the file hiding property * @see #setFileHidingEnabled -- GitLab From 319d23033f4a814935f10885aef725c818b0baed Mon Sep 17 00:00:00 2001 From: Masanori Yano Date: Wed, 12 Jan 2022 06:57:36 +0000 Subject: [PATCH 080/564] 8277463: JFileChooser with Metal L&F doesn't show non-canonical UNC path in - Look in Reviewed-by: psadhukhan --- .../classes/sun/awt/shell/ShellFolder.java | 3 +- .../8277463/UNCFileChooserTest.java | 124 ++++++++++++++++++ 2 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 test/jdk/javax/swing/JFileChooser/8277463/UNCFileChooserTest.java diff --git a/src/java.desktop/share/classes/sun/awt/shell/ShellFolder.java b/src/java.desktop/share/classes/sun/awt/shell/ShellFolder.java index 0c375a900a0..3aa91dcb600 100644 --- a/src/java.desktop/share/classes/sun/awt/shell/ShellFolder.java +++ b/src/java.desktop/share/classes/sun/awt/shell/ShellFolder.java @@ -41,6 +41,7 @@ import java.util.List; import java.util.concurrent.Callable; import javax.swing.SwingConstants; +import sun.awt.OSInfo; /** * @author Michael Martak @@ -295,7 +296,7 @@ public abstract class ShellFolder extends File { */ public static File getNormalizedFile(File f) throws IOException { File canonical = f.getCanonicalFile(); - if (f.equals(canonical)) { + if (f.equals(canonical) || OSInfo.getOSType() == OSInfo.OSType.WINDOWS) { // path of f doesn't contain symbolic links return canonical; } diff --git a/test/jdk/javax/swing/JFileChooser/8277463/UNCFileChooserTest.java b/test/jdk/javax/swing/JFileChooser/8277463/UNCFileChooserTest.java new file mode 100644 index 00000000000..738b5da762e --- /dev/null +++ b/test/jdk/javax/swing/JFileChooser/8277463/UNCFileChooserTest.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2021, 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 8277463 + @requires (os.family == "windows") + @summary JFileChooser with Metal L&F doesn't show non-canonical UNC path in - Look in + @run main/manual UNCFileChooserTest +*/ + +import javax.swing.JButton; +import javax.swing.JFileChooser; +import javax.swing.JFrame; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JTextArea; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.WindowConstants; +import java.awt.BorderLayout; +import java.awt.FlowLayout; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +public class UNCFileChooserTest { + private static volatile CountDownLatch countDownLatch; + private static JFrame instructionFrame; + private static JFrame testFrame; + private static volatile boolean testPassed = false; + + private static boolean validatePlatform() { + String osName = System.getProperty("os.name"); + if (osName == null) { + throw new RuntimeException("Name of the current OS could not be" + + " retrieved."); + } + return osName.startsWith("Windows"); + } + + private static void createInstructionUI() throws Exception { + UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); + String instructions = + "1. Enter the non-canonical UNC path of the directory to test\n" + + "example: \\\\pc-name\\dir\\..\n" + + "2. An \"Open File\" file chooser dialog pops up\n" + + "3. Check the \"Look in\" Combobox at the top for quickly changing directory is not empty\n" + + "4. Close the file chooser Dialog\n" + + "5. If the \"Look in\" Combobox is not empty then press PASS else press FAIL\n"; + instructionFrame = new JFrame("InstructionFrame"); + JTextArea textArea = new JTextArea(instructions); + textArea.setEditable(false); + final JButton passButton = new JButton("PASS"); + passButton.addActionListener((e) -> { + testPassed = true; + instructionFrame.dispose(); + countDownLatch.countDown(); + }); + final JButton failButton = new JButton("FAIL"); + failButton.addActionListener((e) -> { + instructionFrame.dispose(); + countDownLatch.countDown(); + }); + + JPanel mainPanel = new JPanel(new BorderLayout()); + mainPanel.add(textArea, BorderLayout.CENTER); + + JPanel buttonPanel = new JPanel(new FlowLayout()); + buttonPanel.add(passButton); + buttonPanel.add(failButton); + mainPanel.add(buttonPanel, BorderLayout.SOUTH); + instructionFrame.setDefaultCloseOperation( + WindowConstants.DISPOSE_ON_CLOSE); + instructionFrame.setBounds(0,0,500,500); + instructionFrame.add(mainPanel); + instructionFrame.pack(); + instructionFrame.setVisible(true); + } + + private static void showOpenDialog() throws Exception { + String path = JOptionPane.showInputDialog(testFrame, "Enter the non-canonical UNC path of the directory to test.\nexample: \\\\pc-name\\dir\\.."); + if (path == null) { + throw new RuntimeException("Enter the directory path to test."); + } + new JFileChooser(path).showOpenDialog(null); + } + + public static void main(String[] args) throws Exception { + if (!validatePlatform()) { + System.out.println("This test is only for MS Windows OS."); + return; + } + countDownLatch = new CountDownLatch(1); + UNCFileChooserTest uncFileChooserTest = + new UNCFileChooserTest(); + + uncFileChooserTest.createInstructionUI(); + uncFileChooserTest.showOpenDialog(); + countDownLatch.await(15, TimeUnit.MINUTES); + + if(!testPassed) { + throw new RuntimeException("Test failed!"); + } + } +} -- GitLab From bd339aa6c03d12cb830a2caa04bda322e9f40c33 Mon Sep 17 00:00:00 2001 From: Emanuel Peter Date: Wed, 12 Jan 2022 08:17:14 +0000 Subject: [PATCH 081/564] 8277627: Fix copyright years in some jvmci files Reviewed-by: kvn, thartmann --- .../jdk.vm.ci.code/src/jdk/vm/ci/code/MemoryBarriers.java | 2 +- .../src/jdk/vm/ci/hotspot/HotSpotCallingConventionType.java | 2 +- .../jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/UnsafeAccess.java | 2 +- .../classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/Constant.java | 2 +- .../jdk.vm.ci.meta/src/jdk/vm/ci/meta/DeoptimizationReason.java | 2 +- .../classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/InvokeTarget.java | 2 +- .../src/jdk/vm/ci/meta/MethodHandleAccessProvider.java | 2 +- .../jdk.vm.ci.meta/src/jdk/vm/ci/meta/ProfilingInfo.java | 2 +- .../classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/VMConstant.java | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/MemoryBarriers.java b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/MemoryBarriers.java index 074882c9054..08bc0856d3e 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/MemoryBarriers.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/MemoryBarriers.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2016, 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 diff --git a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCallingConventionType.java b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCallingConventionType.java index b554f173972..3a6f28ce2a9 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCallingConventionType.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCallingConventionType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 diff --git a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/UnsafeAccess.java b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/UnsafeAccess.java index 61b0f949655..afdff7a8890 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/UnsafeAccess.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/UnsafeAccess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, 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 diff --git a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/Constant.java b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/Constant.java index c7cc3895987..63002463fb5 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/Constant.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/Constant.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, 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 diff --git a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/DeoptimizationReason.java b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/DeoptimizationReason.java index bcefe66cc79..36c422beda5 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/DeoptimizationReason.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/DeoptimizationReason.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, 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 diff --git a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/InvokeTarget.java b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/InvokeTarget.java index afaa0f635c6..d22d7a9d622 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/InvokeTarget.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/InvokeTarget.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, 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 diff --git a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MethodHandleAccessProvider.java b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MethodHandleAccessProvider.java index c533123ccd8..0faa2af5704 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MethodHandleAccessProvider.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MethodHandleAccessProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, 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 diff --git a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ProfilingInfo.java b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ProfilingInfo.java index 2ba915c9892..7eaa8e96670 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ProfilingInfo.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ProfilingInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, 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 diff --git a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/VMConstant.java b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/VMConstant.java index e7b0484dbd3..ecd15057e97 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/VMConstant.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/VMConstant.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, 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 -- GitLab From 4f0b65023f8f37ba59a6397d8caf6b4b86ab18b7 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Wed, 12 Jan 2022 08:28:51 +0000 Subject: [PATCH 082/564] 8278581: Improve reference processing statistics log output Reviewed-by: tschatzl, kbarrett, sjohanss --- .../share/gc/shared/referenceProcessor.cpp | 2 +- .../shared/referenceProcessorPhaseTimes.cpp | 19 +++++++++++-------- .../shared/referenceProcessorPhaseTimes.hpp | 4 ++-- .../jtreg/gc/logging/TestPrintReferences.java | 8 +++++--- 4 files changed, 19 insertions(+), 14 deletions(-) diff --git a/src/hotspot/share/gc/shared/referenceProcessor.cpp b/src/hotspot/share/gc/shared/referenceProcessor.cpp index e8ba56f0155..21b57621706 100644 --- a/src/hotspot/share/gc/shared/referenceProcessor.cpp +++ b/src/hotspot/share/gc/shared/referenceProcessor.cpp @@ -483,7 +483,7 @@ void RefProcTask::process_discovered_list(uint worker_id, keep_alive, enqueue, do_enqueue_and_clear); - _phase_times->add_ref_cleared(ref_type, removed); + _phase_times->add_ref_dropped(ref_type, removed); } } diff --git a/src/hotspot/share/gc/shared/referenceProcessorPhaseTimes.cpp b/src/hotspot/share/gc/shared/referenceProcessorPhaseTimes.cpp index 027adae7424..f3bfcc22692 100644 --- a/src/hotspot/share/gc/shared/referenceProcessorPhaseTimes.cpp +++ b/src/hotspot/share/gc/shared/referenceProcessorPhaseTimes.cpp @@ -197,7 +197,7 @@ void ReferenceProcessorPhaseTimes::reset() { _soft_weak_final_refs_phase_worker_time_sec->reset(); for (int i = 0; i < number_of_subclasses_of_ref; i++) { - _ref_cleared[i] = 0; + _ref_dropped[i] = 0; _ref_discovered[i] = 0; } @@ -213,9 +213,9 @@ ReferenceProcessorPhaseTimes::~ReferenceProcessorPhaseTimes() { delete _soft_weak_final_refs_phase_worker_time_sec; } -void ReferenceProcessorPhaseTimes::add_ref_cleared(ReferenceType ref_type, size_t count) { +void ReferenceProcessorPhaseTimes::add_ref_dropped(ReferenceType ref_type, size_t count) { ASSERT_REF_TYPE(ref_type); - Atomic::add(&_ref_cleared[ref_type_2_index(ref_type)], count, memory_order_relaxed); + Atomic::add(&_ref_dropped[ref_type_2_index(ref_type)], count, memory_order_relaxed); } void ReferenceProcessorPhaseTimes::set_ref_discovered(ReferenceType ref_type, size_t count) { @@ -270,13 +270,16 @@ void ReferenceProcessorPhaseTimes::print_reference(ReferenceType ref_type, uint LogStream ls(lt); ResourceMark rm; - ls.print_cr("%s%s:", Indents[base_indent], ref_type_2_string(ref_type)); - - uint const next_indent = base_indent + 1; int const ref_type_index = ref_type_2_index(ref_type); - ls.print_cr("%sDiscovered: " SIZE_FORMAT, Indents[next_indent], _ref_discovered[ref_type_index]); - ls.print_cr("%sCleared: " SIZE_FORMAT, Indents[next_indent], _ref_cleared[ref_type_index]); + size_t discovered = _ref_discovered[ref_type_index]; + size_t dropped = _ref_dropped[ref_type_index]; + assert(discovered >= dropped, "invariant"); + size_t processed = discovered - dropped; + + ls.print_cr("%s%s Discovered: %zu, Dropped: %zu, Processed: %zu", + Indents[base_indent], ref_type_2_string(ref_type), + discovered, dropped, processed); } } diff --git a/src/hotspot/share/gc/shared/referenceProcessorPhaseTimes.hpp b/src/hotspot/share/gc/shared/referenceProcessorPhaseTimes.hpp index da115621b16..26ee4e2a918 100644 --- a/src/hotspot/share/gc/shared/referenceProcessorPhaseTimes.hpp +++ b/src/hotspot/share/gc/shared/referenceProcessorPhaseTimes.hpp @@ -52,7 +52,7 @@ class ReferenceProcessorPhaseTimes : public CHeapObj { // Total spent time for reference processing. double _total_time_ms; - size_t _ref_cleared[number_of_subclasses_of_ref]; + size_t _ref_dropped[number_of_subclasses_of_ref]; size_t _ref_discovered[number_of_subclasses_of_ref]; bool _processing_is_mt; @@ -83,7 +83,7 @@ public: void set_total_time_ms(double total_time_ms) { _total_time_ms = total_time_ms; } - void add_ref_cleared(ReferenceType ref_type, size_t count); + void add_ref_dropped(ReferenceType ref_type, size_t count); void set_ref_discovered(ReferenceType ref_type, size_t count); size_t ref_discovered(ReferenceType ref_type); diff --git a/test/hotspot/jtreg/gc/logging/TestPrintReferences.java b/test/hotspot/jtreg/gc/logging/TestPrintReferences.java index c3bf80a48a0..6272f08e994 100644 --- a/test/hotspot/jtreg/gc/logging/TestPrintReferences.java +++ b/test/hotspot/jtreg/gc/logging/TestPrintReferences.java @@ -80,9 +80,11 @@ public class TestPrintReferences { private static String refRegex(String reftype) { String countRegex = "[0-9]+"; - return gcLogTimeRegex + indent(6) + reftype + ":\n" + - gcLogTimeRegex + indent(8) + "Discovered: " + countRegex + "\n" + - gcLogTimeRegex + indent(8) + "Cleared: " + countRegex + "\n"; + return gcLogTimeRegex + indent(6) + reftype + " " + + "Discovered: " + countRegex + ", " + + "Dropped: " + countRegex + ", " + + "Processed: " + countRegex + "\n" + ; } private static void checkRefsLogFormat(OutputAnalyzer output) { -- GitLab From 525b20fce0acd393f31fd37fe1f05f9d32577f77 Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Wed, 12 Jan 2022 08:32:08 +0000 Subject: [PATCH 083/564] 8279676: Dubious YMM register clearing in x86_64 arraycopy stubs Reviewed-by: kvn, vlivanov, neliasso --- src/hotspot/cpu/x86/stubGenerator_x86_64.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp index 8e6257cb786..8b7188ca42c 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp @@ -1221,11 +1221,6 @@ class StubGenerator: public StubCodeGenerator { } __ addptr(qword_count, 4); __ BIND(L_end); - if (UseAVX >= 2) { - // clean upper bits of YMM registers - __ vpxor(xmm0, xmm0); - __ vpxor(xmm1, xmm1); - } } else { // Copy 32-bytes per iteration __ BIND(L_loop); @@ -1299,11 +1294,6 @@ class StubGenerator: public StubCodeGenerator { } __ subptr(qword_count, 4); __ BIND(L_end); - if (UseAVX >= 2) { - // clean upper bits of YMM registers - __ vpxor(xmm0, xmm0); - __ vpxor(xmm1, xmm1); - } } else { // Copy 32-bytes per iteration __ BIND(L_loop); -- GitLab From ece98d859d847196d298a28c1a095b09cebbee6f Mon Sep 17 00:00:00 2001 From: Sergey Tsypanov Date: Wed, 12 Jan 2022 10:16:37 +0000 Subject: [PATCH 084/564] 8278461: Use Executable.getSharedParameterTypes() instead of Executable.getParameterTypes() in trusted code Reviewed-by: redestad --- src/java.base/share/classes/java/lang/reflect/Constructor.java | 2 +- src/java.base/share/classes/java/lang/reflect/Method.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/java.base/share/classes/java/lang/reflect/Constructor.java b/src/java.base/share/classes/java/lang/reflect/Constructor.java index 73ad66d5d5d..17277c7eb35 100644 --- a/src/java.base/share/classes/java/lang/reflect/Constructor.java +++ b/src/java.base/share/classes/java/lang/reflect/Constructor.java @@ -371,7 +371,7 @@ public final class Constructor extends Executable { sb.append(getDeclaringClass().getTypeName()); sb.append('('); StringJoiner sj = new StringJoiner(","); - for (Class parameterType : getParameterTypes()) { + for (Class parameterType : getSharedParameterTypes()) { sj.add(parameterType.getTypeName()); } sb.append(sj); diff --git a/src/java.base/share/classes/java/lang/reflect/Method.java b/src/java.base/share/classes/java/lang/reflect/Method.java index 5d8fe026b40..2aff745d553 100644 --- a/src/java.base/share/classes/java/lang/reflect/Method.java +++ b/src/java.base/share/classes/java/lang/reflect/Method.java @@ -431,7 +431,7 @@ public final class Method extends Executable { String toShortSignature() { StringJoiner sj = new StringJoiner(",", getName() + "(", ")"); - for (Class parameterType : getParameterTypes()) { + for (Class parameterType : getSharedParameterTypes()) { sj.add(parameterType.getTypeName()); } return sj.toString(); -- GitLab From ff0cb98965a0b6be2f6c399e4645630c10b3466e Mon Sep 17 00:00:00 2001 From: Jaikiran Pai Date: Wed, 12 Jan 2022 12:58:17 +0000 Subject: [PATCH 085/564] 8279536: jdk/nio/zipfs/ZipFSOutputStreamTest.java timed out Reviewed-by: lancea --- .../jdk/nio/zipfs/ZipFSOutputStreamTest.java | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/test/jdk/jdk/nio/zipfs/ZipFSOutputStreamTest.java b/test/jdk/jdk/nio/zipfs/ZipFSOutputStreamTest.java index fe59857879b..77f866e9fdf 100644 --- a/test/jdk/jdk/nio/zipfs/ZipFSOutputStreamTest.java +++ b/test/jdk/jdk/nio/zipfs/ZipFSOutputStreamTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,15 +35,15 @@ import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; +import java.util.Arrays; import java.util.Map; -import java.util.Random; /** * @test * @summary Verify that the outputstream created for zip file entries, through the ZipFileSystem * works fine for varying sizes of the zip file entries - * @bug 8190753 8011146 + * @bug 8190753 8011146 8279536 * @run testng/timeout=300 ZipFSOutputStreamTest */ public class ZipFSOutputStreamTest { @@ -87,7 +87,9 @@ public class ZipFSOutputStreamTest { @Test(dataProvider = "zipFSCreationEnv") public void testOutputStream(final Map env) throws Exception { final byte[] chunk = new byte[1024]; - new Random().nextBytes(chunk); + // fill it with some fixed content (the fixed content will later on help ease + // the verification of the content written out) + Arrays.fill(chunk, (byte) 42); try (final FileSystem zipfs = FileSystems.newFileSystem(ZIP_FILE, env)) { // create the zip with varying sized entries for (final Map.Entry entry : ZIP_ENTRIES.entrySet()) { @@ -95,9 +97,12 @@ public class ZipFSOutputStreamTest { if (entryPath.getParent() != null) { Files.createDirectories(entryPath.getParent()); } + long start = System.currentTimeMillis(); try (final OutputStream os = Files.newOutputStream(entryPath)) { writeAsChunks(os, chunk, entry.getValue()); } + System.out.println("Wrote entry " + entryPath + " of bytes " + entry.getValue() + + " in " + (System.currentTimeMillis() - start) + " milli seconds"); } } // now verify the written content @@ -108,15 +113,15 @@ public class ZipFSOutputStreamTest { final byte[] buf = new byte[chunk.length]; int numRead; long totalRead = 0; + long start = System.currentTimeMillis(); while ((numRead = is.read(buf)) != -1) { totalRead += numRead; // verify the content - for (int i = 0, chunkoffset = (int) ((totalRead - numRead) % chunk.length); - i < numRead; i++, chunkoffset++) { - Assert.assertEquals(buf[i], chunk[chunkoffset % chunk.length], - "Unexpected content in " + entryPath); - } + Assert.assertEquals(Arrays.mismatch(buf, chunk), -1, + "Unexpected content in " + entryPath); } + System.out.println("Read entry " + entryPath + " of bytes " + totalRead + + " in " + (System.currentTimeMillis() - start) + " milli seconds"); Assert.assertEquals(totalRead, (long) entry.getValue(), "Unexpected number of bytes read from zip entry " + entryPath); } -- GitLab From f54ce84474c2ced340c92564814fa5c221415944 Mon Sep 17 00:00:00 2001 From: Harold Seigel Date: Wed, 12 Jan 2022 13:11:16 +0000 Subject: [PATCH 086/564] 8238161: use os::fopen in HS code where possible Reviewed-by: mbaesken, coleenp --- src/hotspot/cpu/ppc/vm_version_ppc.cpp | 4 +-- src/hotspot/os/aix/os_perf_aix.cpp | 6 ++-- .../os/linux/cgroupSubsystem_linux.cpp | 8 +++--- .../os/linux/cgroupSubsystem_linux.hpp | 4 +-- src/hotspot/os/linux/decoder_linux.cpp | 4 +-- .../os/linux/gc/z/zMountPoint_linux.cpp | 5 ++-- .../gc/z/zPhysicalMemoryBacking_linux.cpp | 4 +-- src/hotspot/os/linux/os_linux.cpp | 28 +++++++++---------- src/hotspot/os/linux/os_perf_linux.cpp | 10 +++---- .../vm_version_linux_aarch64.cpp | 4 +-- src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp | 4 +-- src/hotspot/share/c1/c1_Compilation.cpp | 6 ++-- src/hotspot/share/ci/ciReplay.cpp | 4 +-- src/hotspot/share/compiler/compileBroker.cpp | 4 +-- src/hotspot/share/compiler/compilerOracle.cpp | 4 +-- src/hotspot/share/compiler/disassembler.cpp | 4 +-- .../share/runtime/abstract_vm_version.cpp | 2 +- src/hotspot/share/runtime/arguments.cpp | 4 +-- src/hotspot/share/utilities/elfFile.cpp | 4 +-- src/hotspot/share/utilities/ostream.cpp | 4 +-- 20 files changed, 59 insertions(+), 58 deletions(-) diff --git a/src/hotspot/cpu/ppc/vm_version_ppc.cpp b/src/hotspot/cpu/ppc/vm_version_ppc.cpp index 96709b7196b..e8138643a1f 100644 --- a/src/hotspot/cpu/ppc/vm_version_ppc.cpp +++ b/src/hotspot/cpu/ppc/vm_version_ppc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2020 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -435,7 +435,7 @@ void VM_Version::check_virtualizations() { // system_type=...qemu indicates PowerKVM // e.g. system_type=IBM pSeries (emulated by qemu) char line[500]; - FILE* fp = fopen(info_file, "r"); + FILE* fp = os::fopen(info_file, "r"); if (fp == NULL) { return; } diff --git a/src/hotspot/os/aix/os_perf_aix.cpp b/src/hotspot/os/aix/os_perf_aix.cpp index ccdf013766e..bdccca0c1c5 100644 --- a/src/hotspot/os/aix/os_perf_aix.cpp +++ b/src/hotspot/os/aix/os_perf_aix.cpp @@ -239,7 +239,7 @@ static int SCANF_ARGS(2, 0) vread_statdata(const char* procfile, _SCANFMT_ const int n; char buf[2048]; - if ((f = fopen(procfile, "r")) == NULL) { + if ((f = os::fopen(procfile, "r")) == NULL) { return -1; } @@ -662,7 +662,7 @@ void SystemProcessInterface::SystemProcesses::ProcessIterator::get_exe_name() { jio_snprintf(buffer, PATH_MAX, "/proc/%s/stat", _entry->d_name); buffer[PATH_MAX - 1] = '\0'; - if ((fp = fopen(buffer, "r")) != NULL) { + if ((fp = os::fopen(buffer, "r")) != NULL) { if (fgets(buffer, PATH_MAX, fp) != NULL) { char* start, *end; // exe-name is between the first pair of ( and ) @@ -690,7 +690,7 @@ char* SystemProcessInterface::SystemProcesses::ProcessIterator::get_cmdline() { jio_snprintf(buffer, PATH_MAX, "/proc/%s/cmdline", _entry->d_name); buffer[PATH_MAX - 1] = '\0'; - if ((fp = fopen(buffer, "r")) != NULL) { + if ((fp = os::fopen(buffer, "r")) != NULL) { size_t size = 0; char dummy; diff --git a/src/hotspot/os/linux/cgroupSubsystem_linux.cpp b/src/hotspot/os/linux/cgroupSubsystem_linux.cpp index 1593a701e67..dd858a30e4c 100644 --- a/src/hotspot/os/linux/cgroupSubsystem_linux.cpp +++ b/src/hotspot/os/linux/cgroupSubsystem_linux.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, 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 @@ -146,7 +146,7 @@ bool CgroupSubsystemFactory::determine_type(CgroupInfo* cg_infos, * Conversely, for cgroups v2 (unified hierarchy), cpu, cpuacct, cpuset, memory * controllers must have hierarchy ID 0 and the unified controller mounted. */ - cgroups = fopen(proc_cgroups, "r"); + cgroups = os::fopen(proc_cgroups, "r"); if (cgroups == NULL) { log_debug(os, container)("Can't open %s, %s", proc_cgroups, os::strerror(errno)); *flags = INVALID_CGROUPS_GENERIC; @@ -214,7 +214,7 @@ bool CgroupSubsystemFactory::determine_type(CgroupInfo* cg_infos, * - on a cgroups v1 system, collect info for mapping * the host mount point to the local one via /proc/self/mountinfo below. */ - cgroup = fopen(proc_self_cgroup, "r"); + cgroup = os::fopen(proc_self_cgroup, "r"); if (cgroup == NULL) { log_debug(os, container)("Can't open %s, %s", proc_self_cgroup, os::strerror(errno)); @@ -269,7 +269,7 @@ bool CgroupSubsystemFactory::determine_type(CgroupInfo* cg_infos, // Find various mount points by reading /proc/self/mountinfo // mountinfo format is documented at https://www.kernel.org/doc/Documentation/filesystems/proc.txt - mntinfo = fopen(proc_self_mountinfo, "r"); + mntinfo = os::fopen(proc_self_mountinfo, "r"); if (mntinfo == NULL) { log_debug(os, container)("Can't open %s, %s", proc_self_mountinfo, os::strerror(errno)); diff --git a/src/hotspot/os/linux/cgroupSubsystem_linux.hpp b/src/hotspot/os/linux/cgroupSubsystem_linux.hpp index 75462971449..644d8adf00a 100644 --- a/src/hotspot/os/linux/cgroupSubsystem_linux.hpp +++ b/src/hotspot/os/linux/cgroupSubsystem_linux.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, 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 @@ -108,7 +108,7 @@ template int subsystem_file_line_contents(CgroupController* c, } strncat(file, filename, MAXPATHLEN-filelen); log_trace(os, container)("Path to %s is %s", filename, file); - fp = fopen(file, "r"); + fp = os::fopen(file, "r"); if (fp != NULL) { int err = 0; while ((p = fgets(buf, MAXPATHLEN, fp)) != NULL) { diff --git a/src/hotspot/os/linux/decoder_linux.cpp b/src/hotspot/os/linux/decoder_linux.cpp index daa12ec6f6d..0fc0daf98e7 100644 --- a/src/hotspot/os/linux/decoder_linux.cpp +++ b/src/hotspot/os/linux/decoder_linux.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -58,7 +58,7 @@ bool ElfDecoder::demangle(const char* symbol, char *buf, int buflen) { bool ElfFile::specifies_noexecstack(const char* filepath) { if (filepath == NULL) return true; - FILE* file = fopen(filepath, "r"); + FILE* file = os::fopen(filepath, "r"); if (file == NULL) return true; // AARCH64 defaults to noexecstack. All others default to execstack. diff --git a/src/hotspot/os/linux/gc/z/zMountPoint_linux.cpp b/src/hotspot/os/linux/gc/z/zMountPoint_linux.cpp index d3c5ef3fd7d..b0fa227ef7c 100644 --- a/src/hotspot/os/linux/gc/z/zMountPoint_linux.cpp +++ b/src/hotspot/os/linux/gc/z/zMountPoint_linux.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ #include "gc/z/zErrno.hpp" #include "gc/z/zMountPoint_linux.hpp" #include "runtime/globals.hpp" +#include "runtime/os.hpp" #include #include @@ -70,7 +71,7 @@ char* ZMountPoint::get_mountpoint(const char* line, const char* filesystem) cons } void ZMountPoint::get_mountpoints(const char* filesystem, ZArray* mountpoints) const { - FILE* fd = fopen(PROC_SELF_MOUNTINFO, "r"); + FILE* fd = os::fopen(PROC_SELF_MOUNTINFO, "r"); if (fd == NULL) { ZErrno err; log_error_p(gc)("Failed to open %s: %s", PROC_SELF_MOUNTINFO, err.to_string()); diff --git a/src/hotspot/os/linux/gc/z/zPhysicalMemoryBacking_linux.cpp b/src/hotspot/os/linux/gc/z/zPhysicalMemoryBacking_linux.cpp index 951b98d6cce..b434acc3215 100644 --- a/src/hotspot/os/linux/gc/z/zPhysicalMemoryBacking_linux.cpp +++ b/src/hotspot/os/linux/gc/z/zPhysicalMemoryBacking_linux.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, 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 @@ -329,7 +329,7 @@ void ZPhysicalMemoryBacking::warn_available_space(size_t max_capacity) const { void ZPhysicalMemoryBacking::warn_max_map_count(size_t max_capacity) const { const char* const filename = ZFILENAME_PROC_MAX_MAP_COUNT; - FILE* const file = fopen(filename, "r"); + FILE* const file = os::fopen(filename, "r"); if (file == NULL) { // Failed to open file, skip check log_debug_p(gc, init)("Failed to open %s", filename); diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index cd0fd06f4e1..2ebdfa0a832 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2022, 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 @@ -258,7 +258,7 @@ bool os::Linux::get_tick_information(CPUPerfTicks* pticks, int which_logical_cpu memset(pticks, 0, sizeof(CPUPerfTicks)); - if ((fh = fopen("/proc/stat", "r")) == NULL) { + if ((fh = os::fopen("/proc/stat", "r")) == NULL) { return false; } @@ -352,7 +352,7 @@ void os::Linux::initialize_system_info() { pid_t pid = os::Linux::gettid(); char fname[32]; jio_snprintf(fname, sizeof(fname), "/proc/%d", pid); - FILE *fp = fopen(fname, "r"); + FILE *fp = os::fopen(fname, "r"); if (fp == NULL) { unsafe_chroot_detected = true; } else { @@ -1027,7 +1027,7 @@ bool os::is_primordial_thread(void) { // Find the virtual memory area that contains addr static bool find_vma(address addr, address* vma_low, address* vma_high) { - FILE *fp = fopen("/proc/self/maps", "r"); + FILE *fp = os::fopen("/proc/self/maps", "r"); if (fp) { address low, high; while (!feof(fp)) { @@ -1139,7 +1139,7 @@ void os::Linux::capture_initial_stack(size_t max_size) { char stat[2048]; int statlen; - fp = fopen("/proc/self/stat", "r"); + fp = os::fopen("/proc/self/stat", "r"); if (fp) { statlen = fread(stat, 1, 2047, fp); stat[statlen] = '\0'; @@ -2004,7 +2004,7 @@ static void parse_os_info_helper(FILE* fp, char* distro, size_t length, bool get } static void parse_os_info(char* distro, size_t length, const char* file) { - FILE* fp = fopen(file, "r"); + FILE* fp = os::fopen(file, "r"); if (fp != NULL) { // if suse format, print out first line bool get_first_line = (strcmp(file, "/etc/SuSE-release") == 0); @@ -2065,7 +2065,7 @@ void os::Linux::print_system_memory_info(outputStream* st) { } bool os::Linux::query_process_memory_info(os::Linux::meminfo_t* info) { - FILE* f = ::fopen("/proc/self/status", "r"); + FILE* f = os::fopen("/proc/self/status", "r"); const int num_values = sizeof(os::Linux::meminfo_t) / sizeof(size_t); int num_found = 0; char buf[256]; @@ -2312,7 +2312,7 @@ void os::print_memory_info(outputStream* st) { static bool print_model_name_and_flags(outputStream* st, char* buf, size_t buflen) { #if defined(IA32) || defined(AMD64) // Other platforms have less repetitive cpuinfo files - FILE *fp = fopen("/proc/cpuinfo", "r"); + FILE *fp = os::fopen("/proc/cpuinfo", "r"); if (fp) { bool model_name_printed = false; while (!feof(fp)) { @@ -2416,7 +2416,7 @@ const char* search_string = "Processor"; // Parses the cpuinfo file for string representing the model name. void os::get_summary_cpu_info(char* cpuinfo, size_t length) { - FILE* fp = fopen("/proc/cpuinfo", "r"); + FILE* fp = os::fopen("/proc/cpuinfo", "r"); if (fp != NULL) { while (!feof(fp)) { char buf[256]; @@ -3551,7 +3551,7 @@ static void set_coredump_filter(CoredumpFilterBit bit) { FILE *f; long cdm; - if ((f = fopen("/proc/self/coredump_filter", "r+")) == NULL) { + if ((f = os::fopen("/proc/self/coredump_filter", "r+")) == NULL) { return; } @@ -3590,7 +3590,7 @@ static size_t scan_default_large_page_size() { // If we can't determine the value (e.g. /proc is not mounted, or the text // format has been changed), we'll set largest page size to 0 - FILE *fp = fopen("/proc/meminfo", "r"); + FILE *fp = os::fopen("/proc/meminfo", "r"); if (fp) { while (!feof(fp)) { int x = 0; @@ -4268,7 +4268,7 @@ int os::Linux::get_namespace_pid(int vmid) { int retpid = -1; snprintf(fname, sizeof(fname), "/proc/%d/status", vmid); - FILE *fp = fopen(fname, "r"); + FILE *fp = os::fopen(fname, "r"); if (fp) { int pid, nspid; @@ -5077,7 +5077,7 @@ static jlong slow_thread_cpu_time(Thread *thread, bool user_sys_cpu_time) { FILE *fp; snprintf(proc_name, 64, "/proc/self/task/%d/stat", tid); - fp = fopen(proc_name, "r"); + fp = os::fopen(proc_name, "r"); if (fp == NULL) return -1; statlen = fread(stat, 1, 2047, fp); stat[statlen] = '\0'; @@ -5382,7 +5382,7 @@ bool os::supports_map_sync() { void os::print_memory_mappings(char* addr, size_t bytes, outputStream* st) { unsigned long long start = (unsigned long long)addr; unsigned long long end = start + bytes; - FILE* f = ::fopen("/proc/self/maps", "r"); + FILE* f = os::fopen("/proc/self/maps", "r"); int num_found = 0; if (f != NULL) { st->print("Range [%llx-%llx) contains: ", start, end); diff --git a/src/hotspot/os/linux/os_perf_linux.cpp b/src/hotspot/os/linux/os_perf_linux.cpp index 4f8e411d47b..8d244887d4b 100644 --- a/src/hotspot/os/linux/os_perf_linux.cpp +++ b/src/hotspot/os/linux/os_perf_linux.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022, 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 @@ -234,7 +234,7 @@ static int SCANF_ARGS(2, 0) vread_statdata(const char* procfile, _SCANFMT_ const int n; char buf[2048]; - if ((f = fopen(procfile, "r")) == NULL) { + if ((f = os::fopen(procfile, "r")) == NULL) { return -1; } @@ -271,7 +271,7 @@ static int SCANF_ARGS(2, 3) read_statdata(const char* procfile, _SCANFMT_ const static FILE* open_statfile(void) { FILE *f; - if ((f = fopen("/proc/stat", "r")) == NULL) { + if ((f = os::fopen("/proc/stat", "r")) == NULL) { static int haveWarned = 0; if (!haveWarned) { haveWarned = 1; @@ -722,7 +722,7 @@ void SystemProcessInterface::SystemProcesses::ProcessIterator::get_exe_name() { jio_snprintf(buffer, PATH_MAX, "/proc/%s/stat", _entry->d_name); buffer[PATH_MAX - 1] = '\0'; - if ((fp = fopen(buffer, "r")) != NULL) { + if ((fp = os::fopen(buffer, "r")) != NULL) { if (fgets(buffer, PATH_MAX, fp) != NULL) { char* start, *end; // exe-name is between the first pair of ( and ) @@ -750,7 +750,7 @@ char* SystemProcessInterface::SystemProcesses::ProcessIterator::get_cmdline() { jio_snprintf(buffer, PATH_MAX, "/proc/%s/cmdline", _entry->d_name); buffer[PATH_MAX - 1] = '\0'; - if ((fp = fopen(buffer, "r")) != NULL) { + if ((fp = os::fopen(buffer, "r")) != NULL) { size_t size = 0; char dummy; diff --git a/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp b/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp index 3497ae2ce73..a23c88518b0 100644 --- a/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp +++ b/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -143,7 +143,7 @@ void VM_Version::get_os_cpu_info() { _zva_length = 4 << (dczid_el0 & 0xf); } - if (FILE *f = fopen("/proc/cpuinfo", "r")) { + if (FILE *f = os::fopen("/proc/cpuinfo", "r")) { // need a large buffer as the flags line may include lots of text char buf[1024], *p; while (fgets(buf, sizeof (buf), f) != NULL) { diff --git a/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp b/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp index cc71b0d2780..5e346efee54 100644 --- a/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp +++ b/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2022, 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 @@ -462,7 +462,7 @@ juint os::cpu_microcode_revision() { juint result = 0; char data[2048] = {0}; // lines should fit in 2K buf size_t len = sizeof(data); - FILE *fp = fopen("/proc/cpuinfo", "r"); + FILE *fp = os::fopen("/proc/cpuinfo", "r"); if (fp) { while (!feof(fp)) { if (fgets(data, len, fp)) { diff --git a/src/hotspot/share/c1/c1_Compilation.cpp b/src/hotspot/share/c1/c1_Compilation.cpp index df4b6bbed54..27c20a9c5fe 100644 --- a/src/hotspot/share/c1/c1_Compilation.cpp +++ b/src/hotspot/share/c1/c1_Compilation.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2022, 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 @@ -703,7 +703,7 @@ void Compilation::print_timers() { #ifndef PRODUCT void Compilation::compile_only_this_method() { ResourceMark rm; - fileStream stream(fopen("c1_compile_only", "wt")); + fileStream stream(os::fopen("c1_compile_only", "wt")); stream.print_cr("# c1 compile only directives"); compile_only_this_scope(&stream, hir()->top_scope()); } @@ -717,7 +717,7 @@ void Compilation::compile_only_this_scope(outputStream* st, IRScope* scope) { } void Compilation::exclude_this_method() { - fileStream stream(fopen(".hotspot_compiler", "at")); + fileStream stream(os::fopen(".hotspot_compiler", "at")); stream.print("exclude "); method()->holder()->name()->print_symbol_on(&stream); stream.print(" "); diff --git a/src/hotspot/share/ci/ciReplay.cpp b/src/hotspot/share/ci/ciReplay.cpp index e630278e649..a2a249f157a 100644 --- a/src/hotspot/share/ci/ciReplay.cpp +++ b/src/hotspot/share/ci/ciReplay.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -145,7 +145,7 @@ class CompileReplay : public StackObj { _protection_domain = Handle(); _protection_domain_initialized = false; - _stream = fopen(filename, "rt"); + _stream = os::fopen(filename, "rt"); if (_stream == NULL) { fprintf(stderr, "ERROR: Can't open replay file %s\n", filename); } diff --git a/src/hotspot/share/compiler/compileBroker.cpp b/src/hotspot/share/compiler/compileBroker.cpp index eab2751c3b0..e3beed13662 100644 --- a/src/hotspot/share/compiler/compileBroker.cpp +++ b/src/hotspot/share/compiler/compileBroker.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2022, 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 @@ -2003,7 +2003,7 @@ void CompileBroker::init_compiler_thread_log() { os::file_separator(), thread_id, os::current_process_id()); } - fp = fopen(file_name, "wt"); + fp = os::fopen(file_name, "wt"); if (fp != NULL) { if (LogCompilation && Verbose) { tty->print_cr("Opening compilation log %s", file_name); diff --git a/src/hotspot/share/compiler/compilerOracle.cpp b/src/hotspot/share/compiler/compilerOracle.cpp index 8464d22ef42..7d58a28d272 100644 --- a/src/hotspot/share/compiler/compilerOracle.cpp +++ b/src/hotspot/share/compiler/compilerOracle.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2022, 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 @@ -932,7 +932,7 @@ bool CompilerOracle::_quiet = false; void CompilerOracle::parse_from_file() { assert(has_command_file(), "command file must be specified"); - FILE* stream = fopen(cc_file(), "rt"); + FILE* stream = os::fopen(cc_file(), "rt"); if (stream == NULL) return; char token[1024]; diff --git a/src/hotspot/share/compiler/disassembler.cpp b/src/hotspot/share/compiler/disassembler.cpp index 54cea9cc281..1beb75441cd 100644 --- a/src/hotspot/share/compiler/disassembler.cpp +++ b/src/hotspot/share/compiler/disassembler.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2022, 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 @@ -267,7 +267,7 @@ void decode_env::print_hook_comments(address pc, bool newline) { _cached_src_lines = new (ResourceObj::C_HEAP, mtCode)GrowableArray(0, mtCode); } - if ((fp = fopen(file, "r")) == NULL) { + if ((fp = os::fopen(file, "r")) == NULL) { _cached_src = NULL; return; } diff --git a/src/hotspot/share/runtime/abstract_vm_version.cpp b/src/hotspot/share/runtime/abstract_vm_version.cpp index 5bb7cb80a28..bcde237bad7 100644 --- a/src/hotspot/share/runtime/abstract_vm_version.cpp +++ b/src/hotspot/share/runtime/abstract_vm_version.cpp @@ -318,7 +318,7 @@ void Abstract_VM_Version::insert_features_names(char* buf, size_t buflen, const bool Abstract_VM_Version::print_matching_lines_from_file(const char* filename, outputStream* st, const char* keywords_to_match[]) { char line[500]; - FILE* fp = fopen(filename, "r"); + FILE* fp = os::fopen(filename, "r"); if (fp == NULL) { return false; } diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index addff98a3ea..ddbf1f3f794 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -1244,7 +1244,7 @@ bool Arguments::process_argument(const char* arg, } bool Arguments::process_settings_file(const char* file_name, bool should_exist, jboolean ignore_unrecognized) { - FILE* stream = fopen(file_name, "rb"); + FILE* stream = os::fopen(file_name, "rb"); if (stream == NULL) { if (should_exist) { jio_fprintf(defaultStream::error_stream(), diff --git a/src/hotspot/share/utilities/elfFile.cpp b/src/hotspot/share/utilities/elfFile.cpp index 1e2a6a5279f..2198d2943c1 100644 --- a/src/hotspot/share/utilities/elfFile.cpp +++ b/src/hotspot/share/utilities/elfFile.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -168,7 +168,7 @@ void ElfFile::cleanup_tables() { NullDecoder::decoder_status ElfFile::parse_elf(const char* filepath) { assert(filepath, "null file path"); - _file = fopen(filepath, "r"); + _file = os::fopen(filepath, "r"); if (_file != NULL) { return load_tables(); } else { diff --git a/src/hotspot/share/utilities/ostream.cpp b/src/hotspot/share/utilities/ostream.cpp index 6b3a9465d0c..323691cf6d6 100644 --- a/src/hotspot/share/utilities/ostream.cpp +++ b/src/hotspot/share/utilities/ostream.cpp @@ -545,7 +545,7 @@ const char* make_log_name(const char* log_name, const char* force_directory) { } fileStream::fileStream(const char* file_name) { - _file = fopen(file_name, "w"); + _file = os::fopen(file_name, "w"); if (_file != NULL) { _need_close = true; } else { @@ -555,7 +555,7 @@ fileStream::fileStream(const char* file_name) { } fileStream::fileStream(const char* file_name, const char* opentype) { - _file = fopen(file_name, opentype); + _file = os::fopen(file_name, opentype); if (_file != NULL) { _need_close = true; } else { -- GitLab From 8fed8ab29cae4f189f44609c23f116967eef6bdf Mon Sep 17 00:00:00 2001 From: Roman Kennke Date: Wed, 12 Jan 2022 13:47:25 +0000 Subject: [PATCH 087/564] 8278065: Refactor subclassAudits to use ClassValue Reviewed-by: rriggs, plevart --- .../classes/java/io/ObjectInputStream.java | 27 +++----- .../classes/java/io/ObjectOutputStream.java | 26 +++----- .../classes/java/io/ObjectStreamClass.java | 66 ------------------- 3 files changed, 16 insertions(+), 103 deletions(-) diff --git a/src/java.base/share/classes/java/io/ObjectInputStream.java b/src/java.base/share/classes/java/io/ObjectInputStream.java index de339627d5b..8fdc3ac8d51 100644 --- a/src/java.base/share/classes/java/io/ObjectInputStream.java +++ b/src/java.base/share/classes/java/io/ObjectInputStream.java @@ -26,11 +26,9 @@ package java.io; import java.io.ObjectInputFilter.Config; -import java.io.ObjectStreamClass.WeakClassKey; import java.io.ObjectStreamClass.RecordSupport; import java.lang.System.Logger; import java.lang.invoke.MethodHandle; -import java.lang.ref.ReferenceQueue; import java.lang.reflect.Array; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Modifier; @@ -43,10 +41,6 @@ import java.security.PrivilegedExceptionAction; import java.util.Arrays; import java.util.Map; import java.util.Objects; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -import static java.io.ObjectStreamClass.processQueue; import jdk.internal.access.SharedSecrets; import jdk.internal.event.DeserializationEvent; @@ -282,12 +276,13 @@ public class ObjectInputStream private static class Caches { /** cache of subclass security audit results */ - static final ConcurrentMap subclassAudits = - new ConcurrentHashMap<>(); - - /** queue for WeakReferences to audited subclasses */ - static final ReferenceQueue> subclassAuditsQueue = - new ReferenceQueue<>(); + static final ClassValue subclassAudits = + new ClassValue<>() { + @Override + protected Boolean computeValue(Class type) { + return auditSubclass(type); + } + }; /** * Property to permit setting a filter after objects @@ -1638,13 +1633,7 @@ public class ObjectInputStream if (sm == null) { return; } - processQueue(Caches.subclassAuditsQueue, Caches.subclassAudits); - WeakClassKey key = new WeakClassKey(cl, Caches.subclassAuditsQueue); - Boolean result = Caches.subclassAudits.get(key); - if (result == null) { - result = auditSubclass(cl); - Caches.subclassAudits.putIfAbsent(key, result); - } + boolean result = Caches.subclassAudits.get(cl); if (!result) { sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION); } diff --git a/src/java.base/share/classes/java/io/ObjectOutputStream.java b/src/java.base/share/classes/java/io/ObjectOutputStream.java index 2a4d455c3a0..811ef3bcc20 100644 --- a/src/java.base/share/classes/java/io/ObjectOutputStream.java +++ b/src/java.base/share/classes/java/io/ObjectOutputStream.java @@ -25,8 +25,6 @@ package java.io; -import java.io.ObjectStreamClass.WeakClassKey; -import java.lang.ref.ReferenceQueue; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.ArrayList; @@ -34,9 +32,6 @@ import java.util.Arrays; import java.util.List; import java.util.Objects; import java.util.StringJoiner; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import static java.io.ObjectStreamClass.processQueue; import sun.reflect.misc.ReflectUtil; /** @@ -177,12 +172,13 @@ public class ObjectOutputStream private static class Caches { /** cache of subclass security audit results */ - static final ConcurrentMap subclassAudits = - new ConcurrentHashMap<>(); - - /** queue for WeakReferences to audited subclasses */ - static final ReferenceQueue> subclassAuditsQueue = - new ReferenceQueue<>(); + static final ClassValue subclassAudits = + new ClassValue<>() { + @Override + protected Boolean computeValue(Class type) { + return auditSubclass(type); + } + }; } /** filter stream for handling block data conversion */ @@ -1065,13 +1061,7 @@ public class ObjectOutputStream if (sm == null) { return; } - processQueue(Caches.subclassAuditsQueue, Caches.subclassAudits); - WeakClassKey key = new WeakClassKey(cl, Caches.subclassAuditsQueue); - Boolean result = Caches.subclassAudits.get(key); - if (result == null) { - result = auditSubclass(cl); - Caches.subclassAudits.putIfAbsent(key, result); - } + boolean result = Caches.subclassAudits.get(cl); if (!result) { sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION); } diff --git a/src/java.base/share/classes/java/io/ObjectStreamClass.java b/src/java.base/share/classes/java/io/ObjectStreamClass.java index 343499863f0..86ed2b839d1 100644 --- a/src/java.base/share/classes/java/io/ObjectStreamClass.java +++ b/src/java.base/share/classes/java/io/ObjectStreamClass.java @@ -28,9 +28,6 @@ package java.io; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; -import java.lang.ref.Reference; -import java.lang.ref.ReferenceQueue; -import java.lang.ref.WeakReference; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; @@ -58,7 +55,6 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; import jdk.internal.misc.Unsafe; import jdk.internal.reflect.CallerSensitive; import jdk.internal.reflect.Reflection; @@ -2227,68 +2223,6 @@ public class ObjectStreamClass implements Serializable { return matches; } - /** - * Removes from the specified map any keys that have been enqueued - * on the specified reference queue. - */ - static void processQueue(ReferenceQueue> queue, - ConcurrentMap>, ?> map) - { - Reference> ref; - while((ref = queue.poll()) != null) { - map.remove(ref); - } - } - - /** - * Weak key for Class objects. - * - **/ - static class WeakClassKey extends WeakReference> { - /** - * saved value of the referent's identity hash code, to maintain - * a consistent hash code after the referent has been cleared - */ - private final int hash; - - /** - * Create a new WeakClassKey to the given object, registered - * with a queue. - */ - WeakClassKey(Class cl, ReferenceQueue> refQueue) { - super(cl, refQueue); - hash = System.identityHashCode(cl); - } - - /** - * Returns the identity hash code of the original referent. - */ - public int hashCode() { - return hash; - } - - /** - * Returns true if the given object is this identical - * WeakClassKey instance, or, if this object's referent has not - * been cleared, if the given object is another WeakClassKey - * instance with the identical non-null referent as this one. - */ - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - - if (obj instanceof WeakClassKey) { - Class referent = get(); - return (referent != null) && - (((WeakClassKey) obj).refersTo(referent)); - } else { - return false; - } - } - } - /** * A LRA cache of record deserialization constructors. */ -- GitLab From ddddec7d74745905230282124524a0dbdd1bd1c1 Mon Sep 17 00:00:00 2001 From: Patric Hedlin Date: Wed, 12 Jan 2022 15:30:54 +0000 Subject: [PATCH 088/564] 8274243: Implement fast-path for ASCII-compatible CharsetEncoders on aarch64 Reviewed-by: neliasso, redestad --- src/hotspot/cpu/aarch64/aarch64.ad | 48 +++- src/hotspot/cpu/aarch64/assembler_aarch64.hpp | 6 + .../cpu/aarch64/macroAssembler_aarch64.cpp | 225 +++++++++--------- .../cpu/aarch64/macroAssembler_aarch64.hpp | 13 +- src/hotspot/cpu/aarch64/matcher_aarch64.hpp | 2 +- .../bench/java/nio/CharsetEncodeDecode.java | 2 +- 6 files changed, 166 insertions(+), 130 deletions(-) diff --git a/src/hotspot/cpu/aarch64/aarch64.ad b/src/hotspot/cpu/aarch64/aarch64.ad index 75af9ed04b2..b82ee59b99c 100644 --- a/src/hotspot/cpu/aarch64/aarch64.ad +++ b/src/hotspot/cpu/aarch64/aarch64.ad @@ -17018,16 +17018,17 @@ instruct string_compress(iRegP_R2 src, iRegP_R1 dst, iRegI_R3 len, iRegI_R0 result, rFlagsReg cr) %{ match(Set result (StrCompressedCopy src (Binary dst len))); - effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, USE_KILL src, USE_KILL dst, USE_KILL len, KILL cr); + effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, + USE_KILL src, USE_KILL dst, USE len, KILL cr); - format %{ "String Compress $src,$dst -> $result // KILL R1, R2, R3, R4" %} + format %{ "String Compress $src,$dst,$len -> $result // KILL $src,$dst" %} ins_encode %{ __ char_array_compress($src$$Register, $dst$$Register, $len$$Register, + $result$$Register, $tmp1$$FloatRegister, $tmp2$$FloatRegister, - $tmp3$$FloatRegister, $tmp4$$FloatRegister, - $result$$Register); + $tmp3$$FloatRegister, $tmp4$$FloatRegister); %} - ins_pipe( pipe_slow ); + ins_pipe(pipe_slow); %} // fast byte[] to char[] inflation @@ -17052,22 +17053,43 @@ instruct string_inflate(Universe dummy, iRegP_R0 src, iRegP_R1 dst, iRegI_R2 len // encode char[] to byte[] in ISO_8859_1 instruct encode_iso_array(iRegP_R2 src, iRegP_R1 dst, iRegI_R3 len, - vRegD_V0 Vtmp1, vRegD_V1 Vtmp2, - vRegD_V2 Vtmp3, vRegD_V3 Vtmp4, + vRegD_V0 vtmp0, vRegD_V1 vtmp1, + vRegD_V2 vtmp2, vRegD_V3 vtmp3, iRegI_R0 result, rFlagsReg cr) %{ predicate(!((EncodeISOArrayNode*)n)->is_ascii()); match(Set result (EncodeISOArray src (Binary dst len))); - effect(USE_KILL src, USE_KILL dst, USE_KILL len, - KILL Vtmp1, KILL Vtmp2, KILL Vtmp3, KILL Vtmp4, KILL cr); + effect(USE_KILL src, USE_KILL dst, USE len, + KILL vtmp0, KILL vtmp1, KILL vtmp2, KILL vtmp3, KILL cr); - format %{ "Encode array $src,$dst,$len -> $result" %} + format %{ "Encode ISO array $src,$dst,$len -> $result" %} ins_encode %{ __ encode_iso_array($src$$Register, $dst$$Register, $len$$Register, - $result$$Register, $Vtmp1$$FloatRegister, $Vtmp2$$FloatRegister, - $Vtmp3$$FloatRegister, $Vtmp4$$FloatRegister); + $result$$Register, false, + $vtmp0$$FloatRegister, $vtmp1$$FloatRegister, + $vtmp2$$FloatRegister, $vtmp3$$FloatRegister); %} - ins_pipe( pipe_class_memory ); + ins_pipe(pipe_class_memory); +%} + +instruct encode_ascii_array(iRegP_R2 src, iRegP_R1 dst, iRegI_R3 len, + vRegD_V0 vtmp0, vRegD_V1 vtmp1, + vRegD_V2 vtmp2, vRegD_V3 vtmp3, + iRegI_R0 result, rFlagsReg cr) +%{ + predicate(((EncodeISOArrayNode*)n)->is_ascii()); + match(Set result (EncodeISOArray src (Binary dst len))); + effect(USE_KILL src, USE_KILL dst, USE len, + KILL vtmp0, KILL vtmp1, KILL vtmp2, KILL vtmp3, KILL cr); + + format %{ "Encode ASCII array $src,$dst,$len -> $result" %} + ins_encode %{ + __ encode_iso_array($src$$Register, $dst$$Register, $len$$Register, + $result$$Register, true, + $vtmp0$$FloatRegister, $vtmp1$$FloatRegister, + $vtmp2$$FloatRegister, $vtmp3$$FloatRegister); + %} + ins_pipe(pipe_class_memory); %} // ============================================================================ diff --git a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp index 95edeadbf18..fb4b7b87141 100644 --- a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp @@ -2424,6 +2424,12 @@ public: INSN(cnt, 0, 0b100000010110, 0); // accepted arrangements: T8B, T16B INSN(uaddlp, 1, 0b100000001010, 2); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S INSN(uaddlv, 1, 0b110000001110, 1); // accepted arrangements: T8B, T16B, T4H, T8H, T4S + // Zero compare. + INSN(cmeq, 0, 0b100000100110, 3); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S, T2D + INSN(cmge, 1, 0b100000100010, 3); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S, T2D + INSN(cmgt, 0, 0b100000100010, 3); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S, T2D + INSN(cmle, 1, 0b100000100110, 3); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S, T2D + INSN(cmlt, 0, 0b100000101010, 3); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S, T2D #undef INSN diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp index bcb5eb92a0b..cce3d497bbc 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp @@ -4923,111 +4923,118 @@ void MacroAssembler::fill_words(Register base, Register cnt, Register value) bind(fini); } -// Intrinsic for sun/nio/cs/ISO_8859_1$Encoder.implEncodeISOArray and -// java/lang/StringUTF16.compress. +// Intrinsic for +// +// - sun/nio/cs/ISO_8859_1$Encoder.implEncodeISOArray +// return the number of characters copied. +// - java/lang/StringUTF16.compress +// return zero (0) if copy fails, otherwise 'len'. +// +// This version always returns the number of characters copied, and does not +// clobber the 'len' register. A successful copy will complete with the post- +// condition: 'res' == 'len', while an unsuccessful copy will exit with the +// post-condition: 0 <= 'res' < 'len'. +// +// NOTE: Attempts to use 'ld2' (and 'umaxv' in the ISO part) has proven to +// degrade performance (on Ampere Altra - Neoverse N1), to an extent +// beyond the acceptable, even though the footprint would be smaller. +// Using 'umaxv' in the ASCII-case comes with a small penalty but does +// avoid additional bloat. +// void MacroAssembler::encode_iso_array(Register src, Register dst, - Register len, Register result, - FloatRegister Vtmp1, FloatRegister Vtmp2, - FloatRegister Vtmp3, FloatRegister Vtmp4) + Register len, Register res, bool ascii, + FloatRegister vtmp0, FloatRegister vtmp1, + FloatRegister vtmp2, FloatRegister vtmp3) { - Label DONE, SET_RESULT, NEXT_32, NEXT_32_PRFM, LOOP_8, NEXT_8, LOOP_1, NEXT_1, - NEXT_32_START, NEXT_32_PRFM_START; - Register tmp1 = rscratch1, tmp2 = rscratch2; - - mov(result, len); // Save initial len - - cmp(len, (u1)8); // handle shortest strings first - br(LT, LOOP_1); - cmp(len, (u1)32); - br(LT, NEXT_8); - // The following code uses the SIMD 'uzp1' and 'uzp2' instructions - // to convert chars to bytes - if (SoftwarePrefetchHintDistance >= 0) { - ld1(Vtmp1, Vtmp2, Vtmp3, Vtmp4, T8H, src); - subs(tmp2, len, SoftwarePrefetchHintDistance/2 + 16); - br(LE, NEXT_32_START); - b(NEXT_32_PRFM_START); - BIND(NEXT_32_PRFM); - ld1(Vtmp1, Vtmp2, Vtmp3, Vtmp4, T8H, src); - BIND(NEXT_32_PRFM_START); - prfm(Address(src, SoftwarePrefetchHintDistance)); - orr(v4, T16B, Vtmp1, Vtmp2); - orr(v5, T16B, Vtmp3, Vtmp4); - uzp1(Vtmp1, T16B, Vtmp1, Vtmp2); - uzp1(Vtmp3, T16B, Vtmp3, Vtmp4); - uzp2(v5, T16B, v4, v5); // high bytes - umov(tmp2, v5, D, 1); - fmovd(tmp1, v5); - orr(tmp1, tmp1, tmp2); - cbnz(tmp1, LOOP_8); - stpq(Vtmp1, Vtmp3, dst); - sub(len, len, 32); - add(dst, dst, 32); - add(src, src, 64); - subs(tmp2, len, SoftwarePrefetchHintDistance/2 + 16); - br(GE, NEXT_32_PRFM); - cmp(len, (u1)32); - br(LT, LOOP_8); - BIND(NEXT_32); - ld1(Vtmp1, Vtmp2, Vtmp3, Vtmp4, T8H, src); - BIND(NEXT_32_START); - } else { - BIND(NEXT_32); - ld1(Vtmp1, Vtmp2, Vtmp3, Vtmp4, T8H, src); - } - prfm(Address(src, SoftwarePrefetchHintDistance)); - uzp1(v4, T16B, Vtmp1, Vtmp2); - uzp1(v5, T16B, Vtmp3, Vtmp4); - orr(Vtmp1, T16B, Vtmp1, Vtmp2); - orr(Vtmp3, T16B, Vtmp3, Vtmp4); - uzp2(Vtmp1, T16B, Vtmp1, Vtmp3); // high bytes - umov(tmp2, Vtmp1, D, 1); - fmovd(tmp1, Vtmp1); - orr(tmp1, tmp1, tmp2); - cbnz(tmp1, LOOP_8); - stpq(v4, v5, dst); - sub(len, len, 32); - add(dst, dst, 32); - add(src, src, 64); - cmp(len, (u1)32); - br(GE, NEXT_32); - cbz(len, DONE); - - BIND(LOOP_8); - cmp(len, (u1)8); - br(LT, LOOP_1); - BIND(NEXT_8); - ld1(Vtmp1, T8H, src); - uzp1(Vtmp2, T16B, Vtmp1, Vtmp1); // low bytes - uzp2(Vtmp3, T16B, Vtmp1, Vtmp1); // high bytes - fmovd(tmp1, Vtmp3); - cbnz(tmp1, NEXT_1); - strd(Vtmp2, dst); - - sub(len, len, 8); - add(dst, dst, 8); - add(src, src, 16); - cmp(len, (u1)8); - br(GE, NEXT_8); - - BIND(LOOP_1); - - cbz(len, DONE); - BIND(NEXT_1); - ldrh(tmp1, Address(post(src, 2))); - tst(tmp1, 0xff00); - br(NE, SET_RESULT); - strb(tmp1, Address(post(dst, 1))); - subs(len, len, 1); - br(GT, NEXT_1); - - BIND(SET_RESULT); - sub(result, result, len); // Return index where we stopped - // Return len == 0 if we processed all - // characters - BIND(DONE); -} + Register cnt = res; + Register max = rscratch1; + Register chk = rscratch2; + + prfm(Address(src), PLDL1STRM); + movw(cnt, len); + +#define ASCII(insn) do { if (ascii) { insn; } } while (0) + Label LOOP_32, DONE_32, FAIL_32; + + BIND(LOOP_32); + { + cmpw(cnt, 32); + br(LT, DONE_32); + ld1(vtmp0, vtmp1, vtmp2, vtmp3, T8H, Address(post(src, 64))); + // Extract lower bytes. + FloatRegister vlo0 = v4; + FloatRegister vlo1 = v5; + uzp1(vlo0, T16B, vtmp0, vtmp1); + uzp1(vlo1, T16B, vtmp2, vtmp3); + // Merge bits... + orr(vtmp0, T16B, vtmp0, vtmp1); + orr(vtmp2, T16B, vtmp2, vtmp3); + // Extract merged upper bytes. + FloatRegister vhix = vtmp0; + uzp2(vhix, T16B, vtmp0, vtmp2); + // ISO-check on hi-parts (all zero). + // ASCII-check on lo-parts (no sign). + FloatRegister vlox = vtmp1; // Merge lower bytes. + ASCII(orr(vlox, T16B, vlo0, vlo1)); + umov(chk, vhix, D, 1); ASCII(cmlt(vlox, T16B, vlox)); + fmovd(max, vhix); ASCII(umaxv(vlox, T16B, vlox)); + orr(chk, chk, max); ASCII(umov(max, vlox, B, 0)); + ASCII(orr(chk, chk, max)); + cbnz(chk, FAIL_32); + subw(cnt, cnt, 32); + st1(vlo0, vlo1, T16B, Address(post(dst, 32))); + b(LOOP_32); + } + BIND(FAIL_32); + sub(src, src, 64); + BIND(DONE_32); + + Label LOOP_8, SKIP_8; + + BIND(LOOP_8); + { + cmpw(cnt, 8); + br(LT, SKIP_8); + FloatRegister vhi = vtmp0; + FloatRegister vlo = vtmp1; + ld1(vtmp3, T8H, src); + uzp1(vlo, T16B, vtmp3, vtmp3); + uzp2(vhi, T16B, vtmp3, vtmp3); + // ISO-check on hi-parts (all zero). + // ASCII-check on lo-parts (no sign). + ASCII(cmlt(vtmp2, T16B, vlo)); + fmovd(chk, vhi); ASCII(umaxv(vtmp2, T16B, vtmp2)); + ASCII(umov(max, vtmp2, B, 0)); + ASCII(orr(chk, chk, max)); + cbnz(chk, SKIP_8); + + strd(vlo, Address(post(dst, 8))); + subw(cnt, cnt, 8); + add(src, src, 16); + b(LOOP_8); + } + BIND(SKIP_8); + +#undef ASCII + + Label LOOP, DONE; + + cbz(cnt, DONE); + BIND(LOOP); + { + Register chr = rscratch1; + ldrh(chr, Address(post(src, 2))); + tst(chr, ascii ? 0xff80 : 0xff00); + br(NE, DONE); + strb(chr, Address(post(dst, 1))); + subs(cnt, cnt, 1); + br(GT, LOOP); + } + BIND(DONE); + // Return index where we stopped. + subw(res, len, cnt); +} // Inflate byte[] array to char[]. address MacroAssembler::byte_array_inflate(Register src, Register dst, Register len, @@ -5136,13 +5143,13 @@ address MacroAssembler::byte_array_inflate(Register src, Register dst, Register // Compress char[] array to byte[]. void MacroAssembler::char_array_compress(Register src, Register dst, Register len, - FloatRegister tmp1Reg, FloatRegister tmp2Reg, - FloatRegister tmp3Reg, FloatRegister tmp4Reg, - Register result) { - encode_iso_array(src, dst, len, result, - tmp1Reg, tmp2Reg, tmp3Reg, tmp4Reg); - cmp(len, zr); - csel(result, result, zr, EQ); + Register res, + FloatRegister tmp0, FloatRegister tmp1, + FloatRegister tmp2, FloatRegister tmp3) { + encode_iso_array(src, dst, len, res, false, tmp0, tmp1, tmp2, tmp3); + // Adjust result: res == len ? len : 0 + cmp(len, res); + csel(res, res, zr, EQ); } // get_thread() can be called anywhere inside generated code so we diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp index a9ebc8bdc69..8a2521f629c 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp @@ -1255,14 +1255,15 @@ public: FloatRegister vtmp3, Register tmp4); void char_array_compress(Register src, Register dst, Register len, - FloatRegister tmp1Reg, FloatRegister tmp2Reg, - FloatRegister tmp3Reg, FloatRegister tmp4Reg, - Register result); + Register res, + FloatRegister vtmp0, FloatRegister vtmp1, + FloatRegister vtmp2, FloatRegister vtmp3); void encode_iso_array(Register src, Register dst, - Register len, Register result, - FloatRegister Vtmp1, FloatRegister Vtmp2, - FloatRegister Vtmp3, FloatRegister Vtmp4); + Register len, Register res, bool ascii, + FloatRegister vtmp0, FloatRegister vtmp1, + FloatRegister vtmp2, FloatRegister vtmp3); + void fast_log(FloatRegister vtmp0, FloatRegister vtmp1, FloatRegister vtmp2, FloatRegister vtmp3, FloatRegister vtmp4, FloatRegister vtmp5, FloatRegister tmpC1, FloatRegister tmpC2, FloatRegister tmpC3, diff --git a/src/hotspot/cpu/aarch64/matcher_aarch64.hpp b/src/hotspot/cpu/aarch64/matcher_aarch64.hpp index f2f55e504ac..aca82240a57 100644 --- a/src/hotspot/cpu/aarch64/matcher_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/matcher_aarch64.hpp @@ -161,6 +161,6 @@ } // Implements a variant of EncodeISOArrayNode that encode ASCII only - static const bool supports_encode_ascii_array = false; + static const bool supports_encode_ascii_array = true; #endif // CPU_AARCH64_MATCHER_AARCH64_HPP diff --git a/test/micro/org/openjdk/bench/java/nio/CharsetEncodeDecode.java b/test/micro/org/openjdk/bench/java/nio/CharsetEncodeDecode.java index 6e129a5466e..404bb0583fd 100644 --- a/test/micro/org/openjdk/bench/java/nio/CharsetEncodeDecode.java +++ b/test/micro/org/openjdk/bench/java/nio/CharsetEncodeDecode.java @@ -61,7 +61,7 @@ public class CharsetEncodeDecode { private CharsetEncoder encoder; private CharsetDecoder decoder; - @Param({"UTF-8", "BIG5", "ISO-8859-15", "ASCII", "UTF-16"}) + @Param({"UTF-8", "BIG5", "ISO-8859-15", "ISO-8859-1", "ASCII", "UTF-16"}) private String type; @Param("16384") -- GitLab From 0a094d7c286ed0b5a35c517391e48c603cb43a68 Mon Sep 17 00:00:00 2001 From: Naoto Sato Date: Wed, 12 Jan 2022 19:17:18 +0000 Subject: [PATCH 089/564] 8268081: Upgrade Unicode Data Files to 14.0.0 Reviewed-by: joehw, iris, lancea --- make/data/unicodedata/Blocks.txt | 22 +- .../unicodedata/DerivedCoreProperties.txt | 700 +++++++++++---- make/data/unicodedata/NormalizationTest.txt | 849 ++++++++++-------- make/data/unicodedata/PropList.txt | 100 ++- .../data/unicodedata/PropertyValueAliases.txt | 26 +- make/data/unicodedata/ReadMe.txt | 16 + make/data/unicodedata/Scripts.txt | 213 +++-- make/data/unicodedata/SpecialCasing.txt | 6 +- make/data/unicodedata/UnicodeData.txt | 837 ++++++++++++++++- make/data/unicodedata/VERSION | 1 - .../auxiliary/GraphemeBreakProperty.txt | 33 +- .../auxiliary/GraphemeBreakTest.txt | 6 +- make/data/unicodedata/emoji/emoji-data.txt | 96 +- .../share/classes/java/lang/Character.java | 707 ++++++++++----- .../classes/java/util/regex/Grapheme.java | 13 +- .../jdk/internal/icu/impl/Punycode.java | 67 +- .../icu/impl/UnicodeSetStringSpan.java | 11 +- .../icu/impl/data/icudt67b/uprops.icu | Bin 135664 -> 0 bytes .../impl/data/{icudt67b => icudt70b}/nfc.nrm | Bin 35136 -> 35296 bytes .../impl/data/{icudt67b => icudt70b}/nfkc.nrm | Bin 54144 -> 54720 bytes .../data/{icudt67b => icudt70b}/ubidi.icu | Bin 26640 -> 27328 bytes .../icu/impl/data/icudt70b/uprops.icu | Bin 0 -> 138576 bytes .../jdk/internal/icu/lang/UCharacter.java | 8 +- .../icu/lang/UCharacterDirection.java | 4 +- .../internal/icu/lang/UCharacterEnums.java | 4 +- .../jdk/internal/icu/text/BidiBase.java | 12 +- .../jdk/internal/icu/text/BidiLine.java | 4 +- .../jdk/internal/icu/text/Normalizer2.java | 4 +- .../jdk/internal/icu/text/NormalizerBase.java | 4 +- .../jdk/internal/icu/text/StringPrep.java | 12 +- .../internal/icu/text/UCharacterIterator.java | 12 +- .../classes/jdk/internal/icu/text/UTF16.java | 47 +- .../jdk/internal/icu/text/UnicodeSet.java | 48 +- .../jdk/internal/icu/util/CodePointTrie.java | 4 +- .../jdk/internal/icu/util/VersionInfo.java | 14 +- src/java.base/share/legal/icu.md | 488 ++++++++-- src/java.base/share/legal/unicode.md | 55 +- .../UnicodeBlock/OptimalMapSize.java | 9 +- 38 files changed, 3342 insertions(+), 1090 deletions(-) create mode 100644 make/data/unicodedata/ReadMe.txt delete mode 100644 make/data/unicodedata/VERSION delete mode 100644 src/java.base/share/classes/jdk/internal/icu/impl/data/icudt67b/uprops.icu rename src/java.base/share/classes/jdk/internal/icu/impl/data/{icudt67b => icudt70b}/nfc.nrm (86%) rename src/java.base/share/classes/jdk/internal/icu/impl/data/{icudt67b => icudt70b}/nfkc.nrm (67%) rename src/java.base/share/classes/jdk/internal/icu/impl/data/{icudt67b => icudt70b}/ubidi.icu (63%) create mode 100644 src/java.base/share/classes/jdk/internal/icu/impl/data/icudt70b/uprops.icu diff --git a/make/data/unicodedata/Blocks.txt b/make/data/unicodedata/Blocks.txt index b20570e0676..d3c73191e76 100644 --- a/make/data/unicodedata/Blocks.txt +++ b/make/data/unicodedata/Blocks.txt @@ -1,6 +1,6 @@ -# Blocks-13.0.0.txt -# Date: 2019-07-10, 19:06:00 GMT [KW] -# Copyright (c) 2019 Unicode, Inc. +# Blocks-14.0.0.txt +# Date: 2021-01-22, 23:29:00 GMT [KW] +# Copyright (c) 2021 Unicode, Inc. # For terms of use, see http://www.unicode.org/terms_of_use.html # # Unicode Character Database @@ -52,6 +52,7 @@ 0800..083F; Samaritan 0840..085F; Mandaic 0860..086F; Syriac Supplement +0870..089F; Arabic Extended-B 08A0..08FF; Arabic Extended-A 0900..097F; Devanagari 0980..09FF; Bengali @@ -215,7 +216,9 @@ FFF0..FFFF; Specials 104B0..104FF; Osage 10500..1052F; Elbasan 10530..1056F; Caucasian Albanian +10570..105BF; Vithkuqi 10600..1077F; Linear A +10780..107BF; Latin Extended-F 10800..1083F; Cypriot Syllabary 10840..1085F; Imperial Aramaic 10860..1087F; Palmyrene @@ -240,6 +243,7 @@ FFF0..FFFF; Specials 10E80..10EBF; Yezidi 10F00..10F2F; Old Sogdian 10F30..10F6F; Sogdian +10F70..10FAF; Old Uyghur 10FB0..10FDF; Chorasmian 10FE0..10FFF; Elymaic 11000..1107F; Brahmi @@ -259,13 +263,14 @@ FFF0..FFFF; Specials 11600..1165F; Modi 11660..1167F; Mongolian Supplement 11680..116CF; Takri -11700..1173F; Ahom +11700..1174F; Ahom 11800..1184F; Dogra 118A0..118FF; Warang Citi 11900..1195F; Dives Akuru 119A0..119FF; Nandinagari 11A00..11A4F; Zanabazar Square 11A50..11AAF; Soyombo +11AB0..11ABF; Unified Canadian Aboriginal Syllabics Extended-A 11AC0..11AFF; Pau Cin Hau 11C00..11C6F; Bhaiksuki 11C70..11CBF; Marchen @@ -277,11 +282,13 @@ FFF0..FFFF; Specials 12000..123FF; Cuneiform 12400..1247F; Cuneiform Numbers and Punctuation 12480..1254F; Early Dynastic Cuneiform +12F90..12FFF; Cypro-Minoan 13000..1342F; Egyptian Hieroglyphs 13430..1343F; Egyptian Hieroglyph Format Controls 14400..1467F; Anatolian Hieroglyphs 16800..16A3F; Bamum Supplement 16A40..16A6F; Mro +16A70..16ACF; Tangsa 16AD0..16AFF; Bassa Vah 16B00..16B8F; Pahawh Hmong 16E40..16E9F; Medefaidrin @@ -290,13 +297,15 @@ FFF0..FFFF; Specials 17000..187FF; Tangut 18800..18AFF; Tangut Components 18B00..18CFF; Khitan Small Script -18D00..18D8F; Tangut Supplement +18D00..18D7F; Tangut Supplement +1AFF0..1AFFF; Kana Extended-B 1B000..1B0FF; Kana Supplement 1B100..1B12F; Kana Extended-A 1B130..1B16F; Small Kana Extension 1B170..1B2FF; Nushu 1BC00..1BC9F; Duployan 1BCA0..1BCAF; Shorthand Format Controls +1CF00..1CFCF; Znamenny Musical Notation 1D000..1D0FF; Byzantine Musical Symbols 1D100..1D1FF; Musical Symbols 1D200..1D24F; Ancient Greek Musical Notation @@ -305,9 +314,12 @@ FFF0..FFFF; Specials 1D360..1D37F; Counting Rod Numerals 1D400..1D7FF; Mathematical Alphanumeric Symbols 1D800..1DAAF; Sutton SignWriting +1DF00..1DFFF; Latin Extended-G 1E000..1E02F; Glagolitic Supplement 1E100..1E14F; Nyiakeng Puachue Hmong +1E290..1E2BF; Toto 1E2C0..1E2FF; Wancho +1E7E0..1E7FF; Ethiopic Extended-B 1E800..1E8DF; Mende Kikakui 1E900..1E95F; Adlam 1EC70..1ECBF; Indic Siyaq Numbers diff --git a/make/data/unicodedata/DerivedCoreProperties.txt b/make/data/unicodedata/DerivedCoreProperties.txt index cbaa2d46ce1..2fb971d7ff5 100644 --- a/make/data/unicodedata/DerivedCoreProperties.txt +++ b/make/data/unicodedata/DerivedCoreProperties.txt @@ -1,6 +1,6 @@ -# DerivedCoreProperties-13.0.0.txt -# Date: 2020-01-22, 00:07:19 GMT -# Copyright (c) 2020 Unicode, Inc. +# DerivedCoreProperties-14.0.0.txt +# Date: 2021-08-12, 23:12:53 GMT +# Copyright (c) 2021 Unicode, Inc. # Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries. # For terms of use, see http://www.unicode.org/terms_of_use.html # @@ -341,8 +341,10 @@ FFE9..FFEC ; Math # Sm [4] HALFWIDTH LEFTWARDS ARROW..HALFWIDTH DOWNWARDS A 0829..082C ; Alphabetic # Mn [4] SAMARITAN VOWEL SIGN LONG I..SAMARITAN VOWEL SIGN SUKUN 0840..0858 ; Alphabetic # Lo [25] MANDAIC LETTER HALQA..MANDAIC LETTER AIN 0860..086A ; Alphabetic # Lo [11] SYRIAC LETTER MALAYALAM NGA..SYRIAC LETTER MALAYALAM SSA -08A0..08B4 ; Alphabetic # Lo [21] ARABIC LETTER BEH WITH SMALL V BELOW..ARABIC LETTER KAF WITH DOT BELOW -08B6..08C7 ; Alphabetic # Lo [18] ARABIC LETTER BEH WITH SMALL MEEM ABOVE..ARABIC LETTER LAM WITH SMALL ARABIC LETTER TAH ABOVE +0870..0887 ; Alphabetic # Lo [24] ARABIC LETTER ALEF WITH ATTACHED FATHA..ARABIC BASELINE ROUND DOT +0889..088E ; Alphabetic # Lo [6] ARABIC LETTER NOON WITH INVERTED SMALL V..ARABIC VERTICAL TAIL +08A0..08C8 ; Alphabetic # Lo [41] ARABIC LETTER BEH WITH SMALL V BELOW..ARABIC LETTER GRAF +08C9 ; Alphabetic # Lm ARABIC SMALL FARSI YEH 08D4..08DF ; Alphabetic # Mn [12] ARABIC SMALL HIGH WORD AR-RUB..ARABIC SMALL HIGH WORD WAQFA 08E3..08E9 ; Alphabetic # Mn [7] ARABIC TURNED DAMMA BELOW..ARABIC CURLY KASRATAN 08F0..0902 ; Alphabetic # Mn [19] ARABIC OPEN FATHATAN..DEVANAGARI SIGN ANUSVARA @@ -471,6 +473,7 @@ FFE9..FFEC ; Math # Sm [4] HALFWIDTH LEFTWARDS ARROW..HALFWIDTH DOWNWARDS A 0C4A..0C4C ; Alphabetic # Mn [3] TELUGU VOWEL SIGN O..TELUGU VOWEL SIGN AU 0C55..0C56 ; Alphabetic # Mn [2] TELUGU LENGTH MARK..TELUGU AI LENGTH MARK 0C58..0C5A ; Alphabetic # Lo [3] TELUGU LETTER TSA..TELUGU LETTER RRRA +0C5D ; Alphabetic # Lo TELUGU LETTER NAKAARA POLLU 0C60..0C61 ; Alphabetic # Lo [2] TELUGU LETTER VOCALIC RR..TELUGU LETTER VOCALIC LL 0C62..0C63 ; Alphabetic # Mn [2] TELUGU VOWEL SIGN VOCALIC L..TELUGU VOWEL SIGN VOCALIC LL 0C80 ; Alphabetic # Lo KANNADA SIGN SPACING CANDRABINDU @@ -490,7 +493,7 @@ FFE9..FFEC ; Math # Sm [4] HALFWIDTH LEFTWARDS ARROW..HALFWIDTH DOWNWARDS A 0CCA..0CCB ; Alphabetic # Mc [2] KANNADA VOWEL SIGN O..KANNADA VOWEL SIGN OO 0CCC ; Alphabetic # Mn KANNADA VOWEL SIGN AU 0CD5..0CD6 ; Alphabetic # Mc [2] KANNADA LENGTH MARK..KANNADA AI LENGTH MARK -0CDE ; Alphabetic # Lo KANNADA LETTER FA +0CDD..0CDE ; Alphabetic # Lo [2] KANNADA LETTER NAKAARA POLLU..KANNADA LETTER FA 0CE0..0CE1 ; Alphabetic # Lo [2] KANNADA LETTER VOCALIC RR..KANNADA LETTER VOCALIC LL 0CE2..0CE3 ; Alphabetic # Mn [2] KANNADA VOWEL SIGN VOCALIC L..KANNADA VOWEL SIGN VOCALIC LL 0CF1..0CF2 ; Alphabetic # Lo [2] KANNADA SIGN JIHVAMULIYA..KANNADA SIGN UPADHMANIYA @@ -614,10 +617,9 @@ FFE9..FFEC ; Math # Sm [4] HALFWIDTH LEFTWARDS ARROW..HALFWIDTH DOWNWARDS A 16A0..16EA ; Alphabetic # Lo [75] RUNIC LETTER FEHU FEOH FE F..RUNIC LETTER X 16EE..16F0 ; Alphabetic # Nl [3] RUNIC ARLAUG SYMBOL..RUNIC BELGTHOR SYMBOL 16F1..16F8 ; Alphabetic # Lo [8] RUNIC LETTER K..RUNIC LETTER FRANKS CASKET AESC -1700..170C ; Alphabetic # Lo [13] TAGALOG LETTER A..TAGALOG LETTER YA -170E..1711 ; Alphabetic # Lo [4] TAGALOG LETTER LA..TAGALOG LETTER HA +1700..1711 ; Alphabetic # Lo [18] TAGALOG LETTER A..TAGALOG LETTER HA 1712..1713 ; Alphabetic # Mn [2] TAGALOG VOWEL SIGN I..TAGALOG VOWEL SIGN U -1720..1731 ; Alphabetic # Lo [18] HANUNOO LETTER A..HANUNOO LETTER HA +171F..1731 ; Alphabetic # Lo [19] TAGALOG LETTER ARCHAIC RA..HANUNOO LETTER HA 1732..1733 ; Alphabetic # Mn [2] HANUNOO VOWEL SIGN I..HANUNOO VOWEL SIGN U 1740..1751 ; Alphabetic # Lo [18] BUHID LETTER A..BUHID LETTER HA 1752..1753 ; Alphabetic # Mn [2] BUHID VOWEL SIGN I..BUHID VOWEL SIGN U @@ -670,6 +672,7 @@ FFE9..FFEC ; Math # Sm [4] HALFWIDTH LEFTWARDS ARROW..HALFWIDTH DOWNWARDS A 1A73..1A74 ; Alphabetic # Mn [2] TAI THAM VOWEL SIGN OA ABOVE..TAI THAM SIGN MAI KANG 1AA7 ; Alphabetic # Lm TAI THAM SIGN MAI YAMOK 1ABF..1AC0 ; Alphabetic # Mn [2] COMBINING LATIN SMALL LETTER W BELOW..COMBINING LATIN SMALL LETTER TURNED W BELOW +1ACC..1ACE ; Alphabetic # Mn [3] COMBINING LATIN SMALL LETTER INSULAR G..COMBINING LATIN SMALL LETTER INSULAR T 1B00..1B03 ; Alphabetic # Mn [4] BALINESE SIGN ULU RICEM..BALINESE SIGN SURANG 1B04 ; Alphabetic # Mc BALINESE SIGN BISAH 1B05..1B33 ; Alphabetic # Lo [47] BALINESE LETTER AKARA..BALINESE LETTER HA @@ -680,7 +683,7 @@ FFE9..FFEC ; Math # Sm [4] HALFWIDTH LEFTWARDS ARROW..HALFWIDTH DOWNWARDS A 1B3D..1B41 ; Alphabetic # Mc [5] BALINESE VOWEL SIGN LA LENGA TEDUNG..BALINESE VOWEL SIGN TALING REPA TEDUNG 1B42 ; Alphabetic # Mn BALINESE VOWEL SIGN PEPET 1B43 ; Alphabetic # Mc BALINESE VOWEL SIGN PEPET TEDUNG -1B45..1B4B ; Alphabetic # Lo [7] BALINESE LETTER KAF SASAK..BALINESE LETTER ASYURA SASAK +1B45..1B4C ; Alphabetic # Lo [8] BALINESE LETTER KAF SASAK..BALINESE LETTER ARCHAIC JNYA 1B80..1B81 ; Alphabetic # Mn [2] SUNDANESE SIGN PANYECEK..SUNDANESE SIGN PANGLAYAR 1B82 ; Alphabetic # Mc SUNDANESE SIGN PANGWISAD 1B83..1BA0 ; Alphabetic # Lo [30] SUNDANESE LETTER A..SUNDANESE LETTER HA @@ -760,9 +763,7 @@ FFE9..FFEC ; Math # Sm [4] HALFWIDTH LEFTWARDS ARROW..HALFWIDTH DOWNWARDS A 2183..2184 ; Alphabetic # L& [2] ROMAN NUMERAL REVERSED ONE HUNDRED..LATIN SMALL LETTER REVERSED C 2185..2188 ; Alphabetic # Nl [4] ROMAN NUMERAL SIX LATE FORM..ROMAN NUMERAL ONE HUNDRED THOUSAND 24B6..24E9 ; Alphabetic # So [52] CIRCLED LATIN CAPITAL LETTER A..CIRCLED LATIN SMALL LETTER Z -2C00..2C2E ; Alphabetic # L& [47] GLAGOLITIC CAPITAL LETTER AZU..GLAGOLITIC CAPITAL LETTER LATINATE MYSLITE -2C30..2C5E ; Alphabetic # L& [47] GLAGOLITIC SMALL LETTER AZU..GLAGOLITIC SMALL LETTER LATINATE MYSLITE -2C60..2C7B ; Alphabetic # L& [28] LATIN CAPITAL LETTER L WITH DOUBLE BAR..LATIN LETTER SMALL CAPITAL TURNED E +2C00..2C7B ; Alphabetic # L& [124] GLAGOLITIC CAPITAL LETTER AZU..LATIN LETTER SMALL CAPITAL TURNED E 2C7C..2C7D ; Alphabetic # Lm [2] LATIN SUBSCRIPT SMALL LETTER J..MODIFIER LETTER CAPITAL V 2C7E..2CE4 ; Alphabetic # L& [103] LATIN CAPITAL LETTER S WITH SWASH TAIL..COPTIC SYMBOL KAI 2CEB..2CEE ; Alphabetic # L& [4] COPTIC CAPITAL LETTER CRYPTOGRAMMIC SHEI..COPTIC SMALL LETTER CRYPTOGRAMMIC GANGIA @@ -802,8 +803,7 @@ FFE9..FFEC ; Math # Sm [4] HALFWIDTH LEFTWARDS ARROW..HALFWIDTH DOWNWARDS A 31A0..31BF ; Alphabetic # Lo [32] BOPOMOFO LETTER BU..BOPOMOFO LETTER AH 31F0..31FF ; Alphabetic # Lo [16] KATAKANA LETTER SMALL KU..KATAKANA LETTER SMALL RO 3400..4DBF ; Alphabetic # Lo [6592] CJK UNIFIED IDEOGRAPH-3400..CJK UNIFIED IDEOGRAPH-4DBF -4E00..9FFC ; Alphabetic # Lo [20989] CJK UNIFIED IDEOGRAPH-4E00..CJK UNIFIED IDEOGRAPH-9FFC -A000..A014 ; Alphabetic # Lo [21] YI SYLLABLE IT..YI SYLLABLE E +4E00..A014 ; Alphabetic # Lo [21013] CJK UNIFIED IDEOGRAPH-4E00..YI SYLLABLE E A015 ; Alphabetic # Lm YI SYLLABLE WU A016..A48C ; Alphabetic # Lo [1143] YI SYLLABLE BIT..YI SYLLABLE YYR A4D0..A4F7 ; Alphabetic # Lo [40] LISU LETTER BA..LISU LETTER OE @@ -828,8 +828,11 @@ A771..A787 ; Alphabetic # L& [23] LATIN SMALL LETTER DUM..LATIN SMALL LETTER A788 ; Alphabetic # Lm MODIFIER LETTER LOW CIRCUMFLEX ACCENT A78B..A78E ; Alphabetic # L& [4] LATIN CAPITAL LETTER SALTILLO..LATIN SMALL LETTER L WITH RETROFLEX HOOK AND BELT A78F ; Alphabetic # Lo LATIN LETTER SINOLOGICAL DOT -A790..A7BF ; Alphabetic # L& [48] LATIN CAPITAL LETTER N WITH DESCENDER..LATIN SMALL LETTER GLOTTAL U -A7C2..A7CA ; Alphabetic # L& [9] LATIN CAPITAL LETTER ANGLICANA W..LATIN SMALL LETTER S WITH SHORT STROKE OVERLAY +A790..A7CA ; Alphabetic # L& [59] LATIN CAPITAL LETTER N WITH DESCENDER..LATIN SMALL LETTER S WITH SHORT STROKE OVERLAY +A7D0..A7D1 ; Alphabetic # L& [2] LATIN CAPITAL LETTER CLOSED INSULAR G..LATIN SMALL LETTER CLOSED INSULAR G +A7D3 ; Alphabetic # L& LATIN SMALL LETTER DOUBLE THORN +A7D5..A7D9 ; Alphabetic # L& [5] LATIN SMALL LETTER DOUBLE WYNN..LATIN SMALL LETTER SIGMOID S +A7F2..A7F4 ; Alphabetic # Lm [3] MODIFIER LETTER CAPITAL C..MODIFIER LETTER CAPITAL Q A7F5..A7F6 ; Alphabetic # L& [2] LATIN CAPITAL LETTER REVERSED HALF H..LATIN SMALL LETTER REVERSED HALF H A7F7 ; Alphabetic # Lo LATIN EPIGRAPHIC LETTER SIDEWAYS I A7F8..A7F9 ; Alphabetic # Lm [2] MODIFIER LETTER CAPITAL H WITH STROKE..MODIFIER LETTER SMALL LIGATURE OE @@ -985,9 +988,20 @@ FFDA..FFDC ; Alphabetic # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANG 104D8..104FB ; Alphabetic # L& [36] OSAGE SMALL LETTER A..OSAGE SMALL LETTER ZHA 10500..10527 ; Alphabetic # Lo [40] ELBASAN LETTER A..ELBASAN LETTER KHE 10530..10563 ; Alphabetic # Lo [52] CAUCASIAN ALBANIAN LETTER ALT..CAUCASIAN ALBANIAN LETTER KIW +10570..1057A ; Alphabetic # L& [11] VITHKUQI CAPITAL LETTER A..VITHKUQI CAPITAL LETTER GA +1057C..1058A ; Alphabetic # L& [15] VITHKUQI CAPITAL LETTER HA..VITHKUQI CAPITAL LETTER RE +1058C..10592 ; Alphabetic # L& [7] VITHKUQI CAPITAL LETTER SE..VITHKUQI CAPITAL LETTER XE +10594..10595 ; Alphabetic # L& [2] VITHKUQI CAPITAL LETTER Y..VITHKUQI CAPITAL LETTER ZE +10597..105A1 ; Alphabetic # L& [11] VITHKUQI SMALL LETTER A..VITHKUQI SMALL LETTER GA +105A3..105B1 ; Alphabetic # L& [15] VITHKUQI SMALL LETTER HA..VITHKUQI SMALL LETTER RE +105B3..105B9 ; Alphabetic # L& [7] VITHKUQI SMALL LETTER SE..VITHKUQI SMALL LETTER XE +105BB..105BC ; Alphabetic # L& [2] VITHKUQI SMALL LETTER Y..VITHKUQI SMALL LETTER ZE 10600..10736 ; Alphabetic # Lo [311] LINEAR A SIGN AB001..LINEAR A SIGN A664 10740..10755 ; Alphabetic # Lo [22] LINEAR A SIGN A701 A..LINEAR A SIGN A732 JE 10760..10767 ; Alphabetic # Lo [8] LINEAR A SIGN A800..LINEAR A SIGN A807 +10780..10785 ; Alphabetic # Lm [6] MODIFIER LETTER SMALL CAPITAL AA..MODIFIER LETTER SMALL B WITH HOOK +10787..107B0 ; Alphabetic # Lm [42] MODIFIER LETTER SMALL DZ DIGRAPH..MODIFIER LETTER SMALL V WITH RIGHT HOOK +107B2..107BA ; Alphabetic # Lm [9] MODIFIER LETTER SMALL CAPITAL Y..MODIFIER LETTER SMALL S WITH CURL 10800..10805 ; Alphabetic # Lo [6] CYPRIOT SYLLABLE A..CYPRIOT SYLLABLE JA 10808 ; Alphabetic # Lo CYPRIOT SYLLABLE JO 1080A..10835 ; Alphabetic # Lo [44] CYPRIOT SYLLABLE KA..CYPRIOT SYLLABLE WO @@ -1028,6 +1042,7 @@ FFDA..FFDC ; Alphabetic # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANG 10F00..10F1C ; Alphabetic # Lo [29] OLD SOGDIAN LETTER ALEPH..OLD SOGDIAN LETTER FINAL TAW WITH VERTICAL TAIL 10F27 ; Alphabetic # Lo OLD SOGDIAN LIGATURE AYIN-DALETH 10F30..10F45 ; Alphabetic # Lo [22] SOGDIAN LETTER ALEPH..SOGDIAN INDEPENDENT SHIN +10F70..10F81 ; Alphabetic # Lo [18] OLD UYGHUR LETTER ALEPH..OLD UYGHUR LETTER LESH 10FB0..10FC4 ; Alphabetic # Lo [21] CHORASMIAN LETTER ALEPH..CHORASMIAN LETTER TAW 10FE0..10FF6 ; Alphabetic # Lo [23] ELYMAIC LETTER ALEPH..ELYMAIC LIGATURE ZAYIN-YODH 11000 ; Alphabetic # Mc BRAHMI SIGN CANDRABINDU @@ -1035,11 +1050,15 @@ FFDA..FFDC ; Alphabetic # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANG 11002 ; Alphabetic # Mc BRAHMI SIGN VISARGA 11003..11037 ; Alphabetic # Lo [53] BRAHMI SIGN JIHVAMULIYA..BRAHMI LETTER OLD TAMIL NNNA 11038..11045 ; Alphabetic # Mn [14] BRAHMI VOWEL SIGN AA..BRAHMI VOWEL SIGN AU +11071..11072 ; Alphabetic # Lo [2] BRAHMI LETTER OLD TAMIL SHORT E..BRAHMI LETTER OLD TAMIL SHORT O +11073..11074 ; Alphabetic # Mn [2] BRAHMI VOWEL SIGN OLD TAMIL SHORT E..BRAHMI VOWEL SIGN OLD TAMIL SHORT O +11075 ; Alphabetic # Lo BRAHMI LETTER OLD TAMIL LLA 11082 ; Alphabetic # Mc KAITHI SIGN VISARGA 11083..110AF ; Alphabetic # Lo [45] KAITHI LETTER A..KAITHI LETTER HA 110B0..110B2 ; Alphabetic # Mc [3] KAITHI VOWEL SIGN AA..KAITHI VOWEL SIGN II 110B3..110B6 ; Alphabetic # Mn [4] KAITHI VOWEL SIGN U..KAITHI VOWEL SIGN AI 110B7..110B8 ; Alphabetic # Mc [2] KAITHI VOWEL SIGN O..KAITHI VOWEL SIGN AU +110C2 ; Alphabetic # Mn KAITHI VOWEL SIGN VOCALIC R 110D0..110E8 ; Alphabetic # Lo [25] SORA SOMPENG LETTER SAH..SORA SOMPENG LETTER MAE 11100..11102 ; Alphabetic # Mn [3] CHAKMA SIGN CANDRABINDU..CHAKMA SIGN VISARGA 11103..11126 ; Alphabetic # Lo [36] CHAKMA LETTER AA..CHAKMA LETTER HAA @@ -1144,6 +1163,7 @@ FFDA..FFDC ; Alphabetic # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANG 11722..11725 ; Alphabetic # Mn [4] AHOM VOWEL SIGN I..AHOM VOWEL SIGN UU 11726 ; Alphabetic # Mc AHOM VOWEL SIGN E 11727..1172A ; Alphabetic # Mn [4] AHOM VOWEL SIGN AW..AHOM VOWEL SIGN AM +11740..11746 ; Alphabetic # Lo [7] AHOM LETTER CA..AHOM LETTER LLA 11800..1182B ; Alphabetic # Lo [44] DOGRA LETTER A..DOGRA LETTER RRA 1182C..1182E ; Alphabetic # Mc [3] DOGRA VOWEL SIGN AA..DOGRA VOWEL SIGN II 1182F..11837 ; Alphabetic # Mn [9] DOGRA VOWEL SIGN U..DOGRA SIGN ANUSVARA @@ -1185,7 +1205,7 @@ FFDA..FFDC ; Alphabetic # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANG 11A8A..11A96 ; Alphabetic # Mn [13] SOYOMBO FINAL CONSONANT SIGN G..SOYOMBO SIGN ANUSVARA 11A97 ; Alphabetic # Mc SOYOMBO SIGN VISARGA 11A9D ; Alphabetic # Lo SOYOMBO MARK PLUTA -11AC0..11AF8 ; Alphabetic # Lo [57] PAU CIN HAU LETTER PA..PAU CIN HAU GLOTTAL STOP FINAL +11AB0..11AF8 ; Alphabetic # Lo [73] CANADIAN SYLLABICS NATTILIK HI..PAU CIN HAU GLOTTAL STOP FINAL 11C00..11C08 ; Alphabetic # Lo [9] BHAIKSUKI LETTER A..BHAIKSUKI LETTER VOCALIC L 11C0A..11C2E ; Alphabetic # Lo [37] BHAIKSUKI LETTER E..BHAIKSUKI LETTER HA 11C2F ; Alphabetic # Mc BHAIKSUKI VOWEL SIGN AA @@ -1227,10 +1247,12 @@ FFDA..FFDC ; Alphabetic # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANG 12000..12399 ; Alphabetic # Lo [922] CUNEIFORM SIGN A..CUNEIFORM SIGN U U 12400..1246E ; Alphabetic # Nl [111] CUNEIFORM NUMERIC SIGN TWO ASH..CUNEIFORM NUMERIC SIGN NINE U VARIANT FORM 12480..12543 ; Alphabetic # Lo [196] CUNEIFORM SIGN AB TIMES NUN TENU..CUNEIFORM SIGN ZU5 TIMES THREE DISH TENU +12F90..12FF0 ; Alphabetic # Lo [97] CYPRO-MINOAN SIGN CM001..CYPRO-MINOAN SIGN CM114 13000..1342E ; Alphabetic # Lo [1071] EGYPTIAN HIEROGLYPH A001..EGYPTIAN HIEROGLYPH AA032 14400..14646 ; Alphabetic # Lo [583] ANATOLIAN HIEROGLYPH A001..ANATOLIAN HIEROGLYPH A530 16800..16A38 ; Alphabetic # Lo [569] BAMUM LETTER PHASE-A NGKUE MFON..BAMUM LETTER PHASE-F VUEQ 16A40..16A5E ; Alphabetic # Lo [31] MRO LETTER TA..MRO LETTER TEK +16A70..16ABE ; Alphabetic # Lo [79] TANGSA LETTER OZ..TANGSA LETTER ZA 16AD0..16AED ; Alphabetic # Lo [30] BASSA VAH LETTER ENNI..BASSA VAH LETTER I 16B00..16B2F ; Alphabetic # Lo [48] PAHAWH HMONG VOWEL KEEB..PAHAWH HMONG CONSONANT CAU 16B40..16B43 ; Alphabetic # Lm [4] PAHAWH HMONG SIGN VOS SEEV..PAHAWH HMONG SIGN IB YAM @@ -1249,7 +1271,10 @@ FFDA..FFDC ; Alphabetic # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANG 17000..187F7 ; Alphabetic # Lo [6136] TANGUT IDEOGRAPH-17000..TANGUT IDEOGRAPH-187F7 18800..18CD5 ; Alphabetic # Lo [1238] TANGUT COMPONENT-001..KHITAN SMALL SCRIPT CHARACTER-18CD5 18D00..18D08 ; Alphabetic # Lo [9] TANGUT IDEOGRAPH-18D00..TANGUT IDEOGRAPH-18D08 -1B000..1B11E ; Alphabetic # Lo [287] KATAKANA LETTER ARCHAIC E..HENTAIGANA LETTER N-MU-MO-2 +1AFF0..1AFF3 ; Alphabetic # Lm [4] KATAKANA LETTER MINNAN TONE-2..KATAKANA LETTER MINNAN TONE-5 +1AFF5..1AFFB ; Alphabetic # Lm [7] KATAKANA LETTER MINNAN TONE-7..KATAKANA LETTER MINNAN NASALIZED TONE-5 +1AFFD..1AFFE ; Alphabetic # Lm [2] KATAKANA LETTER MINNAN NASALIZED TONE-7..KATAKANA LETTER MINNAN NASALIZED TONE-8 +1B000..1B122 ; Alphabetic # Lo [291] KATAKANA LETTER ARCHAIC E..KATAKANA LETTER ARCHAIC WU 1B150..1B152 ; Alphabetic # Lo [3] HIRAGANA LETTER SMALL WI..HIRAGANA LETTER SMALL WO 1B164..1B167 ; Alphabetic # Lo [4] KATAKANA LETTER SMALL WI..KATAKANA LETTER SMALL N 1B170..1B2FB ; Alphabetic # Lo [396] NUSHU CHARACTER-1B170..NUSHU CHARACTER-1B2FB @@ -1288,6 +1313,9 @@ FFDA..FFDC ; Alphabetic # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANG 1D78A..1D7A8 ; Alphabetic # L& [31] MATHEMATICAL SANS-SERIF BOLD EPSILON SYMBOL..MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL OMEGA 1D7AA..1D7C2 ; Alphabetic # L& [25] MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ALPHA..MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMEGA 1D7C4..1D7CB ; Alphabetic # L& [8] MATHEMATICAL SANS-SERIF BOLD ITALIC EPSILON SYMBOL..MATHEMATICAL BOLD SMALL DIGAMMA +1DF00..1DF09 ; Alphabetic # L& [10] LATIN SMALL LETTER FENG DIGRAPH WITH TRILL..LATIN SMALL LETTER T WITH HOOK AND RETROFLEX HOOK +1DF0A ; Alphabetic # Lo LATIN LETTER RETROFLEX CLICK WITH RETROFLEX HOOK +1DF0B..1DF1E ; Alphabetic # L& [20] LATIN SMALL LETTER ESH WITH DOUBLE BAR..LATIN SMALL LETTER S WITH CURL 1E000..1E006 ; Alphabetic # Mn [7] COMBINING GLAGOLITIC LETTER AZU..COMBINING GLAGOLITIC LETTER ZHIVETE 1E008..1E018 ; Alphabetic # Mn [17] COMBINING GLAGOLITIC LETTER ZEMLJA..COMBINING GLAGOLITIC LETTER HERU 1E01B..1E021 ; Alphabetic # Mn [7] COMBINING GLAGOLITIC LETTER SHTA..COMBINING GLAGOLITIC LETTER YATI @@ -1296,7 +1324,12 @@ FFDA..FFDC ; Alphabetic # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANG 1E100..1E12C ; Alphabetic # Lo [45] NYIAKENG PUACHUE HMONG LETTER MA..NYIAKENG PUACHUE HMONG LETTER W 1E137..1E13D ; Alphabetic # Lm [7] NYIAKENG PUACHUE HMONG SIGN FOR PERSON..NYIAKENG PUACHUE HMONG SYLLABLE LENGTHENER 1E14E ; Alphabetic # Lo NYIAKENG PUACHUE HMONG LOGOGRAM NYAJ +1E290..1E2AD ; Alphabetic # Lo [30] TOTO LETTER PA..TOTO LETTER A 1E2C0..1E2EB ; Alphabetic # Lo [44] WANCHO LETTER AA..WANCHO LETTER YIH +1E7E0..1E7E6 ; Alphabetic # Lo [7] ETHIOPIC SYLLABLE HHYA..ETHIOPIC SYLLABLE HHYO +1E7E8..1E7EB ; Alphabetic # Lo [4] ETHIOPIC SYLLABLE GURAGE HHWA..ETHIOPIC SYLLABLE HHWE +1E7ED..1E7EE ; Alphabetic # Lo [2] ETHIOPIC SYLLABLE GURAGE MWI..ETHIOPIC SYLLABLE GURAGE MWEE +1E7F0..1E7FE ; Alphabetic # Lo [15] ETHIOPIC SYLLABLE GURAGE QWI..ETHIOPIC SYLLABLE GURAGE PWEE 1E800..1E8C4 ; Alphabetic # Lo [197] MENDE KIKAKUI SYLLABLE M001 KI..MENDE KIKAKUI SYLLABLE M060 NYON 1E900..1E943 ; Alphabetic # L& [68] ADLAM CAPITAL LETTER ALIF..ADLAM SMALL LETTER SHA 1E947 ; Alphabetic # Mn ADLAM HAMZA @@ -1337,15 +1370,15 @@ FFDA..FFDC ; Alphabetic # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANG 1F130..1F149 ; Alphabetic # So [26] SQUARED LATIN CAPITAL LETTER A..SQUARED LATIN CAPITAL LETTER Z 1F150..1F169 ; Alphabetic # So [26] NEGATIVE CIRCLED LATIN CAPITAL LETTER A..NEGATIVE CIRCLED LATIN CAPITAL LETTER Z 1F170..1F189 ; Alphabetic # So [26] NEGATIVE SQUARED LATIN CAPITAL LETTER A..NEGATIVE SQUARED LATIN CAPITAL LETTER Z -20000..2A6DD ; Alphabetic # Lo [42718] CJK UNIFIED IDEOGRAPH-20000..CJK UNIFIED IDEOGRAPH-2A6DD -2A700..2B734 ; Alphabetic # Lo [4149] CJK UNIFIED IDEOGRAPH-2A700..CJK UNIFIED IDEOGRAPH-2B734 +20000..2A6DF ; Alphabetic # Lo [42720] CJK UNIFIED IDEOGRAPH-20000..CJK UNIFIED IDEOGRAPH-2A6DF +2A700..2B738 ; Alphabetic # Lo [4153] CJK UNIFIED IDEOGRAPH-2A700..CJK UNIFIED IDEOGRAPH-2B738 2B740..2B81D ; Alphabetic # Lo [222] CJK UNIFIED IDEOGRAPH-2B740..CJK UNIFIED IDEOGRAPH-2B81D 2B820..2CEA1 ; Alphabetic # Lo [5762] CJK UNIFIED IDEOGRAPH-2B820..CJK UNIFIED IDEOGRAPH-2CEA1 2CEB0..2EBE0 ; Alphabetic # Lo [7473] CJK UNIFIED IDEOGRAPH-2CEB0..CJK UNIFIED IDEOGRAPH-2EBE0 2F800..2FA1D ; Alphabetic # Lo [542] CJK COMPATIBILITY IDEOGRAPH-2F800..CJK COMPATIBILITY IDEOGRAPH-2FA1D 30000..3134A ; Alphabetic # Lo [4939] CJK UNIFIED IDEOGRAPH-30000..CJK UNIFIED IDEOGRAPH-3134A -# Total code points: 132875 +# Total code points: 133396 # ================================================ @@ -1798,7 +1831,7 @@ FFDA..FFDC ; Alphabetic # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANG 2170..217F ; Lowercase # Nl [16] SMALL ROMAN NUMERAL ONE..SMALL ROMAN NUMERAL ONE THOUSAND 2184 ; Lowercase # L& LATIN SMALL LETTER REVERSED C 24D0..24E9 ; Lowercase # So [26] CIRCLED LATIN SMALL LETTER A..CIRCLED LATIN SMALL LETTER Z -2C30..2C5E ; Lowercase # L& [47] GLAGOLITIC SMALL LETTER AZU..GLAGOLITIC SMALL LETTER LATINATE MYSLITE +2C30..2C5F ; Lowercase # L& [48] GLAGOLITIC SMALL LETTER AZU..GLAGOLITIC SMALL LETTER CAUDATE CHRIVI 2C61 ; Lowercase # L& LATIN SMALL LETTER L WITH DOUBLE BAR 2C65..2C66 ; Lowercase # L& [2] LATIN SMALL LETTER A WITH STROKE..LATIN SMALL LETTER T WITH DIAGONAL STROKE 2C68 ; Lowercase # L& LATIN SMALL LETTER H WITH DESCENDER @@ -1970,9 +2003,15 @@ A7B9 ; Lowercase # L& LATIN SMALL LETTER U WITH STROKE A7BB ; Lowercase # L& LATIN SMALL LETTER GLOTTAL A A7BD ; Lowercase # L& LATIN SMALL LETTER GLOTTAL I A7BF ; Lowercase # L& LATIN SMALL LETTER GLOTTAL U +A7C1 ; Lowercase # L& LATIN SMALL LETTER OLD POLISH O A7C3 ; Lowercase # L& LATIN SMALL LETTER ANGLICANA W A7C8 ; Lowercase # L& LATIN SMALL LETTER D WITH SHORT STROKE OVERLAY A7CA ; Lowercase # L& LATIN SMALL LETTER S WITH SHORT STROKE OVERLAY +A7D1 ; Lowercase # L& LATIN SMALL LETTER CLOSED INSULAR G +A7D3 ; Lowercase # L& LATIN SMALL LETTER DOUBLE THORN +A7D5 ; Lowercase # L& LATIN SMALL LETTER DOUBLE WYNN +A7D7 ; Lowercase # L& LATIN SMALL LETTER MIDDLE SCOTS S +A7D9 ; Lowercase # L& LATIN SMALL LETTER SIGMOID S A7F6 ; Lowercase # L& LATIN SMALL LETTER REVERSED HALF H A7F8..A7F9 ; Lowercase # Lm [2] MODIFIER LETTER CAPITAL H WITH STROKE..MODIFIER LETTER SMALL LIGATURE OE A7FA ; Lowercase # L& LATIN LETTER SMALL CAPITAL TURNED M @@ -1985,6 +2024,14 @@ FB13..FB17 ; Lowercase # L& [5] ARMENIAN SMALL LIGATURE MEN NOW..ARMENIAN S FF41..FF5A ; Lowercase # L& [26] FULLWIDTH LATIN SMALL LETTER A..FULLWIDTH LATIN SMALL LETTER Z 10428..1044F ; Lowercase # L& [40] DESERET SMALL LETTER LONG I..DESERET SMALL LETTER EW 104D8..104FB ; Lowercase # L& [36] OSAGE SMALL LETTER A..OSAGE SMALL LETTER ZHA +10597..105A1 ; Lowercase # L& [11] VITHKUQI SMALL LETTER A..VITHKUQI SMALL LETTER GA +105A3..105B1 ; Lowercase # L& [15] VITHKUQI SMALL LETTER HA..VITHKUQI SMALL LETTER RE +105B3..105B9 ; Lowercase # L& [7] VITHKUQI SMALL LETTER SE..VITHKUQI SMALL LETTER XE +105BB..105BC ; Lowercase # L& [2] VITHKUQI SMALL LETTER Y..VITHKUQI SMALL LETTER ZE +10780 ; Lowercase # Lm MODIFIER LETTER SMALL CAPITAL AA +10783..10785 ; Lowercase # Lm [3] MODIFIER LETTER SMALL AE..MODIFIER LETTER SMALL B WITH HOOK +10787..107B0 ; Lowercase # Lm [42] MODIFIER LETTER SMALL DZ DIGRAPH..MODIFIER LETTER SMALL V WITH RIGHT HOOK +107B2..107BA ; Lowercase # Lm [9] MODIFIER LETTER SMALL CAPITAL Y..MODIFIER LETTER SMALL S WITH CURL 10CC0..10CF2 ; Lowercase # L& [51] OLD HUNGARIAN SMALL LETTER A..OLD HUNGARIAN SMALL LETTER US 118C0..118DF ; Lowercase # L& [32] WARANG CITI SMALL LETTER NGAA..WARANG CITI SMALL LETTER VIYO 16E60..16E7F ; Lowercase # L& [32] MEDEFAIDRIN SMALL LETTER M..MEDEFAIDRIN SMALL LETTER Y @@ -2016,9 +2063,11 @@ FF41..FF5A ; Lowercase # L& [26] FULLWIDTH LATIN SMALL LETTER A..FULLWIDTH L 1D7AA..1D7C2 ; Lowercase # L& [25] MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ALPHA..MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMEGA 1D7C4..1D7C9 ; Lowercase # L& [6] MATHEMATICAL SANS-SERIF BOLD ITALIC EPSILON SYMBOL..MATHEMATICAL SANS-SERIF BOLD ITALIC PI SYMBOL 1D7CB ; Lowercase # L& MATHEMATICAL BOLD SMALL DIGAMMA +1DF00..1DF09 ; Lowercase # L& [10] LATIN SMALL LETTER FENG DIGRAPH WITH TRILL..LATIN SMALL LETTER T WITH HOOK AND RETROFLEX HOOK +1DF0B..1DF1E ; Lowercase # L& [20] LATIN SMALL LETTER ESH WITH DOUBLE BAR..LATIN SMALL LETTER S WITH CURL 1E922..1E943 ; Lowercase # L& [34] ADLAM SMALL LETTER ALIF..ADLAM SMALL LETTER SHA -# Total code points: 2344 +# Total code points: 2471 # ================================================ @@ -2458,7 +2507,7 @@ FF41..FF5A ; Lowercase # L& [26] FULLWIDTH LATIN SMALL LETTER A..FULLWIDTH L 2160..216F ; Uppercase # Nl [16] ROMAN NUMERAL ONE..ROMAN NUMERAL ONE THOUSAND 2183 ; Uppercase # L& ROMAN NUMERAL REVERSED ONE HUNDRED 24B6..24CF ; Uppercase # So [26] CIRCLED LATIN CAPITAL LETTER A..CIRCLED LATIN CAPITAL LETTER Z -2C00..2C2E ; Uppercase # L& [47] GLAGOLITIC CAPITAL LETTER AZU..GLAGOLITIC CAPITAL LETTER LATINATE MYSLITE +2C00..2C2F ; Uppercase # L& [48] GLAGOLITIC CAPITAL LETTER AZU..GLAGOLITIC CAPITAL LETTER CAUDATE CHRIVI 2C60 ; Uppercase # L& LATIN CAPITAL LETTER L WITH DOUBLE BAR 2C62..2C64 ; Uppercase # L& [3] LATIN CAPITAL LETTER L WITH MIDDLE TILDE..LATIN CAPITAL LETTER R WITH TAIL 2C67 ; Uppercase # L& LATIN CAPITAL LETTER H WITH DESCENDER @@ -2623,13 +2672,21 @@ A7B8 ; Uppercase # L& LATIN CAPITAL LETTER U WITH STROKE A7BA ; Uppercase # L& LATIN CAPITAL LETTER GLOTTAL A A7BC ; Uppercase # L& LATIN CAPITAL LETTER GLOTTAL I A7BE ; Uppercase # L& LATIN CAPITAL LETTER GLOTTAL U +A7C0 ; Uppercase # L& LATIN CAPITAL LETTER OLD POLISH O A7C2 ; Uppercase # L& LATIN CAPITAL LETTER ANGLICANA W A7C4..A7C7 ; Uppercase # L& [4] LATIN CAPITAL LETTER C WITH PALATAL HOOK..LATIN CAPITAL LETTER D WITH SHORT STROKE OVERLAY A7C9 ; Uppercase # L& LATIN CAPITAL LETTER S WITH SHORT STROKE OVERLAY +A7D0 ; Uppercase # L& LATIN CAPITAL LETTER CLOSED INSULAR G +A7D6 ; Uppercase # L& LATIN CAPITAL LETTER MIDDLE SCOTS S +A7D8 ; Uppercase # L& LATIN CAPITAL LETTER SIGMOID S A7F5 ; Uppercase # L& LATIN CAPITAL LETTER REVERSED HALF H FF21..FF3A ; Uppercase # L& [26] FULLWIDTH LATIN CAPITAL LETTER A..FULLWIDTH LATIN CAPITAL LETTER Z 10400..10427 ; Uppercase # L& [40] DESERET CAPITAL LETTER LONG I..DESERET CAPITAL LETTER EW 104B0..104D3 ; Uppercase # L& [36] OSAGE CAPITAL LETTER A..OSAGE CAPITAL LETTER ZHA +10570..1057A ; Uppercase # L& [11] VITHKUQI CAPITAL LETTER A..VITHKUQI CAPITAL LETTER GA +1057C..1058A ; Uppercase # L& [15] VITHKUQI CAPITAL LETTER HA..VITHKUQI CAPITAL LETTER RE +1058C..10592 ; Uppercase # L& [7] VITHKUQI CAPITAL LETTER SE..VITHKUQI CAPITAL LETTER XE +10594..10595 ; Uppercase # L& [2] VITHKUQI CAPITAL LETTER Y..VITHKUQI CAPITAL LETTER ZE 10C80..10CB2 ; Uppercase # L& [51] OLD HUNGARIAN CAPITAL LETTER A..OLD HUNGARIAN CAPITAL LETTER US 118A0..118BF ; Uppercase # L& [32] WARANG CITI CAPITAL LETTER NGAA..WARANG CITI CAPITAL LETTER VIYO 16E40..16E5F ; Uppercase # L& [32] MEDEFAIDRIN CAPITAL LETTER M..MEDEFAIDRIN CAPITAL LETTER Y @@ -2669,7 +2726,7 @@ FF21..FF3A ; Uppercase # L& [26] FULLWIDTH LATIN CAPITAL LETTER A..FULLWIDTH 1F150..1F169 ; Uppercase # So [26] NEGATIVE CIRCLED LATIN CAPITAL LETTER A..NEGATIVE CIRCLED LATIN CAPITAL LETTER Z 1F170..1F189 ; Uppercase # So [26] NEGATIVE SQUARED LATIN CAPITAL LETTER A..NEGATIVE SQUARED LATIN CAPITAL LETTER Z -# Total code points: 1911 +# Total code points: 1951 # ================================================ @@ -2761,9 +2818,7 @@ FF21..FF3A ; Uppercase # L& [26] FULLWIDTH LATIN CAPITAL LETTER A..FULLWIDTH 2160..217F ; Cased # Nl [32] ROMAN NUMERAL ONE..SMALL ROMAN NUMERAL ONE THOUSAND 2183..2184 ; Cased # L& [2] ROMAN NUMERAL REVERSED ONE HUNDRED..LATIN SMALL LETTER REVERSED C 24B6..24E9 ; Cased # So [52] CIRCLED LATIN CAPITAL LETTER A..CIRCLED LATIN SMALL LETTER Z -2C00..2C2E ; Cased # L& [47] GLAGOLITIC CAPITAL LETTER AZU..GLAGOLITIC CAPITAL LETTER LATINATE MYSLITE -2C30..2C5E ; Cased # L& [47] GLAGOLITIC SMALL LETTER AZU..GLAGOLITIC SMALL LETTER LATINATE MYSLITE -2C60..2C7B ; Cased # L& [28] LATIN CAPITAL LETTER L WITH DOUBLE BAR..LATIN LETTER SMALL CAPITAL TURNED E +2C00..2C7B ; Cased # L& [124] GLAGOLITIC CAPITAL LETTER AZU..LATIN LETTER SMALL CAPITAL TURNED E 2C7C..2C7D ; Cased # Lm [2] LATIN SUBSCRIPT SMALL LETTER J..MODIFIER LETTER CAPITAL V 2C7E..2CE4 ; Cased # L& [103] LATIN CAPITAL LETTER S WITH SWASH TAIL..COPTIC SYMBOL KAI 2CEB..2CEE ; Cased # L& [4] COPTIC CAPITAL LETTER CRYPTOGRAMMIC SHEI..COPTIC SMALL LETTER CRYPTOGRAMMIC GANGIA @@ -2778,8 +2833,10 @@ A722..A76F ; Cased # L& [78] LATIN CAPITAL LETTER EGYPTOLOGICAL ALEF..LATIN A770 ; Cased # Lm MODIFIER LETTER US A771..A787 ; Cased # L& [23] LATIN SMALL LETTER DUM..LATIN SMALL LETTER INSULAR T A78B..A78E ; Cased # L& [4] LATIN CAPITAL LETTER SALTILLO..LATIN SMALL LETTER L WITH RETROFLEX HOOK AND BELT -A790..A7BF ; Cased # L& [48] LATIN CAPITAL LETTER N WITH DESCENDER..LATIN SMALL LETTER GLOTTAL U -A7C2..A7CA ; Cased # L& [9] LATIN CAPITAL LETTER ANGLICANA W..LATIN SMALL LETTER S WITH SHORT STROKE OVERLAY +A790..A7CA ; Cased # L& [59] LATIN CAPITAL LETTER N WITH DESCENDER..LATIN SMALL LETTER S WITH SHORT STROKE OVERLAY +A7D0..A7D1 ; Cased # L& [2] LATIN CAPITAL LETTER CLOSED INSULAR G..LATIN SMALL LETTER CLOSED INSULAR G +A7D3 ; Cased # L& LATIN SMALL LETTER DOUBLE THORN +A7D5..A7D9 ; Cased # L& [5] LATIN SMALL LETTER DOUBLE WYNN..LATIN SMALL LETTER SIGMOID S A7F5..A7F6 ; Cased # L& [2] LATIN CAPITAL LETTER REVERSED HALF H..LATIN SMALL LETTER REVERSED HALF H A7F8..A7F9 ; Cased # Lm [2] MODIFIER LETTER CAPITAL H WITH STROKE..MODIFIER LETTER SMALL LIGATURE OE A7FA ; Cased # L& LATIN LETTER SMALL CAPITAL TURNED M @@ -2794,6 +2851,18 @@ FF41..FF5A ; Cased # L& [26] FULLWIDTH LATIN SMALL LETTER A..FULLWIDTH LATIN 10400..1044F ; Cased # L& [80] DESERET CAPITAL LETTER LONG I..DESERET SMALL LETTER EW 104B0..104D3 ; Cased # L& [36] OSAGE CAPITAL LETTER A..OSAGE CAPITAL LETTER ZHA 104D8..104FB ; Cased # L& [36] OSAGE SMALL LETTER A..OSAGE SMALL LETTER ZHA +10570..1057A ; Cased # L& [11] VITHKUQI CAPITAL LETTER A..VITHKUQI CAPITAL LETTER GA +1057C..1058A ; Cased # L& [15] VITHKUQI CAPITAL LETTER HA..VITHKUQI CAPITAL LETTER RE +1058C..10592 ; Cased # L& [7] VITHKUQI CAPITAL LETTER SE..VITHKUQI CAPITAL LETTER XE +10594..10595 ; Cased # L& [2] VITHKUQI CAPITAL LETTER Y..VITHKUQI CAPITAL LETTER ZE +10597..105A1 ; Cased # L& [11] VITHKUQI SMALL LETTER A..VITHKUQI SMALL LETTER GA +105A3..105B1 ; Cased # L& [15] VITHKUQI SMALL LETTER HA..VITHKUQI SMALL LETTER RE +105B3..105B9 ; Cased # L& [7] VITHKUQI SMALL LETTER SE..VITHKUQI SMALL LETTER XE +105BB..105BC ; Cased # L& [2] VITHKUQI SMALL LETTER Y..VITHKUQI SMALL LETTER ZE +10780 ; Cased # Lm MODIFIER LETTER SMALL CAPITAL AA +10783..10785 ; Cased # Lm [3] MODIFIER LETTER SMALL AE..MODIFIER LETTER SMALL B WITH HOOK +10787..107B0 ; Cased # Lm [42] MODIFIER LETTER SMALL DZ DIGRAPH..MODIFIER LETTER SMALL V WITH RIGHT HOOK +107B2..107BA ; Cased # Lm [9] MODIFIER LETTER SMALL CAPITAL Y..MODIFIER LETTER SMALL S WITH CURL 10C80..10CB2 ; Cased # L& [51] OLD HUNGARIAN CAPITAL LETTER A..OLD HUNGARIAN CAPITAL LETTER US 10CC0..10CF2 ; Cased # L& [51] OLD HUNGARIAN SMALL LETTER A..OLD HUNGARIAN SMALL LETTER US 118A0..118DF ; Cased # L& [64] WARANG CITI CAPITAL LETTER NGAA..WARANG CITI SMALL LETTER VIYO @@ -2828,12 +2897,14 @@ FF41..FF5A ; Cased # L& [26] FULLWIDTH LATIN SMALL LETTER A..FULLWIDTH LATIN 1D78A..1D7A8 ; Cased # L& [31] MATHEMATICAL SANS-SERIF BOLD EPSILON SYMBOL..MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL OMEGA 1D7AA..1D7C2 ; Cased # L& [25] MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ALPHA..MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMEGA 1D7C4..1D7CB ; Cased # L& [8] MATHEMATICAL SANS-SERIF BOLD ITALIC EPSILON SYMBOL..MATHEMATICAL BOLD SMALL DIGAMMA +1DF00..1DF09 ; Cased # L& [10] LATIN SMALL LETTER FENG DIGRAPH WITH TRILL..LATIN SMALL LETTER T WITH HOOK AND RETROFLEX HOOK +1DF0B..1DF1E ; Cased # L& [20] LATIN SMALL LETTER ESH WITH DOUBLE BAR..LATIN SMALL LETTER S WITH CURL 1E900..1E943 ; Cased # L& [68] ADLAM CAPITAL LETTER ALIF..ADLAM SMALL LETTER SHA 1F130..1F149 ; Cased # So [26] SQUARED LATIN CAPITAL LETTER A..SQUARED LATIN CAPITAL LETTER Z 1F150..1F169 ; Cased # So [26] NEGATIVE CIRCLED LATIN CAPITAL LETTER A..NEGATIVE CIRCLED LATIN CAPITAL LETTER Z 1F170..1F189 ; Cased # So [26] NEGATIVE SQUARED LATIN CAPITAL LETTER A..NEGATIVE SQUARED LATIN CAPITAL LETTER Z -# Total code points: 4286 +# Total code points: 4453 # ================================================ @@ -2908,7 +2979,11 @@ FF41..FF5A ; Cased # L& [26] FULLWIDTH LATIN SMALL LETTER A..FULLWIDTH LATIN 0828 ; Case_Ignorable # Lm SAMARITAN MODIFIER LETTER I 0829..082D ; Case_Ignorable # Mn [5] SAMARITAN VOWEL SIGN LONG I..SAMARITAN MARK NEQUDAA 0859..085B ; Case_Ignorable # Mn [3] MANDAIC AFFRICATION MARK..MANDAIC GEMINATION MARK -08D3..08E1 ; Case_Ignorable # Mn [15] ARABIC SMALL LOW WAW..ARABIC SMALL HIGH SIGN SAFHA +0888 ; Case_Ignorable # Sk ARABIC RAISED ROUND DOT +0890..0891 ; Case_Ignorable # Cf [2] ARABIC POUND MARK ABOVE..ARABIC PIASTRE MARK ABOVE +0898..089F ; Case_Ignorable # Mn [8] ARABIC SMALL HIGH WORD AL-JUZ..ARABIC HALF MADDA OVER MADDA +08C9 ; Case_Ignorable # Lm ARABIC SMALL FARSI YEH +08CA..08E1 ; Case_Ignorable # Mn [24] ARABIC SMALL HIGH FARSI YEH..ARABIC SMALL HIGH SIGN SAFHA 08E2 ; Case_Ignorable # Cf ARABIC DISPUTED END OF AYAH 08E3..0902 ; Case_Ignorable # Mn [32] ARABIC TURNED DAMMA BELOW..DEVANAGARI SIGN ANUSVARA 093A ; Case_Ignorable # Mn DEVANAGARI VOWEL SIGN OE @@ -2951,6 +3026,7 @@ FF41..FF5A ; Cased # L& [26] FULLWIDTH LATIN SMALL LETTER A..FULLWIDTH LATIN 0BCD ; Case_Ignorable # Mn TAMIL SIGN VIRAMA 0C00 ; Case_Ignorable # Mn TELUGU SIGN COMBINING CANDRABINDU ABOVE 0C04 ; Case_Ignorable # Mn TELUGU SIGN COMBINING ANUSVARA ABOVE +0C3C ; Case_Ignorable # Mn TELUGU SIGN NUKTA 0C3E..0C40 ; Case_Ignorable # Mn [3] TELUGU VOWEL SIGN AA..TELUGU VOWEL SIGN II 0C46..0C48 ; Case_Ignorable # Mn [3] TELUGU VOWEL SIGN E..TELUGU VOWEL SIGN AI 0C4A..0C4D ; Case_Ignorable # Mn [4] TELUGU VOWEL SIGN O..TELUGU SIGN VIRAMA @@ -3003,7 +3079,7 @@ FF41..FF5A ; Cased # L& [26] FULLWIDTH LATIN SMALL LETTER A..FULLWIDTH LATIN 10FC ; Case_Ignorable # Lm MODIFIER LETTER GEORGIAN NAR 135D..135F ; Case_Ignorable # Mn [3] ETHIOPIC COMBINING GEMINATION AND VOWEL LENGTH MARK..ETHIOPIC COMBINING GEMINATION MARK 1712..1714 ; Case_Ignorable # Mn [3] TAGALOG VOWEL SIGN I..TAGALOG SIGN VIRAMA -1732..1734 ; Case_Ignorable # Mn [3] HANUNOO VOWEL SIGN I..HANUNOO SIGN PAMUDPOD +1732..1733 ; Case_Ignorable # Mn [2] HANUNOO VOWEL SIGN I..HANUNOO VOWEL SIGN U 1752..1753 ; Case_Ignorable # Mn [2] BUHID VOWEL SIGN I..BUHID VOWEL SIGN U 1772..1773 ; Case_Ignorable # Mn [2] TAGBANWA VOWEL SIGN I..TAGBANWA VOWEL SIGN U 17B4..17B5 ; Case_Ignorable # Mn [2] KHMER VOWEL INHERENT AQ..KHMER VOWEL INHERENT AA @@ -3014,6 +3090,7 @@ FF41..FF5A ; Cased # L& [26] FULLWIDTH LATIN SMALL LETTER A..FULLWIDTH LATIN 17DD ; Case_Ignorable # Mn KHMER SIGN ATTHACAN 180B..180D ; Case_Ignorable # Mn [3] MONGOLIAN FREE VARIATION SELECTOR ONE..MONGOLIAN FREE VARIATION SELECTOR THREE 180E ; Case_Ignorable # Cf MONGOLIAN VOWEL SEPARATOR +180F ; Case_Ignorable # Mn MONGOLIAN FREE VARIATION SELECTOR FOUR 1843 ; Case_Ignorable # Lm MONGOLIAN LETTER TODO LONG VOWEL SIGN 1885..1886 ; Case_Ignorable # Mn [2] MONGOLIAN LETTER ALI GALI BALUDA..MONGOLIAN LETTER ALI GALI THREE BALUDA 18A9 ; Case_Ignorable # Mn MONGOLIAN LETTER ALI GALI DAGALGA @@ -3033,7 +3110,7 @@ FF41..FF5A ; Cased # L& [26] FULLWIDTH LATIN SMALL LETTER A..FULLWIDTH LATIN 1AA7 ; Case_Ignorable # Lm TAI THAM SIGN MAI YAMOK 1AB0..1ABD ; Case_Ignorable # Mn [14] COMBINING DOUBLED CIRCUMFLEX ACCENT..COMBINING PARENTHESES BELOW 1ABE ; Case_Ignorable # Me COMBINING PARENTHESES OVERLAY -1ABF..1AC0 ; Case_Ignorable # Mn [2] COMBINING LATIN SMALL LETTER W BELOW..COMBINING LATIN SMALL LETTER TURNED W BELOW +1ABF..1ACE ; Case_Ignorable # Mn [16] COMBINING LATIN SMALL LETTER W BELOW..COMBINING LATIN SMALL LETTER INSULAR T 1B00..1B03 ; Case_Ignorable # Mn [4] BALINESE SIGN ULU RICEM..BALINESE SIGN SURANG 1B34 ; Case_Ignorable # Mn BALINESE SIGN REREKAN 1B36..1B3A ; Case_Ignorable # Mn [5] BALINESE VOWEL SIGN ULU..BALINESE VOWEL SIGN RA REPA @@ -3060,8 +3137,7 @@ FF41..FF5A ; Cased # L& [26] FULLWIDTH LATIN SMALL LETTER A..FULLWIDTH LATIN 1D2C..1D6A ; Case_Ignorable # Lm [63] MODIFIER LETTER CAPITAL A..GREEK SUBSCRIPT SMALL LETTER CHI 1D78 ; Case_Ignorable # Lm MODIFIER LETTER CYRILLIC EN 1D9B..1DBF ; Case_Ignorable # Lm [37] MODIFIER LETTER SMALL TURNED ALPHA..MODIFIER LETTER SMALL THETA -1DC0..1DF9 ; Case_Ignorable # Mn [58] COMBINING DOTTED GRAVE ACCENT..COMBINING WIDE INVERTED BRIDGE BELOW -1DFB..1DFF ; Case_Ignorable # Mn [5] COMBINING DELETION MARK..COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW +1DC0..1DFF ; Case_Ignorable # Mn [64] COMBINING DOTTED GRAVE ACCENT..COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW 1FBD ; Case_Ignorable # Sk GREEK KORONIS 1FBF..1FC1 ; Case_Ignorable # Sk [3] GREEK PSILI..GREEK DIALYTIKA AND PERISPOMENI 1FCD..1FCF ; Case_Ignorable # Sk [3] GREEK PSILI AND VARIA..GREEK PSILI AND PERISPOMENI @@ -3114,6 +3190,7 @@ A720..A721 ; Case_Ignorable # Sk [2] MODIFIER LETTER STRESS AND HIGH TONE.. A770 ; Case_Ignorable # Lm MODIFIER LETTER US A788 ; Case_Ignorable # Lm MODIFIER LETTER LOW CIRCUMFLEX ACCENT A789..A78A ; Case_Ignorable # Sk [2] MODIFIER LETTER COLON..MODIFIER LETTER SHORT EQUALS SIGN +A7F2..A7F4 ; Case_Ignorable # Lm [3] MODIFIER LETTER CAPITAL C..MODIFIER LETTER CAPITAL Q A7F8..A7F9 ; Case_Ignorable # Lm [2] MODIFIER LETTER CAPITAL H WITH STROKE..MODIFIER LETTER SMALL LIGATURE OE A802 ; Case_Ignorable # Mn SYLOTI NAGRI SIGN DVISVARA A806 ; Case_Ignorable # Mn SYLOTI NAGRI SIGN HASANTA @@ -3156,7 +3233,7 @@ ABE5 ; Case_Ignorable # Mn MEETEI MAYEK VOWEL SIGN ANAP ABE8 ; Case_Ignorable # Mn MEETEI MAYEK VOWEL SIGN UNAP ABED ; Case_Ignorable # Mn MEETEI MAYEK APUN IYEK FB1E ; Case_Ignorable # Mn HEBREW POINT JUDEO-SPANISH VARIKA -FBB2..FBC1 ; Case_Ignorable # Sk [16] ARABIC SYMBOL DOT ABOVE..ARABIC SYMBOL SMALL TAH BELOW +FBB2..FBC2 ; Case_Ignorable # Sk [17] ARABIC SYMBOL DOT ABOVE..ARABIC SYMBOL WASLA ABOVE FE00..FE0F ; Case_Ignorable # Mn [16] VARIATION SELECTOR-1..VARIATION SELECTOR-16 FE13 ; Case_Ignorable # Po PRESENTATION FORM FOR VERTICAL COLON FE20..FE2F ; Case_Ignorable # Mn [16] COMBINING LIGATURE LEFT HALF..COMBINING CYRILLIC TITLO RIGHT HALF @@ -3175,6 +3252,9 @@ FFF9..FFFB ; Case_Ignorable # Cf [3] INTERLINEAR ANNOTATION ANCHOR..INTERLI 101FD ; Case_Ignorable # Mn PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE 102E0 ; Case_Ignorable # Mn COPTIC EPACT THOUSANDS MARK 10376..1037A ; Case_Ignorable # Mn [5] COMBINING OLD PERMIC LETTER AN..COMBINING OLD PERMIC LETTER SII +10780..10785 ; Case_Ignorable # Lm [6] MODIFIER LETTER SMALL CAPITAL AA..MODIFIER LETTER SMALL B WITH HOOK +10787..107B0 ; Case_Ignorable # Lm [42] MODIFIER LETTER SMALL DZ DIGRAPH..MODIFIER LETTER SMALL V WITH RIGHT HOOK +107B2..107BA ; Case_Ignorable # Lm [9] MODIFIER LETTER SMALL CAPITAL Y..MODIFIER LETTER SMALL S WITH CURL 10A01..10A03 ; Case_Ignorable # Mn [3] KHAROSHTHI VOWEL SIGN I..KHAROSHTHI VOWEL SIGN VOCALIC R 10A05..10A06 ; Case_Ignorable # Mn [2] KHAROSHTHI VOWEL SIGN E..KHAROSHTHI VOWEL SIGN O 10A0C..10A0F ; Case_Ignorable # Mn [4] KHAROSHTHI VOWEL LENGTH MARK..KHAROSHTHI SIGN VISARGA @@ -3184,12 +3264,16 @@ FFF9..FFFB ; Case_Ignorable # Cf [3] INTERLINEAR ANNOTATION ANCHOR..INTERLI 10D24..10D27 ; Case_Ignorable # Mn [4] HANIFI ROHINGYA SIGN HARBAHAY..HANIFI ROHINGYA SIGN TASSI 10EAB..10EAC ; Case_Ignorable # Mn [2] YEZIDI COMBINING HAMZA MARK..YEZIDI COMBINING MADDA MARK 10F46..10F50 ; Case_Ignorable # Mn [11] SOGDIAN COMBINING DOT BELOW..SOGDIAN COMBINING STROKE BELOW +10F82..10F85 ; Case_Ignorable # Mn [4] OLD UYGHUR COMBINING DOT ABOVE..OLD UYGHUR COMBINING TWO DOTS BELOW 11001 ; Case_Ignorable # Mn BRAHMI SIGN ANUSVARA 11038..11046 ; Case_Ignorable # Mn [15] BRAHMI VOWEL SIGN AA..BRAHMI VIRAMA +11070 ; Case_Ignorable # Mn BRAHMI SIGN OLD TAMIL VIRAMA +11073..11074 ; Case_Ignorable # Mn [2] BRAHMI VOWEL SIGN OLD TAMIL SHORT E..BRAHMI VOWEL SIGN OLD TAMIL SHORT O 1107F..11081 ; Case_Ignorable # Mn [3] BRAHMI NUMBER JOINER..KAITHI SIGN ANUSVARA 110B3..110B6 ; Case_Ignorable # Mn [4] KAITHI VOWEL SIGN U..KAITHI VOWEL SIGN AI 110B9..110BA ; Case_Ignorable # Mn [2] KAITHI SIGN VIRAMA..KAITHI SIGN NUKTA 110BD ; Case_Ignorable # Cf KAITHI NUMBER SIGN +110C2 ; Case_Ignorable # Mn KAITHI VOWEL SIGN VOCALIC R 110CD ; Case_Ignorable # Cf KAITHI NUMBER SIGN ABOVE 11100..11102 ; Case_Ignorable # Mn [3] CHAKMA SIGN CANDRABINDU..CHAKMA SIGN VISARGA 11127..1112B ; Case_Ignorable # Mn [5] CHAKMA VOWEL SIGN A..CHAKMA VOWEL SIGN UU @@ -3274,8 +3358,13 @@ FFF9..FFFB ; Case_Ignorable # Cf [3] INTERLINEAR ANNOTATION ANCHOR..INTERLI 16FE0..16FE1 ; Case_Ignorable # Lm [2] TANGUT ITERATION MARK..NUSHU ITERATION MARK 16FE3 ; Case_Ignorable # Lm OLD CHINESE ITERATION MARK 16FE4 ; Case_Ignorable # Mn KHITAN SMALL SCRIPT FILLER +1AFF0..1AFF3 ; Case_Ignorable # Lm [4] KATAKANA LETTER MINNAN TONE-2..KATAKANA LETTER MINNAN TONE-5 +1AFF5..1AFFB ; Case_Ignorable # Lm [7] KATAKANA LETTER MINNAN TONE-7..KATAKANA LETTER MINNAN NASALIZED TONE-5 +1AFFD..1AFFE ; Case_Ignorable # Lm [2] KATAKANA LETTER MINNAN NASALIZED TONE-7..KATAKANA LETTER MINNAN NASALIZED TONE-8 1BC9D..1BC9E ; Case_Ignorable # Mn [2] DUPLOYAN THICK LETTER SELECTOR..DUPLOYAN DOUBLE MARK 1BCA0..1BCA3 ; Case_Ignorable # Cf [4] SHORTHAND FORMAT LETTER OVERLAP..SHORTHAND FORMAT UP STEP +1CF00..1CF2D ; Case_Ignorable # Mn [46] ZNAMENNY COMBINING MARK GORAZDO NIZKO S KRYZHEM ON LEFT..ZNAMENNY COMBINING MARK KRYZH ON LEFT +1CF30..1CF46 ; Case_Ignorable # Mn [23] ZNAMENNY COMBINING TONAL RANGE MARK MRACHNO..ZNAMENNY PRIZNAK MODIFIER ROG 1D167..1D169 ; Case_Ignorable # Mn [3] MUSICAL SYMBOL COMBINING TREMOLO-1..MUSICAL SYMBOL COMBINING TREMOLO-3 1D173..1D17A ; Case_Ignorable # Cf [8] MUSICAL SYMBOL BEGIN BEAM..MUSICAL SYMBOL END PHRASE 1D17B..1D182 ; Case_Ignorable # Mn [8] MUSICAL SYMBOL COMBINING ACCENT..MUSICAL SYMBOL COMBINING LOURE @@ -3295,6 +3384,7 @@ FFF9..FFFB ; Case_Ignorable # Cf [3] INTERLINEAR ANNOTATION ANCHOR..INTERLI 1E026..1E02A ; Case_Ignorable # Mn [5] COMBINING GLAGOLITIC LETTER YO..COMBINING GLAGOLITIC LETTER FITA 1E130..1E136 ; Case_Ignorable # Mn [7] NYIAKENG PUACHUE HMONG TONE-B..NYIAKENG PUACHUE HMONG TONE-D 1E137..1E13D ; Case_Ignorable # Lm [7] NYIAKENG PUACHUE HMONG SIGN FOR PERSON..NYIAKENG PUACHUE HMONG SYLLABLE LENGTHENER +1E2AE ; Case_Ignorable # Mn TOTO SIGN RISING TONE 1E2EC..1E2EF ; Case_Ignorable # Mn [4] WANCHO TONE TUP..WANCHO TONE KOINI 1E8D0..1E8D6 ; Case_Ignorable # Mn [7] MENDE KIKAKUI COMBINING NUMBER TEENS..MENDE KIKAKUI COMBINING NUMBER MILLIONS 1E944..1E94A ; Case_Ignorable # Mn [7] ADLAM ALIF LENGTHENER..ADLAM NUKTA @@ -3304,7 +3394,7 @@ E0001 ; Case_Ignorable # Cf LANGUAGE TAG E0020..E007F ; Case_Ignorable # Cf [96] TAG SPACE..CANCEL TAG E0100..E01EF ; Case_Ignorable # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256 -# Total code points: 2413 +# Total code points: 2602 # ================================================ @@ -3738,7 +3828,7 @@ E0100..E01EF ; Case_Ignorable # Mn [240] VARIATION SELECTOR-17..VARIATION SELEC 2160..216F ; Changes_When_Lowercased # Nl [16] ROMAN NUMERAL ONE..ROMAN NUMERAL ONE THOUSAND 2183 ; Changes_When_Lowercased # L& ROMAN NUMERAL REVERSED ONE HUNDRED 24B6..24CF ; Changes_When_Lowercased # So [26] CIRCLED LATIN CAPITAL LETTER A..CIRCLED LATIN CAPITAL LETTER Z -2C00..2C2E ; Changes_When_Lowercased # L& [47] GLAGOLITIC CAPITAL LETTER AZU..GLAGOLITIC CAPITAL LETTER LATINATE MYSLITE +2C00..2C2F ; Changes_When_Lowercased # L& [48] GLAGOLITIC CAPITAL LETTER AZU..GLAGOLITIC CAPITAL LETTER CAUDATE CHRIVI 2C60 ; Changes_When_Lowercased # L& LATIN CAPITAL LETTER L WITH DOUBLE BAR 2C62..2C64 ; Changes_When_Lowercased # L& [3] LATIN CAPITAL LETTER L WITH MIDDLE TILDE..LATIN CAPITAL LETTER R WITH TAIL 2C67 ; Changes_When_Lowercased # L& LATIN CAPITAL LETTER H WITH DESCENDER @@ -3903,19 +3993,27 @@ A7B8 ; Changes_When_Lowercased # L& LATIN CAPITAL LETTER U WITH S A7BA ; Changes_When_Lowercased # L& LATIN CAPITAL LETTER GLOTTAL A A7BC ; Changes_When_Lowercased # L& LATIN CAPITAL LETTER GLOTTAL I A7BE ; Changes_When_Lowercased # L& LATIN CAPITAL LETTER GLOTTAL U +A7C0 ; Changes_When_Lowercased # L& LATIN CAPITAL LETTER OLD POLISH O A7C2 ; Changes_When_Lowercased # L& LATIN CAPITAL LETTER ANGLICANA W A7C4..A7C7 ; Changes_When_Lowercased # L& [4] LATIN CAPITAL LETTER C WITH PALATAL HOOK..LATIN CAPITAL LETTER D WITH SHORT STROKE OVERLAY A7C9 ; Changes_When_Lowercased # L& LATIN CAPITAL LETTER S WITH SHORT STROKE OVERLAY +A7D0 ; Changes_When_Lowercased # L& LATIN CAPITAL LETTER CLOSED INSULAR G +A7D6 ; Changes_When_Lowercased # L& LATIN CAPITAL LETTER MIDDLE SCOTS S +A7D8 ; Changes_When_Lowercased # L& LATIN CAPITAL LETTER SIGMOID S A7F5 ; Changes_When_Lowercased # L& LATIN CAPITAL LETTER REVERSED HALF H FF21..FF3A ; Changes_When_Lowercased # L& [26] FULLWIDTH LATIN CAPITAL LETTER A..FULLWIDTH LATIN CAPITAL LETTER Z 10400..10427 ; Changes_When_Lowercased # L& [40] DESERET CAPITAL LETTER LONG I..DESERET CAPITAL LETTER EW 104B0..104D3 ; Changes_When_Lowercased # L& [36] OSAGE CAPITAL LETTER A..OSAGE CAPITAL LETTER ZHA +10570..1057A ; Changes_When_Lowercased # L& [11] VITHKUQI CAPITAL LETTER A..VITHKUQI CAPITAL LETTER GA +1057C..1058A ; Changes_When_Lowercased # L& [15] VITHKUQI CAPITAL LETTER HA..VITHKUQI CAPITAL LETTER RE +1058C..10592 ; Changes_When_Lowercased # L& [7] VITHKUQI CAPITAL LETTER SE..VITHKUQI CAPITAL LETTER XE +10594..10595 ; Changes_When_Lowercased # L& [2] VITHKUQI CAPITAL LETTER Y..VITHKUQI CAPITAL LETTER ZE 10C80..10CB2 ; Changes_When_Lowercased # L& [51] OLD HUNGARIAN CAPITAL LETTER A..OLD HUNGARIAN CAPITAL LETTER US 118A0..118BF ; Changes_When_Lowercased # L& [32] WARANG CITI CAPITAL LETTER NGAA..WARANG CITI CAPITAL LETTER VIYO 16E40..16E5F ; Changes_When_Lowercased # L& [32] MEDEFAIDRIN CAPITAL LETTER M..MEDEFAIDRIN CAPITAL LETTER Y 1E900..1E921 ; Changes_When_Lowercased # L& [34] ADLAM CAPITAL LETTER ALIF..ADLAM CAPITAL LETTER SHA -# Total code points: 1393 +# Total code points: 1433 # ================================================ @@ -4363,7 +4461,7 @@ FF21..FF3A ; Changes_When_Lowercased # L& [26] FULLWIDTH LATIN CAPITAL LETTE 2170..217F ; Changes_When_Uppercased # Nl [16] SMALL ROMAN NUMERAL ONE..SMALL ROMAN NUMERAL ONE THOUSAND 2184 ; Changes_When_Uppercased # L& LATIN SMALL LETTER REVERSED C 24D0..24E9 ; Changes_When_Uppercased # So [26] CIRCLED LATIN SMALL LETTER A..CIRCLED LATIN SMALL LETTER Z -2C30..2C5E ; Changes_When_Uppercased # L& [47] GLAGOLITIC SMALL LETTER AZU..GLAGOLITIC SMALL LETTER LATINATE MYSLITE +2C30..2C5F ; Changes_When_Uppercased # L& [48] GLAGOLITIC SMALL LETTER AZU..GLAGOLITIC SMALL LETTER CAUDATE CHRIVI 2C61 ; Changes_When_Uppercased # L& LATIN SMALL LETTER L WITH DOUBLE BAR 2C65..2C66 ; Changes_When_Uppercased # L& [2] LATIN SMALL LETTER A WITH STROKE..LATIN SMALL LETTER T WITH DIAGONAL STROKE 2C68 ; Changes_When_Uppercased # L& LATIN SMALL LETTER H WITH DESCENDER @@ -4528,9 +4626,13 @@ A7B9 ; Changes_When_Uppercased # L& LATIN SMALL LETTER U WITH STR A7BB ; Changes_When_Uppercased # L& LATIN SMALL LETTER GLOTTAL A A7BD ; Changes_When_Uppercased # L& LATIN SMALL LETTER GLOTTAL I A7BF ; Changes_When_Uppercased # L& LATIN SMALL LETTER GLOTTAL U +A7C1 ; Changes_When_Uppercased # L& LATIN SMALL LETTER OLD POLISH O A7C3 ; Changes_When_Uppercased # L& LATIN SMALL LETTER ANGLICANA W A7C8 ; Changes_When_Uppercased # L& LATIN SMALL LETTER D WITH SHORT STROKE OVERLAY A7CA ; Changes_When_Uppercased # L& LATIN SMALL LETTER S WITH SHORT STROKE OVERLAY +A7D1 ; Changes_When_Uppercased # L& LATIN SMALL LETTER CLOSED INSULAR G +A7D7 ; Changes_When_Uppercased # L& LATIN SMALL LETTER MIDDLE SCOTS S +A7D9 ; Changes_When_Uppercased # L& LATIN SMALL LETTER SIGMOID S A7F6 ; Changes_When_Uppercased # L& LATIN SMALL LETTER REVERSED HALF H AB53 ; Changes_When_Uppercased # L& LATIN SMALL LETTER CHI AB70..ABBF ; Changes_When_Uppercased # L& [80] CHEROKEE SMALL LETTER A..CHEROKEE SMALL LETTER YA @@ -4539,12 +4641,16 @@ FB13..FB17 ; Changes_When_Uppercased # L& [5] ARMENIAN SMALL LIGATURE MEN N FF41..FF5A ; Changes_When_Uppercased # L& [26] FULLWIDTH LATIN SMALL LETTER A..FULLWIDTH LATIN SMALL LETTER Z 10428..1044F ; Changes_When_Uppercased # L& [40] DESERET SMALL LETTER LONG I..DESERET SMALL LETTER EW 104D8..104FB ; Changes_When_Uppercased # L& [36] OSAGE SMALL LETTER A..OSAGE SMALL LETTER ZHA +10597..105A1 ; Changes_When_Uppercased # L& [11] VITHKUQI SMALL LETTER A..VITHKUQI SMALL LETTER GA +105A3..105B1 ; Changes_When_Uppercased # L& [15] VITHKUQI SMALL LETTER HA..VITHKUQI SMALL LETTER RE +105B3..105B9 ; Changes_When_Uppercased # L& [7] VITHKUQI SMALL LETTER SE..VITHKUQI SMALL LETTER XE +105BB..105BC ; Changes_When_Uppercased # L& [2] VITHKUQI SMALL LETTER Y..VITHKUQI SMALL LETTER ZE 10CC0..10CF2 ; Changes_When_Uppercased # L& [51] OLD HUNGARIAN SMALL LETTER A..OLD HUNGARIAN SMALL LETTER US 118C0..118DF ; Changes_When_Uppercased # L& [32] WARANG CITI SMALL LETTER NGAA..WARANG CITI SMALL LETTER VIYO 16E60..16E7F ; Changes_When_Uppercased # L& [32] MEDEFAIDRIN SMALL LETTER M..MEDEFAIDRIN SMALL LETTER Y 1E922..1E943 ; Changes_When_Uppercased # L& [34] ADLAM SMALL LETTER ALIF..ADLAM SMALL LETTER SHA -# Total code points: 1485 +# Total code points: 1525 # ================================================ @@ -4991,7 +5097,7 @@ FF41..FF5A ; Changes_When_Uppercased # L& [26] FULLWIDTH LATIN SMALL LETTER 2170..217F ; Changes_When_Titlecased # Nl [16] SMALL ROMAN NUMERAL ONE..SMALL ROMAN NUMERAL ONE THOUSAND 2184 ; Changes_When_Titlecased # L& LATIN SMALL LETTER REVERSED C 24D0..24E9 ; Changes_When_Titlecased # So [26] CIRCLED LATIN SMALL LETTER A..CIRCLED LATIN SMALL LETTER Z -2C30..2C5E ; Changes_When_Titlecased # L& [47] GLAGOLITIC SMALL LETTER AZU..GLAGOLITIC SMALL LETTER LATINATE MYSLITE +2C30..2C5F ; Changes_When_Titlecased # L& [48] GLAGOLITIC SMALL LETTER AZU..GLAGOLITIC SMALL LETTER CAUDATE CHRIVI 2C61 ; Changes_When_Titlecased # L& LATIN SMALL LETTER L WITH DOUBLE BAR 2C65..2C66 ; Changes_When_Titlecased # L& [2] LATIN SMALL LETTER A WITH STROKE..LATIN SMALL LETTER T WITH DIAGONAL STROKE 2C68 ; Changes_When_Titlecased # L& LATIN SMALL LETTER H WITH DESCENDER @@ -5156,9 +5262,13 @@ A7B9 ; Changes_When_Titlecased # L& LATIN SMALL LETTER U WITH STR A7BB ; Changes_When_Titlecased # L& LATIN SMALL LETTER GLOTTAL A A7BD ; Changes_When_Titlecased # L& LATIN SMALL LETTER GLOTTAL I A7BF ; Changes_When_Titlecased # L& LATIN SMALL LETTER GLOTTAL U +A7C1 ; Changes_When_Titlecased # L& LATIN SMALL LETTER OLD POLISH O A7C3 ; Changes_When_Titlecased # L& LATIN SMALL LETTER ANGLICANA W A7C8 ; Changes_When_Titlecased # L& LATIN SMALL LETTER D WITH SHORT STROKE OVERLAY A7CA ; Changes_When_Titlecased # L& LATIN SMALL LETTER S WITH SHORT STROKE OVERLAY +A7D1 ; Changes_When_Titlecased # L& LATIN SMALL LETTER CLOSED INSULAR G +A7D7 ; Changes_When_Titlecased # L& LATIN SMALL LETTER MIDDLE SCOTS S +A7D9 ; Changes_When_Titlecased # L& LATIN SMALL LETTER SIGMOID S A7F6 ; Changes_When_Titlecased # L& LATIN SMALL LETTER REVERSED HALF H AB53 ; Changes_When_Titlecased # L& LATIN SMALL LETTER CHI AB70..ABBF ; Changes_When_Titlecased # L& [80] CHEROKEE SMALL LETTER A..CHEROKEE SMALL LETTER YA @@ -5167,12 +5277,16 @@ FB13..FB17 ; Changes_When_Titlecased # L& [5] ARMENIAN SMALL LIGATURE MEN N FF41..FF5A ; Changes_When_Titlecased # L& [26] FULLWIDTH LATIN SMALL LETTER A..FULLWIDTH LATIN SMALL LETTER Z 10428..1044F ; Changes_When_Titlecased # L& [40] DESERET SMALL LETTER LONG I..DESERET SMALL LETTER EW 104D8..104FB ; Changes_When_Titlecased # L& [36] OSAGE SMALL LETTER A..OSAGE SMALL LETTER ZHA +10597..105A1 ; Changes_When_Titlecased # L& [11] VITHKUQI SMALL LETTER A..VITHKUQI SMALL LETTER GA +105A3..105B1 ; Changes_When_Titlecased # L& [15] VITHKUQI SMALL LETTER HA..VITHKUQI SMALL LETTER RE +105B3..105B9 ; Changes_When_Titlecased # L& [7] VITHKUQI SMALL LETTER SE..VITHKUQI SMALL LETTER XE +105BB..105BC ; Changes_When_Titlecased # L& [2] VITHKUQI SMALL LETTER Y..VITHKUQI SMALL LETTER ZE 10CC0..10CF2 ; Changes_When_Titlecased # L& [51] OLD HUNGARIAN SMALL LETTER A..OLD HUNGARIAN SMALL LETTER US 118C0..118DF ; Changes_When_Titlecased # L& [32] WARANG CITI SMALL LETTER NGAA..WARANG CITI SMALL LETTER VIYO 16E60..16E7F ; Changes_When_Titlecased # L& [32] MEDEFAIDRIN SMALL LETTER M..MEDEFAIDRIN SMALL LETTER Y 1E922..1E943 ; Changes_When_Titlecased # L& [34] ADLAM SMALL LETTER ALIF..ADLAM SMALL LETTER SHA -# Total code points: 1412 +# Total code points: 1452 # ================================================ @@ -5616,7 +5730,7 @@ FF41..FF5A ; Changes_When_Titlecased # L& [26] FULLWIDTH LATIN SMALL LETTER 2160..216F ; Changes_When_Casefolded # Nl [16] ROMAN NUMERAL ONE..ROMAN NUMERAL ONE THOUSAND 2183 ; Changes_When_Casefolded # L& ROMAN NUMERAL REVERSED ONE HUNDRED 24B6..24CF ; Changes_When_Casefolded # So [26] CIRCLED LATIN CAPITAL LETTER A..CIRCLED LATIN CAPITAL LETTER Z -2C00..2C2E ; Changes_When_Casefolded # L& [47] GLAGOLITIC CAPITAL LETTER AZU..GLAGOLITIC CAPITAL LETTER LATINATE MYSLITE +2C00..2C2F ; Changes_When_Casefolded # L& [48] GLAGOLITIC CAPITAL LETTER AZU..GLAGOLITIC CAPITAL LETTER CAUDATE CHRIVI 2C60 ; Changes_When_Casefolded # L& LATIN CAPITAL LETTER L WITH DOUBLE BAR 2C62..2C64 ; Changes_When_Casefolded # L& [3] LATIN CAPITAL LETTER L WITH MIDDLE TILDE..LATIN CAPITAL LETTER R WITH TAIL 2C67 ; Changes_When_Casefolded # L& LATIN CAPITAL LETTER H WITH DESCENDER @@ -5781,9 +5895,13 @@ A7B8 ; Changes_When_Casefolded # L& LATIN CAPITAL LETTER U WITH S A7BA ; Changes_When_Casefolded # L& LATIN CAPITAL LETTER GLOTTAL A A7BC ; Changes_When_Casefolded # L& LATIN CAPITAL LETTER GLOTTAL I A7BE ; Changes_When_Casefolded # L& LATIN CAPITAL LETTER GLOTTAL U +A7C0 ; Changes_When_Casefolded # L& LATIN CAPITAL LETTER OLD POLISH O A7C2 ; Changes_When_Casefolded # L& LATIN CAPITAL LETTER ANGLICANA W A7C4..A7C7 ; Changes_When_Casefolded # L& [4] LATIN CAPITAL LETTER C WITH PALATAL HOOK..LATIN CAPITAL LETTER D WITH SHORT STROKE OVERLAY A7C9 ; Changes_When_Casefolded # L& LATIN CAPITAL LETTER S WITH SHORT STROKE OVERLAY +A7D0 ; Changes_When_Casefolded # L& LATIN CAPITAL LETTER CLOSED INSULAR G +A7D6 ; Changes_When_Casefolded # L& LATIN CAPITAL LETTER MIDDLE SCOTS S +A7D8 ; Changes_When_Casefolded # L& LATIN CAPITAL LETTER SIGMOID S A7F5 ; Changes_When_Casefolded # L& LATIN CAPITAL LETTER REVERSED HALF H AB70..ABBF ; Changes_When_Casefolded # L& [80] CHEROKEE SMALL LETTER A..CHEROKEE SMALL LETTER YA FB00..FB06 ; Changes_When_Casefolded # L& [7] LATIN SMALL LIGATURE FF..LATIN SMALL LIGATURE ST @@ -5791,12 +5909,16 @@ FB13..FB17 ; Changes_When_Casefolded # L& [5] ARMENIAN SMALL LIGATURE MEN N FF21..FF3A ; Changes_When_Casefolded # L& [26] FULLWIDTH LATIN CAPITAL LETTER A..FULLWIDTH LATIN CAPITAL LETTER Z 10400..10427 ; Changes_When_Casefolded # L& [40] DESERET CAPITAL LETTER LONG I..DESERET CAPITAL LETTER EW 104B0..104D3 ; Changes_When_Casefolded # L& [36] OSAGE CAPITAL LETTER A..OSAGE CAPITAL LETTER ZHA +10570..1057A ; Changes_When_Casefolded # L& [11] VITHKUQI CAPITAL LETTER A..VITHKUQI CAPITAL LETTER GA +1057C..1058A ; Changes_When_Casefolded # L& [15] VITHKUQI CAPITAL LETTER HA..VITHKUQI CAPITAL LETTER RE +1058C..10592 ; Changes_When_Casefolded # L& [7] VITHKUQI CAPITAL LETTER SE..VITHKUQI CAPITAL LETTER XE +10594..10595 ; Changes_When_Casefolded # L& [2] VITHKUQI CAPITAL LETTER Y..VITHKUQI CAPITAL LETTER ZE 10C80..10CB2 ; Changes_When_Casefolded # L& [51] OLD HUNGARIAN CAPITAL LETTER A..OLD HUNGARIAN CAPITAL LETTER US 118A0..118BF ; Changes_When_Casefolded # L& [32] WARANG CITI CAPITAL LETTER NGAA..WARANG CITI CAPITAL LETTER VIYO 16E40..16E5F ; Changes_When_Casefolded # L& [32] MEDEFAIDRIN CAPITAL LETTER M..MEDEFAIDRIN CAPITAL LETTER Y 1E900..1E921 ; Changes_When_Casefolded # L& [34] ADLAM CAPITAL LETTER ALIF..ADLAM CAPITAL LETTER SHA -# Total code points: 1466 +# Total code points: 1506 # ================================================ @@ -5893,9 +6015,7 @@ FF21..FF3A ; Changes_When_Casefolded # L& [26] FULLWIDTH LATIN CAPITAL LETTE 2160..217F ; Changes_When_Casemapped # Nl [32] ROMAN NUMERAL ONE..SMALL ROMAN NUMERAL ONE THOUSAND 2183..2184 ; Changes_When_Casemapped # L& [2] ROMAN NUMERAL REVERSED ONE HUNDRED..LATIN SMALL LETTER REVERSED C 24B6..24E9 ; Changes_When_Casemapped # So [52] CIRCLED LATIN CAPITAL LETTER A..CIRCLED LATIN SMALL LETTER Z -2C00..2C2E ; Changes_When_Casemapped # L& [47] GLAGOLITIC CAPITAL LETTER AZU..GLAGOLITIC CAPITAL LETTER LATINATE MYSLITE -2C30..2C5E ; Changes_When_Casemapped # L& [47] GLAGOLITIC SMALL LETTER AZU..GLAGOLITIC SMALL LETTER LATINATE MYSLITE -2C60..2C70 ; Changes_When_Casemapped # L& [17] LATIN CAPITAL LETTER L WITH DOUBLE BAR..LATIN CAPITAL LETTER TURNED ALPHA +2C00..2C70 ; Changes_When_Casemapped # L& [113] GLAGOLITIC CAPITAL LETTER AZU..LATIN CAPITAL LETTER TURNED ALPHA 2C72..2C73 ; Changes_When_Casemapped # L& [2] LATIN CAPITAL LETTER W WITH HOOK..LATIN SMALL LETTER W WITH HOOK 2C75..2C76 ; Changes_When_Casemapped # L& [2] LATIN CAPITAL LETTER HALF H..LATIN SMALL LETTER HALF H 2C7E..2CE3 ; Changes_When_Casemapped # L& [102] LATIN CAPITAL LETTER S WITH SWASH TAIL..COPTIC SMALL LETTER OLD NUBIAN WAU @@ -5912,8 +6032,9 @@ A779..A787 ; Changes_When_Casemapped # L& [15] LATIN CAPITAL LETTER INSULAR A78B..A78D ; Changes_When_Casemapped # L& [3] LATIN CAPITAL LETTER SALTILLO..LATIN CAPITAL LETTER TURNED H A790..A794 ; Changes_When_Casemapped # L& [5] LATIN CAPITAL LETTER N WITH DESCENDER..LATIN SMALL LETTER C WITH PALATAL HOOK A796..A7AE ; Changes_When_Casemapped # L& [25] LATIN CAPITAL LETTER B WITH FLOURISH..LATIN CAPITAL LETTER SMALL CAPITAL I -A7B0..A7BF ; Changes_When_Casemapped # L& [16] LATIN CAPITAL LETTER TURNED K..LATIN SMALL LETTER GLOTTAL U -A7C2..A7CA ; Changes_When_Casemapped # L& [9] LATIN CAPITAL LETTER ANGLICANA W..LATIN SMALL LETTER S WITH SHORT STROKE OVERLAY +A7B0..A7CA ; Changes_When_Casemapped # L& [27] LATIN CAPITAL LETTER TURNED K..LATIN SMALL LETTER S WITH SHORT STROKE OVERLAY +A7D0..A7D1 ; Changes_When_Casemapped # L& [2] LATIN CAPITAL LETTER CLOSED INSULAR G..LATIN SMALL LETTER CLOSED INSULAR G +A7D6..A7D9 ; Changes_When_Casemapped # L& [4] LATIN CAPITAL LETTER MIDDLE SCOTS S..LATIN SMALL LETTER SIGMOID S A7F5..A7F6 ; Changes_When_Casemapped # L& [2] LATIN CAPITAL LETTER REVERSED HALF H..LATIN SMALL LETTER REVERSED HALF H AB53 ; Changes_When_Casemapped # L& LATIN SMALL LETTER CHI AB70..ABBF ; Changes_When_Casemapped # L& [80] CHEROKEE SMALL LETTER A..CHEROKEE SMALL LETTER YA @@ -5924,13 +6045,21 @@ FF41..FF5A ; Changes_When_Casemapped # L& [26] FULLWIDTH LATIN SMALL LETTER 10400..1044F ; Changes_When_Casemapped # L& [80] DESERET CAPITAL LETTER LONG I..DESERET SMALL LETTER EW 104B0..104D3 ; Changes_When_Casemapped # L& [36] OSAGE CAPITAL LETTER A..OSAGE CAPITAL LETTER ZHA 104D8..104FB ; Changes_When_Casemapped # L& [36] OSAGE SMALL LETTER A..OSAGE SMALL LETTER ZHA +10570..1057A ; Changes_When_Casemapped # L& [11] VITHKUQI CAPITAL LETTER A..VITHKUQI CAPITAL LETTER GA +1057C..1058A ; Changes_When_Casemapped # L& [15] VITHKUQI CAPITAL LETTER HA..VITHKUQI CAPITAL LETTER RE +1058C..10592 ; Changes_When_Casemapped # L& [7] VITHKUQI CAPITAL LETTER SE..VITHKUQI CAPITAL LETTER XE +10594..10595 ; Changes_When_Casemapped # L& [2] VITHKUQI CAPITAL LETTER Y..VITHKUQI CAPITAL LETTER ZE +10597..105A1 ; Changes_When_Casemapped # L& [11] VITHKUQI SMALL LETTER A..VITHKUQI SMALL LETTER GA +105A3..105B1 ; Changes_When_Casemapped # L& [15] VITHKUQI SMALL LETTER HA..VITHKUQI SMALL LETTER RE +105B3..105B9 ; Changes_When_Casemapped # L& [7] VITHKUQI SMALL LETTER SE..VITHKUQI SMALL LETTER XE +105BB..105BC ; Changes_When_Casemapped # L& [2] VITHKUQI SMALL LETTER Y..VITHKUQI SMALL LETTER ZE 10C80..10CB2 ; Changes_When_Casemapped # L& [51] OLD HUNGARIAN CAPITAL LETTER A..OLD HUNGARIAN CAPITAL LETTER US 10CC0..10CF2 ; Changes_When_Casemapped # L& [51] OLD HUNGARIAN SMALL LETTER A..OLD HUNGARIAN SMALL LETTER US 118A0..118DF ; Changes_When_Casemapped # L& [64] WARANG CITI CAPITAL LETTER NGAA..WARANG CITI SMALL LETTER VIYO 16E40..16E7F ; Changes_When_Casemapped # L& [64] MEDEFAIDRIN CAPITAL LETTER M..MEDEFAIDRIN SMALL LETTER Y 1E900..1E943 ; Changes_When_Casemapped # L& [68] ADLAM CAPITAL LETTER ALIF..ADLAM SMALL LETTER SHA -# Total code points: 2847 +# Total code points: 2927 # ================================================ @@ -6003,8 +6132,10 @@ FF41..FF5A ; Changes_When_Casemapped # L& [26] FULLWIDTH LATIN SMALL LETTER 0828 ; ID_Start # Lm SAMARITAN MODIFIER LETTER I 0840..0858 ; ID_Start # Lo [25] MANDAIC LETTER HALQA..MANDAIC LETTER AIN 0860..086A ; ID_Start # Lo [11] SYRIAC LETTER MALAYALAM NGA..SYRIAC LETTER MALAYALAM SSA -08A0..08B4 ; ID_Start # Lo [21] ARABIC LETTER BEH WITH SMALL V BELOW..ARABIC LETTER KAF WITH DOT BELOW -08B6..08C7 ; ID_Start # Lo [18] ARABIC LETTER BEH WITH SMALL MEEM ABOVE..ARABIC LETTER LAM WITH SMALL ARABIC LETTER TAH ABOVE +0870..0887 ; ID_Start # Lo [24] ARABIC LETTER ALEF WITH ATTACHED FATHA..ARABIC BASELINE ROUND DOT +0889..088E ; ID_Start # Lo [6] ARABIC LETTER NOON WITH INVERTED SMALL V..ARABIC VERTICAL TAIL +08A0..08C8 ; ID_Start # Lo [41] ARABIC LETTER BEH WITH SMALL V BELOW..ARABIC LETTER GRAF +08C9 ; ID_Start # Lm ARABIC SMALL FARSI YEH 0904..0939 ; ID_Start # Lo [54] DEVANAGARI LETTER SHORT A..DEVANAGARI LETTER HA 093D ; ID_Start # Lo DEVANAGARI SIGN AVAGRAHA 0950 ; ID_Start # Lo DEVANAGARI OM @@ -6070,6 +6201,7 @@ FF41..FF5A ; Changes_When_Casemapped # L& [26] FULLWIDTH LATIN SMALL LETTER 0C2A..0C39 ; ID_Start # Lo [16] TELUGU LETTER PA..TELUGU LETTER HA 0C3D ; ID_Start # Lo TELUGU SIGN AVAGRAHA 0C58..0C5A ; ID_Start # Lo [3] TELUGU LETTER TSA..TELUGU LETTER RRRA +0C5D ; ID_Start # Lo TELUGU LETTER NAKAARA POLLU 0C60..0C61 ; ID_Start # Lo [2] TELUGU LETTER VOCALIC RR..TELUGU LETTER VOCALIC LL 0C80 ; ID_Start # Lo KANNADA SIGN SPACING CANDRABINDU 0C85..0C8C ; ID_Start # Lo [8] KANNADA LETTER A..KANNADA LETTER VOCALIC L @@ -6078,7 +6210,7 @@ FF41..FF5A ; Changes_When_Casemapped # L& [26] FULLWIDTH LATIN SMALL LETTER 0CAA..0CB3 ; ID_Start # Lo [10] KANNADA LETTER PA..KANNADA LETTER LLA 0CB5..0CB9 ; ID_Start # Lo [5] KANNADA LETTER VA..KANNADA LETTER HA 0CBD ; ID_Start # Lo KANNADA SIGN AVAGRAHA -0CDE ; ID_Start # Lo KANNADA LETTER FA +0CDD..0CDE ; ID_Start # Lo [2] KANNADA LETTER NAKAARA POLLU..KANNADA LETTER FA 0CE0..0CE1 ; ID_Start # Lo [2] KANNADA LETTER VOCALIC RR..KANNADA LETTER VOCALIC LL 0CF1..0CF2 ; ID_Start # Lo [2] KANNADA SIGN JIHVAMULIYA..KANNADA SIGN UPADHMANIYA 0D04..0D0C ; ID_Start # Lo [9] MALAYALAM LETTER VEDIC ANUSVARA..MALAYALAM LETTER VOCALIC L @@ -6153,9 +6285,8 @@ FF41..FF5A ; Changes_When_Casemapped # L& [26] FULLWIDTH LATIN SMALL LETTER 16A0..16EA ; ID_Start # Lo [75] RUNIC LETTER FEHU FEOH FE F..RUNIC LETTER X 16EE..16F0 ; ID_Start # Nl [3] RUNIC ARLAUG SYMBOL..RUNIC BELGTHOR SYMBOL 16F1..16F8 ; ID_Start # Lo [8] RUNIC LETTER K..RUNIC LETTER FRANKS CASKET AESC -1700..170C ; ID_Start # Lo [13] TAGALOG LETTER A..TAGALOG LETTER YA -170E..1711 ; ID_Start # Lo [4] TAGALOG LETTER LA..TAGALOG LETTER HA -1720..1731 ; ID_Start # Lo [18] HANUNOO LETTER A..HANUNOO LETTER HA +1700..1711 ; ID_Start # Lo [18] TAGALOG LETTER A..TAGALOG LETTER HA +171F..1731 ; ID_Start # Lo [19] TAGALOG LETTER ARCHAIC RA..HANUNOO LETTER HA 1740..1751 ; ID_Start # Lo [18] BUHID LETTER A..BUHID LETTER HA 1760..176C ; ID_Start # Lo [13] TAGBANWA LETTER A..TAGBANWA LETTER YA 176E..1770 ; ID_Start # Lo [3] TAGBANWA LETTER LA..TAGBANWA LETTER SA @@ -6179,7 +6310,7 @@ FF41..FF5A ; Changes_When_Casemapped # L& [26] FULLWIDTH LATIN SMALL LETTER 1A20..1A54 ; ID_Start # Lo [53] TAI THAM LETTER HIGH KA..TAI THAM LETTER GREAT SA 1AA7 ; ID_Start # Lm TAI THAM SIGN MAI YAMOK 1B05..1B33 ; ID_Start # Lo [47] BALINESE LETTER AKARA..BALINESE LETTER HA -1B45..1B4B ; ID_Start # Lo [7] BALINESE LETTER KAF SASAK..BALINESE LETTER ASYURA SASAK +1B45..1B4C ; ID_Start # Lo [8] BALINESE LETTER KAF SASAK..BALINESE LETTER ARCHAIC JNYA 1B83..1BA0 ; ID_Start # Lo [30] SUNDANESE LETTER A..SUNDANESE LETTER HA 1BAE..1BAF ; ID_Start # Lo [2] SUNDANESE LETTER KHA..SUNDANESE LETTER SYA 1BBA..1BE5 ; ID_Start # Lo [44] SUNDANESE AVAGRAHA..BATAK LETTER U @@ -6242,9 +6373,7 @@ FF41..FF5A ; Changes_When_Casemapped # L& [26] FULLWIDTH LATIN SMALL LETTER 2160..2182 ; ID_Start # Nl [35] ROMAN NUMERAL ONE..ROMAN NUMERAL TEN THOUSAND 2183..2184 ; ID_Start # L& [2] ROMAN NUMERAL REVERSED ONE HUNDRED..LATIN SMALL LETTER REVERSED C 2185..2188 ; ID_Start # Nl [4] ROMAN NUMERAL SIX LATE FORM..ROMAN NUMERAL ONE HUNDRED THOUSAND -2C00..2C2E ; ID_Start # L& [47] GLAGOLITIC CAPITAL LETTER AZU..GLAGOLITIC CAPITAL LETTER LATINATE MYSLITE -2C30..2C5E ; ID_Start # L& [47] GLAGOLITIC SMALL LETTER AZU..GLAGOLITIC SMALL LETTER LATINATE MYSLITE -2C60..2C7B ; ID_Start # L& [28] LATIN CAPITAL LETTER L WITH DOUBLE BAR..LATIN LETTER SMALL CAPITAL TURNED E +2C00..2C7B ; ID_Start # L& [124] GLAGOLITIC CAPITAL LETTER AZU..LATIN LETTER SMALL CAPITAL TURNED E 2C7C..2C7D ; ID_Start # Lm [2] LATIN SUBSCRIPT SMALL LETTER J..MODIFIER LETTER CAPITAL V 2C7E..2CE4 ; ID_Start # L& [103] LATIN CAPITAL LETTER S WITH SWASH TAIL..COPTIC SYMBOL KAI 2CEB..2CEE ; ID_Start # L& [4] COPTIC CAPITAL LETTER CRYPTOGRAMMIC SHEI..COPTIC SMALL LETTER CRYPTOGRAMMIC GANGIA @@ -6283,8 +6412,7 @@ FF41..FF5A ; Changes_When_Casemapped # L& [26] FULLWIDTH LATIN SMALL LETTER 31A0..31BF ; ID_Start # Lo [32] BOPOMOFO LETTER BU..BOPOMOFO LETTER AH 31F0..31FF ; ID_Start # Lo [16] KATAKANA LETTER SMALL KU..KATAKANA LETTER SMALL RO 3400..4DBF ; ID_Start # Lo [6592] CJK UNIFIED IDEOGRAPH-3400..CJK UNIFIED IDEOGRAPH-4DBF -4E00..9FFC ; ID_Start # Lo [20989] CJK UNIFIED IDEOGRAPH-4E00..CJK UNIFIED IDEOGRAPH-9FFC -A000..A014 ; ID_Start # Lo [21] YI SYLLABLE IT..YI SYLLABLE E +4E00..A014 ; ID_Start # Lo [21013] CJK UNIFIED IDEOGRAPH-4E00..YI SYLLABLE E A015 ; ID_Start # Lm YI SYLLABLE WU A016..A48C ; ID_Start # Lo [1143] YI SYLLABLE BIT..YI SYLLABLE YYR A4D0..A4F7 ; ID_Start # Lo [40] LISU LETTER BA..LISU LETTER OE @@ -6307,8 +6435,11 @@ A771..A787 ; ID_Start # L& [23] LATIN SMALL LETTER DUM..LATIN SMALL LETTER I A788 ; ID_Start # Lm MODIFIER LETTER LOW CIRCUMFLEX ACCENT A78B..A78E ; ID_Start # L& [4] LATIN CAPITAL LETTER SALTILLO..LATIN SMALL LETTER L WITH RETROFLEX HOOK AND BELT A78F ; ID_Start # Lo LATIN LETTER SINOLOGICAL DOT -A790..A7BF ; ID_Start # L& [48] LATIN CAPITAL LETTER N WITH DESCENDER..LATIN SMALL LETTER GLOTTAL U -A7C2..A7CA ; ID_Start # L& [9] LATIN CAPITAL LETTER ANGLICANA W..LATIN SMALL LETTER S WITH SHORT STROKE OVERLAY +A790..A7CA ; ID_Start # L& [59] LATIN CAPITAL LETTER N WITH DESCENDER..LATIN SMALL LETTER S WITH SHORT STROKE OVERLAY +A7D0..A7D1 ; ID_Start # L& [2] LATIN CAPITAL LETTER CLOSED INSULAR G..LATIN SMALL LETTER CLOSED INSULAR G +A7D3 ; ID_Start # L& LATIN SMALL LETTER DOUBLE THORN +A7D5..A7D9 ; ID_Start # L& [5] LATIN SMALL LETTER DOUBLE WYNN..LATIN SMALL LETTER SIGMOID S +A7F2..A7F4 ; ID_Start # Lm [3] MODIFIER LETTER CAPITAL C..MODIFIER LETTER CAPITAL Q A7F5..A7F6 ; ID_Start # L& [2] LATIN CAPITAL LETTER REVERSED HALF H..LATIN SMALL LETTER REVERSED HALF H A7F7 ; ID_Start # Lo LATIN EPIGRAPHIC LETTER SIDEWAYS I A7F8..A7F9 ; ID_Start # Lm [2] MODIFIER LETTER CAPITAL H WITH STROKE..MODIFIER LETTER SMALL LIGATURE OE @@ -6418,9 +6549,20 @@ FFDA..FFDC ; ID_Start # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGUL 104D8..104FB ; ID_Start # L& [36] OSAGE SMALL LETTER A..OSAGE SMALL LETTER ZHA 10500..10527 ; ID_Start # Lo [40] ELBASAN LETTER A..ELBASAN LETTER KHE 10530..10563 ; ID_Start # Lo [52] CAUCASIAN ALBANIAN LETTER ALT..CAUCASIAN ALBANIAN LETTER KIW +10570..1057A ; ID_Start # L& [11] VITHKUQI CAPITAL LETTER A..VITHKUQI CAPITAL LETTER GA +1057C..1058A ; ID_Start # L& [15] VITHKUQI CAPITAL LETTER HA..VITHKUQI CAPITAL LETTER RE +1058C..10592 ; ID_Start # L& [7] VITHKUQI CAPITAL LETTER SE..VITHKUQI CAPITAL LETTER XE +10594..10595 ; ID_Start # L& [2] VITHKUQI CAPITAL LETTER Y..VITHKUQI CAPITAL LETTER ZE +10597..105A1 ; ID_Start # L& [11] VITHKUQI SMALL LETTER A..VITHKUQI SMALL LETTER GA +105A3..105B1 ; ID_Start # L& [15] VITHKUQI SMALL LETTER HA..VITHKUQI SMALL LETTER RE +105B3..105B9 ; ID_Start # L& [7] VITHKUQI SMALL LETTER SE..VITHKUQI SMALL LETTER XE +105BB..105BC ; ID_Start # L& [2] VITHKUQI SMALL LETTER Y..VITHKUQI SMALL LETTER ZE 10600..10736 ; ID_Start # Lo [311] LINEAR A SIGN AB001..LINEAR A SIGN A664 10740..10755 ; ID_Start # Lo [22] LINEAR A SIGN A701 A..LINEAR A SIGN A732 JE 10760..10767 ; ID_Start # Lo [8] LINEAR A SIGN A800..LINEAR A SIGN A807 +10780..10785 ; ID_Start # Lm [6] MODIFIER LETTER SMALL CAPITAL AA..MODIFIER LETTER SMALL B WITH HOOK +10787..107B0 ; ID_Start # Lm [42] MODIFIER LETTER SMALL DZ DIGRAPH..MODIFIER LETTER SMALL V WITH RIGHT HOOK +107B2..107BA ; ID_Start # Lm [9] MODIFIER LETTER SMALL CAPITAL Y..MODIFIER LETTER SMALL S WITH CURL 10800..10805 ; ID_Start # Lo [6] CYPRIOT SYLLABLE A..CYPRIOT SYLLABLE JA 10808 ; ID_Start # Lo CYPRIOT SYLLABLE JO 1080A..10835 ; ID_Start # Lo [44] CYPRIOT SYLLABLE KA..CYPRIOT SYLLABLE WO @@ -6456,9 +6598,12 @@ FFDA..FFDC ; ID_Start # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGUL 10F00..10F1C ; ID_Start # Lo [29] OLD SOGDIAN LETTER ALEPH..OLD SOGDIAN LETTER FINAL TAW WITH VERTICAL TAIL 10F27 ; ID_Start # Lo OLD SOGDIAN LIGATURE AYIN-DALETH 10F30..10F45 ; ID_Start # Lo [22] SOGDIAN LETTER ALEPH..SOGDIAN INDEPENDENT SHIN +10F70..10F81 ; ID_Start # Lo [18] OLD UYGHUR LETTER ALEPH..OLD UYGHUR LETTER LESH 10FB0..10FC4 ; ID_Start # Lo [21] CHORASMIAN LETTER ALEPH..CHORASMIAN LETTER TAW 10FE0..10FF6 ; ID_Start # Lo [23] ELYMAIC LETTER ALEPH..ELYMAIC LIGATURE ZAYIN-YODH 11003..11037 ; ID_Start # Lo [53] BRAHMI SIGN JIHVAMULIYA..BRAHMI LETTER OLD TAMIL NNNA +11071..11072 ; ID_Start # Lo [2] BRAHMI LETTER OLD TAMIL SHORT E..BRAHMI LETTER OLD TAMIL SHORT O +11075 ; ID_Start # Lo BRAHMI LETTER OLD TAMIL LLA 11083..110AF ; ID_Start # Lo [45] KAITHI LETTER A..KAITHI LETTER HA 110D0..110E8 ; ID_Start # Lo [25] SORA SOMPENG LETTER SAH..SORA SOMPENG LETTER MAE 11103..11126 ; ID_Start # Lo [36] CHAKMA LETTER AA..CHAKMA LETTER HAA @@ -6500,6 +6645,7 @@ FFDA..FFDC ; ID_Start # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGUL 11680..116AA ; ID_Start # Lo [43] TAKRI LETTER A..TAKRI LETTER RRA 116B8 ; ID_Start # Lo TAKRI LETTER ARCHAIC KHA 11700..1171A ; ID_Start # Lo [27] AHOM LETTER KA..AHOM LETTER ALTERNATE BA +11740..11746 ; ID_Start # Lo [7] AHOM LETTER CA..AHOM LETTER LLA 11800..1182B ; ID_Start # Lo [44] DOGRA LETTER A..DOGRA LETTER RRA 118A0..118DF ; ID_Start # L& [64] WARANG CITI CAPITAL LETTER NGAA..WARANG CITI SMALL LETTER VIYO 118FF..11906 ; ID_Start # Lo [8] WARANG CITI OM..DIVES AKURU LETTER E @@ -6519,7 +6665,7 @@ FFDA..FFDC ; ID_Start # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGUL 11A50 ; ID_Start # Lo SOYOMBO LETTER A 11A5C..11A89 ; ID_Start # Lo [46] SOYOMBO LETTER KA..SOYOMBO CLUSTER-INITIAL LETTER SA 11A9D ; ID_Start # Lo SOYOMBO MARK PLUTA -11AC0..11AF8 ; ID_Start # Lo [57] PAU CIN HAU LETTER PA..PAU CIN HAU GLOTTAL STOP FINAL +11AB0..11AF8 ; ID_Start # Lo [73] CANADIAN SYLLABICS NATTILIK HI..PAU CIN HAU GLOTTAL STOP FINAL 11C00..11C08 ; ID_Start # Lo [9] BHAIKSUKI LETTER A..BHAIKSUKI LETTER VOCALIC L 11C0A..11C2E ; ID_Start # Lo [37] BHAIKSUKI LETTER E..BHAIKSUKI LETTER HA 11C40 ; ID_Start # Lo BHAIKSUKI SIGN AVAGRAHA @@ -6537,10 +6683,12 @@ FFDA..FFDC ; ID_Start # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGUL 12000..12399 ; ID_Start # Lo [922] CUNEIFORM SIGN A..CUNEIFORM SIGN U U 12400..1246E ; ID_Start # Nl [111] CUNEIFORM NUMERIC SIGN TWO ASH..CUNEIFORM NUMERIC SIGN NINE U VARIANT FORM 12480..12543 ; ID_Start # Lo [196] CUNEIFORM SIGN AB TIMES NUN TENU..CUNEIFORM SIGN ZU5 TIMES THREE DISH TENU +12F90..12FF0 ; ID_Start # Lo [97] CYPRO-MINOAN SIGN CM001..CYPRO-MINOAN SIGN CM114 13000..1342E ; ID_Start # Lo [1071] EGYPTIAN HIEROGLYPH A001..EGYPTIAN HIEROGLYPH AA032 14400..14646 ; ID_Start # Lo [583] ANATOLIAN HIEROGLYPH A001..ANATOLIAN HIEROGLYPH A530 16800..16A38 ; ID_Start # Lo [569] BAMUM LETTER PHASE-A NGKUE MFON..BAMUM LETTER PHASE-F VUEQ 16A40..16A5E ; ID_Start # Lo [31] MRO LETTER TA..MRO LETTER TEK +16A70..16ABE ; ID_Start # Lo [79] TANGSA LETTER OZ..TANGSA LETTER ZA 16AD0..16AED ; ID_Start # Lo [30] BASSA VAH LETTER ENNI..BASSA VAH LETTER I 16B00..16B2F ; ID_Start # Lo [48] PAHAWH HMONG VOWEL KEEB..PAHAWH HMONG CONSONANT CAU 16B40..16B43 ; ID_Start # Lm [4] PAHAWH HMONG SIGN VOS SEEV..PAHAWH HMONG SIGN IB YAM @@ -6555,7 +6703,10 @@ FFDA..FFDC ; ID_Start # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGUL 17000..187F7 ; ID_Start # Lo [6136] TANGUT IDEOGRAPH-17000..TANGUT IDEOGRAPH-187F7 18800..18CD5 ; ID_Start # Lo [1238] TANGUT COMPONENT-001..KHITAN SMALL SCRIPT CHARACTER-18CD5 18D00..18D08 ; ID_Start # Lo [9] TANGUT IDEOGRAPH-18D00..TANGUT IDEOGRAPH-18D08 -1B000..1B11E ; ID_Start # Lo [287] KATAKANA LETTER ARCHAIC E..HENTAIGANA LETTER N-MU-MO-2 +1AFF0..1AFF3 ; ID_Start # Lm [4] KATAKANA LETTER MINNAN TONE-2..KATAKANA LETTER MINNAN TONE-5 +1AFF5..1AFFB ; ID_Start # Lm [7] KATAKANA LETTER MINNAN TONE-7..KATAKANA LETTER MINNAN NASALIZED TONE-5 +1AFFD..1AFFE ; ID_Start # Lm [2] KATAKANA LETTER MINNAN NASALIZED TONE-7..KATAKANA LETTER MINNAN NASALIZED TONE-8 +1B000..1B122 ; ID_Start # Lo [291] KATAKANA LETTER ARCHAIC E..KATAKANA LETTER ARCHAIC WU 1B150..1B152 ; ID_Start # Lo [3] HIRAGANA LETTER SMALL WI..HIRAGANA LETTER SMALL WO 1B164..1B167 ; ID_Start # Lo [4] KATAKANA LETTER SMALL WI..KATAKANA LETTER SMALL N 1B170..1B2FB ; ID_Start # Lo [396] NUSHU CHARACTER-1B170..NUSHU CHARACTER-1B2FB @@ -6593,10 +6744,18 @@ FFDA..FFDC ; ID_Start # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGUL 1D78A..1D7A8 ; ID_Start # L& [31] MATHEMATICAL SANS-SERIF BOLD EPSILON SYMBOL..MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL OMEGA 1D7AA..1D7C2 ; ID_Start # L& [25] MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ALPHA..MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMEGA 1D7C4..1D7CB ; ID_Start # L& [8] MATHEMATICAL SANS-SERIF BOLD ITALIC EPSILON SYMBOL..MATHEMATICAL BOLD SMALL DIGAMMA +1DF00..1DF09 ; ID_Start # L& [10] LATIN SMALL LETTER FENG DIGRAPH WITH TRILL..LATIN SMALL LETTER T WITH HOOK AND RETROFLEX HOOK +1DF0A ; ID_Start # Lo LATIN LETTER RETROFLEX CLICK WITH RETROFLEX HOOK +1DF0B..1DF1E ; ID_Start # L& [20] LATIN SMALL LETTER ESH WITH DOUBLE BAR..LATIN SMALL LETTER S WITH CURL 1E100..1E12C ; ID_Start # Lo [45] NYIAKENG PUACHUE HMONG LETTER MA..NYIAKENG PUACHUE HMONG LETTER W 1E137..1E13D ; ID_Start # Lm [7] NYIAKENG PUACHUE HMONG SIGN FOR PERSON..NYIAKENG PUACHUE HMONG SYLLABLE LENGTHENER 1E14E ; ID_Start # Lo NYIAKENG PUACHUE HMONG LOGOGRAM NYAJ +1E290..1E2AD ; ID_Start # Lo [30] TOTO LETTER PA..TOTO LETTER A 1E2C0..1E2EB ; ID_Start # Lo [44] WANCHO LETTER AA..WANCHO LETTER YIH +1E7E0..1E7E6 ; ID_Start # Lo [7] ETHIOPIC SYLLABLE HHYA..ETHIOPIC SYLLABLE HHYO +1E7E8..1E7EB ; ID_Start # Lo [4] ETHIOPIC SYLLABLE GURAGE HHWA..ETHIOPIC SYLLABLE HHWE +1E7ED..1E7EE ; ID_Start # Lo [2] ETHIOPIC SYLLABLE GURAGE MWI..ETHIOPIC SYLLABLE GURAGE MWEE +1E7F0..1E7FE ; ID_Start # Lo [15] ETHIOPIC SYLLABLE GURAGE QWI..ETHIOPIC SYLLABLE GURAGE PWEE 1E800..1E8C4 ; ID_Start # Lo [197] MENDE KIKAKUI SYLLABLE M001 KI..MENDE KIKAKUI SYLLABLE M060 NYON 1E900..1E943 ; ID_Start # L& [68] ADLAM CAPITAL LETTER ALIF..ADLAM SMALL LETTER SHA 1E94B ; ID_Start # Lm ADLAM NASALIZATION MARK @@ -6633,15 +6792,15 @@ FFDA..FFDC ; ID_Start # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGUL 1EEA1..1EEA3 ; ID_Start # Lo [3] ARABIC MATHEMATICAL DOUBLE-STRUCK BEH..ARABIC MATHEMATICAL DOUBLE-STRUCK DAL 1EEA5..1EEA9 ; ID_Start # Lo [5] ARABIC MATHEMATICAL DOUBLE-STRUCK WAW..ARABIC MATHEMATICAL DOUBLE-STRUCK YEH 1EEAB..1EEBB ; ID_Start # Lo [17] ARABIC MATHEMATICAL DOUBLE-STRUCK LAM..ARABIC MATHEMATICAL DOUBLE-STRUCK GHAIN -20000..2A6DD ; ID_Start # Lo [42718] CJK UNIFIED IDEOGRAPH-20000..CJK UNIFIED IDEOGRAPH-2A6DD -2A700..2B734 ; ID_Start # Lo [4149] CJK UNIFIED IDEOGRAPH-2A700..CJK UNIFIED IDEOGRAPH-2B734 +20000..2A6DF ; ID_Start # Lo [42720] CJK UNIFIED IDEOGRAPH-20000..CJK UNIFIED IDEOGRAPH-2A6DF +2A700..2B738 ; ID_Start # Lo [4153] CJK UNIFIED IDEOGRAPH-2A700..CJK UNIFIED IDEOGRAPH-2B738 2B740..2B81D ; ID_Start # Lo [222] CJK UNIFIED IDEOGRAPH-2B740..CJK UNIFIED IDEOGRAPH-2B81D 2B820..2CEA1 ; ID_Start # Lo [5762] CJK UNIFIED IDEOGRAPH-2B820..CJK UNIFIED IDEOGRAPH-2CEA1 2CEB0..2EBE0 ; ID_Start # Lo [7473] CJK UNIFIED IDEOGRAPH-2CEB0..CJK UNIFIED IDEOGRAPH-2EBE0 2F800..2FA1D ; ID_Start # Lo [542] CJK COMPATIBILITY IDEOGRAPH-2F800..CJK COMPATIBILITY IDEOGRAPH-2FA1D 30000..3134A ; ID_Start # Lo [4939] CJK UNIFIED IDEOGRAPH-30000..CJK UNIFIED IDEOGRAPH-3134A -# Total code points: 131482 +# Total code points: 131997 # ================================================ @@ -6746,9 +6905,12 @@ FFDA..FFDC ; ID_Start # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGUL 0840..0858 ; ID_Continue # Lo [25] MANDAIC LETTER HALQA..MANDAIC LETTER AIN 0859..085B ; ID_Continue # Mn [3] MANDAIC AFFRICATION MARK..MANDAIC GEMINATION MARK 0860..086A ; ID_Continue # Lo [11] SYRIAC LETTER MALAYALAM NGA..SYRIAC LETTER MALAYALAM SSA -08A0..08B4 ; ID_Continue # Lo [21] ARABIC LETTER BEH WITH SMALL V BELOW..ARABIC LETTER KAF WITH DOT BELOW -08B6..08C7 ; ID_Continue # Lo [18] ARABIC LETTER BEH WITH SMALL MEEM ABOVE..ARABIC LETTER LAM WITH SMALL ARABIC LETTER TAH ABOVE -08D3..08E1 ; ID_Continue # Mn [15] ARABIC SMALL LOW WAW..ARABIC SMALL HIGH SIGN SAFHA +0870..0887 ; ID_Continue # Lo [24] ARABIC LETTER ALEF WITH ATTACHED FATHA..ARABIC BASELINE ROUND DOT +0889..088E ; ID_Continue # Lo [6] ARABIC LETTER NOON WITH INVERTED SMALL V..ARABIC VERTICAL TAIL +0898..089F ; ID_Continue # Mn [8] ARABIC SMALL HIGH WORD AL-JUZ..ARABIC HALF MADDA OVER MADDA +08A0..08C8 ; ID_Continue # Lo [41] ARABIC LETTER BEH WITH SMALL V BELOW..ARABIC LETTER GRAF +08C9 ; ID_Continue # Lm ARABIC SMALL FARSI YEH +08CA..08E1 ; ID_Continue # Mn [24] ARABIC SMALL HIGH FARSI YEH..ARABIC SMALL HIGH SIGN SAFHA 08E3..0902 ; ID_Continue # Mn [32] ARABIC TURNED DAMMA BELOW..DEVANAGARI SIGN ANUSVARA 0903 ; ID_Continue # Mc DEVANAGARI SIGN VISARGA 0904..0939 ; ID_Continue # Lo [54] DEVANAGARI LETTER SHORT A..DEVANAGARI LETTER HA @@ -6886,6 +7048,7 @@ FFDA..FFDC ; ID_Start # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGUL 0C0E..0C10 ; ID_Continue # Lo [3] TELUGU LETTER E..TELUGU LETTER AI 0C12..0C28 ; ID_Continue # Lo [23] TELUGU LETTER O..TELUGU LETTER NA 0C2A..0C39 ; ID_Continue # Lo [16] TELUGU LETTER PA..TELUGU LETTER HA +0C3C ; ID_Continue # Mn TELUGU SIGN NUKTA 0C3D ; ID_Continue # Lo TELUGU SIGN AVAGRAHA 0C3E..0C40 ; ID_Continue # Mn [3] TELUGU VOWEL SIGN AA..TELUGU VOWEL SIGN II 0C41..0C44 ; ID_Continue # Mc [4] TELUGU VOWEL SIGN U..TELUGU VOWEL SIGN VOCALIC RR @@ -6893,6 +7056,7 @@ FFDA..FFDC ; ID_Start # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGUL 0C4A..0C4D ; ID_Continue # Mn [4] TELUGU VOWEL SIGN O..TELUGU SIGN VIRAMA 0C55..0C56 ; ID_Continue # Mn [2] TELUGU LENGTH MARK..TELUGU AI LENGTH MARK 0C58..0C5A ; ID_Continue # Lo [3] TELUGU LETTER TSA..TELUGU LETTER RRRA +0C5D ; ID_Continue # Lo TELUGU LETTER NAKAARA POLLU 0C60..0C61 ; ID_Continue # Lo [2] TELUGU LETTER VOCALIC RR..TELUGU LETTER VOCALIC LL 0C62..0C63 ; ID_Continue # Mn [2] TELUGU VOWEL SIGN VOCALIC L..TELUGU VOWEL SIGN VOCALIC LL 0C66..0C6F ; ID_Continue # Nd [10] TELUGU DIGIT ZERO..TELUGU DIGIT NINE @@ -6914,7 +7078,7 @@ FFDA..FFDC ; ID_Start # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGUL 0CCA..0CCB ; ID_Continue # Mc [2] KANNADA VOWEL SIGN O..KANNADA VOWEL SIGN OO 0CCC..0CCD ; ID_Continue # Mn [2] KANNADA VOWEL SIGN AU..KANNADA SIGN VIRAMA 0CD5..0CD6 ; ID_Continue # Mc [2] KANNADA LENGTH MARK..KANNADA AI LENGTH MARK -0CDE ; ID_Continue # Lo KANNADA LETTER FA +0CDD..0CDE ; ID_Continue # Lo [2] KANNADA LETTER NAKAARA POLLU..KANNADA LETTER FA 0CE0..0CE1 ; ID_Continue # Lo [2] KANNADA LETTER VOCALIC RR..KANNADA LETTER VOCALIC LL 0CE2..0CE3 ; ID_Continue # Mn [2] KANNADA VOWEL SIGN VOCALIC L..KANNADA VOWEL SIGN VOCALIC LL 0CE6..0CEF ; ID_Continue # Nd [10] KANNADA DIGIT ZERO..KANNADA DIGIT NINE @@ -7058,11 +7222,12 @@ FFDA..FFDC ; ID_Start # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGUL 16A0..16EA ; ID_Continue # Lo [75] RUNIC LETTER FEHU FEOH FE F..RUNIC LETTER X 16EE..16F0 ; ID_Continue # Nl [3] RUNIC ARLAUG SYMBOL..RUNIC BELGTHOR SYMBOL 16F1..16F8 ; ID_Continue # Lo [8] RUNIC LETTER K..RUNIC LETTER FRANKS CASKET AESC -1700..170C ; ID_Continue # Lo [13] TAGALOG LETTER A..TAGALOG LETTER YA -170E..1711 ; ID_Continue # Lo [4] TAGALOG LETTER LA..TAGALOG LETTER HA +1700..1711 ; ID_Continue # Lo [18] TAGALOG LETTER A..TAGALOG LETTER HA 1712..1714 ; ID_Continue # Mn [3] TAGALOG VOWEL SIGN I..TAGALOG SIGN VIRAMA -1720..1731 ; ID_Continue # Lo [18] HANUNOO LETTER A..HANUNOO LETTER HA -1732..1734 ; ID_Continue # Mn [3] HANUNOO VOWEL SIGN I..HANUNOO SIGN PAMUDPOD +1715 ; ID_Continue # Mc TAGALOG SIGN PAMUDPOD +171F..1731 ; ID_Continue # Lo [19] TAGALOG LETTER ARCHAIC RA..HANUNOO LETTER HA +1732..1733 ; ID_Continue # Mn [2] HANUNOO VOWEL SIGN I..HANUNOO VOWEL SIGN U +1734 ; ID_Continue # Mc HANUNOO SIGN PAMUDPOD 1740..1751 ; ID_Continue # Lo [18] BUHID LETTER A..BUHID LETTER HA 1752..1753 ; ID_Continue # Mn [2] BUHID VOWEL SIGN I..BUHID VOWEL SIGN U 1760..176C ; ID_Continue # Lo [13] TAGBANWA LETTER A..TAGBANWA LETTER YA @@ -7081,6 +7246,7 @@ FFDA..FFDC ; ID_Start # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGUL 17DD ; ID_Continue # Mn KHMER SIGN ATTHACAN 17E0..17E9 ; ID_Continue # Nd [10] KHMER DIGIT ZERO..KHMER DIGIT NINE 180B..180D ; ID_Continue # Mn [3] MONGOLIAN FREE VARIATION SELECTOR ONE..MONGOLIAN FREE VARIATION SELECTOR THREE +180F ; ID_Continue # Mn MONGOLIAN FREE VARIATION SELECTOR FOUR 1810..1819 ; ID_Continue # Nd [10] MONGOLIAN DIGIT ZERO..MONGOLIAN DIGIT NINE 1820..1842 ; ID_Continue # Lo [35] MONGOLIAN LETTER A..MONGOLIAN LETTER CHI 1843 ; ID_Continue # Lm MONGOLIAN LETTER TODO LONG VOWEL SIGN @@ -7128,7 +7294,7 @@ FFDA..FFDC ; ID_Start # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGUL 1A90..1A99 ; ID_Continue # Nd [10] TAI THAM THAM DIGIT ZERO..TAI THAM THAM DIGIT NINE 1AA7 ; ID_Continue # Lm TAI THAM SIGN MAI YAMOK 1AB0..1ABD ; ID_Continue # Mn [14] COMBINING DOUBLED CIRCUMFLEX ACCENT..COMBINING PARENTHESES BELOW -1ABF..1AC0 ; ID_Continue # Mn [2] COMBINING LATIN SMALL LETTER W BELOW..COMBINING LATIN SMALL LETTER TURNED W BELOW +1ABF..1ACE ; ID_Continue # Mn [16] COMBINING LATIN SMALL LETTER W BELOW..COMBINING LATIN SMALL LETTER INSULAR T 1B00..1B03 ; ID_Continue # Mn [4] BALINESE SIGN ULU RICEM..BALINESE SIGN SURANG 1B04 ; ID_Continue # Mc BALINESE SIGN BISAH 1B05..1B33 ; ID_Continue # Lo [47] BALINESE LETTER AKARA..BALINESE LETTER HA @@ -7140,7 +7306,7 @@ FFDA..FFDC ; ID_Start # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGUL 1B3D..1B41 ; ID_Continue # Mc [5] BALINESE VOWEL SIGN LA LENGA TEDUNG..BALINESE VOWEL SIGN TALING REPA TEDUNG 1B42 ; ID_Continue # Mn BALINESE VOWEL SIGN PEPET 1B43..1B44 ; ID_Continue # Mc [2] BALINESE VOWEL SIGN PEPET TEDUNG..BALINESE ADEG ADEG -1B45..1B4B ; ID_Continue # Lo [7] BALINESE LETTER KAF SASAK..BALINESE LETTER ASYURA SASAK +1B45..1B4C ; ID_Continue # Lo [8] BALINESE LETTER KAF SASAK..BALINESE LETTER ARCHAIC JNYA 1B50..1B59 ; ID_Continue # Nd [10] BALINESE DIGIT ZERO..BALINESE DIGIT NINE 1B6B..1B73 ; ID_Continue # Mn [9] BALINESE MUSICAL SYMBOL COMBINING TEGEH..BALINESE MUSICAL SYMBOL COMBINING GONG 1B80..1B81 ; ID_Continue # Mn [2] SUNDANESE SIGN PANYECEK..SUNDANESE SIGN PANGLAYAR @@ -7194,8 +7360,7 @@ FFDA..FFDC ; ID_Start # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGUL 1D78 ; ID_Continue # Lm MODIFIER LETTER CYRILLIC EN 1D79..1D9A ; ID_Continue # L& [34] LATIN SMALL LETTER INSULAR G..LATIN SMALL LETTER EZH WITH RETROFLEX HOOK 1D9B..1DBF ; ID_Continue # Lm [37] MODIFIER LETTER SMALL TURNED ALPHA..MODIFIER LETTER SMALL THETA -1DC0..1DF9 ; ID_Continue # Mn [58] COMBINING DOTTED GRAVE ACCENT..COMBINING WIDE INVERTED BRIDGE BELOW -1DFB..1DFF ; ID_Continue # Mn [5] COMBINING DELETION MARK..COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW +1DC0..1DFF ; ID_Continue # Mn [64] COMBINING DOTTED GRAVE ACCENT..COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW 1E00..1F15 ; ID_Continue # L& [278] LATIN CAPITAL LETTER A WITH RING BELOW..GREEK SMALL LETTER EPSILON WITH DASIA AND OXIA 1F18..1F1D ; ID_Continue # L& [6] GREEK CAPITAL LETTER EPSILON WITH PSILI..GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA 1F20..1F45 ; ID_Continue # L& [38] GREEK SMALL LETTER ETA WITH PSILI..GREEK SMALL LETTER OMICRON WITH DASIA AND OXIA @@ -7243,9 +7408,7 @@ FFDA..FFDC ; ID_Start # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGUL 2160..2182 ; ID_Continue # Nl [35] ROMAN NUMERAL ONE..ROMAN NUMERAL TEN THOUSAND 2183..2184 ; ID_Continue # L& [2] ROMAN NUMERAL REVERSED ONE HUNDRED..LATIN SMALL LETTER REVERSED C 2185..2188 ; ID_Continue # Nl [4] ROMAN NUMERAL SIX LATE FORM..ROMAN NUMERAL ONE HUNDRED THOUSAND -2C00..2C2E ; ID_Continue # L& [47] GLAGOLITIC CAPITAL LETTER AZU..GLAGOLITIC CAPITAL LETTER LATINATE MYSLITE -2C30..2C5E ; ID_Continue # L& [47] GLAGOLITIC SMALL LETTER AZU..GLAGOLITIC SMALL LETTER LATINATE MYSLITE -2C60..2C7B ; ID_Continue # L& [28] LATIN CAPITAL LETTER L WITH DOUBLE BAR..LATIN LETTER SMALL CAPITAL TURNED E +2C00..2C7B ; ID_Continue # L& [124] GLAGOLITIC CAPITAL LETTER AZU..LATIN LETTER SMALL CAPITAL TURNED E 2C7C..2C7D ; ID_Continue # Lm [2] LATIN SUBSCRIPT SMALL LETTER J..MODIFIER LETTER CAPITAL V 2C7E..2CE4 ; ID_Continue # L& [103] LATIN CAPITAL LETTER S WITH SWASH TAIL..COPTIC SYMBOL KAI 2CEB..2CEE ; ID_Continue # L& [4] COPTIC CAPITAL LETTER CRYPTOGRAMMIC SHEI..COPTIC SMALL LETTER CRYPTOGRAMMIC GANGIA @@ -7290,8 +7453,7 @@ FFDA..FFDC ; ID_Start # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGUL 31A0..31BF ; ID_Continue # Lo [32] BOPOMOFO LETTER BU..BOPOMOFO LETTER AH 31F0..31FF ; ID_Continue # Lo [16] KATAKANA LETTER SMALL KU..KATAKANA LETTER SMALL RO 3400..4DBF ; ID_Continue # Lo [6592] CJK UNIFIED IDEOGRAPH-3400..CJK UNIFIED IDEOGRAPH-4DBF -4E00..9FFC ; ID_Continue # Lo [20989] CJK UNIFIED IDEOGRAPH-4E00..CJK UNIFIED IDEOGRAPH-9FFC -A000..A014 ; ID_Continue # Lo [21] YI SYLLABLE IT..YI SYLLABLE E +4E00..A014 ; ID_Continue # Lo [21013] CJK UNIFIED IDEOGRAPH-4E00..YI SYLLABLE E A015 ; ID_Continue # Lm YI SYLLABLE WU A016..A48C ; ID_Continue # Lo [1143] YI SYLLABLE BIT..YI SYLLABLE YYR A4D0..A4F7 ; ID_Continue # Lo [40] LISU LETTER BA..LISU LETTER OE @@ -7319,8 +7481,11 @@ A771..A787 ; ID_Continue # L& [23] LATIN SMALL LETTER DUM..LATIN SMALL LETTE A788 ; ID_Continue # Lm MODIFIER LETTER LOW CIRCUMFLEX ACCENT A78B..A78E ; ID_Continue # L& [4] LATIN CAPITAL LETTER SALTILLO..LATIN SMALL LETTER L WITH RETROFLEX HOOK AND BELT A78F ; ID_Continue # Lo LATIN LETTER SINOLOGICAL DOT -A790..A7BF ; ID_Continue # L& [48] LATIN CAPITAL LETTER N WITH DESCENDER..LATIN SMALL LETTER GLOTTAL U -A7C2..A7CA ; ID_Continue # L& [9] LATIN CAPITAL LETTER ANGLICANA W..LATIN SMALL LETTER S WITH SHORT STROKE OVERLAY +A790..A7CA ; ID_Continue # L& [59] LATIN CAPITAL LETTER N WITH DESCENDER..LATIN SMALL LETTER S WITH SHORT STROKE OVERLAY +A7D0..A7D1 ; ID_Continue # L& [2] LATIN CAPITAL LETTER CLOSED INSULAR G..LATIN SMALL LETTER CLOSED INSULAR G +A7D3 ; ID_Continue # L& LATIN SMALL LETTER DOUBLE THORN +A7D5..A7D9 ; ID_Continue # L& [5] LATIN SMALL LETTER DOUBLE WYNN..LATIN SMALL LETTER SIGMOID S +A7F2..A7F4 ; ID_Continue # Lm [3] MODIFIER LETTER CAPITAL C..MODIFIER LETTER CAPITAL Q A7F5..A7F6 ; ID_Continue # L& [2] LATIN CAPITAL LETTER REVERSED HALF H..LATIN SMALL LETTER REVERSED HALF H A7F7 ; ID_Continue # Lo LATIN EPIGRAPHIC LETTER SIDEWAYS I A7F8..A7F9 ; ID_Continue # Lm [2] MODIFIER LETTER CAPITAL H WITH STROKE..MODIFIER LETTER SMALL LIGATURE OE @@ -7499,9 +7664,20 @@ FFDA..FFDC ; ID_Continue # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HAN 104D8..104FB ; ID_Continue # L& [36] OSAGE SMALL LETTER A..OSAGE SMALL LETTER ZHA 10500..10527 ; ID_Continue # Lo [40] ELBASAN LETTER A..ELBASAN LETTER KHE 10530..10563 ; ID_Continue # Lo [52] CAUCASIAN ALBANIAN LETTER ALT..CAUCASIAN ALBANIAN LETTER KIW +10570..1057A ; ID_Continue # L& [11] VITHKUQI CAPITAL LETTER A..VITHKUQI CAPITAL LETTER GA +1057C..1058A ; ID_Continue # L& [15] VITHKUQI CAPITAL LETTER HA..VITHKUQI CAPITAL LETTER RE +1058C..10592 ; ID_Continue # L& [7] VITHKUQI CAPITAL LETTER SE..VITHKUQI CAPITAL LETTER XE +10594..10595 ; ID_Continue # L& [2] VITHKUQI CAPITAL LETTER Y..VITHKUQI CAPITAL LETTER ZE +10597..105A1 ; ID_Continue # L& [11] VITHKUQI SMALL LETTER A..VITHKUQI SMALL LETTER GA +105A3..105B1 ; ID_Continue # L& [15] VITHKUQI SMALL LETTER HA..VITHKUQI SMALL LETTER RE +105B3..105B9 ; ID_Continue # L& [7] VITHKUQI SMALL LETTER SE..VITHKUQI SMALL LETTER XE +105BB..105BC ; ID_Continue # L& [2] VITHKUQI SMALL LETTER Y..VITHKUQI SMALL LETTER ZE 10600..10736 ; ID_Continue # Lo [311] LINEAR A SIGN AB001..LINEAR A SIGN A664 10740..10755 ; ID_Continue # Lo [22] LINEAR A SIGN A701 A..LINEAR A SIGN A732 JE 10760..10767 ; ID_Continue # Lo [8] LINEAR A SIGN A800..LINEAR A SIGN A807 +10780..10785 ; ID_Continue # Lm [6] MODIFIER LETTER SMALL CAPITAL AA..MODIFIER LETTER SMALL B WITH HOOK +10787..107B0 ; ID_Continue # Lm [42] MODIFIER LETTER SMALL DZ DIGRAPH..MODIFIER LETTER SMALL V WITH RIGHT HOOK +107B2..107BA ; ID_Continue # Lm [9] MODIFIER LETTER SMALL CAPITAL Y..MODIFIER LETTER SMALL S WITH CURL 10800..10805 ; ID_Continue # Lo [6] CYPRIOT SYLLABLE A..CYPRIOT SYLLABLE JA 10808 ; ID_Continue # Lo CYPRIOT SYLLABLE JO 1080A..10835 ; ID_Continue # Lo [44] CYPRIOT SYLLABLE KA..CYPRIOT SYLLABLE WO @@ -7547,6 +7723,8 @@ FFDA..FFDC ; ID_Continue # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HAN 10F27 ; ID_Continue # Lo OLD SOGDIAN LIGATURE AYIN-DALETH 10F30..10F45 ; ID_Continue # Lo [22] SOGDIAN LETTER ALEPH..SOGDIAN INDEPENDENT SHIN 10F46..10F50 ; ID_Continue # Mn [11] SOGDIAN COMBINING DOT BELOW..SOGDIAN COMBINING STROKE BELOW +10F70..10F81 ; ID_Continue # Lo [18] OLD UYGHUR LETTER ALEPH..OLD UYGHUR LETTER LESH +10F82..10F85 ; ID_Continue # Mn [4] OLD UYGHUR COMBINING DOT ABOVE..OLD UYGHUR COMBINING TWO DOTS BELOW 10FB0..10FC4 ; ID_Continue # Lo [21] CHORASMIAN LETTER ALEPH..CHORASMIAN LETTER TAW 10FE0..10FF6 ; ID_Continue # Lo [23] ELYMAIC LETTER ALEPH..ELYMAIC LIGATURE ZAYIN-YODH 11000 ; ID_Continue # Mc BRAHMI SIGN CANDRABINDU @@ -7555,6 +7733,10 @@ FFDA..FFDC ; ID_Continue # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HAN 11003..11037 ; ID_Continue # Lo [53] BRAHMI SIGN JIHVAMULIYA..BRAHMI LETTER OLD TAMIL NNNA 11038..11046 ; ID_Continue # Mn [15] BRAHMI VOWEL SIGN AA..BRAHMI VIRAMA 11066..1106F ; ID_Continue # Nd [10] BRAHMI DIGIT ZERO..BRAHMI DIGIT NINE +11070 ; ID_Continue # Mn BRAHMI SIGN OLD TAMIL VIRAMA +11071..11072 ; ID_Continue # Lo [2] BRAHMI LETTER OLD TAMIL SHORT E..BRAHMI LETTER OLD TAMIL SHORT O +11073..11074 ; ID_Continue # Mn [2] BRAHMI VOWEL SIGN OLD TAMIL SHORT E..BRAHMI VOWEL SIGN OLD TAMIL SHORT O +11075 ; ID_Continue # Lo BRAHMI LETTER OLD TAMIL LLA 1107F..11081 ; ID_Continue # Mn [3] BRAHMI NUMBER JOINER..KAITHI SIGN ANUSVARA 11082 ; ID_Continue # Mc KAITHI SIGN VISARGA 11083..110AF ; ID_Continue # Lo [45] KAITHI LETTER A..KAITHI LETTER HA @@ -7562,6 +7744,7 @@ FFDA..FFDC ; ID_Continue # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HAN 110B3..110B6 ; ID_Continue # Mn [4] KAITHI VOWEL SIGN U..KAITHI VOWEL SIGN AI 110B7..110B8 ; ID_Continue # Mc [2] KAITHI VOWEL SIGN O..KAITHI VOWEL SIGN AU 110B9..110BA ; ID_Continue # Mn [2] KAITHI SIGN VIRAMA..KAITHI SIGN NUKTA +110C2 ; ID_Continue # Mn KAITHI VOWEL SIGN VOCALIC R 110D0..110E8 ; ID_Continue # Lo [25] SORA SOMPENG LETTER SAH..SORA SOMPENG LETTER MAE 110F0..110F9 ; ID_Continue # Nd [10] SORA SOMPENG DIGIT ZERO..SORA SOMPENG DIGIT NINE 11100..11102 ; ID_Continue # Mn [3] CHAKMA SIGN CANDRABINDU..CHAKMA SIGN VISARGA @@ -7687,6 +7870,7 @@ FFDA..FFDC ; ID_Continue # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HAN 11726 ; ID_Continue # Mc AHOM VOWEL SIGN E 11727..1172B ; ID_Continue # Mn [5] AHOM VOWEL SIGN AW..AHOM SIGN KILLER 11730..11739 ; ID_Continue # Nd [10] AHOM DIGIT ZERO..AHOM DIGIT NINE +11740..11746 ; ID_Continue # Lo [7] AHOM LETTER CA..AHOM LETTER LLA 11800..1182B ; ID_Continue # Lo [44] DOGRA LETTER A..DOGRA LETTER RRA 1182C..1182E ; ID_Continue # Mc [3] DOGRA VOWEL SIGN AA..DOGRA VOWEL SIGN II 1182F..11837 ; ID_Continue # Mn [9] DOGRA VOWEL SIGN U..DOGRA SIGN ANUSVARA @@ -7737,7 +7921,7 @@ FFDA..FFDC ; ID_Continue # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HAN 11A97 ; ID_Continue # Mc SOYOMBO SIGN VISARGA 11A98..11A99 ; ID_Continue # Mn [2] SOYOMBO GEMINATION MARK..SOYOMBO SUBJOINER 11A9D ; ID_Continue # Lo SOYOMBO MARK PLUTA -11AC0..11AF8 ; ID_Continue # Lo [57] PAU CIN HAU LETTER PA..PAU CIN HAU GLOTTAL STOP FINAL +11AB0..11AF8 ; ID_Continue # Lo [73] CANADIAN SYLLABICS NATTILIK HI..PAU CIN HAU GLOTTAL STOP FINAL 11C00..11C08 ; ID_Continue # Lo [9] BHAIKSUKI LETTER A..BHAIKSUKI LETTER VOCALIC L 11C0A..11C2E ; ID_Continue # Lo [37] BHAIKSUKI LETTER E..BHAIKSUKI LETTER HA 11C2F ; ID_Continue # Mc BHAIKSUKI VOWEL SIGN AA @@ -7783,11 +7967,14 @@ FFDA..FFDC ; ID_Continue # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HAN 12000..12399 ; ID_Continue # Lo [922] CUNEIFORM SIGN A..CUNEIFORM SIGN U U 12400..1246E ; ID_Continue # Nl [111] CUNEIFORM NUMERIC SIGN TWO ASH..CUNEIFORM NUMERIC SIGN NINE U VARIANT FORM 12480..12543 ; ID_Continue # Lo [196] CUNEIFORM SIGN AB TIMES NUN TENU..CUNEIFORM SIGN ZU5 TIMES THREE DISH TENU +12F90..12FF0 ; ID_Continue # Lo [97] CYPRO-MINOAN SIGN CM001..CYPRO-MINOAN SIGN CM114 13000..1342E ; ID_Continue # Lo [1071] EGYPTIAN HIEROGLYPH A001..EGYPTIAN HIEROGLYPH AA032 14400..14646 ; ID_Continue # Lo [583] ANATOLIAN HIEROGLYPH A001..ANATOLIAN HIEROGLYPH A530 16800..16A38 ; ID_Continue # Lo [569] BAMUM LETTER PHASE-A NGKUE MFON..BAMUM LETTER PHASE-F VUEQ 16A40..16A5E ; ID_Continue # Lo [31] MRO LETTER TA..MRO LETTER TEK 16A60..16A69 ; ID_Continue # Nd [10] MRO DIGIT ZERO..MRO DIGIT NINE +16A70..16ABE ; ID_Continue # Lo [79] TANGSA LETTER OZ..TANGSA LETTER ZA +16AC0..16AC9 ; ID_Continue # Nd [10] TANGSA DIGIT ZERO..TANGSA DIGIT NINE 16AD0..16AED ; ID_Continue # Lo [30] BASSA VAH LETTER ENNI..BASSA VAH LETTER I 16AF0..16AF4 ; ID_Continue # Mn [5] BASSA VAH COMBINING HIGH TONE..BASSA VAH COMBINING HIGH-LOW TONE 16B00..16B2F ; ID_Continue # Lo [48] PAHAWH HMONG VOWEL KEEB..PAHAWH HMONG CONSONANT CAU @@ -7810,7 +7997,10 @@ FFDA..FFDC ; ID_Continue # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HAN 17000..187F7 ; ID_Continue # Lo [6136] TANGUT IDEOGRAPH-17000..TANGUT IDEOGRAPH-187F7 18800..18CD5 ; ID_Continue # Lo [1238] TANGUT COMPONENT-001..KHITAN SMALL SCRIPT CHARACTER-18CD5 18D00..18D08 ; ID_Continue # Lo [9] TANGUT IDEOGRAPH-18D00..TANGUT IDEOGRAPH-18D08 -1B000..1B11E ; ID_Continue # Lo [287] KATAKANA LETTER ARCHAIC E..HENTAIGANA LETTER N-MU-MO-2 +1AFF0..1AFF3 ; ID_Continue # Lm [4] KATAKANA LETTER MINNAN TONE-2..KATAKANA LETTER MINNAN TONE-5 +1AFF5..1AFFB ; ID_Continue # Lm [7] KATAKANA LETTER MINNAN TONE-7..KATAKANA LETTER MINNAN NASALIZED TONE-5 +1AFFD..1AFFE ; ID_Continue # Lm [2] KATAKANA LETTER MINNAN NASALIZED TONE-7..KATAKANA LETTER MINNAN NASALIZED TONE-8 +1B000..1B122 ; ID_Continue # Lo [291] KATAKANA LETTER ARCHAIC E..KATAKANA LETTER ARCHAIC WU 1B150..1B152 ; ID_Continue # Lo [3] HIRAGANA LETTER SMALL WI..HIRAGANA LETTER SMALL WO 1B164..1B167 ; ID_Continue # Lo [4] KATAKANA LETTER SMALL WI..KATAKANA LETTER SMALL N 1B170..1B2FB ; ID_Continue # Lo [396] NUSHU CHARACTER-1B170..NUSHU CHARACTER-1B2FB @@ -7819,6 +8009,8 @@ FFDA..FFDC ; ID_Continue # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HAN 1BC80..1BC88 ; ID_Continue # Lo [9] DUPLOYAN AFFIX HIGH ACUTE..DUPLOYAN AFFIX HIGH VERTICAL 1BC90..1BC99 ; ID_Continue # Lo [10] DUPLOYAN AFFIX LOW ACUTE..DUPLOYAN AFFIX LOW ARROW 1BC9D..1BC9E ; ID_Continue # Mn [2] DUPLOYAN THICK LETTER SELECTOR..DUPLOYAN DOUBLE MARK +1CF00..1CF2D ; ID_Continue # Mn [46] ZNAMENNY COMBINING MARK GORAZDO NIZKO S KRYZHEM ON LEFT..ZNAMENNY COMBINING MARK KRYZH ON LEFT +1CF30..1CF46 ; ID_Continue # Mn [23] ZNAMENNY COMBINING TONAL RANGE MARK MRACHNO..ZNAMENNY PRIZNAK MODIFIER ROG 1D165..1D166 ; ID_Continue # Mc [2] MUSICAL SYMBOL COMBINING STEM..MUSICAL SYMBOL COMBINING SPRECHGESANG STEM 1D167..1D169 ; ID_Continue # Mn [3] MUSICAL SYMBOL COMBINING TREMOLO-1..MUSICAL SYMBOL COMBINING TREMOLO-3 1D16D..1D172 ; ID_Continue # Mc [6] MUSICAL SYMBOL COMBINING AUGMENTATION DOT..MUSICAL SYMBOL COMBINING FLAG-5 @@ -7863,6 +8055,9 @@ FFDA..FFDC ; ID_Continue # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HAN 1DA84 ; ID_Continue # Mn SIGNWRITING LOCATION HEAD NECK 1DA9B..1DA9F ; ID_Continue # Mn [5] SIGNWRITING FILL MODIFIER-2..SIGNWRITING FILL MODIFIER-6 1DAA1..1DAAF ; ID_Continue # Mn [15] SIGNWRITING ROTATION MODIFIER-2..SIGNWRITING ROTATION MODIFIER-16 +1DF00..1DF09 ; ID_Continue # L& [10] LATIN SMALL LETTER FENG DIGRAPH WITH TRILL..LATIN SMALL LETTER T WITH HOOK AND RETROFLEX HOOK +1DF0A ; ID_Continue # Lo LATIN LETTER RETROFLEX CLICK WITH RETROFLEX HOOK +1DF0B..1DF1E ; ID_Continue # L& [20] LATIN SMALL LETTER ESH WITH DOUBLE BAR..LATIN SMALL LETTER S WITH CURL 1E000..1E006 ; ID_Continue # Mn [7] COMBINING GLAGOLITIC LETTER AZU..COMBINING GLAGOLITIC LETTER ZHIVETE 1E008..1E018 ; ID_Continue # Mn [17] COMBINING GLAGOLITIC LETTER ZEMLJA..COMBINING GLAGOLITIC LETTER HERU 1E01B..1E021 ; ID_Continue # Mn [7] COMBINING GLAGOLITIC LETTER SHTA..COMBINING GLAGOLITIC LETTER YATI @@ -7873,9 +8068,15 @@ FFDA..FFDC ; ID_Continue # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HAN 1E137..1E13D ; ID_Continue # Lm [7] NYIAKENG PUACHUE HMONG SIGN FOR PERSON..NYIAKENG PUACHUE HMONG SYLLABLE LENGTHENER 1E140..1E149 ; ID_Continue # Nd [10] NYIAKENG PUACHUE HMONG DIGIT ZERO..NYIAKENG PUACHUE HMONG DIGIT NINE 1E14E ; ID_Continue # Lo NYIAKENG PUACHUE HMONG LOGOGRAM NYAJ +1E290..1E2AD ; ID_Continue # Lo [30] TOTO LETTER PA..TOTO LETTER A +1E2AE ; ID_Continue # Mn TOTO SIGN RISING TONE 1E2C0..1E2EB ; ID_Continue # Lo [44] WANCHO LETTER AA..WANCHO LETTER YIH 1E2EC..1E2EF ; ID_Continue # Mn [4] WANCHO TONE TUP..WANCHO TONE KOINI 1E2F0..1E2F9 ; ID_Continue # Nd [10] WANCHO DIGIT ZERO..WANCHO DIGIT NINE +1E7E0..1E7E6 ; ID_Continue # Lo [7] ETHIOPIC SYLLABLE HHYA..ETHIOPIC SYLLABLE HHYO +1E7E8..1E7EB ; ID_Continue # Lo [4] ETHIOPIC SYLLABLE GURAGE HHWA..ETHIOPIC SYLLABLE HHWE +1E7ED..1E7EE ; ID_Continue # Lo [2] ETHIOPIC SYLLABLE GURAGE MWI..ETHIOPIC SYLLABLE GURAGE MWEE +1E7F0..1E7FE ; ID_Continue # Lo [15] ETHIOPIC SYLLABLE GURAGE QWI..ETHIOPIC SYLLABLE GURAGE PWEE 1E800..1E8C4 ; ID_Continue # Lo [197] MENDE KIKAKUI SYLLABLE M001 KI..MENDE KIKAKUI SYLLABLE M060 NYON 1E8D0..1E8D6 ; ID_Continue # Mn [7] MENDE KIKAKUI COMBINING NUMBER TEENS..MENDE KIKAKUI COMBINING NUMBER MILLIONS 1E900..1E943 ; ID_Continue # L& [68] ADLAM CAPITAL LETTER ALIF..ADLAM SMALL LETTER SHA @@ -7916,8 +8117,8 @@ FFDA..FFDC ; ID_Continue # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HAN 1EEA5..1EEA9 ; ID_Continue # Lo [5] ARABIC MATHEMATICAL DOUBLE-STRUCK WAW..ARABIC MATHEMATICAL DOUBLE-STRUCK YEH 1EEAB..1EEBB ; ID_Continue # Lo [17] ARABIC MATHEMATICAL DOUBLE-STRUCK LAM..ARABIC MATHEMATICAL DOUBLE-STRUCK GHAIN 1FBF0..1FBF9 ; ID_Continue # Nd [10] SEGMENTED DIGIT ZERO..SEGMENTED DIGIT NINE -20000..2A6DD ; ID_Continue # Lo [42718] CJK UNIFIED IDEOGRAPH-20000..CJK UNIFIED IDEOGRAPH-2A6DD -2A700..2B734 ; ID_Continue # Lo [4149] CJK UNIFIED IDEOGRAPH-2A700..CJK UNIFIED IDEOGRAPH-2B734 +20000..2A6DF ; ID_Continue # Lo [42720] CJK UNIFIED IDEOGRAPH-20000..CJK UNIFIED IDEOGRAPH-2A6DF +2A700..2B738 ; ID_Continue # Lo [4153] CJK UNIFIED IDEOGRAPH-2A700..CJK UNIFIED IDEOGRAPH-2B738 2B740..2B81D ; ID_Continue # Lo [222] CJK UNIFIED IDEOGRAPH-2B740..CJK UNIFIED IDEOGRAPH-2B81D 2B820..2CEA1 ; ID_Continue # Lo [5762] CJK UNIFIED IDEOGRAPH-2B820..CJK UNIFIED IDEOGRAPH-2CEA1 2CEB0..2EBE0 ; ID_Continue # Lo [7473] CJK UNIFIED IDEOGRAPH-2CEB0..CJK UNIFIED IDEOGRAPH-2EBE0 @@ -7925,7 +8126,7 @@ FFDA..FFDC ; ID_Continue # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HAN 30000..3134A ; ID_Continue # Lo [4939] CJK UNIFIED IDEOGRAPH-30000..CJK UNIFIED IDEOGRAPH-3134A E0100..E01EF ; ID_Continue # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256 -# Total code points: 134434 +# Total code points: 135072 # ================================================ @@ -7995,8 +8196,10 @@ E0100..E01EF ; ID_Continue # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR 0828 ; XID_Start # Lm SAMARITAN MODIFIER LETTER I 0840..0858 ; XID_Start # Lo [25] MANDAIC LETTER HALQA..MANDAIC LETTER AIN 0860..086A ; XID_Start # Lo [11] SYRIAC LETTER MALAYALAM NGA..SYRIAC LETTER MALAYALAM SSA -08A0..08B4 ; XID_Start # Lo [21] ARABIC LETTER BEH WITH SMALL V BELOW..ARABIC LETTER KAF WITH DOT BELOW -08B6..08C7 ; XID_Start # Lo [18] ARABIC LETTER BEH WITH SMALL MEEM ABOVE..ARABIC LETTER LAM WITH SMALL ARABIC LETTER TAH ABOVE +0870..0887 ; XID_Start # Lo [24] ARABIC LETTER ALEF WITH ATTACHED FATHA..ARABIC BASELINE ROUND DOT +0889..088E ; XID_Start # Lo [6] ARABIC LETTER NOON WITH INVERTED SMALL V..ARABIC VERTICAL TAIL +08A0..08C8 ; XID_Start # Lo [41] ARABIC LETTER BEH WITH SMALL V BELOW..ARABIC LETTER GRAF +08C9 ; XID_Start # Lm ARABIC SMALL FARSI YEH 0904..0939 ; XID_Start # Lo [54] DEVANAGARI LETTER SHORT A..DEVANAGARI LETTER HA 093D ; XID_Start # Lo DEVANAGARI SIGN AVAGRAHA 0950 ; XID_Start # Lo DEVANAGARI OM @@ -8062,6 +8265,7 @@ E0100..E01EF ; ID_Continue # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR 0C2A..0C39 ; XID_Start # Lo [16] TELUGU LETTER PA..TELUGU LETTER HA 0C3D ; XID_Start # Lo TELUGU SIGN AVAGRAHA 0C58..0C5A ; XID_Start # Lo [3] TELUGU LETTER TSA..TELUGU LETTER RRRA +0C5D ; XID_Start # Lo TELUGU LETTER NAKAARA POLLU 0C60..0C61 ; XID_Start # Lo [2] TELUGU LETTER VOCALIC RR..TELUGU LETTER VOCALIC LL 0C80 ; XID_Start # Lo KANNADA SIGN SPACING CANDRABINDU 0C85..0C8C ; XID_Start # Lo [8] KANNADA LETTER A..KANNADA LETTER VOCALIC L @@ -8070,7 +8274,7 @@ E0100..E01EF ; ID_Continue # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR 0CAA..0CB3 ; XID_Start # Lo [10] KANNADA LETTER PA..KANNADA LETTER LLA 0CB5..0CB9 ; XID_Start # Lo [5] KANNADA LETTER VA..KANNADA LETTER HA 0CBD ; XID_Start # Lo KANNADA SIGN AVAGRAHA -0CDE ; XID_Start # Lo KANNADA LETTER FA +0CDD..0CDE ; XID_Start # Lo [2] KANNADA LETTER NAKAARA POLLU..KANNADA LETTER FA 0CE0..0CE1 ; XID_Start # Lo [2] KANNADA LETTER VOCALIC RR..KANNADA LETTER VOCALIC LL 0CF1..0CF2 ; XID_Start # Lo [2] KANNADA SIGN JIHVAMULIYA..KANNADA SIGN UPADHMANIYA 0D04..0D0C ; XID_Start # Lo [9] MALAYALAM LETTER VEDIC ANUSVARA..MALAYALAM LETTER VOCALIC L @@ -8145,9 +8349,8 @@ E0100..E01EF ; ID_Continue # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR 16A0..16EA ; XID_Start # Lo [75] RUNIC LETTER FEHU FEOH FE F..RUNIC LETTER X 16EE..16F0 ; XID_Start # Nl [3] RUNIC ARLAUG SYMBOL..RUNIC BELGTHOR SYMBOL 16F1..16F8 ; XID_Start # Lo [8] RUNIC LETTER K..RUNIC LETTER FRANKS CASKET AESC -1700..170C ; XID_Start # Lo [13] TAGALOG LETTER A..TAGALOG LETTER YA -170E..1711 ; XID_Start # Lo [4] TAGALOG LETTER LA..TAGALOG LETTER HA -1720..1731 ; XID_Start # Lo [18] HANUNOO LETTER A..HANUNOO LETTER HA +1700..1711 ; XID_Start # Lo [18] TAGALOG LETTER A..TAGALOG LETTER HA +171F..1731 ; XID_Start # Lo [19] TAGALOG LETTER ARCHAIC RA..HANUNOO LETTER HA 1740..1751 ; XID_Start # Lo [18] BUHID LETTER A..BUHID LETTER HA 1760..176C ; XID_Start # Lo [13] TAGBANWA LETTER A..TAGBANWA LETTER YA 176E..1770 ; XID_Start # Lo [3] TAGBANWA LETTER LA..TAGBANWA LETTER SA @@ -8171,7 +8374,7 @@ E0100..E01EF ; ID_Continue # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR 1A20..1A54 ; XID_Start # Lo [53] TAI THAM LETTER HIGH KA..TAI THAM LETTER GREAT SA 1AA7 ; XID_Start # Lm TAI THAM SIGN MAI YAMOK 1B05..1B33 ; XID_Start # Lo [47] BALINESE LETTER AKARA..BALINESE LETTER HA -1B45..1B4B ; XID_Start # Lo [7] BALINESE LETTER KAF SASAK..BALINESE LETTER ASYURA SASAK +1B45..1B4C ; XID_Start # Lo [8] BALINESE LETTER KAF SASAK..BALINESE LETTER ARCHAIC JNYA 1B83..1BA0 ; XID_Start # Lo [30] SUNDANESE LETTER A..SUNDANESE LETTER HA 1BAE..1BAF ; XID_Start # Lo [2] SUNDANESE LETTER KHA..SUNDANESE LETTER SYA 1BBA..1BE5 ; XID_Start # Lo [44] SUNDANESE AVAGRAHA..BATAK LETTER U @@ -8234,9 +8437,7 @@ E0100..E01EF ; ID_Continue # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR 2160..2182 ; XID_Start # Nl [35] ROMAN NUMERAL ONE..ROMAN NUMERAL TEN THOUSAND 2183..2184 ; XID_Start # L& [2] ROMAN NUMERAL REVERSED ONE HUNDRED..LATIN SMALL LETTER REVERSED C 2185..2188 ; XID_Start # Nl [4] ROMAN NUMERAL SIX LATE FORM..ROMAN NUMERAL ONE HUNDRED THOUSAND -2C00..2C2E ; XID_Start # L& [47] GLAGOLITIC CAPITAL LETTER AZU..GLAGOLITIC CAPITAL LETTER LATINATE MYSLITE -2C30..2C5E ; XID_Start # L& [47] GLAGOLITIC SMALL LETTER AZU..GLAGOLITIC SMALL LETTER LATINATE MYSLITE -2C60..2C7B ; XID_Start # L& [28] LATIN CAPITAL LETTER L WITH DOUBLE BAR..LATIN LETTER SMALL CAPITAL TURNED E +2C00..2C7B ; XID_Start # L& [124] GLAGOLITIC CAPITAL LETTER AZU..LATIN LETTER SMALL CAPITAL TURNED E 2C7C..2C7D ; XID_Start # Lm [2] LATIN SUBSCRIPT SMALL LETTER J..MODIFIER LETTER CAPITAL V 2C7E..2CE4 ; XID_Start # L& [103] LATIN CAPITAL LETTER S WITH SWASH TAIL..COPTIC SYMBOL KAI 2CEB..2CEE ; XID_Start # L& [4] COPTIC CAPITAL LETTER CRYPTOGRAMMIC SHEI..COPTIC SMALL LETTER CRYPTOGRAMMIC GANGIA @@ -8274,8 +8475,7 @@ E0100..E01EF ; ID_Continue # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR 31A0..31BF ; XID_Start # Lo [32] BOPOMOFO LETTER BU..BOPOMOFO LETTER AH 31F0..31FF ; XID_Start # Lo [16] KATAKANA LETTER SMALL KU..KATAKANA LETTER SMALL RO 3400..4DBF ; XID_Start # Lo [6592] CJK UNIFIED IDEOGRAPH-3400..CJK UNIFIED IDEOGRAPH-4DBF -4E00..9FFC ; XID_Start # Lo [20989] CJK UNIFIED IDEOGRAPH-4E00..CJK UNIFIED IDEOGRAPH-9FFC -A000..A014 ; XID_Start # Lo [21] YI SYLLABLE IT..YI SYLLABLE E +4E00..A014 ; XID_Start # Lo [21013] CJK UNIFIED IDEOGRAPH-4E00..YI SYLLABLE E A015 ; XID_Start # Lm YI SYLLABLE WU A016..A48C ; XID_Start # Lo [1143] YI SYLLABLE BIT..YI SYLLABLE YYR A4D0..A4F7 ; XID_Start # Lo [40] LISU LETTER BA..LISU LETTER OE @@ -8298,8 +8498,11 @@ A771..A787 ; XID_Start # L& [23] LATIN SMALL LETTER DUM..LATIN SMALL LETTER A788 ; XID_Start # Lm MODIFIER LETTER LOW CIRCUMFLEX ACCENT A78B..A78E ; XID_Start # L& [4] LATIN CAPITAL LETTER SALTILLO..LATIN SMALL LETTER L WITH RETROFLEX HOOK AND BELT A78F ; XID_Start # Lo LATIN LETTER SINOLOGICAL DOT -A790..A7BF ; XID_Start # L& [48] LATIN CAPITAL LETTER N WITH DESCENDER..LATIN SMALL LETTER GLOTTAL U -A7C2..A7CA ; XID_Start # L& [9] LATIN CAPITAL LETTER ANGLICANA W..LATIN SMALL LETTER S WITH SHORT STROKE OVERLAY +A790..A7CA ; XID_Start # L& [59] LATIN CAPITAL LETTER N WITH DESCENDER..LATIN SMALL LETTER S WITH SHORT STROKE OVERLAY +A7D0..A7D1 ; XID_Start # L& [2] LATIN CAPITAL LETTER CLOSED INSULAR G..LATIN SMALL LETTER CLOSED INSULAR G +A7D3 ; XID_Start # L& LATIN SMALL LETTER DOUBLE THORN +A7D5..A7D9 ; XID_Start # L& [5] LATIN SMALL LETTER DOUBLE WYNN..LATIN SMALL LETTER SIGMOID S +A7F2..A7F4 ; XID_Start # Lm [3] MODIFIER LETTER CAPITAL C..MODIFIER LETTER CAPITAL Q A7F5..A7F6 ; XID_Start # L& [2] LATIN CAPITAL LETTER REVERSED HALF H..LATIN SMALL LETTER REVERSED HALF H A7F7 ; XID_Start # Lo LATIN EPIGRAPHIC LETTER SIDEWAYS I A7F8..A7F9 ; XID_Start # Lm [2] MODIFIER LETTER CAPITAL H WITH STROKE..MODIFIER LETTER SMALL LIGATURE OE @@ -8414,9 +8617,20 @@ FFDA..FFDC ; XID_Start # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGU 104D8..104FB ; XID_Start # L& [36] OSAGE SMALL LETTER A..OSAGE SMALL LETTER ZHA 10500..10527 ; XID_Start # Lo [40] ELBASAN LETTER A..ELBASAN LETTER KHE 10530..10563 ; XID_Start # Lo [52] CAUCASIAN ALBANIAN LETTER ALT..CAUCASIAN ALBANIAN LETTER KIW +10570..1057A ; XID_Start # L& [11] VITHKUQI CAPITAL LETTER A..VITHKUQI CAPITAL LETTER GA +1057C..1058A ; XID_Start # L& [15] VITHKUQI CAPITAL LETTER HA..VITHKUQI CAPITAL LETTER RE +1058C..10592 ; XID_Start # L& [7] VITHKUQI CAPITAL LETTER SE..VITHKUQI CAPITAL LETTER XE +10594..10595 ; XID_Start # L& [2] VITHKUQI CAPITAL LETTER Y..VITHKUQI CAPITAL LETTER ZE +10597..105A1 ; XID_Start # L& [11] VITHKUQI SMALL LETTER A..VITHKUQI SMALL LETTER GA +105A3..105B1 ; XID_Start # L& [15] VITHKUQI SMALL LETTER HA..VITHKUQI SMALL LETTER RE +105B3..105B9 ; XID_Start # L& [7] VITHKUQI SMALL LETTER SE..VITHKUQI SMALL LETTER XE +105BB..105BC ; XID_Start # L& [2] VITHKUQI SMALL LETTER Y..VITHKUQI SMALL LETTER ZE 10600..10736 ; XID_Start # Lo [311] LINEAR A SIGN AB001..LINEAR A SIGN A664 10740..10755 ; XID_Start # Lo [22] LINEAR A SIGN A701 A..LINEAR A SIGN A732 JE 10760..10767 ; XID_Start # Lo [8] LINEAR A SIGN A800..LINEAR A SIGN A807 +10780..10785 ; XID_Start # Lm [6] MODIFIER LETTER SMALL CAPITAL AA..MODIFIER LETTER SMALL B WITH HOOK +10787..107B0 ; XID_Start # Lm [42] MODIFIER LETTER SMALL DZ DIGRAPH..MODIFIER LETTER SMALL V WITH RIGHT HOOK +107B2..107BA ; XID_Start # Lm [9] MODIFIER LETTER SMALL CAPITAL Y..MODIFIER LETTER SMALL S WITH CURL 10800..10805 ; XID_Start # Lo [6] CYPRIOT SYLLABLE A..CYPRIOT SYLLABLE JA 10808 ; XID_Start # Lo CYPRIOT SYLLABLE JO 1080A..10835 ; XID_Start # Lo [44] CYPRIOT SYLLABLE KA..CYPRIOT SYLLABLE WO @@ -8452,9 +8666,12 @@ FFDA..FFDC ; XID_Start # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGU 10F00..10F1C ; XID_Start # Lo [29] OLD SOGDIAN LETTER ALEPH..OLD SOGDIAN LETTER FINAL TAW WITH VERTICAL TAIL 10F27 ; XID_Start # Lo OLD SOGDIAN LIGATURE AYIN-DALETH 10F30..10F45 ; XID_Start # Lo [22] SOGDIAN LETTER ALEPH..SOGDIAN INDEPENDENT SHIN +10F70..10F81 ; XID_Start # Lo [18] OLD UYGHUR LETTER ALEPH..OLD UYGHUR LETTER LESH 10FB0..10FC4 ; XID_Start # Lo [21] CHORASMIAN LETTER ALEPH..CHORASMIAN LETTER TAW 10FE0..10FF6 ; XID_Start # Lo [23] ELYMAIC LETTER ALEPH..ELYMAIC LIGATURE ZAYIN-YODH 11003..11037 ; XID_Start # Lo [53] BRAHMI SIGN JIHVAMULIYA..BRAHMI LETTER OLD TAMIL NNNA +11071..11072 ; XID_Start # Lo [2] BRAHMI LETTER OLD TAMIL SHORT E..BRAHMI LETTER OLD TAMIL SHORT O +11075 ; XID_Start # Lo BRAHMI LETTER OLD TAMIL LLA 11083..110AF ; XID_Start # Lo [45] KAITHI LETTER A..KAITHI LETTER HA 110D0..110E8 ; XID_Start # Lo [25] SORA SOMPENG LETTER SAH..SORA SOMPENG LETTER MAE 11103..11126 ; XID_Start # Lo [36] CHAKMA LETTER AA..CHAKMA LETTER HAA @@ -8496,6 +8713,7 @@ FFDA..FFDC ; XID_Start # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGU 11680..116AA ; XID_Start # Lo [43] TAKRI LETTER A..TAKRI LETTER RRA 116B8 ; XID_Start # Lo TAKRI LETTER ARCHAIC KHA 11700..1171A ; XID_Start # Lo [27] AHOM LETTER KA..AHOM LETTER ALTERNATE BA +11740..11746 ; XID_Start # Lo [7] AHOM LETTER CA..AHOM LETTER LLA 11800..1182B ; XID_Start # Lo [44] DOGRA LETTER A..DOGRA LETTER RRA 118A0..118DF ; XID_Start # L& [64] WARANG CITI CAPITAL LETTER NGAA..WARANG CITI SMALL LETTER VIYO 118FF..11906 ; XID_Start # Lo [8] WARANG CITI OM..DIVES AKURU LETTER E @@ -8515,7 +8733,7 @@ FFDA..FFDC ; XID_Start # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGU 11A50 ; XID_Start # Lo SOYOMBO LETTER A 11A5C..11A89 ; XID_Start # Lo [46] SOYOMBO LETTER KA..SOYOMBO CLUSTER-INITIAL LETTER SA 11A9D ; XID_Start # Lo SOYOMBO MARK PLUTA -11AC0..11AF8 ; XID_Start # Lo [57] PAU CIN HAU LETTER PA..PAU CIN HAU GLOTTAL STOP FINAL +11AB0..11AF8 ; XID_Start # Lo [73] CANADIAN SYLLABICS NATTILIK HI..PAU CIN HAU GLOTTAL STOP FINAL 11C00..11C08 ; XID_Start # Lo [9] BHAIKSUKI LETTER A..BHAIKSUKI LETTER VOCALIC L 11C0A..11C2E ; XID_Start # Lo [37] BHAIKSUKI LETTER E..BHAIKSUKI LETTER HA 11C40 ; XID_Start # Lo BHAIKSUKI SIGN AVAGRAHA @@ -8533,10 +8751,12 @@ FFDA..FFDC ; XID_Start # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGU 12000..12399 ; XID_Start # Lo [922] CUNEIFORM SIGN A..CUNEIFORM SIGN U U 12400..1246E ; XID_Start # Nl [111] CUNEIFORM NUMERIC SIGN TWO ASH..CUNEIFORM NUMERIC SIGN NINE U VARIANT FORM 12480..12543 ; XID_Start # Lo [196] CUNEIFORM SIGN AB TIMES NUN TENU..CUNEIFORM SIGN ZU5 TIMES THREE DISH TENU +12F90..12FF0 ; XID_Start # Lo [97] CYPRO-MINOAN SIGN CM001..CYPRO-MINOAN SIGN CM114 13000..1342E ; XID_Start # Lo [1071] EGYPTIAN HIEROGLYPH A001..EGYPTIAN HIEROGLYPH AA032 14400..14646 ; XID_Start # Lo [583] ANATOLIAN HIEROGLYPH A001..ANATOLIAN HIEROGLYPH A530 16800..16A38 ; XID_Start # Lo [569] BAMUM LETTER PHASE-A NGKUE MFON..BAMUM LETTER PHASE-F VUEQ 16A40..16A5E ; XID_Start # Lo [31] MRO LETTER TA..MRO LETTER TEK +16A70..16ABE ; XID_Start # Lo [79] TANGSA LETTER OZ..TANGSA LETTER ZA 16AD0..16AED ; XID_Start # Lo [30] BASSA VAH LETTER ENNI..BASSA VAH LETTER I 16B00..16B2F ; XID_Start # Lo [48] PAHAWH HMONG VOWEL KEEB..PAHAWH HMONG CONSONANT CAU 16B40..16B43 ; XID_Start # Lm [4] PAHAWH HMONG SIGN VOS SEEV..PAHAWH HMONG SIGN IB YAM @@ -8551,7 +8771,10 @@ FFDA..FFDC ; XID_Start # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGU 17000..187F7 ; XID_Start # Lo [6136] TANGUT IDEOGRAPH-17000..TANGUT IDEOGRAPH-187F7 18800..18CD5 ; XID_Start # Lo [1238] TANGUT COMPONENT-001..KHITAN SMALL SCRIPT CHARACTER-18CD5 18D00..18D08 ; XID_Start # Lo [9] TANGUT IDEOGRAPH-18D00..TANGUT IDEOGRAPH-18D08 -1B000..1B11E ; XID_Start # Lo [287] KATAKANA LETTER ARCHAIC E..HENTAIGANA LETTER N-MU-MO-2 +1AFF0..1AFF3 ; XID_Start # Lm [4] KATAKANA LETTER MINNAN TONE-2..KATAKANA LETTER MINNAN TONE-5 +1AFF5..1AFFB ; XID_Start # Lm [7] KATAKANA LETTER MINNAN TONE-7..KATAKANA LETTER MINNAN NASALIZED TONE-5 +1AFFD..1AFFE ; XID_Start # Lm [2] KATAKANA LETTER MINNAN NASALIZED TONE-7..KATAKANA LETTER MINNAN NASALIZED TONE-8 +1B000..1B122 ; XID_Start # Lo [291] KATAKANA LETTER ARCHAIC E..KATAKANA LETTER ARCHAIC WU 1B150..1B152 ; XID_Start # Lo [3] HIRAGANA LETTER SMALL WI..HIRAGANA LETTER SMALL WO 1B164..1B167 ; XID_Start # Lo [4] KATAKANA LETTER SMALL WI..KATAKANA LETTER SMALL N 1B170..1B2FB ; XID_Start # Lo [396] NUSHU CHARACTER-1B170..NUSHU CHARACTER-1B2FB @@ -8589,10 +8812,18 @@ FFDA..FFDC ; XID_Start # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGU 1D78A..1D7A8 ; XID_Start # L& [31] MATHEMATICAL SANS-SERIF BOLD EPSILON SYMBOL..MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL OMEGA 1D7AA..1D7C2 ; XID_Start # L& [25] MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ALPHA..MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMEGA 1D7C4..1D7CB ; XID_Start # L& [8] MATHEMATICAL SANS-SERIF BOLD ITALIC EPSILON SYMBOL..MATHEMATICAL BOLD SMALL DIGAMMA +1DF00..1DF09 ; XID_Start # L& [10] LATIN SMALL LETTER FENG DIGRAPH WITH TRILL..LATIN SMALL LETTER T WITH HOOK AND RETROFLEX HOOK +1DF0A ; XID_Start # Lo LATIN LETTER RETROFLEX CLICK WITH RETROFLEX HOOK +1DF0B..1DF1E ; XID_Start # L& [20] LATIN SMALL LETTER ESH WITH DOUBLE BAR..LATIN SMALL LETTER S WITH CURL 1E100..1E12C ; XID_Start # Lo [45] NYIAKENG PUACHUE HMONG LETTER MA..NYIAKENG PUACHUE HMONG LETTER W 1E137..1E13D ; XID_Start # Lm [7] NYIAKENG PUACHUE HMONG SIGN FOR PERSON..NYIAKENG PUACHUE HMONG SYLLABLE LENGTHENER 1E14E ; XID_Start # Lo NYIAKENG PUACHUE HMONG LOGOGRAM NYAJ +1E290..1E2AD ; XID_Start # Lo [30] TOTO LETTER PA..TOTO LETTER A 1E2C0..1E2EB ; XID_Start # Lo [44] WANCHO LETTER AA..WANCHO LETTER YIH +1E7E0..1E7E6 ; XID_Start # Lo [7] ETHIOPIC SYLLABLE HHYA..ETHIOPIC SYLLABLE HHYO +1E7E8..1E7EB ; XID_Start # Lo [4] ETHIOPIC SYLLABLE GURAGE HHWA..ETHIOPIC SYLLABLE HHWE +1E7ED..1E7EE ; XID_Start # Lo [2] ETHIOPIC SYLLABLE GURAGE MWI..ETHIOPIC SYLLABLE GURAGE MWEE +1E7F0..1E7FE ; XID_Start # Lo [15] ETHIOPIC SYLLABLE GURAGE QWI..ETHIOPIC SYLLABLE GURAGE PWEE 1E800..1E8C4 ; XID_Start # Lo [197] MENDE KIKAKUI SYLLABLE M001 KI..MENDE KIKAKUI SYLLABLE M060 NYON 1E900..1E943 ; XID_Start # L& [68] ADLAM CAPITAL LETTER ALIF..ADLAM SMALL LETTER SHA 1E94B ; XID_Start # Lm ADLAM NASALIZATION MARK @@ -8629,15 +8860,15 @@ FFDA..FFDC ; XID_Start # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGU 1EEA1..1EEA3 ; XID_Start # Lo [3] ARABIC MATHEMATICAL DOUBLE-STRUCK BEH..ARABIC MATHEMATICAL DOUBLE-STRUCK DAL 1EEA5..1EEA9 ; XID_Start # Lo [5] ARABIC MATHEMATICAL DOUBLE-STRUCK WAW..ARABIC MATHEMATICAL DOUBLE-STRUCK YEH 1EEAB..1EEBB ; XID_Start # Lo [17] ARABIC MATHEMATICAL DOUBLE-STRUCK LAM..ARABIC MATHEMATICAL DOUBLE-STRUCK GHAIN -20000..2A6DD ; XID_Start # Lo [42718] CJK UNIFIED IDEOGRAPH-20000..CJK UNIFIED IDEOGRAPH-2A6DD -2A700..2B734 ; XID_Start # Lo [4149] CJK UNIFIED IDEOGRAPH-2A700..CJK UNIFIED IDEOGRAPH-2B734 +20000..2A6DF ; XID_Start # Lo [42720] CJK UNIFIED IDEOGRAPH-20000..CJK UNIFIED IDEOGRAPH-2A6DF +2A700..2B738 ; XID_Start # Lo [4153] CJK UNIFIED IDEOGRAPH-2A700..CJK UNIFIED IDEOGRAPH-2B738 2B740..2B81D ; XID_Start # Lo [222] CJK UNIFIED IDEOGRAPH-2B740..CJK UNIFIED IDEOGRAPH-2B81D 2B820..2CEA1 ; XID_Start # Lo [5762] CJK UNIFIED IDEOGRAPH-2B820..CJK UNIFIED IDEOGRAPH-2CEA1 2CEB0..2EBE0 ; XID_Start # Lo [7473] CJK UNIFIED IDEOGRAPH-2CEB0..CJK UNIFIED IDEOGRAPH-2EBE0 2F800..2FA1D ; XID_Start # Lo [542] CJK COMPATIBILITY IDEOGRAPH-2F800..CJK COMPATIBILITY IDEOGRAPH-2FA1D 30000..3134A ; XID_Start # Lo [4939] CJK UNIFIED IDEOGRAPH-30000..CJK UNIFIED IDEOGRAPH-3134A -# Total code points: 131459 +# Total code points: 131974 # ================================================ @@ -8738,9 +8969,12 @@ FFDA..FFDC ; XID_Start # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGU 0840..0858 ; XID_Continue # Lo [25] MANDAIC LETTER HALQA..MANDAIC LETTER AIN 0859..085B ; XID_Continue # Mn [3] MANDAIC AFFRICATION MARK..MANDAIC GEMINATION MARK 0860..086A ; XID_Continue # Lo [11] SYRIAC LETTER MALAYALAM NGA..SYRIAC LETTER MALAYALAM SSA -08A0..08B4 ; XID_Continue # Lo [21] ARABIC LETTER BEH WITH SMALL V BELOW..ARABIC LETTER KAF WITH DOT BELOW -08B6..08C7 ; XID_Continue # Lo [18] ARABIC LETTER BEH WITH SMALL MEEM ABOVE..ARABIC LETTER LAM WITH SMALL ARABIC LETTER TAH ABOVE -08D3..08E1 ; XID_Continue # Mn [15] ARABIC SMALL LOW WAW..ARABIC SMALL HIGH SIGN SAFHA +0870..0887 ; XID_Continue # Lo [24] ARABIC LETTER ALEF WITH ATTACHED FATHA..ARABIC BASELINE ROUND DOT +0889..088E ; XID_Continue # Lo [6] ARABIC LETTER NOON WITH INVERTED SMALL V..ARABIC VERTICAL TAIL +0898..089F ; XID_Continue # Mn [8] ARABIC SMALL HIGH WORD AL-JUZ..ARABIC HALF MADDA OVER MADDA +08A0..08C8 ; XID_Continue # Lo [41] ARABIC LETTER BEH WITH SMALL V BELOW..ARABIC LETTER GRAF +08C9 ; XID_Continue # Lm ARABIC SMALL FARSI YEH +08CA..08E1 ; XID_Continue # Mn [24] ARABIC SMALL HIGH FARSI YEH..ARABIC SMALL HIGH SIGN SAFHA 08E3..0902 ; XID_Continue # Mn [32] ARABIC TURNED DAMMA BELOW..DEVANAGARI SIGN ANUSVARA 0903 ; XID_Continue # Mc DEVANAGARI SIGN VISARGA 0904..0939 ; XID_Continue # Lo [54] DEVANAGARI LETTER SHORT A..DEVANAGARI LETTER HA @@ -8878,6 +9112,7 @@ FFDA..FFDC ; XID_Start # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGU 0C0E..0C10 ; XID_Continue # Lo [3] TELUGU LETTER E..TELUGU LETTER AI 0C12..0C28 ; XID_Continue # Lo [23] TELUGU LETTER O..TELUGU LETTER NA 0C2A..0C39 ; XID_Continue # Lo [16] TELUGU LETTER PA..TELUGU LETTER HA +0C3C ; XID_Continue # Mn TELUGU SIGN NUKTA 0C3D ; XID_Continue # Lo TELUGU SIGN AVAGRAHA 0C3E..0C40 ; XID_Continue # Mn [3] TELUGU VOWEL SIGN AA..TELUGU VOWEL SIGN II 0C41..0C44 ; XID_Continue # Mc [4] TELUGU VOWEL SIGN U..TELUGU VOWEL SIGN VOCALIC RR @@ -8885,6 +9120,7 @@ FFDA..FFDC ; XID_Start # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGU 0C4A..0C4D ; XID_Continue # Mn [4] TELUGU VOWEL SIGN O..TELUGU SIGN VIRAMA 0C55..0C56 ; XID_Continue # Mn [2] TELUGU LENGTH MARK..TELUGU AI LENGTH MARK 0C58..0C5A ; XID_Continue # Lo [3] TELUGU LETTER TSA..TELUGU LETTER RRRA +0C5D ; XID_Continue # Lo TELUGU LETTER NAKAARA POLLU 0C60..0C61 ; XID_Continue # Lo [2] TELUGU LETTER VOCALIC RR..TELUGU LETTER VOCALIC LL 0C62..0C63 ; XID_Continue # Mn [2] TELUGU VOWEL SIGN VOCALIC L..TELUGU VOWEL SIGN VOCALIC LL 0C66..0C6F ; XID_Continue # Nd [10] TELUGU DIGIT ZERO..TELUGU DIGIT NINE @@ -8906,7 +9142,7 @@ FFDA..FFDC ; XID_Start # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGU 0CCA..0CCB ; XID_Continue # Mc [2] KANNADA VOWEL SIGN O..KANNADA VOWEL SIGN OO 0CCC..0CCD ; XID_Continue # Mn [2] KANNADA VOWEL SIGN AU..KANNADA SIGN VIRAMA 0CD5..0CD6 ; XID_Continue # Mc [2] KANNADA LENGTH MARK..KANNADA AI LENGTH MARK -0CDE ; XID_Continue # Lo KANNADA LETTER FA +0CDD..0CDE ; XID_Continue # Lo [2] KANNADA LETTER NAKAARA POLLU..KANNADA LETTER FA 0CE0..0CE1 ; XID_Continue # Lo [2] KANNADA LETTER VOCALIC RR..KANNADA LETTER VOCALIC LL 0CE2..0CE3 ; XID_Continue # Mn [2] KANNADA VOWEL SIGN VOCALIC L..KANNADA VOWEL SIGN VOCALIC LL 0CE6..0CEF ; XID_Continue # Nd [10] KANNADA DIGIT ZERO..KANNADA DIGIT NINE @@ -9050,11 +9286,12 @@ FFDA..FFDC ; XID_Start # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGU 16A0..16EA ; XID_Continue # Lo [75] RUNIC LETTER FEHU FEOH FE F..RUNIC LETTER X 16EE..16F0 ; XID_Continue # Nl [3] RUNIC ARLAUG SYMBOL..RUNIC BELGTHOR SYMBOL 16F1..16F8 ; XID_Continue # Lo [8] RUNIC LETTER K..RUNIC LETTER FRANKS CASKET AESC -1700..170C ; XID_Continue # Lo [13] TAGALOG LETTER A..TAGALOG LETTER YA -170E..1711 ; XID_Continue # Lo [4] TAGALOG LETTER LA..TAGALOG LETTER HA +1700..1711 ; XID_Continue # Lo [18] TAGALOG LETTER A..TAGALOG LETTER HA 1712..1714 ; XID_Continue # Mn [3] TAGALOG VOWEL SIGN I..TAGALOG SIGN VIRAMA -1720..1731 ; XID_Continue # Lo [18] HANUNOO LETTER A..HANUNOO LETTER HA -1732..1734 ; XID_Continue # Mn [3] HANUNOO VOWEL SIGN I..HANUNOO SIGN PAMUDPOD +1715 ; XID_Continue # Mc TAGALOG SIGN PAMUDPOD +171F..1731 ; XID_Continue # Lo [19] TAGALOG LETTER ARCHAIC RA..HANUNOO LETTER HA +1732..1733 ; XID_Continue # Mn [2] HANUNOO VOWEL SIGN I..HANUNOO VOWEL SIGN U +1734 ; XID_Continue # Mc HANUNOO SIGN PAMUDPOD 1740..1751 ; XID_Continue # Lo [18] BUHID LETTER A..BUHID LETTER HA 1752..1753 ; XID_Continue # Mn [2] BUHID VOWEL SIGN I..BUHID VOWEL SIGN U 1760..176C ; XID_Continue # Lo [13] TAGBANWA LETTER A..TAGBANWA LETTER YA @@ -9073,6 +9310,7 @@ FFDA..FFDC ; XID_Start # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGU 17DD ; XID_Continue # Mn KHMER SIGN ATTHACAN 17E0..17E9 ; XID_Continue # Nd [10] KHMER DIGIT ZERO..KHMER DIGIT NINE 180B..180D ; XID_Continue # Mn [3] MONGOLIAN FREE VARIATION SELECTOR ONE..MONGOLIAN FREE VARIATION SELECTOR THREE +180F ; XID_Continue # Mn MONGOLIAN FREE VARIATION SELECTOR FOUR 1810..1819 ; XID_Continue # Nd [10] MONGOLIAN DIGIT ZERO..MONGOLIAN DIGIT NINE 1820..1842 ; XID_Continue # Lo [35] MONGOLIAN LETTER A..MONGOLIAN LETTER CHI 1843 ; XID_Continue # Lm MONGOLIAN LETTER TODO LONG VOWEL SIGN @@ -9120,7 +9358,7 @@ FFDA..FFDC ; XID_Start # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGU 1A90..1A99 ; XID_Continue # Nd [10] TAI THAM THAM DIGIT ZERO..TAI THAM THAM DIGIT NINE 1AA7 ; XID_Continue # Lm TAI THAM SIGN MAI YAMOK 1AB0..1ABD ; XID_Continue # Mn [14] COMBINING DOUBLED CIRCUMFLEX ACCENT..COMBINING PARENTHESES BELOW -1ABF..1AC0 ; XID_Continue # Mn [2] COMBINING LATIN SMALL LETTER W BELOW..COMBINING LATIN SMALL LETTER TURNED W BELOW +1ABF..1ACE ; XID_Continue # Mn [16] COMBINING LATIN SMALL LETTER W BELOW..COMBINING LATIN SMALL LETTER INSULAR T 1B00..1B03 ; XID_Continue # Mn [4] BALINESE SIGN ULU RICEM..BALINESE SIGN SURANG 1B04 ; XID_Continue # Mc BALINESE SIGN BISAH 1B05..1B33 ; XID_Continue # Lo [47] BALINESE LETTER AKARA..BALINESE LETTER HA @@ -9132,7 +9370,7 @@ FFDA..FFDC ; XID_Start # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGU 1B3D..1B41 ; XID_Continue # Mc [5] BALINESE VOWEL SIGN LA LENGA TEDUNG..BALINESE VOWEL SIGN TALING REPA TEDUNG 1B42 ; XID_Continue # Mn BALINESE VOWEL SIGN PEPET 1B43..1B44 ; XID_Continue # Mc [2] BALINESE VOWEL SIGN PEPET TEDUNG..BALINESE ADEG ADEG -1B45..1B4B ; XID_Continue # Lo [7] BALINESE LETTER KAF SASAK..BALINESE LETTER ASYURA SASAK +1B45..1B4C ; XID_Continue # Lo [8] BALINESE LETTER KAF SASAK..BALINESE LETTER ARCHAIC JNYA 1B50..1B59 ; XID_Continue # Nd [10] BALINESE DIGIT ZERO..BALINESE DIGIT NINE 1B6B..1B73 ; XID_Continue # Mn [9] BALINESE MUSICAL SYMBOL COMBINING TEGEH..BALINESE MUSICAL SYMBOL COMBINING GONG 1B80..1B81 ; XID_Continue # Mn [2] SUNDANESE SIGN PANYECEK..SUNDANESE SIGN PANGLAYAR @@ -9186,8 +9424,7 @@ FFDA..FFDC ; XID_Start # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGU 1D78 ; XID_Continue # Lm MODIFIER LETTER CYRILLIC EN 1D79..1D9A ; XID_Continue # L& [34] LATIN SMALL LETTER INSULAR G..LATIN SMALL LETTER EZH WITH RETROFLEX HOOK 1D9B..1DBF ; XID_Continue # Lm [37] MODIFIER LETTER SMALL TURNED ALPHA..MODIFIER LETTER SMALL THETA -1DC0..1DF9 ; XID_Continue # Mn [58] COMBINING DOTTED GRAVE ACCENT..COMBINING WIDE INVERTED BRIDGE BELOW -1DFB..1DFF ; XID_Continue # Mn [5] COMBINING DELETION MARK..COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW +1DC0..1DFF ; XID_Continue # Mn [64] COMBINING DOTTED GRAVE ACCENT..COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW 1E00..1F15 ; XID_Continue # L& [278] LATIN CAPITAL LETTER A WITH RING BELOW..GREEK SMALL LETTER EPSILON WITH DASIA AND OXIA 1F18..1F1D ; XID_Continue # L& [6] GREEK CAPITAL LETTER EPSILON WITH PSILI..GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA 1F20..1F45 ; XID_Continue # L& [38] GREEK SMALL LETTER ETA WITH PSILI..GREEK SMALL LETTER OMICRON WITH DASIA AND OXIA @@ -9235,9 +9472,7 @@ FFDA..FFDC ; XID_Start # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGU 2160..2182 ; XID_Continue # Nl [35] ROMAN NUMERAL ONE..ROMAN NUMERAL TEN THOUSAND 2183..2184 ; XID_Continue # L& [2] ROMAN NUMERAL REVERSED ONE HUNDRED..LATIN SMALL LETTER REVERSED C 2185..2188 ; XID_Continue # Nl [4] ROMAN NUMERAL SIX LATE FORM..ROMAN NUMERAL ONE HUNDRED THOUSAND -2C00..2C2E ; XID_Continue # L& [47] GLAGOLITIC CAPITAL LETTER AZU..GLAGOLITIC CAPITAL LETTER LATINATE MYSLITE -2C30..2C5E ; XID_Continue # L& [47] GLAGOLITIC SMALL LETTER AZU..GLAGOLITIC SMALL LETTER LATINATE MYSLITE -2C60..2C7B ; XID_Continue # L& [28] LATIN CAPITAL LETTER L WITH DOUBLE BAR..LATIN LETTER SMALL CAPITAL TURNED E +2C00..2C7B ; XID_Continue # L& [124] GLAGOLITIC CAPITAL LETTER AZU..LATIN LETTER SMALL CAPITAL TURNED E 2C7C..2C7D ; XID_Continue # Lm [2] LATIN SUBSCRIPT SMALL LETTER J..MODIFIER LETTER CAPITAL V 2C7E..2CE4 ; XID_Continue # L& [103] LATIN CAPITAL LETTER S WITH SWASH TAIL..COPTIC SYMBOL KAI 2CEB..2CEE ; XID_Continue # L& [4] COPTIC CAPITAL LETTER CRYPTOGRAMMIC SHEI..COPTIC SMALL LETTER CRYPTOGRAMMIC GANGIA @@ -9281,8 +9516,7 @@ FFDA..FFDC ; XID_Start # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGU 31A0..31BF ; XID_Continue # Lo [32] BOPOMOFO LETTER BU..BOPOMOFO LETTER AH 31F0..31FF ; XID_Continue # Lo [16] KATAKANA LETTER SMALL KU..KATAKANA LETTER SMALL RO 3400..4DBF ; XID_Continue # Lo [6592] CJK UNIFIED IDEOGRAPH-3400..CJK UNIFIED IDEOGRAPH-4DBF -4E00..9FFC ; XID_Continue # Lo [20989] CJK UNIFIED IDEOGRAPH-4E00..CJK UNIFIED IDEOGRAPH-9FFC -A000..A014 ; XID_Continue # Lo [21] YI SYLLABLE IT..YI SYLLABLE E +4E00..A014 ; XID_Continue # Lo [21013] CJK UNIFIED IDEOGRAPH-4E00..YI SYLLABLE E A015 ; XID_Continue # Lm YI SYLLABLE WU A016..A48C ; XID_Continue # Lo [1143] YI SYLLABLE BIT..YI SYLLABLE YYR A4D0..A4F7 ; XID_Continue # Lo [40] LISU LETTER BA..LISU LETTER OE @@ -9310,8 +9544,11 @@ A771..A787 ; XID_Continue # L& [23] LATIN SMALL LETTER DUM..LATIN SMALL LETT A788 ; XID_Continue # Lm MODIFIER LETTER LOW CIRCUMFLEX ACCENT A78B..A78E ; XID_Continue # L& [4] LATIN CAPITAL LETTER SALTILLO..LATIN SMALL LETTER L WITH RETROFLEX HOOK AND BELT A78F ; XID_Continue # Lo LATIN LETTER SINOLOGICAL DOT -A790..A7BF ; XID_Continue # L& [48] LATIN CAPITAL LETTER N WITH DESCENDER..LATIN SMALL LETTER GLOTTAL U -A7C2..A7CA ; XID_Continue # L& [9] LATIN CAPITAL LETTER ANGLICANA W..LATIN SMALL LETTER S WITH SHORT STROKE OVERLAY +A790..A7CA ; XID_Continue # L& [59] LATIN CAPITAL LETTER N WITH DESCENDER..LATIN SMALL LETTER S WITH SHORT STROKE OVERLAY +A7D0..A7D1 ; XID_Continue # L& [2] LATIN CAPITAL LETTER CLOSED INSULAR G..LATIN SMALL LETTER CLOSED INSULAR G +A7D3 ; XID_Continue # L& LATIN SMALL LETTER DOUBLE THORN +A7D5..A7D9 ; XID_Continue # L& [5] LATIN SMALL LETTER DOUBLE WYNN..LATIN SMALL LETTER SIGMOID S +A7F2..A7F4 ; XID_Continue # Lm [3] MODIFIER LETTER CAPITAL C..MODIFIER LETTER CAPITAL Q A7F5..A7F6 ; XID_Continue # L& [2] LATIN CAPITAL LETTER REVERSED HALF H..LATIN SMALL LETTER REVERSED HALF H A7F7 ; XID_Continue # Lo LATIN EPIGRAPHIC LETTER SIDEWAYS I A7F8..A7F9 ; XID_Continue # Lm [2] MODIFIER LETTER CAPITAL H WITH STROKE..MODIFIER LETTER SMALL LIGATURE OE @@ -9496,9 +9733,20 @@ FFDA..FFDC ; XID_Continue # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HA 104D8..104FB ; XID_Continue # L& [36] OSAGE SMALL LETTER A..OSAGE SMALL LETTER ZHA 10500..10527 ; XID_Continue # Lo [40] ELBASAN LETTER A..ELBASAN LETTER KHE 10530..10563 ; XID_Continue # Lo [52] CAUCASIAN ALBANIAN LETTER ALT..CAUCASIAN ALBANIAN LETTER KIW +10570..1057A ; XID_Continue # L& [11] VITHKUQI CAPITAL LETTER A..VITHKUQI CAPITAL LETTER GA +1057C..1058A ; XID_Continue # L& [15] VITHKUQI CAPITAL LETTER HA..VITHKUQI CAPITAL LETTER RE +1058C..10592 ; XID_Continue # L& [7] VITHKUQI CAPITAL LETTER SE..VITHKUQI CAPITAL LETTER XE +10594..10595 ; XID_Continue # L& [2] VITHKUQI CAPITAL LETTER Y..VITHKUQI CAPITAL LETTER ZE +10597..105A1 ; XID_Continue # L& [11] VITHKUQI SMALL LETTER A..VITHKUQI SMALL LETTER GA +105A3..105B1 ; XID_Continue # L& [15] VITHKUQI SMALL LETTER HA..VITHKUQI SMALL LETTER RE +105B3..105B9 ; XID_Continue # L& [7] VITHKUQI SMALL LETTER SE..VITHKUQI SMALL LETTER XE +105BB..105BC ; XID_Continue # L& [2] VITHKUQI SMALL LETTER Y..VITHKUQI SMALL LETTER ZE 10600..10736 ; XID_Continue # Lo [311] LINEAR A SIGN AB001..LINEAR A SIGN A664 10740..10755 ; XID_Continue # Lo [22] LINEAR A SIGN A701 A..LINEAR A SIGN A732 JE 10760..10767 ; XID_Continue # Lo [8] LINEAR A SIGN A800..LINEAR A SIGN A807 +10780..10785 ; XID_Continue # Lm [6] MODIFIER LETTER SMALL CAPITAL AA..MODIFIER LETTER SMALL B WITH HOOK +10787..107B0 ; XID_Continue # Lm [42] MODIFIER LETTER SMALL DZ DIGRAPH..MODIFIER LETTER SMALL V WITH RIGHT HOOK +107B2..107BA ; XID_Continue # Lm [9] MODIFIER LETTER SMALL CAPITAL Y..MODIFIER LETTER SMALL S WITH CURL 10800..10805 ; XID_Continue # Lo [6] CYPRIOT SYLLABLE A..CYPRIOT SYLLABLE JA 10808 ; XID_Continue # Lo CYPRIOT SYLLABLE JO 1080A..10835 ; XID_Continue # Lo [44] CYPRIOT SYLLABLE KA..CYPRIOT SYLLABLE WO @@ -9544,6 +9792,8 @@ FFDA..FFDC ; XID_Continue # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HA 10F27 ; XID_Continue # Lo OLD SOGDIAN LIGATURE AYIN-DALETH 10F30..10F45 ; XID_Continue # Lo [22] SOGDIAN LETTER ALEPH..SOGDIAN INDEPENDENT SHIN 10F46..10F50 ; XID_Continue # Mn [11] SOGDIAN COMBINING DOT BELOW..SOGDIAN COMBINING STROKE BELOW +10F70..10F81 ; XID_Continue # Lo [18] OLD UYGHUR LETTER ALEPH..OLD UYGHUR LETTER LESH +10F82..10F85 ; XID_Continue # Mn [4] OLD UYGHUR COMBINING DOT ABOVE..OLD UYGHUR COMBINING TWO DOTS BELOW 10FB0..10FC4 ; XID_Continue # Lo [21] CHORASMIAN LETTER ALEPH..CHORASMIAN LETTER TAW 10FE0..10FF6 ; XID_Continue # Lo [23] ELYMAIC LETTER ALEPH..ELYMAIC LIGATURE ZAYIN-YODH 11000 ; XID_Continue # Mc BRAHMI SIGN CANDRABINDU @@ -9552,6 +9802,10 @@ FFDA..FFDC ; XID_Continue # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HA 11003..11037 ; XID_Continue # Lo [53] BRAHMI SIGN JIHVAMULIYA..BRAHMI LETTER OLD TAMIL NNNA 11038..11046 ; XID_Continue # Mn [15] BRAHMI VOWEL SIGN AA..BRAHMI VIRAMA 11066..1106F ; XID_Continue # Nd [10] BRAHMI DIGIT ZERO..BRAHMI DIGIT NINE +11070 ; XID_Continue # Mn BRAHMI SIGN OLD TAMIL VIRAMA +11071..11072 ; XID_Continue # Lo [2] BRAHMI LETTER OLD TAMIL SHORT E..BRAHMI LETTER OLD TAMIL SHORT O +11073..11074 ; XID_Continue # Mn [2] BRAHMI VOWEL SIGN OLD TAMIL SHORT E..BRAHMI VOWEL SIGN OLD TAMIL SHORT O +11075 ; XID_Continue # Lo BRAHMI LETTER OLD TAMIL LLA 1107F..11081 ; XID_Continue # Mn [3] BRAHMI NUMBER JOINER..KAITHI SIGN ANUSVARA 11082 ; XID_Continue # Mc KAITHI SIGN VISARGA 11083..110AF ; XID_Continue # Lo [45] KAITHI LETTER A..KAITHI LETTER HA @@ -9559,6 +9813,7 @@ FFDA..FFDC ; XID_Continue # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HA 110B3..110B6 ; XID_Continue # Mn [4] KAITHI VOWEL SIGN U..KAITHI VOWEL SIGN AI 110B7..110B8 ; XID_Continue # Mc [2] KAITHI VOWEL SIGN O..KAITHI VOWEL SIGN AU 110B9..110BA ; XID_Continue # Mn [2] KAITHI SIGN VIRAMA..KAITHI SIGN NUKTA +110C2 ; XID_Continue # Mn KAITHI VOWEL SIGN VOCALIC R 110D0..110E8 ; XID_Continue # Lo [25] SORA SOMPENG LETTER SAH..SORA SOMPENG LETTER MAE 110F0..110F9 ; XID_Continue # Nd [10] SORA SOMPENG DIGIT ZERO..SORA SOMPENG DIGIT NINE 11100..11102 ; XID_Continue # Mn [3] CHAKMA SIGN CANDRABINDU..CHAKMA SIGN VISARGA @@ -9684,6 +9939,7 @@ FFDA..FFDC ; XID_Continue # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HA 11726 ; XID_Continue # Mc AHOM VOWEL SIGN E 11727..1172B ; XID_Continue # Mn [5] AHOM VOWEL SIGN AW..AHOM SIGN KILLER 11730..11739 ; XID_Continue # Nd [10] AHOM DIGIT ZERO..AHOM DIGIT NINE +11740..11746 ; XID_Continue # Lo [7] AHOM LETTER CA..AHOM LETTER LLA 11800..1182B ; XID_Continue # Lo [44] DOGRA LETTER A..DOGRA LETTER RRA 1182C..1182E ; XID_Continue # Mc [3] DOGRA VOWEL SIGN AA..DOGRA VOWEL SIGN II 1182F..11837 ; XID_Continue # Mn [9] DOGRA VOWEL SIGN U..DOGRA SIGN ANUSVARA @@ -9734,7 +9990,7 @@ FFDA..FFDC ; XID_Continue # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HA 11A97 ; XID_Continue # Mc SOYOMBO SIGN VISARGA 11A98..11A99 ; XID_Continue # Mn [2] SOYOMBO GEMINATION MARK..SOYOMBO SUBJOINER 11A9D ; XID_Continue # Lo SOYOMBO MARK PLUTA -11AC0..11AF8 ; XID_Continue # Lo [57] PAU CIN HAU LETTER PA..PAU CIN HAU GLOTTAL STOP FINAL +11AB0..11AF8 ; XID_Continue # Lo [73] CANADIAN SYLLABICS NATTILIK HI..PAU CIN HAU GLOTTAL STOP FINAL 11C00..11C08 ; XID_Continue # Lo [9] BHAIKSUKI LETTER A..BHAIKSUKI LETTER VOCALIC L 11C0A..11C2E ; XID_Continue # Lo [37] BHAIKSUKI LETTER E..BHAIKSUKI LETTER HA 11C2F ; XID_Continue # Mc BHAIKSUKI VOWEL SIGN AA @@ -9780,11 +10036,14 @@ FFDA..FFDC ; XID_Continue # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HA 12000..12399 ; XID_Continue # Lo [922] CUNEIFORM SIGN A..CUNEIFORM SIGN U U 12400..1246E ; XID_Continue # Nl [111] CUNEIFORM NUMERIC SIGN TWO ASH..CUNEIFORM NUMERIC SIGN NINE U VARIANT FORM 12480..12543 ; XID_Continue # Lo [196] CUNEIFORM SIGN AB TIMES NUN TENU..CUNEIFORM SIGN ZU5 TIMES THREE DISH TENU +12F90..12FF0 ; XID_Continue # Lo [97] CYPRO-MINOAN SIGN CM001..CYPRO-MINOAN SIGN CM114 13000..1342E ; XID_Continue # Lo [1071] EGYPTIAN HIEROGLYPH A001..EGYPTIAN HIEROGLYPH AA032 14400..14646 ; XID_Continue # Lo [583] ANATOLIAN HIEROGLYPH A001..ANATOLIAN HIEROGLYPH A530 16800..16A38 ; XID_Continue # Lo [569] BAMUM LETTER PHASE-A NGKUE MFON..BAMUM LETTER PHASE-F VUEQ 16A40..16A5E ; XID_Continue # Lo [31] MRO LETTER TA..MRO LETTER TEK 16A60..16A69 ; XID_Continue # Nd [10] MRO DIGIT ZERO..MRO DIGIT NINE +16A70..16ABE ; XID_Continue # Lo [79] TANGSA LETTER OZ..TANGSA LETTER ZA +16AC0..16AC9 ; XID_Continue # Nd [10] TANGSA DIGIT ZERO..TANGSA DIGIT NINE 16AD0..16AED ; XID_Continue # Lo [30] BASSA VAH LETTER ENNI..BASSA VAH LETTER I 16AF0..16AF4 ; XID_Continue # Mn [5] BASSA VAH COMBINING HIGH TONE..BASSA VAH COMBINING HIGH-LOW TONE 16B00..16B2F ; XID_Continue # Lo [48] PAHAWH HMONG VOWEL KEEB..PAHAWH HMONG CONSONANT CAU @@ -9807,7 +10066,10 @@ FFDA..FFDC ; XID_Continue # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HA 17000..187F7 ; XID_Continue # Lo [6136] TANGUT IDEOGRAPH-17000..TANGUT IDEOGRAPH-187F7 18800..18CD5 ; XID_Continue # Lo [1238] TANGUT COMPONENT-001..KHITAN SMALL SCRIPT CHARACTER-18CD5 18D00..18D08 ; XID_Continue # Lo [9] TANGUT IDEOGRAPH-18D00..TANGUT IDEOGRAPH-18D08 -1B000..1B11E ; XID_Continue # Lo [287] KATAKANA LETTER ARCHAIC E..HENTAIGANA LETTER N-MU-MO-2 +1AFF0..1AFF3 ; XID_Continue # Lm [4] KATAKANA LETTER MINNAN TONE-2..KATAKANA LETTER MINNAN TONE-5 +1AFF5..1AFFB ; XID_Continue # Lm [7] KATAKANA LETTER MINNAN TONE-7..KATAKANA LETTER MINNAN NASALIZED TONE-5 +1AFFD..1AFFE ; XID_Continue # Lm [2] KATAKANA LETTER MINNAN NASALIZED TONE-7..KATAKANA LETTER MINNAN NASALIZED TONE-8 +1B000..1B122 ; XID_Continue # Lo [291] KATAKANA LETTER ARCHAIC E..KATAKANA LETTER ARCHAIC WU 1B150..1B152 ; XID_Continue # Lo [3] HIRAGANA LETTER SMALL WI..HIRAGANA LETTER SMALL WO 1B164..1B167 ; XID_Continue # Lo [4] KATAKANA LETTER SMALL WI..KATAKANA LETTER SMALL N 1B170..1B2FB ; XID_Continue # Lo [396] NUSHU CHARACTER-1B170..NUSHU CHARACTER-1B2FB @@ -9816,6 +10078,8 @@ FFDA..FFDC ; XID_Continue # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HA 1BC80..1BC88 ; XID_Continue # Lo [9] DUPLOYAN AFFIX HIGH ACUTE..DUPLOYAN AFFIX HIGH VERTICAL 1BC90..1BC99 ; XID_Continue # Lo [10] DUPLOYAN AFFIX LOW ACUTE..DUPLOYAN AFFIX LOW ARROW 1BC9D..1BC9E ; XID_Continue # Mn [2] DUPLOYAN THICK LETTER SELECTOR..DUPLOYAN DOUBLE MARK +1CF00..1CF2D ; XID_Continue # Mn [46] ZNAMENNY COMBINING MARK GORAZDO NIZKO S KRYZHEM ON LEFT..ZNAMENNY COMBINING MARK KRYZH ON LEFT +1CF30..1CF46 ; XID_Continue # Mn [23] ZNAMENNY COMBINING TONAL RANGE MARK MRACHNO..ZNAMENNY PRIZNAK MODIFIER ROG 1D165..1D166 ; XID_Continue # Mc [2] MUSICAL SYMBOL COMBINING STEM..MUSICAL SYMBOL COMBINING SPRECHGESANG STEM 1D167..1D169 ; XID_Continue # Mn [3] MUSICAL SYMBOL COMBINING TREMOLO-1..MUSICAL SYMBOL COMBINING TREMOLO-3 1D16D..1D172 ; XID_Continue # Mc [6] MUSICAL SYMBOL COMBINING AUGMENTATION DOT..MUSICAL SYMBOL COMBINING FLAG-5 @@ -9860,6 +10124,9 @@ FFDA..FFDC ; XID_Continue # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HA 1DA84 ; XID_Continue # Mn SIGNWRITING LOCATION HEAD NECK 1DA9B..1DA9F ; XID_Continue # Mn [5] SIGNWRITING FILL MODIFIER-2..SIGNWRITING FILL MODIFIER-6 1DAA1..1DAAF ; XID_Continue # Mn [15] SIGNWRITING ROTATION MODIFIER-2..SIGNWRITING ROTATION MODIFIER-16 +1DF00..1DF09 ; XID_Continue # L& [10] LATIN SMALL LETTER FENG DIGRAPH WITH TRILL..LATIN SMALL LETTER T WITH HOOK AND RETROFLEX HOOK +1DF0A ; XID_Continue # Lo LATIN LETTER RETROFLEX CLICK WITH RETROFLEX HOOK +1DF0B..1DF1E ; XID_Continue # L& [20] LATIN SMALL LETTER ESH WITH DOUBLE BAR..LATIN SMALL LETTER S WITH CURL 1E000..1E006 ; XID_Continue # Mn [7] COMBINING GLAGOLITIC LETTER AZU..COMBINING GLAGOLITIC LETTER ZHIVETE 1E008..1E018 ; XID_Continue # Mn [17] COMBINING GLAGOLITIC LETTER ZEMLJA..COMBINING GLAGOLITIC LETTER HERU 1E01B..1E021 ; XID_Continue # Mn [7] COMBINING GLAGOLITIC LETTER SHTA..COMBINING GLAGOLITIC LETTER YATI @@ -9870,9 +10137,15 @@ FFDA..FFDC ; XID_Continue # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HA 1E137..1E13D ; XID_Continue # Lm [7] NYIAKENG PUACHUE HMONG SIGN FOR PERSON..NYIAKENG PUACHUE HMONG SYLLABLE LENGTHENER 1E140..1E149 ; XID_Continue # Nd [10] NYIAKENG PUACHUE HMONG DIGIT ZERO..NYIAKENG PUACHUE HMONG DIGIT NINE 1E14E ; XID_Continue # Lo NYIAKENG PUACHUE HMONG LOGOGRAM NYAJ +1E290..1E2AD ; XID_Continue # Lo [30] TOTO LETTER PA..TOTO LETTER A +1E2AE ; XID_Continue # Mn TOTO SIGN RISING TONE 1E2C0..1E2EB ; XID_Continue # Lo [44] WANCHO LETTER AA..WANCHO LETTER YIH 1E2EC..1E2EF ; XID_Continue # Mn [4] WANCHO TONE TUP..WANCHO TONE KOINI 1E2F0..1E2F9 ; XID_Continue # Nd [10] WANCHO DIGIT ZERO..WANCHO DIGIT NINE +1E7E0..1E7E6 ; XID_Continue # Lo [7] ETHIOPIC SYLLABLE HHYA..ETHIOPIC SYLLABLE HHYO +1E7E8..1E7EB ; XID_Continue # Lo [4] ETHIOPIC SYLLABLE GURAGE HHWA..ETHIOPIC SYLLABLE HHWE +1E7ED..1E7EE ; XID_Continue # Lo [2] ETHIOPIC SYLLABLE GURAGE MWI..ETHIOPIC SYLLABLE GURAGE MWEE +1E7F0..1E7FE ; XID_Continue # Lo [15] ETHIOPIC SYLLABLE GURAGE QWI..ETHIOPIC SYLLABLE GURAGE PWEE 1E800..1E8C4 ; XID_Continue # Lo [197] MENDE KIKAKUI SYLLABLE M001 KI..MENDE KIKAKUI SYLLABLE M060 NYON 1E8D0..1E8D6 ; XID_Continue # Mn [7] MENDE KIKAKUI COMBINING NUMBER TEENS..MENDE KIKAKUI COMBINING NUMBER MILLIONS 1E900..1E943 ; XID_Continue # L& [68] ADLAM CAPITAL LETTER ALIF..ADLAM SMALL LETTER SHA @@ -9913,8 +10186,8 @@ FFDA..FFDC ; XID_Continue # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HA 1EEA5..1EEA9 ; XID_Continue # Lo [5] ARABIC MATHEMATICAL DOUBLE-STRUCK WAW..ARABIC MATHEMATICAL DOUBLE-STRUCK YEH 1EEAB..1EEBB ; XID_Continue # Lo [17] ARABIC MATHEMATICAL DOUBLE-STRUCK LAM..ARABIC MATHEMATICAL DOUBLE-STRUCK GHAIN 1FBF0..1FBF9 ; XID_Continue # Nd [10] SEGMENTED DIGIT ZERO..SEGMENTED DIGIT NINE -20000..2A6DD ; XID_Continue # Lo [42718] CJK UNIFIED IDEOGRAPH-20000..CJK UNIFIED IDEOGRAPH-2A6DD -2A700..2B734 ; XID_Continue # Lo [4149] CJK UNIFIED IDEOGRAPH-2A700..CJK UNIFIED IDEOGRAPH-2B734 +20000..2A6DF ; XID_Continue # Lo [42720] CJK UNIFIED IDEOGRAPH-20000..CJK UNIFIED IDEOGRAPH-2A6DF +2A700..2B738 ; XID_Continue # Lo [4153] CJK UNIFIED IDEOGRAPH-2A700..CJK UNIFIED IDEOGRAPH-2B738 2B740..2B81D ; XID_Continue # Lo [222] CJK UNIFIED IDEOGRAPH-2B740..CJK UNIFIED IDEOGRAPH-2B81D 2B820..2CEA1 ; XID_Continue # Lo [5762] CJK UNIFIED IDEOGRAPH-2B820..CJK UNIFIED IDEOGRAPH-2CEA1 2CEB0..2EBE0 ; XID_Continue # Lo [7473] CJK UNIFIED IDEOGRAPH-2CEB0..CJK UNIFIED IDEOGRAPH-2EBE0 @@ -9922,7 +10195,7 @@ FFDA..FFDC ; XID_Continue # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HA 30000..3134A ; XID_Continue # Lo [4939] CJK UNIFIED IDEOGRAPH-30000..CJK UNIFIED IDEOGRAPH-3134A E0100..E01EF ; XID_Continue # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256 -# Total code points: 134415 +# Total code points: 135053 # ================================================ @@ -9943,6 +10216,7 @@ E0100..E01EF ; XID_Continue # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTO 17B4..17B5 ; Default_Ignorable_Code_Point # Mn [2] KHMER VOWEL INHERENT AQ..KHMER VOWEL INHERENT AA 180B..180D ; Default_Ignorable_Code_Point # Mn [3] MONGOLIAN FREE VARIATION SELECTOR ONE..MONGOLIAN FREE VARIATION SELECTOR THREE 180E ; Default_Ignorable_Code_Point # Cf MONGOLIAN VOWEL SEPARATOR +180F ; Default_Ignorable_Code_Point # Mn MONGOLIAN FREE VARIATION SELECTOR FOUR 200B..200F ; Default_Ignorable_Code_Point # Cf [5] ZERO WIDTH SPACE..RIGHT-TO-LEFT MARK 202A..202E ; Default_Ignorable_Code_Point # Cf [5] LEFT-TO-RIGHT EMBEDDING..RIGHT-TO-LEFT OVERRIDE 2060..2064 ; Default_Ignorable_Code_Point # Cf [5] WORD JOINER..INVISIBLE PLUS @@ -9963,7 +10237,7 @@ E0080..E00FF ; Default_Ignorable_Code_Point # Cn [128] .... -# Total code points: 4173 +# Total code points: 4174 # ================================================ @@ -9997,7 +10271,8 @@ E01F0..E0FFF ; Default_Ignorable_Code_Point # Cn [3600] .............. +2E52..2E54 ; Pattern_Syntax # Po [3] TIRONIAN SIGN CAPITAL ET..MEDIEVAL QUESTION MARK +2E55 ; Pattern_Syntax # Ps LEFT SQUARE BRACKET WITH STROKE +2E56 ; Pattern_Syntax # Pe RIGHT SQUARE BRACKET WITH STROKE +2E57 ; Pattern_Syntax # Ps LEFT SQUARE BRACKET WITH DOUBLE STROKE +2E58 ; Pattern_Syntax # Pe RIGHT SQUARE BRACKET WITH DOUBLE STROKE +2E59 ; Pattern_Syntax # Ps TOP HALF LEFT PARENTHESIS +2E5A ; Pattern_Syntax # Pe TOP HALF RIGHT PARENTHESIS +2E5B ; Pattern_Syntax # Ps BOTTOM HALF LEFT PARENTHESIS +2E5C ; Pattern_Syntax # Pe BOTTOM HALF RIGHT PARENTHESIS +2E5D ; Pattern_Syntax # Pd OBLIQUE HYPHEN +2E5E..2E7F ; Pattern_Syntax # Cn [34] .. 3001..3003 ; Pattern_Syntax # Po [3] IDEOGRAPHIC COMMA..DITTO MARK 3008 ; Pattern_Syntax # Ps LEFT ANGLE BRACKET 3009 ; Pattern_Syntax # Pe RIGHT ANGLE BRACKET @@ -1682,11 +1727,12 @@ FE45..FE46 ; Pattern_Syntax # Po [2] SESAME DOT..WHITE SESAME DOT 0600..0605 ; Prepended_Concatenation_Mark # Cf [6] ARABIC NUMBER SIGN..ARABIC NUMBER MARK ABOVE 06DD ; Prepended_Concatenation_Mark # Cf ARABIC END OF AYAH 070F ; Prepended_Concatenation_Mark # Cf SYRIAC ABBREVIATION MARK +0890..0891 ; Prepended_Concatenation_Mark # Cf [2] ARABIC POUND MARK ABOVE..ARABIC PIASTRE MARK ABOVE 08E2 ; Prepended_Concatenation_Mark # Cf ARABIC DISPUTED END OF AYAH 110BD ; Prepended_Concatenation_Mark # Cf KAITHI NUMBER SIGN 110CD ; Prepended_Concatenation_Mark # Cf KAITHI NUMBER SIGN ABOVE -# Total code points: 11 +# Total code points: 13 # ================================================ diff --git a/make/data/unicodedata/PropertyValueAliases.txt b/make/data/unicodedata/PropertyValueAliases.txt index a72c8671591..0d9356fb8e9 100644 --- a/make/data/unicodedata/PropertyValueAliases.txt +++ b/make/data/unicodedata/PropertyValueAliases.txt @@ -1,6 +1,6 @@ -# PropertyValueAliases-13.0.0.txt -# Date: 2019-11-13, 21:52:10 GMT -# Copyright (c) 2019 Unicode, Inc. +# PropertyValueAliases-14.0.0.txt +# Date: 2021-05-10, 21:08:53 GMT +# Copyright (c) 2021 Unicode, Inc. # Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries. # For terms of use, see http://www.unicode.org/terms_of_use.html # @@ -89,6 +89,7 @@ age; 11.0 ; V11_0 age; 12.0 ; V12_0 age; 12.1 ; V12_1 age; 13.0 ; V13_0 +age; 14.0 ; V14_0 age; NA ; Unassigned # Alphabetic (Alpha) @@ -160,6 +161,7 @@ blk; Ancient_Greek_Numbers ; Ancient_Greek_Numbers blk; Ancient_Symbols ; Ancient_Symbols blk; Arabic ; Arabic blk; Arabic_Ext_A ; Arabic_Extended_A +blk; Arabic_Ext_B ; Arabic_Extended_B blk; Arabic_Math ; Arabic_Mathematical_Alphabetic_Symbols blk; Arabic_PF_A ; Arabic_Presentation_Forms_A ; Arabic_Presentation_Forms-A blk; Arabic_PF_B ; Arabic_Presentation_Forms_B @@ -216,6 +218,7 @@ blk; Cuneiform ; Cuneiform blk; Cuneiform_Numbers ; Cuneiform_Numbers_And_Punctuation blk; Currency_Symbols ; Currency_Symbols blk; Cypriot_Syllabary ; Cypriot_Syllabary +blk; Cypro_Minoan ; Cypro_Minoan blk; Cyrillic ; Cyrillic blk; Cyrillic_Ext_A ; Cyrillic_Extended_A blk; Cyrillic_Ext_B ; Cyrillic_Extended_B @@ -246,6 +249,7 @@ blk; Enclosed_Ideographic_Sup ; Enclosed_Ideographic_Supplement blk; Ethiopic ; Ethiopic blk; Ethiopic_Ext ; Ethiopic_Extended blk; Ethiopic_Ext_A ; Ethiopic_Extended_A +blk; Ethiopic_Ext_B ; Ethiopic_Extended_B blk; Ethiopic_Sup ; Ethiopic_Supplement blk; Geometric_Shapes ; Geometric_Shapes blk; Geometric_Shapes_Ext ; Geometric_Shapes_Extended @@ -285,6 +289,7 @@ blk; Jamo_Ext_B ; Hangul_Jamo_Extended_B blk; Javanese ; Javanese blk; Kaithi ; Kaithi blk; Kana_Ext_A ; Kana_Extended_A +blk; Kana_Ext_B ; Kana_Extended_B blk; Kana_Sup ; Kana_Supplement blk; Kanbun ; Kanbun blk; Kangxi ; Kangxi_Radicals @@ -306,6 +311,8 @@ blk; Latin_Ext_B ; Latin_Extended_B blk; Latin_Ext_C ; Latin_Extended_C blk; Latin_Ext_D ; Latin_Extended_D blk; Latin_Ext_E ; Latin_Extended_E +blk; Latin_Ext_F ; Latin_Extended_F +blk; Latin_Ext_G ; Latin_Extended_G blk; Lepcha ; Lepcha blk; Letterlike_Symbols ; Letterlike_Symbols blk; Limbu ; Limbu @@ -372,6 +379,7 @@ blk; Old_Persian ; Old_Persian blk; Old_Sogdian ; Old_Sogdian blk; Old_South_Arabian ; Old_South_Arabian blk; Old_Turkic ; Old_Turkic +blk; Old_Uyghur ; Old_Uyghur blk; Oriya ; Oriya blk; Ornamental_Dingbats ; Ornamental_Dingbats blk; Osage ; Osage @@ -433,6 +441,7 @@ blk; Tai_Xuan_Jing ; Tai_Xuan_Jing_Symbols blk; Takri ; Takri blk; Tamil ; Tamil blk; Tamil_Sup ; Tamil_Supplement +blk; Tangsa ; Tangsa blk; Tangut ; Tangut blk; Tangut_Components ; Tangut_Components blk; Tangut_Sup ; Tangut_Supplement @@ -442,13 +451,16 @@ blk; Thai ; Thai blk; Tibetan ; Tibetan blk; Tifinagh ; Tifinagh blk; Tirhuta ; Tirhuta +blk; Toto ; Toto blk; Transport_And_Map ; Transport_And_Map_Symbols blk; UCAS ; Unified_Canadian_Aboriginal_Syllabics; Canadian_Syllabics blk; UCAS_Ext ; Unified_Canadian_Aboriginal_Syllabics_Extended +blk; UCAS_Ext_A ; Unified_Canadian_Aboriginal_Syllabics_Extended_A blk; Ugaritic ; Ugaritic blk; Vai ; Vai blk; Vedic_Ext ; Vedic_Extensions blk; Vertical_Forms ; Vertical_Forms +blk; Vithkuqi ; Vithkuqi blk; VS ; Variation_Selectors blk; VS_Sup ; Variation_Selectors_Supplement blk; Wancho ; Wancho @@ -458,6 +470,7 @@ blk; Yi_Radicals ; Yi_Radicals blk; Yi_Syllables ; Yi_Syllables blk; Yijing ; Yijing_Hexagram_Symbols blk; Zanabazar_Square ; Zanabazar_Square +blk; Znamenny_Music ; Znamenny_Musical_Notation # Canonical_Combining_Class (ccc) @@ -1032,6 +1045,8 @@ jg ; Taw ; Taw jg ; Teh_Marbuta ; Teh_Marbuta jg ; Teh_Marbuta_Goal ; Hamza_On_Heh_Goal jg ; Teth ; Teth +jg ; Thin_Yeh ; Thin_Yeh +jg ; Vertical_Tail ; Vertical_Tail jg ; Waw ; Waw jg ; Yeh ; Yeh jg ; Yeh_Barree ; Yeh_Barree @@ -1262,6 +1277,7 @@ sc ; Cham ; Cham sc ; Cher ; Cherokee sc ; Chrs ; Chorasmian sc ; Copt ; Coptic ; Qaac +sc ; Cpmn ; Cypro_Minoan sc ; Cprt ; Cypriot sc ; Cyrl ; Cyrillic sc ; Deva ; Devanagari @@ -1341,6 +1357,7 @@ sc ; Orkh ; Old_Turkic sc ; Orya ; Oriya sc ; Osge ; Osage sc ; Osma ; Osmanya +sc ; Ougr ; Old_Uyghur sc ; Palm ; Palmyrene sc ; Pauc ; Pau_Cin_Hau sc ; Perm ; Old_Permic @@ -1383,8 +1400,11 @@ sc ; Thaa ; Thaana sc ; Thai ; Thai sc ; Tibt ; Tibetan sc ; Tirh ; Tirhuta +sc ; Tnsa ; Tangsa +sc ; Toto ; Toto sc ; Ugar ; Ugaritic sc ; Vaii ; Vai +sc ; Vith ; Vithkuqi sc ; Wara ; Warang_Citi sc ; Wcho ; Wancho sc ; Xpeo ; Old_Persian diff --git a/make/data/unicodedata/ReadMe.txt b/make/data/unicodedata/ReadMe.txt new file mode 100644 index 00000000000..154781ab2d2 --- /dev/null +++ b/make/data/unicodedata/ReadMe.txt @@ -0,0 +1,16 @@ +# Unicode Character Database +# Date: 2021-09-10, 17:22:00 GMT [KW] +# Copyright (c) 2021 Unicode, Inc. +# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries. +# For terms of use, see https://www.unicode.org/terms_of_use.html +# +# For documentation, see the following: +# NamesList.html +# UAX #38, "Unicode Han Database (Unihan)" +# UAX #44, "Unicode Character Database" +# UTS #51, "Unicode Emoji" +# +# The UAXes and UTS #51 can be accessed at https://www.unicode.org/versions/Unicode14.0.0/ + +This directory contains the final data files +for the Unicode Character Database, for Version 14.0.0 of the Unicode Standard. diff --git a/make/data/unicodedata/Scripts.txt b/make/data/unicodedata/Scripts.txt index eb3cd86e0c7..00a04f5587a 100644 --- a/make/data/unicodedata/Scripts.txt +++ b/make/data/unicodedata/Scripts.txt @@ -1,16 +1,16 @@ -# Scripts-13.0.0.txt -# Date: 2020-01-22, 00:07:43 GMT -# Copyright (c) 2020 Unicode, Inc. +# Scripts-14.0.0.txt +# Date: 2021-07-10, 00:35:31 GMT +# Copyright (c) 2021 Unicode, Inc. # Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries. # For terms of use, see http://www.unicode.org/terms_of_use.html # # Unicode Character Database # For documentation, see http://www.unicode.org/reports/tr44/ # For more information, see: -# UAX #24, Unicode Script Property: http://www.unicode.org/reports/tr24/ +# UAX #24, Unicode Script Property: https://www.unicode.org/reports/tr24/ # Especially the sections: -# http://www.unicode.org/reports/tr24/#Assignment_Script_Values -# http://www.unicode.org/reports/tr24/#Assignment_ScriptX_Values +# https://www.unicode.org/reports/tr24/#Assignment_Script_Values +# https://www.unicode.org/reports/tr24/#Assignment_ScriptX_Values # # ================================================ @@ -154,7 +154,7 @@ 208A..208C ; Common # Sm [3] SUBSCRIPT PLUS SIGN..SUBSCRIPT EQUALS SIGN 208D ; Common # Ps SUBSCRIPT LEFT PARENTHESIS 208E ; Common # Pe SUBSCRIPT RIGHT PARENTHESIS -20A0..20BF ; Common # Sc [32] EURO-CURRENCY SIGN..BITCOIN SIGN +20A0..20C0 ; Common # Sc [33] EURO-CURRENCY SIGN..SOM SIGN 2100..2101 ; Common # So [2] ACCOUNT OF..ADDRESSED TO THE SUBJECT 2102 ; Common # L& DOUBLE-STRUCK CAPITAL C 2103..2106 ; Common # So [4] DEGREE CELSIUS..CADA UNA @@ -347,7 +347,16 @@ 2E42 ; Common # Ps DOUBLE LOW-REVERSED-9 QUOTATION MARK 2E43..2E4F ; Common # Po [13] DASH WITH LEFT UPTURN..CORNISH VERSE DIVIDER 2E50..2E51 ; Common # So [2] CROSS PATTY WITH RIGHT CROSSBAR..CROSS PATTY WITH LEFT CROSSBAR -2E52 ; Common # Po TIRONIAN SIGN CAPITAL ET +2E52..2E54 ; Common # Po [3] TIRONIAN SIGN CAPITAL ET..MEDIEVAL QUESTION MARK +2E55 ; Common # Ps LEFT SQUARE BRACKET WITH STROKE +2E56 ; Common # Pe RIGHT SQUARE BRACKET WITH STROKE +2E57 ; Common # Ps LEFT SQUARE BRACKET WITH DOUBLE STROKE +2E58 ; Common # Pe RIGHT SQUARE BRACKET WITH DOUBLE STROKE +2E59 ; Common # Ps TOP HALF LEFT PARENTHESIS +2E5A ; Common # Pe TOP HALF RIGHT PARENTHESIS +2E5B ; Common # Ps BOTTOM HALF LEFT PARENTHESIS +2E5C ; Common # Pe BOTTOM HALF RIGHT PARENTHESIS +2E5D ; Common # Pd OBLIQUE HYPHEN 2FF0..2FFB ; Common # So [12] IDEOGRAPHIC DESCRIPTION CHARACTER LEFT TO RIGHT..IDEOGRAPHIC DESCRIPTION CHARACTER OVERLAID 3000 ; Common # Zs IDEOGRAPHIC SPACE 3001..3003 ; Common # Po [3] IDEOGRAPHIC COMMA..DITTO MARK @@ -511,9 +520,8 @@ FFFC..FFFD ; Common # So [2] OBJECT REPLACEMENT CHARACTER..REPLACEMENT CHAR 10190..1019C ; Common # So [13] ROMAN SEXTANS SIGN..ASCIA SYMBOL 101D0..101FC ; Common # So [45] PHAISTOS DISC SIGN PEDESTRIAN..PHAISTOS DISC SIGN WAVY BAND 102E1..102FB ; Common # No [27] COPTIC EPACT DIGIT ONE..COPTIC EPACT NUMBER NINE HUNDRED -16FE2 ; Common # Po OLD CHINESE HOOK MARK -16FE3 ; Common # Lm OLD CHINESE ITERATION MARK 1BCA0..1BCA3 ; Common # Cf [4] SHORTHAND FORMAT LETTER OVERLAP..SHORTHAND FORMAT UP STEP +1CF50..1CFC3 ; Common # So [116] ZNAMENNY NEUME KRYUK..ZNAMENNY NEUME PAUK 1D000..1D0F5 ; Common # So [246] BYZANTINE MUSICAL SYMBOL PSILI..BYZANTINE MUSICAL SYMBOL GORGON NEO KATO 1D100..1D126 ; Common # So [39] MUSICAL SYMBOL SINGLE BARLINE..MUSICAL SYMBOL DRUM CLEF-2 1D129..1D164 ; Common # So [60] MUSICAL SYMBOL MULTIPLE MEASURE REST..MUSICAL SYMBOL ONE HUNDRED TWENTY-EIGHTH NOTE @@ -523,7 +531,7 @@ FFFC..FFFD ; Common # So [2] OBJECT REPLACEMENT CHARACTER..REPLACEMENT CHAR 1D173..1D17A ; Common # Cf [8] MUSICAL SYMBOL BEGIN BEAM..MUSICAL SYMBOL END PHRASE 1D183..1D184 ; Common # So [2] MUSICAL SYMBOL ARPEGGIATO UP..MUSICAL SYMBOL ARPEGGIATO DOWN 1D18C..1D1A9 ; Common # So [30] MUSICAL SYMBOL RINFORZANDO..MUSICAL SYMBOL DEGREE SLASH -1D1AE..1D1E8 ; Common # So [59] MUSICAL SYMBOL PEDAL MARK..MUSICAL SYMBOL KIEVAN FLAT SIGN +1D1AE..1D1EA ; Common # So [61] MUSICAL SYMBOL PEDAL MARK..MUSICAL SYMBOL KORON 1D2E0..1D2F3 ; Common # No [20] MAYAN NUMERAL ZERO..MAYAN NUMERAL NINETEEN 1D300..1D356 ; Common # So [87] MONOGRAM FOR EARTH..TETRAGRAM FOR FOSTERING 1D360..1D378 ; Common # No [25] COUNTING ROD UNIT DIGIT ONE..TALLY MARK FIVE @@ -593,35 +601,36 @@ FFFC..FFFD ; Common # So [2] OBJECT REPLACEMENT CHARACTER..REPLACEMENT CHAR 1F300..1F3FA ; Common # So [251] CYCLONE..AMPHORA 1F3FB..1F3FF ; Common # Sk [5] EMOJI MODIFIER FITZPATRICK TYPE-1-2..EMOJI MODIFIER FITZPATRICK TYPE-6 1F400..1F6D7 ; Common # So [728] RAT..ELEVATOR -1F6E0..1F6EC ; Common # So [13] HAMMER AND WRENCH..AIRPLANE ARRIVING +1F6DD..1F6EC ; Common # So [16] PLAYGROUND SLIDE..AIRPLANE ARRIVING 1F6F0..1F6FC ; Common # So [13] SATELLITE..ROLLER SKATE 1F700..1F773 ; Common # So [116] ALCHEMICAL SYMBOL FOR QUINTESSENCE..ALCHEMICAL SYMBOL FOR HALF OUNCE 1F780..1F7D8 ; Common # So [89] BLACK LEFT-POINTING ISOSCELES RIGHT TRIANGLE..NEGATIVE CIRCLED SQUARE 1F7E0..1F7EB ; Common # So [12] LARGE ORANGE CIRCLE..LARGE BROWN SQUARE +1F7F0 ; Common # So HEAVY EQUALS SIGN 1F800..1F80B ; Common # So [12] LEFTWARDS ARROW WITH SMALL TRIANGLE ARROWHEAD..DOWNWARDS ARROW WITH LARGE TRIANGLE ARROWHEAD 1F810..1F847 ; Common # So [56] LEFTWARDS ARROW WITH SMALL EQUILATERAL ARROWHEAD..DOWNWARDS HEAVY ARROW 1F850..1F859 ; Common # So [10] LEFTWARDS SANS-SERIF ARROW..UP DOWN SANS-SERIF ARROW 1F860..1F887 ; Common # So [40] WIDE-HEADED LEFTWARDS LIGHT BARB ARROW..WIDE-HEADED SOUTH WEST VERY HEAVY BARB ARROW 1F890..1F8AD ; Common # So [30] LEFTWARDS TRIANGLE ARROWHEAD..WHITE ARROW SHAFT WIDTH TWO THIRDS 1F8B0..1F8B1 ; Common # So [2] ARROW POINTING UPWARDS THEN NORTH WEST..ARROW POINTING RIGHTWARDS THEN CURVING SOUTH WEST -1F900..1F978 ; Common # So [121] CIRCLED CROSS FORMEE WITH FOUR DOTS..DISGUISED FACE -1F97A..1F9CB ; Common # So [82] FACE WITH PLEADING EYES..BUBBLE TEA -1F9CD..1FA53 ; Common # So [135] STANDING PERSON..BLACK CHESS KNIGHT-BISHOP +1F900..1FA53 ; Common # So [340] CIRCLED CROSS FORMEE WITH FOUR DOTS..BLACK CHESS KNIGHT-BISHOP 1FA60..1FA6D ; Common # So [14] XIANGQI RED GENERAL..XIANGQI BLACK SOLDIER 1FA70..1FA74 ; Common # So [5] BALLET SHOES..THONG SANDAL -1FA78..1FA7A ; Common # So [3] DROP OF BLOOD..STETHOSCOPE +1FA78..1FA7C ; Common # So [5] DROP OF BLOOD..CRUTCH 1FA80..1FA86 ; Common # So [7] YO-YO..NESTING DOLLS -1FA90..1FAA8 ; Common # So [25] RINGED PLANET..ROCK -1FAB0..1FAB6 ; Common # So [7] FLY..FEATHER -1FAC0..1FAC2 ; Common # So [3] ANATOMICAL HEART..PEOPLE HUGGING -1FAD0..1FAD6 ; Common # So [7] BLUEBERRIES..TEAPOT +1FA90..1FAAC ; Common # So [29] RINGED PLANET..HAMSA +1FAB0..1FABA ; Common # So [11] FLY..NEST WITH EGGS +1FAC0..1FAC5 ; Common # So [6] ANATOMICAL HEART..PERSON WITH CROWN +1FAD0..1FAD9 ; Common # So [10] BLUEBERRIES..JAR +1FAE0..1FAE7 ; Common # So [8] MELTING FACE..BUBBLES +1FAF0..1FAF6 ; Common # So [7] HAND WITH INDEX FINGER AND THUMB CROSSED..HEART HANDS 1FB00..1FB92 ; Common # So [147] BLOCK SEXTANT-1..UPPER HALF INVERSE MEDIUM SHADE AND LOWER HALF BLOCK 1FB94..1FBCA ; Common # So [55] LEFT HALF INVERSE MEDIUM SHADE AND RIGHT HALF BLOCK..WHITE UP-POINTING CHEVRON 1FBF0..1FBF9 ; Common # Nd [10] SEGMENTED DIGIT ZERO..SEGMENTED DIGIT NINE E0001 ; Common # Cf LANGUAGE TAG E0020..E007F ; Common # Cf [96] TAG SPACE..CANCEL TAG -# Total code points: 8087 +# Total code points: 8252 # ================================================ @@ -664,8 +673,11 @@ A770 ; Latin # Lm MODIFIER LETTER US A771..A787 ; Latin # L& [23] LATIN SMALL LETTER DUM..LATIN SMALL LETTER INSULAR T A78B..A78E ; Latin # L& [4] LATIN CAPITAL LETTER SALTILLO..LATIN SMALL LETTER L WITH RETROFLEX HOOK AND BELT A78F ; Latin # Lo LATIN LETTER SINOLOGICAL DOT -A790..A7BF ; Latin # L& [48] LATIN CAPITAL LETTER N WITH DESCENDER..LATIN SMALL LETTER GLOTTAL U -A7C2..A7CA ; Latin # L& [9] LATIN CAPITAL LETTER ANGLICANA W..LATIN SMALL LETTER S WITH SHORT STROKE OVERLAY +A790..A7CA ; Latin # L& [59] LATIN CAPITAL LETTER N WITH DESCENDER..LATIN SMALL LETTER S WITH SHORT STROKE OVERLAY +A7D0..A7D1 ; Latin # L& [2] LATIN CAPITAL LETTER CLOSED INSULAR G..LATIN SMALL LETTER CLOSED INSULAR G +A7D3 ; Latin # L& LATIN SMALL LETTER DOUBLE THORN +A7D5..A7D9 ; Latin # L& [5] LATIN SMALL LETTER DOUBLE WYNN..LATIN SMALL LETTER SIGMOID S +A7F2..A7F4 ; Latin # Lm [3] MODIFIER LETTER CAPITAL C..MODIFIER LETTER CAPITAL Q A7F5..A7F6 ; Latin # L& [2] LATIN CAPITAL LETTER REVERSED HALF H..LATIN SMALL LETTER REVERSED HALF H A7F7 ; Latin # Lo LATIN EPIGRAPHIC LETTER SIDEWAYS I A7F8..A7F9 ; Latin # Lm [2] MODIFIER LETTER CAPITAL H WITH STROKE..MODIFIER LETTER SMALL LIGATURE OE @@ -679,8 +691,14 @@ AB69 ; Latin # Lm MODIFIER LETTER SMALL TURNED W FB00..FB06 ; Latin # L& [7] LATIN SMALL LIGATURE FF..LATIN SMALL LIGATURE ST FF21..FF3A ; Latin # L& [26] FULLWIDTH LATIN CAPITAL LETTER A..FULLWIDTH LATIN CAPITAL LETTER Z FF41..FF5A ; Latin # L& [26] FULLWIDTH LATIN SMALL LETTER A..FULLWIDTH LATIN SMALL LETTER Z +10780..10785 ; Latin # Lm [6] MODIFIER LETTER SMALL CAPITAL AA..MODIFIER LETTER SMALL B WITH HOOK +10787..107B0 ; Latin # Lm [42] MODIFIER LETTER SMALL DZ DIGRAPH..MODIFIER LETTER SMALL V WITH RIGHT HOOK +107B2..107BA ; Latin # Lm [9] MODIFIER LETTER SMALL CAPITAL Y..MODIFIER LETTER SMALL S WITH CURL +1DF00..1DF09 ; Latin # L& [10] LATIN SMALL LETTER FENG DIGRAPH WITH TRILL..LATIN SMALL LETTER T WITH HOOK AND RETROFLEX HOOK +1DF0A ; Latin # Lo LATIN LETTER RETROFLEX CLICK WITH RETROFLEX HOOK +1DF0B..1DF1E ; Latin # L& [20] LATIN SMALL LETTER ESH WITH DOUBLE BAR..LATIN SMALL LETTER S WITH CURL -# Total code points: 1374 +# Total code points: 1475 # ================================================ @@ -820,7 +838,7 @@ FB46..FB4F ; Hebrew # Lo [10] HEBREW LETTER TSADI WITH DAGESH..HEBREW LIGATU 060E..060F ; Arabic # So [2] ARABIC POETIC VERSE SIGN..ARABIC SIGN MISRA 0610..061A ; Arabic # Mn [11] ARABIC SIGN SALLALLAHOU ALAYHE WASSALLAM..ARABIC SMALL KASRA 061C ; Arabic # Cf ARABIC LETTER MARK -061E ; Arabic # Po ARABIC TRIPLE DOT PUNCTUATION MARK +061D..061E ; Arabic # Po [2] ARABIC END OF TEXT MARK..ARABIC TRIPLE DOT PUNCTUATION MARK 0620..063F ; Arabic # Lo [32] ARABIC LETTER KASHMIRI YEH..ARABIC LETTER FARSI YEH WITH THREE DOTS ABOVE 0641..064A ; Arabic # Lo [10] ARABIC LETTER FEH..ARABIC LETTER YEH 0656..065F ; Arabic # Mn [10] ARABIC SUBSCRIPT ALEF..ARABIC WAVY HAMZA BELOW @@ -843,18 +861,25 @@ FB46..FB4F ; Hebrew # Lo [10] HEBREW LETTER TSADI WITH DAGESH..HEBREW LIGATU 06FD..06FE ; Arabic # So [2] ARABIC SIGN SINDHI AMPERSAND..ARABIC SIGN SINDHI POSTPOSITION MEN 06FF ; Arabic # Lo ARABIC LETTER HEH WITH INVERTED V 0750..077F ; Arabic # Lo [48] ARABIC LETTER BEH WITH THREE DOTS HORIZONTALLY BELOW..ARABIC LETTER KAF WITH TWO DOTS ABOVE -08A0..08B4 ; Arabic # Lo [21] ARABIC LETTER BEH WITH SMALL V BELOW..ARABIC LETTER KAF WITH DOT BELOW -08B6..08C7 ; Arabic # Lo [18] ARABIC LETTER BEH WITH SMALL MEEM ABOVE..ARABIC LETTER LAM WITH SMALL ARABIC LETTER TAH ABOVE -08D3..08E1 ; Arabic # Mn [15] ARABIC SMALL LOW WAW..ARABIC SMALL HIGH SIGN SAFHA +0870..0887 ; Arabic # Lo [24] ARABIC LETTER ALEF WITH ATTACHED FATHA..ARABIC BASELINE ROUND DOT +0888 ; Arabic # Sk ARABIC RAISED ROUND DOT +0889..088E ; Arabic # Lo [6] ARABIC LETTER NOON WITH INVERTED SMALL V..ARABIC VERTICAL TAIL +0890..0891 ; Arabic # Cf [2] ARABIC POUND MARK ABOVE..ARABIC PIASTRE MARK ABOVE +0898..089F ; Arabic # Mn [8] ARABIC SMALL HIGH WORD AL-JUZ..ARABIC HALF MADDA OVER MADDA +08A0..08C8 ; Arabic # Lo [41] ARABIC LETTER BEH WITH SMALL V BELOW..ARABIC LETTER GRAF +08C9 ; Arabic # Lm ARABIC SMALL FARSI YEH +08CA..08E1 ; Arabic # Mn [24] ARABIC SMALL HIGH FARSI YEH..ARABIC SMALL HIGH SIGN SAFHA 08E3..08FF ; Arabic # Mn [29] ARABIC TURNED DAMMA BELOW..ARABIC MARK SIDEWAYS NOON GHUNNA FB50..FBB1 ; Arabic # Lo [98] ARABIC LETTER ALEF WASLA ISOLATED FORM..ARABIC LETTER YEH BARREE WITH HAMZA ABOVE FINAL FORM -FBB2..FBC1 ; Arabic # Sk [16] ARABIC SYMBOL DOT ABOVE..ARABIC SYMBOL SMALL TAH BELOW +FBB2..FBC2 ; Arabic # Sk [17] ARABIC SYMBOL DOT ABOVE..ARABIC SYMBOL WASLA ABOVE FBD3..FD3D ; Arabic # Lo [363] ARABIC LETTER NG ISOLATED FORM..ARABIC LIGATURE ALEF WITH FATHATAN ISOLATED FORM +FD40..FD4F ; Arabic # So [16] ARABIC LIGATURE RAHIMAHU ALLAAH..ARABIC LIGATURE RAHIMAHUM ALLAAH FD50..FD8F ; Arabic # Lo [64] ARABIC LIGATURE TEH WITH JEEM WITH MEEM INITIAL FORM..ARABIC LIGATURE MEEM WITH KHAH WITH MEEM INITIAL FORM FD92..FDC7 ; Arabic # Lo [54] ARABIC LIGATURE MEEM WITH JEEM WITH KHAH INITIAL FORM..ARABIC LIGATURE NOON WITH JEEM WITH YEH FINAL FORM +FDCF ; Arabic # So ARABIC LIGATURE SALAAMUHU ALAYNAA FDF0..FDFB ; Arabic # Lo [12] ARABIC LIGATURE SALLA USED AS KORANIC STOP SIGN ISOLATED FORM..ARABIC LIGATURE JALLAJALALOUHOU FDFC ; Arabic # Sc RIAL SIGN -FDFD ; Arabic # So ARABIC LIGATURE BISMILLAH AR-RAHMAN AR-RAHEEM +FDFD..FDFF ; Arabic # So [3] ARABIC LIGATURE BISMILLAH AR-RAHMAN AR-RAHEEM..ARABIC LIGATURE AZZA WA JALL FE70..FE74 ; Arabic # Lo [5] ARABIC FATHATAN ISOLATED FORM..ARABIC KASRATAN ISOLATED FORM FE76..FEFC ; Arabic # Lo [135] ARABIC FATHA ISOLATED FORM..ARABIC LIGATURE LAM WITH ALEF FINAL FORM 10E60..10E7E ; Arabic # No [31] RUMI DIGIT ONE..RUMI FRACTION TWO THIRDS @@ -893,7 +918,7 @@ FE76..FEFC ; Arabic # Lo [135] ARABIC FATHA ISOLATED FORM..ARABIC LIGATURE LA 1EEAB..1EEBB ; Arabic # Lo [17] ARABIC MATHEMATICAL DOUBLE-STRUCK LAM..ARABIC MATHEMATICAL DOUBLE-STRUCK GHAIN 1EEF0..1EEF1 ; Arabic # Sm [2] ARABIC MATHEMATICAL OPERATOR MEEM WITH HAH WITH TATWEEL..ARABIC MATHEMATICAL OPERATOR HAH WITH DAL -# Total code points: 1291 +# Total code points: 1365 # ================================================ @@ -1113,6 +1138,7 @@ A8FF ; Devanagari # Mn DEVANAGARI VOWEL SIGN AY 0C0E..0C10 ; Telugu # Lo [3] TELUGU LETTER E..TELUGU LETTER AI 0C12..0C28 ; Telugu # Lo [23] TELUGU LETTER O..TELUGU LETTER NA 0C2A..0C39 ; Telugu # Lo [16] TELUGU LETTER PA..TELUGU LETTER HA +0C3C ; Telugu # Mn TELUGU SIGN NUKTA 0C3D ; Telugu # Lo TELUGU SIGN AVAGRAHA 0C3E..0C40 ; Telugu # Mn [3] TELUGU VOWEL SIGN AA..TELUGU VOWEL SIGN II 0C41..0C44 ; Telugu # Mc [4] TELUGU VOWEL SIGN U..TELUGU VOWEL SIGN VOCALIC RR @@ -1120,6 +1146,7 @@ A8FF ; Devanagari # Mn DEVANAGARI VOWEL SIGN AY 0C4A..0C4D ; Telugu # Mn [4] TELUGU VOWEL SIGN O..TELUGU SIGN VIRAMA 0C55..0C56 ; Telugu # Mn [2] TELUGU LENGTH MARK..TELUGU AI LENGTH MARK 0C58..0C5A ; Telugu # Lo [3] TELUGU LETTER TSA..TELUGU LETTER RRRA +0C5D ; Telugu # Lo TELUGU LETTER NAKAARA POLLU 0C60..0C61 ; Telugu # Lo [2] TELUGU LETTER VOCALIC RR..TELUGU LETTER VOCALIC LL 0C62..0C63 ; Telugu # Mn [2] TELUGU VOWEL SIGN VOCALIC L..TELUGU VOWEL SIGN VOCALIC LL 0C66..0C6F ; Telugu # Nd [10] TELUGU DIGIT ZERO..TELUGU DIGIT NINE @@ -1127,7 +1154,7 @@ A8FF ; Devanagari # Mn DEVANAGARI VOWEL SIGN AY 0C78..0C7E ; Telugu # No [7] TELUGU FRACTION DIGIT ZERO FOR ODD POWERS OF FOUR..TELUGU FRACTION DIGIT THREE FOR EVEN POWERS OF FOUR 0C7F ; Telugu # So TELUGU SIGN TUUMU -# Total code points: 98 +# Total code points: 100 # ================================================ @@ -1150,13 +1177,13 @@ A8FF ; Devanagari # Mn DEVANAGARI VOWEL SIGN AY 0CCA..0CCB ; Kannada # Mc [2] KANNADA VOWEL SIGN O..KANNADA VOWEL SIGN OO 0CCC..0CCD ; Kannada # Mn [2] KANNADA VOWEL SIGN AU..KANNADA SIGN VIRAMA 0CD5..0CD6 ; Kannada # Mc [2] KANNADA LENGTH MARK..KANNADA AI LENGTH MARK -0CDE ; Kannada # Lo KANNADA LETTER FA +0CDD..0CDE ; Kannada # Lo [2] KANNADA LETTER NAKAARA POLLU..KANNADA LETTER FA 0CE0..0CE1 ; Kannada # Lo [2] KANNADA LETTER VOCALIC RR..KANNADA LETTER VOCALIC LL 0CE2..0CE3 ; Kannada # Mn [2] KANNADA VOWEL SIGN VOCALIC L..KANNADA VOWEL SIGN VOCALIC LL 0CE6..0CEF ; Kannada # Nd [10] KANNADA DIGIT ZERO..KANNADA DIGIT NINE 0CF1..0CF2 ; Kannada # Lo [2] KANNADA SIGN JIHVAMULIYA..KANNADA SIGN UPADHMANIYA -# Total code points: 89 +# Total code points: 90 # ================================================ @@ -1411,8 +1438,12 @@ AB09..AB0E ; Ethiopic # Lo [6] ETHIOPIC SYLLABLE DDHU..ETHIOPIC SYLLABLE DD AB11..AB16 ; Ethiopic # Lo [6] ETHIOPIC SYLLABLE DZU..ETHIOPIC SYLLABLE DZO AB20..AB26 ; Ethiopic # Lo [7] ETHIOPIC SYLLABLE CCHHA..ETHIOPIC SYLLABLE CCHHO AB28..AB2E ; Ethiopic # Lo [7] ETHIOPIC SYLLABLE BBA..ETHIOPIC SYLLABLE BBO +1E7E0..1E7E6 ; Ethiopic # Lo [7] ETHIOPIC SYLLABLE HHYA..ETHIOPIC SYLLABLE HHYO +1E7E8..1E7EB ; Ethiopic # Lo [4] ETHIOPIC SYLLABLE GURAGE HHWA..ETHIOPIC SYLLABLE HHWE +1E7ED..1E7EE ; Ethiopic # Lo [2] ETHIOPIC SYLLABLE GURAGE MWI..ETHIOPIC SYLLABLE GURAGE MWEE +1E7F0..1E7FE ; Ethiopic # Lo [15] ETHIOPIC SYLLABLE GURAGE QWI..ETHIOPIC SYLLABLE GURAGE PWEE -# Total code points: 495 +# Total code points: 523 # ================================================ @@ -1430,8 +1461,9 @@ AB70..ABBF ; Cherokee # L& [80] CHEROKEE SMALL LETTER A..CHEROKEE SMALL LETT 166E ; Canadian_Aboriginal # Po CANADIAN SYLLABICS FULL STOP 166F..167F ; Canadian_Aboriginal # Lo [17] CANADIAN SYLLABICS QAI..CANADIAN SYLLABICS BLACKFOOT W 18B0..18F5 ; Canadian_Aboriginal # Lo [70] CANADIAN SYLLABICS OY..CANADIAN SYLLABICS CARRIER DENTAL S +11AB0..11ABF ; Canadian_Aboriginal # Lo [16] CANADIAN SYLLABICS NATTILIK HI..CANADIAN SYLLABICS SPA -# Total code points: 710 +# Total code points: 726 # ================================================ @@ -1480,6 +1512,7 @@ AB70..ABBF ; Cherokee # L& [80] CHEROKEE SMALL LETTER A..CHEROKEE SMALL LETT 1807..180A ; Mongolian # Po [4] MONGOLIAN SIBE SYLLABLE BOUNDARY MARKER..MONGOLIAN NIRUGU 180B..180D ; Mongolian # Mn [3] MONGOLIAN FREE VARIATION SELECTOR ONE..MONGOLIAN FREE VARIATION SELECTOR THREE 180E ; Mongolian # Cf MONGOLIAN VOWEL SEPARATOR +180F ; Mongolian # Mn MONGOLIAN FREE VARIATION SELECTOR FOUR 1810..1819 ; Mongolian # Nd [10] MONGOLIAN DIGIT ZERO..MONGOLIAN DIGIT NINE 1820..1842 ; Mongolian # Lo [35] MONGOLIAN LETTER A..MONGOLIAN LETTER CHI 1843 ; Mongolian # Lm MONGOLIAN LETTER TODO LONG VOWEL SIGN @@ -1491,18 +1524,18 @@ AB70..ABBF ; Cherokee # L& [80] CHEROKEE SMALL LETTER A..CHEROKEE SMALL LETT 18AA ; Mongolian # Lo MONGOLIAN LETTER MANCHU ALI GALI LHA 11660..1166C ; Mongolian # Po [13] MONGOLIAN BIRGA WITH ORNAMENT..MONGOLIAN TURNED SWIRL BIRGA WITH DOUBLE ORNAMENT -# Total code points: 167 +# Total code points: 168 # ================================================ 3041..3096 ; Hiragana # Lo [86] HIRAGANA LETTER SMALL A..HIRAGANA LETTER SMALL KE 309D..309E ; Hiragana # Lm [2] HIRAGANA ITERATION MARK..HIRAGANA VOICED ITERATION MARK 309F ; Hiragana # Lo HIRAGANA DIGRAPH YORI -1B001..1B11E ; Hiragana # Lo [286] HIRAGANA LETTER ARCHAIC YE..HENTAIGANA LETTER N-MU-MO-2 +1B001..1B11F ; Hiragana # Lo [287] HIRAGANA LETTER ARCHAIC YE..HIRAGANA LETTER ARCHAIC WU 1B150..1B152 ; Hiragana # Lo [3] HIRAGANA LETTER SMALL WI..HIRAGANA LETTER SMALL WO 1F200 ; Hiragana # So SQUARE HIRAGANA HOKA -# Total code points: 379 +# Total code points: 380 # ================================================ @@ -1514,10 +1547,14 @@ AB70..ABBF ; Cherokee # L& [80] CHEROKEE SMALL LETTER A..CHEROKEE SMALL LETT 3300..3357 ; Katakana # So [88] SQUARE APAATO..SQUARE WATTO FF66..FF6F ; Katakana # Lo [10] HALFWIDTH KATAKANA LETTER WO..HALFWIDTH KATAKANA LETTER SMALL TU FF71..FF9D ; Katakana # Lo [45] HALFWIDTH KATAKANA LETTER A..HALFWIDTH KATAKANA LETTER N +1AFF0..1AFF3 ; Katakana # Lm [4] KATAKANA LETTER MINNAN TONE-2..KATAKANA LETTER MINNAN TONE-5 +1AFF5..1AFFB ; Katakana # Lm [7] KATAKANA LETTER MINNAN TONE-7..KATAKANA LETTER MINNAN NASALIZED TONE-5 +1AFFD..1AFFE ; Katakana # Lm [2] KATAKANA LETTER MINNAN NASALIZED TONE-7..KATAKANA LETTER MINNAN NASALIZED TONE-8 1B000 ; Katakana # Lo KATAKANA LETTER ARCHAIC E +1B120..1B122 ; Katakana # Lo [3] KATAKANA LETTER ARCHAIC YI..KATAKANA LETTER ARCHAIC WU 1B164..1B167 ; Katakana # Lo [4] KATAKANA LETTER SMALL WI..KATAKANA LETTER SMALL N -# Total code points: 304 +# Total code points: 320 # ================================================ @@ -1538,19 +1575,21 @@ FF71..FF9D ; Katakana # Lo [45] HALFWIDTH KATAKANA LETTER A..HALFWIDTH KATAK 3038..303A ; Han # Nl [3] HANGZHOU NUMERAL TEN..HANGZHOU NUMERAL THIRTY 303B ; Han # Lm VERTICAL IDEOGRAPHIC ITERATION MARK 3400..4DBF ; Han # Lo [6592] CJK UNIFIED IDEOGRAPH-3400..CJK UNIFIED IDEOGRAPH-4DBF -4E00..9FFC ; Han # Lo [20989] CJK UNIFIED IDEOGRAPH-4E00..CJK UNIFIED IDEOGRAPH-9FFC +4E00..9FFF ; Han # Lo [20992] CJK UNIFIED IDEOGRAPH-4E00..CJK UNIFIED IDEOGRAPH-9FFF F900..FA6D ; Han # Lo [366] CJK COMPATIBILITY IDEOGRAPH-F900..CJK COMPATIBILITY IDEOGRAPH-FA6D FA70..FAD9 ; Han # Lo [106] CJK COMPATIBILITY IDEOGRAPH-FA70..CJK COMPATIBILITY IDEOGRAPH-FAD9 +16FE2 ; Han # Po OLD CHINESE HOOK MARK +16FE3 ; Han # Lm OLD CHINESE ITERATION MARK 16FF0..16FF1 ; Han # Mc [2] VIETNAMESE ALTERNATE READING MARK CA..VIETNAMESE ALTERNATE READING MARK NHAY -20000..2A6DD ; Han # Lo [42718] CJK UNIFIED IDEOGRAPH-20000..CJK UNIFIED IDEOGRAPH-2A6DD -2A700..2B734 ; Han # Lo [4149] CJK UNIFIED IDEOGRAPH-2A700..CJK UNIFIED IDEOGRAPH-2B734 +20000..2A6DF ; Han # Lo [42720] CJK UNIFIED IDEOGRAPH-20000..CJK UNIFIED IDEOGRAPH-2A6DF +2A700..2B738 ; Han # Lo [4153] CJK UNIFIED IDEOGRAPH-2A700..CJK UNIFIED IDEOGRAPH-2B738 2B740..2B81D ; Han # Lo [222] CJK UNIFIED IDEOGRAPH-2B740..CJK UNIFIED IDEOGRAPH-2B81D 2B820..2CEA1 ; Han # Lo [5762] CJK UNIFIED IDEOGRAPH-2B820..CJK UNIFIED IDEOGRAPH-2CEA1 2CEB0..2EBE0 ; Han # Lo [7473] CJK UNIFIED IDEOGRAPH-2CEB0..CJK UNIFIED IDEOGRAPH-2EBE0 2F800..2FA1D ; Han # Lo [542] CJK COMPATIBILITY IDEOGRAPH-2F800..CJK COMPATIBILITY IDEOGRAPH-2FA1D 30000..3134A ; Han # Lo [4939] CJK UNIFIED IDEOGRAPH-30000..CJK UNIFIED IDEOGRAPH-3134A -# Total code points: 94204 +# Total code points: 94215 # ================================================ @@ -1593,15 +1632,14 @@ A490..A4C6 ; Yi # So [55] YI RADICAL QOT..YI RADICAL KE 0951..0954 ; Inherited # Mn [4] DEVANAGARI STRESS SIGN UDATTA..DEVANAGARI ACUTE ACCENT 1AB0..1ABD ; Inherited # Mn [14] COMBINING DOUBLED CIRCUMFLEX ACCENT..COMBINING PARENTHESES BELOW 1ABE ; Inherited # Me COMBINING PARENTHESES OVERLAY -1ABF..1AC0 ; Inherited # Mn [2] COMBINING LATIN SMALL LETTER W BELOW..COMBINING LATIN SMALL LETTER TURNED W BELOW +1ABF..1ACE ; Inherited # Mn [16] COMBINING LATIN SMALL LETTER W BELOW..COMBINING LATIN SMALL LETTER INSULAR T 1CD0..1CD2 ; Inherited # Mn [3] VEDIC TONE KARSHANA..VEDIC TONE PRENKHA 1CD4..1CE0 ; Inherited # Mn [13] VEDIC SIGN YAJURVEDIC MIDLINE SVARITA..VEDIC TONE RIGVEDIC KASHMIRI INDEPENDENT SVARITA 1CE2..1CE8 ; Inherited # Mn [7] VEDIC SIGN VISARGA SVARITA..VEDIC SIGN VISARGA ANUDATTA WITH TAIL 1CED ; Inherited # Mn VEDIC SIGN TIRYAK 1CF4 ; Inherited # Mn VEDIC TONE CANDRA ABOVE 1CF8..1CF9 ; Inherited # Mn [2] VEDIC TONE RING ABOVE..VEDIC TONE DOUBLE RING ABOVE -1DC0..1DF9 ; Inherited # Mn [58] COMBINING DOTTED GRAVE ACCENT..COMBINING WIDE INVERTED BRIDGE BELOW -1DFB..1DFF ; Inherited # Mn [5] COMBINING DELETION MARK..COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW +1DC0..1DFF ; Inherited # Mn [64] COMBINING DOTTED GRAVE ACCENT..COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW 200C..200D ; Inherited # Cf [2] ZERO WIDTH NON-JOINER..ZERO WIDTH JOINER 20D0..20DC ; Inherited # Mn [13] COMBINING LEFT HARPOON ABOVE..COMBINING FOUR DOTS ABOVE 20DD..20E0 ; Inherited # Me [4] COMBINING ENCLOSING CIRCLE..COMBINING ENCLOSING CIRCLE BACKSLASH @@ -1615,26 +1653,30 @@ FE20..FE2D ; Inherited # Mn [14] COMBINING LIGATURE LEFT HALF..COMBINING CON 101FD ; Inherited # Mn PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE 102E0 ; Inherited # Mn COPTIC EPACT THOUSANDS MARK 1133B ; Inherited # Mn COMBINING BINDU BELOW +1CF00..1CF2D ; Inherited # Mn [46] ZNAMENNY COMBINING MARK GORAZDO NIZKO S KRYZHEM ON LEFT..ZNAMENNY COMBINING MARK KRYZH ON LEFT +1CF30..1CF46 ; Inherited # Mn [23] ZNAMENNY COMBINING TONAL RANGE MARK MRACHNO..ZNAMENNY PRIZNAK MODIFIER ROG 1D167..1D169 ; Inherited # Mn [3] MUSICAL SYMBOL COMBINING TREMOLO-1..MUSICAL SYMBOL COMBINING TREMOLO-3 1D17B..1D182 ; Inherited # Mn [8] MUSICAL SYMBOL COMBINING ACCENT..MUSICAL SYMBOL COMBINING LOURE 1D185..1D18B ; Inherited # Mn [7] MUSICAL SYMBOL COMBINING DOIT..MUSICAL SYMBOL COMBINING TRIPLE TONGUE 1D1AA..1D1AD ; Inherited # Mn [4] MUSICAL SYMBOL COMBINING DOWN BOW..MUSICAL SYMBOL COMBINING SNAP PIZZICATO E0100..E01EF ; Inherited # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256 -# Total code points: 573 +# Total code points: 657 # ================================================ -1700..170C ; Tagalog # Lo [13] TAGALOG LETTER A..TAGALOG LETTER YA -170E..1711 ; Tagalog # Lo [4] TAGALOG LETTER LA..TAGALOG LETTER HA +1700..1711 ; Tagalog # Lo [18] TAGALOG LETTER A..TAGALOG LETTER HA 1712..1714 ; Tagalog # Mn [3] TAGALOG VOWEL SIGN I..TAGALOG SIGN VIRAMA +1715 ; Tagalog # Mc TAGALOG SIGN PAMUDPOD +171F ; Tagalog # Lo TAGALOG LETTER ARCHAIC RA -# Total code points: 20 +# Total code points: 23 # ================================================ 1720..1731 ; Hanunoo # Lo [18] HANUNOO LETTER A..HANUNOO LETTER HA -1732..1734 ; Hanunoo # Mn [3] HANUNOO VOWEL SIGN I..HANUNOO SIGN PAMUDPOD +1732..1733 ; Hanunoo # Mn [2] HANUNOO VOWEL SIGN I..HANUNOO VOWEL SIGN U +1734 ; Hanunoo # Mc HANUNOO SIGN PAMUDPOD # Total code points: 21 @@ -1762,15 +1804,14 @@ E0100..E01EF ; Inherited # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-2 # ================================================ -2C00..2C2E ; Glagolitic # L& [47] GLAGOLITIC CAPITAL LETTER AZU..GLAGOLITIC CAPITAL LETTER LATINATE MYSLITE -2C30..2C5E ; Glagolitic # L& [47] GLAGOLITIC SMALL LETTER AZU..GLAGOLITIC SMALL LETTER LATINATE MYSLITE +2C00..2C5F ; Glagolitic # L& [96] GLAGOLITIC CAPITAL LETTER AZU..GLAGOLITIC SMALL LETTER CAUDATE CHRIVI 1E000..1E006 ; Glagolitic # Mn [7] COMBINING GLAGOLITIC LETTER AZU..COMBINING GLAGOLITIC LETTER ZHIVETE 1E008..1E018 ; Glagolitic # Mn [17] COMBINING GLAGOLITIC LETTER ZEMLJA..COMBINING GLAGOLITIC LETTER HERU 1E01B..1E021 ; Glagolitic # Mn [7] COMBINING GLAGOLITIC LETTER SHTA..COMBINING GLAGOLITIC LETTER YATI 1E023..1E024 ; Glagolitic # Mn [2] COMBINING GLAGOLITIC LETTER YU..COMBINING GLAGOLITIC LETTER SMALL YUS 1E026..1E02A ; Glagolitic # Mn [5] COMBINING GLAGOLITIC LETTER YO..COMBINING GLAGOLITIC LETTER FITA -# Total code points: 132 +# Total code points: 134 # ================================================ @@ -1836,14 +1877,15 @@ A82C ; Syloti_Nagri # Mn SYLOTI NAGRI SIGN ALTERNATE HASANTA 1B3D..1B41 ; Balinese # Mc [5] BALINESE VOWEL SIGN LA LENGA TEDUNG..BALINESE VOWEL SIGN TALING REPA TEDUNG 1B42 ; Balinese # Mn BALINESE VOWEL SIGN PEPET 1B43..1B44 ; Balinese # Mc [2] BALINESE VOWEL SIGN PEPET TEDUNG..BALINESE ADEG ADEG -1B45..1B4B ; Balinese # Lo [7] BALINESE LETTER KAF SASAK..BALINESE LETTER ASYURA SASAK +1B45..1B4C ; Balinese # Lo [8] BALINESE LETTER KAF SASAK..BALINESE LETTER ARCHAIC JNYA 1B50..1B59 ; Balinese # Nd [10] BALINESE DIGIT ZERO..BALINESE DIGIT NINE 1B5A..1B60 ; Balinese # Po [7] BALINESE PANTI..BALINESE PAMENENG 1B61..1B6A ; Balinese # So [10] BALINESE MUSICAL SYMBOL DONG..BALINESE MUSICAL SYMBOL DANG GEDE 1B6B..1B73 ; Balinese # Mn [9] BALINESE MUSICAL SYMBOL COMBINING TEGEH..BALINESE MUSICAL SYMBOL COMBINING GONG 1B74..1B7C ; Balinese # So [9] BALINESE MUSICAL SYMBOL RIGHT-HAND OPEN DUG..BALINESE MUSICAL SYMBOL LEFT-HAND OPEN PING +1B7D..1B7E ; Balinese # Po [2] BALINESE PANTI LANTANG..BALINESE PAMADA LANTANG -# Total code points: 121 +# Total code points: 124 # ================================================ @@ -2178,9 +2220,10 @@ ABF0..ABF9 ; Meetei_Mayek # Nd [10] MEETEI MAYEK DIGIT ZERO..MEETEI MAYEK DI 110BB..110BC ; Kaithi # Po [2] KAITHI ABBREVIATION SIGN..KAITHI ENUMERATION SIGN 110BD ; Kaithi # Cf KAITHI NUMBER SIGN 110BE..110C1 ; Kaithi # Po [4] KAITHI SECTION MARK..KAITHI DOUBLE DANDA +110C2 ; Kaithi # Mn KAITHI VOWEL SIGN VOCALIC R 110CD ; Kaithi # Cf KAITHI NUMBER SIGN ABOVE -# Total code points: 67 +# Total code points: 68 # ================================================ @@ -2207,9 +2250,13 @@ ABF0..ABF9 ; Meetei_Mayek # Nd [10] MEETEI MAYEK DIGIT ZERO..MEETEI MAYEK DI 11047..1104D ; Brahmi # Po [7] BRAHMI DANDA..BRAHMI PUNCTUATION LOTUS 11052..11065 ; Brahmi # No [20] BRAHMI NUMBER ONE..BRAHMI NUMBER ONE THOUSAND 11066..1106F ; Brahmi # Nd [10] BRAHMI DIGIT ZERO..BRAHMI DIGIT NINE +11070 ; Brahmi # Mn BRAHMI SIGN OLD TAMIL VIRAMA +11071..11072 ; Brahmi # Lo [2] BRAHMI LETTER OLD TAMIL SHORT E..BRAHMI LETTER OLD TAMIL SHORT O +11073..11074 ; Brahmi # Mn [2] BRAHMI VOWEL SIGN OLD TAMIL SHORT E..BRAHMI VOWEL SIGN OLD TAMIL SHORT O +11075 ; Brahmi # Lo BRAHMI LETTER OLD TAMIL LLA 1107F ; Brahmi # Mn BRAHMI NUMBER JOINER -# Total code points: 109 +# Total code points: 115 # ================================================ @@ -2301,9 +2348,10 @@ ABF0..ABF9 ; Meetei_Mayek # Nd [10] MEETEI MAYEK DIGIT ZERO..MEETEI MAYEK DI 116B6 ; Takri # Mc TAKRI SIGN VIRAMA 116B7 ; Takri # Mn TAKRI SIGN NUKTA 116B8 ; Takri # Lo TAKRI LETTER ARCHAIC KHA +116B9 ; Takri # Po TAKRI ABBREVIATION SIGN 116C0..116C9 ; Takri # Nd [10] TAKRI DIGIT ZERO..TAKRI DIGIT NINE -# Total code points: 67 +# Total code points: 68 # ================================================ @@ -2561,8 +2609,9 @@ ABF0..ABF9 ; Meetei_Mayek # Nd [10] MEETEI MAYEK DIGIT ZERO..MEETEI MAYEK DI 1173A..1173B ; Ahom # No [2] AHOM NUMBER TEN..AHOM NUMBER TWENTY 1173C..1173E ; Ahom # Po [3] AHOM SIGN SMALL SECTION..AHOM SIGN RULAI 1173F ; Ahom # So AHOM SYMBOL VI +11740..11746 ; Ahom # Lo [7] AHOM LETTER CA..AHOM LETTER LLA -# Total code points: 58 +# Total code points: 65 # ================================================ @@ -2897,4 +2946,46 @@ ABF0..ABF9 ; Meetei_Mayek # Nd [10] MEETEI MAYEK DIGIT ZERO..MEETEI MAYEK DI # Total code points: 47 +# ================================================ + +12F90..12FF0 ; Cypro_Minoan # Lo [97] CYPRO-MINOAN SIGN CM001..CYPRO-MINOAN SIGN CM114 +12FF1..12FF2 ; Cypro_Minoan # Po [2] CYPRO-MINOAN SIGN CM301..CYPRO-MINOAN SIGN CM302 + +# Total code points: 99 + +# ================================================ + +10F70..10F81 ; Old_Uyghur # Lo [18] OLD UYGHUR LETTER ALEPH..OLD UYGHUR LETTER LESH +10F82..10F85 ; Old_Uyghur # Mn [4] OLD UYGHUR COMBINING DOT ABOVE..OLD UYGHUR COMBINING TWO DOTS BELOW +10F86..10F89 ; Old_Uyghur # Po [4] OLD UYGHUR PUNCTUATION BAR..OLD UYGHUR PUNCTUATION FOUR DOTS + +# Total code points: 26 + +# ================================================ + +16A70..16ABE ; Tangsa # Lo [79] TANGSA LETTER OZ..TANGSA LETTER ZA +16AC0..16AC9 ; Tangsa # Nd [10] TANGSA DIGIT ZERO..TANGSA DIGIT NINE + +# Total code points: 89 + +# ================================================ + +1E290..1E2AD ; Toto # Lo [30] TOTO LETTER PA..TOTO LETTER A +1E2AE ; Toto # Mn TOTO SIGN RISING TONE + +# Total code points: 31 + +# ================================================ + +10570..1057A ; Vithkuqi # L& [11] VITHKUQI CAPITAL LETTER A..VITHKUQI CAPITAL LETTER GA +1057C..1058A ; Vithkuqi # L& [15] VITHKUQI CAPITAL LETTER HA..VITHKUQI CAPITAL LETTER RE +1058C..10592 ; Vithkuqi # L& [7] VITHKUQI CAPITAL LETTER SE..VITHKUQI CAPITAL LETTER XE +10594..10595 ; Vithkuqi # L& [2] VITHKUQI CAPITAL LETTER Y..VITHKUQI CAPITAL LETTER ZE +10597..105A1 ; Vithkuqi # L& [11] VITHKUQI SMALL LETTER A..VITHKUQI SMALL LETTER GA +105A3..105B1 ; Vithkuqi # L& [15] VITHKUQI SMALL LETTER HA..VITHKUQI SMALL LETTER RE +105B3..105B9 ; Vithkuqi # L& [7] VITHKUQI SMALL LETTER SE..VITHKUQI SMALL LETTER XE +105BB..105BC ; Vithkuqi # L& [2] VITHKUQI SMALL LETTER Y..VITHKUQI SMALL LETTER ZE + +# Total code points: 70 + # EOF diff --git a/make/data/unicodedata/SpecialCasing.txt b/make/data/unicodedata/SpecialCasing.txt index ae71d58f644..5c2a8aae46d 100644 --- a/make/data/unicodedata/SpecialCasing.txt +++ b/make/data/unicodedata/SpecialCasing.txt @@ -1,6 +1,6 @@ -# SpecialCasing-13.0.0.txt -# Date: 2019-09-08, 23:31:24 GMT -# Copyright (c) 2019 Unicode, Inc. +# SpecialCasing-14.0.0.txt +# Date: 2021-03-08, 19:35:55 GMT +# Copyright (c) 2021 Unicode, Inc. # Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries. # For terms of use, see http://www.unicode.org/terms_of_use.html # diff --git a/make/data/unicodedata/UnicodeData.txt b/make/data/unicodedata/UnicodeData.txt index e22f967bbab..b5abef7ed43 100644 --- a/make/data/unicodedata/UnicodeData.txt +++ b/make/data/unicodedata/UnicodeData.txt @@ -1525,6 +1525,7 @@ 061A;ARABIC SMALL KASRA;Mn;32;NSM;;;;;N;;;;; 061B;ARABIC SEMICOLON;Po;0;AL;;;;;N;;;;; 061C;ARABIC LETTER MARK;Cf;0;AL;;;;;N;;;;; +061D;ARABIC END OF TEXT MARK;Po;0;AL;;;;;N;;;;; 061E;ARABIC TRIPLE DOT PUNCTUATION MARK;Po;0;AL;;;;;N;;;;; 061F;ARABIC QUESTION MARK;Po;0;AL;;;;;N;;;;; 0620;ARABIC LETTER KASHMIRI YEH;Lo;0;AL;;;;;N;;;;; @@ -2089,6 +2090,47 @@ 0868;SYRIAC LETTER MALAYALAM LLA;Lo;0;AL;;;;;N;;;;; 0869;SYRIAC LETTER MALAYALAM LLLA;Lo;0;AL;;;;;N;;;;; 086A;SYRIAC LETTER MALAYALAM SSA;Lo;0;AL;;;;;N;;;;; +0870;ARABIC LETTER ALEF WITH ATTACHED FATHA;Lo;0;AL;;;;;N;;;;; +0871;ARABIC LETTER ALEF WITH ATTACHED TOP RIGHT FATHA;Lo;0;AL;;;;;N;;;;; +0872;ARABIC LETTER ALEF WITH RIGHT MIDDLE STROKE;Lo;0;AL;;;;;N;;;;; +0873;ARABIC LETTER ALEF WITH LEFT MIDDLE STROKE;Lo;0;AL;;;;;N;;;;; +0874;ARABIC LETTER ALEF WITH ATTACHED KASRA;Lo;0;AL;;;;;N;;;;; +0875;ARABIC LETTER ALEF WITH ATTACHED BOTTOM RIGHT KASRA;Lo;0;AL;;;;;N;;;;; +0876;ARABIC LETTER ALEF WITH ATTACHED ROUND DOT ABOVE;Lo;0;AL;;;;;N;;;;; +0877;ARABIC LETTER ALEF WITH ATTACHED RIGHT ROUND DOT;Lo;0;AL;;;;;N;;;;; +0878;ARABIC LETTER ALEF WITH ATTACHED LEFT ROUND DOT;Lo;0;AL;;;;;N;;;;; +0879;ARABIC LETTER ALEF WITH ATTACHED ROUND DOT BELOW;Lo;0;AL;;;;;N;;;;; +087A;ARABIC LETTER ALEF WITH DOT ABOVE;Lo;0;AL;;;;;N;;;;; +087B;ARABIC LETTER ALEF WITH ATTACHED TOP RIGHT FATHA AND DOT ABOVE;Lo;0;AL;;;;;N;;;;; +087C;ARABIC LETTER ALEF WITH RIGHT MIDDLE STROKE AND DOT ABOVE;Lo;0;AL;;;;;N;;;;; +087D;ARABIC LETTER ALEF WITH ATTACHED BOTTOM RIGHT KASRA AND DOT ABOVE;Lo;0;AL;;;;;N;;;;; +087E;ARABIC LETTER ALEF WITH ATTACHED TOP RIGHT FATHA AND LEFT RING;Lo;0;AL;;;;;N;;;;; +087F;ARABIC LETTER ALEF WITH RIGHT MIDDLE STROKE AND LEFT RING;Lo;0;AL;;;;;N;;;;; +0880;ARABIC LETTER ALEF WITH ATTACHED BOTTOM RIGHT KASRA AND LEFT RING;Lo;0;AL;;;;;N;;;;; +0881;ARABIC LETTER ALEF WITH ATTACHED RIGHT HAMZA;Lo;0;AL;;;;;N;;;;; +0882;ARABIC LETTER ALEF WITH ATTACHED LEFT HAMZA;Lo;0;AL;;;;;N;;;;; +0883;ARABIC TATWEEL WITH OVERSTRUCK HAMZA;Lo;0;AL;;;;;N;;;;; +0884;ARABIC TATWEEL WITH OVERSTRUCK WAW;Lo;0;AL;;;;;N;;;;; +0885;ARABIC TATWEEL WITH TWO DOTS BELOW;Lo;0;AL;;;;;N;;;;; +0886;ARABIC LETTER THIN YEH;Lo;0;AL;;;;;N;;;;; +0887;ARABIC BASELINE ROUND DOT;Lo;0;AL;;;;;N;;;;; +0888;ARABIC RAISED ROUND DOT;Sk;0;AL;;;;;N;;;;; +0889;ARABIC LETTER NOON WITH INVERTED SMALL V;Lo;0;AL;;;;;N;;;;; +088A;ARABIC LETTER HAH WITH INVERTED SMALL V BELOW;Lo;0;AL;;;;;N;;;;; +088B;ARABIC LETTER TAH WITH DOT BELOW;Lo;0;AL;;;;;N;;;;; +088C;ARABIC LETTER TAH WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;;;;; +088D;ARABIC LETTER KEHEH WITH TWO DOTS VERTICALLY BELOW;Lo;0;AL;;;;;N;;;;; +088E;ARABIC VERTICAL TAIL;Lo;0;AL;;;;;N;;;;; +0890;ARABIC POUND MARK ABOVE;Cf;0;AN;;;;;N;;;;; +0891;ARABIC PIASTRE MARK ABOVE;Cf;0;AN;;;;;N;;;;; +0898;ARABIC SMALL HIGH WORD AL-JUZ;Mn;230;NSM;;;;;N;;;;; +0899;ARABIC SMALL LOW WORD ISHMAAM;Mn;220;NSM;;;;;N;;;;; +089A;ARABIC SMALL LOW WORD IMAALA;Mn;220;NSM;;;;;N;;;;; +089B;ARABIC SMALL LOW WORD TASHEEL;Mn;220;NSM;;;;;N;;;;; +089C;ARABIC MADDA WAAJIB;Mn;230;NSM;;;;;N;;;;; +089D;ARABIC SUPERSCRIPT ALEF MOKHASSAS;Mn;230;NSM;;;;;N;;;;; +089E;ARABIC DOUBLED MADDA;Mn;230;NSM;;;;;N;;;;; +089F;ARABIC HALF MADDA OVER MADDA;Mn;230;NSM;;;;;N;;;;; 08A0;ARABIC LETTER BEH WITH SMALL V BELOW;Lo;0;AL;;;;;N;;;;; 08A1;ARABIC LETTER BEH WITH HAMZA ABOVE;Lo;0;AL;;;;;N;;;;; 08A2;ARABIC LETTER JEEM WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;; @@ -2110,6 +2152,7 @@ 08B2;ARABIC LETTER ZAIN WITH INVERTED V ABOVE;Lo;0;AL;;;;;N;;;;; 08B3;ARABIC LETTER AIN WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;;;;; 08B4;ARABIC LETTER KAF WITH DOT BELOW;Lo;0;AL;;;;;N;;;;; +08B5;ARABIC LETTER QAF WITH DOT BELOW AND NO DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 08B6;ARABIC LETTER BEH WITH SMALL MEEM ABOVE;Lo;0;AL;;;;;N;;;;; 08B7;ARABIC LETTER PEH WITH SMALL MEEM ABOVE;Lo;0;AL;;;;;N;;;;; 08B8;ARABIC LETTER TEH WITH SMALL TEH ABOVE;Lo;0;AL;;;;;N;;;;; @@ -2128,6 +2171,17 @@ 08C5;ARABIC LETTER JEEM WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 08C6;ARABIC LETTER JEEM WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;;;;; 08C7;ARABIC LETTER LAM WITH SMALL ARABIC LETTER TAH ABOVE;Lo;0;AL;;;;;N;;;;; +08C8;ARABIC LETTER GRAF;Lo;0;AL;;;;;N;;;;; +08C9;ARABIC SMALL FARSI YEH;Lm;0;AL;;;;;N;;;;; +08CA;ARABIC SMALL HIGH FARSI YEH;Mn;230;NSM;;;;;N;;;;; +08CB;ARABIC SMALL HIGH YEH BARREE WITH TWO DOTS BELOW;Mn;230;NSM;;;;;N;;;;; +08CC;ARABIC SMALL HIGH WORD SAH;Mn;230;NSM;;;;;N;;;;; +08CD;ARABIC SMALL HIGH ZAH;Mn;230;NSM;;;;;N;;;;; +08CE;ARABIC LARGE ROUND DOT ABOVE;Mn;230;NSM;;;;;N;;;;; +08CF;ARABIC LARGE ROUND DOT BELOW;Mn;220;NSM;;;;;N;;;;; +08D0;ARABIC SUKUN BELOW;Mn;220;NSM;;;;;N;;;;; +08D1;ARABIC LARGE CIRCLE BELOW;Mn;220;NSM;;;;;N;;;;; +08D2;ARABIC LARGE ROUND DOT INSIDE CIRCLE BELOW;Mn;220;NSM;;;;;N;;;;; 08D3;ARABIC SMALL LOW WAW;Mn;220;NSM;;;;;N;;;;; 08D4;ARABIC SMALL HIGH WORD AR-RUB;Mn;230;NSM;;;;;N;;;;; 08D5;ARABIC SMALL HIGH SAD;Mn;230;NSM;;;;;N;;;;; @@ -2786,6 +2840,7 @@ 0C37;TELUGU LETTER SSA;Lo;0;L;;;;;N;;;;; 0C38;TELUGU LETTER SA;Lo;0;L;;;;;N;;;;; 0C39;TELUGU LETTER HA;Lo;0;L;;;;;N;;;;; +0C3C;TELUGU SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; 0C3D;TELUGU SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; 0C3E;TELUGU VOWEL SIGN AA;Mn;0;NSM;;;;;N;;;;; 0C3F;TELUGU VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; @@ -2806,6 +2861,7 @@ 0C58;TELUGU LETTER TSA;Lo;0;L;;;;;N;;;;; 0C59;TELUGU LETTER DZA;Lo;0;L;;;;;N;;;;; 0C5A;TELUGU LETTER RRRA;Lo;0;L;;;;;N;;;;; +0C5D;TELUGU LETTER NAKAARA POLLU;Lo;0;L;;;;;N;;;;; 0C60;TELUGU LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; 0C61;TELUGU LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; 0C62;TELUGU VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; @@ -2901,6 +2957,7 @@ 0CCD;KANNADA SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 0CD5;KANNADA LENGTH MARK;Mc;0;L;;;;;N;;;;; 0CD6;KANNADA AI LENGTH MARK;Mc;0;L;;;;;N;;;;; +0CDD;KANNADA LETTER NAKAARA POLLU;Lo;0;L;;;;;N;;;;; 0CDE;KANNADA LETTER FA;Lo;0;L;;;;;N;;;;; 0CE0;KANNADA LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; 0CE1;KANNADA LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; @@ -5258,6 +5315,7 @@ 170A;TAGALOG LETTER BA;Lo;0;L;;;;;N;;;;; 170B;TAGALOG LETTER MA;Lo;0;L;;;;;N;;;;; 170C;TAGALOG LETTER YA;Lo;0;L;;;;;N;;;;; +170D;TAGALOG LETTER RA;Lo;0;L;;;;;N;;;;; 170E;TAGALOG LETTER LA;Lo;0;L;;;;;N;;;;; 170F;TAGALOG LETTER WA;Lo;0;L;;;;;N;;;;; 1710;TAGALOG LETTER SA;Lo;0;L;;;;;N;;;;; @@ -5265,6 +5323,8 @@ 1712;TAGALOG VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 1713;TAGALOG VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 1714;TAGALOG SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; +1715;TAGALOG SIGN PAMUDPOD;Mc;9;L;;;;;N;;;;; +171F;TAGALOG LETTER ARCHAIC RA;Lo;0;L;;;;;N;;;;; 1720;HANUNOO LETTER A;Lo;0;L;;;;;N;;;;; 1721;HANUNOO LETTER I;Lo;0;L;;;;;N;;;;; 1722;HANUNOO LETTER U;Lo;0;L;;;;;N;;;;; @@ -5285,7 +5345,7 @@ 1731;HANUNOO LETTER HA;Lo;0;L;;;;;N;;;;; 1732;HANUNOO VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 1733;HANUNOO VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; -1734;HANUNOO SIGN PAMUDPOD;Mn;9;NSM;;;;;N;;;;; +1734;HANUNOO SIGN PAMUDPOD;Mc;9;L;;;;;N;;;;; 1735;PHILIPPINE SINGLE PUNCTUATION;Po;0;L;;;;;N;;;;; 1736;PHILIPPINE DOUBLE PUNCTUATION;Po;0;L;;;;;N;;;;; 1740;BUHID LETTER A;Lo;0;L;;;;;N;;;;; @@ -5455,6 +5515,7 @@ 180C;MONGOLIAN FREE VARIATION SELECTOR TWO;Mn;0;NSM;;;;;N;;;;; 180D;MONGOLIAN FREE VARIATION SELECTOR THREE;Mn;0;NSM;;;;;N;;;;; 180E;MONGOLIAN VOWEL SEPARATOR;Cf;0;BN;;;;;N;;;;; +180F;MONGOLIAN FREE VARIATION SELECTOR FOUR;Mn;0;NSM;;;;;N;;;;; 1810;MONGOLIAN DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 1811;MONGOLIAN DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 1812;MONGOLIAN DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; @@ -6059,6 +6120,20 @@ 1ABE;COMBINING PARENTHESES OVERLAY;Me;0;NSM;;;;;N;;;;; 1ABF;COMBINING LATIN SMALL LETTER W BELOW;Mn;220;NSM;;;;;N;;;;; 1AC0;COMBINING LATIN SMALL LETTER TURNED W BELOW;Mn;220;NSM;;;;;N;;;;; +1AC1;COMBINING LEFT PARENTHESIS ABOVE LEFT;Mn;230;NSM;;;;;N;;;;; +1AC2;COMBINING RIGHT PARENTHESIS ABOVE RIGHT;Mn;230;NSM;;;;;N;;;;; +1AC3;COMBINING LEFT PARENTHESIS BELOW LEFT;Mn;220;NSM;;;;;N;;;;; +1AC4;COMBINING RIGHT PARENTHESIS BELOW RIGHT;Mn;220;NSM;;;;;N;;;;; +1AC5;COMBINING SQUARE BRACKETS ABOVE;Mn;230;NSM;;;;;N;;;;; +1AC6;COMBINING NUMBER SIGN ABOVE;Mn;230;NSM;;;;;N;;;;; +1AC7;COMBINING INVERTED DOUBLE ARCH ABOVE;Mn;230;NSM;;;;;N;;;;; +1AC8;COMBINING PLUS SIGN ABOVE;Mn;230;NSM;;;;;N;;;;; +1AC9;COMBINING DOUBLE PLUS SIGN ABOVE;Mn;230;NSM;;;;;N;;;;; +1ACA;COMBINING DOUBLE PLUS SIGN BELOW;Mn;220;NSM;;;;;N;;;;; +1ACB;COMBINING TRIPLE ACUTE ACCENT;Mn;230;NSM;;;;;N;;;;; +1ACC;COMBINING LATIN SMALL LETTER INSULAR G;Mn;230;NSM;;;;;N;;;;; +1ACD;COMBINING LATIN SMALL LETTER INSULAR R;Mn;230;NSM;;;;;N;;;;; +1ACE;COMBINING LATIN SMALL LETTER INSULAR T;Mn;230;NSM;;;;;N;;;;; 1B00;BALINESE SIGN ULU RICEM;Mn;0;NSM;;;;;N;;;;; 1B01;BALINESE SIGN ULU CANDRA;Mn;0;NSM;;;;;N;;;;; 1B02;BALINESE SIGN CECEK;Mn;0;NSM;;;;;N;;;;; @@ -6135,6 +6210,7 @@ 1B49;BALINESE LETTER VE SASAK;Lo;0;L;;;;;N;;;;; 1B4A;BALINESE LETTER ZAL SASAK;Lo;0;L;;;;;N;;;;; 1B4B;BALINESE LETTER ASYURA SASAK;Lo;0;L;;;;;N;;;;; +1B4C;BALINESE LETTER ARCHAIC JNYA;Lo;0;L;;;;;N;;;;; 1B50;BALINESE DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 1B51;BALINESE DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 1B52;BALINESE DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; @@ -6180,6 +6256,8 @@ 1B7A;BALINESE MUSICAL SYMBOL LEFT-HAND CLOSED PLAK;So;0;L;;;;;N;;;;; 1B7B;BALINESE MUSICAL SYMBOL LEFT-HAND CLOSED PLUK;So;0;L;;;;;N;;;;; 1B7C;BALINESE MUSICAL SYMBOL LEFT-HAND OPEN PING;So;0;L;;;;;N;;;;; +1B7D;BALINESE PANTI LANTANG;Po;0;L;;;;;N;;;;; +1B7E;BALINESE PAMADA LANTANG;Po;0;L;;;;;N;;;;; 1B80;SUNDANESE SIGN PANYECEK;Mn;0;NSM;;;;;N;;;;; 1B81;SUNDANESE SIGN PANGLAYAR;Mn;0;NSM;;;;;N;;;;; 1B82;SUNDANESE SIGN PANGWISAD;Mc;0;L;;;;;N;;;;; @@ -6778,6 +6856,7 @@ 1DF7;COMBINING KAVYKA ABOVE LEFT;Mn;228;NSM;;;;;N;;;;; 1DF8;COMBINING DOT ABOVE LEFT;Mn;228;NSM;;;;;N;;;;; 1DF9;COMBINING WIDE INVERTED BRIDGE BELOW;Mn;220;NSM;;;;;N;;;;; +1DFA;COMBINING DOT BELOW LEFT;Mn;218;NSM;;;;;N;;;;; 1DFB;COMBINING DELETION MARK;Mn;230;NSM;;;;;N;;;;; 1DFC;COMBINING DOUBLE INVERTED BREVE BELOW;Mn;233;NSM;;;;;N;;;;; 1DFD;COMBINING ALMOST EQUAL TO BELOW;Mn;220;NSM;;;;;N;;;;; @@ -7457,6 +7536,7 @@ 20BD;RUBLE SIGN;Sc;0;ET;;;;;N;;;;; 20BE;LARI SIGN;Sc;0;ET;;;;;N;;;;; 20BF;BITCOIN SIGN;Sc;0;ET;;;;;N;;;;; +20C0;SOM SIGN;Sc;0;ET;;;;;N;;;;; 20D0;COMBINING LEFT HARPOON ABOVE;Mn;230;NSM;;;;;N;NON-SPACING LEFT HARPOON ABOVE;;;; 20D1;COMBINING RIGHT HARPOON ABOVE;Mn;230;NSM;;;;;N;NON-SPACING RIGHT HARPOON ABOVE;;;; 20D2;COMBINING LONG VERTICAL LINE OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING LONG VERTICAL BAR OVERLAY;;;; @@ -10300,6 +10380,7 @@ 2C2C;GLAGOLITIC CAPITAL LETTER SHTAPIC;Lu;0;L;;;;;N;;;;2C5C; 2C2D;GLAGOLITIC CAPITAL LETTER TROKUTASTI A;Lu;0;L;;;;;N;;;;2C5D; 2C2E;GLAGOLITIC CAPITAL LETTER LATINATE MYSLITE;Lu;0;L;;;;;N;;;;2C5E; +2C2F;GLAGOLITIC CAPITAL LETTER CAUDATE CHRIVI;Lu;0;L;;;;;N;;;;2C5F; 2C30;GLAGOLITIC SMALL LETTER AZU;Ll;0;L;;;;;N;;;2C00;;2C00 2C31;GLAGOLITIC SMALL LETTER BUKY;Ll;0;L;;;;;N;;;2C01;;2C01 2C32;GLAGOLITIC SMALL LETTER VEDE;Ll;0;L;;;;;N;;;2C02;;2C02 @@ -10347,6 +10428,7 @@ 2C5C;GLAGOLITIC SMALL LETTER SHTAPIC;Ll;0;L;;;;;N;;;2C2C;;2C2C 2C5D;GLAGOLITIC SMALL LETTER TROKUTASTI A;Ll;0;L;;;;;N;;;2C2D;;2C2D 2C5E;GLAGOLITIC SMALL LETTER LATINATE MYSLITE;Ll;0;L;;;;;N;;;2C2E;;2C2E +2C5F;GLAGOLITIC SMALL LETTER CAUDATE CHRIVI;Ll;0;L;;;;;N;;;2C2F;;2C2F 2C60;LATIN CAPITAL LETTER L WITH DOUBLE BAR;Lu;0;L;;;;;N;;;;2C61; 2C61;LATIN SMALL LETTER L WITH DOUBLE BAR;Ll;0;L;;;;;N;;;2C60;;2C60 2C62;LATIN CAPITAL LETTER L WITH MIDDLE TILDE;Lu;0;L;;;;;N;;;;026B; @@ -10795,6 +10877,17 @@ 2E50;CROSS PATTY WITH RIGHT CROSSBAR;So;0;ON;;;;;N;;;;; 2E51;CROSS PATTY WITH LEFT CROSSBAR;So;0;ON;;;;;N;;;;; 2E52;TIRONIAN SIGN CAPITAL ET;Po;0;ON;;;;;N;;;;; +2E53;MEDIEVAL EXCLAMATION MARK;Po;0;ON;;;;;N;;;;; +2E54;MEDIEVAL QUESTION MARK;Po;0;ON;;;;;N;;;;; +2E55;LEFT SQUARE BRACKET WITH STROKE;Ps;0;ON;;;;;Y;;;;; +2E56;RIGHT SQUARE BRACKET WITH STROKE;Pe;0;ON;;;;;Y;;;;; +2E57;LEFT SQUARE BRACKET WITH DOUBLE STROKE;Ps;0;ON;;;;;Y;;;;; +2E58;RIGHT SQUARE BRACKET WITH DOUBLE STROKE;Pe;0;ON;;;;;Y;;;;; +2E59;TOP HALF LEFT PARENTHESIS;Ps;0;ON;;;;;Y;;;;; +2E5A;TOP HALF RIGHT PARENTHESIS;Pe;0;ON;;;;;Y;;;;; +2E5B;BOTTOM HALF LEFT PARENTHESIS;Ps;0;ON;;;;;Y;;;;; +2E5C;BOTTOM HALF RIGHT PARENTHESIS;Pe;0;ON;;;;;Y;;;;; +2E5D;OBLIQUE HYPHEN;Pd;0;ON;;;;;N;;;;; 2E80;CJK RADICAL REPEAT;So;0;ON;;;;;N;;;;; 2E81;CJK RADICAL CLIFF;So;0;ON;;;;;N;;;;; 2E82;CJK RADICAL SECOND ONE;So;0;ON;;;;;N;;;;; @@ -12204,7 +12297,7 @@ 4DFE;HEXAGRAM FOR AFTER COMPLETION;So;0;ON;;;;;N;;;;; 4DFF;HEXAGRAM FOR BEFORE COMPLETION;So;0;ON;;;;;N;;;;; 4E00;;Lo;0;L;;;;;N;;;;; -9FFC;;Lo;0;L;;;;;N;;;;; +9FFF;;Lo;0;L;;;;;N;;;;; A000;YI SYLLABLE IT;Lo;0;L;;;;;N;;;;; A001;YI SYLLABLE IX;Lo;0;L;;;;;N;;;;; A002;YI SYLLABLE I;Lo;0;L;;;;;N;;;;; @@ -14149,6 +14242,8 @@ A7BC;LATIN CAPITAL LETTER GLOTTAL I;Lu;0;L;;;;;N;;;;A7BD; A7BD;LATIN SMALL LETTER GLOTTAL I;Ll;0;L;;;;;N;;;A7BC;;A7BC A7BE;LATIN CAPITAL LETTER GLOTTAL U;Lu;0;L;;;;;N;;;;A7BF; A7BF;LATIN SMALL LETTER GLOTTAL U;Ll;0;L;;;;;N;;;A7BE;;A7BE +A7C0;LATIN CAPITAL LETTER OLD POLISH O;Lu;0;L;;;;;N;;;;A7C1; +A7C1;LATIN SMALL LETTER OLD POLISH O;Ll;0;L;;;;;N;;;A7C0;;A7C0 A7C2;LATIN CAPITAL LETTER ANGLICANA W;Lu;0;L;;;;;N;;;;A7C3; A7C3;LATIN SMALL LETTER ANGLICANA W;Ll;0;L;;;;;N;;;A7C2;;A7C2 A7C4;LATIN CAPITAL LETTER C WITH PALATAL HOOK;Lu;0;L;;;;;N;;;;A794; @@ -14158,6 +14253,17 @@ A7C7;LATIN CAPITAL LETTER D WITH SHORT STROKE OVERLAY;Lu;0;L;;;;;N;;;;A7C8; A7C8;LATIN SMALL LETTER D WITH SHORT STROKE OVERLAY;Ll;0;L;;;;;N;;;A7C7;;A7C7 A7C9;LATIN CAPITAL LETTER S WITH SHORT STROKE OVERLAY;Lu;0;L;;;;;N;;;;A7CA; A7CA;LATIN SMALL LETTER S WITH SHORT STROKE OVERLAY;Ll;0;L;;;;;N;;;A7C9;;A7C9 +A7D0;LATIN CAPITAL LETTER CLOSED INSULAR G;Lu;0;L;;;;;N;;;;A7D1; +A7D1;LATIN SMALL LETTER CLOSED INSULAR G;Ll;0;L;;;;;N;;;A7D0;;A7D0 +A7D3;LATIN SMALL LETTER DOUBLE THORN;Ll;0;L;;;;;N;;;;; +A7D5;LATIN SMALL LETTER DOUBLE WYNN;Ll;0;L;;;;;N;;;;; +A7D6;LATIN CAPITAL LETTER MIDDLE SCOTS S;Lu;0;L;;;;;N;;;;A7D7; +A7D7;LATIN SMALL LETTER MIDDLE SCOTS S;Ll;0;L;;;;;N;;;A7D6;;A7D6 +A7D8;LATIN CAPITAL LETTER SIGMOID S;Lu;0;L;;;;;N;;;;A7D9; +A7D9;LATIN SMALL LETTER SIGMOID S;Ll;0;L;;;;;N;;;A7D8;;A7D8 +A7F2;MODIFIER LETTER CAPITAL C;Lm;0;L; 0043;;;;N;;;;; +A7F3;MODIFIER LETTER CAPITAL F;Lm;0;L; 0046;;;;N;;;;; +A7F4;MODIFIER LETTER CAPITAL Q;Lm;0;L; 0051;;;;N;;;;; A7F5;LATIN CAPITAL LETTER REVERSED HALF H;Lu;0;L;;;;;N;;;;A7F6; A7F6;LATIN SMALL LETTER REVERSED HALF H;Ll;0;L;;;;;N;;;A7F5;;A7F5 A7F7;LATIN EPIGRAPHIC LETTER SIDEWAYS I;Lo;0;L;;;;;N;;;;; @@ -15794,6 +15900,7 @@ FBBE;ARABIC SYMBOL TWO DOTS VERTICALLY BELOW;Sk;0;AL;;;;;N;;;;; FBBF;ARABIC SYMBOL RING;Sk;0;AL;;;;;N;;;;; FBC0;ARABIC SYMBOL SMALL TAH ABOVE;Sk;0;AL;;;;;N;;;;; FBC1;ARABIC SYMBOL SMALL TAH BELOW;Sk;0;AL;;;;;N;;;;; +FBC2;ARABIC SYMBOL WASLA ABOVE;Sk;0;AL;;;;;N;;;;; FBD3;ARABIC LETTER NG ISOLATED FORM;Lo;0;AL; 06AD;;;;N;;;;; FBD4;ARABIC LETTER NG FINAL FORM;Lo;0;AL; 06AD;;;;N;;;;; FBD5;ARABIC LETTER NG INITIAL FORM;Lo;0;AL; 06AD;;;;N;;;;; @@ -16159,6 +16266,22 @@ FD3C;ARABIC LIGATURE ALEF WITH FATHATAN FINAL FORM;Lo;0;AL; 0627 064B;;;; FD3D;ARABIC LIGATURE ALEF WITH FATHATAN ISOLATED FORM;Lo;0;AL; 0627 064B;;;;N;;;;; FD3E;ORNATE LEFT PARENTHESIS;Pe;0;ON;;;;;N;;;;; FD3F;ORNATE RIGHT PARENTHESIS;Ps;0;ON;;;;;N;;;;; +FD40;ARABIC LIGATURE RAHIMAHU ALLAAH;So;0;ON;;;;;N;;;;; +FD41;ARABIC LIGATURE RADI ALLAAHU ANH;So;0;ON;;;;;N;;;;; +FD42;ARABIC LIGATURE RADI ALLAAHU ANHAA;So;0;ON;;;;;N;;;;; +FD43;ARABIC LIGATURE RADI ALLAAHU ANHUM;So;0;ON;;;;;N;;;;; +FD44;ARABIC LIGATURE RADI ALLAAHU ANHUMAA;So;0;ON;;;;;N;;;;; +FD45;ARABIC LIGATURE RADI ALLAAHU ANHUNNA;So;0;ON;;;;;N;;;;; +FD46;ARABIC LIGATURE SALLALLAAHU ALAYHI WA-AALIH;So;0;ON;;;;;N;;;;; +FD47;ARABIC LIGATURE ALAYHI AS-SALAAM;So;0;ON;;;;;N;;;;; +FD48;ARABIC LIGATURE ALAYHIM AS-SALAAM;So;0;ON;;;;;N;;;;; +FD49;ARABIC LIGATURE ALAYHIMAA AS-SALAAM;So;0;ON;;;;;N;;;;; +FD4A;ARABIC LIGATURE ALAYHI AS-SALAATU WAS-SALAAM;So;0;ON;;;;;N;;;;; +FD4B;ARABIC LIGATURE QUDDISA SIRRAH;So;0;ON;;;;;N;;;;; +FD4C;ARABIC LIGATURE SALLALLAHU ALAYHI WAAALIHEE WA-SALLAM;So;0;ON;;;;;N;;;;; +FD4D;ARABIC LIGATURE ALAYHAA AS-SALAAM;So;0;ON;;;;;N;;;;; +FD4E;ARABIC LIGATURE TABAARAKA WA-TAAALAA;So;0;ON;;;;;N;;;;; +FD4F;ARABIC LIGATURE RAHIMAHUM ALLAAH;So;0;ON;;;;;N;;;;; FD50;ARABIC LIGATURE TEH WITH JEEM WITH MEEM INITIAL FORM;Lo;0;AL; 062A 062C 0645;;;;N;;;;; FD51;ARABIC LIGATURE TEH WITH HAH WITH JEEM FINAL FORM;Lo;0;AL; 062A 062D 062C;;;;N;;;;; FD52;ARABIC LIGATURE TEH WITH HAH WITH JEEM INITIAL FORM;Lo;0;AL; 062A 062D 062C;;;;N;;;;; @@ -16277,6 +16400,7 @@ FDC4;ARABIC LIGATURE AIN WITH JEEM WITH MEEM INITIAL FORM;Lo;0;AL; 0639 FDC5;ARABIC LIGATURE SAD WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL; 0635 0645 0645;;;;N;;;;; FDC6;ARABIC LIGATURE SEEN WITH KHAH WITH YEH FINAL FORM;Lo;0;AL; 0633 062E 064A;;;;N;;;;; FDC7;ARABIC LIGATURE NOON WITH JEEM WITH YEH FINAL FORM;Lo;0;AL; 0646 062C 064A;;;;N;;;;; +FDCF;ARABIC LIGATURE SALAAMUHU ALAYNAA;So;0;ON;;;;;N;;;;; FDF0;ARABIC LIGATURE SALLA USED AS KORANIC STOP SIGN ISOLATED FORM;Lo;0;AL; 0635 0644 06D2;;;;N;;;;; FDF1;ARABIC LIGATURE QALA USED AS KORANIC STOP SIGN ISOLATED FORM;Lo;0;AL; 0642 0644 06D2;;;;N;;;;; FDF2;ARABIC LIGATURE ALLAH ISOLATED FORM;Lo;0;AL; 0627 0644 0644 0647;;;;N;;;;; @@ -16291,6 +16415,8 @@ FDFA;ARABIC LIGATURE SALLALLAHOU ALAYHE WASALLAM;Lo;0;AL; 0635 0644 06 FDFB;ARABIC LIGATURE JALLAJALALOUHOU;Lo;0;AL; 062C 0644 0020 062C 0644 0627 0644 0647;;;;N;ARABIC LETTER JALLAJALALOUHOU;;;; FDFC;RIAL SIGN;Sc;0;AL; 0631 06CC 0627 0644;;;;N;;;;; FDFD;ARABIC LIGATURE BISMILLAH AR-RAHMAN AR-RAHEEM;So;0;ON;;;;;N;;;;; +FDFE;ARABIC LIGATURE SUBHAANAHU WA TAAALAA;So;0;ON;;;;;N;;;;; +FDFF;ARABIC LIGATURE AZZA WA JALL;So;0;ON;;;;;N;;;;; FE00;VARIATION SELECTOR-1;Mn;0;NSM;;;;;N;;;;; FE01;VARIATION SELECTOR-2;Mn;0;NSM;;;;;N;;;;; FE02;VARIATION SELECTOR-3;Mn;0;NSM;;;;;N;;;;; @@ -17798,6 +17924,76 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 10562;CAUCASIAN ALBANIAN LETTER PIWR;Lo;0;L;;;;;N;;;;; 10563;CAUCASIAN ALBANIAN LETTER KIW;Lo;0;L;;;;;N;;;;; 1056F;CAUCASIAN ALBANIAN CITATION MARK;Po;0;L;;;;;N;;;;; +10570;VITHKUQI CAPITAL LETTER A;Lu;0;L;;;;;N;;;;10597; +10571;VITHKUQI CAPITAL LETTER BBE;Lu;0;L;;;;;N;;;;10598; +10572;VITHKUQI CAPITAL LETTER BE;Lu;0;L;;;;;N;;;;10599; +10573;VITHKUQI CAPITAL LETTER CE;Lu;0;L;;;;;N;;;;1059A; +10574;VITHKUQI CAPITAL LETTER CHE;Lu;0;L;;;;;N;;;;1059B; +10575;VITHKUQI CAPITAL LETTER DE;Lu;0;L;;;;;N;;;;1059C; +10576;VITHKUQI CAPITAL LETTER DHE;Lu;0;L;;;;;N;;;;1059D; +10577;VITHKUQI CAPITAL LETTER EI;Lu;0;L;;;;;N;;;;1059E; +10578;VITHKUQI CAPITAL LETTER E;Lu;0;L;;;;;N;;;;1059F; +10579;VITHKUQI CAPITAL LETTER FE;Lu;0;L;;;;;N;;;;105A0; +1057A;VITHKUQI CAPITAL LETTER GA;Lu;0;L;;;;;N;;;;105A1; +1057C;VITHKUQI CAPITAL LETTER HA;Lu;0;L;;;;;N;;;;105A3; +1057D;VITHKUQI CAPITAL LETTER HHA;Lu;0;L;;;;;N;;;;105A4; +1057E;VITHKUQI CAPITAL LETTER I;Lu;0;L;;;;;N;;;;105A5; +1057F;VITHKUQI CAPITAL LETTER IJE;Lu;0;L;;;;;N;;;;105A6; +10580;VITHKUQI CAPITAL LETTER JE;Lu;0;L;;;;;N;;;;105A7; +10581;VITHKUQI CAPITAL LETTER KA;Lu;0;L;;;;;N;;;;105A8; +10582;VITHKUQI CAPITAL LETTER LA;Lu;0;L;;;;;N;;;;105A9; +10583;VITHKUQI CAPITAL LETTER LLA;Lu;0;L;;;;;N;;;;105AA; +10584;VITHKUQI CAPITAL LETTER ME;Lu;0;L;;;;;N;;;;105AB; +10585;VITHKUQI CAPITAL LETTER NE;Lu;0;L;;;;;N;;;;105AC; +10586;VITHKUQI CAPITAL LETTER NJE;Lu;0;L;;;;;N;;;;105AD; +10587;VITHKUQI CAPITAL LETTER O;Lu;0;L;;;;;N;;;;105AE; +10588;VITHKUQI CAPITAL LETTER PE;Lu;0;L;;;;;N;;;;105AF; +10589;VITHKUQI CAPITAL LETTER QA;Lu;0;L;;;;;N;;;;105B0; +1058A;VITHKUQI CAPITAL LETTER RE;Lu;0;L;;;;;N;;;;105B1; +1058C;VITHKUQI CAPITAL LETTER SE;Lu;0;L;;;;;N;;;;105B3; +1058D;VITHKUQI CAPITAL LETTER SHE;Lu;0;L;;;;;N;;;;105B4; +1058E;VITHKUQI CAPITAL LETTER TE;Lu;0;L;;;;;N;;;;105B5; +1058F;VITHKUQI CAPITAL LETTER THE;Lu;0;L;;;;;N;;;;105B6; +10590;VITHKUQI CAPITAL LETTER U;Lu;0;L;;;;;N;;;;105B7; +10591;VITHKUQI CAPITAL LETTER VE;Lu;0;L;;;;;N;;;;105B8; +10592;VITHKUQI CAPITAL LETTER XE;Lu;0;L;;;;;N;;;;105B9; +10594;VITHKUQI CAPITAL LETTER Y;Lu;0;L;;;;;N;;;;105BB; +10595;VITHKUQI CAPITAL LETTER ZE;Lu;0;L;;;;;N;;;;105BC; +10597;VITHKUQI SMALL LETTER A;Ll;0;L;;;;;N;;;10570;;10570 +10598;VITHKUQI SMALL LETTER BBE;Ll;0;L;;;;;N;;;10571;;10571 +10599;VITHKUQI SMALL LETTER BE;Ll;0;L;;;;;N;;;10572;;10572 +1059A;VITHKUQI SMALL LETTER CE;Ll;0;L;;;;;N;;;10573;;10573 +1059B;VITHKUQI SMALL LETTER CHE;Ll;0;L;;;;;N;;;10574;;10574 +1059C;VITHKUQI SMALL LETTER DE;Ll;0;L;;;;;N;;;10575;;10575 +1059D;VITHKUQI SMALL LETTER DHE;Ll;0;L;;;;;N;;;10576;;10576 +1059E;VITHKUQI SMALL LETTER EI;Ll;0;L;;;;;N;;;10577;;10577 +1059F;VITHKUQI SMALL LETTER E;Ll;0;L;;;;;N;;;10578;;10578 +105A0;VITHKUQI SMALL LETTER FE;Ll;0;L;;;;;N;;;10579;;10579 +105A1;VITHKUQI SMALL LETTER GA;Ll;0;L;;;;;N;;;1057A;;1057A +105A3;VITHKUQI SMALL LETTER HA;Ll;0;L;;;;;N;;;1057C;;1057C +105A4;VITHKUQI SMALL LETTER HHA;Ll;0;L;;;;;N;;;1057D;;1057D +105A5;VITHKUQI SMALL LETTER I;Ll;0;L;;;;;N;;;1057E;;1057E +105A6;VITHKUQI SMALL LETTER IJE;Ll;0;L;;;;;N;;;1057F;;1057F +105A7;VITHKUQI SMALL LETTER JE;Ll;0;L;;;;;N;;;10580;;10580 +105A8;VITHKUQI SMALL LETTER KA;Ll;0;L;;;;;N;;;10581;;10581 +105A9;VITHKUQI SMALL LETTER LA;Ll;0;L;;;;;N;;;10582;;10582 +105AA;VITHKUQI SMALL LETTER LLA;Ll;0;L;;;;;N;;;10583;;10583 +105AB;VITHKUQI SMALL LETTER ME;Ll;0;L;;;;;N;;;10584;;10584 +105AC;VITHKUQI SMALL LETTER NE;Ll;0;L;;;;;N;;;10585;;10585 +105AD;VITHKUQI SMALL LETTER NJE;Ll;0;L;;;;;N;;;10586;;10586 +105AE;VITHKUQI SMALL LETTER O;Ll;0;L;;;;;N;;;10587;;10587 +105AF;VITHKUQI SMALL LETTER PE;Ll;0;L;;;;;N;;;10588;;10588 +105B0;VITHKUQI SMALL LETTER QA;Ll;0;L;;;;;N;;;10589;;10589 +105B1;VITHKUQI SMALL LETTER RE;Ll;0;L;;;;;N;;;1058A;;1058A +105B3;VITHKUQI SMALL LETTER SE;Ll;0;L;;;;;N;;;1058C;;1058C +105B4;VITHKUQI SMALL LETTER SHE;Ll;0;L;;;;;N;;;1058D;;1058D +105B5;VITHKUQI SMALL LETTER TE;Ll;0;L;;;;;N;;;1058E;;1058E +105B6;VITHKUQI SMALL LETTER THE;Ll;0;L;;;;;N;;;1058F;;1058F +105B7;VITHKUQI SMALL LETTER U;Ll;0;L;;;;;N;;;10590;;10590 +105B8;VITHKUQI SMALL LETTER VE;Ll;0;L;;;;;N;;;10591;;10591 +105B9;VITHKUQI SMALL LETTER XE;Ll;0;L;;;;;N;;;10592;;10592 +105BB;VITHKUQI SMALL LETTER Y;Ll;0;L;;;;;N;;;10594;;10594 +105BC;VITHKUQI SMALL LETTER ZE;Ll;0;L;;;;;N;;;10595;;10595 10600;LINEAR A SIGN AB001;Lo;0;L;;;;;N;;;;; 10601;LINEAR A SIGN AB002;Lo;0;L;;;;;N;;;;; 10602;LINEAR A SIGN AB003;Lo;0;L;;;;;N;;;;; @@ -18139,6 +18335,63 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 10765;LINEAR A SIGN A805;Lo;0;L;;;;;N;;;;; 10766;LINEAR A SIGN A806;Lo;0;L;;;;;N;;;;; 10767;LINEAR A SIGN A807;Lo;0;L;;;;;N;;;;; +10780;MODIFIER LETTER SMALL CAPITAL AA;Lm;0;L;;;;;N;;;;; +10781;MODIFIER LETTER SUPERSCRIPT TRIANGULAR COLON;Lm;0;L; 02D0;;;;N;;;;; +10782;MODIFIER LETTER SUPERSCRIPT HALF TRIANGULAR COLON;Lm;0;L; 02D1;;;;N;;;;; +10783;MODIFIER LETTER SMALL AE;Lm;0;L; 00E6;;;;N;;;;; +10784;MODIFIER LETTER SMALL CAPITAL B;Lm;0;L; 0299;;;;N;;;;; +10785;MODIFIER LETTER SMALL B WITH HOOK;Lm;0;L; 0253;;;;N;;;;; +10787;MODIFIER LETTER SMALL DZ DIGRAPH;Lm;0;L; 02A3;;;;N;;;;; +10788;MODIFIER LETTER SMALL DZ DIGRAPH WITH RETROFLEX HOOK;Lm;0;L; AB66;;;;N;;;;; +10789;MODIFIER LETTER SMALL DZ DIGRAPH WITH CURL;Lm;0;L; 02A5;;;;N;;;;; +1078A;MODIFIER LETTER SMALL DEZH DIGRAPH;Lm;0;L; 02A4;;;;N;;;;; +1078B;MODIFIER LETTER SMALL D WITH TAIL;Lm;0;L; 0256;;;;N;;;;; +1078C;MODIFIER LETTER SMALL D WITH HOOK;Lm;0;L; 0257;;;;N;;;;; +1078D;MODIFIER LETTER SMALL D WITH HOOK AND TAIL;Lm;0;L; 1D91;;;;N;;;;; +1078E;MODIFIER LETTER SMALL REVERSED E;Lm;0;L; 0258;;;;N;;;;; +1078F;MODIFIER LETTER SMALL CLOSED REVERSED OPEN E;Lm;0;L; 025E;;;;N;;;;; +10790;MODIFIER LETTER SMALL FENG DIGRAPH;Lm;0;L; 02A9;;;;N;;;;; +10791;MODIFIER LETTER SMALL RAMS HORN;Lm;0;L; 0264;;;;N;;;;; +10792;MODIFIER LETTER SMALL CAPITAL G;Lm;0;L; 0262;;;;N;;;;; +10793;MODIFIER LETTER SMALL G WITH HOOK;Lm;0;L; 0260;;;;N;;;;; +10794;MODIFIER LETTER SMALL CAPITAL G WITH HOOK;Lm;0;L; 029B;;;;N;;;;; +10795;MODIFIER LETTER SMALL H WITH STROKE;Lm;0;L; 0127;;;;N;;;;; +10796;MODIFIER LETTER SMALL CAPITAL H;Lm;0;L; 029C;;;;N;;;;; +10797;MODIFIER LETTER SMALL HENG WITH HOOK;Lm;0;L; 0267;;;;N;;;;; +10798;MODIFIER LETTER SMALL DOTLESS J WITH STROKE AND HOOK;Lm;0;L; 0284;;;;N;;;;; +10799;MODIFIER LETTER SMALL LS DIGRAPH;Lm;0;L; 02AA;;;;N;;;;; +1079A;MODIFIER LETTER SMALL LZ DIGRAPH;Lm;0;L; 02AB;;;;N;;;;; +1079B;MODIFIER LETTER SMALL L WITH BELT;Lm;0;L; 026C;;;;N;;;;; +1079C;MODIFIER LETTER SMALL CAPITAL L WITH BELT;Lm;0;L; 1DF04;;;;N;;;;; +1079D;MODIFIER LETTER SMALL L WITH RETROFLEX HOOK AND BELT;Lm;0;L; A78E;;;;N;;;;; +1079E;MODIFIER LETTER SMALL LEZH;Lm;0;L; 026E;;;;N;;;;; +1079F;MODIFIER LETTER SMALL LEZH WITH RETROFLEX HOOK;Lm;0;L; 1DF05;;;;N;;;;; +107A0;MODIFIER LETTER SMALL TURNED Y;Lm;0;L; 028E;;;;N;;;;; +107A1;MODIFIER LETTER SMALL TURNED Y WITH BELT;Lm;0;L; 1DF06;;;;N;;;;; +107A2;MODIFIER LETTER SMALL O WITH STROKE;Lm;0;L; 00F8;;;;N;;;;; +107A3;MODIFIER LETTER SMALL CAPITAL OE;Lm;0;L; 0276;;;;N;;;;; +107A4;MODIFIER LETTER SMALL CLOSED OMEGA;Lm;0;L; 0277;;;;N;;;;; +107A5;MODIFIER LETTER SMALL Q;Lm;0;L; 0071;;;;N;;;;; +107A6;MODIFIER LETTER SMALL TURNED R WITH LONG LEG;Lm;0;L; 027A;;;;N;;;;; +107A7;MODIFIER LETTER SMALL TURNED R WITH LONG LEG AND RETROFLEX HOOK;Lm;0;L; 1DF08;;;;N;;;;; +107A8;MODIFIER LETTER SMALL R WITH TAIL;Lm;0;L; 027D;;;;N;;;;; +107A9;MODIFIER LETTER SMALL R WITH FISHHOOK;Lm;0;L; 027E;;;;N;;;;; +107AA;MODIFIER LETTER SMALL CAPITAL R;Lm;0;L; 0280;;;;N;;;;; +107AB;MODIFIER LETTER SMALL TC DIGRAPH WITH CURL;Lm;0;L; 02A8;;;;N;;;;; +107AC;MODIFIER LETTER SMALL TS DIGRAPH;Lm;0;L; 02A6;;;;N;;;;; +107AD;MODIFIER LETTER SMALL TS DIGRAPH WITH RETROFLEX HOOK;Lm;0;L; AB67;;;;N;;;;; +107AE;MODIFIER LETTER SMALL TESH DIGRAPH;Lm;0;L; 02A7;;;;N;;;;; +107AF;MODIFIER LETTER SMALL T WITH RETROFLEX HOOK;Lm;0;L; 0288;;;;N;;;;; +107B0;MODIFIER LETTER SMALL V WITH RIGHT HOOK;Lm;0;L; 2C71;;;;N;;;;; +107B2;MODIFIER LETTER SMALL CAPITAL Y;Lm;0;L; 028F;;;;N;;;;; +107B3;MODIFIER LETTER GLOTTAL STOP WITH STROKE;Lm;0;L; 02A1;;;;N;;;;; +107B4;MODIFIER LETTER REVERSED GLOTTAL STOP WITH STROKE;Lm;0;L; 02A2;;;;N;;;;; +107B5;MODIFIER LETTER BILABIAL CLICK;Lm;0;L; 0298;;;;N;;;;; +107B6;MODIFIER LETTER DENTAL CLICK;Lm;0;L; 01C0;;;;N;;;;; +107B7;MODIFIER LETTER LATERAL CLICK;Lm;0;L; 01C1;;;;N;;;;; +107B8;MODIFIER LETTER ALVEOLAR CLICK;Lm;0;L; 01C2;;;;N;;;;; +107B9;MODIFIER LETTER RETROFLEX CLICK WITH RETROFLEX HOOK;Lm;0;L; 1DF0A;;;;N;;;;; +107BA;MODIFIER LETTER SMALL S WITH CURL;Lm;0;L; 1DF1E;;;;N;;;;; 10800;CYPRIOT SYLLABLE A;Lo;0;R;;;;;N;;;;; 10801;CYPRIOT SYLLABLE E;Lo;0;R;;;;;N;;;;; 10802;CYPRIOT SYLLABLE I;Lo;0;R;;;;;N;;;;; @@ -19222,6 +19475,32 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 10F57;SOGDIAN PUNCTUATION CIRCLE WITH DOT;Po;0;AL;;;;;N;;;;; 10F58;SOGDIAN PUNCTUATION TWO CIRCLES WITH DOTS;Po;0;AL;;;;;N;;;;; 10F59;SOGDIAN PUNCTUATION HALF CIRCLE WITH DOT;Po;0;AL;;;;;N;;;;; +10F70;OLD UYGHUR LETTER ALEPH;Lo;0;R;;;;;N;;;;; +10F71;OLD UYGHUR LETTER BETH;Lo;0;R;;;;;N;;;;; +10F72;OLD UYGHUR LETTER GIMEL-HETH;Lo;0;R;;;;;N;;;;; +10F73;OLD UYGHUR LETTER WAW;Lo;0;R;;;;;N;;;;; +10F74;OLD UYGHUR LETTER ZAYIN;Lo;0;R;;;;;N;;;;; +10F75;OLD UYGHUR LETTER FINAL HETH;Lo;0;R;;;;;N;;;;; +10F76;OLD UYGHUR LETTER YODH;Lo;0;R;;;;;N;;;;; +10F77;OLD UYGHUR LETTER KAPH;Lo;0;R;;;;;N;;;;; +10F78;OLD UYGHUR LETTER LAMEDH;Lo;0;R;;;;;N;;;;; +10F79;OLD UYGHUR LETTER MEM;Lo;0;R;;;;;N;;;;; +10F7A;OLD UYGHUR LETTER NUN;Lo;0;R;;;;;N;;;;; +10F7B;OLD UYGHUR LETTER SAMEKH;Lo;0;R;;;;;N;;;;; +10F7C;OLD UYGHUR LETTER PE;Lo;0;R;;;;;N;;;;; +10F7D;OLD UYGHUR LETTER SADHE;Lo;0;R;;;;;N;;;;; +10F7E;OLD UYGHUR LETTER RESH;Lo;0;R;;;;;N;;;;; +10F7F;OLD UYGHUR LETTER SHIN;Lo;0;R;;;;;N;;;;; +10F80;OLD UYGHUR LETTER TAW;Lo;0;R;;;;;N;;;;; +10F81;OLD UYGHUR LETTER LESH;Lo;0;R;;;;;N;;;;; +10F82;OLD UYGHUR COMBINING DOT ABOVE;Mn;230;NSM;;;;;N;;;;; +10F83;OLD UYGHUR COMBINING DOT BELOW;Mn;220;NSM;;;;;N;;;;; +10F84;OLD UYGHUR COMBINING TWO DOTS ABOVE;Mn;230;NSM;;;;;N;;;;; +10F85;OLD UYGHUR COMBINING TWO DOTS BELOW;Mn;220;NSM;;;;;N;;;;; +10F86;OLD UYGHUR PUNCTUATION BAR;Po;0;R;;;;;N;;;;; +10F87;OLD UYGHUR PUNCTUATION TWO BARS;Po;0;R;;;;;N;;;;; +10F88;OLD UYGHUR PUNCTUATION TWO DOTS;Po;0;R;;;;;N;;;;; +10F89;OLD UYGHUR PUNCTUATION FOUR DOTS;Po;0;R;;;;;N;;;;; 10FB0;CHORASMIAN LETTER ALEPH;Lo;0;R;;;;;N;;;;; 10FB1;CHORASMIAN LETTER SMALL ALEPH;Lo;0;R;;;;;N;;;;; 10FB2;CHORASMIAN LETTER BETH;Lo;0;R;;;;;N;;;;; @@ -19381,6 +19660,12 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1106D;BRAHMI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 1106E;BRAHMI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 1106F;BRAHMI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +11070;BRAHMI SIGN OLD TAMIL VIRAMA;Mn;9;NSM;;;;;N;;;;; +11071;BRAHMI LETTER OLD TAMIL SHORT E;Lo;0;L;;;;;N;;;;; +11072;BRAHMI LETTER OLD TAMIL SHORT O;Lo;0;L;;;;;N;;;;; +11073;BRAHMI VOWEL SIGN OLD TAMIL SHORT E;Mn;0;NSM;;;;;N;;;;; +11074;BRAHMI VOWEL SIGN OLD TAMIL SHORT O;Mn;0;NSM;;;;;N;;;;; +11075;BRAHMI LETTER OLD TAMIL LLA;Lo;0;L;;;;;N;;;;; 1107F;BRAHMI NUMBER JOINER;Mn;9;NSM;;;;;N;;;;; 11080;KAITHI SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; 11081;KAITHI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; @@ -19448,6 +19733,7 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 110BF;KAITHI DOUBLE SECTION MARK;Po;0;L;;;;;N;;;;; 110C0;KAITHI DANDA;Po;0;L;;;;;N;;;;; 110C1;KAITHI DOUBLE DANDA;Po;0;L;;;;;N;;;;; +110C2;KAITHI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; 110CD;KAITHI NUMBER SIGN ABOVE;Cf;0;L;;;;;N;;;;; 110D0;SORA SOMPENG LETTER SAH;Lo;0;L;;;;;N;;;;; 110D1;SORA SOMPENG LETTER TAH;Lo;0;L;;;;;N;;;;; @@ -20385,6 +20671,7 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 116B6;TAKRI SIGN VIRAMA;Mc;9;L;;;;;N;;;;; 116B7;TAKRI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; 116B8;TAKRI LETTER ARCHAIC KHA;Lo;0;L;;;;;N;;;;; +116B9;TAKRI ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; 116C0;TAKRI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 116C1;TAKRI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 116C2;TAKRI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; @@ -20453,6 +20740,13 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1173D;AHOM SIGN SECTION;Po;0;L;;;;;N;;;;; 1173E;AHOM SIGN RULAI;Po;0;L;;;;;N;;;;; 1173F;AHOM SYMBOL VI;So;0;L;;;;;N;;;;; +11740;AHOM LETTER CA;Lo;0;L;;;;;N;;;;; +11741;AHOM LETTER TTA;Lo;0;L;;;;;N;;;;; +11742;AHOM LETTER TTHA;Lo;0;L;;;;;N;;;;; +11743;AHOM LETTER DDA;Lo;0;L;;;;;N;;;;; +11744;AHOM LETTER DDHA;Lo;0;L;;;;;N;;;;; +11745;AHOM LETTER NNA;Lo;0;L;;;;;N;;;;; +11746;AHOM LETTER LLA;Lo;0;L;;;;;N;;;;; 11800;DOGRA LETTER A;Lo;0;L;;;;;N;;;;; 11801;DOGRA LETTER AA;Lo;0;L;;;;;N;;;;; 11802;DOGRA LETTER I;Lo;0;L;;;;;N;;;;; @@ -20889,6 +21183,22 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 11AA0;SOYOMBO HEAD MARK WITH MOON AND SUN;Po;0;L;;;;;N;;;;; 11AA1;SOYOMBO TERMINAL MARK-1;Po;0;L;;;;;N;;;;; 11AA2;SOYOMBO TERMINAL MARK-2;Po;0;L;;;;;N;;;;; +11AB0;CANADIAN SYLLABICS NATTILIK HI;Lo;0;L;;;;;N;;;;; +11AB1;CANADIAN SYLLABICS NATTILIK HII;Lo;0;L;;;;;N;;;;; +11AB2;CANADIAN SYLLABICS NATTILIK HO;Lo;0;L;;;;;N;;;;; +11AB3;CANADIAN SYLLABICS NATTILIK HOO;Lo;0;L;;;;;N;;;;; +11AB4;CANADIAN SYLLABICS NATTILIK HA;Lo;0;L;;;;;N;;;;; +11AB5;CANADIAN SYLLABICS NATTILIK HAA;Lo;0;L;;;;;N;;;;; +11AB6;CANADIAN SYLLABICS NATTILIK SHRI;Lo;0;L;;;;;N;;;;; +11AB7;CANADIAN SYLLABICS NATTILIK SHRII;Lo;0;L;;;;;N;;;;; +11AB8;CANADIAN SYLLABICS NATTILIK SHRO;Lo;0;L;;;;;N;;;;; +11AB9;CANADIAN SYLLABICS NATTILIK SHROO;Lo;0;L;;;;;N;;;;; +11ABA;CANADIAN SYLLABICS NATTILIK SHRA;Lo;0;L;;;;;N;;;;; +11ABB;CANADIAN SYLLABICS NATTILIK SHRAA;Lo;0;L;;;;;N;;;;; +11ABC;CANADIAN SYLLABICS SPE;Lo;0;L;;;;;N;;;;; +11ABD;CANADIAN SYLLABICS SPI;Lo;0;L;;;;;N;;;;; +11ABE;CANADIAN SYLLABICS SPO;Lo;0;L;;;;;N;;;;; +11ABF;CANADIAN SYLLABICS SPA;Lo;0;L;;;;;N;;;;; 11AC0;PAU CIN HAU LETTER PA;Lo;0;L;;;;;N;;;;; 11AC1;PAU CIN HAU LETTER KA;Lo;0;L;;;;;N;;;;; 11AC2;PAU CIN HAU LETTER LA;Lo;0;L;;;;;N;;;;; @@ -22560,6 +22870,105 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 12541;CUNEIFORM SIGN ZA7;Lo;0;L;;;;;N;;;;; 12542;CUNEIFORM SIGN ZU OVER ZU PLUS SAR;Lo;0;L;;;;;N;;;;; 12543;CUNEIFORM SIGN ZU5 TIMES THREE DISH TENU;Lo;0;L;;;;;N;;;;; +12F90;CYPRO-MINOAN SIGN CM001;Lo;0;L;;;;;N;;;;; +12F91;CYPRO-MINOAN SIGN CM002;Lo;0;L;;;;;N;;;;; +12F92;CYPRO-MINOAN SIGN CM004;Lo;0;L;;;;;N;;;;; +12F93;CYPRO-MINOAN SIGN CM005;Lo;0;L;;;;;N;;;;; +12F94;CYPRO-MINOAN SIGN CM006;Lo;0;L;;;;;N;;;;; +12F95;CYPRO-MINOAN SIGN CM007;Lo;0;L;;;;;N;;;;; +12F96;CYPRO-MINOAN SIGN CM008;Lo;0;L;;;;;N;;;;; +12F97;CYPRO-MINOAN SIGN CM009;Lo;0;L;;;;;N;;;;; +12F98;CYPRO-MINOAN SIGN CM010;Lo;0;L;;;;;N;;;;; +12F99;CYPRO-MINOAN SIGN CM011;Lo;0;L;;;;;N;;;;; +12F9A;CYPRO-MINOAN SIGN CM012;Lo;0;L;;;;;N;;;;; +12F9B;CYPRO-MINOAN SIGN CM012B;Lo;0;L;;;;;N;;;;; +12F9C;CYPRO-MINOAN SIGN CM013;Lo;0;L;;;;;N;;;;; +12F9D;CYPRO-MINOAN SIGN CM015;Lo;0;L;;;;;N;;;;; +12F9E;CYPRO-MINOAN SIGN CM017;Lo;0;L;;;;;N;;;;; +12F9F;CYPRO-MINOAN SIGN CM019;Lo;0;L;;;;;N;;;;; +12FA0;CYPRO-MINOAN SIGN CM021;Lo;0;L;;;;;N;;;;; +12FA1;CYPRO-MINOAN SIGN CM023;Lo;0;L;;;;;N;;;;; +12FA2;CYPRO-MINOAN SIGN CM024;Lo;0;L;;;;;N;;;;; +12FA3;CYPRO-MINOAN SIGN CM025;Lo;0;L;;;;;N;;;;; +12FA4;CYPRO-MINOAN SIGN CM026;Lo;0;L;;;;;N;;;;; +12FA5;CYPRO-MINOAN SIGN CM027;Lo;0;L;;;;;N;;;;; +12FA6;CYPRO-MINOAN SIGN CM028;Lo;0;L;;;;;N;;;;; +12FA7;CYPRO-MINOAN SIGN CM029;Lo;0;L;;;;;N;;;;; +12FA8;CYPRO-MINOAN SIGN CM030;Lo;0;L;;;;;N;;;;; +12FA9;CYPRO-MINOAN SIGN CM033;Lo;0;L;;;;;N;;;;; +12FAA;CYPRO-MINOAN SIGN CM034;Lo;0;L;;;;;N;;;;; +12FAB;CYPRO-MINOAN SIGN CM035;Lo;0;L;;;;;N;;;;; +12FAC;CYPRO-MINOAN SIGN CM036;Lo;0;L;;;;;N;;;;; +12FAD;CYPRO-MINOAN SIGN CM037;Lo;0;L;;;;;N;;;;; +12FAE;CYPRO-MINOAN SIGN CM038;Lo;0;L;;;;;N;;;;; +12FAF;CYPRO-MINOAN SIGN CM039;Lo;0;L;;;;;N;;;;; +12FB0;CYPRO-MINOAN SIGN CM040;Lo;0;L;;;;;N;;;;; +12FB1;CYPRO-MINOAN SIGN CM041;Lo;0;L;;;;;N;;;;; +12FB2;CYPRO-MINOAN SIGN CM044;Lo;0;L;;;;;N;;;;; +12FB3;CYPRO-MINOAN SIGN CM046;Lo;0;L;;;;;N;;;;; +12FB4;CYPRO-MINOAN SIGN CM047;Lo;0;L;;;;;N;;;;; +12FB5;CYPRO-MINOAN SIGN CM049;Lo;0;L;;;;;N;;;;; +12FB6;CYPRO-MINOAN SIGN CM050;Lo;0;L;;;;;N;;;;; +12FB7;CYPRO-MINOAN SIGN CM051;Lo;0;L;;;;;N;;;;; +12FB8;CYPRO-MINOAN SIGN CM052;Lo;0;L;;;;;N;;;;; +12FB9;CYPRO-MINOAN SIGN CM053;Lo;0;L;;;;;N;;;;; +12FBA;CYPRO-MINOAN SIGN CM054;Lo;0;L;;;;;N;;;;; +12FBB;CYPRO-MINOAN SIGN CM055;Lo;0;L;;;;;N;;;;; +12FBC;CYPRO-MINOAN SIGN CM056;Lo;0;L;;;;;N;;;;; +12FBD;CYPRO-MINOAN SIGN CM058;Lo;0;L;;;;;N;;;;; +12FBE;CYPRO-MINOAN SIGN CM059;Lo;0;L;;;;;N;;;;; +12FBF;CYPRO-MINOAN SIGN CM060;Lo;0;L;;;;;N;;;;; +12FC0;CYPRO-MINOAN SIGN CM061;Lo;0;L;;;;;N;;;;; +12FC1;CYPRO-MINOAN SIGN CM062;Lo;0;L;;;;;N;;;;; +12FC2;CYPRO-MINOAN SIGN CM063;Lo;0;L;;;;;N;;;;; +12FC3;CYPRO-MINOAN SIGN CM064;Lo;0;L;;;;;N;;;;; +12FC4;CYPRO-MINOAN SIGN CM066;Lo;0;L;;;;;N;;;;; +12FC5;CYPRO-MINOAN SIGN CM067;Lo;0;L;;;;;N;;;;; +12FC6;CYPRO-MINOAN SIGN CM068;Lo;0;L;;;;;N;;;;; +12FC7;CYPRO-MINOAN SIGN CM069;Lo;0;L;;;;;N;;;;; +12FC8;CYPRO-MINOAN SIGN CM070;Lo;0;L;;;;;N;;;;; +12FC9;CYPRO-MINOAN SIGN CM071;Lo;0;L;;;;;N;;;;; +12FCA;CYPRO-MINOAN SIGN CM072;Lo;0;L;;;;;N;;;;; +12FCB;CYPRO-MINOAN SIGN CM073;Lo;0;L;;;;;N;;;;; +12FCC;CYPRO-MINOAN SIGN CM074;Lo;0;L;;;;;N;;;;; +12FCD;CYPRO-MINOAN SIGN CM075;Lo;0;L;;;;;N;;;;; +12FCE;CYPRO-MINOAN SIGN CM075B;Lo;0;L;;;;;N;;;;; +12FCF;CYPRO-MINOAN SIGN CM076;Lo;0;L;;;;;N;;;;; +12FD0;CYPRO-MINOAN SIGN CM078;Lo;0;L;;;;;N;;;;; +12FD1;CYPRO-MINOAN SIGN CM079;Lo;0;L;;;;;N;;;;; +12FD2;CYPRO-MINOAN SIGN CM080;Lo;0;L;;;;;N;;;;; +12FD3;CYPRO-MINOAN SIGN CM081;Lo;0;L;;;;;N;;;;; +12FD4;CYPRO-MINOAN SIGN CM082;Lo;0;L;;;;;N;;;;; +12FD5;CYPRO-MINOAN SIGN CM083;Lo;0;L;;;;;N;;;;; +12FD6;CYPRO-MINOAN SIGN CM084;Lo;0;L;;;;;N;;;;; +12FD7;CYPRO-MINOAN SIGN CM085;Lo;0;L;;;;;N;;;;; +12FD8;CYPRO-MINOAN SIGN CM086;Lo;0;L;;;;;N;;;;; +12FD9;CYPRO-MINOAN SIGN CM087;Lo;0;L;;;;;N;;;;; +12FDA;CYPRO-MINOAN SIGN CM088;Lo;0;L;;;;;N;;;;; +12FDB;CYPRO-MINOAN SIGN CM089;Lo;0;L;;;;;N;;;;; +12FDC;CYPRO-MINOAN SIGN CM090;Lo;0;L;;;;;N;;;;; +12FDD;CYPRO-MINOAN SIGN CM091;Lo;0;L;;;;;N;;;;; +12FDE;CYPRO-MINOAN SIGN CM092;Lo;0;L;;;;;N;;;;; +12FDF;CYPRO-MINOAN SIGN CM094;Lo;0;L;;;;;N;;;;; +12FE0;CYPRO-MINOAN SIGN CM095;Lo;0;L;;;;;N;;;;; +12FE1;CYPRO-MINOAN SIGN CM096;Lo;0;L;;;;;N;;;;; +12FE2;CYPRO-MINOAN SIGN CM097;Lo;0;L;;;;;N;;;;; +12FE3;CYPRO-MINOAN SIGN CM098;Lo;0;L;;;;;N;;;;; +12FE4;CYPRO-MINOAN SIGN CM099;Lo;0;L;;;;;N;;;;; +12FE5;CYPRO-MINOAN SIGN CM100;Lo;0;L;;;;;N;;;;; +12FE6;CYPRO-MINOAN SIGN CM101;Lo;0;L;;;;;N;;;;; +12FE7;CYPRO-MINOAN SIGN CM102;Lo;0;L;;;;;N;;;;; +12FE8;CYPRO-MINOAN SIGN CM103;Lo;0;L;;;;;N;;;;; +12FE9;CYPRO-MINOAN SIGN CM104;Lo;0;L;;;;;N;;;;; +12FEA;CYPRO-MINOAN SIGN CM105;Lo;0;L;;;;;N;;;;; +12FEB;CYPRO-MINOAN SIGN CM107;Lo;0;L;;;;;N;;;;; +12FEC;CYPRO-MINOAN SIGN CM108;Lo;0;L;;;;;N;;;;; +12FED;CYPRO-MINOAN SIGN CM109;Lo;0;L;;;;;N;;;;; +12FEE;CYPRO-MINOAN SIGN CM110;Lo;0;L;;;;;N;;;;; +12FEF;CYPRO-MINOAN SIGN CM112;Lo;0;L;;;;;N;;;;; +12FF0;CYPRO-MINOAN SIGN CM114;Lo;0;L;;;;;N;;;;; +12FF1;CYPRO-MINOAN SIGN CM301;Po;0;L;;;;;N;;;;; +12FF2;CYPRO-MINOAN SIGN CM302;Po;0;L;;;;;N;;;;; 13000;EGYPTIAN HIEROGLYPH A001;Lo;0;L;;;;;N;;;;; 13001;EGYPTIAN HIEROGLYPH A002;Lo;0;L;;;;;N;;;;; 13002;EGYPTIAN HIEROGLYPH A003;Lo;0;L;;;;;N;;;;; @@ -24835,6 +25244,95 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 16A69;MRO DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 16A6E;MRO DANDA;Po;0;L;;;;;N;;;;; 16A6F;MRO DOUBLE DANDA;Po;0;L;;;;;N;;;;; +16A70;TANGSA LETTER OZ;Lo;0;L;;;;;N;;;;; +16A71;TANGSA LETTER OC;Lo;0;L;;;;;N;;;;; +16A72;TANGSA LETTER OQ;Lo;0;L;;;;;N;;;;; +16A73;TANGSA LETTER OX;Lo;0;L;;;;;N;;;;; +16A74;TANGSA LETTER AZ;Lo;0;L;;;;;N;;;;; +16A75;TANGSA LETTER AC;Lo;0;L;;;;;N;;;;; +16A76;TANGSA LETTER AQ;Lo;0;L;;;;;N;;;;; +16A77;TANGSA LETTER AX;Lo;0;L;;;;;N;;;;; +16A78;TANGSA LETTER VZ;Lo;0;L;;;;;N;;;;; +16A79;TANGSA LETTER VC;Lo;0;L;;;;;N;;;;; +16A7A;TANGSA LETTER VQ;Lo;0;L;;;;;N;;;;; +16A7B;TANGSA LETTER VX;Lo;0;L;;;;;N;;;;; +16A7C;TANGSA LETTER EZ;Lo;0;L;;;;;N;;;;; +16A7D;TANGSA LETTER EC;Lo;0;L;;;;;N;;;;; +16A7E;TANGSA LETTER EQ;Lo;0;L;;;;;N;;;;; +16A7F;TANGSA LETTER EX;Lo;0;L;;;;;N;;;;; +16A80;TANGSA LETTER IZ;Lo;0;L;;;;;N;;;;; +16A81;TANGSA LETTER IC;Lo;0;L;;;;;N;;;;; +16A82;TANGSA LETTER IQ;Lo;0;L;;;;;N;;;;; +16A83;TANGSA LETTER IX;Lo;0;L;;;;;N;;;;; +16A84;TANGSA LETTER UZ;Lo;0;L;;;;;N;;;;; +16A85;TANGSA LETTER UC;Lo;0;L;;;;;N;;;;; +16A86;TANGSA LETTER UQ;Lo;0;L;;;;;N;;;;; +16A87;TANGSA LETTER UX;Lo;0;L;;;;;N;;;;; +16A88;TANGSA LETTER AWZ;Lo;0;L;;;;;N;;;;; +16A89;TANGSA LETTER AWC;Lo;0;L;;;;;N;;;;; +16A8A;TANGSA LETTER AWQ;Lo;0;L;;;;;N;;;;; +16A8B;TANGSA LETTER AWX;Lo;0;L;;;;;N;;;;; +16A8C;TANGSA LETTER UIZ;Lo;0;L;;;;;N;;;;; +16A8D;TANGSA LETTER UIC;Lo;0;L;;;;;N;;;;; +16A8E;TANGSA LETTER UIQ;Lo;0;L;;;;;N;;;;; +16A8F;TANGSA LETTER UIX;Lo;0;L;;;;;N;;;;; +16A90;TANGSA LETTER FINAL NG;Lo;0;L;;;;;N;;;;; +16A91;TANGSA LETTER LONG UEX;Lo;0;L;;;;;N;;;;; +16A92;TANGSA LETTER SHORT UEZ;Lo;0;L;;;;;N;;;;; +16A93;TANGSA LETTER SHORT AWX;Lo;0;L;;;;;N;;;;; +16A94;TANGSA LETTER UEC;Lo;0;L;;;;;N;;;;; +16A95;TANGSA LETTER UEZ;Lo;0;L;;;;;N;;;;; +16A96;TANGSA LETTER UEQ;Lo;0;L;;;;;N;;;;; +16A97;TANGSA LETTER UEX;Lo;0;L;;;;;N;;;;; +16A98;TANGSA LETTER UIUZ;Lo;0;L;;;;;N;;;;; +16A99;TANGSA LETTER UIUC;Lo;0;L;;;;;N;;;;; +16A9A;TANGSA LETTER UIUQ;Lo;0;L;;;;;N;;;;; +16A9B;TANGSA LETTER UIUX;Lo;0;L;;;;;N;;;;; +16A9C;TANGSA LETTER MZ;Lo;0;L;;;;;N;;;;; +16A9D;TANGSA LETTER MC;Lo;0;L;;;;;N;;;;; +16A9E;TANGSA LETTER MQ;Lo;0;L;;;;;N;;;;; +16A9F;TANGSA LETTER MX;Lo;0;L;;;;;N;;;;; +16AA0;TANGSA LETTER KA;Lo;0;L;;;;;N;;;;; +16AA1;TANGSA LETTER KHA;Lo;0;L;;;;;N;;;;; +16AA2;TANGSA LETTER GA;Lo;0;L;;;;;N;;;;; +16AA3;TANGSA LETTER NGA;Lo;0;L;;;;;N;;;;; +16AA4;TANGSA LETTER SA;Lo;0;L;;;;;N;;;;; +16AA5;TANGSA LETTER YA;Lo;0;L;;;;;N;;;;; +16AA6;TANGSA LETTER WA;Lo;0;L;;;;;N;;;;; +16AA7;TANGSA LETTER PA;Lo;0;L;;;;;N;;;;; +16AA8;TANGSA LETTER NYA;Lo;0;L;;;;;N;;;;; +16AA9;TANGSA LETTER PHA;Lo;0;L;;;;;N;;;;; +16AAA;TANGSA LETTER BA;Lo;0;L;;;;;N;;;;; +16AAB;TANGSA LETTER MA;Lo;0;L;;;;;N;;;;; +16AAC;TANGSA LETTER NA;Lo;0;L;;;;;N;;;;; +16AAD;TANGSA LETTER HA;Lo;0;L;;;;;N;;;;; +16AAE;TANGSA LETTER LA;Lo;0;L;;;;;N;;;;; +16AAF;TANGSA LETTER HTA;Lo;0;L;;;;;N;;;;; +16AB0;TANGSA LETTER TA;Lo;0;L;;;;;N;;;;; +16AB1;TANGSA LETTER DA;Lo;0;L;;;;;N;;;;; +16AB2;TANGSA LETTER RA;Lo;0;L;;;;;N;;;;; +16AB3;TANGSA LETTER NHA;Lo;0;L;;;;;N;;;;; +16AB4;TANGSA LETTER SHA;Lo;0;L;;;;;N;;;;; +16AB5;TANGSA LETTER CA;Lo;0;L;;;;;N;;;;; +16AB6;TANGSA LETTER TSA;Lo;0;L;;;;;N;;;;; +16AB7;TANGSA LETTER GHA;Lo;0;L;;;;;N;;;;; +16AB8;TANGSA LETTER HTTA;Lo;0;L;;;;;N;;;;; +16AB9;TANGSA LETTER THA;Lo;0;L;;;;;N;;;;; +16ABA;TANGSA LETTER XA;Lo;0;L;;;;;N;;;;; +16ABB;TANGSA LETTER FA;Lo;0;L;;;;;N;;;;; +16ABC;TANGSA LETTER DHA;Lo;0;L;;;;;N;;;;; +16ABD;TANGSA LETTER CHA;Lo;0;L;;;;;N;;;;; +16ABE;TANGSA LETTER ZA;Lo;0;L;;;;;N;;;;; +16AC0;TANGSA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +16AC1;TANGSA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +16AC2;TANGSA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +16AC3;TANGSA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +16AC4;TANGSA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +16AC5;TANGSA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +16AC6;TANGSA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +16AC7;TANGSA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +16AC8;TANGSA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +16AC9;TANGSA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 16AD0;BASSA VAH LETTER ENNI;Lo;0;L;;;;;N;;;;; 16AD1;BASSA VAH LETTER KA;Lo;0;L;;;;;N;;;;; 16AD2;BASSA VAH LETTER SE;Lo;0;L;;;;;N;;;;; @@ -26487,6 +26985,19 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 18CD5;KHITAN SMALL SCRIPT CHARACTER-18CD5;Lo;0;L;;;;;N;;;;; 18D00;;Lo;0;L;;;;;N;;;;; 18D08;;Lo;0;L;;;;;N;;;;; +1AFF0;KATAKANA LETTER MINNAN TONE-2;Lm;0;L;;;;;N;;;;; +1AFF1;KATAKANA LETTER MINNAN TONE-3;Lm;0;L;;;;;N;;;;; +1AFF2;KATAKANA LETTER MINNAN TONE-4;Lm;0;L;;;;;N;;;;; +1AFF3;KATAKANA LETTER MINNAN TONE-5;Lm;0;L;;;;;N;;;;; +1AFF5;KATAKANA LETTER MINNAN TONE-7;Lm;0;L;;;;;N;;;;; +1AFF6;KATAKANA LETTER MINNAN TONE-8;Lm;0;L;;;;;N;;;;; +1AFF7;KATAKANA LETTER MINNAN NASALIZED TONE-1;Lm;0;L;;;;;N;;;;; +1AFF8;KATAKANA LETTER MINNAN NASALIZED TONE-2;Lm;0;L;;;;;N;;;;; +1AFF9;KATAKANA LETTER MINNAN NASALIZED TONE-3;Lm;0;L;;;;;N;;;;; +1AFFA;KATAKANA LETTER MINNAN NASALIZED TONE-4;Lm;0;L;;;;;N;;;;; +1AFFB;KATAKANA LETTER MINNAN NASALIZED TONE-5;Lm;0;L;;;;;N;;;;; +1AFFD;KATAKANA LETTER MINNAN NASALIZED TONE-7;Lm;0;L;;;;;N;;;;; +1AFFE;KATAKANA LETTER MINNAN NASALIZED TONE-8;Lm;0;L;;;;;N;;;;; 1B000;KATAKANA LETTER ARCHAIC E;Lo;0;L;;;;;N;;;;; 1B001;HIRAGANA LETTER ARCHAIC YE;Lo;0;L;;;;;N;;;;; 1B002;HENTAIGANA LETTER A-1;Lo;0;L;;;;;N;;;;; @@ -26774,6 +27285,10 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1B11C;HENTAIGANA LETTER WO-7;Lo;0;L;;;;;N;;;;; 1B11D;HENTAIGANA LETTER N-MU-MO-1;Lo;0;L;;;;;N;;;;; 1B11E;HENTAIGANA LETTER N-MU-MO-2;Lo;0;L;;;;;N;;;;; +1B11F;HIRAGANA LETTER ARCHAIC WU;Lo;0;L;;;;;N;;;;; +1B120;KATAKANA LETTER ARCHAIC YI;Lo;0;L;;;;;N;;;;; +1B121;KATAKANA LETTER ARCHAIC YE;Lo;0;L;;;;;N;;;;; +1B122;KATAKANA LETTER ARCHAIC WU;Lo;0;L;;;;;N;;;;; 1B150;HIRAGANA LETTER SMALL WI;Lo;0;L;;;;;N;;;;; 1B151;HIRAGANA LETTER SMALL WE;Lo;0;L;;;;;N;;;;; 1B152;HIRAGANA LETTER SMALL WO;Lo;0;L;;;;;N;;;;; @@ -27324,6 +27839,191 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1BCA1;SHORTHAND FORMAT CONTINUING OVERLAP;Cf;0;BN;;;;;N;;;;; 1BCA2;SHORTHAND FORMAT DOWN STEP;Cf;0;BN;;;;;N;;;;; 1BCA3;SHORTHAND FORMAT UP STEP;Cf;0;BN;;;;;N;;;;; +1CF00;ZNAMENNY COMBINING MARK GORAZDO NIZKO S KRYZHEM ON LEFT;Mn;0;NSM;;;;;N;;;;; +1CF01;ZNAMENNY COMBINING MARK NIZKO S KRYZHEM ON LEFT;Mn;0;NSM;;;;;N;;;;; +1CF02;ZNAMENNY COMBINING MARK TSATA ON LEFT;Mn;0;NSM;;;;;N;;;;; +1CF03;ZNAMENNY COMBINING MARK GORAZDO NIZKO ON LEFT;Mn;0;NSM;;;;;N;;;;; +1CF04;ZNAMENNY COMBINING MARK NIZKO ON LEFT;Mn;0;NSM;;;;;N;;;;; +1CF05;ZNAMENNY COMBINING MARK SREDNE ON LEFT;Mn;0;NSM;;;;;N;;;;; +1CF06;ZNAMENNY COMBINING MARK MALO POVYSHE ON LEFT;Mn;0;NSM;;;;;N;;;;; +1CF07;ZNAMENNY COMBINING MARK POVYSHE ON LEFT;Mn;0;NSM;;;;;N;;;;; +1CF08;ZNAMENNY COMBINING MARK VYSOKO ON LEFT;Mn;0;NSM;;;;;N;;;;; +1CF09;ZNAMENNY COMBINING MARK MALO POVYSHE S KHOKHLOM ON LEFT;Mn;0;NSM;;;;;N;;;;; +1CF0A;ZNAMENNY COMBINING MARK POVYSHE S KHOKHLOM ON LEFT;Mn;0;NSM;;;;;N;;;;; +1CF0B;ZNAMENNY COMBINING MARK VYSOKO S KHOKHLOM ON LEFT;Mn;0;NSM;;;;;N;;;;; +1CF0C;ZNAMENNY COMBINING MARK GORAZDO NIZKO S KRYZHEM ON RIGHT;Mn;0;NSM;;;;;N;;;;; +1CF0D;ZNAMENNY COMBINING MARK NIZKO S KRYZHEM ON RIGHT;Mn;0;NSM;;;;;N;;;;; +1CF0E;ZNAMENNY COMBINING MARK TSATA ON RIGHT;Mn;0;NSM;;;;;N;;;;; +1CF0F;ZNAMENNY COMBINING MARK GORAZDO NIZKO ON RIGHT;Mn;0;NSM;;;;;N;;;;; +1CF10;ZNAMENNY COMBINING MARK NIZKO ON RIGHT;Mn;0;NSM;;;;;N;;;;; +1CF11;ZNAMENNY COMBINING MARK SREDNE ON RIGHT;Mn;0;NSM;;;;;N;;;;; +1CF12;ZNAMENNY COMBINING MARK MALO POVYSHE ON RIGHT;Mn;0;NSM;;;;;N;;;;; +1CF13;ZNAMENNY COMBINING MARK POVYSHE ON RIGHT;Mn;0;NSM;;;;;N;;;;; +1CF14;ZNAMENNY COMBINING MARK VYSOKO ON RIGHT;Mn;0;NSM;;;;;N;;;;; +1CF15;ZNAMENNY COMBINING MARK MALO POVYSHE S KHOKHLOM ON RIGHT;Mn;0;NSM;;;;;N;;;;; +1CF16;ZNAMENNY COMBINING MARK POVYSHE S KHOKHLOM ON RIGHT;Mn;0;NSM;;;;;N;;;;; +1CF17;ZNAMENNY COMBINING MARK VYSOKO S KHOKHLOM ON RIGHT;Mn;0;NSM;;;;;N;;;;; +1CF18;ZNAMENNY COMBINING MARK TSATA S KRYZHEM;Mn;0;NSM;;;;;N;;;;; +1CF19;ZNAMENNY COMBINING MARK MALO POVYSHE S KRYZHEM;Mn;0;NSM;;;;;N;;;;; +1CF1A;ZNAMENNY COMBINING MARK STRANNO MALO POVYSHE;Mn;0;NSM;;;;;N;;;;; +1CF1B;ZNAMENNY COMBINING MARK POVYSHE S KRYZHEM;Mn;0;NSM;;;;;N;;;;; +1CF1C;ZNAMENNY COMBINING MARK POVYSHE STRANNO;Mn;0;NSM;;;;;N;;;;; +1CF1D;ZNAMENNY COMBINING MARK VYSOKO S KRYZHEM;Mn;0;NSM;;;;;N;;;;; +1CF1E;ZNAMENNY COMBINING MARK MALO POVYSHE STRANNO;Mn;0;NSM;;;;;N;;;;; +1CF1F;ZNAMENNY COMBINING MARK GORAZDO VYSOKO;Mn;0;NSM;;;;;N;;;;; +1CF20;ZNAMENNY COMBINING MARK ZELO;Mn;0;NSM;;;;;N;;;;; +1CF21;ZNAMENNY COMBINING MARK ON;Mn;0;NSM;;;;;N;;;;; +1CF22;ZNAMENNY COMBINING MARK RAVNO;Mn;0;NSM;;;;;N;;;;; +1CF23;ZNAMENNY COMBINING MARK TIKHAYA;Mn;0;NSM;;;;;N;;;;; +1CF24;ZNAMENNY COMBINING MARK BORZAYA;Mn;0;NSM;;;;;N;;;;; +1CF25;ZNAMENNY COMBINING MARK UDARKA;Mn;0;NSM;;;;;N;;;;; +1CF26;ZNAMENNY COMBINING MARK PODVERTKA;Mn;0;NSM;;;;;N;;;;; +1CF27;ZNAMENNY COMBINING MARK LOMKA;Mn;0;NSM;;;;;N;;;;; +1CF28;ZNAMENNY COMBINING MARK KUPNAYA;Mn;0;NSM;;;;;N;;;;; +1CF29;ZNAMENNY COMBINING MARK KACHKA;Mn;0;NSM;;;;;N;;;;; +1CF2A;ZNAMENNY COMBINING MARK ZEVOK;Mn;0;NSM;;;;;N;;;;; +1CF2B;ZNAMENNY COMBINING MARK SKOBA;Mn;0;NSM;;;;;N;;;;; +1CF2C;ZNAMENNY COMBINING MARK RAZSEKA;Mn;0;NSM;;;;;N;;;;; +1CF2D;ZNAMENNY COMBINING MARK KRYZH ON LEFT;Mn;0;NSM;;;;;N;;;;; +1CF30;ZNAMENNY COMBINING TONAL RANGE MARK MRACHNO;Mn;0;NSM;;;;;N;;;;; +1CF31;ZNAMENNY COMBINING TONAL RANGE MARK SVETLO;Mn;0;NSM;;;;;N;;;;; +1CF32;ZNAMENNY COMBINING TONAL RANGE MARK TRESVETLO;Mn;0;NSM;;;;;N;;;;; +1CF33;ZNAMENNY COMBINING MARK ZADERZHKA;Mn;0;NSM;;;;;N;;;;; +1CF34;ZNAMENNY COMBINING MARK DEMESTVENNY ZADERZHKA;Mn;0;NSM;;;;;N;;;;; +1CF35;ZNAMENNY COMBINING MARK OTSECHKA;Mn;0;NSM;;;;;N;;;;; +1CF36;ZNAMENNY COMBINING MARK PODCHASHIE;Mn;0;NSM;;;;;N;;;;; +1CF37;ZNAMENNY COMBINING MARK PODCHASHIE WITH VERTICAL STROKE;Mn;0;NSM;;;;;N;;;;; +1CF38;ZNAMENNY COMBINING MARK CHASHKA;Mn;0;NSM;;;;;N;;;;; +1CF39;ZNAMENNY COMBINING MARK CHASHKA POLNAYA;Mn;0;NSM;;;;;N;;;;; +1CF3A;ZNAMENNY COMBINING MARK OBLACHKO;Mn;0;NSM;;;;;N;;;;; +1CF3B;ZNAMENNY COMBINING MARK SOROCHYA NOZHKA;Mn;0;NSM;;;;;N;;;;; +1CF3C;ZNAMENNY COMBINING MARK TOCHKA;Mn;0;NSM;;;;;N;;;;; +1CF3D;ZNAMENNY COMBINING MARK DVOETOCHIE;Mn;0;NSM;;;;;N;;;;; +1CF3E;ZNAMENNY COMBINING ATTACHING VERTICAL OMET;Mn;0;NSM;;;;;N;;;;; +1CF3F;ZNAMENNY COMBINING MARK CURVED OMET;Mn;0;NSM;;;;;N;;;;; +1CF40;ZNAMENNY COMBINING MARK KRYZH;Mn;0;NSM;;;;;N;;;;; +1CF41;ZNAMENNY COMBINING LOWER TONAL RANGE INDICATOR;Mn;0;NSM;;;;;N;;;;; +1CF42;ZNAMENNY PRIZNAK MODIFIER LEVEL-2;Mn;0;NSM;;;;;N;;;;; +1CF43;ZNAMENNY PRIZNAK MODIFIER LEVEL-3;Mn;0;NSM;;;;;N;;;;; +1CF44;ZNAMENNY PRIZNAK MODIFIER DIRECTION FLIP;Mn;0;NSM;;;;;N;;;;; +1CF45;ZNAMENNY PRIZNAK MODIFIER KRYZH;Mn;0;NSM;;;;;N;;;;; +1CF46;ZNAMENNY PRIZNAK MODIFIER ROG;Mn;0;NSM;;;;;N;;;;; +1CF50;ZNAMENNY NEUME KRYUK;So;0;L;;;;;N;;;;; +1CF51;ZNAMENNY NEUME KRYUK TIKHY;So;0;L;;;;;N;;;;; +1CF52;ZNAMENNY NEUME PARAKLIT;So;0;L;;;;;N;;;;; +1CF53;ZNAMENNY NEUME DVA V CHELNU;So;0;L;;;;;N;;;;; +1CF54;ZNAMENNY NEUME KLYUCH;So;0;L;;;;;N;;;;; +1CF55;ZNAMENNY NEUME ZANOZHEK;So;0;L;;;;;N;;;;; +1CF56;ZNAMENNY NEUME STOPITSA;So;0;L;;;;;N;;;;; +1CF57;ZNAMENNY NEUME STOPITSA S OCHKOM;So;0;L;;;;;N;;;;; +1CF58;ZNAMENNY NEUME PEREVODKA;So;0;L;;;;;N;;;;; +1CF59;ZNAMENNY NEUME PEREVODKA NEPOSTOYANNAYA;So;0;L;;;;;N;;;;; +1CF5A;ZNAMENNY NEUME STOPITSA WITH SOROCHYA NOZHKA;So;0;L;;;;;N;;;;; +1CF5B;ZNAMENNY NEUME CHELYUSTKA;So;0;L;;;;;N;;;;; +1CF5C;ZNAMENNY NEUME PALKA;So;0;L;;;;;N;;;;; +1CF5D;ZNAMENNY NEUME ZAPYATAYA;So;0;L;;;;;N;;;;; +1CF5E;ZNAMENNY NEUME GOLUBCHIK BORZY;So;0;L;;;;;N;;;;; +1CF5F;ZNAMENNY NEUME GOLUBCHIK TIKHY;So;0;L;;;;;N;;;;; +1CF60;ZNAMENNY NEUME GOLUBCHIK MRACHNY;So;0;L;;;;;N;;;;; +1CF61;ZNAMENNY NEUME GOLUBCHIK SVETLY;So;0;L;;;;;N;;;;; +1CF62;ZNAMENNY NEUME GOLUBCHIK TRESVETLY;So;0;L;;;;;N;;;;; +1CF63;ZNAMENNY NEUME VRAKHIYA PROSTAYA;So;0;L;;;;;N;;;;; +1CF64;ZNAMENNY NEUME VRAKHIYA MRACHNAYA;So;0;L;;;;;N;;;;; +1CF65;ZNAMENNY NEUME VRAKHIYA SVETLAYA;So;0;L;;;;;N;;;;; +1CF66;ZNAMENNY NEUME VRAKHIYA TRESVETLAYA;So;0;L;;;;;N;;;;; +1CF67;ZNAMENNY NEUME VRAKHIYA KLYUCHEVAYA PROSTAYA;So;0;L;;;;;N;;;;; +1CF68;ZNAMENNY NEUME VRAKHIYA KLYUCHEVAYA MRACHNAYA;So;0;L;;;;;N;;;;; +1CF69;ZNAMENNY NEUME VRAKHIYA KLYUCHEVAYA SVETLAYA;So;0;L;;;;;N;;;;; +1CF6A;ZNAMENNY NEUME VRAKHIYA KLYUCHEVAYA TRESVETLAYA;So;0;L;;;;;N;;;;; +1CF6B;ZNAMENNY NEUME DOUBLE ZAPYATAYA;So;0;L;;;;;N;;;;; +1CF6C;ZNAMENNY NEUME REVERSED CHELYUSTKA;So;0;L;;;;;N;;;;; +1CF6D;ZNAMENNY NEUME DERBITSA;So;0;L;;;;;N;;;;; +1CF6E;ZNAMENNY NEUME KHAMILO;So;0;L;;;;;N;;;;; +1CF6F;ZNAMENNY NEUME CHASHKA;So;0;L;;;;;N;;;;; +1CF70;ZNAMENNY NEUME PODCHASHIE;So;0;L;;;;;N;;;;; +1CF71;ZNAMENNY NEUME SKAMEYTSA MRACHNAYA;So;0;L;;;;;N;;;;; +1CF72;ZNAMENNY NEUME SKAMEYTSA SVETLAYA;So;0;L;;;;;N;;;;; +1CF73;ZNAMENNY NEUME SKAMEYTSA TRESVETLAYA;So;0;L;;;;;N;;;;; +1CF74;ZNAMENNY NEUME SKAMEYTSA TIKHAYA;So;0;L;;;;;N;;;;; +1CF75;ZNAMENNY NEUME DEMESTVENNY KLYUCH;So;0;L;;;;;N;;;;; +1CF76;ZNAMENNY NEUME SKAMEYTSA KLYUCHEVAYA SVETLAYA;So;0;L;;;;;N;;;;; +1CF77;ZNAMENNY NEUME SKAMEYTSA KLYUCHENEPOSTOYANNAYA;So;0;L;;;;;N;;;;; +1CF78;ZNAMENNY NEUME SKAMEYTSA KLYUCHEVAYA TIKHAYA;So;0;L;;;;;N;;;;; +1CF79;ZNAMENNY NEUME SKAMEYTSA DVOECHELNAYA PROSTAYA;So;0;L;;;;;N;;;;; +1CF7A;ZNAMENNY NEUME SKAMEYTSA DVOECHELNAYA SVETLAYA;So;0;L;;;;;N;;;;; +1CF7B;ZNAMENNY NEUME SKAMEYTSA DVOECHELNAYA NEPOSTOYANNAYA;So;0;L;;;;;N;;;;; +1CF7C;ZNAMENNY NEUME SKAMEYTSA DVOECHELNAYA KLYUCHEVAYA;So;0;L;;;;;N;;;;; +1CF7D;ZNAMENNY NEUME SLOZHITIE;So;0;L;;;;;N;;;;; +1CF7E;ZNAMENNY NEUME SLOZHITIE S ZAPYATOY;So;0;L;;;;;N;;;;; +1CF7F;ZNAMENNY NEUME SLOZHITIE ZAKRYTOE;So;0;L;;;;;N;;;;; +1CF80;ZNAMENNY NEUME SLOZHITIE S KRYZHEM;So;0;L;;;;;N;;;;; +1CF81;ZNAMENNY NEUME KRYZH;So;0;L;;;;;N;;;;; +1CF82;ZNAMENNY NEUME ROG;So;0;L;;;;;N;;;;; +1CF83;ZNAMENNY NEUME FITA;So;0;L;;;;;N;;;;; +1CF84;ZNAMENNY NEUME KOBYLA;So;0;L;;;;;N;;;;; +1CF85;ZNAMENNY NEUME ZMEYTSA;So;0;L;;;;;N;;;;; +1CF86;ZNAMENNY NEUME STATYA;So;0;L;;;;;N;;;;; +1CF87;ZNAMENNY NEUME STATYA S ZAPYATOY;So;0;L;;;;;N;;;;; +1CF88;ZNAMENNY NEUME STATYA S KRYZHEM;So;0;L;;;;;N;;;;; +1CF89;ZNAMENNY NEUME STATYA S ZAPYATOY I KRYZHEM;So;0;L;;;;;N;;;;; +1CF8A;ZNAMENNY NEUME STATYA S KRYZHEM I ZAPYATOY;So;0;L;;;;;N;;;;; +1CF8B;ZNAMENNY NEUME STATYA ZAKRYTAYA;So;0;L;;;;;N;;;;; +1CF8C;ZNAMENNY NEUME STATYA ZAKRYTAYA S ZAPYATOY;So;0;L;;;;;N;;;;; +1CF8D;ZNAMENNY NEUME STATYA S ROGOM;So;0;L;;;;;N;;;;; +1CF8E;ZNAMENNY NEUME STATYA S DVUMYA ZAPYATYMI;So;0;L;;;;;N;;;;; +1CF8F;ZNAMENNY NEUME STATYA S ZAPYATOY I PODCHASHIEM;So;0;L;;;;;N;;;;; +1CF90;ZNAMENNY NEUME POLKULIZMY;So;0;L;;;;;N;;;;; +1CF91;ZNAMENNY NEUME STATYA NEPOSTOYANNAYA;So;0;L;;;;;N;;;;; +1CF92;ZNAMENNY NEUME STRELA PROSTAYA;So;0;L;;;;;N;;;;; +1CF93;ZNAMENNY NEUME STRELA MRACHNOTIKHAYA;So;0;L;;;;;N;;;;; +1CF94;ZNAMENNY NEUME STRELA KRYZHEVAYA;So;0;L;;;;;N;;;;; +1CF95;ZNAMENNY NEUME STRELA POLUPOVODNAYA;So;0;L;;;;;N;;;;; +1CF96;ZNAMENNY NEUME STRELA POVODNAYA;So;0;L;;;;;N;;;;; +1CF97;ZNAMENNY NEUME STRELA NEPOSTOYANNAYA;So;0;L;;;;;N;;;;; +1CF98;ZNAMENNY NEUME STRELA KLYUCHEPOVODNAYA;So;0;L;;;;;N;;;;; +1CF99;ZNAMENNY NEUME STRELA KLYUCHENEPOSTOYANNAYA;So;0;L;;;;;N;;;;; +1CF9A;ZNAMENNY NEUME STRELA TIKHAYA PUTNAYA;So;0;L;;;;;N;;;;; +1CF9B;ZNAMENNY NEUME STRELA DVOECHELNAYA;So;0;L;;;;;N;;;;; +1CF9C;ZNAMENNY NEUME STRELA DVOECHELNOKRYZHEVAYA;So;0;L;;;;;N;;;;; +1CF9D;ZNAMENNY NEUME STRELA DVOECHELNOPOVODNAYA;So;0;L;;;;;N;;;;; +1CF9E;ZNAMENNY NEUME STRELA DVOECHELNAYA KLYUCHEVAYA;So;0;L;;;;;N;;;;; +1CF9F;ZNAMENNY NEUME STRELA DVOECHELNOPOVODNAYA KLYUCHEVAYA;So;0;L;;;;;N;;;;; +1CFA0;ZNAMENNY NEUME STRELA GROMNAYA WITH SINGLE ZAPYATAYA;So;0;L;;;;;N;;;;; +1CFA1;ZNAMENNY NEUME STRELA GROMOPOVODNAYA WITH SINGLE ZAPYATAYA;So;0;L;;;;;N;;;;; +1CFA2;ZNAMENNY NEUME STRELA GROMNAYA;So;0;L;;;;;N;;;;; +1CFA3;ZNAMENNY NEUME STRELA GROMOPOVODNAYA;So;0;L;;;;;N;;;;; +1CFA4;ZNAMENNY NEUME STRELA GROMOPOVODNAYA WITH DOUBLE ZAPYATAYA;So;0;L;;;;;N;;;;; +1CFA5;ZNAMENNY NEUME STRELA GROMOKRYZHEVAYA;So;0;L;;;;;N;;;;; +1CFA6;ZNAMENNY NEUME STRELA GROMOKRYZHEVAYA POVODNAYA;So;0;L;;;;;N;;;;; +1CFA7;ZNAMENNY NEUME MECHIK;So;0;L;;;;;N;;;;; +1CFA8;ZNAMENNY NEUME MECHIK POVODNY;So;0;L;;;;;N;;;;; +1CFA9;ZNAMENNY NEUME MECHIK KLYUCHEVOY;So;0;L;;;;;N;;;;; +1CFAA;ZNAMENNY NEUME MECHIK KLYUCHEPOVODNY;So;0;L;;;;;N;;;;; +1CFAB;ZNAMENNY NEUME MECHIK KLYUCHENEPOSTOYANNY;So;0;L;;;;;N;;;;; +1CFAC;ZNAMENNY NEUME STRELA TRYASOGLASNAYA;So;0;L;;;;;N;;;;; +1CFAD;ZNAMENNY NEUME STRELA TRYASOPOVODNAYA;So;0;L;;;;;N;;;;; +1CFAE;ZNAMENNY NEUME STRELA TRYASOSTRELNAYA;So;0;L;;;;;N;;;;; +1CFAF;ZNAMENNY NEUME OSOKA;So;0;L;;;;;N;;;;; +1CFB0;ZNAMENNY NEUME OSOKA SVETLAYA;So;0;L;;;;;N;;;;; +1CFB1;ZNAMENNY NEUME OSOKA TRESVETLAYA;So;0;L;;;;;N;;;;; +1CFB2;ZNAMENNY NEUME OSOKA KRYUKOVAYA SVETLAYA;So;0;L;;;;;N;;;;; +1CFB3;ZNAMENNY NEUME OSOKA KLYUCHEVAYA SVETLAYA;So;0;L;;;;;N;;;;; +1CFB4;ZNAMENNY NEUME OSOKA KLYUCHEVAYA NEPOSTOYANNAYA;So;0;L;;;;;N;;;;; +1CFB5;ZNAMENNY NEUME STRELA KRYUKOVAYA;So;0;L;;;;;N;;;;; +1CFB6;ZNAMENNY NEUME STRELA KRYUKOVAYA POVODNAYA;So;0;L;;;;;N;;;;; +1CFB7;ZNAMENNY NEUME STRELA KRYUKOVAYA GROMNAYA WITH SINGLE ZAPYATAYA;So;0;L;;;;;N;;;;; +1CFB8;ZNAMENNY NEUME STRELA KRYUKOVAYA GROMOPOVODNAYA WITH SINGLE ZAPYATAYA;So;0;L;;;;;N;;;;; +1CFB9;ZNAMENNY NEUME STRELA KRYUKOVAYA GROMNAYA;So;0;L;;;;;N;;;;; +1CFBA;ZNAMENNY NEUME STRELA KRYUKOVAYA GROMOPOVODNAYA;So;0;L;;;;;N;;;;; +1CFBB;ZNAMENNY NEUME STRELA KRYUKOVAYA GROMOPOVODNAYA WITH DOUBLE ZAPYATAYA;So;0;L;;;;;N;;;;; +1CFBC;ZNAMENNY NEUME STRELA KRYUKOVAYA GROMOKRYZHEVAYA;So;0;L;;;;;N;;;;; +1CFBD;ZNAMENNY NEUME STRELA KRYUKOVAYA GROMOKRYZHEVAYA POVODNAYA;So;0;L;;;;;N;;;;; +1CFBE;ZNAMENNY NEUME STRELA KRYUKOVAYA TRYASKA;So;0;L;;;;;N;;;;; +1CFBF;ZNAMENNY NEUME KUFISMA;So;0;L;;;;;N;;;;; +1CFC0;ZNAMENNY NEUME OBLAKO;So;0;L;;;;;N;;;;; +1CFC1;ZNAMENNY NEUME DUDA;So;0;L;;;;;N;;;;; +1CFC2;ZNAMENNY NEUME NEMKA;So;0;L;;;;;N;;;;; +1CFC3;ZNAMENNY NEUME PAUK;So;0;L;;;;;N;;;;; 1D000;BYZANTINE MUSICAL SYMBOL PSILI;So;0;L;;;;;N;;;;; 1D001;BYZANTINE MUSICAL SYMBOL DASEIA;So;0;L;;;;;N;;;;; 1D002;BYZANTINE MUSICAL SYMBOL PERISPOMENI;So;0;L;;;;;N;;;;; @@ -27801,6 +28501,8 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1D1E6;MUSICAL SYMBOL KIEVAN EIGHTH NOTE STEM DOWN;So;0;L;;;;;N;;;;; 1D1E7;MUSICAL SYMBOL KIEVAN EIGHTH NOTE STEM UP;So;0;L;;;;;N;;;;; 1D1E8;MUSICAL SYMBOL KIEVAN FLAT SIGN;So;0;L;;;;;N;;;;; +1D1E9;MUSICAL SYMBOL SORI;So;0;ON;;;;;N;;;;; +1D1EA;MUSICAL SYMBOL KORON;So;0;ON;;;;;N;;;;; 1D200;GREEK VOCAL NOTATION SYMBOL-1;So;0;ON;;;;;N;;;;; 1D201;GREEK VOCAL NOTATION SYMBOL-2;So;0;ON;;;;;N;;;;; 1D202;GREEK VOCAL NOTATION SYMBOL-3;So;0;ON;;;;;N;;;;; @@ -29671,6 +30373,37 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1DAAD;SIGNWRITING ROTATION MODIFIER-14;Mn;0;NSM;;;;;N;;;;; 1DAAE;SIGNWRITING ROTATION MODIFIER-15;Mn;0;NSM;;;;;N;;;;; 1DAAF;SIGNWRITING ROTATION MODIFIER-16;Mn;0;NSM;;;;;N;;;;; +1DF00;LATIN SMALL LETTER FENG DIGRAPH WITH TRILL;Ll;0;L;;;;;N;;;;; +1DF01;LATIN SMALL LETTER REVERSED SCRIPT G;Ll;0;L;;;;;N;;;;; +1DF02;LATIN LETTER SMALL CAPITAL TURNED G;Ll;0;L;;;;;N;;;;; +1DF03;LATIN SMALL LETTER REVERSED K;Ll;0;L;;;;;N;;;;; +1DF04;LATIN LETTER SMALL CAPITAL L WITH BELT;Ll;0;L;;;;;N;;;;; +1DF05;LATIN SMALL LETTER LEZH WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; +1DF06;LATIN SMALL LETTER TURNED Y WITH BELT;Ll;0;L;;;;;N;;;;; +1DF07;LATIN SMALL LETTER REVERSED ENG;Ll;0;L;;;;;N;;;;; +1DF08;LATIN SMALL LETTER TURNED R WITH LONG LEG AND RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; +1DF09;LATIN SMALL LETTER T WITH HOOK AND RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; +1DF0A;LATIN LETTER RETROFLEX CLICK WITH RETROFLEX HOOK;Lo;0;L;;;;;N;;;;; +1DF0B;LATIN SMALL LETTER ESH WITH DOUBLE BAR;Ll;0;L;;;;;N;;;;; +1DF0C;LATIN SMALL LETTER ESH WITH DOUBLE BAR AND CURL;Ll;0;L;;;;;N;;;;; +1DF0D;LATIN SMALL LETTER TURNED T WITH CURL;Ll;0;L;;;;;N;;;;; +1DF0E;LATIN LETTER INVERTED GLOTTAL STOP WITH CURL;Ll;0;L;;;;;N;;;;; +1DF0F;LATIN LETTER STRETCHED C WITH CURL;Ll;0;L;;;;;N;;;;; +1DF10;LATIN LETTER SMALL CAPITAL TURNED K;Ll;0;L;;;;;N;;;;; +1DF11;LATIN SMALL LETTER L WITH FISHHOOK;Ll;0;L;;;;;N;;;;; +1DF12;LATIN SMALL LETTER DEZH DIGRAPH WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; +1DF13;LATIN SMALL LETTER L WITH BELT AND PALATAL HOOK;Ll;0;L;;;;;N;;;;; +1DF14;LATIN SMALL LETTER ENG WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; +1DF15;LATIN SMALL LETTER TURNED R WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; +1DF16;LATIN SMALL LETTER R WITH FISHHOOK AND PALATAL HOOK;Ll;0;L;;;;;N;;;;; +1DF17;LATIN SMALL LETTER TESH DIGRAPH WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; +1DF18;LATIN SMALL LETTER EZH WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; +1DF19;LATIN SMALL LETTER DEZH DIGRAPH WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; +1DF1A;LATIN SMALL LETTER I WITH STROKE AND RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; +1DF1B;LATIN SMALL LETTER O WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; +1DF1C;LATIN SMALL LETTER TESH DIGRAPH WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; +1DF1D;LATIN SMALL LETTER C WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; +1DF1E;LATIN SMALL LETTER S WITH CURL;Ll;0;L;;;;;N;;;;; 1E000;COMBINING GLAGOLITIC LETTER AZU;Mn;230;NSM;;;;;N;;;;; 1E001;COMBINING GLAGOLITIC LETTER BUKY;Mn;230;NSM;;;;;N;;;;; 1E002;COMBINING GLAGOLITIC LETTER VEDE;Mn;230;NSM;;;;;N;;;;; @@ -29780,6 +30513,37 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1E149;NYIAKENG PUACHUE HMONG DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 1E14E;NYIAKENG PUACHUE HMONG LOGOGRAM NYAJ;Lo;0;L;;;;;N;;;;; 1E14F;NYIAKENG PUACHUE HMONG CIRCLED CA;So;0;L;;;;;N;;;;; +1E290;TOTO LETTER PA;Lo;0;L;;;;;N;;;;; +1E291;TOTO LETTER BA;Lo;0;L;;;;;N;;;;; +1E292;TOTO LETTER TA;Lo;0;L;;;;;N;;;;; +1E293;TOTO LETTER DA;Lo;0;L;;;;;N;;;;; +1E294;TOTO LETTER KA;Lo;0;L;;;;;N;;;;; +1E295;TOTO LETTER GA;Lo;0;L;;;;;N;;;;; +1E296;TOTO LETTER MA;Lo;0;L;;;;;N;;;;; +1E297;TOTO LETTER NA;Lo;0;L;;;;;N;;;;; +1E298;TOTO LETTER NGA;Lo;0;L;;;;;N;;;;; +1E299;TOTO LETTER SA;Lo;0;L;;;;;N;;;;; +1E29A;TOTO LETTER CHA;Lo;0;L;;;;;N;;;;; +1E29B;TOTO LETTER YA;Lo;0;L;;;;;N;;;;; +1E29C;TOTO LETTER WA;Lo;0;L;;;;;N;;;;; +1E29D;TOTO LETTER JA;Lo;0;L;;;;;N;;;;; +1E29E;TOTO LETTER HA;Lo;0;L;;;;;N;;;;; +1E29F;TOTO LETTER RA;Lo;0;L;;;;;N;;;;; +1E2A0;TOTO LETTER LA;Lo;0;L;;;;;N;;;;; +1E2A1;TOTO LETTER I;Lo;0;L;;;;;N;;;;; +1E2A2;TOTO LETTER BREATHY I;Lo;0;L;;;;;N;;;;; +1E2A3;TOTO LETTER IU;Lo;0;L;;;;;N;;;;; +1E2A4;TOTO LETTER BREATHY IU;Lo;0;L;;;;;N;;;;; +1E2A5;TOTO LETTER U;Lo;0;L;;;;;N;;;;; +1E2A6;TOTO LETTER E;Lo;0;L;;;;;N;;;;; +1E2A7;TOTO LETTER BREATHY E;Lo;0;L;;;;;N;;;;; +1E2A8;TOTO LETTER EO;Lo;0;L;;;;;N;;;;; +1E2A9;TOTO LETTER BREATHY EO;Lo;0;L;;;;;N;;;;; +1E2AA;TOTO LETTER O;Lo;0;L;;;;;N;;;;; +1E2AB;TOTO LETTER AE;Lo;0;L;;;;;N;;;;; +1E2AC;TOTO LETTER BREATHY AE;Lo;0;L;;;;;N;;;;; +1E2AD;TOTO LETTER A;Lo;0;L;;;;;N;;;;; +1E2AE;TOTO SIGN RISING TONE;Mn;230;NSM;;;;;N;;;;; 1E2C0;WANCHO LETTER AA;Lo;0;L;;;;;N;;;;; 1E2C1;WANCHO LETTER A;Lo;0;L;;;;;N;;;;; 1E2C2;WANCHO LETTER BA;Lo;0;L;;;;;N;;;;; @@ -29839,6 +30603,34 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1E2F8;WANCHO DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 1E2F9;WANCHO DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 1E2FF;WANCHO NGUN SIGN;Sc;0;ET;;;;;N;;;;; +1E7E0;ETHIOPIC SYLLABLE HHYA;Lo;0;L;;;;;N;;;;; +1E7E1;ETHIOPIC SYLLABLE HHYU;Lo;0;L;;;;;N;;;;; +1E7E2;ETHIOPIC SYLLABLE HHYI;Lo;0;L;;;;;N;;;;; +1E7E3;ETHIOPIC SYLLABLE HHYAA;Lo;0;L;;;;;N;;;;; +1E7E4;ETHIOPIC SYLLABLE HHYEE;Lo;0;L;;;;;N;;;;; +1E7E5;ETHIOPIC SYLLABLE HHYE;Lo;0;L;;;;;N;;;;; +1E7E6;ETHIOPIC SYLLABLE HHYO;Lo;0;L;;;;;N;;;;; +1E7E8;ETHIOPIC SYLLABLE GURAGE HHWA;Lo;0;L;;;;;N;;;;; +1E7E9;ETHIOPIC SYLLABLE HHWI;Lo;0;L;;;;;N;;;;; +1E7EA;ETHIOPIC SYLLABLE HHWEE;Lo;0;L;;;;;N;;;;; +1E7EB;ETHIOPIC SYLLABLE HHWE;Lo;0;L;;;;;N;;;;; +1E7ED;ETHIOPIC SYLLABLE GURAGE MWI;Lo;0;L;;;;;N;;;;; +1E7EE;ETHIOPIC SYLLABLE GURAGE MWEE;Lo;0;L;;;;;N;;;;; +1E7F0;ETHIOPIC SYLLABLE GURAGE QWI;Lo;0;L;;;;;N;;;;; +1E7F1;ETHIOPIC SYLLABLE GURAGE QWEE;Lo;0;L;;;;;N;;;;; +1E7F2;ETHIOPIC SYLLABLE GURAGE QWE;Lo;0;L;;;;;N;;;;; +1E7F3;ETHIOPIC SYLLABLE GURAGE BWI;Lo;0;L;;;;;N;;;;; +1E7F4;ETHIOPIC SYLLABLE GURAGE BWEE;Lo;0;L;;;;;N;;;;; +1E7F5;ETHIOPIC SYLLABLE GURAGE KWI;Lo;0;L;;;;;N;;;;; +1E7F6;ETHIOPIC SYLLABLE GURAGE KWEE;Lo;0;L;;;;;N;;;;; +1E7F7;ETHIOPIC SYLLABLE GURAGE KWE;Lo;0;L;;;;;N;;;;; +1E7F8;ETHIOPIC SYLLABLE GURAGE GWI;Lo;0;L;;;;;N;;;;; +1E7F9;ETHIOPIC SYLLABLE GURAGE GWEE;Lo;0;L;;;;;N;;;;; +1E7FA;ETHIOPIC SYLLABLE GURAGE GWE;Lo;0;L;;;;;N;;;;; +1E7FB;ETHIOPIC SYLLABLE GURAGE FWI;Lo;0;L;;;;;N;;;;; +1E7FC;ETHIOPIC SYLLABLE GURAGE FWEE;Lo;0;L;;;;;N;;;;; +1E7FD;ETHIOPIC SYLLABLE GURAGE PWI;Lo;0;L;;;;;N;;;;; +1E7FE;ETHIOPIC SYLLABLE GURAGE PWEE;Lo;0;L;;;;;N;;;;; 1E800;MENDE KIKAKUI SYLLABLE M001 KI;Lo;0;R;;;;;N;;;;; 1E801;MENDE KIKAKUI SYLLABLE M002 KA;Lo;0;R;;;;;N;;;;; 1E802;MENDE KIKAKUI SYLLABLE M003 KU;Lo;0;R;;;;;N;;;;; @@ -31886,6 +32678,9 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1F6D5;HINDU TEMPLE;So;0;ON;;;;;N;;;;; 1F6D6;HUT;So;0;ON;;;;;N;;;;; 1F6D7;ELEVATOR;So;0;ON;;;;;N;;;;; +1F6DD;PLAYGROUND SLIDE;So;0;ON;;;;;N;;;;; +1F6DE;WHEEL;So;0;ON;;;;;N;;;;; +1F6DF;RING BUOY;So;0;ON;;;;;N;;;;; 1F6E0;HAMMER AND WRENCH;So;0;ON;;;;;N;;;;; 1F6E1;SHIELD;So;0;ON;;;;;N;;;;; 1F6E2;OIL DRUM;So;0;ON;;;;;N;;;;; @@ -32129,6 +32924,7 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1F7E9;LARGE GREEN SQUARE;So;0;ON;;;;;N;;;;; 1F7EA;LARGE PURPLE SQUARE;So;0;ON;;;;;N;;;;; 1F7EB;LARGE BROWN SQUARE;So;0;ON;;;;;N;;;;; +1F7F0;HEAVY EQUALS SIGN;So;0;ON;;;;;N;;;;; 1F800;LEFTWARDS ARROW WITH SMALL TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; 1F801;UPWARDS ARROW WITH SMALL TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; 1F802;RIGHTWARDS ARROW WITH SMALL TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; @@ -32400,6 +33196,7 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1F976;FREEZING FACE;So;0;ON;;;;;N;;;;; 1F977;NINJA;So;0;ON;;;;;N;;;;; 1F978;DISGUISED FACE;So;0;ON;;;;;N;;;;; +1F979;FACE HOLDING BACK TEARS;So;0;ON;;;;;N;;;;; 1F97A;FACE WITH PLEADING EYES;So;0;ON;;;;;N;;;;; 1F97B;SARI;So;0;ON;;;;;N;;;;; 1F97C;LAB COAT;So;0;ON;;;;;N;;;;; @@ -32482,6 +33279,7 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1F9C9;MATE DRINK;So;0;ON;;;;;N;;;;; 1F9CA;ICE CUBE;So;0;ON;;;;;N;;;;; 1F9CB;BUBBLE TEA;So;0;ON;;;;;N;;;;; +1F9CC;TROLL;So;0;ON;;;;;N;;;;; 1F9CD;STANDING PERSON;So;0;ON;;;;;N;;;;; 1F9CE;KNEELING PERSON;So;0;ON;;;;;N;;;;; 1F9CF;DEAF PERSON;So;0;ON;;;;;N;;;;; @@ -32639,6 +33437,8 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1FA78;DROP OF BLOOD;So;0;ON;;;;;N;;;;; 1FA79;ADHESIVE BANDAGE;So;0;ON;;;;;N;;;;; 1FA7A;STETHOSCOPE;So;0;ON;;;;;N;;;;; +1FA7B;X-RAY;So;0;ON;;;;;N;;;;; +1FA7C;CRUTCH;So;0;ON;;;;;N;;;;; 1FA80;YO-YO;So;0;ON;;;;;N;;;;; 1FA81;KITE;So;0;ON;;;;;N;;;;; 1FA82;PARACHUTE;So;0;ON;;;;;N;;;;; @@ -32671,6 +33471,10 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1FAA6;HEADSTONE;So;0;ON;;;;;N;;;;; 1FAA7;PLACARD;So;0;ON;;;;;N;;;;; 1FAA8;ROCK;So;0;ON;;;;;N;;;;; +1FAA9;MIRROR BALL;So;0;ON;;;;;N;;;;; +1FAAA;IDENTIFICATION CARD;So;0;ON;;;;;N;;;;; +1FAAB;LOW BATTERY;So;0;ON;;;;;N;;;;; +1FAAC;HAMSA;So;0;ON;;;;;N;;;;; 1FAB0;FLY;So;0;ON;;;;;N;;;;; 1FAB1;WORM;So;0;ON;;;;;N;;;;; 1FAB2;BEETLE;So;0;ON;;;;;N;;;;; @@ -32678,9 +33482,16 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1FAB4;POTTED PLANT;So;0;ON;;;;;N;;;;; 1FAB5;WOOD;So;0;ON;;;;;N;;;;; 1FAB6;FEATHER;So;0;ON;;;;;N;;;;; +1FAB7;LOTUS;So;0;ON;;;;;N;;;;; +1FAB8;CORAL;So;0;ON;;;;;N;;;;; +1FAB9;EMPTY NEST;So;0;ON;;;;;N;;;;; +1FABA;NEST WITH EGGS;So;0;ON;;;;;N;;;;; 1FAC0;ANATOMICAL HEART;So;0;ON;;;;;N;;;;; 1FAC1;LUNGS;So;0;ON;;;;;N;;;;; 1FAC2;PEOPLE HUGGING;So;0;ON;;;;;N;;;;; +1FAC3;PREGNANT MAN;So;0;ON;;;;;N;;;;; +1FAC4;PREGNANT PERSON;So;0;ON;;;;;N;;;;; +1FAC5;PERSON WITH CROWN;So;0;ON;;;;;N;;;;; 1FAD0;BLUEBERRIES;So;0;ON;;;;;N;;;;; 1FAD1;BELL PEPPER;So;0;ON;;;;;N;;;;; 1FAD2;OLIVE;So;0;ON;;;;;N;;;;; @@ -32688,6 +33499,24 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1FAD4;TAMALE;So;0;ON;;;;;N;;;;; 1FAD5;FONDUE;So;0;ON;;;;;N;;;;; 1FAD6;TEAPOT;So;0;ON;;;;;N;;;;; +1FAD7;POURING LIQUID;So;0;ON;;;;;N;;;;; +1FAD8;BEANS;So;0;ON;;;;;N;;;;; +1FAD9;JAR;So;0;ON;;;;;N;;;;; +1FAE0;MELTING FACE;So;0;ON;;;;;N;;;;; +1FAE1;SALUTING FACE;So;0;ON;;;;;N;;;;; +1FAE2;FACE WITH OPEN EYES AND HAND OVER MOUTH;So;0;ON;;;;;N;;;;; +1FAE3;FACE WITH PEEKING EYE;So;0;ON;;;;;N;;;;; +1FAE4;FACE WITH DIAGONAL MOUTH;So;0;ON;;;;;N;;;;; +1FAE5;DOTTED LINE FACE;So;0;ON;;;;;N;;;;; +1FAE6;BITING LIP;So;0;ON;;;;;N;;;;; +1FAE7;BUBBLES;So;0;ON;;;;;N;;;;; +1FAF0;HAND WITH INDEX FINGER AND THUMB CROSSED;So;0;ON;;;;;N;;;;; +1FAF1;RIGHTWARDS HAND;So;0;ON;;;;;N;;;;; +1FAF2;LEFTWARDS HAND;So;0;ON;;;;;N;;;;; +1FAF3;PALM DOWN HAND;So;0;ON;;;;;N;;;;; +1FAF4;PALM UP HAND;So;0;ON;;;;;N;;;;; +1FAF5;INDEX POINTING AT THE VIEWER;So;0;ON;;;;;N;;;;; +1FAF6;HEART HANDS;So;0;ON;;;;;N;;;;; 1FB00;BLOCK SEXTANT-1;So;0;ON;;;;;N;;;;; 1FB01;BLOCK SEXTANT-2;So;0;ON;;;;;N;;;;; 1FB02;BLOCK SEXTANT-12;So;0;ON;;;;;N;;;;; @@ -32901,9 +33730,9 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1FBF8;SEGMENTED DIGIT EIGHT;Nd;0;EN; 0038;8;8;8;N;;;;; 1FBF9;SEGMENTED DIGIT NINE;Nd;0;EN; 0039;9;9;9;N;;;;; 20000;;Lo;0;L;;;;;N;;;;; -2A6DD;;Lo;0;L;;;;;N;;;;; +2A6DF;;Lo;0;L;;;;;N;;;;; 2A700;;Lo;0;L;;;;;N;;;;; -2B734;;Lo;0;L;;;;;N;;;;; +2B738;;Lo;0;L;;;;;N;;;;; 2B740;;Lo;0;L;;;;;N;;;;; 2B81D;;Lo;0;L;;;;;N;;;;; 2B820;;Lo;0;L;;;;;N;;;;; diff --git a/make/data/unicodedata/VERSION b/make/data/unicodedata/VERSION deleted file mode 100644 index 02161ca86e5..00000000000 --- a/make/data/unicodedata/VERSION +++ /dev/null @@ -1 +0,0 @@ -13.0.0 diff --git a/make/data/unicodedata/auxiliary/GraphemeBreakProperty.txt b/make/data/unicodedata/auxiliary/GraphemeBreakProperty.txt index 504c7082802..15de396fdc1 100644 --- a/make/data/unicodedata/auxiliary/GraphemeBreakProperty.txt +++ b/make/data/unicodedata/auxiliary/GraphemeBreakProperty.txt @@ -1,6 +1,6 @@ -# GraphemeBreakProperty-13.0.0.txt -# Date: 2019-10-21, 14:30:35 GMT -# Copyright (c) 2019 Unicode, Inc. +# GraphemeBreakProperty-14.0.0.txt +# Date: 2021-08-12, 23:13:02 GMT +# Copyright (c) 2021 Unicode, Inc. # Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries. # For terms of use, see http://www.unicode.org/terms_of_use.html # @@ -21,6 +21,7 @@ 0600..0605 ; Prepend # Cf [6] ARABIC NUMBER SIGN..ARABIC NUMBER MARK ABOVE 06DD ; Prepend # Cf ARABIC END OF AYAH 070F ; Prepend # Cf SYRIAC ABBREVIATION MARK +0890..0891 ; Prepend # Cf [2] ARABIC POUND MARK ABOVE..ARABIC PIASTRE MARK ABOVE 08E2 ; Prepend # Cf ARABIC DISPUTED END OF AYAH 0D4E ; Prepend # Lo MALAYALAM LETTER DOT REPH 110BD ; Prepend # Cf KAITHI NUMBER SIGN @@ -32,7 +33,7 @@ 11A84..11A89 ; Prepend # Lo [6] SOYOMBO SIGN JIHVAMULIYA..SOYOMBO CLUSTER-INITIAL LETTER SA 11D46 ; Prepend # Lo MASARAM GONDI REPHA -# Total code points: 24 +# Total code points: 26 # ================================================ @@ -104,7 +105,8 @@ E01F0..E0FFF ; Control # Cn [3600] .. 0825..0827 ; Extend # Mn [3] SAMARITAN VOWEL SIGN SHORT A..SAMARITAN VOWEL SIGN U 0829..082D ; Extend # Mn [5] SAMARITAN VOWEL SIGN LONG I..SAMARITAN MARK NEQUDAA 0859..085B ; Extend # Mn [3] MANDAIC AFFRICATION MARK..MANDAIC GEMINATION MARK -08D3..08E1 ; Extend # Mn [15] ARABIC SMALL LOW WAW..ARABIC SMALL HIGH SIGN SAFHA +0898..089F ; Extend # Mn [8] ARABIC SMALL HIGH WORD AL-JUZ..ARABIC HALF MADDA OVER MADDA +08CA..08E1 ; Extend # Mn [24] ARABIC SMALL HIGH FARSI YEH..ARABIC SMALL HIGH SIGN SAFHA 08E3..0902 ; Extend # Mn [32] ARABIC TURNED DAMMA BELOW..DEVANAGARI SIGN ANUSVARA 093A ; Extend # Mn DEVANAGARI VOWEL SIGN OE 093C ; Extend # Mn DEVANAGARI SIGN NUKTA @@ -151,6 +153,7 @@ E01F0..E0FFF ; Control # Cn [3600] .. 0BD7 ; Extend # Mc TAMIL AU LENGTH MARK 0C00 ; Extend # Mn TELUGU SIGN COMBINING CANDRABINDU ABOVE 0C04 ; Extend # Mn TELUGU SIGN COMBINING ANUSVARA ABOVE +0C3C ; Extend # Mn TELUGU SIGN NUKTA 0C3E..0C40 ; Extend # Mn [3] TELUGU VOWEL SIGN AA..TELUGU VOWEL SIGN II 0C46..0C48 ; Extend # Mn [3] TELUGU VOWEL SIGN E..TELUGU VOWEL SIGN AI 0C4A..0C4D ; Extend # Mn [4] TELUGU VOWEL SIGN O..TELUGU SIGN VIRAMA @@ -206,7 +209,7 @@ E01F0..E0FFF ; Control # Cn [3600] .. 109D ; Extend # Mn MYANMAR VOWEL SIGN AITON AI 135D..135F ; Extend # Mn [3] ETHIOPIC COMBINING GEMINATION AND VOWEL LENGTH MARK..ETHIOPIC COMBINING GEMINATION MARK 1712..1714 ; Extend # Mn [3] TAGALOG VOWEL SIGN I..TAGALOG SIGN VIRAMA -1732..1734 ; Extend # Mn [3] HANUNOO VOWEL SIGN I..HANUNOO SIGN PAMUDPOD +1732..1733 ; Extend # Mn [2] HANUNOO VOWEL SIGN I..HANUNOO VOWEL SIGN U 1752..1753 ; Extend # Mn [2] BUHID VOWEL SIGN I..BUHID VOWEL SIGN U 1772..1773 ; Extend # Mn [2] TAGBANWA VOWEL SIGN I..TAGBANWA VOWEL SIGN U 17B4..17B5 ; Extend # Mn [2] KHMER VOWEL INHERENT AQ..KHMER VOWEL INHERENT AA @@ -215,6 +218,7 @@ E01F0..E0FFF ; Control # Cn [3600] .. 17C9..17D3 ; Extend # Mn [11] KHMER SIGN MUUSIKATOAN..KHMER SIGN BATHAMASAT 17DD ; Extend # Mn KHMER SIGN ATTHACAN 180B..180D ; Extend # Mn [3] MONGOLIAN FREE VARIATION SELECTOR ONE..MONGOLIAN FREE VARIATION SELECTOR THREE +180F ; Extend # Mn MONGOLIAN FREE VARIATION SELECTOR FOUR 1885..1886 ; Extend # Mn [2] MONGOLIAN LETTER ALI GALI BALUDA..MONGOLIAN LETTER ALI GALI THREE BALUDA 18A9 ; Extend # Mn MONGOLIAN LETTER ALI GALI DAGALGA 1920..1922 ; Extend # Mn [3] LIMBU VOWEL SIGN A..LIMBU VOWEL SIGN U @@ -232,7 +236,7 @@ E01F0..E0FFF ; Control # Cn [3600] .. 1A7F ; Extend # Mn TAI THAM COMBINING CRYPTOGRAMMIC DOT 1AB0..1ABD ; Extend # Mn [14] COMBINING DOUBLED CIRCUMFLEX ACCENT..COMBINING PARENTHESES BELOW 1ABE ; Extend # Me COMBINING PARENTHESES OVERLAY -1ABF..1AC0 ; Extend # Mn [2] COMBINING LATIN SMALL LETTER W BELOW..COMBINING LATIN SMALL LETTER TURNED W BELOW +1ABF..1ACE ; Extend # Mn [16] COMBINING LATIN SMALL LETTER W BELOW..COMBINING LATIN SMALL LETTER INSULAR T 1B00..1B03 ; Extend # Mn [4] BALINESE SIGN ULU RICEM..BALINESE SIGN SURANG 1B34 ; Extend # Mn BALINESE SIGN REREKAN 1B35 ; Extend # Mc BALINESE VOWEL SIGN TEDUNG @@ -256,8 +260,7 @@ E01F0..E0FFF ; Control # Cn [3600] .. 1CED ; Extend # Mn VEDIC SIGN TIRYAK 1CF4 ; Extend # Mn VEDIC TONE CANDRA ABOVE 1CF8..1CF9 ; Extend # Mn [2] VEDIC TONE RING ABOVE..VEDIC TONE DOUBLE RING ABOVE -1DC0..1DF9 ; Extend # Mn [58] COMBINING DOTTED GRAVE ACCENT..COMBINING WIDE INVERTED BRIDGE BELOW -1DFB..1DFF ; Extend # Mn [5] COMBINING DELETION MARK..COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW +1DC0..1DFF ; Extend # Mn [64] COMBINING DOTTED GRAVE ACCENT..COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW 200C ; Extend # Cf ZERO WIDTH NON-JOINER 20D0..20DC ; Extend # Mn [13] COMBINING LEFT HARPOON ABOVE..COMBINING FOUR DOTS ABOVE 20DD..20E0 ; Extend # Me [4] COMBINING ENCLOSING CIRCLE..COMBINING ENCLOSING CIRCLE BACKSLASH @@ -322,11 +325,15 @@ FF9E..FF9F ; Extend # Lm [2] HALFWIDTH KATAKANA VOICED SOUND MARK..HALFWIDT 10D24..10D27 ; Extend # Mn [4] HANIFI ROHINGYA SIGN HARBAHAY..HANIFI ROHINGYA SIGN TASSI 10EAB..10EAC ; Extend # Mn [2] YEZIDI COMBINING HAMZA MARK..YEZIDI COMBINING MADDA MARK 10F46..10F50 ; Extend # Mn [11] SOGDIAN COMBINING DOT BELOW..SOGDIAN COMBINING STROKE BELOW +10F82..10F85 ; Extend # Mn [4] OLD UYGHUR COMBINING DOT ABOVE..OLD UYGHUR COMBINING TWO DOTS BELOW 11001 ; Extend # Mn BRAHMI SIGN ANUSVARA 11038..11046 ; Extend # Mn [15] BRAHMI VOWEL SIGN AA..BRAHMI VIRAMA +11070 ; Extend # Mn BRAHMI SIGN OLD TAMIL VIRAMA +11073..11074 ; Extend # Mn [2] BRAHMI VOWEL SIGN OLD TAMIL SHORT E..BRAHMI VOWEL SIGN OLD TAMIL SHORT O 1107F..11081 ; Extend # Mn [3] BRAHMI NUMBER JOINER..KAITHI SIGN ANUSVARA 110B3..110B6 ; Extend # Mn [4] KAITHI VOWEL SIGN U..KAITHI VOWEL SIGN AI 110B9..110BA ; Extend # Mn [2] KAITHI SIGN VIRAMA..KAITHI SIGN NUKTA +110C2 ; Extend # Mn KAITHI VOWEL SIGN VOCALIC R 11100..11102 ; Extend # Mn [3] CHAKMA SIGN CANDRABINDU..CHAKMA SIGN VISARGA 11127..1112B ; Extend # Mn [5] CHAKMA VOWEL SIGN A..CHAKMA VOWEL SIGN UU 1112D..11134 ; Extend # Mn [8] CHAKMA VOWEL SIGN AI..CHAKMA MAAYYAA @@ -412,6 +419,8 @@ FF9E..FF9F ; Extend # Lm [2] HALFWIDTH KATAKANA VOICED SOUND MARK..HALFWIDT 16F8F..16F92 ; Extend # Mn [4] MIAO TONE RIGHT..MIAO TONE BELOW 16FE4 ; Extend # Mn KHITAN SMALL SCRIPT FILLER 1BC9D..1BC9E ; Extend # Mn [2] DUPLOYAN THICK LETTER SELECTOR..DUPLOYAN DOUBLE MARK +1CF00..1CF2D ; Extend # Mn [46] ZNAMENNY COMBINING MARK GORAZDO NIZKO S KRYZHEM ON LEFT..ZNAMENNY COMBINING MARK KRYZH ON LEFT +1CF30..1CF46 ; Extend # Mn [23] ZNAMENNY COMBINING TONAL RANGE MARK MRACHNO..ZNAMENNY PRIZNAK MODIFIER ROG 1D165 ; Extend # Mc MUSICAL SYMBOL COMBINING STEM 1D167..1D169 ; Extend # Mn [3] MUSICAL SYMBOL COMBINING TREMOLO-1..MUSICAL SYMBOL COMBINING TREMOLO-3 1D16E..1D172 ; Extend # Mc [5] MUSICAL SYMBOL COMBINING FLAG-1..MUSICAL SYMBOL COMBINING FLAG-5 @@ -431,6 +440,7 @@ FF9E..FF9F ; Extend # Lm [2] HALFWIDTH KATAKANA VOICED SOUND MARK..HALFWIDT 1E023..1E024 ; Extend # Mn [2] COMBINING GLAGOLITIC LETTER YU..COMBINING GLAGOLITIC LETTER SMALL YUS 1E026..1E02A ; Extend # Mn [5] COMBINING GLAGOLITIC LETTER YO..COMBINING GLAGOLITIC LETTER FITA 1E130..1E136 ; Extend # Mn [7] NYIAKENG PUACHUE HMONG TONE-B..NYIAKENG PUACHUE HMONG TONE-D +1E2AE ; Extend # Mn TOTO SIGN RISING TONE 1E2EC..1E2EF ; Extend # Mn [4] WANCHO TONE TUP..WANCHO TONE KOINI 1E8D0..1E8D6 ; Extend # Mn [7] MENDE KIKAKUI COMBINING NUMBER TEENS..MENDE KIKAKUI COMBINING NUMBER MILLIONS 1E944..1E94A ; Extend # Mn [7] ADLAM ALIF LENGTHENER..ADLAM NUKTA @@ -438,7 +448,7 @@ FF9E..FF9F ; Extend # Lm [2] HALFWIDTH KATAKANA VOICED SOUND MARK..HALFWIDT E0020..E007F ; Extend # Cf [96] TAG SPACE..CANCEL TAG E0100..E01EF ; Extend # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256 -# Total code points: 1984 +# Total code points: 2095 # ================================================ @@ -495,6 +505,8 @@ E0100..E01EF ; Extend # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256 103B..103C ; SpacingMark # Mc [2] MYANMAR CONSONANT SIGN MEDIAL YA..MYANMAR CONSONANT SIGN MEDIAL RA 1056..1057 ; SpacingMark # Mc [2] MYANMAR VOWEL SIGN VOCALIC R..MYANMAR VOWEL SIGN VOCALIC RR 1084 ; SpacingMark # Mc MYANMAR VOWEL SIGN SHAN E +1715 ; SpacingMark # Mc TAGALOG SIGN PAMUDPOD +1734 ; SpacingMark # Mc HANUNOO SIGN PAMUDPOD 17B6 ; SpacingMark # Mc KHMER VOWEL SIGN AA 17BE..17C5 ; SpacingMark # Mc [8] KHMER VOWEL SIGN OE..KHMER VOWEL SIGN AU 17C7..17C8 ; SpacingMark # Mc [2] KHMER SIGN REAHMUK..KHMER SIGN YUUKALEAPINTU @@ -579,7 +591,6 @@ ABEC ; SpacingMark # Mc MEETEI MAYEK LUM IYEK 116AC ; SpacingMark # Mc TAKRI SIGN VISARGA 116AE..116AF ; SpacingMark # Mc [2] TAKRI VOWEL SIGN I..TAKRI VOWEL SIGN II 116B6 ; SpacingMark # Mc TAKRI SIGN VIRAMA -11720..11721 ; SpacingMark # Mc [2] AHOM VOWEL SIGN A..AHOM VOWEL SIGN AA 11726 ; SpacingMark # Mc AHOM VOWEL SIGN E 1182C..1182E ; SpacingMark # Mc [3] DOGRA VOWEL SIGN AA..DOGRA VOWEL SIGN II 11838 ; SpacingMark # Mc DOGRA SIGN VISARGA diff --git a/make/data/unicodedata/auxiliary/GraphemeBreakTest.txt b/make/data/unicodedata/auxiliary/GraphemeBreakTest.txt index e3cd8806ceb..6bb1fe98b5a 100644 --- a/make/data/unicodedata/auxiliary/GraphemeBreakTest.txt +++ b/make/data/unicodedata/auxiliary/GraphemeBreakTest.txt @@ -1,6 +1,6 @@ -# GraphemeBreakTest-13.0.0.txt -# Date: 2019-11-15, 19:49:10 GMT -# Copyright (c) 2019 Unicode, Inc. +# GraphemeBreakTest-14.0.0.txt +# Date: 2021-03-08, 06:22:32 GMT +# Copyright (c) 2021 Unicode, Inc. # Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries. # For terms of use, see http://www.unicode.org/terms_of_use.html # diff --git a/make/data/unicodedata/emoji/emoji-data.txt b/make/data/unicodedata/emoji/emoji-data.txt index a01213299b7..a35d434df22 100644 --- a/make/data/unicodedata/emoji/emoji-data.txt +++ b/make/data/unicodedata/emoji/emoji-data.txt @@ -1,11 +1,11 @@ -# emoji-data.txt -# Date: 2020-01-28, 20:52:38 GMT -# Copyright (c) 2020 Unicode, Inc. +# emoji-data-14.0.0.txt +# Date: 2021-08-26, 17:22:22 GMT +# Copyright (c) 2021 Unicode, Inc. # Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries. # For terms of use, see http://www.unicode.org/terms_of_use.html # # Emoji Data for UTS #51 -# Version: 13.0 +# Used with Emoji Version 14.0 and subsequent minor revisions (if any) # # For documentation and usage, see http://www.unicode.org/reports/tr51 # @@ -22,7 +22,7 @@ # All omitted code points have Emoji=No # @missing: 0000..10FFFF ; Emoji ; No -0023 ; Emoji # E0.0 [1] (#️) number sign +0023 ; Emoji # E0.0 [1] (#️) hash sign 002A ; Emoji # E0.0 [1] (*️) asterisk 0030..0039 ; Emoji # E0.0 [10] (0️..9️) digit zero..digit nine 00A9 ; Emoji # E0.6 [1] (©️) copyright @@ -119,8 +119,8 @@ 2747 ; Emoji # E0.6 [1] (❇️) sparkle 274C ; Emoji # E0.6 [1] (❌) cross mark 274E ; Emoji # E0.6 [1] (❎) cross mark button -2753..2755 ; Emoji # E0.6 [3] (❓..❕) question mark..white exclamation mark -2757 ; Emoji # E0.6 [1] (❗) exclamation mark +2753..2755 ; Emoji # E0.6 [3] (❓..❕) red question mark..white exclamation mark +2757 ; Emoji # E0.6 [1] (❗) red exclamation mark 2763 ; Emoji # E1.0 [1] (❣️) heart exclamation 2764 ; Emoji # E0.6 [1] (❤️) red heart 2795..2797 ; Emoji # E0.6 [3] (➕..➗) plus..divide @@ -239,7 +239,7 @@ 1F509 ; Emoji # E1.0 [1] (🔉) speaker medium volume 1F50A..1F514 ; Emoji # E0.6 [11] (🔊..🔔) speaker high volume..bell 1F515 ; Emoji # E1.0 [1] (🔕) bell with slash -1F516..1F52B ; Emoji # E0.6 [22] (🔖..🔫) bookmark..pistol +1F516..1F52B ; Emoji # E0.6 [22] (🔖..🔫) bookmark..water pistol 1F52C..1F52D ; Emoji # E1.0 [2] (🔬..🔭) microscope..telescope 1F52E..1F53D ; Emoji # E0.6 [16] (🔮..🔽) crystal ball..downwards button 1F549..1F54A ; Emoji # E0.7 [2] (🕉️..🕊️) om..dove @@ -294,7 +294,7 @@ 1F62E..1F62F ; Emoji # E1.0 [2] (😮..😯) face with open mouth..hushed face 1F630..1F633 ; Emoji # E0.6 [4] (😰..😳) anxious face with sweat..flushed face 1F634 ; Emoji # E1.0 [1] (😴) sleeping face -1F635 ; Emoji # E0.6 [1] (😵) dizzy face +1F635 ; Emoji # E0.6 [1] (😵) face with crossed-out eyes 1F636 ; Emoji # E1.0 [1] (😶) face without mouth 1F637..1F640 ; Emoji # E0.6 [10] (😷..🙀) face with medical mask..weary cat 1F641..1F644 ; Emoji # E1.0 [4] (🙁..🙄) slightly frowning face..face with rolling eyes @@ -341,6 +341,7 @@ 1F6D1..1F6D2 ; Emoji # E3.0 [2] (🛑..🛒) stop sign..shopping cart 1F6D5 ; Emoji # E12.0 [1] (🛕) hindu temple 1F6D6..1F6D7 ; Emoji # E13.0 [2] (🛖..🛗) hut..elevator +1F6DD..1F6DF ; Emoji # E14.0 [3] (🛝..🛟) playground slide..ring buoy 1F6E0..1F6E5 ; Emoji # E0.7 [6] (🛠️..🛥️) hammer and wrench..motor boat 1F6E9 ; Emoji # E0.7 [1] (🛩️) small airplane 1F6EB..1F6EC ; Emoji # E1.0 [2] (🛫..🛬) airplane departure..airplane arrival @@ -352,6 +353,7 @@ 1F6FA ; Emoji # E12.0 [1] (🛺) auto rickshaw 1F6FB..1F6FC ; Emoji # E13.0 [2] (🛻..🛼) pickup truck..roller skate 1F7E0..1F7EB ; Emoji # E12.0 [12] (🟠..🟫) orange circle..brown square +1F7F0 ; Emoji # E14.0 [1] (🟰) heavy equals sign 1F90C ; Emoji # E13.0 [1] (🤌) pinched fingers 1F90D..1F90F ; Emoji # E12.0 [3] (🤍..🤏) white heart..pinching hand 1F910..1F918 ; Emoji # E1.0 [9] (🤐..🤘) zipper-mouth face..sign of the horns @@ -375,6 +377,7 @@ 1F972 ; Emoji # E13.0 [1] (🥲) smiling face with tear 1F973..1F976 ; Emoji # E11.0 [4] (🥳..🥶) partying face..cold face 1F977..1F978 ; Emoji # E13.0 [2] (🥷..🥸) ninja..disguised face +1F979 ; Emoji # E14.0 [1] (🥹) face holding back tears 1F97A ; Emoji # E11.0 [1] (🥺) pleading face 1F97B ; Emoji # E12.0 [1] (🥻) sari 1F97C..1F97F ; Emoji # E11.0 [4] (🥼..🥿) lab coat..flat shoe @@ -392,21 +395,29 @@ 1F9C1..1F9C2 ; Emoji # E11.0 [2] (🧁..🧂) cupcake..salt 1F9C3..1F9CA ; Emoji # E12.0 [8] (🧃..🧊) beverage box..ice 1F9CB ; Emoji # E13.0 [1] (🧋) bubble tea +1F9CC ; Emoji # E14.0 [1] (🧌) troll 1F9CD..1F9CF ; Emoji # E12.0 [3] (🧍..🧏) person standing..deaf person 1F9D0..1F9E6 ; Emoji # E5.0 [23] (🧐..🧦) face with monocle..socks 1F9E7..1F9FF ; Emoji # E11.0 [25] (🧧..🧿) red envelope..nazar amulet 1FA70..1FA73 ; Emoji # E12.0 [4] (🩰..🩳) ballet shoes..shorts 1FA74 ; Emoji # E13.0 [1] (🩴) thong sandal 1FA78..1FA7A ; Emoji # E12.0 [3] (🩸..🩺) drop of blood..stethoscope +1FA7B..1FA7C ; Emoji # E14.0 [2] (🩻..🩼) x-ray..crutch 1FA80..1FA82 ; Emoji # E12.0 [3] (🪀..🪂) yo-yo..parachute 1FA83..1FA86 ; Emoji # E13.0 [4] (🪃..🪆) boomerang..nesting dolls 1FA90..1FA95 ; Emoji # E12.0 [6] (🪐..🪕) ringed planet..banjo 1FA96..1FAA8 ; Emoji # E13.0 [19] (🪖..🪨) military helmet..rock +1FAA9..1FAAC ; Emoji # E14.0 [4] (🪩..🪬) mirror ball..hamsa 1FAB0..1FAB6 ; Emoji # E13.0 [7] (🪰..🪶) fly..feather +1FAB7..1FABA ; Emoji # E14.0 [4] (🪷..🪺) lotus..nest with eggs 1FAC0..1FAC2 ; Emoji # E13.0 [3] (🫀..🫂) anatomical heart..people hugging +1FAC3..1FAC5 ; Emoji # E14.0 [3] (🫃..🫅) pregnant man..person with crown 1FAD0..1FAD6 ; Emoji # E13.0 [7] (🫐..🫖) blueberries..teapot +1FAD7..1FAD9 ; Emoji # E14.0 [3] (🫗..🫙) pouring liquid..jar +1FAE0..1FAE7 ; Emoji # E14.0 [8] (🫠..🫧) melting face..bubbles +1FAF0..1FAF6 ; Emoji # E14.0 [7] (🫰..🫶) hand with index finger and thumb crossed..heart hands -# Total elements: 1367 +# Total elements: 1404 # ================================================ @@ -438,8 +449,8 @@ 2728 ; Emoji_Presentation # E0.6 [1] (✨) sparkles 274C ; Emoji_Presentation # E0.6 [1] (❌) cross mark 274E ; Emoji_Presentation # E0.6 [1] (❎) cross mark button -2753..2755 ; Emoji_Presentation # E0.6 [3] (❓..❕) question mark..white exclamation mark -2757 ; Emoji_Presentation # E0.6 [1] (❗) exclamation mark +2753..2755 ; Emoji_Presentation # E0.6 [3] (❓..❕) red question mark..white exclamation mark +2757 ; Emoji_Presentation # E0.6 [1] (❗) red exclamation mark 2795..2797 ; Emoji_Presentation # E0.6 [3] (➕..➗) plus..divide 27B0 ; Emoji_Presentation # E0.6 [1] (➰) curly loop 27BF ; Emoji_Presentation # E1.0 [1] (➿) double curly loop @@ -533,7 +544,7 @@ 1F509 ; Emoji_Presentation # E1.0 [1] (🔉) speaker medium volume 1F50A..1F514 ; Emoji_Presentation # E0.6 [11] (🔊..🔔) speaker high volume..bell 1F515 ; Emoji_Presentation # E1.0 [1] (🔕) bell with slash -1F516..1F52B ; Emoji_Presentation # E0.6 [22] (🔖..🔫) bookmark..pistol +1F516..1F52B ; Emoji_Presentation # E0.6 [22] (🔖..🔫) bookmark..water pistol 1F52C..1F52D ; Emoji_Presentation # E1.0 [2] (🔬..🔭) microscope..telescope 1F52E..1F53D ; Emoji_Presentation # E0.6 [16] (🔮..🔽) crystal ball..downwards button 1F54B..1F54E ; Emoji_Presentation # E1.0 [4] (🕋..🕎) kaaba..menorah @@ -569,7 +580,7 @@ 1F62E..1F62F ; Emoji_Presentation # E1.0 [2] (😮..😯) face with open mouth..hushed face 1F630..1F633 ; Emoji_Presentation # E0.6 [4] (😰..😳) anxious face with sweat..flushed face 1F634 ; Emoji_Presentation # E1.0 [1] (😴) sleeping face -1F635 ; Emoji_Presentation # E0.6 [1] (😵) dizzy face +1F635 ; Emoji_Presentation # E0.6 [1] (😵) face with crossed-out eyes 1F636 ; Emoji_Presentation # E1.0 [1] (😶) face without mouth 1F637..1F640 ; Emoji_Presentation # E0.6 [10] (😷..🙀) face with medical mask..weary cat 1F641..1F644 ; Emoji_Presentation # E1.0 [4] (🙁..🙄) slightly frowning face..face with rolling eyes @@ -614,6 +625,7 @@ 1F6D1..1F6D2 ; Emoji_Presentation # E3.0 [2] (🛑..🛒) stop sign..shopping cart 1F6D5 ; Emoji_Presentation # E12.0 [1] (🛕) hindu temple 1F6D6..1F6D7 ; Emoji_Presentation # E13.0 [2] (🛖..🛗) hut..elevator +1F6DD..1F6DF ; Emoji_Presentation # E14.0 [3] (🛝..🛟) playground slide..ring buoy 1F6EB..1F6EC ; Emoji_Presentation # E1.0 [2] (🛫..🛬) airplane departure..airplane arrival 1F6F4..1F6F6 ; Emoji_Presentation # E3.0 [3] (🛴..🛶) kick scooter..canoe 1F6F7..1F6F8 ; Emoji_Presentation # E5.0 [2] (🛷..🛸) sled..flying saucer @@ -621,6 +633,7 @@ 1F6FA ; Emoji_Presentation # E12.0 [1] (🛺) auto rickshaw 1F6FB..1F6FC ; Emoji_Presentation # E13.0 [2] (🛻..🛼) pickup truck..roller skate 1F7E0..1F7EB ; Emoji_Presentation # E12.0 [12] (🟠..🟫) orange circle..brown square +1F7F0 ; Emoji_Presentation # E14.0 [1] (🟰) heavy equals sign 1F90C ; Emoji_Presentation # E13.0 [1] (🤌) pinched fingers 1F90D..1F90F ; Emoji_Presentation # E12.0 [3] (🤍..🤏) white heart..pinching hand 1F910..1F918 ; Emoji_Presentation # E1.0 [9] (🤐..🤘) zipper-mouth face..sign of the horns @@ -644,6 +657,7 @@ 1F972 ; Emoji_Presentation # E13.0 [1] (🥲) smiling face with tear 1F973..1F976 ; Emoji_Presentation # E11.0 [4] (🥳..🥶) partying face..cold face 1F977..1F978 ; Emoji_Presentation # E13.0 [2] (🥷..🥸) ninja..disguised face +1F979 ; Emoji_Presentation # E14.0 [1] (🥹) face holding back tears 1F97A ; Emoji_Presentation # E11.0 [1] (🥺) pleading face 1F97B ; Emoji_Presentation # E12.0 [1] (🥻) sari 1F97C..1F97F ; Emoji_Presentation # E11.0 [4] (🥼..🥿) lab coat..flat shoe @@ -661,21 +675,29 @@ 1F9C1..1F9C2 ; Emoji_Presentation # E11.0 [2] (🧁..🧂) cupcake..salt 1F9C3..1F9CA ; Emoji_Presentation # E12.0 [8] (🧃..🧊) beverage box..ice 1F9CB ; Emoji_Presentation # E13.0 [1] (🧋) bubble tea +1F9CC ; Emoji_Presentation # E14.0 [1] (🧌) troll 1F9CD..1F9CF ; Emoji_Presentation # E12.0 [3] (🧍..🧏) person standing..deaf person 1F9D0..1F9E6 ; Emoji_Presentation # E5.0 [23] (🧐..🧦) face with monocle..socks 1F9E7..1F9FF ; Emoji_Presentation # E11.0 [25] (🧧..🧿) red envelope..nazar amulet 1FA70..1FA73 ; Emoji_Presentation # E12.0 [4] (🩰..🩳) ballet shoes..shorts 1FA74 ; Emoji_Presentation # E13.0 [1] (🩴) thong sandal 1FA78..1FA7A ; Emoji_Presentation # E12.0 [3] (🩸..🩺) drop of blood..stethoscope +1FA7B..1FA7C ; Emoji_Presentation # E14.0 [2] (🩻..🩼) x-ray..crutch 1FA80..1FA82 ; Emoji_Presentation # E12.0 [3] (🪀..🪂) yo-yo..parachute 1FA83..1FA86 ; Emoji_Presentation # E13.0 [4] (🪃..🪆) boomerang..nesting dolls 1FA90..1FA95 ; Emoji_Presentation # E12.0 [6] (🪐..🪕) ringed planet..banjo 1FA96..1FAA8 ; Emoji_Presentation # E13.0 [19] (🪖..🪨) military helmet..rock +1FAA9..1FAAC ; Emoji_Presentation # E14.0 [4] (🪩..🪬) mirror ball..hamsa 1FAB0..1FAB6 ; Emoji_Presentation # E13.0 [7] (🪰..🪶) fly..feather +1FAB7..1FABA ; Emoji_Presentation # E14.0 [4] (🪷..🪺) lotus..nest with eggs 1FAC0..1FAC2 ; Emoji_Presentation # E13.0 [3] (🫀..🫂) anatomical heart..people hugging +1FAC3..1FAC5 ; Emoji_Presentation # E14.0 [3] (🫃..🫅) pregnant man..person with crown 1FAD0..1FAD6 ; Emoji_Presentation # E13.0 [7] (🫐..🫖) blueberries..teapot +1FAD7..1FAD9 ; Emoji_Presentation # E14.0 [3] (🫗..🫙) pouring liquid..jar +1FAE0..1FAE7 ; Emoji_Presentation # E14.0 [8] (🫠..🫧) melting face..bubbles +1FAF0..1FAF6 ; Emoji_Presentation # E14.0 [7] (🫰..🫶) hand with index finger and thumb crossed..heart hands -# Total elements: 1148 +# Total elements: 1185 # ================================================ @@ -738,15 +760,17 @@ 1F9BB ; Emoji_Modifier_Base # E12.0 [1] (🦻) ear with hearing aid 1F9CD..1F9CF ; Emoji_Modifier_Base # E12.0 [3] (🧍..🧏) person standing..deaf person 1F9D1..1F9DD ; Emoji_Modifier_Base # E5.0 [13] (🧑..🧝) person..elf +1FAC3..1FAC5 ; Emoji_Modifier_Base # E14.0 [3] (🫃..🫅) pregnant man..person with crown +1FAF0..1FAF6 ; Emoji_Modifier_Base # E14.0 [7] (🫰..🫶) hand with index finger and thumb crossed..heart hands -# Total elements: 122 +# Total elements: 132 # ================================================ # All omitted code points have Emoji_Component=No # @missing: 0000..10FFFF ; Emoji_Component ; No -0023 ; Emoji_Component # E0.0 [1] (#️) number sign +0023 ; Emoji_Component # E0.0 [1] (#️) hash sign 002A ; Emoji_Component # E0.0 [1] (*️) asterisk 0030..0039 ; Emoji_Component # E0.0 [10] (0️..9️) digit zero..digit nine 200D ; Emoji_Component # E0.0 [1] (‍) zero width joiner @@ -902,8 +926,8 @@ E0020..E007F ; Emoji_Component # E0.0 [96] (󠀠..󠁿) tag space..c 2747 ; Extended_Pictographic# E0.6 [1] (❇️) sparkle 274C ; Extended_Pictographic# E0.6 [1] (❌) cross mark 274E ; Extended_Pictographic# E0.6 [1] (❎) cross mark button -2753..2755 ; Extended_Pictographic# E0.6 [3] (❓..❕) question mark..white exclamation mark -2757 ; Extended_Pictographic# E0.6 [1] (❗) exclamation mark +2753..2755 ; Extended_Pictographic# E0.6 [3] (❓..❕) red question mark..white exclamation mark +2757 ; Extended_Pictographic# E0.6 [1] (❗) red exclamation mark 2763 ; Extended_Pictographic# E1.0 [1] (❣️) heart exclamation 2764 ; Extended_Pictographic# E0.6 [1] (❤️) red heart 2765..2767 ; Extended_Pictographic# E0.0 [3] (❥..❧) ROTATED HEAVY BLACK HEART BULLET..ROTATED FLORAL HEART BULLET @@ -1041,7 +1065,7 @@ E0020..E007F ; Emoji_Component # E0.0 [96] (󠀠..󠁿) tag space..c 1F509 ; Extended_Pictographic# E1.0 [1] (🔉) speaker medium volume 1F50A..1F514 ; Extended_Pictographic# E0.6 [11] (🔊..🔔) speaker high volume..bell 1F515 ; Extended_Pictographic# E1.0 [1] (🔕) bell with slash -1F516..1F52B ; Extended_Pictographic# E0.6 [22] (🔖..🔫) bookmark..pistol +1F516..1F52B ; Extended_Pictographic# E0.6 [22] (🔖..🔫) bookmark..water pistol 1F52C..1F52D ; Extended_Pictographic# E1.0 [2] (🔬..🔭) microscope..telescope 1F52E..1F53D ; Extended_Pictographic# E0.6 [16] (🔮..🔽) crystal ball..downwards button 1F546..1F548 ; Extended_Pictographic# E0.0 [3] (🕆..🕈) WHITE LATIN CROSS..CELTIC CROSS @@ -1117,7 +1141,7 @@ E0020..E007F ; Emoji_Component # E0.0 [96] (󠀠..󠁿) tag space..c 1F62E..1F62F ; Extended_Pictographic# E1.0 [2] (😮..😯) face with open mouth..hushed face 1F630..1F633 ; Extended_Pictographic# E0.6 [4] (😰..😳) anxious face with sweat..flushed face 1F634 ; Extended_Pictographic# E1.0 [1] (😴) sleeping face -1F635 ; Extended_Pictographic# E0.6 [1] (😵) dizzy face +1F635 ; Extended_Pictographic# E0.6 [1] (😵) face with crossed-out eyes 1F636 ; Extended_Pictographic# E1.0 [1] (😶) face without mouth 1F637..1F640 ; Extended_Pictographic# E0.6 [10] (😷..🙀) face with medical mask..weary cat 1F641..1F644 ; Extended_Pictographic# E1.0 [4] (🙁..🙄) slightly frowning face..face with rolling eyes @@ -1166,7 +1190,8 @@ E0020..E007F ; Emoji_Component # E0.0 [96] (󠀠..󠁿) tag space..c 1F6D3..1F6D4 ; Extended_Pictographic# E0.0 [2] (🛓..🛔) STUPA..PAGODA 1F6D5 ; Extended_Pictographic# E12.0 [1] (🛕) hindu temple 1F6D6..1F6D7 ; Extended_Pictographic# E13.0 [2] (🛖..🛗) hut..elevator -1F6D8..1F6DF ; Extended_Pictographic# E0.0 [8] (🛘..🛟) .. +1F6D8..1F6DC ; Extended_Pictographic# E0.0 [5] (🛘..🛜) .. +1F6DD..1F6DF ; Extended_Pictographic# E14.0 [3] (🛝..🛟) playground slide..ring buoy 1F6E0..1F6E5 ; Extended_Pictographic# E0.7 [6] (🛠️..🛥️) hammer and wrench..motor boat 1F6E6..1F6E8 ; Extended_Pictographic# E0.0 [3] (🛦..🛨) UP-POINTING MILITARY AIRPLANE..UP-POINTING SMALL AIRPLANE 1F6E9 ; Extended_Pictographic# E0.7 [1] (🛩️) small airplane @@ -1185,7 +1210,9 @@ E0020..E007F ; Emoji_Component # E0.0 [96] (󠀠..󠁿) tag space..c 1F774..1F77F ; Extended_Pictographic# E0.0 [12] (🝴..🝿) .. 1F7D5..1F7DF ; Extended_Pictographic# E0.0 [11] (🟕..🟟) CIRCLED TRIANGLE.. 1F7E0..1F7EB ; Extended_Pictographic# E12.0 [12] (🟠..🟫) orange circle..brown square -1F7EC..1F7FF ; Extended_Pictographic# E0.0 [20] (🟬..🟿) .. +1F7EC..1F7EF ; Extended_Pictographic# E0.0 [4] (🟬..🟯) .. +1F7F0 ; Extended_Pictographic# E14.0 [1] (🟰) heavy equals sign +1F7F1..1F7FF ; Extended_Pictographic# E0.0 [15] (🟱..🟿) .. 1F80C..1F80F ; Extended_Pictographic# E0.0 [4] (🠌..🠏) .. 1F848..1F84F ; Extended_Pictographic# E0.0 [8] (🡈..🡏) .. 1F85A..1F85F ; Extended_Pictographic# E0.0 [6] (🡚..🡟) .. @@ -1214,7 +1241,7 @@ E0020..E007F ; Emoji_Component # E0.0 [96] (󠀠..󠁿) tag space..c 1F972 ; Extended_Pictographic# E13.0 [1] (🥲) smiling face with tear 1F973..1F976 ; Extended_Pictographic# E11.0 [4] (🥳..🥶) partying face..cold face 1F977..1F978 ; Extended_Pictographic# E13.0 [2] (🥷..🥸) ninja..disguised face -1F979 ; Extended_Pictographic# E0.0 [1] (🥹) +1F979 ; Extended_Pictographic# E14.0 [1] (🥹) face holding back tears 1F97A ; Extended_Pictographic# E11.0 [1] (🥺) pleading face 1F97B ; Extended_Pictographic# E12.0 [1] (🥻) sari 1F97C..1F97F ; Extended_Pictographic# E11.0 [4] (🥼..🥿) lab coat..flat shoe @@ -1232,7 +1259,7 @@ E0020..E007F ; Emoji_Component # E0.0 [96] (󠀠..󠁿) tag space..c 1F9C1..1F9C2 ; Extended_Pictographic# E11.0 [2] (🧁..🧂) cupcake..salt 1F9C3..1F9CA ; Extended_Pictographic# E12.0 [8] (🧃..🧊) beverage box..ice 1F9CB ; Extended_Pictographic# E13.0 [1] (🧋) bubble tea -1F9CC ; Extended_Pictographic# E0.0 [1] (🧌) +1F9CC ; Extended_Pictographic# E14.0 [1] (🧌) troll 1F9CD..1F9CF ; Extended_Pictographic# E12.0 [3] (🧍..🧏) person standing..deaf person 1F9D0..1F9E6 ; Extended_Pictographic# E5.0 [23] (🧐..🧦) face with monocle..socks 1F9E7..1F9FF ; Extended_Pictographic# E11.0 [25] (🧧..🧿) red envelope..nazar amulet @@ -1241,19 +1268,28 @@ E0020..E007F ; Emoji_Component # E0.0 [96] (󠀠..󠁿) tag space..c 1FA74 ; Extended_Pictographic# E13.0 [1] (🩴) thong sandal 1FA75..1FA77 ; Extended_Pictographic# E0.0 [3] (🩵..🩷) .. 1FA78..1FA7A ; Extended_Pictographic# E12.0 [3] (🩸..🩺) drop of blood..stethoscope -1FA7B..1FA7F ; Extended_Pictographic# E0.0 [5] (🩻..🩿) .. +1FA7B..1FA7C ; Extended_Pictographic# E14.0 [2] (🩻..🩼) x-ray..crutch +1FA7D..1FA7F ; Extended_Pictographic# E0.0 [3] (🩽..🩿) .. 1FA80..1FA82 ; Extended_Pictographic# E12.0 [3] (🪀..🪂) yo-yo..parachute 1FA83..1FA86 ; Extended_Pictographic# E13.0 [4] (🪃..🪆) boomerang..nesting dolls 1FA87..1FA8F ; Extended_Pictographic# E0.0 [9] (🪇..🪏) .. 1FA90..1FA95 ; Extended_Pictographic# E12.0 [6] (🪐..🪕) ringed planet..banjo 1FA96..1FAA8 ; Extended_Pictographic# E13.0 [19] (🪖..🪨) military helmet..rock -1FAA9..1FAAF ; Extended_Pictographic# E0.0 [7] (🪩..🪯) .. +1FAA9..1FAAC ; Extended_Pictographic# E14.0 [4] (🪩..🪬) mirror ball..hamsa +1FAAD..1FAAF ; Extended_Pictographic# E0.0 [3] (🪭..🪯) .. 1FAB0..1FAB6 ; Extended_Pictographic# E13.0 [7] (🪰..🪶) fly..feather -1FAB7..1FABF ; Extended_Pictographic# E0.0 [9] (🪷..🪿) .. +1FAB7..1FABA ; Extended_Pictographic# E14.0 [4] (🪷..🪺) lotus..nest with eggs +1FABB..1FABF ; Extended_Pictographic# E0.0 [5] (🪻..🪿) .. 1FAC0..1FAC2 ; Extended_Pictographic# E13.0 [3] (🫀..🫂) anatomical heart..people hugging -1FAC3..1FACF ; Extended_Pictographic# E0.0 [13] (🫃..🫏) .. +1FAC3..1FAC5 ; Extended_Pictographic# E14.0 [3] (🫃..🫅) pregnant man..person with crown +1FAC6..1FACF ; Extended_Pictographic# E0.0 [10] (🫆..🫏) .. 1FAD0..1FAD6 ; Extended_Pictographic# E13.0 [7] (🫐..🫖) blueberries..teapot -1FAD7..1FAFF ; Extended_Pictographic# E0.0 [41] (🫗..🫿) .. +1FAD7..1FAD9 ; Extended_Pictographic# E14.0 [3] (🫗..🫙) pouring liquid..jar +1FADA..1FADF ; Extended_Pictographic# E0.0 [6] (🫚..🫟) .. +1FAE0..1FAE7 ; Extended_Pictographic# E14.0 [8] (🫠..🫧) melting face..bubbles +1FAE8..1FAEF ; Extended_Pictographic# E0.0 [8] (🫨..🫯) .. +1FAF0..1FAF6 ; Extended_Pictographic# E14.0 [7] (🫰..🫶) hand with index finger and thumb crossed..heart hands +1FAF7..1FAFF ; Extended_Pictographic# E0.0 [9] (🫷..🫿) .. 1FC00..1FFFD ; Extended_Pictographic# E0.0[1022] (🰀..🿽) .. # Total elements: 3537 diff --git a/src/java.base/share/classes/java/lang/Character.java b/src/java.base/share/classes/java/lang/Character.java index 4a5d9afb585..1cc12940ef1 100644 --- a/src/java.base/share/classes/java/lang/Character.java +++ b/src/java.base/share/classes/java/lang/Character.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -63,7 +63,7 @@ import static java.lang.constant.ConstantDescs.DEFAULT_NAME; * from the Unicode Consortium at * http://www.unicode.org. *

- * Character information is based on the Unicode Standard, version 13.0. + * Character information is based on the Unicode Standard, version 14.0. *

* The Java platform has supported different versions of the Unicode * Standard over time. Upgrades to newer versions of the Unicode Standard @@ -75,6 +75,8 @@ import static java.lang.constant.ConstantDescs.DEFAULT_NAME; * Unicode version * * + * Java SE 19 + * Unicode 14.0 * Java SE 15 * Unicode 13.0 * Java SE 13 @@ -735,10 +737,10 @@ class Character implements java.io.Serializable, Comparable, Constabl */ public static final class UnicodeBlock extends Subset { /** - * 684 - the expected number of entities + * 696 - the expected number of entities * 0.75 - the default load factor of HashMap */ - private static final int NUM_ENTITIES = 684; + private static final int NUM_ENTITIES = 696; private static Map map = new HashMap<>((int)(NUM_ENTITIES / 0.75f + 1.0f)); @@ -3424,6 +3426,120 @@ class Character implements java.io.Serializable, Comparable, Constabl "CJK UNIFIED IDEOGRAPHS EXTENSION G", "CJKUNIFIEDIDEOGRAPHSEXTENSIONG"); + /** + * Constant for the "Arabic Extended-B" Unicode + * character block. + * @since 19 + */ + public static final UnicodeBlock ARABIC_EXTENDED_B = + new UnicodeBlock("ARABIC_EXTENDED_B", + "ARABIC EXTENDED-B", + "ARABICEXTENDED-B"); + + /** + * Constant for the "Vithkuqi" Unicode + * character block. + * @since 19 + */ + public static final UnicodeBlock VITHKUQI = + new UnicodeBlock("VITHKUQI"); + + /** + * Constant for the "Latin Extended-F" Unicode + * character block. + * @since 19 + */ + public static final UnicodeBlock LATIN_EXTENDED_F = + new UnicodeBlock("LATIN_EXTENDED_F", + "LATIN EXTENDED-F", + "LATINEXTENDED-F"); + + /** + * Constant for the "Old Uyghur" Unicode + * character block. + * @since 19 + */ + public static final UnicodeBlock OLD_UYGHUR = + new UnicodeBlock("OLD_UYGHUR", + "OLD UYGHUR", + "OLDUYGHUR"); + + /** + * Constant for the "Unified Canadian Aboriginal Syllabics Extended-A" Unicode + * character block. + * @since 19 + */ + public static final UnicodeBlock UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS_EXTENDED_A = + new UnicodeBlock("UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS_EXTENDED_A", + "UNIFIED CANADIAN ABORIGINAL SYLLABICS EXTENDED-A", + "UNIFIEDCANADIANABORIGINALSYLLABICSEXTENDED-A"); + + /** + * Constant for the "Cypro-Minoan" Unicode + * character block. + * @since 19 + */ + public static final UnicodeBlock CYPRO_MINOAN = + new UnicodeBlock("CYPRO_MINOAN", + "CYPRO-MINOAN", + "CYPRO-MINOAN"); + + /** + * Constant for the "Tangsa" Unicode + * character block. + * @since 19 + */ + public static final UnicodeBlock TANGSA = + new UnicodeBlock("TANGSA"); + + /** + * Constant for the "Kana Extended-B" Unicode + * character block. + * @since 19 + */ + public static final UnicodeBlock KANA_EXTENDED_B = + new UnicodeBlock("KANA_EXTENDED_B", + "KANA EXTENDED-B", + "KANAEXTENDED-B"); + + /** + * Constant for the "Znamenny Musical Notation" Unicode + * character block. + * @since 19 + */ + public static final UnicodeBlock ZNAMENNY_MUSICAL_NOTATION = + new UnicodeBlock("ZNAMENNY_MUSICAL_NOTATION", + "ZNAMENNY MUSICAL NOTATION", + "ZNAMENNYMUSICALNOTATION"); + + /** + * Constant for the "Latin Extended-G" Unicode + * character block. + * @since 19 + */ + public static final UnicodeBlock LATIN_EXTENDED_G = + new UnicodeBlock("LATIN_EXTENDED_G", + "LATIN EXTENDED-G", + "LATINEXTENDED-G"); + + /** + * Constant for the "Toto" Unicode + * character block. + * @since 19 + */ + public static final UnicodeBlock TOTO = + new UnicodeBlock("TOTO"); + + /** + * Constant for the "Ethiopic Extended-B" Unicode + * character block. + * @since 19 + */ + public static final UnicodeBlock ETHIOPIC_EXTENDED_B = + new UnicodeBlock("ETHIOPIC_EXTENDED_B", + "ETHIOPIC EXTENDED-B", + "ETHIOPICEXTENDED-B"); + private static final int[] blockStarts = { 0x0000, // 0000..007F; Basic Latin 0x0080, // 0080..00FF; Latin-1 Supplement @@ -3445,7 +3561,7 @@ class Character implements java.io.Serializable, Comparable, Constabl 0x0800, // 0800..083F; Samaritan 0x0840, // 0840..085F; Mandaic 0x0860, // 0860..086F; Syriac Supplement - 0x0870, // unassigned + 0x0870, // 0870..089F; Arabic Extended-B 0x08A0, // 08A0..08FF; Arabic Extended-A 0x0900, // 0900..097F; Devanagari 0x0980, // 0980..09FF; Bengali @@ -3612,9 +3728,11 @@ class Character implements java.io.Serializable, Comparable, Constabl 0x104B0, // 104B0..104FF; Osage 0x10500, // 10500..1052F; Elbasan 0x10530, // 10530..1056F; Caucasian Albanian - 0x10570, // unassigned + 0x10570, // 10570..105BF; Vithkuqi + 0x105C0, // unassigned 0x10600, // 10600..1077F; Linear A - 0x10780, // unassigned + 0x10780, // 10780..107BF; Latin Extended-F + 0x107C0, // unassigned 0x10800, // 10800..1083F; Cypriot Syllabary 0x10840, // 10840..1085F; Imperial Aramaic 0x10860, // 10860..1087F; Palmyrene @@ -3646,7 +3764,7 @@ class Character implements java.io.Serializable, Comparable, Constabl 0x10EC0, // unassigned 0x10F00, // 10F00..10F2F; Old Sogdian 0x10F30, // 10F30..10F6F; Sogdian - 0x10F70, // unassigned + 0x10F70, // 10F70..10FAF; Old Uyghur 0x10FB0, // 10FB0..10FDF; Chorasmian 0x10FE0, // 10FE0..10FFF; Elymaic 0x11000, // 11000..1107F; Brahmi @@ -3670,8 +3788,8 @@ class Character implements java.io.Serializable, Comparable, Constabl 0x11660, // 11660..1167F; Mongolian Supplement 0x11680, // 11680..116CF; Takri 0x116D0, // unassigned - 0x11700, // 11700..1173F; Ahom - 0x11740, // unassigned + 0x11700, // 11700..1174F; Ahom + 0x11750, // unassigned 0x11800, // 11800..1184F; Dogra 0x11850, // unassigned 0x118A0, // 118A0..118FF; Warang Citi @@ -3680,7 +3798,7 @@ class Character implements java.io.Serializable, Comparable, Constabl 0x119A0, // 119A0..119FF; Nandinagari 0x11A00, // 11A00..11A4F; Zanabazar Square 0x11A50, // 11A50..11AAF; Soyombo - 0x11AB0, // unassigned + 0x11AB0, // 11AB0..11ABF; Unified Canadian Aboriginal Syllabics Extended-A 0x11AC0, // 11AC0..11AFF; Pau Cin Hau 0x11B00, // unassigned 0x11C00, // 11C00..11C6F; Bhaiksuki @@ -3697,6 +3815,7 @@ class Character implements java.io.Serializable, Comparable, Constabl 0x12400, // 12400..1247F; Cuneiform Numbers and Punctuation 0x12480, // 12480..1254F; Early Dynastic Cuneiform 0x12550, // unassigned + 0x12F90, // 12F90..12FFF; Cypro-Minoan 0x13000, // 13000..1342F; Egyptian Hieroglyphs 0x13430, // 13430..1343F; Egyptian Hieroglyph Format Controls 0x13440, // unassigned @@ -3704,7 +3823,7 @@ class Character implements java.io.Serializable, Comparable, Constabl 0x14680, // unassigned 0x16800, // 16800..16A3F; Bamum Supplement 0x16A40, // 16A40..16A6F; Mro - 0x16A70, // unassigned + 0x16A70, // 16A70..16ACF; Tangsa 0x16AD0, // 16AD0..16AFF; Bassa Vah 0x16B00, // 16B00..16B8F; Pahawh Hmong 0x16B90, // unassigned @@ -3716,8 +3835,9 @@ class Character implements java.io.Serializable, Comparable, Constabl 0x17000, // 17000..187FF; Tangut 0x18800, // 18800..18AFF; Tangut Components 0x18B00, // 18B00..18CFF; Khitan Small Script - 0x18D00, // 18D00..18D8F; Tangut Supplement - 0x18D90, // unassigned + 0x18D00, // 18D00..18D7F; Tangut Supplement + 0x18D80, // unassigned + 0x1AFF0, // 1AFF0..1AFFF; Kana Extended-B 0x1B000, // 1B000..1B0FF; Kana Supplement 0x1B100, // 1B100..1B12F; Kana Extended-A 0x1B130, // 1B130..1B16F; Small Kana Extension @@ -3726,6 +3846,8 @@ class Character implements java.io.Serializable, Comparable, Constabl 0x1BC00, // 1BC00..1BC9F; Duployan 0x1BCA0, // 1BCA0..1BCAF; Shorthand Format Controls 0x1BCB0, // unassigned + 0x1CF00, // 1CF00..1CFCF; Znamenny Musical Notation + 0x1CFD0, // unassigned 0x1D000, // 1D000..1D0FF; Byzantine Musical Symbols 0x1D100, // 1D100..1D1FF; Musical Symbols 0x1D200, // 1D200..1D24F; Ancient Greek Musical Notation @@ -3737,12 +3859,15 @@ class Character implements java.io.Serializable, Comparable, Constabl 0x1D400, // 1D400..1D7FF; Mathematical Alphanumeric Symbols 0x1D800, // 1D800..1DAAF; Sutton SignWriting 0x1DAB0, // unassigned + 0x1DF00, // 1DF00..1DFFF; Latin Extended-G 0x1E000, // 1E000..1E02F; Glagolitic Supplement 0x1E030, // unassigned 0x1E100, // 1E100..1E14F; Nyiakeng Puachue Hmong 0x1E150, // unassigned + 0x1E290, // 1E290..1E2BF; Toto 0x1E2C0, // 1E2C0..1E2FF; Wancho 0x1E300, // unassigned + 0x1E7E0, // 1E7E0..1E7FF; Ethiopic Extended-B 0x1E800, // 1E800..1E8DF; Mende Kikakui 0x1E8E0, // unassigned 0x1E900, // 1E900..1E95F; Adlam @@ -3810,7 +3935,7 @@ class Character implements java.io.Serializable, Comparable, Constabl SAMARITAN, MANDAIC, SYRIAC_SUPPLEMENT, - null, + ARABIC_EXTENDED_B, ARABIC_EXTENDED_A, DEVANAGARI, BENGALI, @@ -3977,8 +4102,10 @@ class Character implements java.io.Serializable, Comparable, Constabl OSAGE, ELBASAN, CAUCASIAN_ALBANIAN, + VITHKUQI, null, LINEAR_A, + LATIN_EXTENDED_F, null, CYPRIOT_SYLLABARY, IMPERIAL_ARAMAIC, @@ -4011,7 +4138,7 @@ class Character implements java.io.Serializable, Comparable, Constabl null, OLD_SOGDIAN, SOGDIAN, - null, + OLD_UYGHUR, CHORASMIAN, ELYMAIC, BRAHMI, @@ -4045,7 +4172,7 @@ class Character implements java.io.Serializable, Comparable, Constabl NANDINAGARI, ZANABAZAR_SQUARE, SOYOMBO, - null, + UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS_EXTENDED_A, PAU_CIN_HAU, null, BHAIKSUKI, @@ -4062,6 +4189,7 @@ class Character implements java.io.Serializable, Comparable, Constabl CUNEIFORM_NUMBERS_AND_PUNCTUATION, EARLY_DYNASTIC_CUNEIFORM, null, + CYPRO_MINOAN, EGYPTIAN_HIEROGLYPHS, EGYPTIAN_HIEROGLYPH_FORMAT_CONTROLS, null, @@ -4069,7 +4197,7 @@ class Character implements java.io.Serializable, Comparable, Constabl null, BAMUM_SUPPLEMENT, MRO, - null, + TANGSA, BASSA_VAH, PAHAWH_HMONG, null, @@ -4083,6 +4211,7 @@ class Character implements java.io.Serializable, Comparable, Constabl KHITAN_SMALL_SCRIPT, TANGUT_SUPPLEMENT, null, + KANA_EXTENDED_B, KANA_SUPPLEMENT, KANA_EXTENDED_A, SMALL_KANA_EXTENSION, @@ -4091,6 +4220,8 @@ class Character implements java.io.Serializable, Comparable, Constabl DUPLOYAN, SHORTHAND_FORMAT_CONTROLS, null, + ZNAMENNY_MUSICAL_NOTATION, + null, BYZANTINE_MUSICAL_SYMBOLS, MUSICAL_SYMBOLS, ANCIENT_GREEK_MUSICAL_NOTATION, @@ -4102,12 +4233,15 @@ class Character implements java.io.Serializable, Comparable, Constabl MATHEMATICAL_ALPHANUMERIC_SYMBOLS, SUTTON_SIGNWRITING, null, + LATIN_EXTENDED_G, GLAGOLITIC_SUPPLEMENT, null, NYIAKENG_PUACHUE_HMONG, null, + TOTO, WANCHO, null, + ETHIOPIC_EXTENDED_B, MENDE_KIKAKUI, null, ADLAM, @@ -4217,7 +4351,7 @@ class Character implements java.io.Serializable, Comparable, Constabl /** * Returns the UnicodeBlock with the given name. Block * names are determined by The Unicode Standard. The file - * {@code Blocks-.txt} defines blocks for a particular + * {@code Blocks.txt} defines blocks for a particular * version of the standard. The {@link Character} class specifies * the version of the standard that it supports. *

@@ -5116,6 +5250,36 @@ class Character implements java.io.Serializable, Comparable, Constabl */ KHITAN_SMALL_SCRIPT, + /** + * Unicode script "Vithkuqi". + * @since 19 + */ + VITHKUQI, + + /** + * Unicode script "Old Uyghur". + * @since 19 + */ + OLD_UYGHUR, + + /** + * Unicode script "Cypro Minoan". + * @since 19 + */ + CYPRO_MINOAN, + + /** + * Unicode script "Tangsa". + * @since 19 + */ + TANGSA, + + /** + * Unicode script "Toto". + * @since 19 + */ + TOTO, + /** * Unicode script "Unknown". */ @@ -5185,9 +5349,7 @@ class Character implements java.io.Serializable, Comparable, Constabl 0x060C, // 060C ; COMMON 0x060D, // 060D..061A; ARABIC 0x061B, // 061B ; COMMON - 0x061C, // 061C ; ARABIC - 0x061D, // 061D ; UNKNOWN - 0x061E, // 061E ; ARABIC + 0x061C, // 061C..061E; ARABIC 0x061F, // 061F ; COMMON 0x0620, // 0620..063F; ARABIC 0x0640, // 0640 ; COMMON @@ -5218,12 +5380,12 @@ class Character implements java.io.Serializable, Comparable, Constabl 0x085E, // 085E ; MANDAIC 0x085F, // 085F ; UNKNOWN 0x0860, // 0860..086A; SYRIAC - 0x086B, // 086B..089F; UNKNOWN - 0x08A0, // 08A0..08B4; ARABIC - 0x08B5, // 08B5 ; UNKNOWN - 0x08B6, // 08B6..08C7; ARABIC - 0x08C8, // 08C8..08D2; UNKNOWN - 0x08D3, // 08D3..08E1; ARABIC + 0x086B, // 086B..086F; UNKNOWN + 0x0870, // 0870..088E; ARABIC + 0x088F, // 088F ; UNKNOWN + 0x0890, // 0890..0891; ARABIC + 0x0892, // 0892..0897; UNKNOWN + 0x0898, // 0898..08E1; ARABIC 0x08E2, // 08E2 ; COMMON 0x08E3, // 08E3..08FF; ARABIC 0x0900, // 0900..0950; DEVANAGARI @@ -5386,8 +5548,8 @@ class Character implements java.io.Serializable, Comparable, Constabl 0x0C12, // 0C12..0C28; TELUGU 0x0C29, // 0C29 ; UNKNOWN 0x0C2A, // 0C2A..0C39; TELUGU - 0x0C3A, // 0C3A..0C3C; UNKNOWN - 0x0C3D, // 0C3D..0C44; TELUGU + 0x0C3A, // 0C3A..0C3B; UNKNOWN + 0x0C3C, // 0C3C..0C44; TELUGU 0x0C45, // 0C45 ; UNKNOWN 0x0C46, // 0C46..0C48; TELUGU 0x0C49, // 0C49 ; UNKNOWN @@ -5396,7 +5558,9 @@ class Character implements java.io.Serializable, Comparable, Constabl 0x0C55, // 0C55..0C56; TELUGU 0x0C57, // 0C57 ; UNKNOWN 0x0C58, // 0C58..0C5A; TELUGU - 0x0C5B, // 0C5B..0C5F; UNKNOWN + 0x0C5B, // 0C5B..0C5C; UNKNOWN + 0x0C5D, // 0C5D ; TELUGU + 0x0C5E, // 0C5E..0C5F; UNKNOWN 0x0C60, // 0C60..0C63; TELUGU 0x0C64, // 0C64..0C65; UNKNOWN 0x0C66, // 0C66..0C6F; TELUGU @@ -5419,8 +5583,8 @@ class Character implements java.io.Serializable, Comparable, Constabl 0x0CCA, // 0CCA..0CCD; KANNADA 0x0CCE, // 0CCE..0CD4; UNKNOWN 0x0CD5, // 0CD5..0CD6; KANNADA - 0x0CD7, // 0CD7..0CDD; UNKNOWN - 0x0CDE, // 0CDE ; KANNADA + 0x0CD7, // 0CD7..0CDC; UNKNOWN + 0x0CDD, // 0CDD..0CDE; KANNADA 0x0CDF, // 0CDF ; UNKNOWN 0x0CE0, // 0CE0..0CE3; KANNADA 0x0CE4, // 0CE4..0CE5; UNKNOWN @@ -5565,10 +5729,9 @@ class Character implements java.io.Serializable, Comparable, Constabl 0x16EB, // 16EB..16ED; COMMON 0x16EE, // 16EE..16F8; RUNIC 0x16F9, // 16F9..16FF; UNKNOWN - 0x1700, // 1700..170C; TAGALOG - 0x170D, // 170D ; UNKNOWN - 0x170E, // 170E..1714; TAGALOG - 0x1715, // 1715..171F; UNKNOWN + 0x1700, // 1700..1715; TAGALOG + 0x1716, // 1716..171E; UNKNOWN + 0x171F, // 171F ; TAGALOG 0x1720, // 1720..1734; HANUNOO 0x1735, // 1735..1736; COMMON 0x1737, // 1737..173F; UNKNOWN @@ -5590,9 +5753,7 @@ class Character implements java.io.Serializable, Comparable, Constabl 0x1802, // 1802..1803; COMMON 0x1804, // 1804 ; MONGOLIAN 0x1805, // 1805 ; COMMON - 0x1806, // 1806..180E; MONGOLIAN - 0x180F, // 180F ; UNKNOWN - 0x1810, // 1810..1819; MONGOLIAN + 0x1806, // 1806..1819; MONGOLIAN 0x181A, // 181A..181F; UNKNOWN 0x1820, // 1820..1878; MONGOLIAN 0x1879, // 1879..187F; UNKNOWN @@ -5634,12 +5795,12 @@ class Character implements java.io.Serializable, Comparable, Constabl 0x1A9A, // 1A9A..1A9F; UNKNOWN 0x1AA0, // 1AA0..1AAD; TAI_THAM 0x1AAE, // 1AAE..1AAF; UNKNOWN - 0x1AB0, // 1AB0..1AC0; INHERITED - 0x1AC1, // 1AC1..1AFF; UNKNOWN - 0x1B00, // 1B00..1B4B; BALINESE - 0x1B4C, // 1B4C..1B4F; UNKNOWN - 0x1B50, // 1B50..1B7C; BALINESE - 0x1B7D, // 1B7D..1B7F; UNKNOWN + 0x1AB0, // 1AB0..1ACE; INHERITED + 0x1ACF, // 1ACF..1AFF; UNKNOWN + 0x1B00, // 1B00..1B4C; BALINESE + 0x1B4D, // 1B4D..1B4F; UNKNOWN + 0x1B50, // 1B50..1B7E; BALINESE + 0x1B7F, // 1B7F ; UNKNOWN 0x1B80, // 1B80..1BBF; SUNDANESE 0x1BC0, // 1BC0..1BF3; BATAK 0x1BF4, // 1BF4..1BFB; UNKNOWN @@ -5681,9 +5842,7 @@ class Character implements java.io.Serializable, Comparable, Constabl 0x1D78, // 1D78 ; CYRILLIC 0x1D79, // 1D79..1DBE; LATIN 0x1DBF, // 1DBF ; GREEK - 0x1DC0, // 1DC0..1DF9; INHERITED - 0x1DFA, // 1DFA ; UNKNOWN - 0x1DFB, // 1DFB..1DFF; INHERITED + 0x1DC0, // 1DC0..1DFF; INHERITED 0x1E00, // 1E00..1EFF; LATIN 0x1F00, // 1F00..1F15; GREEK 0x1F16, // 1F16..1F17; UNKNOWN @@ -5730,8 +5889,8 @@ class Character implements java.io.Serializable, Comparable, Constabl 0x208F, // 208F ; UNKNOWN 0x2090, // 2090..209C; LATIN 0x209D, // 209D..209F; UNKNOWN - 0x20A0, // 20A0..20BF; COMMON - 0x20C0, // 20C0..20CF; UNKNOWN + 0x20A0, // 20A0..20C0; COMMON + 0x20C1, // 20C1..20CF; UNKNOWN 0x20D0, // 20D0..20F0; INHERITED 0x20F1, // 20F1..20FF; UNKNOWN 0x2100, // 2100..2125; COMMON @@ -5757,10 +5916,7 @@ class Character implements java.io.Serializable, Comparable, Constabl 0x2B76, // 2B76..2B95; COMMON 0x2B96, // 2B96 ; UNKNOWN 0x2B97, // 2B97..2BFF; COMMON - 0x2C00, // 2C00..2C2E; GLAGOLITIC - 0x2C2F, // 2C2F ; UNKNOWN - 0x2C30, // 2C30..2C5E; GLAGOLITIC - 0x2C5F, // 2C5F ; UNKNOWN + 0x2C00, // 2C00..2C5F; GLAGOLITIC 0x2C60, // 2C60..2C7F; LATIN 0x2C80, // 2C80..2CF3; COPTIC 0x2CF4, // 2CF4..2CF8; UNKNOWN @@ -5795,8 +5951,8 @@ class Character implements java.io.Serializable, Comparable, Constabl 0x2DD8, // 2DD8..2DDE; ETHIOPIC 0x2DDF, // 2DDF ; UNKNOWN 0x2DE0, // 2DE0..2DFF; CYRILLIC - 0x2E00, // 2E00..2E52; COMMON - 0x2E53, // 2E53..2E7F; UNKNOWN + 0x2E00, // 2E00..2E5D; COMMON + 0x2E5E, // 2E5E..2E7F; UNKNOWN 0x2E80, // 2E80..2E99; HAN 0x2E9A, // 2E9A ; UNKNOWN 0x2E9B, // 2E9B..2EF3; HAN @@ -5847,8 +6003,7 @@ class Character implements java.io.Serializable, Comparable, Constabl 0x3358, // 3358..33FF; COMMON 0x3400, // 3400..4DBF; HAN 0x4DC0, // 4DC0..4DFF; COMMON - 0x4E00, // 4E00..9FFC; HAN - 0x9FFD, // 9FFD..9FFF; UNKNOWN + 0x4E00, // 4E00..9FFF; HAN 0xA000, // A000..A48C; YI 0xA48D, // A48D..A48F; UNKNOWN 0xA490, // A490..A4C6; YI @@ -5862,11 +6017,15 @@ class Character implements java.io.Serializable, Comparable, Constabl 0xA700, // A700..A721; COMMON 0xA722, // A722..A787; LATIN 0xA788, // A788..A78A; COMMON - 0xA78B, // A78B..A7BF; LATIN - 0xA7C0, // A7C0..A7C1; UNKNOWN - 0xA7C2, // A7C2..A7CA; LATIN - 0xA7CB, // A7CB..A7F4; UNKNOWN - 0xA7F5, // A7F5..A7FF; LATIN + 0xA78B, // A78B..A7CA; LATIN + 0xA7CB, // A7CB..A7CF; UNKNOWN + 0xA7D0, // A7D0..A7D1; LATIN + 0xA7D2, // A7D2 ; UNKNOWN + 0xA7D3, // A7D3 ; LATIN + 0xA7D4, // A7D4 ; UNKNOWN + 0xA7D5, // A7D5..A7D9; LATIN + 0xA7DA, // A7DA..A7F1; UNKNOWN + 0xA7F2, // A7F2..A7FF; LATIN 0xA800, // A800..A82C; SYLOTI_NAGRI 0xA82D, // A82D..A82F; UNKNOWN 0xA830, // A830..A839; COMMON @@ -5954,17 +6113,17 @@ class Character implements java.io.Serializable, Comparable, Constabl 0xFB43, // FB43..FB44; HEBREW 0xFB45, // FB45 ; UNKNOWN 0xFB46, // FB46..FB4F; HEBREW - 0xFB50, // FB50..FBC1; ARABIC - 0xFBC2, // FBC2..FBD2; UNKNOWN + 0xFB50, // FB50..FBC2; ARABIC + 0xFBC3, // FBC3..FBD2; UNKNOWN 0xFBD3, // FBD3..FD3D; ARABIC 0xFD3E, // FD3E..FD3F; COMMON - 0xFD40, // FD40..FD4F; UNKNOWN - 0xFD50, // FD50..FD8F; ARABIC + 0xFD40, // FD40..FD8F; ARABIC 0xFD90, // FD90..FD91; UNKNOWN 0xFD92, // FD92..FDC7; ARABIC - 0xFDC8, // FDC8..FDEF; UNKNOWN - 0xFDF0, // FDF0..FDFD; ARABIC - 0xFDFE, // FDFE..FDFF; UNKNOWN + 0xFDC8, // FDC8..FDCE; UNKNOWN + 0xFDCF, // FDCF ; ARABIC + 0xFDD0, // FDD0..FDEF; UNKNOWN + 0xFDF0, // FDF0..FDFF; ARABIC 0xFE00, // FE00..FE0F; INHERITED 0xFE10, // FE10..FE19; COMMON 0xFE1A, // FE1A..FE1F; UNKNOWN @@ -6071,13 +6230,34 @@ class Character implements java.io.Serializable, Comparable, Constabl 0x10530, // 10530..10563; CAUCASIAN_ALBANIAN 0x10564, // 10564..1056E; UNKNOWN 0x1056F, // 1056F ; CAUCASIAN_ALBANIAN - 0x10570, // 10570..105FF; UNKNOWN + 0x10570, // 10570..1057A; VITHKUQI + 0x1057B, // 1057B ; UNKNOWN + 0x1057C, // 1057C..1058A; VITHKUQI + 0x1058B, // 1058B ; UNKNOWN + 0x1058C, // 1058C..10592; VITHKUQI + 0x10593, // 10593 ; UNKNOWN + 0x10594, // 10594..10595; VITHKUQI + 0x10596, // 10596 ; UNKNOWN + 0x10597, // 10597..105A1; VITHKUQI + 0x105A2, // 105A2 ; UNKNOWN + 0x105A3, // 105A3..105B1; VITHKUQI + 0x105B2, // 105B2 ; UNKNOWN + 0x105B3, // 105B3..105B9; VITHKUQI + 0x105BA, // 105BA ; UNKNOWN + 0x105BB, // 105BB..105BC; VITHKUQI + 0x105BD, // 105BD..105FF; UNKNOWN 0x10600, // 10600..10736; LINEAR_A 0x10737, // 10737..1073F; UNKNOWN 0x10740, // 10740..10755; LINEAR_A 0x10756, // 10756..1075F; UNKNOWN 0x10760, // 10760..10767; LINEAR_A - 0x10768, // 10768..107FF; UNKNOWN + 0x10768, // 10768..1077F; UNKNOWN + 0x10780, // 10780..10785; LATIN + 0x10786, // 10786 ; UNKNOWN + 0x10787, // 10787..107B0; LATIN + 0x107B1, // 107B1 ; UNKNOWN + 0x107B2, // 107B2..107BA; LATIN + 0x107BB, // 107BB..107FF; UNKNOWN 0x10800, // 10800..10805; CYPRIOT 0x10806, // 10806..10807; UNKNOWN 0x10808, // 10808 ; CYPRIOT @@ -6175,18 +6355,20 @@ class Character implements java.io.Serializable, Comparable, Constabl 0x10F00, // 10F00..10F27; OLD_SOGDIAN 0x10F28, // 10F28..10F2F; UNKNOWN 0x10F30, // 10F30..10F59; SOGDIAN - 0x10F5A, // 10F5A..10FAF; UNKNOWN + 0x10F5A, // 10F5A..10F6F; UNKNOWN + 0x10F70, // 10F70..10F89; OLD_UYGHUR + 0x10F8A, // 10F8A..10FAF; UNKNOWN 0x10FB0, // 10FB0..10FCB; CHORASMIAN 0x10FCC, // 10FCC..10FDF; UNKNOWN 0x10FE0, // 10FE0..10FF6; ELYMAIC 0x10FF7, // 10FF7..10FFF; UNKNOWN 0x11000, // 11000..1104D; BRAHMI 0x1104E, // 1104E..11051; UNKNOWN - 0x11052, // 11052..1106F; BRAHMI - 0x11070, // 11070..1107E; UNKNOWN + 0x11052, // 11052..11075; BRAHMI + 0x11076, // 11076..1107E; UNKNOWN 0x1107F, // 1107F ; BRAHMI - 0x11080, // 11080..110C1; KAITHI - 0x110C2, // 110C2..110CC; UNKNOWN + 0x11080, // 11080..110C2; KAITHI + 0x110C3, // 110C3..110CC; UNKNOWN 0x110CD, // 110CD ; KAITHI 0x110CE, // 110CE..110CF; UNKNOWN 0x110D0, // 110D0..110E8; SORA_SOMPENG @@ -6270,16 +6452,16 @@ class Character implements java.io.Serializable, Comparable, Constabl 0x1165A, // 1165A..1165F; UNKNOWN 0x11660, // 11660..1166C; MONGOLIAN 0x1166D, // 1166D..1167F; UNKNOWN - 0x11680, // 11680..116B8; TAKRI - 0x116B9, // 116B9..116BF; UNKNOWN + 0x11680, // 11680..116B9; TAKRI + 0x116BA, // 116BA..116BF; UNKNOWN 0x116C0, // 116C0..116C9; TAKRI 0x116CA, // 116CA..116FF; UNKNOWN 0x11700, // 11700..1171A; AHOM 0x1171B, // 1171B..1171C; UNKNOWN 0x1171D, // 1171D..1172B; AHOM 0x1172C, // 1172C..1172F; UNKNOWN - 0x11730, // 11730..1173F; AHOM - 0x11740, // 11740..117FF; UNKNOWN + 0x11730, // 11730..11746; AHOM + 0x11747, // 11747..117FF; UNKNOWN 0x11800, // 11800..1183B; DOGRA 0x1183C, // 1183C..1189F; UNKNOWN 0x118A0, // 118A0..118F2; WARANG_CITI @@ -6310,7 +6492,8 @@ class Character implements java.io.Serializable, Comparable, Constabl 0x11A00, // 11A00..11A47; ZANABAZAR_SQUARE 0x11A48, // 11A48..11A4F; UNKNOWN 0x11A50, // 11A50..11AA2; SOYOMBO - 0x11AA3, // 11AA3..11ABF; UNKNOWN + 0x11AA3, // 11AA3..11AAF; UNKNOWN + 0x11AB0, // 11AB0..11ABF; CANADIAN_ABORIGINAL 0x11AC0, // 11AC0..11AF8; PAU_CIN_HAU 0x11AF9, // 11AF9..11BFF; UNKNOWN 0x11C00, // 11C00..11C08; BHAIKSUKI @@ -6367,7 +6550,9 @@ class Character implements java.io.Serializable, Comparable, Constabl 0x12470, // 12470..12474; CUNEIFORM 0x12475, // 12475..1247F; UNKNOWN 0x12480, // 12480..12543; CUNEIFORM - 0x12544, // 12544..12FFF; UNKNOWN + 0x12544, // 12544..12F8F; UNKNOWN + 0x12F90, // 12F90..12FF2; CYPRO_MINOAN + 0x12FF3, // 12FF3..12FFF; UNKNOWN 0x13000, // 13000..1342E; EGYPTIAN_HIEROGLYPHS 0x1342F, // 1342F ; UNKNOWN 0x13430, // 13430..13438; EGYPTIAN_HIEROGLYPHS @@ -6381,7 +6566,10 @@ class Character implements java.io.Serializable, Comparable, Constabl 0x16A60, // 16A60..16A69; MRO 0x16A6A, // 16A6A..16A6D; UNKNOWN 0x16A6E, // 16A6E..16A6F; MRO - 0x16A70, // 16A70..16ACF; UNKNOWN + 0x16A70, // 16A70..16ABE; TANGSA + 0x16ABF, // 16ABF ; UNKNOWN + 0x16AC0, // 16AC0..16AC9; TANGSA + 0x16ACA, // 16ACA..16ACF; UNKNOWN 0x16AD0, // 16AD0..16AED; BASSA_VAH 0x16AEE, // 16AEE..16AEF; UNKNOWN 0x16AF0, // 16AF0..16AF5; BASSA_VAH @@ -6406,7 +6594,7 @@ class Character implements java.io.Serializable, Comparable, Constabl 0x16FA0, // 16FA0..16FDF; UNKNOWN 0x16FE0, // 16FE0 ; TANGUT 0x16FE1, // 16FE1 ; NUSHU - 0x16FE2, // 16FE2..16FE3; COMMON + 0x16FE2, // 16FE2..16FE3; HAN 0x16FE4, // 16FE4 ; KHITAN_SMALL_SCRIPT 0x16FE5, // 16FE5..16FEF; UNKNOWN 0x16FF0, // 16FF0..16FF1; HAN @@ -6417,10 +6605,17 @@ class Character implements java.io.Serializable, Comparable, Constabl 0x18B00, // 18B00..18CD5; KHITAN_SMALL_SCRIPT 0x18CD6, // 18CD6..18CFF; UNKNOWN 0x18D00, // 18D00..18D08; TANGUT - 0x18D09, // 18D09..1AFFF; UNKNOWN + 0x18D09, // 18D09..1AFEF; UNKNOWN + 0x1AFF0, // 1AFF0..1AFF3; KATAKANA + 0x1AFF4, // 1AFF4 ; UNKNOWN + 0x1AFF5, // 1AFF5..1AFFB; KATAKANA + 0x1AFFC, // 1AFFC ; UNKNOWN + 0x1AFFD, // 1AFFD..1AFFE; KATAKANA + 0x1AFFF, // 1AFFF ; UNKNOWN 0x1B000, // 1B000 ; KATAKANA - 0x1B001, // 1B001..1B11E; HIRAGANA - 0x1B11F, // 1B11F..1B14F; UNKNOWN + 0x1B001, // 1B001..1B11F; HIRAGANA + 0x1B120, // 1B120..1B122; KATAKANA + 0x1B123, // 1B123..1B14F; UNKNOWN 0x1B150, // 1B150..1B152; HIRAGANA 0x1B153, // 1B153..1B163; UNKNOWN 0x1B164, // 1B164..1B167; KATAKANA @@ -6437,7 +6632,13 @@ class Character implements java.io.Serializable, Comparable, Constabl 0x1BC9A, // 1BC9A..1BC9B; UNKNOWN 0x1BC9C, // 1BC9C..1BC9F; DUPLOYAN 0x1BCA0, // 1BCA0..1BCA3; COMMON - 0x1BCA4, // 1BCA4..1CFFF; UNKNOWN + 0x1BCA4, // 1BCA4..1CEFF; UNKNOWN + 0x1CF00, // 1CF00..1CF2D; INHERITED + 0x1CF2E, // 1CF2E..1CF2F; UNKNOWN + 0x1CF30, // 1CF30..1CF46; INHERITED + 0x1CF47, // 1CF47..1CF4F; UNKNOWN + 0x1CF50, // 1CF50..1CFC3; COMMON + 0x1CFC4, // 1CFC4..1CFFF; UNKNOWN 0x1D000, // 1D000..1D0F5; COMMON 0x1D0F6, // 1D0F6..1D0FF; UNKNOWN 0x1D100, // 1D100..1D126; COMMON @@ -6450,8 +6651,8 @@ class Character implements java.io.Serializable, Comparable, Constabl 0x1D185, // 1D185..1D18B; INHERITED 0x1D18C, // 1D18C..1D1A9; COMMON 0x1D1AA, // 1D1AA..1D1AD; INHERITED - 0x1D1AE, // 1D1AE..1D1E8; COMMON - 0x1D1E9, // 1D1E9..1D1FF; UNKNOWN + 0x1D1AE, // 1D1AE..1D1EA; COMMON + 0x1D1EB, // 1D1EB..1D1FF; UNKNOWN 0x1D200, // 1D200..1D245; GREEK 0x1D246, // 1D246..1D2DF; UNKNOWN 0x1D2E0, // 1D2E0..1D2F3; COMMON @@ -6506,7 +6707,9 @@ class Character implements java.io.Serializable, Comparable, Constabl 0x1DA9B, // 1DA9B..1DA9F; SIGNWRITING 0x1DAA0, // 1DAA0 ; UNKNOWN 0x1DAA1, // 1DAA1..1DAAF; SIGNWRITING - 0x1DAB0, // 1DAB0..1DFFF; UNKNOWN + 0x1DAB0, // 1DAB0..1DEFF; UNKNOWN + 0x1DF00, // 1DF00..1DF1E; LATIN + 0x1DF1F, // 1DF1F..1DFFF; UNKNOWN 0x1E000, // 1E000..1E006; GLAGOLITIC 0x1E007, // 1E007 ; UNKNOWN 0x1E008, // 1E008..1E018; GLAGOLITIC @@ -6524,11 +6727,21 @@ class Character implements java.io.Serializable, Comparable, Constabl 0x1E140, // 1E140..1E149; NYIAKENG_PUACHUE_HMONG 0x1E14A, // 1E14A..1E14D; UNKNOWN 0x1E14E, // 1E14E..1E14F; NYIAKENG_PUACHUE_HMONG - 0x1E150, // 1E150..1E2BF; UNKNOWN + 0x1E150, // 1E150..1E28F; UNKNOWN + 0x1E290, // 1E290..1E2AE; TOTO + 0x1E2AF, // 1E2AF..1E2BF; UNKNOWN 0x1E2C0, // 1E2C0..1E2F9; WANCHO 0x1E2FA, // 1E2FA..1E2FE; UNKNOWN 0x1E2FF, // 1E2FF ; WANCHO - 0x1E300, // 1E300..1E7FF; UNKNOWN + 0x1E300, // 1E300..1E7DF; UNKNOWN + 0x1E7E0, // 1E7E0..1E7E6; ETHIOPIC + 0x1E7E7, // 1E7E7 ; UNKNOWN + 0x1E7E8, // 1E7E8..1E7EB; ETHIOPIC + 0x1E7EC, // 1E7EC ; UNKNOWN + 0x1E7ED, // 1E7ED..1E7EE; ETHIOPIC + 0x1E7EF, // 1E7EF ; UNKNOWN + 0x1E7F0, // 1E7F0..1E7FE; ETHIOPIC + 0x1E7FF, // 1E7FF ; UNKNOWN 0x1E800, // 1E800..1E8C4; MENDE_KIKAKUI 0x1E8C5, // 1E8C5..1E8C6; UNKNOWN 0x1E8C7, // 1E8C7..1E8D6; MENDE_KIKAKUI @@ -6638,8 +6851,8 @@ class Character implements java.io.Serializable, Comparable, Constabl 0x1F260, // 1F260..1F265; COMMON 0x1F266, // 1F266..1F2FF; UNKNOWN 0x1F300, // 1F300..1F6D7; COMMON - 0x1F6D8, // 1F6D8..1F6DF; UNKNOWN - 0x1F6E0, // 1F6E0..1F6EC; COMMON + 0x1F6D8, // 1F6D8..1F6DC; UNKNOWN + 0x1F6DD, // 1F6DD..1F6EC; COMMON 0x1F6ED, // 1F6ED..1F6EF; UNKNOWN 0x1F6F0, // 1F6F0..1F6FC; COMMON 0x1F6FD, // 1F6FD..1F6FF; UNKNOWN @@ -6648,7 +6861,9 @@ class Character implements java.io.Serializable, Comparable, Constabl 0x1F780, // 1F780..1F7D8; COMMON 0x1F7D9, // 1F7D9..1F7DF; UNKNOWN 0x1F7E0, // 1F7E0..1F7EB; COMMON - 0x1F7EC, // 1F7EC..1F7FF; UNKNOWN + 0x1F7EC, // 1F7EC..1F7EF; UNKNOWN + 0x1F7F0, // 1F7F0 ; COMMON + 0x1F7F1, // 1F7F1..1F7FF; UNKNOWN 0x1F800, // 1F800..1F80B; COMMON 0x1F80C, // 1F80C..1F80F; UNKNOWN 0x1F810, // 1F810..1F847; COMMON @@ -6661,38 +6876,38 @@ class Character implements java.io.Serializable, Comparable, Constabl 0x1F8AE, // 1F8AE..1F8AF; UNKNOWN 0x1F8B0, // 1F8B0..1F8B1; COMMON 0x1F8B2, // 1F8B2..1F8FF; UNKNOWN - 0x1F900, // 1F900..1F978; COMMON - 0x1F979, // 1F979 ; UNKNOWN - 0x1F97A, // 1F97A..1F9CB; COMMON - 0x1F9CC, // 1F9CC ; UNKNOWN - 0x1F9CD, // 1F9CD..1FA53; COMMON + 0x1F900, // 1F900..1FA53; COMMON 0x1FA54, // 1FA54..1FA5F; UNKNOWN 0x1FA60, // 1FA60..1FA6D; COMMON 0x1FA6E, // 1FA6E..1FA6F; UNKNOWN 0x1FA70, // 1FA70..1FA74; COMMON 0x1FA75, // 1FA75..1FA77; UNKNOWN - 0x1FA78, // 1FA78..1FA7A; COMMON - 0x1FA7B, // 1FA7B..1FA7F; UNKNOWN + 0x1FA78, // 1FA78..1FA7C; COMMON + 0x1FA7D, // 1FA7D..1FA7F; UNKNOWN 0x1FA80, // 1FA80..1FA86; COMMON 0x1FA87, // 1FA87..1FA8F; UNKNOWN - 0x1FA90, // 1FA90..1FAA8; COMMON - 0x1FAA9, // 1FAA9..1FAAF; UNKNOWN - 0x1FAB0, // 1FAB0..1FAB6; COMMON - 0x1FAB7, // 1FAB7..1FABF; UNKNOWN - 0x1FAC0, // 1FAC0..1FAC2; COMMON - 0x1FAC3, // 1FAC3..1FACF; UNKNOWN - 0x1FAD0, // 1FAD0..1FAD6; COMMON - 0x1FAD7, // 1FAD7..1FAFF; UNKNOWN + 0x1FA90, // 1FA90..1FAAC; COMMON + 0x1FAAD, // 1FAAD..1FAAF; UNKNOWN + 0x1FAB0, // 1FAB0..1FABA; COMMON + 0x1FABB, // 1FABB..1FABF; UNKNOWN + 0x1FAC0, // 1FAC0..1FAC5; COMMON + 0x1FAC6, // 1FAC6..1FACF; UNKNOWN + 0x1FAD0, // 1FAD0..1FAD9; COMMON + 0x1FADA, // 1FADA..1FADF; UNKNOWN + 0x1FAE0, // 1FAE0..1FAE7; COMMON + 0x1FAE8, // 1FAE8..1FAEF; UNKNOWN + 0x1FAF0, // 1FAF0..1FAF6; COMMON + 0x1FAF7, // 1FAF7..1FAFF; UNKNOWN 0x1FB00, // 1FB00..1FB92; COMMON 0x1FB93, // 1FB93 ; UNKNOWN 0x1FB94, // 1FB94..1FBCA; COMMON 0x1FBCB, // 1FBCB..1FBEF; UNKNOWN 0x1FBF0, // 1FBF0..1FBF9; COMMON 0x1FBFA, // 1FBFA..1FFFF; UNKNOWN - 0x20000, // 20000..2A6DD; HAN - 0x2A6DE, // 2A6DE..2A6FF; UNKNOWN - 0x2A700, // 2A700..2B734; HAN - 0x2B735, // 2B735..2B73F; UNKNOWN + 0x20000, // 20000..2A6DF; HAN + 0x2A6E0, // 2A6E0..2A6FF; UNKNOWN + 0x2A700, // 2A700..2B738; HAN + 0x2B739, // 2B739..2B73F; UNKNOWN 0x2B740, // 2B740..2B81D; HAN 0x2B81E, // 2B81E..2B81F; UNKNOWN 0x2B820, // 2B820..2CEA1; HAN @@ -6775,9 +6990,7 @@ class Character implements java.io.Serializable, Comparable, Constabl COMMON, // 060C ARABIC, // 060D..061A COMMON, // 061B - ARABIC, // 061C - UNKNOWN, // 061D - ARABIC, // 061E + ARABIC, // 061C..061E COMMON, // 061F ARABIC, // 0620..063F COMMON, // 0640 @@ -6808,12 +7021,12 @@ class Character implements java.io.Serializable, Comparable, Constabl MANDAIC, // 085E UNKNOWN, // 085F SYRIAC, // 0860..086A - UNKNOWN, // 086B..089F - ARABIC, // 08A0..08B4 - UNKNOWN, // 08B5 - ARABIC, // 08B6..08C7 - UNKNOWN, // 08C8..08D2 - ARABIC, // 08D3..08E1 + UNKNOWN, // 086B..086F + ARABIC, // 0870..088E + UNKNOWN, // 088F + ARABIC, // 0890..0891 + UNKNOWN, // 0892..0897 + ARABIC, // 0898..08E1 COMMON, // 08E2 ARABIC, // 08E3..08FF DEVANAGARI, // 0900..0950 @@ -6976,8 +7189,8 @@ class Character implements java.io.Serializable, Comparable, Constabl TELUGU, // 0C12..0C28 UNKNOWN, // 0C29 TELUGU, // 0C2A..0C39 - UNKNOWN, // 0C3A..0C3C - TELUGU, // 0C3D..0C44 + UNKNOWN, // 0C3A..0C3B + TELUGU, // 0C3C..0C44 UNKNOWN, // 0C45 TELUGU, // 0C46..0C48 UNKNOWN, // 0C49 @@ -6986,7 +7199,9 @@ class Character implements java.io.Serializable, Comparable, Constabl TELUGU, // 0C55..0C56 UNKNOWN, // 0C57 TELUGU, // 0C58..0C5A - UNKNOWN, // 0C5B..0C5F + UNKNOWN, // 0C5B..0C5C + TELUGU, // 0C5D + UNKNOWN, // 0C5E..0C5F TELUGU, // 0C60..0C63 UNKNOWN, // 0C64..0C65 TELUGU, // 0C66..0C6F @@ -7009,8 +7224,8 @@ class Character implements java.io.Serializable, Comparable, Constabl KANNADA, // 0CCA..0CCD UNKNOWN, // 0CCE..0CD4 KANNADA, // 0CD5..0CD6 - UNKNOWN, // 0CD7..0CDD - KANNADA, // 0CDE + UNKNOWN, // 0CD7..0CDC + KANNADA, // 0CDD..0CDE UNKNOWN, // 0CDF KANNADA, // 0CE0..0CE3 UNKNOWN, // 0CE4..0CE5 @@ -7155,10 +7370,9 @@ class Character implements java.io.Serializable, Comparable, Constabl COMMON, // 16EB..16ED RUNIC, // 16EE..16F8 UNKNOWN, // 16F9..16FF - TAGALOG, // 1700..170C - UNKNOWN, // 170D - TAGALOG, // 170E..1714 - UNKNOWN, // 1715..171F + TAGALOG, // 1700..1715 + UNKNOWN, // 1716..171E + TAGALOG, // 171F HANUNOO, // 1720..1734 COMMON, // 1735..1736 UNKNOWN, // 1737..173F @@ -7180,9 +7394,7 @@ class Character implements java.io.Serializable, Comparable, Constabl COMMON, // 1802..1803 MONGOLIAN, // 1804 COMMON, // 1805 - MONGOLIAN, // 1806..180E - UNKNOWN, // 180F - MONGOLIAN, // 1810..1819 + MONGOLIAN, // 1806..1819 UNKNOWN, // 181A..181F MONGOLIAN, // 1820..1878 UNKNOWN, // 1879..187F @@ -7224,12 +7436,12 @@ class Character implements java.io.Serializable, Comparable, Constabl UNKNOWN, // 1A9A..1A9F TAI_THAM, // 1AA0..1AAD UNKNOWN, // 1AAE..1AAF - INHERITED, // 1AB0..1AC0 - UNKNOWN, // 1AC1..1AFF - BALINESE, // 1B00..1B4B - UNKNOWN, // 1B4C..1B4F - BALINESE, // 1B50..1B7C - UNKNOWN, // 1B7D..1B7F + INHERITED, // 1AB0..1ACE + UNKNOWN, // 1ACF..1AFF + BALINESE, // 1B00..1B4C + UNKNOWN, // 1B4D..1B4F + BALINESE, // 1B50..1B7E + UNKNOWN, // 1B7F SUNDANESE, // 1B80..1BBF BATAK, // 1BC0..1BF3 UNKNOWN, // 1BF4..1BFB @@ -7271,9 +7483,7 @@ class Character implements java.io.Serializable, Comparable, Constabl CYRILLIC, // 1D78 LATIN, // 1D79..1DBE GREEK, // 1DBF - INHERITED, // 1DC0..1DF9 - UNKNOWN, // 1DFA - INHERITED, // 1DFB..1DFF + INHERITED, // 1DC0..1DFF LATIN, // 1E00..1EFF GREEK, // 1F00..1F15 UNKNOWN, // 1F16..1F17 @@ -7320,8 +7530,8 @@ class Character implements java.io.Serializable, Comparable, Constabl UNKNOWN, // 208F LATIN, // 2090..209C UNKNOWN, // 209D..209F - COMMON, // 20A0..20BF - UNKNOWN, // 20C0..20CF + COMMON, // 20A0..20C0 + UNKNOWN, // 20C1..20CF INHERITED, // 20D0..20F0 UNKNOWN, // 20F1..20FF COMMON, // 2100..2125 @@ -7347,10 +7557,7 @@ class Character implements java.io.Serializable, Comparable, Constabl COMMON, // 2B76..2B95 UNKNOWN, // 2B96 COMMON, // 2B97..2BFF - GLAGOLITIC, // 2C00..2C2E - UNKNOWN, // 2C2F - GLAGOLITIC, // 2C30..2C5E - UNKNOWN, // 2C5F + GLAGOLITIC, // 2C00..2C5F LATIN, // 2C60..2C7F COPTIC, // 2C80..2CF3 UNKNOWN, // 2CF4..2CF8 @@ -7385,8 +7592,8 @@ class Character implements java.io.Serializable, Comparable, Constabl ETHIOPIC, // 2DD8..2DDE UNKNOWN, // 2DDF CYRILLIC, // 2DE0..2DFF - COMMON, // 2E00..2E52 - UNKNOWN, // 2E53..2E7F + COMMON, // 2E00..2E5D + UNKNOWN, // 2E5E..2E7F HAN, // 2E80..2E99 UNKNOWN, // 2E9A HAN, // 2E9B..2EF3 @@ -7437,8 +7644,7 @@ class Character implements java.io.Serializable, Comparable, Constabl COMMON, // 3358..33FF HAN, // 3400..4DBF COMMON, // 4DC0..4DFF - HAN, // 4E00..9FFC - UNKNOWN, // 9FFD..9FFF + HAN, // 4E00..9FFF YI, // A000..A48C UNKNOWN, // A48D..A48F YI, // A490..A4C6 @@ -7452,11 +7658,15 @@ class Character implements java.io.Serializable, Comparable, Constabl COMMON, // A700..A721 LATIN, // A722..A787 COMMON, // A788..A78A - LATIN, // A78B..A7BF - UNKNOWN, // A7C0..A7C1 - LATIN, // A7C2..A7CA - UNKNOWN, // A7CB..A7F4 - LATIN, // A7F5..A7FF + LATIN, // A78B..A7CA + UNKNOWN, // A7CB..A7CF + LATIN, // A7D0..A7D1 + UNKNOWN, // A7D2 + LATIN, // A7D3 + UNKNOWN, // A7D4 + LATIN, // A7D5..A7D9 + UNKNOWN, // A7DA..A7F1 + LATIN, // A7F2..A7FF SYLOTI_NAGRI, // A800..A82C UNKNOWN, // A82D..A82F COMMON, // A830..A839 @@ -7544,17 +7754,17 @@ class Character implements java.io.Serializable, Comparable, Constabl HEBREW, // FB43..FB44 UNKNOWN, // FB45 HEBREW, // FB46..FB4F - ARABIC, // FB50..FBC1 - UNKNOWN, // FBC2..FBD2 + ARABIC, // FB50..FBC2 + UNKNOWN, // FBC3..FBD2 ARABIC, // FBD3..FD3D COMMON, // FD3E..FD3F - UNKNOWN, // FD40..FD4F - ARABIC, // FD50..FD8F + ARABIC, // FD40..FD8F UNKNOWN, // FD90..FD91 ARABIC, // FD92..FDC7 - UNKNOWN, // FDC8..FDEF - ARABIC, // FDF0..FDFD - UNKNOWN, // FDFE..FDFF + UNKNOWN, // FDC8..FDCE + ARABIC, // FDCF + UNKNOWN, // FDD0..FDEF + ARABIC, // FDF0..FDFF INHERITED, // FE00..FE0F COMMON, // FE10..FE19 UNKNOWN, // FE1A..FE1F @@ -7661,13 +7871,34 @@ class Character implements java.io.Serializable, Comparable, Constabl CAUCASIAN_ALBANIAN, // 10530..10563 UNKNOWN, // 10564..1056E CAUCASIAN_ALBANIAN, // 1056F - UNKNOWN, // 10570..105FF + VITHKUQI, // 10570..1057A + UNKNOWN, // 1057B + VITHKUQI, // 1057C..1058A + UNKNOWN, // 1058B + VITHKUQI, // 1058C..10592 + UNKNOWN, // 10593 + VITHKUQI, // 10594..10595 + UNKNOWN, // 10596 + VITHKUQI, // 10597..105A1 + UNKNOWN, // 105A2 + VITHKUQI, // 105A3..105B1 + UNKNOWN, // 105B2 + VITHKUQI, // 105B3..105B9 + UNKNOWN, // 105BA + VITHKUQI, // 105BB..105BC + UNKNOWN, // 105BD..105FF LINEAR_A, // 10600..10736 UNKNOWN, // 10737..1073F LINEAR_A, // 10740..10755 UNKNOWN, // 10756..1075F LINEAR_A, // 10760..10767 - UNKNOWN, // 10768..107FF + UNKNOWN, // 10768..1077F + LATIN, // 10780..10785 + UNKNOWN, // 10786 + LATIN, // 10787..107B0 + UNKNOWN, // 107B1 + LATIN, // 107B2..107BA + UNKNOWN, // 107BB..107FF CYPRIOT, // 10800..10805 UNKNOWN, // 10806..10807 CYPRIOT, // 10808 @@ -7765,18 +7996,20 @@ class Character implements java.io.Serializable, Comparable, Constabl OLD_SOGDIAN, // 10F00..10F27 UNKNOWN, // 10F28..10F2F SOGDIAN, // 10F30..10F59 - UNKNOWN, // 10F5A..10FAF + UNKNOWN, // 10F5A..10F6F + OLD_UYGHUR, // 10F70..10F89 + UNKNOWN, // 10F8A..10FAF CHORASMIAN, // 10FB0..10FCB UNKNOWN, // 10FCC..10FDF ELYMAIC, // 10FE0..10FF6 UNKNOWN, // 10FF7..10FFF BRAHMI, // 11000..1104D UNKNOWN, // 1104E..11051 - BRAHMI, // 11052..1106F - UNKNOWN, // 11070..1107E + BRAHMI, // 11052..11075 + UNKNOWN, // 11076..1107E BRAHMI, // 1107F - KAITHI, // 11080..110C1 - UNKNOWN, // 110C2..110CC + KAITHI, // 11080..110C2 + UNKNOWN, // 110C3..110CC KAITHI, // 110CD UNKNOWN, // 110CE..110CF SORA_SOMPENG, // 110D0..110E8 @@ -7860,16 +8093,16 @@ class Character implements java.io.Serializable, Comparable, Constabl UNKNOWN, // 1165A..1165F MONGOLIAN, // 11660..1166C UNKNOWN, // 1166D..1167F - TAKRI, // 11680..116B8 - UNKNOWN, // 116B9..116BF + TAKRI, // 11680..116B9 + UNKNOWN, // 116BA..116BF TAKRI, // 116C0..116C9 UNKNOWN, // 116CA..116FF AHOM, // 11700..1171A UNKNOWN, // 1171B..1171C AHOM, // 1171D..1172B UNKNOWN, // 1172C..1172F - AHOM, // 11730..1173F - UNKNOWN, // 11740..117FF + AHOM, // 11730..11746 + UNKNOWN, // 11747..117FF DOGRA, // 11800..1183B UNKNOWN, // 1183C..1189F WARANG_CITI, // 118A0..118F2 @@ -7900,7 +8133,8 @@ class Character implements java.io.Serializable, Comparable, Constabl ZANABAZAR_SQUARE, // 11A00..11A47 UNKNOWN, // 11A48..11A4F SOYOMBO, // 11A50..11AA2 - UNKNOWN, // 11AA3..11ABF + UNKNOWN, // 11AA3..11AAF + CANADIAN_ABORIGINAL, // 11AB0..11ABF PAU_CIN_HAU, // 11AC0..11AF8 UNKNOWN, // 11AF9..11BFF BHAIKSUKI, // 11C00..11C08 @@ -7957,7 +8191,9 @@ class Character implements java.io.Serializable, Comparable, Constabl CUNEIFORM, // 12470..12474 UNKNOWN, // 12475..1247F CUNEIFORM, // 12480..12543 - UNKNOWN, // 12544..12FFF + UNKNOWN, // 12544..12F8F + CYPRO_MINOAN, // 12F90..12FF2 + UNKNOWN, // 12FF3..12FFF EGYPTIAN_HIEROGLYPHS, // 13000..1342E UNKNOWN, // 1342F EGYPTIAN_HIEROGLYPHS, // 13430..13438 @@ -7971,7 +8207,10 @@ class Character implements java.io.Serializable, Comparable, Constabl MRO, // 16A60..16A69 UNKNOWN, // 16A6A..16A6D MRO, // 16A6E..16A6F - UNKNOWN, // 16A70..16ACF + TANGSA, // 16A70..16ABE + UNKNOWN, // 16ABF + TANGSA, // 16AC0..16AC9 + UNKNOWN, // 16ACA..16ACF BASSA_VAH, // 16AD0..16AED UNKNOWN, // 16AEE..16AEF BASSA_VAH, // 16AF0..16AF5 @@ -7996,7 +8235,7 @@ class Character implements java.io.Serializable, Comparable, Constabl UNKNOWN, // 16FA0..16FDF TANGUT, // 16FE0 NUSHU, // 16FE1 - COMMON, // 16FE2..16FE3 + HAN, // 16FE2..16FE3 KHITAN_SMALL_SCRIPT, // 16FE4 UNKNOWN, // 16FE5..16FEF HAN, // 16FF0..16FF1 @@ -8007,10 +8246,17 @@ class Character implements java.io.Serializable, Comparable, Constabl KHITAN_SMALL_SCRIPT, // 18B00..18CD5 UNKNOWN, // 18CD6..18CFF TANGUT, // 18D00..18D08 - UNKNOWN, // 18D09..1AFFF + UNKNOWN, // 18D09..1AFEF + KATAKANA, // 1AFF0..1AFF3 + UNKNOWN, // 1AFF4 + KATAKANA, // 1AFF5..1AFFB + UNKNOWN, // 1AFFC + KATAKANA, // 1AFFD..1AFFE + UNKNOWN, // 1AFFF KATAKANA, // 1B000 - HIRAGANA, // 1B001..1B11E - UNKNOWN, // 1B11F..1B14F + HIRAGANA, // 1B001..1B11F + KATAKANA, // 1B120..1B122 + UNKNOWN, // 1B123..1B14F HIRAGANA, // 1B150..1B152 UNKNOWN, // 1B153..1B163 KATAKANA, // 1B164..1B167 @@ -8027,7 +8273,13 @@ class Character implements java.io.Serializable, Comparable, Constabl UNKNOWN, // 1BC9A..1BC9B DUPLOYAN, // 1BC9C..1BC9F COMMON, // 1BCA0..1BCA3 - UNKNOWN, // 1BCA4..1CFFF + UNKNOWN, // 1BCA4..1CEFF + INHERITED, // 1CF00..1CF2D + UNKNOWN, // 1CF2E..1CF2F + INHERITED, // 1CF30..1CF46 + UNKNOWN, // 1CF47..1CF4F + COMMON, // 1CF50..1CFC3 + UNKNOWN, // 1CFC4..1CFFF COMMON, // 1D000..1D0F5 UNKNOWN, // 1D0F6..1D0FF COMMON, // 1D100..1D126 @@ -8040,8 +8292,8 @@ class Character implements java.io.Serializable, Comparable, Constabl INHERITED, // 1D185..1D18B COMMON, // 1D18C..1D1A9 INHERITED, // 1D1AA..1D1AD - COMMON, // 1D1AE..1D1E8 - UNKNOWN, // 1D1E9..1D1FF + COMMON, // 1D1AE..1D1EA + UNKNOWN, // 1D1EB..1D1FF GREEK, // 1D200..1D245 UNKNOWN, // 1D246..1D2DF COMMON, // 1D2E0..1D2F3 @@ -8096,7 +8348,9 @@ class Character implements java.io.Serializable, Comparable, Constabl SIGNWRITING, // 1DA9B..1DA9F UNKNOWN, // 1DAA0 SIGNWRITING, // 1DAA1..1DAAF - UNKNOWN, // 1DAB0..1DFFF + UNKNOWN, // 1DAB0..1DEFF + LATIN, // 1DF00..1DF1E + UNKNOWN, // 1DF1F..1DFFF GLAGOLITIC, // 1E000..1E006 UNKNOWN, // 1E007 GLAGOLITIC, // 1E008..1E018 @@ -8114,11 +8368,21 @@ class Character implements java.io.Serializable, Comparable, Constabl NYIAKENG_PUACHUE_HMONG, // 1E140..1E149 UNKNOWN, // 1E14A..1E14D NYIAKENG_PUACHUE_HMONG, // 1E14E..1E14F - UNKNOWN, // 1E150..1E2BF + UNKNOWN, // 1E150..1E28F + TOTO, // 1E290..1E2AE + UNKNOWN, // 1E2AF..1E2BF WANCHO, // 1E2C0..1E2F9 UNKNOWN, // 1E2FA..1E2FE WANCHO, // 1E2FF - UNKNOWN, // 1E300..1E7FF + UNKNOWN, // 1E300..1E7DF + ETHIOPIC, // 1E7E0..1E7E6 + UNKNOWN, // 1E7E7 + ETHIOPIC, // 1E7E8..1E7EB + UNKNOWN, // 1E7EC + ETHIOPIC, // 1E7ED..1E7EE + UNKNOWN, // 1E7EF + ETHIOPIC, // 1E7F0..1E7FE + UNKNOWN, // 1E7FF MENDE_KIKAKUI, // 1E800..1E8C4 UNKNOWN, // 1E8C5..1E8C6 MENDE_KIKAKUI, // 1E8C7..1E8D6 @@ -8228,8 +8492,8 @@ class Character implements java.io.Serializable, Comparable, Constabl COMMON, // 1F260..1F265 UNKNOWN, // 1F266..1F2FF COMMON, // 1F300..1F6D7 - UNKNOWN, // 1F6D8..1F6DF - COMMON, // 1F6E0..1F6EC + UNKNOWN, // 1F6D8..1F6DC + COMMON, // 1F6DD..1F6EC UNKNOWN, // 1F6ED..1F6EF COMMON, // 1F6F0..1F6FC UNKNOWN, // 1F6FD..1F6FF @@ -8238,7 +8502,9 @@ class Character implements java.io.Serializable, Comparable, Constabl COMMON, // 1F780..1F7D8 UNKNOWN, // 1F7D9..1F7DF COMMON, // 1F7E0..1F7EB - UNKNOWN, // 1F7EC..1F7FF + UNKNOWN, // 1F7EC..1F7EF + COMMON, // 1F7F0 + UNKNOWN, // 1F7F1..1F7FF COMMON, // 1F800..1F80B UNKNOWN, // 1F80C..1F80F COMMON, // 1F810..1F847 @@ -8251,38 +8517,38 @@ class Character implements java.io.Serializable, Comparable, Constabl UNKNOWN, // 1F8AE..1F8AF COMMON, // 1F8B0..1F8B1 UNKNOWN, // 1F8B2..1F8FF - COMMON, // 1F900..1F978 - UNKNOWN, // 1F979 - COMMON, // 1F97A..1F9CB - UNKNOWN, // 1F9CC - COMMON, // 1F9CD..1FA53 + COMMON, // 1F900..1FA53 UNKNOWN, // 1FA54..1FA5F COMMON, // 1FA60..1FA6D UNKNOWN, // 1FA6E..1FA6F COMMON, // 1FA70..1FA74 UNKNOWN, // 1FA75..1FA77 - COMMON, // 1FA78..1FA7A - UNKNOWN, // 1FA7B..1FA7F + COMMON, // 1FA78..1FA7C + UNKNOWN, // 1FA7D..1FA7F COMMON, // 1FA80..1FA86 UNKNOWN, // 1FA87..1FA8F - COMMON, // 1FA90..1FAA8 - UNKNOWN, // 1FAA9..1FAAF - COMMON, // 1FAB0..1FAB6 - UNKNOWN, // 1FAB7..1FABF - COMMON, // 1FAC0..1FAC2 - UNKNOWN, // 1FAC3..1FACF - COMMON, // 1FAD0..1FAD6 - UNKNOWN, // 1FAD7..1FAFF + COMMON, // 1FA90..1FAAC + UNKNOWN, // 1FAAD..1FAAF + COMMON, // 1FAB0..1FABA + UNKNOWN, // 1FABB..1FABF + COMMON, // 1FAC0..1FAC5 + UNKNOWN, // 1FAC6..1FACF + COMMON, // 1FAD0..1FAD9 + UNKNOWN, // 1FADA..1FADF + COMMON, // 1FAE0..1FAE7 + UNKNOWN, // 1FAE8..1FAEF + COMMON, // 1FAF0..1FAF6 + UNKNOWN, // 1FAF7..1FAFF COMMON, // 1FB00..1FB92 UNKNOWN, // 1FB93 COMMON, // 1FB94..1FBCA UNKNOWN, // 1FBCB..1FBEF COMMON, // 1FBF0..1FBF9 UNKNOWN, // 1FBFA..1FFFF - HAN, // 20000..2A6DD - UNKNOWN, // 2A6DE..2A6FF - HAN, // 2A700..2B734 - UNKNOWN, // 2B735..2B73F + HAN, // 20000..2A6DF + UNKNOWN, // 2A6E0..2A6FF + HAN, // 2A700..2B738 + UNKNOWN, // 2B739..2B73F HAN, // 2B740..2B81D UNKNOWN, // 2B81E..2B81F HAN, // 2B820..2CEA1 @@ -8303,7 +8569,7 @@ class Character implements java.io.Serializable, Comparable, Constabl private static final HashMap aliases; static { - aliases = new HashMap<>((int)(157 / 0.75f + 1.0f)); + aliases = new HashMap<>((int)(162 / 0.75f + 1.0f)); aliases.put("ADLM", ADLAM); aliases.put("AGHB", CAUCASIAN_ALBANIAN); aliases.put("AHOM", AHOM); @@ -8329,6 +8595,7 @@ class Character implements java.io.Serializable, Comparable, Constabl aliases.put("CHER", CHEROKEE); aliases.put("CHRS", CHORASMIAN); aliases.put("COPT", COPTIC); + aliases.put("CPMN", CYPRO_MINOAN); aliases.put("CPRT", CYPRIOT); aliases.put("CYRL", CYRILLIC); aliases.put("DEVA", DEVANAGARI); @@ -8409,6 +8676,7 @@ class Character implements java.io.Serializable, Comparable, Constabl aliases.put("ORYA", ORIYA); aliases.put("OSGE", OSAGE); aliases.put("OSMA", OSMANYA); + aliases.put("OUGR", OLD_UYGHUR); aliases.put("PALM", PALMYRENE); aliases.put("PAUC", PAU_CIN_HAU); aliases.put("PERM", OLD_PERMIC); @@ -8451,8 +8719,11 @@ class Character implements java.io.Serializable, Comparable, Constabl aliases.put("THAI", THAI); aliases.put("TIBT", TIBETAN); aliases.put("TIRH", TIRHUTA); + aliases.put("TNSA", TANGSA); + aliases.put("TOTO", TOTO); aliases.put("UGAR", UGARITIC); aliases.put("VAII", VAI); + aliases.put("VITH", VITHKUQI); aliases.put("WARA", WARANG_CITI); aliases.put("WCHO", WANCHO); aliases.put("XPEO", OLD_PERSIAN); @@ -8495,8 +8766,8 @@ class Character implements java.io.Serializable, Comparable, Constabl /** * Returns the UnicodeScript constant with the given Unicode script * name or the script name alias. Script names and their aliases are - * determined by The Unicode Standard. The files {@code Scripts.txt} - * and {@code PropertyValueAliases.txt} define script names + * determined by The Unicode Standard. The files {@code Scripts.txt} + * and {@code PropertyValueAliases.txt} define script names * and the script name aliases for a particular version of the * standard. The {@link Character} class specifies the version of * the standard that it supports. diff --git a/src/java.base/share/classes/java/util/regex/Grapheme.java b/src/java.base/share/classes/java/util/regex/Grapheme.java index efc92158dfe..9922cab121a 100644 --- a/src/java.base/share/classes/java/util/regex/Grapheme.java +++ b/src/java.base/share/classes/java/util/regex/Grapheme.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,8 +35,8 @@ final class Grapheme { *

* See Unicode Standard Annex #29 Unicode Text Segmentation for the specification * for the extended grapheme cluster boundary rules. The following implementation - * is based on version 12.0 of the annex. - * (http://www.unicode.org/reports/tr29/tr29-35.html) + * is based on the annex for Unicode version 14.0. + * (http://www.unicode.org/reports/tr29/tr29-38.html) * * @param src the {@code CharSequence} to be scanned * @param off offset to start looking for the next boundary in the src @@ -97,7 +97,7 @@ final class Grapheme { private static final int FIRST_TYPE = 0; private static final int LAST_TYPE = 14; - private static boolean[][] rules; + private static final boolean[][] rules; static { rules = new boolean[LAST_TYPE + 1][LAST_TYPE + 1]; // GB 999 Any + Any -> default @@ -201,8 +201,9 @@ final class Grapheme { if (cp == 0x200D) return ZWJ; if (cp >= 0x0600 && cp <= 0x0605 || - cp == 0x06DD || cp == 0x070F || cp == 0x08E2 || - cp == 0x110BD || cp == 0x110CD) + cp == 0x06DD || cp == 0x070F || + cp == 0x0890 || cp == 0x0891 || + cp == 0x08E2 || cp == 0x110BD || cp == 0x110CD) return PREPEND; return CONTROL; case Character.NON_SPACING_MARK: diff --git a/src/java.base/share/classes/jdk/internal/icu/impl/Punycode.java b/src/java.base/share/classes/jdk/internal/icu/impl/Punycode.java index 52f6e546f3a..6fe1ebcc546 100644 --- a/src/java.base/share/classes/jdk/internal/icu/impl/Punycode.java +++ b/src/java.base/share/classes/jdk/internal/icu/impl/Punycode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -76,9 +76,6 @@ public final class Punycode { // TODO: eliminate the 256 limitation private static final int MAX_CP_COUNT = 256; - private static final int UINT_MAGIC = 0x80000000; - private static final long ULONG_MAGIC = 0x8000000000000000L; - private static int adaptBias(int delta, int length, boolean firstTime){ if(firstTime){ delta /=DAMP; @@ -96,34 +93,25 @@ public final class Punycode { } /** - * basicToDigit[] contains the numeric value of a basic code - * point (for use in representing integers) in the range 0 to - * BASE-1, or -1 if b is does not represent a value. + * @return the numeric value of a basic code point (for use in representing integers) + * in the range 0 to BASE-1, or a negative value if cp is invalid. */ - static final int[] basicToDigit= new int[]{ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, -1, - - -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, - - -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, - - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 + private static final int decodeDigit(int cp) { + if(cp<='Z') { + if(cp<='9') { + if(cp<'0') { + return -1; + } else { + return cp-'0'+26; // 0..9 -> 26..35 + } + } else { + return cp-'A'; // A-Z -> 0..25 + } + } else if(cp<='z') { + return cp-'a'; // a..z -> 0..25 + } else { + return -1; + } }; private static char asciiCaseMap(char b, boolean uppercase) { @@ -158,6 +146,12 @@ public final class Punycode { return (char)((ZERO-26)+digit); } } + + // ICU-13727: Limit input length for n^2 algorithm + // where well-formed strings are at most 59 characters long. + private static final int ENCODE_MAX_CODE_UNITS = 1000; + private static final int DECODE_MAX_CHARS = 2000; + /** * Converts Unicode to Punycode. * The input string must not contain single, unpaired surrogates. @@ -174,6 +168,10 @@ public final class Punycode { int n, delta, handledCPCount, basicLength, destLength, bias, j, m, q, k, t, srcCPCount; char c, c2; int srcLength = src.length(); + if (srcLength > ENCODE_MAX_CODE_UNITS) { + throw new RuntimeException( + "input too long: " + srcLength + " UTF-16 code units"); + } int destCapacity = MAX_CP_COUNT; char[] dest = new char[destCapacity]; StringBuffer result = new StringBuffer(); @@ -251,7 +249,7 @@ public final class Punycode { * Increase delta enough to advance the decoder's * state to , but guard against overflow: */ - if(m-n>(0x7fffffff-MAX_CP_COUNT-delta)/(handledCPCount+1)) { + if(m-n>(0x7fffffff-handledCPCount-delta)/(handledCPCount+1)) { throw new RuntimeException("Internal program error"); } delta+=(m-n)*(handledCPCount+1); @@ -332,6 +330,9 @@ public final class Punycode { public static StringBuffer decode(StringBuffer src, boolean[] caseFlags) throws ParseException{ int srcLength = src.length(); + if (srcLength > DECODE_MAX_CHARS) { + throw new RuntimeException("input too long: " + srcLength + " characters"); + } StringBuffer result = new StringBuffer(); int n, destLength, i, bias, basicLength, j, in, oldi, w, k, digit, t, destCPCount, firstSupplementaryIndex, cpLength; @@ -395,7 +396,7 @@ public final class Punycode { throw new ParseException("Illegal char found", -1); } - digit=basicToDigit[(byte)src.charAt(in++)]; + digit=decodeDigit(src.charAt(in++)); if(digit<0) { throw new ParseException("Invalid char found", -1); } diff --git a/src/java.base/share/classes/jdk/internal/icu/impl/UnicodeSetStringSpan.java b/src/java.base/share/classes/jdk/internal/icu/impl/UnicodeSetStringSpan.java index ee5e80dd883..331ab234f59 100644 --- a/src/java.base/share/classes/jdk/internal/icu/impl/UnicodeSetStringSpan.java +++ b/src/java.base/share/classes/jdk/internal/icu/impl/UnicodeSetStringSpan.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, 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 @@ -134,9 +134,15 @@ public class UnicodeSetStringSpan { int i, spanLength; someRelevant = false; - for (i = 0; i < stringsLength; ++i) { + for (i = 0; i < stringsLength;) { String string = strings.get(i); int length16 = string.length(); + if (length16 == 0) { + // Remove the empty string. + strings.remove(i); + --stringsLength; + continue; + } spanLength = spanSet.span(string, SpanCondition.CONTAINED); if (spanLength < length16) { // Relevant string. someRelevant = true; @@ -144,6 +150,7 @@ public class UnicodeSetStringSpan { if (/* (0 != (which & UTF16)) && */ length16 > maxLength16) { maxLength16 = length16; } + ++i; } if (!someRelevant && (which & WITH_COUNT) == 0) { return; diff --git a/src/java.base/share/classes/jdk/internal/icu/impl/data/icudt67b/uprops.icu b/src/java.base/share/classes/jdk/internal/icu/impl/data/icudt67b/uprops.icu deleted file mode 100644 index ee08ff5b011d49d5866413c5856f37f58b0ab8cc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 135664 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

ngp%RM_Lo+r~Rk8fO=eo^~3vttUsnd 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 Lc&&rh4J`c&#^rf8 delta 1421 zcmb_cT}Tu`9N(KeclY-89P?NGE0xQC(X71cndJE^z%>VQE|NnPpcHUrc zuLqn{OC)B|sArhXHyEZ%Wtda{%=5L?&KG9-eEX(7z+%s^PdGPM$Q|Uaag)50ujLB) zqx>~~3Rv!lyV~9A?sh)~mf#ffh5f=I;fnCoBX~A>Iz1PG{jMsVy5IC8e~i$~)z5`I!QgGM=Y)C6@In{mQsE&l~ghd&hJ0a$~vu zx#QI1^ZC}1^@#7PZ^EDFkNNxjL)Z&yD*RuvKzkMM0!x+2BqbM<+N}-;*uaK_7xX)E zxr6TroD4h&OxRHxqLQ{=Yt^psqIM^v4eOcqNWO@^QLoqc=#Baoy+Pl%1X{<^r1|eG z9ZT{R|6N`WEZ)RkVCm_gLXOAfP=j^Bv%!&&5~>TG4UL4Aa7DNoM;vM-++&|tmb1Iq zID3q}z~0JGl3a>4z%z!Q^J}?>G$j0z;(#3A-S29;5G`cg1i1Y8etRv4IX#-Y>Um|X|B(f3Gf2E zPTMNsN8xRFKkK0N7ZQB3P~)a30KmtDnI-V`d^ht^{MM|@ed4BVEBB57N`QNiu!!hM z|FuukL<0PnHORAcA2s;X_Rn+p3t#e-h9mQvNY0MxOQc(e_L{Zd$;;036qFywBk|>4JXcEns zE>krN%t|wAHkfg<#q2bD%>grMrbw?fxJ|hy@e|A6yfKqEHX7biW(Aag@X=!yQq;k%*3tY9sn3eB3ial g!>?A$iLq!OmuT5?xF+Y()PW6g{J!fue|>KJ0rN0D-T(jq diff --git a/src/java.base/share/classes/jdk/internal/icu/impl/data/icudt67b/nfkc.nrm b/src/java.base/share/classes/jdk/internal/icu/impl/data/icudt70b/nfkc.nrm similarity index 67% rename from src/java.base/share/classes/jdk/internal/icu/impl/data/icudt67b/nfkc.nrm rename to src/java.base/share/classes/jdk/internal/icu/impl/data/icudt70b/nfkc.nrm index 2c0587b6d455a6221287faf70600adcea6a7ef7b..450b6ed323b8ecd52cffd1f91c59bc284fdeb161 100644 GIT binary patch delta 4912 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 CJ6A^l delta 4453 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

raxrAItZX*vyJVT>Qj7FdeVJDgV=|FBU3XMaP z&{1esV0BEaSg|0_8qFc~yL$skCXb9bl?nArKL+BCoINFPT zf%XN_^XNtNGI|aD7QKbuvOhrYpabY2CblPFGE9ZVRL;W^uoNr}%ffOoEe2p_tO$Dw zvtkpGYODftVAWU+hF}E7U|uYM)naq81=u2i2CNZVR*{A^V=FNpTZ?TNJBV$mluzu_kb_KhR-NNo*1K8l?DqLJ_#uWlFc!EF* zo`!31Ee_yjya>18W%zi!9IwQy>{@&}?!*zCaDX_0Gj=oX#RGUPKG$AUejZJkS5c`Pz!~vq) zfe=TDlf)N9A90?zL|h}jbr8fY;tnxD43c6}Mykj-GKowhv&ejhm(-IWSwvdMGIAnW zNmh~5$r=(8z(~qbOS(xvIh(8_=aGxZh6*j&NH&ozd zp|(@)R0kEJ_EP(({nR1qDAkL{P-m!fR6lizx5bUWQahe}%Mz4S+P7k!96LLaAl=`-|s`XYVVvEOl^?ljC@KZhZf9^X&@m-xsvhJ@ryN^Hq`EBLS$Im|j DjXbH8 diff --git a/src/java.base/share/classes/jdk/internal/icu/impl/data/icudt67b/ubidi.icu b/src/java.base/share/classes/jdk/internal/icu/impl/data/icudt70b/ubidi.icu similarity index 63% rename from src/java.base/share/classes/jdk/internal/icu/impl/data/icudt67b/ubidi.icu rename to src/java.base/share/classes/jdk/internal/icu/impl/data/icudt70b/ubidi.icu index bec7b093064530bb5049258a4280cf55a113ec8a..b125866b8e2d907c50bcd715e3174bbf1796c03a 100644 GIT binary patch literal 27328 zcmeHQ4Uk=BdH(L6|8wq5HoHlnA<1rTA|%T$VuYkZgiR16=qi6|3@S-PAN|DhHb)d7;;xu*o6KPYy3iN%y_q_Z4obQ}_ z?p=OnbiZ%TdHwVSxmiImH z@4YGSOU~^_-ecZRy#Mfydrx~$`3*nu7x+zoA^ZAE{Z-5(^+)`*{#pJe|04fVf2+U4 zzsA4Lf4{%m|3iPDf2;o)|1SS-|6c!_{saDZ{fGS@`~U1e;Xmd7G-w1~kOhOmNx{-! zRWKTy0dzyKQPR!9C7^$EupR6>y{X{(;Jv}`2fKosf?Gg;TkzRn&|eOo1=bHoe@yo91HmVvkAvTzVW#i~))r~>=SmmtM?ShI zy3ekUeWJgK9*Q1`4o63$W6_h*vvC;DiwB}O+I(8tw5kCnOS03Miy7;d6ZluBA!aezSq~>1ojlUV+ zAD$n}zoWq&@sGgwvG{TDY{dTt`z0X%EPg6j3iRpVq$HrIB+Kal(YgIx2j)63*MVRC z4kRZhOOoaA?YVR&rzPvinw*`So4h)CeR5fHMXtFrx!Suec~|m2>Qn;X*1ZM7#AYGI$^EU)1r7uZG)0g|p z)3fC>%|^P(n@TSPc_MuSt}NZk>x-dsrvs52t%2{X}qM z`f0$q6Qyu|DxZq7XL=8FMANUP`SZl|I}rCk`e6DG5c`p_=IL^8dVRjlvzsYAU(Do_$Bdsl&Jq#M{4=w2W>-}Y z(Z{n30^yF!UYETwdkd^{2VR}owaQD%`4elUt;c2W2SoS`lKmcRAB63r*~dCY9?x#| zj%T0F{v!KAN8cWfL-v*IuT0#sGbDX4RQzqzclMHg_sEX;8?qn3blz)pPn*v_BjVi+ zJ}GAUJ<0gwm>snv;piU2V;b(tj%QEBTbd2;h&R=YU~8(?MIT~b`l5div$+uN^Asna z%r}=dS7G+%C~RjmUx7KCxVxGgn-k4Tn_HWk+1`XRGx~T_J2Sb$ZfH~9OS_49Zhf2A zH}^Dekn@90IpH@PZ8kqj+81x{eFUc%D9l(yA{Ghki#DZ+z)pUtNQEyaa4&;DAs~Aq zlv@Zte->vb(u=|CA@oe`A2;jBmq6UZ6g|86fjZfqS0BBjim%T>FZ1sEvYWD_`*43q z%6Me(2wi*N|P;*xt{dT%OhJ-Sbz08=30D&iL?Rhgr*WDIqrDt9=7BFXRk_nz-VYyvwxU zzTT48hkL!P_={l2IRV?=d`g3VlS0LMeuVE0j0T8u0H74FMB%ts4p+5Do+YIlZL zOtrJbUK0>Q8}9WA%X!T2LPN~GauRyk9(~w`oRSqs_Og}sqIa*S8p(AnZxpkg#Y!*_ zUcWe3$U6w$Th!f)Ii`rt|Yw)HR*` z36uPkx86w|&&BIeMZ4W2L{_utUr)n5R%mvd-JkL*ZBHAiN-mErw-oXCj*S$**QvoM zOqHcO4&$loDvo778p?uPRln+2qpwU~mzk@xL>VUyM_nqf)(9yPs-x}IQopc6bq0A+ z4DUJ4zBbs-l>Mrx3m@a%gOSTU+;Ob!J`O998$K(N&x;tVn(CF>JfF){jaifJOR^r} z_UNRou2$hI4iQPhSdu!S*mgaNDzrUpnY_x5KYEi*M^;)JP03Y=%B!5KSG{?^AW6rZ z%{>Hh5*@5A-^E#rko8t-Ca0r8k-RrO^y9`JikiN7U!mhQE@nFq0z&;^9>0s^_mGji zBLjI&RcPH;YolRLx<{c-G8Rh3Vd~5XJ}+_ovmIs+dy~4Wf!AxUuoDJ)Qx|woXC0xi zj;W5uI-R1ubACO-#p_wBc(e9SnTwgKvB@8OkfVL)wJ|0~kjzqbyj>y2Qf@|dQ?AsG zS29=68pbi}VF|rvH}LwQbKZ?pWy6R%cJ@j|nE!&+-Bp&ruPrLQ2!9L|H^$oLab0)L5$^N>H_uZ<_;JMvYOR|UV<#RuZM<9p&S#9xA^wDgM{?(>+_ z(_?zHUI+7fJ$bpMMB(?w@!3;Gu~v0dh;tRAyp&a6Cq}A`eC$uz97#E))UPnus#l|U zoF9n0Au* z+~%xQEql5$U!Sf`f0iC9bOdAekf)vz3S)7l z%8T;vlQk)9^vBvvOw{6r(K-VAu{T!KX(9qmj8cfmaUO+>8YS_%bxj=}^O=4+uBwOq zm|_gq^juJ?!ba*ohgu6F?z7gWtPT#Z_ip^rxBCbqgRGD5GbR>m=~E3$L=6nn)U|}a z?#>)ZT0fluv@h=n+mZ4$#I!uhW#K5M;Df_lWj(3es50(!yQPDSGHK@@A9*t-)b+W+hcYDwCV5imkE{T9pUe+<95cUN-GyxBW@36GcAm zcw5V7f_jI7HQgNr8<%9nu!nwz*|sv7QJCU4^ZJ9T;Lepr;UH&AivDhgi?7OEZNs-*8pgXLF8nGTUmI1lDqh*r%6GK! zEn?+sbCjLVmGZr-M!i4fkz{ej>pFaYIRrr5OTGRVGkRKw8+7!}o5J8+N>h)cIQBg#-Bzc;t1{3JB0BUl)7L&Sz%`2cNxuW>fk^57T zTU*58>d=C`J=l&G#S>@yR>?)=YVSI^*awm7;;YJeMS2|yg|V6HUY&W4QrYzGmB+Kc zs-xUjx77F7E7QA%da6;!?UrYBJ#Mzh6t5#z@mv8@^re**uPWA5;n_CAB2>^d|gnq7=S;Hdo6k zt}70HEvr4c@nz7Gm|niG+cA9X>QOGJ%A0+dy00v^mSb$H^4aI9vJhuS+Op~22@Sn* zxT18eouyo6q;e0m;J<6Go{U4Z=(|yVOY41a;@{Ds8kN8N8!K6qr<>~(kJoRNPuca& z{Vubcdh|9mw$#aPUuPsM6t1U=D(^b?mpVS3s@5|Suj(t>>S+`La%C~>)oB%WJjXG$ z?I`QRw(Bqdvq6jGkxNeN5$lt zPm059CdKYGcQ&@IxlfF*Io{Yk@=uM!BmdHv9C^GkJ@OMVJ@TJo+o{it3C|n##yt3c zPW)D@6^27YD_5>qv3hl*k!9=GuNTR(!Nn&o=^q^%;}um1#QzEkZ{51>?QgsC&D*bd%MQ6ZIQ;ei z{X2zN(ptSbySmT;IO|p?%NCzFHa0Z+3K6cz-Z0b{Tn1ep8hhiGHvw&BjV-O#;tV3s z+OT1K{FUNTarxy!Y<&G?=bd-ntIoOj{0m-t_SqL+_?pd|H(w;+@xL6eKKFH(Y$_z1 cQ~a8D;2pI7oXj-iDk0t>u7WA9`g}hAA5~vR{r~^~ literal 26640 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%0DXpv4t8s*< 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 * Further detail on differences can be determined using the program * + * "https://github.com/unicode-org/icu/blob/main/icu4j/main/tests/core/src/com/ibm/icu/dev/test/lang/UCharacterCompare.java"> * com.ibm.icu.dev.test.lang.UCharacterCompare *

*

@@ -101,9 +101,9 @@ import jdk.internal.icu.util.VersionInfo; * For more information see * "About the Unicode Character Database" * (http://www.unicode.org/ucd/) - * and the ICU + * and the ICU * User Guide chapter on Properties - * (http://www.icu-project.org/userguide/properties.html). + * (https://unicode-org.github.io/icu/userguide/strings/properties). *

*

* There are also functions that provide easy migration from C/POSIX functions diff --git a/src/java.base/share/classes/jdk/internal/icu/lang/UCharacterDirection.java b/src/java.base/share/classes/jdk/internal/icu/lang/UCharacterDirection.java index db9beb0c3ac..22b878155bb 100644 --- a/src/java.base/share/classes/jdk/internal/icu/lang/UCharacterDirection.java +++ b/src/java.base/share/classes/jdk/internal/icu/lang/UCharacterDirection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -53,7 +53,7 @@ public final class UCharacterDirection implements UCharacterEnums.ECharacterDire // private constructor ========================================= ///CLOVER:OFF /** - * Private constructor to prevent initialisation + * Private constructor to prevent initialization */ private UCharacterDirection() { diff --git a/src/java.base/share/classes/jdk/internal/icu/lang/UCharacterEnums.java b/src/java.base/share/classes/jdk/internal/icu/lang/UCharacterEnums.java index 9b4809ae411..38f8684ea04 100644 --- a/src/java.base/share/classes/jdk/internal/icu/lang/UCharacterEnums.java +++ b/src/java.base/share/classes/jdk/internal/icu/lang/UCharacterEnums.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2022, 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 @@ -62,7 +62,7 @@ package jdk.internal.icu.lang; @Deprecated class UCharacterEnums { - /** This is just a namespace, it is not instantiatable. */ + /** This is just a namespace, it is not instantiable. */ private UCharacterEnums() {}; /** diff --git a/src/java.base/share/classes/jdk/internal/icu/text/BidiBase.java b/src/java.base/share/classes/jdk/internal/icu/text/BidiBase.java index 1714c15143a..1161e9c8464 100644 --- a/src/java.base/share/classes/jdk/internal/icu/text/BidiBase.java +++ b/src/java.base/share/classes/jdk/internal/icu/text/BidiBase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -63,7 +63,7 @@ import jdk.internal.icu.impl.UBiDiProps; * * This is an implementation of the Unicode Bidirectional Algorithm. The * algorithm is defined in the - * Unicode Standard Annex #9: + * Unicode Standard Annex #9: * Unicode Bidirectional Algorithm. *

* @@ -985,7 +985,7 @@ public class BidiBase { /** * Enumerated property Bidi_Paired_Bracket_Type (new in Unicode 6.3). * Used in - * Unicode Standard Annex #9: + * Unicode Standard Annex #9: * Unicode Bidirectional Algorithm. * Returns UCharacter.BidiPairedBracketType values. * @stable ICU 52 @@ -3365,7 +3365,7 @@ public class BidiBase { /** * Perform the Unicode Bidi algorithm. It is defined in the - * Unicode Standard Annex #9: + * Unicode Standard Annex #9: * Unicode Bidirectional Algorithm, version 13, * also described in The Unicode Standard, Version 4.0 .

* @@ -3450,7 +3450,7 @@ public class BidiBase { /** * Perform the Unicode Bidi algorithm. It is defined in the - * Unicode Standard Annex #9: + * Unicode Standard Annex #9: * Unicode Bidirectional Algorithm, version 13, * also described in The Unicode Standard, Version 4.0 .

* @@ -3786,7 +3786,7 @@ public class BidiBase { /** * Perform the Unicode Bidi algorithm on a given paragraph, as defined in the - * Unicode Standard Annex #9: + * Unicode Standard Annex #9: * Unicode Bidirectional Algorithm, version 13, * also described in The Unicode Standard, Version 4.0 .

* diff --git a/src/java.base/share/classes/jdk/internal/icu/text/BidiLine.java b/src/java.base/share/classes/jdk/internal/icu/text/BidiLine.java index 6a358abebd7..d8fa4f61fa4 100644 --- a/src/java.base/share/classes/jdk/internal/icu/text/BidiLine.java +++ b/src/java.base/share/classes/jdk/internal/icu/text/BidiLine.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2022, 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 @@ final class BidiLine { * text in a single paragraph or in a line of a single paragraph * which has already been processed according to * the Unicode 3.0 Bidi algorithm as defined in - * Unicode Standard Annex #9: + * Unicode Standard Annex #9: * Unicode Bidirectional Algorithm, version 13, * also described in The Unicode Standard, Version 4.0.1 . * diff --git a/src/java.base/share/classes/jdk/internal/icu/text/Normalizer2.java b/src/java.base/share/classes/jdk/internal/icu/text/Normalizer2.java index f7fc6d294a3..db0d1fc20bf 100644 --- a/src/java.base/share/classes/jdk/internal/icu/text/Normalizer2.java +++ b/src/java.base/share/classes/jdk/internal/icu/text/Normalizer2.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, 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 @@ -43,7 +43,7 @@ import jdk.internal.icu.impl.Norm2AllModes; * The primary functions are to produce a normalized string and to detect whether * a string is already normalized. * The most commonly used normalization forms are those defined in - * Unicode Standard Annex #15: + * Unicode Standard Annex #15: * Unicode Normalization Forms. * However, this API supports additional normalization forms for specialized purposes. * For example, NFKC_Casefold is provided via getInstance("nfkc_cf", COMPOSE) diff --git a/src/java.base/share/classes/jdk/internal/icu/text/NormalizerBase.java b/src/java.base/share/classes/jdk/internal/icu/text/NormalizerBase.java index ffe065413a5..f2566d9d419 100644 --- a/src/java.base/share/classes/jdk/internal/icu/text/NormalizerBase.java +++ b/src/java.base/share/classes/jdk/internal/icu/text/NormalizerBase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,7 +44,7 @@ import java.text.Normalizer; * normalize transforms Unicode text into an equivalent composed or * decomposed form, allowing for easier sorting and searching of text. * normalize supports the standard normalization forms described in - * + * * Unicode Standard Annex #15 — Unicode Normalization Forms. * * Characters with accents or other adornments can be encoded in diff --git a/src/java.base/share/classes/jdk/internal/icu/text/StringPrep.java b/src/java.base/share/classes/jdk/internal/icu/text/StringPrep.java index 82fe7d3a5a9..f05d0403665 100644 --- a/src/java.base/share/classes/jdk/internal/icu/text/StringPrep.java +++ b/src/java.base/share/classes/jdk/internal/icu/text/StringPrep.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2022, 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 @@ -67,9 +67,9 @@ import jdk.internal.icu.util.VersionInfo; *

  • Unassigned Table: Contains code points that are unassigned * in the Unicode Version supported by StringPrep. Currently * RFC 3454 supports Unicode 3.2.
  • - *
  • Prohibited Table: Contains code points that are prohibted from + *
  • Prohibited Table: Contains code points that are prohibited from * the output of the StringPrep processing function.
  • - *
  • Mapping Table: Contains code ponts that are deleted from the output or case mapped.
  • + *
  • Mapping Table: Contains code points that are deleted from the output or case mapped.
  • * * * The procedure for preparing Unicode strings: @@ -226,8 +226,8 @@ public final class StringPrep { sprepUniVer = getVersionInfo(reader.getUnicodeVersion()); normCorrVer = getVersionInfo(indexes[NORM_CORRECTNS_LAST_UNI_VERSION]); VersionInfo normUniVer = UCharacter.getUnicodeVersion(); - if(normUniVer.compareTo(sprepUniVer) < 0 && /* the Unicode version of SPREP file must be less than the Unicode Vesion of the normalization data */ - normUniVer.compareTo(normCorrVer) < 0 && /* the Unicode version of the NormalizationCorrections.txt file should be less than the Unicode Vesion of the normalization data */ + if(normUniVer.compareTo(sprepUniVer) < 0 && /* the Unicode version of SPREP file must be less than the Unicode Version of the normalization data */ + normUniVer.compareTo(normCorrVer) < 0 && /* the Unicode version of the NormalizationCorrections.txt file should be less than the Unicode Version of the normalization data */ ((indexes[OPTIONS] & NORMALIZATION_ON) > 0) /* normalization turned on*/ ){ throw new IOException("Normalization Correction version not supported"); @@ -325,7 +325,7 @@ public final class StringPrep { ch -= val.value; } }else if(val.type == DELETE){ - // just consume the codepoint and contine + // just consume the codepoint and continue continue; } //copy the source into destination diff --git a/src/java.base/share/classes/jdk/internal/icu/text/UCharacterIterator.java b/src/java.base/share/classes/jdk/internal/icu/text/UCharacterIterator.java index e85a08c4605..93978372c3a 100644 --- a/src/java.base/share/classes/jdk/internal/icu/text/UCharacterIterator.java +++ b/src/java.base/share/classes/jdk/internal/icu/text/UCharacterIterator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, 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 @@ -147,9 +147,9 @@ public abstract class UCharacterIterator */ public int nextCodePoint(){ int ch1 = next(); - if(UTF16.isLeadSurrogate((char)ch1)){ + if(UTF16.isLeadSurrogate(ch1)){ int ch2 = next(); - if(UTF16.isTrailSurrogate((char)ch2)){ + if(UTF16.isTrailSurrogate(ch2)){ return UCharacterProperty.getRawSupplementary((char)ch1, (char)ch2); }else if (ch2 != DONE) { @@ -175,7 +175,7 @@ public abstract class UCharacterIterator /** * Retreat to the start of the previous code point in the text, * and return it (pre-decrement semantics). If the index is not - * preceeded by a valid surrogate pair, the behavior is the same + * preceded by a valid surrogate pair, the behavior is the same * as previous(). Otherwise the iterator is * decremented to the start of the surrogate pair, and the code * point represented by the pair is returned. @@ -185,9 +185,9 @@ public abstract class UCharacterIterator */ public int previousCodePoint(){ int ch1 = previous(); - if(UTF16.isTrailSurrogate((char)ch1)){ + if(UTF16.isTrailSurrogate(ch1)){ int ch2 = previous(); - if(UTF16.isLeadSurrogate((char)ch2)){ + if(UTF16.isLeadSurrogate(ch2)){ return UCharacterProperty.getRawSupplementary((char)ch2, (char)ch1); }else if (ch2 != DONE) { diff --git a/src/java.base/share/classes/jdk/internal/icu/text/UTF16.java b/src/java.base/share/classes/jdk/internal/icu/text/UTF16.java index b35d842b0d5..4205487a966 100644 --- a/src/java.base/share/classes/jdk/internal/icu/text/UTF16.java +++ b/src/java.base/share/classes/jdk/internal/icu/text/UTF16.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2022, 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 @@ -382,36 +382,39 @@ public final class UTF16 } /** - * Determines whether the code value is a surrogate. - * @param char16 the input character. - * @return true if the input character is a surrogate. - * @stable ICU 2.1 + * Determines whether the code point is a surrogate. + * + * @param codePoint The input character. + * (In ICU 2.1-69 the type of this parameter was char.) + * @return true If the input code point is a surrogate. + * @stable ICU 70 */ - public static boolean isSurrogate(char char16) - { - return (char16 & SURROGATE_BITMASK) == SURROGATE_BITS; + public static boolean isSurrogate(int codePoint) { + return (codePoint & SURROGATE_BITMASK) == SURROGATE_BITS; } /** - * Determines whether the character is a trail surrogate. - * @param char16 the input character. - * @return true if the input character is a trail surrogate. - * @stable ICU 2.1 + * Determines whether the code point is a trail surrogate. + * + * @param codePoint The input character. + * (In ICU 2.1-69 the type of this parameter was char.) + * @return true If the input code point is a trail surrogate. + * @stable ICU 70 */ - public static boolean isTrailSurrogate(char char16) - { - return (char16 & TRAIL_SURROGATE_BITMASK) == TRAIL_SURROGATE_BITS; + public static boolean isTrailSurrogate(int codePoint) { + return (codePoint & TRAIL_SURROGATE_BITMASK) == TRAIL_SURROGATE_BITS; } /** - * Determines whether the character is a lead surrogate. - * @param char16 the input character. - * @return true if the input character is a lead surrogate - * @stable ICU 2.1 + * Determines whether the code point is a lead surrogate. + * + * @param codePoint The input character. + * (In ICU 2.1-69 the type of this parameter was char.) + * @return true If the input code point is a lead surrogate + * @stable ICU 70 */ - public static boolean isLeadSurrogate(char char16) - { - return (char16 & LEAD_SURROGATE_BITMASK) == LEAD_SURROGATE_BITS; + public static boolean isLeadSurrogate(int codePoint) { + return (codePoint & LEAD_SURROGATE_BITMASK) == LEAD_SURROGATE_BITS; } /** diff --git a/src/java.base/share/classes/jdk/internal/icu/text/UnicodeSet.java b/src/java.base/share/classes/jdk/internal/icu/text/UnicodeSet.java index 63188dca460..6f5919e016b 100644 --- a/src/java.base/share/classes/jdk/internal/icu/text/UnicodeSet.java +++ b/src/java.base/share/classes/jdk/internal/icu/text/UnicodeSet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2022, 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 @@ -135,8 +135,8 @@ import jdk.internal.icu.util.VersionInfo; * "[:Lu:]" and the Perl-like syntax "\p{Lu}" are recognized. For a * complete list of supported property patterns, see the User's Guide * for UnicodeSet at - * - * http://www.icu-project.org/userguide/unicodeSet.html. + * + * https://unicode-org.github.io/icu/userguide/strings/unicodeset. * Actual determination of property data is defined by the underlying * Unicode database as implemented by UCharacter. * @@ -147,6 +147,13 @@ import jdk.internal.icu.util.VersionInfo; * their delimiters; "[:^foo]" and "\P{foo}". In any other location, * '^' has no special meaning. * + *

    Since ICU 70, "[^...]", "[:^foo]", "\P{foo}", and "[:binaryProperty=No:]" + * perform a "code point complement" (all code points minus the original set), + * removing all multicharacter strings, + * equivalent to .{@link #complement()}.{@link #removeAllStrings()} . + * The {@link #complement()} API function continues to perform a + * symmetric difference with all code points and thus retains all multicharacter strings. + * *

    Ranges are indicated by placing two a '-' between two * characters, as in "a-z". This specifies the range of all * characters from the left to the right, in Unicode order. If the @@ -189,8 +196,6 @@ import jdk.internal.icu.util.VersionInfo; * Unicode property * * - *

    Warning: you cannot add an empty string ("") to a UnicodeSet.

    - * *

    Formal syntax

    * *
    @@ -230,9 +235,8 @@ import jdk.internal.icu.util.VersionInfo; * * * hex :=  - * any character for which - * Character.digit(c, 16) - * returns a non-negative result + * '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' |
    + *     'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'a' | 'b' | 'c' | 'd' | 'e' | 'f'
    * * * property :=  @@ -487,7 +491,7 @@ public class UnicodeSet { else if (i > 0 && c == list[i-1]) { // c is after end of prior range list[i-1]++; - // no need to chcek for collapse here + // no need to check for collapse here } else { @@ -528,7 +532,6 @@ public class UnicodeSet { * present. If this set already contains the multicharacter, * the call leaves this set unchanged. * Thus {@code "ch" => {"ch"}} - *
    Warning: you cannot add an empty string ("") to a UnicodeSet. * @param s the source string * @return this object, for chaining * @stable ICU 2.0 @@ -546,22 +549,19 @@ public class UnicodeSet { /** * Utility for getting code point from single code point CharSequence. - * See the public UTF16.getSingleCodePoint() + * See the public UTF16.getSingleCodePoint() (which returns -1 for null rather than throwing NPE). + * * @return a code point IF the string consists of a single one. * otherwise returns -1. * @param s to test */ private static int getSingleCP(CharSequence s) { - if (s.length() < 1) { - throw new IllegalArgumentException("Can't use zero-length strings in UnicodeSet"); - } - if (s.length() > 2) return -1; if (s.length() == 1) return s.charAt(0); - - // at this point, len = 2 - int cp = UTF16.charAt(s, 0); - if (cp > 0xFFFF) { // is surrogate pair - return cp; + if (s.length() == 2) { + int cp = Character.codePointAt(s, 0); + if (cp > 0xFFFF) { // is surrogate pair + return cp; + } } return -1; } @@ -569,13 +569,11 @@ public class UnicodeSet { /** * Complements the specified range in this set. Any character in * the range will be removed if it is in this set, or will be - * added if it is not in this set. If {@code end > start} + * added if it is not in this set. If start > end * then an empty range is complemented, leaving the set unchanged. * - * @param start first character, inclusive, of range to be removed - * from this set. - * @param end last character, inclusive, of range to be removed - * from this set. + * @param start first character, inclusive, of range + * @param end last character, inclusive, of range * @stable ICU 2.0 */ public UnicodeSet complement(int start, int end) { diff --git a/src/java.base/share/classes/jdk/internal/icu/util/CodePointTrie.java b/src/java.base/share/classes/jdk/internal/icu/util/CodePointTrie.java index 1738696f75a..7aaa0be68c8 100644 --- a/src/java.base/share/classes/jdk/internal/icu/util/CodePointTrie.java +++ b/src/java.base/share/classes/jdk/internal/icu/util/CodePointTrie.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, 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 @@ -43,7 +43,7 @@ import static jdk.internal.icu.impl.NormalizerImpl.UTF16Plus; /** * Immutable Unicode code point trie. * Fast, reasonably compact, map from Unicode code points (U+0000..U+10FFFF) to integer values. - * For details see http://site.icu-project.org/design/struct/utrie + * For details see https://icu.unicode.org/design/struct/utrie * *

    This class is not intended for public subclassing. * diff --git a/src/java.base/share/classes/jdk/internal/icu/util/VersionInfo.java b/src/java.base/share/classes/jdk/internal/icu/util/VersionInfo.java index d79ee84731b..799d570e2aa 100644 --- a/src/java.base/share/classes/jdk/internal/icu/util/VersionInfo.java +++ b/src/java.base/share/classes/jdk/internal/icu/util/VersionInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2022, 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 @@ -54,7 +54,7 @@ public final class VersionInfo * @deprecated This API is ICU internal only. */ @Deprecated - public static final String ICU_DATA_VERSION_PATH = "67b"; + public static final String ICU_DATA_VERSION_PATH = "70b"; // public methods ------------------------------------------------------ @@ -148,7 +148,15 @@ public final class VersionInfo */ public int compareTo(VersionInfo other) { - return m_version_ - other.m_version_; + // m_version_ is an int, a signed 32-bit integer. + // When the major version is >=128, then the version int is negative. + // Compare it in two steps to simulate an unsigned-int comparison. + // (Alternatively we could turn each int into a long and reset the upper 32 bits.) + // Compare the upper bits first, using logical shift right (unsigned). + int diff = (m_version_ >>> 1) - (other.m_version_ >>> 1); + if (diff != 0) { return diff; } + // Compare the remaining bits. + return (m_version_ & 1) - (other.m_version_ & 1); } // private data members ---------------------------------------------- diff --git a/src/java.base/share/legal/icu.md b/src/java.base/share/legal/icu.md index ab850bf143e..35a54e61112 100644 --- a/src/java.base/share/legal/icu.md +++ b/src/java.base/share/legal/icu.md @@ -1,4 +1,4 @@ -## International Components for Unicode (ICU4J) v67.1 +## International Components for Unicode (ICU4J) v70.1 ### ICU4J License ``` @@ -80,61 +80,439 @@ of the copyright holder. All trademarks and registered trademarks mentioned herein are the property of their respective owners. +2. Chinese/Japanese Word Break Dictionary Data (cjdict.txt) -—————————————————————————————————————————————————————————————————————— - - -From: https://www.unicode.org/copyright.html: - - Unicode® Copyright and Terms of Use - - For the general privacy policy governing access to this site, see the Unicode Privacy Policy. - - Unicode Copyright - Copyright © 1991-2020 Unicode, Inc. All rights reserved. - Definitions - - Unicode Data Files ("DATA FILES") include all data files under the directories: - https://www.unicode.org/Public/ - https://www.unicode.org/reports/ - https://www.unicode.org/ivd/data/ - - Unicode Data Files do not include PDF online code charts under the directory: - https://www.unicode.org/Public/ - - Unicode Software ("SOFTWARE") includes any source code published in the Unicode Standard - or any source code or compiled code under the directories: - https://www.unicode.org/Public/PROGRAMS/ - https://www.unicode.org/Public/cldr/ - http://site.icu-project.org/download/ - - Terms of Use - Certain documents and files on this website contain a legend indicating that "Modification is permitted." Any person is hereby authorized, without fee, to modify such documents and files to create derivative works conforming to the Unicode® Standard, subject to Terms and Conditions herein. - Any person is hereby authorized, without fee, to view, use, reproduce, and distribute all documents and files, subject to the Terms and Conditions herein. - Further specifications of rights and restrictions pertaining to the use of the Unicode DATA FILES and SOFTWARE can be found in the Unicode Data Files and Software License. - Each version of the Unicode Standard has further specifications of rights and restrictions of use. For the book editions (Unicode 5.0 and earlier), these are found on the back of the title page. - The Unicode PDF online code charts carry specific restrictions. Those restrictions are incorporated as the first page of each PDF code chart. - All other files, including online documentation of the core specification for Unicode 6.0 and later, are covered under these general Terms of Use. - No license is granted to "mirror" the Unicode website where a fee is charged for access to the "mirror" site. - Modification is not permitted with respect to this document. All copies of this document must be verbatim. - Restricted Rights Legend - Any technical data or software which is licensed to the United States of America, its agencies and/or instrumentalities under this Agreement is commercial technical data or commercial computer software developed exclusively at private expense as defined in FAR 2.101, or DFARS 252.227-7014 (June 1995), as applicable. For technical data, use, duplication, or disclosure by the Government is subject to restrictions as set forth in DFARS 202.227-7015 Technical Data, Commercial and Items (Nov 1995) and this Agreement. For Software, in accordance with FAR 12-212 or DFARS 227-7202, as applicable, use, duplication or disclosure by the Government is subject to the restrictions set forth in this Agreement. - Warranties and Disclaimers - This publication and/or website may include technical or typographical errors or other inaccuracies. Changes are periodically added to the information herein; these changes will be incorporated in new editions of the publication and/or website. Unicode, Inc. may make improvements and/or changes in the product(s) and/or program(s) described in this publication and/or website at any time. - If this file has been purchased on magnetic or optical media from Unicode, Inc. the sole and exclusive remedy for any claim will be exchange of the defective media within ninety (90) days of original purchase. - EXCEPT AS PROVIDED IN SECTION E.2, THIS PUBLICATION AND/OR SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND EITHER EXPRESS, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. UNICODE, INC. AND ITS LICENSORS ASSUME NO RESPONSIBILITY FOR ERRORS OR OMISSIONS IN THIS PUBLICATION AND/OR SOFTWARE OR OTHER DOCUMENTS WHICH ARE REFERENCED BY OR LINKED TO THIS PUBLICATION OR THE UNICODE WEBSITE. - Waiver of Damages - In no event shall Unicode, Inc. or its licensors be liable for any special, incidental, indirect or consequential damages of any kind, or any damages whatsoever, whether or not Unicode, Inc. was advised of the possibility of the damage, including, without limitation, those resulting from the following: loss of use, data or profits, in connection with the use, modification or distribution of this information or its derivatives. - Trademarks & Logos - The Unicode Word Mark and the Unicode Logo are trademarks of Unicode, Inc. “The Unicode Consortium” and “Unicode, Inc.” are trade names of Unicode, Inc. Use of the information and materials found on this website indicates your acknowledgement of Unicode, Inc.’s exclusive worldwide rights in the Unicode Word Mark, the Unicode Logo, and the Unicode trade names. - The Unicode Consortium Name and Trademark Usage Policy (“Trademark Policy”) are incorporated herein by reference and you agree to abide by the provisions of the Trademark Policy, which may be changed from time to time in the sole discretion of Unicode, Inc. - All third party trademarks referenced herein are the property of their respective owners. - Miscellaneous - Jurisdiction and Venue. This website is operated from a location in the State of California, United States of America. Unicode, Inc. makes no representation that the materials are appropriate for use in other locations. If you access this website from other locations, you are responsible for compliance with local laws. This Agreement, all use of this website and any claims and damages resulting from use of this website are governed solely by the laws of the State of California without regard to any principles which would apply the laws of a different jurisdiction. The user agrees that any disputes regarding this website shall be resolved solely in the courts located in Santa Clara County, California. The user agrees said courts have personal jurisdiction and agree to waive any right to transfer the dispute to any other forum. - Modification by Unicode, Inc. Unicode, Inc. shall have the right to modify this Agreement at any time by posting it to this website. The user may not assign any part of this Agreement without Unicode, Inc.’s prior written consent. - Taxes. The user agrees to pay any taxes arising from access to this website or use of the information herein, except for those based on Unicode’s net income. - Severability. If any provision of this Agreement is declared invalid or unenforceable, the remaining provisions of this Agreement shall remain in effect. - Entire Agreement. This Agreement constitutes the entire agreement between the parties. + # The Google Chrome software developed by Google is licensed under + # the BSD license. Other software included in this distribution is + # provided under other licenses, as set forth below. + # + # The BSD License + # http://opensource.org/licenses/bsd-license.php + # Copyright (C) 2006-2008, Google Inc. + # + # All rights reserved. + # + # Redistribution and use in source and binary forms, with or without + # modification, are permitted provided that the following conditions are met: + # + # Redistributions of source code must retain the above copyright notice, + # this list of conditions and the following disclaimer. + # Redistributions in binary form must reproduce the above + # copyright notice, this list of conditions and the following + # disclaimer in the documentation and/or other materials provided with + # the distribution. + # Neither the name of Google Inc. nor the names of its + # contributors may be used to endorse or promote products derived from + # this software without specific prior written permission. + # + # + # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + # CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + # BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + # + # + # The word list in cjdict.txt are generated by combining three word lists + # listed below with further processing for compound word breaking. The + # frequency is generated with an iterative training against Google web + # corpora. + # + # * Libtabe (Chinese) + # - https://sourceforge.net/project/?group_id=1519 + # - Its license terms and conditions are shown below. + # + # * IPADIC (Japanese) + # - http://chasen.aist-nara.ac.jp/chasen/distribution.html + # - Its license terms and conditions are shown below. + # + # ---------COPYING.libtabe ---- BEGIN-------------------- + # + # /* + # * Copyright (c) 1999 TaBE Project. + # * Copyright (c) 1999 Pai-Hsiang Hsiao. + # * All rights reserved. + # * + # * Redistribution and use in source and binary forms, with or without + # * modification, are permitted provided that the following conditions + # * are met: + # * + # * . Redistributions of source code must retain the above copyright + # * notice, this list of conditions and the following disclaimer. + # * . Redistributions in binary form must reproduce the above copyright + # * notice, this list of conditions and the following disclaimer in + # * the documentation and/or other materials provided with the + # * distribution. + # * . Neither the name of the TaBE Project nor the names of its + # * contributors may be used to endorse or promote products derived + # * from this software without specific prior written permission. + # * + # * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + # * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + # * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + # * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + # * REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + # * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + # * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + # * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + # * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + # * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + # * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + # * OF THE POSSIBILITY OF SUCH DAMAGE. + # */ + # + # /* + # * Copyright (c) 1999 Computer Systems and Communication Lab, + # * Institute of Information Science, Academia + # * Sinica. All rights reserved. + # * + # * Redistribution and use in source and binary forms, with or without + # * modification, are permitted provided that the following conditions + # * are met: + # * + # * . Redistributions of source code must retain the above copyright + # * notice, this list of conditions and the following disclaimer. + # * . Redistributions in binary form must reproduce the above copyright + # * notice, this list of conditions and the following disclaimer in + # * the documentation and/or other materials provided with the + # * distribution. + # * . Neither the name of the Computer Systems and Communication Lab + # * nor the names of its contributors may be used to endorse or + # * promote products derived from this software without specific + # * prior written permission. + # * + # * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + # * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + # * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + # * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + # * REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + # * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + # * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + # * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + # * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + # * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + # * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + # * OF THE POSSIBILITY OF SUCH DAMAGE. + # */ + # + # Copyright 1996 Chih-Hao Tsai @ Beckman Institute, + # University of Illinois + # c-tsai4@uiuc.edu http://casper.beckman.uiuc.edu/~c-tsai4 + # + # ---------------COPYING.libtabe-----END-------------------------------- + # + # + # ---------------COPYING.ipadic-----BEGIN------------------------------- + # + # Copyright 2000, 2001, 2002, 2003 Nara Institute of Science + # and Technology. All Rights Reserved. + # + # Use, reproduction, and distribution of this software is permitted. + # Any copy of this software, whether in its original form or modified, + # must include both the above copyright notice and the following + # paragraphs. + # + # Nara Institute of Science and Technology (NAIST), + # the copyright holders, disclaims all warranties with regard to this + # software, including all implied warranties of merchantability and + # fitness, in no event shall NAIST be liable for + # any special, indirect or consequential damages or any damages + # whatsoever resulting from loss of use, data or profits, whether in an + # action of contract, negligence or other tortuous action, arising out + # of or in connection with the use or performance of this software. + # + # A large portion of the dictionary entries + # originate from ICOT Free Software. The following conditions for ICOT + # Free Software applies to the current dictionary as well. + # + # Each User may also freely distribute the Program, whether in its + # original form or modified, to any third party or parties, PROVIDED + # that the provisions of Section 3 ("NO WARRANTY") will ALWAYS appear + # on, or be attached to, the Program, which is distributed substantially + # in the same form as set out herein and that such intended + # distribution, if actually made, will neither violate or otherwise + # contravene any of the laws and regulations of the countries having + # jurisdiction over the User or the intended distribution itself. + # + # NO WARRANTY + # + # The program was produced on an experimental basis in the course of the + # research and development conducted during the project and is provided + # to users as so produced on an experimental basis. Accordingly, the + # program is provided without any warranty whatsoever, whether express, + # implied, statutory or otherwise. The term "warranty" used herein + # includes, but is not limited to, any warranty of the quality, + # performance, merchantability and fitness for a particular purpose of + # the program and the nonexistence of any infringement or violation of + # any right of any third party. + # + # Each user of the program will agree and understand, and be deemed to + # have agreed and understood, that there is no warranty whatsoever for + # the program and, accordingly, the entire risk arising from or + # otherwise connected with the program is assumed by the user. + # + # Therefore, neither ICOT, the copyright holder, or any other + # organization that participated in or was otherwise related to the + # development of the program and their respective officials, directors, + # officers and other employees shall be held liable for any and all + # damages, including, without limitation, general, special, incidental + # and consequential damages, arising out of or otherwise in connection + # with the use or inability to use the program or any product, material + # or result produced or otherwise obtained by using the program, + # regardless of whether they have been advised of, or otherwise had + # knowledge of, the possibility of such damages at any time during the + # project or thereafter. Each user will be deemed to have agreed to the + # foregoing by his or her commencement of use of the program. The term + # "use" as used herein includes, but is not limited to, the use, + # modification, copying and distribution of the program and the + # production of secondary products from the program. + # + # In the case where the program, whether in its original form or + # modified, was distributed or delivered to or received by a user from + # any person, organization or entity other than ICOT, unless it makes or + # grants independently of ICOT any specific warranty to the user in + # writing, such person, organization or entity, will also be exempted + # from and not be held liable to the user for any such damages as noted + # above as far as the program is concerned. + # + # ---------------COPYING.ipadic-----END---------------------------------- + +3. Lao Word Break Dictionary Data (laodict.txt) + + # Copyright (C) 2016 and later: Unicode, Inc. and others. + # License & terms of use: http://www.unicode.org/copyright.html + # Copyright (c) 2015 International Business Machines Corporation + # and others. All Rights Reserved. + # + # Project: https://github.com/rober42539/lao-dictionary + # Dictionary: https://github.com/rober42539/lao-dictionary/laodict.txt + # License: https://github.com/rober42539/lao-dictionary/LICENSE.txt + # (copied below) + # + # This file is derived from the above dictionary version of Nov 22, 2020 + # ---------------------------------------------------------------------- + # Copyright (C) 2013 Brian Eugene Wilson, Robert Martin Campbell. + # All rights reserved. + # + # Redistribution and use in source and binary forms, with or without + # modification, are permitted provided that the following conditions are met: + # + # Redistributions of source code must retain the above copyright notice, this + # list of conditions and the following disclaimer. Redistributions in binary + # form must reproduce the above copyright notice, this list of conditions and + # the following disclaimer in the documentation and/or ther materials + # provided with the distribution. + # + # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + # OF THE POSSIBILITY OF SUCH DAMAGE. + # -------------------------------------------------------------------------- + +4. Burmese Word Break Dictionary Data (burmesedict.txt) + + # Copyright (c) 2014 International Business Machines Corporation + # and others. All Rights Reserved. + # + # This list is part of a project hosted at: + # github.com/kanyawtech/myanmar-karen-word-lists + # + # -------------------------------------------------------------------------- + # Copyright (c) 2013, LeRoy Benjamin Sharon + # All rights reserved. + # + # Redistribution and use in source and binary forms, with or without + # modification, are permitted provided that the following conditions + # are met: Redistributions of source code must retain the above + # copyright notice, this list of conditions and the following + # disclaimer. Redistributions in binary form must reproduce the + # above copyright notice, this list of conditions and the following + # disclaimer in the documentation and/or other materials provided + # with the distribution. + # + # Neither the name Myanmar Karen Word Lists, nor the names of its + # contributors may be used to endorse or promote products derived + # from this software without specific prior written permission. + # + # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + # CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS + # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + # TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + # TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + # THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + # SUCH DAMAGE. + # -------------------------------------------------------------------------- + +5. Time Zone Database + + ICU uses the public domain data and code derived from Time Zone +Database for its time zone support. The ownership of the TZ database +is explained in BCP 175: Procedure for Maintaining the Time Zone +Database section 7. + + # 7. Database Ownership + # + # The TZ database itself is not an IETF Contribution or an IETF + # document. Rather it is a pre-existing and regularly updated work + # that is in the public domain, and is intended to remain in the + # public domain. Therefore, BCPs 78 [RFC5378] and 79 [RFC3979] do + # not apply to the TZ Database or contributions that individuals make + # to it. Should any claims be made and substantiated against the TZ + # Database, the organization that is providing the IANA + # Considerations defined in this RFC, under the memorandum of + # understanding with the IETF, currently ICANN, may act in accordance + # with all competent court orders. No ownership claims will be made + # by ICANN or the IETF Trust on the database or the code. Any person + # making a contribution to the database or code waives all rights to + # future claims in that contribution or in the TZ Database. + +6. Google double-conversion + +Copyright 2006-2011, the V8 project authors. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +==================================================== + +Unicode® Copyright and Terms of Use +For the general privacy policy governing access to this site, see the Unicode Privacy Policy. + +Unicode Copyright +Copyright © 1991-2021 Unicode, Inc. All rights reserved. +Definitions +Unicode Data Files ("DATA FILES") include all data files under the directories: +https://www.unicode.org/Public/ +https://www.unicode.org/reports/ +https://www.unicode.org/ivd/data/ + +Unicode Data Files do not include PDF online code charts under the directory: +https://www.unicode.org/Public/ + +Unicode Software ("SOFTWARE") includes any source code published in the Unicode Standard +or any source code or compiled code under the directories: +https://www.unicode.org/Public/PROGRAMS/ +https://www.unicode.org/Public/cldr/ +http://site.icu-project.org/download/ +Terms of Use +Certain documents and files on this website contain a legend indicating that "Modification is permitted." Any person is hereby authorized, without fee, to modify such documents and files to create derivative works conforming to the Unicode® Standard, subject to Terms and Conditions herein. +Any person is hereby authorized, without fee, to view, use, reproduce, and distribute all documents and files, subject to the Terms and Conditions herein. +Further specifications of rights and restrictions pertaining to the use of the Unicode DATA FILES and SOFTWARE can be found in the Unicode Data Files and Software License. +Each version of the Unicode Standard has further specifications of rights and restrictions of use. For the book editions (Unicode 5.0 and earlier), these are found on the back of the title page. +The Unicode PDF online code charts carry specific restrictions. Those restrictions are incorporated as the first page of each PDF code chart. +All other files, including online documentation of the core specification for Unicode 6.0 and later, are covered under these general Terms of Use. +No license is granted to "mirror" the Unicode website where a fee is charged for access to the "mirror" site. +Modification is not permitted with respect to this document. All copies of this document must be verbatim. +Restricted Rights Legend +Any technical data or software which is licensed to the United States of America, its agencies and/or instrumentalities under this Agreement is commercial technical data or commercial computer software developed exclusively at private expense as defined in FAR 2.101, or DFARS 252.227-7014 (June 1995), as applicable. For technical data, use, duplication, or disclosure by the Government is subject to restrictions as set forth in DFARS 202.227-7015 Technical Data, Commercial and Items (Nov 1995) and this Agreement. For Software, in accordance with FAR 12-212 or DFARS 227-7202, as applicable, use, duplication or disclosure by the Government is subject to the restrictions set forth in this Agreement. +Warranties and Disclaimers +This publication and/or website may include technical or typographical errors or other inaccuracies. Changes are periodically added to the information herein; these changes will be incorporated in new editions of the publication and/or website. Unicode, Inc. may make improvements and/or changes in the product(s) and/or program(s) described in this publication and/or website at any time. +If this file has been purchased on magnetic or optical media from Unicode, Inc. the sole and exclusive remedy for any claim will be exchange of the defective media within ninety (90) days of original purchase. +EXCEPT AS PROVIDED IN SECTION E.2, THIS PUBLICATION AND/OR SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND EITHER EXPRESS, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. UNICODE, INC. AND ITS LICENSORS ASSUME NO RESPONSIBILITY FOR ERRORS OR OMISSIONS IN THIS PUBLICATION AND/OR SOFTWARE OR OTHER DOCUMENTS WHICH ARE REFERENCED BY OR LINKED TO THIS PUBLICATION OR THE UNICODE WEBSITE. +Waiver of Damages +In no event shall Unicode, Inc. or its licensors be liable for any special, incidental, indirect or consequential damages of any kind, or any damages whatsoever, whether or not Unicode, Inc. was advised of the possibility of the damage, including, without limitation, those resulting from the following: loss of use, data or profits, in connection with the use, modification or distribution of this information or its derivatives. +Trademarks & Logos +The Unicode Word Mark and the Unicode Logo are trademarks of Unicode, Inc. “The Unicode Consortium” and “Unicode, Inc.” are trade names of Unicode, Inc. Use of the information and materials found on this website indicates your acknowledgement of Unicode, Inc.’s exclusive worldwide rights in the Unicode Word Mark, the Unicode Logo, and the Unicode trade names. +The Unicode Consortium Name and Trademark Usage Policy (“Trademark Policy”) are incorporated herein by reference and you agree to abide by the provisions of the Trademark Policy, which may be changed from time to time in the sole discretion of Unicode, Inc. +All third party trademarks referenced herein are the property of their respective owners. +Miscellaneous +Jurisdiction and Venue. This website is operated from a location in the State of California, United States of America. Unicode, Inc. makes no representation that the materials are appropriate for use in other locations. If you access this website from other locations, you are responsible for compliance with local laws. This Agreement, all use of this website and any claims and damages resulting from use of this website are governed solely by the laws of the State of California without regard to any principles which would apply the laws of a different jurisdiction. The user agrees that any disputes regarding this website shall be resolved solely in the courts located in Santa Clara County, California. The user agrees said courts have personal jurisdiction and agree to waive any right to transfer the dispute to any other forum. +Modification by Unicode, Inc. Unicode, Inc. shall have the right to modify this Agreement at any time by posting it to this website. The user may not assign any part of this Agreement without Unicode, Inc.’s prior written consent. +Taxes. The user agrees to pay any taxes arising from access to this website or use of the information herein, except for those based on Unicode’s net income. +Severability. If any provision of this Agreement is declared invalid or unenforceable, the remaining provisions of this Agreement shall remain in effect. +Entire Agreement. This Agreement constitutes the entire agreement between the parties. + +======================================================= + +UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE + +See Terms of Use +for definitions of Unicode Inc.’s Data Files and Software. + +NOTICE TO USER: Carefully read the following legal agreement. +BY DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S +DATA FILES ("DATA FILES"), AND/OR SOFTWARE ("SOFTWARE"), +YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE +TERMS AND CONDITIONS OF THIS AGREEMENT. +IF YOU DO NOT AGREE, DO NOT DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE +THE DATA FILES OR SOFTWARE. + +COPYRIGHT AND PERMISSION NOTICE + +Copyright © 1991-2021 Unicode, Inc. All rights reserved. +Distributed under the Terms of Use in https://www.unicode.org/copyright.html. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Unicode data files and any associated documentation +(the "Data Files") or Unicode software and any associated documentation +(the "Software") to deal in the Data Files or Software +without restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, and/or sell copies of +the Data Files or Software, and to permit persons to whom the Data Files +or Software are furnished to do so, provided that either +(a) this copyright and permission notice appear with all copies +of the Data Files or Software, or +(b) this copyright and permission notice appear in associated +Documentation. + +THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT OF THIRD PARTY RIGHTS. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS +NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL +DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THE DATA FILES OR SOFTWARE. + +Except as contained in this notice, the name of a copyright holder +shall not be used in advertising or otherwise to promote the sale, +use or other dealings in these Data Files or Software without prior +written authorization of the copyright holder. ``` diff --git a/src/java.base/share/legal/unicode.md b/src/java.base/share/legal/unicode.md index cff0c82a873..fbb82346769 100644 --- a/src/java.base/share/legal/unicode.md +++ b/src/java.base/share/legal/unicode.md @@ -1,5 +1,5 @@ -## The Unicode Standard, Unicode Character Database, Version 13.0.0 - +## The Unicode Standard, Unicode Character Database, Version 14.0.0 + ### Unicode Character Database ``` @@ -18,7 +18,7 @@ THE DATA FILES OR SOFTWARE. COPYRIGHT AND PERMISSION NOTICE -Copyright © 1991-2020 Unicode, Inc. All rights reserved. +Copyright © 1991-2021 Unicode, Inc. All rights reserved. Distributed under the Terms of Use in https://www.unicode.org/copyright.html. Permission is hereby granted, free of charge, to any person obtaining @@ -50,5 +50,54 @@ shall not be used in advertising or otherwise to promote the sale, use or other dealings in these Data Files or Software without prior written authorization of the copyright holder. +=== http://www.unicode.org/copyright.html content === +Unicode (R) Copyright and Terms of Use +For the general privacy policy governing access to this site, see the Unicode Privacy Policy. + +Unicode Copyright +Copyright (C) 1991-2021 Unicode, Inc. All rights reserved. +Definitions +Unicode Data Files ("DATA FILES") include all data files under the directories: +https://www.unicode.org/Public/ +https://www.unicode.org/reports/ +https://www.unicode.org/ivd/data/ + +Unicode Data Files do not include PDF online code charts under the directory: +https://www.unicode.org/Public/ + +Unicode Software ("SOFTWARE") includes any source code published in the Unicode Standard +or any source code or compiled code under the directories: +https://www.unicode.org/Public/PROGRAMS/ +https://www.unicode.org/Public/cldr/ +http://site.icu-project.org/download/ +Terms of Use +Certain documents and files on this website contain a legend indicating that "Modification is permitted." Any person is hereby authorized, without fee, to modify such documents and files to create derivative works conforming to the Unicode® Standard, subject to Terms and Conditions herein. +Any person is hereby authorized, without fee, to view, use, reproduce, and distribute all documents and files, subject to the Terms and Conditions herein. +Further specifications of rights and restrictions pertaining to the use of the Unicode DATA FILES and SOFTWARE can be found in the Unicode Data Files and Software License. +Each version of the Unicode Standard has further specifications of rights and restrictions of use. For the book editions (Unicode 5.0 and earlier), these are found on the back of the title page. +The Unicode PDF online code charts carry specific restrictions. Those restrictions are incorporated as the first page of each PDF code chart. +All other files, including online documentation of the core specification for Unicode 6.0 and later, are covered under these general Terms of Use. +No license is granted to "mirror" the Unicode website where a fee is charged for access to the "mirror" site. +Modification is not permitted with respect to this document. All copies of this document must be verbatim. +Restricted Rights Legend +Any technical data or software which is licensed to the United States of America, its agencies and/or instrumentalities under this Agreement is commercial technical data or commercial computer software developed exclusively at private expense as defined in FAR 2.101, or DFARS 252.227-7014 (June 1995), as applicable. For technical data, use, duplication, or disclosure by the Government is subject to restrictions as set forth in DFARS 202.227-7015 Technical Data, Commercial and Items (Nov 1995) and this Agreement. For Software, in accordance with FAR 12-212 or DFARS 227-7202, as applicable, use, duplication or disclosure by the Government is subject to the restrictions set forth in this Agreement. +Warranties and Disclaimers +This publication and/or website may include technical or typographical errors or other inaccuracies. Changes are periodically added to the information herein; these changes will be incorporated in new editions of the publication and/or website. Unicode, Inc. may make improvements and/or changes in the product(s) and/or program(s) described in this publication and/or website at any time. +If this file has been purchased on magnetic or optical media from Unicode, Inc. the sole and exclusive remedy for any claim will be exchange of the defective media within ninety (90) days of original purchase. +EXCEPT AS PROVIDED IN SECTION E.2, THIS PUBLICATION AND/OR SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND EITHER EXPRESS, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. UNICODE, INC. AND ITS LICENSORS ASSUME NO RESPONSIBILITY FOR ERRORS OR OMISSIONS IN THIS PUBLICATION AND/OR SOFTWARE OR OTHER DOCUMENTS WHICH ARE REFERENCED BY OR LINKED TO THIS PUBLICATION OR THE UNICODE WEBSITE. +Waiver of Damages +In no event shall Unicode, Inc. or its licensors be liable for any special, incidental, indirect or consequential damages of any kind, or any damages whatsoever, whether or not Unicode, Inc. was advised of the possibility of the damage, including, without limitation, those resulting from the following: loss of use, data or profits, in connection with the use, modification or distribution of this information or its derivatives. +Trademarks & Logos +The Unicode Word Mark and the Unicode Logo are trademarks of Unicode, Inc. “The Unicode Consortium” and “Unicode, Inc.” are trade names of Unicode, Inc. Use of the information and materials found on this website indicates your acknowledgement of Unicode, Inc.’s exclusive worldwide rights in the Unicode Word Mark, the Unicode Logo, and the Unicode trade names. +The Unicode Consortium Name and Trademark Usage Policy (“Trademark Policy”) are incorporated herein by reference and you agree to abide by the provisions of the Trademark Policy, which may be changed from time to time in the sole discretion of Unicode, Inc. +All third party trademarks referenced herein are the property of their respective owners. +Miscellaneous +Jurisdiction and Venue. This website is operated from a location in the State of California, United States of America. Unicode, Inc. makes no representation that the materials are appropriate for use in other locations. If you access this website from other locations, you are responsible for compliance with local laws. This Agreement, all use of this website and any claims and damages resulting from use of this website are governed solely by the laws of the State of California without regard to any principles which would apply the laws of a different jurisdiction. The user agrees that any disputes regarding this website shall be resolved solely in the courts located in Santa Clara County, California. The user agrees said courts have personal jurisdiction and agree to waive any right to transfer the dispute to any other forum. +Modification by Unicode, Inc. Unicode, Inc. shall have the right to modify this Agreement at any time by posting it to this website. The user may not assign any part of this Agreement without Unicode, Inc.’s prior written consent. +Taxes. The user agrees to pay any taxes arising from access to this website or use of the information herein, except for those based on Unicode’s net income. +Severability. If any provision of this Agreement is declared invalid or unenforceable, the remaining provisions of this Agreement shall remain in effect. +Entire Agreement. This Agreement constitutes the entire agreement between the parties. + + ``` diff --git a/test/jdk/java/lang/Character/UnicodeBlock/OptimalMapSize.java b/test/jdk/java/lang/Character/UnicodeBlock/OptimalMapSize.java index 8883f0d8263..abe63eb0b7c 100644 --- a/test/jdk/java/lang/Character/UnicodeBlock/OptimalMapSize.java +++ b/test/jdk/java/lang/Character/UnicodeBlock/OptimalMapSize.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, 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 8080535 8191410 8215194 8221431 8239383 + * @bug 8080535 8191410 8215194 8221431 8239383 8268081 * @summary Expected size of Character.UnicodeBlock.map is not optimal * @library /test/lib * @modules java.base/java.lang:open @@ -48,13 +48,14 @@ import jdk.test.lib.util.OptimalCapacity; // As of Unicode 11, 667 entries are expected. // As of Unicode 12.1, 676 entries are expected. // As of Unicode 13.0, 684 entries are expected. +// As of Unicode 14.0, 696 entries are expected. // // Initialization of the map and this test will have to be adjusted // accordingly then. // // Note that HashMap's implementation aligns the initial capacity to // a power of two size, so it will end up 1024 (and thus succeed) in -// cases, such as 638, 667, 676, and 684. +// cases, such as 638, 667, 676, 684, and 696. public class OptimalMapSize { public static void main(String[] args) throws Throwable { @@ -63,7 +64,7 @@ public class OptimalMapSize { Field f = Character.UnicodeBlock.class.getDeclaredField("NUM_ENTITIES"); f.setAccessible(true); int num_entities = f.getInt(null); - assert num_entities == 684; + assert num_entities == 696; int initialCapacity = (int)(num_entities / 0.75f + 1.0f); OptimalCapacity.ofHashMap(Character.UnicodeBlock.class, -- GitLab From d70545d71080d534fefd3c9652656549f689f620 Mon Sep 17 00:00:00 2001 From: Ludvig Janiuk Date: Wed, 12 Jan 2022 19:24:52 +0000 Subject: [PATCH 090/564] 8258603: c1 IR::verify is expensive Reviewed-by: chagedorn, kvn --- src/hotspot/share/c1/c1_IR.cpp | 122 ++++++++++++++++++------ src/hotspot/share/c1/c1_IR.hpp | 7 +- src/hotspot/share/c1/c1_Instruction.hpp | 3 +- src/hotspot/share/c1/c1_Optimizer.cpp | 48 +++++++++- 4 files changed, 145 insertions(+), 35 deletions(-) diff --git a/src/hotspot/share/c1/c1_IR.cpp b/src/hotspot/share/c1/c1_IR.cpp index 11208901980..78aef07b4cf 100644 --- a/src/hotspot/share/c1/c1_IR.cpp +++ b/src/hotspot/share/c1/c1_IR.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2022, 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 @@ -1263,21 +1263,36 @@ void IR::print(bool cfg_only, bool live_only) { tty->print_cr("invalid IR"); } } +#endif // PRODUCT +#ifdef ASSERT class EndNotNullValidator : public BlockClosure { public: - EndNotNullValidator(IR* hir) { - hir->start()->iterate_postorder(this); + virtual void block_do(BlockBegin* block) { + assert(block->end() != NULL, "Expect block end to exist."); } +}; - void block_do(BlockBegin* block) { - assert(block->end() != NULL, "Expect block end to exist."); +class XentryFlagValidator : public BlockClosure { + public: + virtual void block_do(BlockBegin* block) { + for (int i = 0; i < block->end()->number_of_sux(); i++) { + assert(!block->end()->sux_at(i)->is_set(BlockBegin::exception_entry_flag), "must not be xhandler"); + } + for (int i = 0; i < block->number_of_exception_handlers(); i++) { + assert(block->exception_handler_at(i)->is_set(BlockBegin::exception_entry_flag), "must be xhandler"); + } } }; typedef GrowableArray BlockListList; -class PredecessorValidator : public BlockClosure { +// Validation goals: +// - code() length == blocks length +// - code() contents == blocks content +// - Each block's computed predecessors match sux lists (length) +// - Each block's computed predecessors match sux lists (set content) +class PredecessorAndCodeValidator : public BlockClosure { private: BlockListList* _predecessors; // Each index i will hold predecessors of block with id i BlockList* _blocks; @@ -1287,7 +1302,7 @@ class PredecessorValidator : public BlockClosure { } public: - PredecessorValidator(IR* hir) { + PredecessorAndCodeValidator(IR* hir) { ResourceMark rm; _predecessors = new BlockListList(BlockBegin::number_of_blocks(), BlockBegin::number_of_blocks(), NULL); _blocks = new BlockList(BlockBegin::number_of_blocks()); @@ -1308,20 +1323,10 @@ class PredecessorValidator : public BlockClosure { virtual void block_do(BlockBegin* block) { _blocks->append(block); - verify_successor_xentry_flag(block); collect_predecessors(block); } private: - void verify_successor_xentry_flag(const BlockBegin* block) const { - for (int i = 0; i < block->end()->number_of_sux(); i++) { - assert(!block->end()->sux_at(i)->is_set(BlockBegin::exception_entry_flag), "must not be xhandler"); - } - for (int i = 0; i < block->number_of_exception_handlers(); i++) { - assert(block->exception_handler_at(i)->is_set(BlockBegin::exception_entry_flag), "must be xhandler"); - } - } - void collect_predecessors(BlockBegin* block) { for (int i = 0; i < block->end()->number_of_sux(); i++) { collect_predecessor(block, block->end()->sux_at(i)); @@ -1363,26 +1368,87 @@ class PredecessorValidator : public BlockClosure { }; class VerifyBlockBeginField : public BlockClosure { - public: - - virtual void block_do(BlockBegin *block) { - for ( Instruction *cur = block; cur != NULL; cur = cur->next()) { + virtual void block_do(BlockBegin* block) { + for (Instruction* cur = block; cur != NULL; cur = cur->next()) { assert(cur->block() == block, "Block begin is not correct"); } } }; -void IR::verify() { -#ifdef ASSERT - PredecessorValidator pv(this); - EndNotNullValidator(this); +class ValidateEdgeMutuality : public BlockClosure { + public: + virtual void block_do(BlockBegin* block) { + for (int i = 0; i < block->end()->number_of_sux(); i++) { + assert(block->end()->sux_at(i)->is_predecessor(block), "Block's successor should have it as predecessor"); + } + + for (int i = 0; i < block->number_of_exception_handlers(); i++) { + assert(block->exception_handler_at(i)->is_predecessor(block), "Block's exception handler should have it as predecessor"); + } + + for (int i = 0; i < block->number_of_preds(); i++) { + assert(block->pred_at(i) != NULL, "Predecessor must exist"); + assert(block->pred_at(i)->end() != NULL, "Predecessor end must exist"); + bool is_sux = block->pred_at(i)->end()->is_sux(block); + bool is_xhandler = block->pred_at(i)->is_exception_handler(block); + assert(is_sux || is_xhandler, "Block's predecessor should have it as successor or xhandler"); + } + } +}; + +void IR::expand_with_neighborhood(BlockList& blocks) { + int original_size = blocks.length(); + for (int h = 0; h < original_size; h++) { + BlockBegin* block = blocks.at(h); + + for (int i = 0; i < block->end()->number_of_sux(); i++) { + if (!blocks.contains(block->end()->sux_at(i))) { + blocks.append(block->end()->sux_at(i)); + } + } + + for (int i = 0; i < block->number_of_preds(); i++) { + if (!blocks.contains(block->pred_at(i))) { + blocks.append(block->pred_at(i)); + } + } + + for (int i = 0; i < block->number_of_exception_handlers(); i++) { + if (!blocks.contains(block->exception_handler_at(i))) { + blocks.append(block->exception_handler_at(i)); + } + } + } +} + +void IR::verify_local(BlockList& blocks) { + EndNotNullValidator ennv; + blocks.iterate_forward(&ennv); + + ValidateEdgeMutuality vem; + blocks.iterate_forward(&vem); + VerifyBlockBeginField verifier; - this->iterate_postorder(&verifier); -#endif + blocks.iterate_forward(&verifier); } -#endif // PRODUCT +void IR::verify() { + XentryFlagValidator xe; + iterate_postorder(&xe); + + PredecessorAndCodeValidator pv(this); + + EndNotNullValidator ennv; + iterate_postorder(&ennv); + + ValidateEdgeMutuality vem; + iterate_postorder(&vem); + + VerifyBlockBeginField verifier; + iterate_postorder(&verifier); +} +#endif // ASSERT void SubstitutionResolver::visit(Value* v) { Value v0 = *v; diff --git a/src/hotspot/share/c1/c1_IR.hpp b/src/hotspot/share/c1/c1_IR.hpp index 31f44411280..1c759a8bee2 100644 --- a/src/hotspot/share/c1/c1_IR.hpp +++ b/src/hotspot/share/c1/c1_IR.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2022, 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 @@ -342,7 +342,10 @@ class IR: public CompilationResourceObj { // debugging static void print(BlockBegin* start, bool cfg_only, bool live_only = false) PRODUCT_RETURN; void print(bool cfg_only, bool live_only = false) PRODUCT_RETURN; - void verify() PRODUCT_RETURN; + + void expand_with_neighborhood(BlockList& blocks) NOT_DEBUG_RETURN; + void verify_local(BlockList&) NOT_DEBUG_RETURN; + void verify() NOT_DEBUG_RETURN; }; diff --git a/src/hotspot/share/c1/c1_Instruction.hpp b/src/hotspot/share/c1/c1_Instruction.hpp index 932b79792a5..1646557018f 100644 --- a/src/hotspot/share/c1/c1_Instruction.hpp +++ b/src/hotspot/share/c1/c1_Instruction.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2022, 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 @@ -1822,6 +1822,7 @@ BASE(BlockEnd, StateSplit) // successors int number_of_sux() const { return _sux != NULL ? _sux->length() : 0; } BlockBegin* sux_at(int i) const { return _sux->at(i); } + bool is_sux(BlockBegin* sux) const { return _sux == NULL ? false : _sux->contains(sux); } BlockBegin* default_sux() const { return sux_at(number_of_sux() - 1); } void substitute_sux(BlockBegin* old_sux, BlockBegin* new_sux); }; diff --git a/src/hotspot/share/c1/c1_Optimizer.cpp b/src/hotspot/share/c1/c1_Optimizer.cpp index e406a530b73..e741cf90f92 100644 --- a/src/hotspot/share/c1/c1_Optimizer.cpp +++ b/src/hotspot/share/c1/c1_Optimizer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2022, 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 @@ -180,6 +180,25 @@ void CE_Eliminator::block_do(BlockBegin* block) { return; } +#ifdef ASSERT +#define DO_DELAYED_VERIFICATION + /* + * We need to verify the internal representation after modifying it. + * Verifying only the blocks that have been tampered with is cheaper than verifying the whole graph, but we must + * capture blocks_to_verify_later before making the changes, since they might not be reachable afterwards. + * DO_DELAYED_VERIFICATION ensures that the code for this is either enabled in full, or not at all. + */ +#endif // ASSERT + +#ifdef DO_DELAYED_VERIFICATION + BlockList blocks_to_verify_later; + blocks_to_verify_later.append(block); + blocks_to_verify_later.append(t_block); + blocks_to_verify_later.append(f_block); + blocks_to_verify_later.append(sux); + _hir->expand_with_neighborhood(blocks_to_verify_later); +#endif // DO_DELAYED_VERIFICATION + // 2) substitute conditional expression // with an IfOp followed by a Goto // cut if_ away and get node before @@ -248,7 +267,10 @@ void CE_Eliminator::block_do(BlockBegin* block) { tty->print_cr("%d. IfOp in B%d", ifop_count(), block->block_id()); } - _hir->verify(); +#ifdef DO_DELAYED_VERIFICATION + _hir->verify_local(blocks_to_verify_later); +#endif // DO_DELAYED_VERIFICATION + } Value CE_Eliminator::make_ifop(Value x, Instruction::Condition cond, Value y, Value tval, Value fval) { @@ -312,6 +334,7 @@ void Optimizer::eliminate_conditional_expressions() { CE_Eliminator ce(ir()); } +// This removes others' relation to block, but doesnt empty block's lists void disconnect_from_graph(BlockBegin* block) { for (int p = 0; p < block->number_of_preds(); p++) { BlockBegin* pred = block->pred_at(p); @@ -387,6 +410,12 @@ class BlockMerger: public BlockClosure { assert(sux_state->caller_state() == end_state->caller_state(), "caller not equal"); #endif +#ifdef DO_DELAYED_VERIFICATION + BlockList blocks_to_verify_later; + blocks_to_verify_later.append(block); + _hir->expand_with_neighborhood(blocks_to_verify_later); +#endif // DO_DELAYED_VERIFICATION + // find instruction before end & append first instruction of sux block Instruction* prev = end->prev(); Instruction* next = sux->next(); @@ -396,6 +425,9 @@ class BlockMerger: public BlockClosure { // disconnect this block from all other blocks disconnect_from_graph(sux); +#ifdef DO_DELAYED_VERIFICATION + blocks_to_verify_later.remove(sux); // Sux is not part of graph anymore +#endif // DO_DELAYED_VERIFICATION block->set_end(sux->end()); // TODO Should this be done in set_end universally? @@ -404,6 +436,7 @@ class BlockMerger: public BlockClosure { BlockBegin* xhandler = sux->exception_handler_at(k); block->add_exception_handler(xhandler); + // TODO This should be in disconnect from graph... // also substitute predecessor of exception handler assert(xhandler->is_predecessor(sux), "missing predecessor"); xhandler->remove_predecessor(sux); @@ -419,7 +452,9 @@ class BlockMerger: public BlockClosure { _merge_count, block->block_id(), sux->block_id(), sux->state()->stack_size()); } - _hir->verify(); +#ifdef DO_DELAYED_VERIFICATION + _hir->verify_local(blocks_to_verify_later); +#endif // DO_DELAYED_VERIFICATION If* if_ = block->end()->as_If(); if (if_) { @@ -469,7 +504,9 @@ class BlockMerger: public BlockClosure { tty->print_cr("%d. replaced If and IfOp at end of B%d with single If", _merge_count, block->block_id()); } - _hir->verify(); +#ifdef DO_DELAYED_VERIFICATION + _hir->verify_local(blocks_to_verify_later); +#endif // DO_DELAYED_VERIFICATION } } } @@ -485,6 +522,9 @@ class BlockMerger: public BlockClosure { } }; +#ifdef ASSERT +#undef DO_DELAYED_VERIFICATION +#endif // ASSERT void Optimizer::eliminate_blocks() { // merge blocks if possible -- GitLab From 1228b2f1f8737a363ab6a7065b24e9f972441b27 Mon Sep 17 00:00:00 2001 From: Yumin Qi Date: Thu, 13 Jan 2022 00:23:05 +0000 Subject: [PATCH 091/564] 8261455: Automatically generate the CDS archive if necessary Reviewed-by: iklam, ccheung --- src/hotspot/share/cds/dynamicArchive.cpp | 4 +- src/hotspot/share/cds/filemap.cpp | 115 ++- src/hotspot/share/cds/filemap.hpp | 5 +- src/hotspot/share/cds/metaspaceShared.cpp | 18 +- src/hotspot/share/runtime/arguments.cpp | 28 +- src/hotspot/share/runtime/globals.hpp | 5 +- .../jtreg/runtime/cds/appcds/MoveJDKTest.java | 115 +-- .../cds/appcds/SharedArchiveConsistency.java | 6 +- .../DynamicArchiveTestBase.java | 16 +- .../TestAutoCreateSharedArchive.java | 693 ++++++++++++++++++ ...toCreateSharedArchiveNoDefaultArchive.java | 147 ++++ .../lib/jdk/test/lib/cds/CDSArchiveUtils.java | 14 +- test/lib/jdk/test/lib/cds/CDSTestUtils.java | 79 +- 13 files changed, 1074 insertions(+), 171 deletions(-) create mode 100644 test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchive.java create mode 100644 test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchiveNoDefaultArchive.java diff --git a/src/hotspot/share/cds/dynamicArchive.cpp b/src/hotspot/share/cds/dynamicArchive.cpp index 8592e076c7f..eb99176405f 100644 --- a/src/hotspot/share/cds/dynamicArchive.cpp +++ b/src/hotspot/share/cds/dynamicArchive.cpp @@ -187,7 +187,7 @@ public: }; void DynamicArchiveBuilder::init_header() { - FileMapInfo* mapinfo = new FileMapInfo(false); + FileMapInfo* mapinfo = new FileMapInfo(_archive_name, false); assert(FileMapInfo::dynamic_info() == mapinfo, "must be"); FileMapInfo* base_info = FileMapInfo::current_info(); // header only be available after populate_header @@ -327,7 +327,7 @@ void DynamicArchiveBuilder::write_archive(char* serialized_data) { FileMapInfo* dynamic_info = FileMapInfo::dynamic_info(); assert(dynamic_info != NULL, "Sanity"); - dynamic_info->open_for_write(_archive_name); + dynamic_info->open_for_write(); ArchiveBuilder::write_archive(dynamic_info, NULL, NULL, NULL, NULL); address base = _requested_dynamic_archive_bottom; diff --git a/src/hotspot/share/cds/filemap.cpp b/src/hotspot/share/cds/filemap.cpp index f4a9b8dec03..0011157e7f7 100644 --- a/src/hotspot/share/cds/filemap.cpp +++ b/src/hotspot/share/cds/filemap.cpp @@ -166,8 +166,9 @@ template static void get_header_version(char (&header_version) [N]) { assert(header_version[JVM_IDENT_MAX-1] == 0, "must be"); } -FileMapInfo::FileMapInfo(bool is_static) { +FileMapInfo::FileMapInfo(const char* full_path, bool is_static) { memset((void*)this, 0, sizeof(FileMapInfo)); + _full_path = full_path; _is_static = is_static; if (_is_static) { assert(_current_info == NULL, "must be singleton"); // not thread safe @@ -188,6 +189,9 @@ FileMapInfo::~FileMapInfo() { assert(_dynamic_archive_info == this, "must be singleton"); // not thread safe _dynamic_archive_info = NULL; } + if (_file_open) { + os::close(_fd); + } } void FileMapInfo::populate_header(size_t core_region_alignment) { @@ -1049,11 +1053,20 @@ void FileMapInfo::validate_non_existent_class_paths() { class FileHeaderHelper { int _fd; bool _is_valid; + bool _is_static; GenericCDSFileMapHeader* _header; + const char* _archive_name; const char* _base_archive_name; public: - FileHeaderHelper() : _fd(-1), _is_valid(false), _header(nullptr), _base_archive_name(nullptr) {} + FileHeaderHelper(const char* archive_name, bool is_static) { + _fd = -1; + _is_valid = false; + _header = nullptr; + _base_archive_name = nullptr; + _archive_name = archive_name; + _is_static = is_static; + } ~FileHeaderHelper() { if (_fd != -1) { @@ -1061,11 +1074,11 @@ public: } } - bool initialize(const char* archive_name) { - log_info(cds)("Opening shared archive: %s", archive_name); - _fd = os::open(archive_name, O_RDONLY | O_BINARY, 0); + bool initialize() { + assert(_archive_name != nullptr, "Archive name is NULL"); + _fd = os::open(_archive_name, O_RDONLY | O_BINARY, 0); if (_fd < 0) { - FileMapInfo::fail_continue("Specified shared archive not found (%s)", archive_name); + FileMapInfo::fail_continue("Specified shared archive not found (%s)", _archive_name); return false; } return initialize(_fd); @@ -1073,9 +1086,8 @@ public: // for an already opened file, do not set _fd bool initialize(int fd) { - assert(fd != -1, "Archive should be opened"); - - + assert(_archive_name != nullptr, "Archive name is NULL"); + assert(fd != -1, "Archive must be opened already"); // First read the generic header so we know the exact size of the actual header. GenericCDSFileMapHeader gen_header; size_t size = sizeof(GenericCDSFileMapHeader); @@ -1098,6 +1110,11 @@ public: return false; } + if (gen_header._version != CURRENT_CDS_ARCHIVE_VERSION) { + FileMapInfo::fail_continue("The shared archive file version %d does not match the required version %d", + gen_header._version, CURRENT_CDS_ARCHIVE_VERSION); + } + size_t filelen = os::lseek(fd, 0, SEEK_END); if (gen_header._header_size >= filelen) { FileMapInfo::fail_continue("Archive file header larger than archive file"); @@ -1203,28 +1220,6 @@ public: } }; -bool FileMapInfo::check_archive(const char* archive_name, bool is_static) { - FileHeaderHelper file_helper; - if (!file_helper.initialize(archive_name)) { - // Any errors are reported by fail_continue(). - return false; - } - - GenericCDSFileMapHeader* header = file_helper.get_generic_file_header(); - if (is_static) { - if (header->_magic != CDS_ARCHIVE_MAGIC) { - fail_continue("Not a base shared archive: %s", archive_name); - return false; - } - } else { - if (header->_magic != CDS_DYNAMIC_ARCHIVE_MAGIC) { - fail_continue("Not a top shared archive: %s", archive_name); - return false; - } - } - return true; -} - // Return value: // false: // is not a valid archive. *base_archive_name is set to null. @@ -1234,15 +1229,18 @@ bool FileMapInfo::check_archive(const char* archive_name, bool is_static) { // is a valid dynamic archive. bool FileMapInfo::get_base_archive_name_from_header(const char* archive_name, char** base_archive_name) { - FileHeaderHelper file_helper; + FileHeaderHelper file_helper(archive_name, false); *base_archive_name = NULL; - if (!file_helper.initialize(archive_name)) { + if (!file_helper.initialize()) { return false; } GenericCDSFileMapHeader* header = file_helper.get_generic_file_header(); if (header->_magic != CDS_DYNAMIC_ARCHIVE_MAGIC) { assert(header->_magic == CDS_ARCHIVE_MAGIC, "must be"); + if (AutoCreateSharedArchive) { + log_warning(cds)("AutoCreateSharedArchive is ignored because %s is a static archive", archive_name); + } return true; } @@ -1259,19 +1257,23 @@ bool FileMapInfo::get_base_archive_name_from_header(const char* archive_name, // Read the FileMapInfo information from the file. bool FileMapInfo::init_from_file(int fd) { - FileHeaderHelper file_helper; + FileHeaderHelper file_helper(_full_path, _is_static); if (!file_helper.initialize(fd)) { fail_continue("Unable to read the file header."); return false; } GenericCDSFileMapHeader* gen_header = file_helper.get_generic_file_header(); - unsigned int expected_magic = is_static() ? CDS_ARCHIVE_MAGIC : CDS_DYNAMIC_ARCHIVE_MAGIC; - if (gen_header->_magic != expected_magic) { - log_info(cds)("_magic expected: 0x%08x", expected_magic); - log_info(cds)(" actual: 0x%08x", gen_header->_magic); - FileMapInfo::fail_continue("The shared archive file has a bad magic number."); - return false; + if (_is_static) { + if (gen_header->_magic != CDS_ARCHIVE_MAGIC) { + FileMapInfo::fail_continue("Not a base shared archive: %s", _full_path); + return false; + } + } else { + if (gen_header->_magic != CDS_DYNAMIC_ARCHIVE_MAGIC) { + FileMapInfo::fail_continue("Not a top shared archive: %s", _full_path); + return false; + } } _header = (FileMapHeader*)os::malloc(gen_header->_header_size, mtInternal); @@ -1348,11 +1350,6 @@ bool FileMapInfo::open_for_read() { if (_file_open) { return true; } - if (is_static()) { - _full_path = Arguments::GetSharedArchivePath(); - } else { - _full_path = Arguments::GetSharedDynamicArchivePath(); - } log_info(cds)("trying to map %s", _full_path); int fd = os::open(_full_path, O_RDONLY | O_BINARY, 0); if (fd < 0) { @@ -1374,12 +1371,7 @@ bool FileMapInfo::open_for_read() { // Write the FileMapInfo information to the file. -void FileMapInfo::open_for_write(const char* path) { - if (path == NULL) { - _full_path = Arguments::GetSharedArchivePath(); - } else { - _full_path = path; - } +void FileMapInfo::open_for_write() { LogMessage(cds) msg; if (msg.is_info()) { msg.info("Dumping shared data to file: "); @@ -2364,15 +2356,20 @@ bool FileMapInfo::initialize() { return false; } - if (!open_for_read()) { - return false; - } - if (!init_from_file(_fd)) { - return false; - } - if (!validate_header()) { - return false; + if (!open_for_read() || !init_from_file(_fd) || !validate_header()) { + if (_is_static) { + FileMapInfo::fail_continue("Initialize static archive failed."); + return false; + } else { + FileMapInfo::fail_continue("Initialize dynamic archive failed."); + if (AutoCreateSharedArchive) { + DynamicDumpSharedSpaces = true; + ArchiveClassesAtExit = Arguments::GetSharedDynamicArchivePath(); + } + return false; + } } + return true; } diff --git a/src/hotspot/share/cds/filemap.hpp b/src/hotspot/share/cds/filemap.hpp index a8afe5dbdfd..d29c240b192 100644 --- a/src/hotspot/share/cds/filemap.hpp +++ b/src/hotspot/share/cds/filemap.hpp @@ -356,7 +356,6 @@ private: public: static bool get_base_archive_name_from_header(const char* archive_name, char** base_archive_name); - static bool check_archive(const char* archive_name, bool is_static); static SharedPathTable shared_path_table() { return _shared_path_table; } @@ -370,7 +369,7 @@ public: void log_paths(const char* msg, int start_idx, int end_idx); - FileMapInfo(bool is_static); + FileMapInfo(const char* full_apth, bool is_static); ~FileMapInfo(); // Accessors @@ -441,7 +440,7 @@ public: // File manipulation. bool initialize() NOT_CDS_RETURN_(false); bool open_for_read(); - void open_for_write(const char* path = NULL); + void open_for_write(); void write_header(); void write_region(int region, char* base, size_t size, bool read_only, bool allow_exec); diff --git a/src/hotspot/share/cds/metaspaceShared.cpp b/src/hotspot/share/cds/metaspaceShared.cpp index c56680997c2..c79e8df4200 100644 --- a/src/hotspot/share/cds/metaspaceShared.cpp +++ b/src/hotspot/share/cds/metaspaceShared.cpp @@ -556,7 +556,9 @@ void VM_PopulateDumpSharedSpace::doit() { builder.relocate_to_requested(); // Write the archive file - FileMapInfo* mapinfo = new FileMapInfo(true); + const char* static_archive = Arguments::GetSharedArchivePath(); + assert(static_archive != nullptr, "SharedArchiveFile not set?"); + FileMapInfo* mapinfo = new FileMapInfo(static_archive, true); mapinfo->populate_header(MetaspaceShared::core_region_alignment()); mapinfo->set_serialized_data(serialized_data); mapinfo->set_cloned_vtables(cloned_vtables); @@ -946,12 +948,17 @@ void MetaspaceShared::initialize_runtime_shared_and_meta_spaces() { _requested_base_address = static_mapinfo->requested_base_address(); if (dynamic_mapped) { FileMapInfo::set_shared_path_table(dynamic_mapinfo); + // turn AutoCreateSharedArchive off if successfully mapped + AutoCreateSharedArchive = false; } else { FileMapInfo::set_shared_path_table(static_mapinfo); } } else { set_shared_metaspace_range(NULL, NULL, NULL); UseSharedSpaces = false; + // The base archive cannot be mapped. We cannot dump the dynamic shared archive. + AutoCreateSharedArchive = false; + DynamicDumpSharedSpaces = false; FileMapInfo::fail_continue("Unable to map shared spaces"); if (PrintSharedArchiveAndExit) { vm_exit_during_initialization("Unable to use shared archive."); @@ -967,7 +974,9 @@ void MetaspaceShared::initialize_runtime_shared_and_meta_spaces() { } FileMapInfo* MetaspaceShared::open_static_archive() { - FileMapInfo* mapinfo = new FileMapInfo(true); + const char* static_archive = Arguments::GetSharedArchivePath(); + assert(static_archive != nullptr, "SharedArchivePath is NULL"); + FileMapInfo* mapinfo = new FileMapInfo(static_archive, true); if (!mapinfo->initialize()) { delete(mapinfo); return NULL; @@ -979,11 +988,12 @@ FileMapInfo* MetaspaceShared::open_dynamic_archive() { if (DynamicDumpSharedSpaces) { return NULL; } - if (Arguments::GetSharedDynamicArchivePath() == NULL) { + const char* dynamic_archive = Arguments::GetSharedDynamicArchivePath(); + if (dynamic_archive == nullptr) { return NULL; } - FileMapInfo* mapinfo = new FileMapInfo(false); + FileMapInfo* mapinfo = new FileMapInfo(dynamic_archive, false); if (!mapinfo->initialize()) { delete(mapinfo); return NULL; diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index ddbf1f3f794..b3855b4a0da 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -3140,6 +3140,17 @@ jint Arguments::finalize_vm_init_args(bool patch_mod_javabase) { DynamicDumpSharedSpaces = true; } + if (AutoCreateSharedArchive) { + if (SharedArchiveFile == NULL) { + log_warning(cds)("-XX:+AutoCreateSharedArchive requires -XX:SharedArchiveFile"); + return JNI_ERR; + } + if (ArchiveClassesAtExit != NULL) { + log_warning(cds)("-XX:+AutoCreateSharedArchive does not work with ArchiveClassesAtExit"); + return JNI_ERR; + } + } + if (UseSharedSpaces && patch_mod_javabase) { no_shared_spaces("CDS is disabled when " JAVA_BASE_NAME " module is patched."); } @@ -3487,9 +3498,6 @@ void Arguments::extract_shared_archive_paths(const char* archive_path, char* cur_path = NEW_C_HEAP_ARRAY(char, len + 1, mtInternal); strncpy(cur_path, begin_ptr, len); cur_path[len] = '\0'; - if (!FileMapInfo::check_archive((const char*)cur_path, true /*is_static*/)) { - return; - } *base_archive_path = cur_path; begin_ptr = ++end_ptr; @@ -3501,9 +3509,6 @@ void Arguments::extract_shared_archive_paths(const char* archive_path, len = end_ptr - begin_ptr; cur_path = NEW_C_HEAP_ARRAY(char, len + 1, mtInternal); strncpy(cur_path, begin_ptr, len + 1); - if (!FileMapInfo::check_archive((const char*)cur_path, false /*is_static*/)) { - return; - } *top_archive_path = cur_path; } @@ -3556,7 +3561,16 @@ void Arguments::init_shared_archive_paths() { bool success = FileMapInfo::get_base_archive_name_from_header(SharedArchiveFile, &base_archive_path); if (!success) { - no_shared_spaces("invalid archive"); + // If +AutoCreateSharedArchive and the specified shared archive does not exist, + // regenerate the dynamic archive base on default archive. + if (AutoCreateSharedArchive && !os::file_exists(SharedArchiveFile)) { + DynamicDumpSharedSpaces = true; + ArchiveClassesAtExit = const_cast(SharedArchiveFile); + SharedArchivePath = get_default_shared_archive_path(); + SharedArchiveFile = nullptr; + } else { + no_shared_spaces("invalid archive"); + } } else if (base_archive_path == NULL) { // User has specified a single archive, which is a static archive. SharedArchivePath = const_cast(SharedArchiveFile); diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index 12df1142ee3..fad671e3d26 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -1802,6 +1802,9 @@ const intx ObjectAlignmentInBytes = 8; product(bool, RecordDynamicDumpInfo, false, \ "Record class info for jcmd VM.cds dynamic_dump") \ \ + product(bool, AutoCreateSharedArchive, false, \ + "Create shared archive at exit if cds mapping failed") \ + \ product(bool, PrintSharedArchiveAndExit, false, \ "Print shared archive file contents") \ \ diff --git a/test/hotspot/jtreg/runtime/cds/appcds/MoveJDKTest.java b/test/hotspot/jtreg/runtime/cds/appcds/MoveJDKTest.java index c5ad8e53873..b127fec8604 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/MoveJDKTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/MoveJDKTest.java @@ -47,37 +47,39 @@ public class MoveJDKTest { public static void main(String[] args) throws Exception { String java_home_src = System.getProperty("java.home"); String java_home_dst = CDSTestUtils.getOutputDir() + File.separator + "moved_jdk"; + String homeJava = java_home_src + File.separator + "bin" + File.separator + "java"; + String dstJava = java_home_dst + File.separator + "bin" + File.separator + "java"; TestCommon.startNewArchiveName(); String jsaFile = TestCommon.getCurrentArchiveName(); String jsaOpt = "-XX:SharedArchiveFile=" + jsaFile; { - ProcessBuilder pb = makeBuilder(java_home_src + "/bin/java", "-Xshare:dump", jsaOpt); + ProcessBuilder pb = CDSTestUtils.makeBuilder(homeJava, "-Xshare:dump", jsaOpt); TestCommon.executeAndLog(pb, "dump") .shouldHaveExitValue(0); } { - ProcessBuilder pb = makeBuilder(java_home_src + "/bin/java", - "-Xshare:auto", - jsaOpt, - "-Xlog:class+path=info", - "-version"); + ProcessBuilder pb = CDSTestUtils.makeBuilder(homeJava, + "-Xshare:auto", + jsaOpt, + "-Xlog:class+path=info", + "-version"); OutputAnalyzer out = TestCommon.executeAndLog(pb, "exec-src"); out.shouldHaveExitValue(0); out.shouldNotContain("shared class paths mismatch"); out.shouldNotContain("BOOT classpath mismatch"); } - clone(new File(java_home_src), new File(java_home_dst)); + CDSTestUtils.clone(new File(java_home_src), new File(java_home_dst)); System.out.println("============== Cloned JDK at " + java_home_dst); // Test runtime with cloned JDK { - ProcessBuilder pb = makeBuilder(java_home_dst + "/bin/java", - "-Xshare:auto", - jsaOpt, - "-Xlog:class+path=info", - "-version"); + ProcessBuilder pb = CDSTestUtils.makeBuilder(dstJava, + "-Xshare:auto", + jsaOpt, + "-Xlog:class+path=info", + "-version"); OutputAnalyzer out = TestCommon.executeAndLog(pb, "exec-dst"); out.shouldHaveExitValue(0); out.shouldNotContain("shared class paths mismatch"); @@ -89,21 +91,21 @@ public class MoveJDKTest { String fake_modules = copyFakeModulesFromHelloJar(); String dumptimeBootAppendOpt = "-Xbootclasspath/a:" + fake_modules; { - ProcessBuilder pb = makeBuilder(java_home_src + "/bin/java", - "-Xshare:dump", - dumptimeBootAppendOpt, - jsaOpt); + ProcessBuilder pb = CDSTestUtils.makeBuilder(homeJava, + "-Xshare:dump", + dumptimeBootAppendOpt, + jsaOpt); TestCommon.executeAndLog(pb, "dump") .shouldHaveExitValue(0); } { String runtimeBootAppendOpt = dumptimeBootAppendOpt + System.getProperty("path.separator") + helloJar; - ProcessBuilder pb = makeBuilder(java_home_dst + "/bin/java", - "-Xshare:auto", - runtimeBootAppendOpt, - jsaOpt, - "-Xlog:class+path=info", - "-version"); + ProcessBuilder pb = CDSTestUtils.makeBuilder(dstJava, + "-Xshare:auto", + runtimeBootAppendOpt, + jsaOpt, + "-Xlog:class+path=info", + "-version"); OutputAnalyzer out = TestCommon.executeAndLog(pb, "exec-dst"); out.shouldHaveExitValue(0); out.shouldNotContain("shared class paths mismatch"); @@ -111,78 +113,17 @@ public class MoveJDKTest { } // Test with no modules image in the /lib directory - renameModulesFile(java_home_dst); + String locDir = java_home_dst + File.separator + "lib"; + CDSTestUtils.rename(new File(locDir + File.separator + "modules"), + new File(locDir + File.separator + "orig-modules")); { - ProcessBuilder pb = makeBuilder(java_home_dst + "/bin/java", - "-version"); + ProcessBuilder pb = CDSTestUtils.makeBuilder(dstJava, "-version"); OutputAnalyzer out = TestCommon.executeAndLog(pb, "exec-missing-modules"); out.shouldHaveExitValue(1); out.shouldContain("Failed setting boot class path."); } } - // Do a cheap clone of the JDK. Most files can be sym-linked. However, $JAVA_HOME/bin/java and $JAVA_HOME/lib/.../libjvm.so" - // must be copied, because the java.home property is derived from the canonicalized paths of these 2 files. - static void clone(File src, File dst) throws Exception { - if (dst.exists()) { - if (!dst.isDirectory()) { - throw new RuntimeException("Not a directory :" + dst); - } - } else { - if (!dst.mkdir()) { - throw new RuntimeException("Cannot create directory: " + dst); - } - } - final String jvmLib = System.mapLibraryName("jvm"); - for (String child : src.list()) { - if (child.equals(".") || child.equals("..")) { - continue; - } - - File child_src = new File(src, child); - File child_dst = new File(dst, child); - if (child_dst.exists()) { - throw new RuntimeException("Already exists: " + child_dst); - } - if (child_src.isFile()) { - if (child.equals(jvmLib) || child.equals("java")) { - Files.copy(child_src.toPath(), /* copy data to -> */ child_dst.toPath()); - } else { - Files.createSymbolicLink(child_dst.toPath(), /* link to -> */ child_src.toPath()); - } - } else { - clone(child_src, child_dst); - } - } - } - - static void renameModulesFile(String javaHome) throws Exception { - String modulesDir = javaHome + File.separator + "lib"; - File origModules = new File(modulesDir, "modules"); - if (!origModules.exists()) { - throw new RuntimeException("modules file not found"); - } - - File renamedModules = new File(modulesDir, "orig_modules"); - if (renamedModules.exists()) { - throw new RuntimeException("found orig_modules unexpectedly"); - } - - boolean success = origModules.renameTo(renamedModules); - if (!success) { - throw new RuntimeException("rename modules file failed"); - } - } - - static ProcessBuilder makeBuilder(String... args) throws Exception { - System.out.print("["); - for (String s : args) { - System.out.print(" " + s); - } - System.out.println(" ]"); - return new ProcessBuilder(args); - } - private static String copyFakeModulesFromHelloJar() throws Exception { String outDir = CDSTestUtils.getOutputDir(); String newFile = "hello.modules"; diff --git a/test/hotspot/jtreg/runtime/cds/appcds/SharedArchiveConsistency.java b/test/hotspot/jtreg/runtime/cds/appcds/SharedArchiveConsistency.java index 0d5296801b2..fd0291f06e0 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/SharedArchiveConsistency.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/SharedArchiveConsistency.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2022, 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 @@ -181,9 +181,7 @@ public class SharedArchiveConsistency { copiedJsa = CDSArchiveUtils.copyArchiveFile(orgJsaFile, modVersion); CDSArchiveUtils.modifyHeaderIntField(copiedJsa, CDSArchiveUtils.offsetVersion(), version); output = shareAuto ? TestCommon.execAuto(execArgs) : TestCommon.execCommon(execArgs); - output.shouldContain("The shared archive file has the wrong version") - .shouldContain("_version expected: " + currentCDSArchiveVersion) - .shouldContain("actual: " + version); + output.shouldContain("The shared archive file version " + version + " does not match the required version " + currentCDSArchiveVersion); if (shareAuto) { output.shouldContain(HELLO_WORLD); } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/DynamicArchiveTestBase.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/DynamicArchiveTestBase.java index 050ccef88e2..f97a7b4a70f 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/DynamicArchiveTestBase.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/DynamicArchiveTestBase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,7 +37,6 @@ import sun.hotspot.WhiteBox; class DynamicArchiveTestBase { private static boolean executedIn_run = false; private static boolean autoMode = false; // -Xshare:auto - private static final WhiteBox WB = WhiteBox.getWhiteBox(); public static interface DynamicArchiveTest { @@ -96,6 +95,19 @@ class DynamicArchiveTestBase { return TestCommon.getNewArchiveName(stem); } + /** + * Excute a JVM to dump a base archive by + * -Xshare:dump -XX:SharedArchiveFile=baseArchiveName + */ + public static Result dumpBaseArchive(String baseArchiveName, String... cmdLineSuffix) + throws Exception + { + OutputAnalyzer output = TestCommon.dumpBaseArchive(baseArchiveName, cmdLineSuffix); + CDSOptions opts = new CDSOptions(); + opts.setXShareMode("dump"); + return new Result(opts, output); + } + /** * Execute a JVM using the base archive (given by baseArchiveName) with the command line * (given by cmdLineSuffix). At JVM exit, dump all eligible classes into the top archive diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchive.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchive.java new file mode 100644 index 00000000000..dd38cbfec08 --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchive.java @@ -0,0 +1,693 @@ +/* + * Copyright (c) 2022, 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 8261455 + * @summary test -XX:+AutoCreateSharedArchive feature + * @requires vm.cds + * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds /test/hotspot/jtreg/runtime/cds/appcds/test-classes + * @build Hello + * @build sun.hotspot.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar hello.jar Hello + * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar WhiteBox.jar sun.hotspot.WhiteBox + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:./WhiteBox.jar TestAutoCreateSharedArchive verifySharedSpacesOff + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:./WhiteBox.jar TestAutoCreateSharedArchive verifySharedSpacesOn + */ + +/* + * -XX:SharedArchiveFile can be specified in two styles: + * + * (A) Test with default base archive -XX:+SharedArchiveFile= + * (B) Test with the base archive specified: -XX:SharedArchiveFile=: + * all the following if not explained explicitly, run with flag -XX:+AutoCreateSharedArchive + * + * Note VerifySharedSpaces will affect output so the tests run twice: one with -XX:+VerifySharedSpaces and the other with -XX:-VerifySharedSpaces + * + * 10 Case (A) + * + * 10.01 run with non-existing archive should automatically create dynamic archive. + * If the JDK's default CDS archive cannot be loaded, print out warning, run continue without shared archive and no shared archive created at exit. + * 10.02 run with the created dynamic archive should pass. + * 10.03 run with the created dynamic archive and -XX:+AutoCreateSharedArchive should pass and no shared archive created at exit. + * + * 11 run with static archive. + * run with static archive should printout warning and continue, share or no share depends on the archive validation at exit, + * no shared archive (top) will be generated. + * + * 12 run with damaged magic should not regenerate dynamic archive. + * if magic is not expected, no shared archive will be regenerated at exit. + * + * 13 run with a bad versioned archive. + * 13.01 run with a bad versioned (< CDS_GENERIC_HEADER_SUPPORTED_MIN_VERSION) archive should not create dynamic archive at exit. + * 13.02 run with a bad versioned (> CDS_GENERIC_HEADER_SUPPORTED_MIN_VERSION) archive should create dynamic archive at exit. + * + * 14 run with an archive whose base name is not matched, no shared archive at exit. + * + * 15 run with an archive whose jvm_ident is corrupted should + * create dynamic archive at exit with -XX:-VerifySharedSpaces + * not create dynamic archive at exit with -XX:+VerifySharedSpaces + * + * 16 run with an archive only containing magic in the file (size of 4 bytes) + * the archive will be created at exit. + * + * 20 (case B) + * + * 20.01 dump base archive which will be used for dumping top archive. + * 20.02 dump top archive based on base archive obtained in 20.1. + * 20.03 run -XX:SharedArchiveFile=: to verify the archives. + * 20.04 run with -XX:SharedArchveFile=base:top (reversed) + * + * 21 Mismatched versions + * 21.01 if version of top archive is higher than CDS_GENERIC_HEADER_SUPPORTED_MIN_VERSION, the archive cannot be shared and will be + * regenerated at exit. + * 21.02 if version of top archive is lower than CDS_GENERIC_HEADER_SUPPORTED_MIN_VERSION, the archive cannot be shared and will be + * created at exit. + * + * 22 create an archive with dynamic magic number only + * archive will be created at exit if base can be shared. + * + * 23 mismatched jvm_indent in base/top archive + * 23.01 mismatched jvm_indent in top archive + * 23.02 mismatched jvm_indent in base archive + * + * 24 run with non-existing shared archives + * 24.01 run -Xshare:auto -XX:+AutoCreateSharedArchive -XX:SharedArchiveFile=base.jsa:non-exist-top.jsa + * The top archive will be regenerated. + * 24.02 run -Xshare:auto -XX:+AutoCreateSharedArchive -XX:SharedArchiveFile=non-exist-base.jsa:top.jsa + * top archive will not be shared if base archive failed to load. + */ + +import java.io.IOException; +import java.io.File; + +import java.nio.file.attribute.FileTime; +import java.nio.file.Files; +import java.nio.file.Paths; + +import jdk.test.lib.cds.CDSTestUtils; +import jdk.test.lib.cds.CDSArchiveUtils; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.helpers.ClassFileInstaller; + +public class TestAutoCreateSharedArchive extends DynamicArchiveTestBase { + private static final String BASE_NAME = CDSTestUtils.getOutputFileName("base.jsa"); + private static final String TOP_NAME = CDSTestUtils.getOutputFileName("top.jsa"); + private static final String mainAppClass = "Hello"; + private static final String HELLO_SOURCE = "Hello source: shared objects file (top)"; + private static final String HELLO_WORLD = "Hello World"; + private static boolean verifyOn = false; + + private static int genericHeaderMinVersion = CDSArchiveUtils.getGenericHeaderMinVersion(); + private static int currentCDSVersion = CDSArchiveUtils.getCurrentCDSArchiveVersion(); + + public static void main(String[] args) throws Exception { + if (args.length != 1 || (!args[0].equals("verifySharedSpacesOff") && !args[0].equals("verifySharedSpacesOn"))) { + throw new RuntimeException("Must run with verifySharedSpacesOff or verifySharedSpacesOn"); + } + verifyOn = args[0].equals("verifySharedSpacesOn"); + runTest(TestAutoCreateSharedArchive::testAutoCreateSharedArchive); + } + + public static void checkFileExists(String fileName) throws Exception { + File file = new File(fileName); + if (!file.exists()) { + throw new IOException("Archive " + fileName + " is not automatically created"); + } + } + + public static String startNewArchive(String testName) { + String newArchiveName = TestCommon.getNewArchiveName(testName); + TestCommon.setCurrentArchiveName(newArchiveName); + return newArchiveName; + } + + public static void print(String message) { + System.out.println(message); + } + + private static void testAutoCreateSharedArchive() throws Exception { + String appJar = ClassFileInstaller.getJarPath("hello.jar"); + boolean fileModified = false; + + String verifySharedSpaces = verifyOn ? "-XX:+VerifySharedSpaces" : "-XX:-VerifySharedSpaces"; + File archiveFile = new File(TOP_NAME); + if (archiveFile.exists()) { + archiveFile.delete(); + } + + // dump a static archive, used later. + // 0. Dump a static archive + print("0. dump a static archive " + BASE_NAME); + dumpBaseArchive(BASE_NAME, + "-Xlog:cds", + "-cp", appJar, + mainAppClass) + .assertNormalExit(output -> { + output.shouldHaveExitValue(0); + }); + checkFileExists(BASE_NAME); + + // The list numbers try to match JDK-8272331 (CSR for JDK-8261455) test items but not exactly matched. + + // 10 non-existing archive should automatically create dynamic archive based on default shared archive + // if base archive loaded. + print("10 Test with default base shared archive"); + print(" 10.01 run with non-existing archive should automatically create dynamic archive"); + File fileTop = new File(TOP_NAME); + if (fileTop.exists()) { + fileTop.delete(); + } + run(TOP_NAME, + "-Xshare:auto", + "-XX:+AutoCreateSharedArchive", + "-Xlog:cds", + "-cp", appJar, + mainAppClass) + .assertNormalExit(output -> { + output.shouldHaveExitValue(0) + .shouldContain(HELLO_WORLD) + .shouldContain("Dumping shared data to file:") + .shouldContain(TOP_NAME); + }); + checkFileExists(TOP_NAME); + + //10.02 run with the created dynamic archive should pass + print(" 10.02 run with the created dynamic archive should pass"); + run(TOP_NAME, + "-Xlog:cds", + "-Xlog:class+load", + "-cp", appJar, + mainAppClass) + .assertNormalExit(output -> { + output.shouldHaveExitValue(0) + .shouldContain(HELLO_WORLD) + .shouldContain(HELLO_SOURCE); + }); + // remember the FileTime + FileTime ft1 = Files.getLastModifiedTime(Paths.get(TOP_NAME)); + + // 10.03 run with the created dynamic archive with -XX:+AutoCreateSharedArchive should pass + // archive should not be created again. + print(" 10.03 run with the created dynamic archive with -XX:+AutoCreateSharedArchive should pass"); + run(TOP_NAME, + "-Xlog:cds", + "-Xlog:class+load", + "-Xlog:cds+dynamic=info", + "-XX:+AutoCreateSharedArchive", + "-cp", appJar, + mainAppClass) + .assertNormalExit(output -> { + output.shouldHaveExitValue(0) + .shouldContain(HELLO_WORLD) + .shouldContain(HELLO_SOURCE) + .shouldNotContain("Dumping shared data to file"); + }); + FileTime ft2 = Files.getLastModifiedTime(Paths.get(TOP_NAME)); + fileModified = !ft2.equals(ft1); + if (fileModified) { + throw new RuntimeException("Archive file " + TOP_NAME + " should not be updated"); + } + + // 11 run with static archive + print("11 run with static archive"); + ft1 = Files.getLastModifiedTime(Paths.get(BASE_NAME)); + run(BASE_NAME, + "-Xlog:cds", + "-Xlog:cds+dynamic=info", + "-Xshare:auto", + "-XX:+AutoCreateSharedArchive", + verifySharedSpaces, + "-cp", appJar, + mainAppClass) + .assertNormalExit(output -> { + output.shouldHaveExitValue(0) + .shouldContain(HELLO_WORLD) + .shouldContain("AutoCreateSharedArchive is ignored because " + BASE_NAME + " is a static archive") + .shouldNotContain("Dumping shared data to file"); + }); + ft2 = Files.getLastModifiedTime(Paths.get(BASE_NAME)); + fileModified = !ft1.equals(ft2); + if (fileModified) { + throw new RuntimeException("Run -XX:+AutoCreateSharedArchive on static archive create new archive"); + } + + // 12 run with damaged magic should not regenerate dynamic archive + print("12 run with damaged magic should not regenerate dynamic archive"); + String modMagic = startNewArchive("modify-magic"); + File copiedJsa = CDSArchiveUtils.copyArchiveFile(archiveFile, modMagic); + CDSArchiveUtils.modifyHeaderIntField(copiedJsa, CDSArchiveUtils.offsetMagic(), 0x1234); + ft1 = Files.getLastModifiedTime(Paths.get(modMagic)); + + run(modMagic, + "-Xshare:auto", + "-XX:+AutoCreateSharedArchive", + "-Xlog:cds", + "-Xlog:cds+dynamic=info", + verifySharedSpaces, + "-cp", appJar, + mainAppClass) + .assertNormalExit(output -> { + output.shouldHaveExitValue(0) + .shouldContain(HELLO_WORLD) + .shouldNotContain("Dumping shared data to file"); + }); + ft2 = Files.getLastModifiedTime(Paths.get(modMagic)); + fileModified = !ft1.equals(ft2); + if (fileModified) { + throw new RuntimeException("Shared archive " + modMagic + " should not automatically be generated"); + } + + // 13 run with a bad versioned (< genericHeaderMinVersion) archive + print("13 run with a bad versioned archive"); + print(" 13.01 run with a bad versioned (< genericHeaderMinVersion) archive should not create new archive"); + String modVersion = startNewArchive("modify-version-b"); + copiedJsa = CDSArchiveUtils.copyArchiveFile(archiveFile, modVersion); + final int version1 = genericHeaderMinVersion - 1; + CDSArchiveUtils.modifyHeaderIntField(copiedJsa, CDSArchiveUtils.offsetVersion(), version1); + ft1 = Files.getLastModifiedTime(Paths.get(modVersion)); + + run(modVersion, + "-Xshare:auto", + "-XX:+AutoCreateSharedArchive", + "-Xlog:cds", + "-Xlog:cds+dynamic=info", + verifySharedSpaces, + "-cp", appJar, + mainAppClass) + .assertNormalExit(output -> { + output.shouldHaveExitValue(0) + .shouldContain(HELLO_WORLD) + .shouldContain("Cannot handle shared archive file version " + version1 + ". Must be at least " + genericHeaderMinVersion) + .shouldContain("Unable to use shared archive: invalid archive") + .shouldNotContain("Dumping shared data to file"); + }); + ft2 = Files.getLastModifiedTime(Paths.get(modVersion)); + fileModified = !ft1.equals(ft2); + if (fileModified) { + throw new RuntimeException("Run -XX:+AutoCreateSharedArchive with lower version archive " + modVersion + " should not create new archive"); + } + // 13.02 run with a bad versioned (> currentCDSVersion) archive + print(" 13.02 run with a bad versioned (> currentCDSVersion) archive"); + modVersion = startNewArchive("modify-version-d"); + copiedJsa = CDSArchiveUtils.copyArchiveFile(archiveFile, modVersion); + final int version2 = currentCDSVersion + 1; + CDSArchiveUtils.modifyHeaderIntField(copiedJsa, CDSArchiveUtils.offsetVersion(), version2); + ft1 = Files.getLastModifiedTime(Paths.get(modVersion)); + + run(modVersion, + "-Xshare:auto", + "-XX:+AutoCreateSharedArchive", + "-Xlog:cds", + "-Xlog:cds+dynamic=info", + verifySharedSpaces, + "-cp", appJar, + mainAppClass) + .assertNormalExit(output -> { + output.shouldHaveExitValue(0) + .shouldContain(HELLO_WORLD) + .shouldContain("The shared archive file version " + version2 + " does not match the required version " + currentCDSVersion) + .shouldContain("UseSharedSpaces: The shared archive file has the wrong version") + .shouldContain("UseSharedSpaces: Initialize dynamic archive failed") + .shouldContain("Dumping shared data to file"); + }); + ft2 = Files.getLastModifiedTime(Paths.get(modVersion)); + fileModified = !ft1.equals(ft2); + if (!fileModified) { + throw new RuntimeException("Run -XX:+AutoCreateSharedArchive with higher version archive " + modVersion + " should create new archive"); + } + + // 14 run with an archive whose base name is not matched, no share + print("14 run with an archive whose base name is not matched, no share"); + String baseNameMismatch= startNewArchive("basename-mismatch"); + copiedJsa = CDSArchiveUtils.copyArchiveFile(archiveFile, baseNameMismatch); + int nameSize = CDSArchiveUtils.baseArchiveNameSize(copiedJsa); + int offset = CDSArchiveUtils.baseArchiveNameOffset(copiedJsa); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < nameSize - 4; i++) { + sb.append('Z'); + } + sb.append(".jsa"); + sb.append('\0'); + String newName = sb.toString(); + CDSArchiveUtils.writeData(copiedJsa, offset, newName.getBytes()); + + ft1 = Files.getLastModifiedTime(Paths.get(baseNameMismatch)); + run(baseNameMismatch, + "-Xshare:auto", + "-XX:+AutoCreateSharedArchive", + "-Xlog:cds", + "-Xlog:cds+dynamic=info", + verifySharedSpaces, + "-cp", appJar, + mainAppClass) + .assertNormalExit(output -> { + output.shouldHaveExitValue(0) + .shouldContain(HELLO_WORLD) + .shouldNotContain("Dumping shared data to file"); + }); + ft2 = Files.getLastModifiedTime(Paths.get(baseNameMismatch)); + + fileModified = !ft1.equals(ft2); + if (fileModified) { + throw new RuntimeException("Shared archive " + baseNameMismatch+ " should not automatically be generated"); + } + + // 15 mismatched jvm_indent in archive, create (-VerifySharedSpaces) or not (-XX:+VerifySharedSpaces) create the new archive + print("15 mismatched jvm_indent in archive, " + (verifyOn ? "-XX:+VerifySharedSpaces not " : "-XX:-VerifySharedSpaces ") + "create new archive"); + String modJvmIdent = startNewArchive("modify-jvmident"); + copiedJsa = CDSArchiveUtils.copyArchiveFile(archiveFile, modJvmIdent); + CDSArchiveUtils.modifyHeaderIntField(copiedJsa, CDSArchiveUtils.offsetJvmIdent(), 0x65656565); + ft1 = Files.getLastModifiedTime(Paths.get(modJvmIdent)); + + run(modJvmIdent, + "-Xshare:auto", + "-XX:+AutoCreateSharedArchive", + "-Xlog:cds", + "-Xlog:cds+dynamic=info", + verifySharedSpaces, + "-cp", appJar, + mainAppClass) + .assertNormalExit(output -> { + output.shouldHaveExitValue(0); + if (verifyOn) { + output.shouldContain("UseSharedSpaces: Header checksum verification failed") + .shouldContain("Unable to use shared archive: invalid archive") + .shouldNotContain("Dumping shared data to file"); + } else { + output.shouldContain(HELLO_WORLD) + .shouldContain("Dumping shared data to file"); + } + }); + ft2 = Files.getLastModifiedTime(Paths.get(modJvmIdent)); + fileModified = !ft1.equals(ft2); + if (verifyOn) { + if (fileModified) { + throw new RuntimeException("Shared archive " + modJvmIdent + " should not be generated"); + } + + } else { + if (!fileModified) { + throw new RuntimeException("Shared archive " + modJvmIdent + " should be generated"); + } + } + + // 16 run with an archive of only containing dynamic magic (size of 4) will not create new archive at exit + print("16 run with an archive of only containing dynamic magic (size of 4) will not create new archive at exit"); + String magicOnly = startNewArchive("magic-only"); + copiedJsa = CDSArchiveUtils.createMagicOnlyFile(magicOnly, false/*dynamic*/); + ft1 = Files.getLastModifiedTime(Paths.get(magicOnly)); + run(magicOnly, + "-Xshare:auto", + "-XX:+AutoCreateSharedArchive", + "-Xlog:cds", + "-Xlog:cds+dynamic=info", + "-cp", appJar, + mainAppClass) + .assertNormalExit(output -> { + output.shouldHaveExitValue(0) + .shouldContain(HELLO_WORLD) + .shouldContain("Unable to read generic CDS file map header from shared archive") + .shouldNotContain("Dumping shared data to file:"); + }); + ft2 = Files.getLastModifiedTime(Paths.get(magicOnly)); + fileModified = !ft1.equals(ft2); + if (fileModified) { + throw new RuntimeException("Shared archive " + magicOnly + " should not automatically be generated"); + } + + // Do some base tests for -XX:SharedArchiveFile=base:top, they should be same as default archive as base. + // delete top archive + if (archiveFile.exists()) { + archiveFile.delete(); + } + // delete base archive + File baseFile = new File(BASE_NAME); + if (baseFile.exists()) { + baseFile.delete(); + } + + // 20 Testing with -XX:SharedArchiveFile=base:top + print("20 Testing with -XX:SharedArchiveFile=base:top"); + // 20.01 dump base archive and top archive + print(" 20.01 dump base archive " + BASE_NAME); + dumpBaseArchive(BASE_NAME, "-Xlog:cds") + .assertNormalExit(output -> { + output.shouldHaveExitValue(0); + }); + checkFileExists(BASE_NAME); + + // 20.02 dump top based on base + print(" 20.02 dump top based on base"); + dump2(BASE_NAME, TOP_NAME, + "-Xlog:cds", + "-cp", appJar, mainAppClass) + .assertNormalExit(output -> { + output.shouldHaveExitValue(0) + .shouldContain("Dumping shared data to file:") + .shouldContain(TOP_NAME); + }); + checkFileExists(TOP_NAME); + + // 20.03 run with -XX:SharedArchveFile=base:top + print(" 20.03 run with -XX:SharedArchveFile=base:top"); + run2(BASE_NAME, TOP_NAME, + "-Xlog:cds", + "-Xlog:cds+dynamic=info", + "-Xlog:class+load", + "-cp", appJar, + mainAppClass) + .assertNormalExit(output -> { + output.shouldHaveExitValue(0) + .shouldContain(HELLO_SOURCE); + }); + + // 20.04 run with -XX:SharedArchveFile=top:base (reversed) + print(" 20.04 run with -XX:SharedArchveFile=top:base (reversed)"); + run2(TOP_NAME, BASE_NAME, + "-Xlog:cds", + "-Xlog:cds+dynamic=info", + "-Xlog:class+load", + "-cp", appJar, + mainAppClass) + .assertAbnormalExit(output -> { + output.shouldHaveExitValue(1) + .shouldContain("Not a base shared archive: " + TOP_NAME) + .shouldContain("An error has occurred while processing the shared archive file") + .shouldNotContain(HELLO_WORLD); + }); + + // 21 Mismatched versions + print("21 Mismatched versions"); + // 21.01 top version is lower than CDS_GENERIC_HEADER_SUPPORTED_MIN_VERSION, regenerate top + print(" 21.01 top version is lower than CDS_GENERIC_HEADER_SUPPORTED_MIN_VERSION, regenerate top"); + String versionB = startNewArchive("modify-version-B"); + archiveFile = new File(TOP_NAME); + copiedJsa = CDSArchiveUtils.copyArchiveFile(archiveFile, versionB); + CDSArchiveUtils.modifyHeaderIntField(copiedJsa, CDSArchiveUtils.offsetVersion(), version1); + ft1 = Files.getLastModifiedTime(Paths.get(versionB)); + + run2(BASE_NAME, versionB, + "-Xshare:auto", + "-XX:+AutoCreateSharedArchive", + "-Xlog:cds", + "-Xlog:cds+dynamic=info", + verifySharedSpaces, + "-cp", appJar, + mainAppClass) + .assertNormalExit(output -> { + output.shouldHaveExitValue(0) + .shouldContain(HELLO_WORLD) + .shouldContain("Cannot handle shared archive file version " + version1) + .shouldContain(versionB) + .shouldContain("Dumping shared data to file:"); + }); + ft2 = Files.getLastModifiedTime(Paths.get(versionB)); + fileModified = !ft1.equals(ft2); + if (!fileModified) { + throw new RuntimeException("Shared archive " + versionB + " should automatically be generated"); + } + + // 21.02 top version is higher than CDS_GENERIC_HEADER_SUPPORTED_MIN_VERSION, no share for top, create archive at exit + print(" 21.02 top version is higher than CDS_GENERIC_HEADER_SUPPORTED_MIN_VERSION, no share for top, create archive at exit"); + String versionF = startNewArchive("versionF"); + copiedJsa = CDSArchiveUtils.copyArchiveFile(archiveFile, versionF); + CDSArchiveUtils.modifyHeaderIntField(copiedJsa, CDSArchiveUtils.offsetVersion(), version2); + ft1 = Files.getLastModifiedTime(Paths.get(versionF)); + run2(BASE_NAME, versionF, + "-Xshare:auto", + "-XX:+AutoCreateSharedArchive", + "-Xlog:cds", + "-Xlog:cds+dynamic=info", + verifySharedSpaces, + "-cp", appJar, + mainAppClass) + .assertNormalExit(output -> { + output.shouldContain("The shared archive file version " + version2 + " does not match the required version " + currentCDSVersion) + .shouldContain(HELLO_WORLD) + .shouldContain("Dumping shared data to file:"); + }); + ft2 = Files.getLastModifiedTime(Paths.get(versionB)); + fileModified = !ft1.equals(ft2); + if (!fileModified) { + throw new RuntimeException("Shared archive " + versionB + " should be created at exit"); + } + + // 22 create an archive with dynamic magic number only + // archive will be created at exit if base can be shared. + print("22 create an archive with dynamic magic number only"); + copiedJsa = CDSArchiveUtils.createMagicOnlyFile(magicOnly, false /*dynamic*/); + ft1 = Files.getLastModifiedTime(Paths.get(magicOnly)); + run2(BASE_NAME, magicOnly, + "-Xshare:auto", + "-XX:+AutoCreateSharedArchive", + "-Xlog:cds", + "-Xlog:cds+dynamic=info", + verifySharedSpaces, + "-cp", appJar, + mainAppClass) + .assertNormalExit(output -> { + output.shouldContain(HELLO_WORLD) + .shouldContain("Unable to read generic CDS file map header from shared archive") + .shouldContain("Dumping shared data to file:"); + }); + ft2 = Files.getLastModifiedTime(Paths.get(magicOnly)); + fileModified = !ft1.equals(ft2); + if (!fileModified) { + throw new RuntimeException("Shared archive " + magicOnly + " should be created at exit"); + } + + // 23 mismatched jvm_indent in top or base archive + // 23.01 mismatched jvm_indent in top archive + print(" 23.01 mismatched jvm_indent in top archive"); + String modJvmIdentTop = startNewArchive("modify-jvmident-top"); + copiedJsa = CDSArchiveUtils.copyArchiveFile(archiveFile, modJvmIdentTop); + CDSArchiveUtils.modifyHeaderIntField(copiedJsa, CDSArchiveUtils.offsetJvmIdent(), 0x65656565); + ft1 = Files.getLastModifiedTime(Paths.get(modJvmIdentTop)); + + run2(BASE_NAME, modJvmIdentTop, + "-Xshare:auto", + "-XX:+AutoCreateSharedArchive", + "-Xlog:cds", + "-Xlog:cds+dynamic=info", + verifySharedSpaces, + "-cp", appJar, + mainAppClass) + .assertNormalExit(output -> { + output.shouldHaveExitValue(0); + if (verifyOn) { + output.shouldContain("UseSharedSpaces: Header checksum verification failed"); + } + output.shouldContain(HELLO_WORLD) + .shouldContain("Dumping shared data to file"); + }); + ft2 = Files.getLastModifiedTime(Paths.get(modJvmIdentTop)); + fileModified = !ft1.equals(ft2); + if (!fileModified) { + throw new RuntimeException("Shared archive " + modJvmIdentTop + " should be generated"); + } + // 23.02 mismatched jvm_indent in base archive + print(" 23.02 mismatched jvm_indent in base archive"); + String modJvmIdentBase = startNewArchive("modify-jvmident-base"); + copiedJsa = CDSArchiveUtils.copyArchiveFile(new File(BASE_NAME), modJvmIdentBase); + CDSArchiveUtils.modifyHeaderIntField(copiedJsa, CDSArchiveUtils.offsetJvmIdent(), 0x65656565); + ft1 = Files.getLastModifiedTime(Paths.get(TOP_NAME)); + + run2(modJvmIdentBase, TOP_NAME, + "-Xshare:auto", + "-XX:+AutoCreateSharedArchive", + "-Xlog:cds", + "-Xlog:cds+dynamic=info", + verifySharedSpaces, + "-cp", appJar, + mainAppClass) + .assertNormalExit(output -> { + output.shouldHaveExitValue(0) + .shouldContain(HELLO_WORLD); + if (verifyOn) { + output.shouldContain("UseSharedSpaces: Header checksum verification failed"); + } + output.shouldContain("Unable to map shared spaces") + .shouldNotContain("Dumping shared data to file"); + }); + ft2 = Files.getLastModifiedTime(Paths.get(TOP_NAME)); + fileModified = !ft1.equals(ft2); + if (fileModified) { + throw new RuntimeException("Shared archive " + TOP_NAME + " should not be generated"); + } + + // 24 run with non-existing shared archives + print("24 run with non-existing shared archives"); + // 24.01 run -Xshare:auto -XX:+AutoCreateSharedArchive -XX:SharedArchiveFile=base.jsa:non-exist-top.jsa + print(" 24.01 run -Xshare:auto -XX:+AutoCreateSharedArchive -XX:SharedArchiveFile=base.jsa:non-exist-top.jsa"); + String nonExistTop = "non-existing-top.jsa"; + File fileNonExist = new File(nonExistTop); + if (fileNonExist.exists()) { + fileNonExist.delete(); + } + run2(BASE_NAME, nonExistTop, + "-Xshare:auto", + "-XX:+AutoCreateSharedArchive", + "-Xlog:cds", + "-Xlog:cds+dynamic=info", + verifySharedSpaces, + "-cp", appJar, + mainAppClass) + .assertNormalExit(output -> { + output.shouldContain("Specified shared archive not found (" + nonExistTop + ")") + .shouldContain(HELLO_WORLD) + .shouldContain("Dumping shared data to file:"); + }); + if (!fileNonExist.exists()) { + throw new RuntimeException("Shared archive " + nonExistTop + " should be created at exit"); + } + + // 24.02 run -Xshare:auto -XX:+AutoCreateSharedArchive -XX:SharedArchiveFile=non-exist-base.jsa:top.jsa + print(" 24.02 run -Xshare:auto -XX:+AutoCreateSharedArchive -XX:SharedArchiveFile=non-exist-base.jsa:top.jsa"); + String nonExistBase = "non-existing-base.jsa"; + fileNonExist = new File(nonExistBase); + if (fileNonExist.exists()) { + fileNonExist.delete(); + } + ft1 = Files.getLastModifiedTime(Paths.get(TOP_NAME)); + run2(nonExistBase, TOP_NAME, + "-Xshare:auto", + "-XX:+AutoCreateSharedArchive", + "-Xlog:cds", + "-Xlog:cds+dynamic=info", + verifySharedSpaces, + "-cp", appJar, + mainAppClass) + .assertNormalExit(output -> { + output.shouldContain("Specified shared archive not found (" + nonExistBase + ")") + .shouldContain(HELLO_WORLD) + .shouldNotContain("Dumping shared data to file:"); + }); + ft2 = Files.getLastModifiedTime(Paths.get(TOP_NAME)); + fileModified = !ft1.equals(ft2); + if (fileModified) { + throw new RuntimeException("Shared archive " + TOP_NAME + " should not be created at exit"); + } + } +} diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchiveNoDefaultArchive.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchiveNoDefaultArchive.java new file mode 100644 index 00000000000..d2db4a3b2ad --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchiveNoDefaultArchive.java @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2022, 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 + * @summary Test -XX:+AutoCreateSharedArchive on a copied JDK without default shared archive + * @bug 8261455 + * @requires vm.cds + * @requires vm.flagless + * @comment This test doesn't work on Windows because it depends on symlinks + * @requires os.family != "windows" + * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds + * @compile ../test-classes/Hello.java + * @run driver TestAutoCreateSharedArchiveNoDefaultArchive + */ + +import java.io.File; +import jdk.test.lib.cds.CDSTestUtils; +import jdk.test.lib.process.OutputAnalyzer; + +public class TestAutoCreateSharedArchiveNoDefaultArchive { + public static void main(String[] args) throws Exception { + String mainClass = "Hello"; + String java_home_src = System.getProperty("java.home"); + String java_home_dst = CDSTestUtils.getOutputDir() + File.separator + "moved_jdk"; + CDSTestUtils.clone(new File(java_home_src), new File(java_home_dst)); + System.out.println("======== Cloned JDK at " + java_home_dst); + + String homeJava = java_home_src + File.separator + "bin" + File.separator + "java"; + String dstJava = java_home_dst + File.separator + "bin" + File.separator + "java"; + + TestCommon.startNewArchiveName(); + String jsaFileName = TestCommon.getCurrentArchiveName(); + File jsaFile = new File(jsaFileName); + if (jsaFile.exists()) { + jsaFile.delete(); + } + + String jsaOpt = "-XX:SharedArchiveFile=" + jsaFileName; + String autoCreateArchive = "-XX:+AutoCreateSharedArchive"; + { + ProcessBuilder pb = CDSTestUtils.makeBuilder(homeJava, + "-Xshare:dump", + jsaOpt); + TestCommon.executeAndLog(pb, "dump") + .shouldHaveExitValue(0); + } + { + ProcessBuilder pb = CDSTestUtils.makeBuilder(homeJava, + "-Xshare:auto", + jsaOpt, + "-Xlog:class+path=info", + "-version"); + OutputAnalyzer out = TestCommon.executeAndLog(pb, "exec-src"); + out.shouldHaveExitValue(0); + out.shouldNotContain("shared class paths mismatch"); + out.shouldNotContain("BOOT classpath mismatch"); + } + + String helloJar = JarBuilder.getOrCreateHelloJar(); + + if (jsaFile.exists()) { + jsaFile.delete(); + } + // Test runtime with cloned JDK + System.out.println("======== run with cloned jdk to created dynamic shared archive at exit"); + { + ProcessBuilder pb = CDSTestUtils.makeBuilder(dstJava, + "-Xshare:auto", + autoCreateArchive, + jsaOpt, + "-Xlog:cds", + "-Xlog:class+path=info", + "-cp", helloJar, + mainClass); + OutputAnalyzer out = TestCommon.executeAndLog(pb, "exec-dst"); + out.shouldHaveExitValue(0); + out.shouldContain("Dumping shared data to file"); + if (!jsaFile.exists()) { + throw new RuntimeException("Shared archive " + jsaFileName + " should be created at exit"); + } + } + + // Now rename classes.jsa to old-classes.jsa + String dstDir = java_home_dst + File.separator + "lib" + File.separator + "server"; + CDSTestUtils.rename(new File(dstDir + File.separator + "classes.jsa"), + new File(dstDir + File.separator + "old-classes.jsa")); + System.out.println("======= renamed classes.jsa to old-classes.jsa"); + + { + ProcessBuilder pb = CDSTestUtils.makeBuilder(dstJava, + "-Xlog:cds", + "-version"); + TestCommon.executeAndLog(pb, "show-version") + .shouldHaveExitValue(0) + .shouldContain("UseSharedSpaces: Initialize static archive failed") + .shouldContain("UseSharedSpaces: Unable to map shared spaces") + .shouldContain("mixed mode") + .shouldNotContain("sharing"); + } + // delete existing jsa file + if (jsaFile.exists()) { + jsaFile.delete(); + } + System.out.println("======= run with no default shared archive should not create shared archive at exit"); + { + ProcessBuilder pb = CDSTestUtils.makeBuilder(dstJava, + "-Xshare:auto", + autoCreateArchive, + jsaOpt, + "-Xlog:cds", + "-Xlog:class+path=info", + "-cp", helloJar, + mainClass); + TestCommon.executeAndLog(pb, "no-default-archive") + .shouldHaveExitValue(0) + .shouldContain("UseSharedSpaces: Initialize static archive failed") + .shouldContain("UseSharedSpaces: Unable to map shared spaces") + .shouldNotContain("Dumping shared data to file"); + if (jsaFile.exists()) { + throw new RuntimeException("Archive file " + jsaFileName + " should not be created at exit"); + } + } + + } +} diff --git a/test/lib/jdk/test/lib/cds/CDSArchiveUtils.java b/test/lib/jdk/test/lib/cds/CDSArchiveUtils.java index 4c7fdd2ec96..f5c504ba1c8 100644 --- a/test/lib/jdk/test/lib/cds/CDSArchiveUtils.java +++ b/test/lib/jdk/test/lib/cds/CDSArchiveUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022, 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 @@ -341,6 +341,18 @@ public class CDSArchiveUtils { return newJsaFile; } + public static File createMagicOnlyFile(String fileName, boolean createStatic) throws Exception { + File file = new File(fileName); + if (file.exists()) { + file.delete(); + } + try (FileOutputStream out = new FileOutputStream(file)) { + ByteBuffer buffer = ByteBuffer.allocate(4).putInt(createStatic ? staticMagic: dynamicMagic); + out.write(buffer.array(), 0, 4); + } + return file; + } + private static FileChannel getFileChannel(File file, boolean write) throws Exception { List arry = new ArrayList(); arry.add(READ); diff --git a/test/lib/jdk/test/lib/cds/CDSTestUtils.java b/test/lib/jdk/test/lib/cds/CDSTestUtils.java index f7e263ba5c5..f9391c96ee4 100644 --- a/test/lib/jdk/test/lib/cds/CDSTestUtils.java +++ b/test/lib/jdk/test/lib/cds/CDSTestUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,9 @@ import java.io.IOException; import java.io.File; import java.io.FileOutputStream; import java.io.PrintStream; +import java.nio.file.Files; +import java.nio.file.CopyOption; +import java.nio.file.StandardCopyOption; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; @@ -684,4 +687,78 @@ public class CDSTestUtils { private static boolean isAsciiPrintable(char ch) { return ch >= 32 && ch < 127; } + + // JDK utility + + // Do a cheap clone of the JDK. Most files can be sym-linked. However, $JAVA_HOME/bin/java and $JAVA_HOME/lib/.../libjvm.so" + // must be copied, because the java.home property is derived from the canonicalized paths of these 2 files. + // Set a list of {jvm, "java"} which will be physically copied. If a file needs copied physically, add it to the list. + private static String[] phCopied = {System.mapLibraryName("jvm"), "java"}; + public static void clone(File src, File dst) throws Exception { + if (dst.exists()) { + if (!dst.isDirectory()) { + throw new RuntimeException("Not a directory :" + dst); + } + } else { + if (!dst.mkdir()) { + throw new RuntimeException("Cannot create directory: " + dst); + } + } + // final String jvmLib = System.mapLibraryName("jvm"); + for (String child : src.list()) { + if (child.equals(".") || child.equals("..")) { + continue; + } + + File child_src = new File(src, child); + File child_dst = new File(dst, child); + if (child_dst.exists()) { + throw new RuntimeException("Already exists: " + child_dst); + } + if (child_src.isFile()) { + boolean needPhCopy = false; + for (String target : phCopied) { + if (child.equals(target)) { + needPhCopy = true; + break; + } + } + if (needPhCopy) { + Files.copy(child_src.toPath(), /* copy data to -> */ child_dst.toPath(), + new CopyOption[] { StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.COPY_ATTRIBUTES}); + } else { + Files.createSymbolicLink(child_dst.toPath(), /* link to -> */ child_src.toPath()); + } + } else { + clone(child_src, child_dst); + } + } + } + + // modulesDir, like $JDK/lib + // oldName, module name under modulesDir + // newName, new name for oldName + public static void rename(File fromFile, File toFile) throws Exception { + if (!fromFile.exists()) { + throw new RuntimeException(fromFile.getName() + " does not exist"); + } + + if (toFile.exists()) { + throw new RuntimeException(toFile.getName() + " already exists"); + } + + boolean success = fromFile.renameTo(toFile); + if (!success) { + throw new RuntimeException("rename file " + fromFile.getName()+ " to " + toFile.getName() + " failed"); + } + } + + public static ProcessBuilder makeBuilder(String... args) throws Exception { + System.out.print("["); + for (String s : args) { + System.out.print(" " + s); + } + System.out.println(" ]"); + return new ProcessBuilder(args); + } } -- GitLab From cb25029885b176be9ebbc84ac1a8ba71be96a6a7 Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Thu, 13 Jan 2022 00:42:00 +0000 Subject: [PATCH 092/564] 8279800: isAssignableFrom checks in AlgorithmParametersSpi.engineGetParameterSpec appear to be backwards Reviewed-by: xuelei, valeriep --- .../provider/BlockCipherParamsCore.java | 4 +- .../provider/ChaCha20Poly1305Parameters.java | 4 +- .../com/sun/crypto/provider/DHParameters.java | 4 +- .../sun/crypto/provider/GCMParameters.java | 4 +- .../sun/crypto/provider/OAEPParameters.java | 4 +- .../sun/crypto/provider/PBEKeyFactory.java | 2 +- .../sun/crypto/provider/PBEParameters.java | 4 +- .../sun/crypto/provider/PBES2Parameters.java | 4 +- .../com/sun/crypto/provider/PBKDF2Core.java | 2 +- .../provider/PBKDF2HmacSHA1Factory.java | 167 ------------------ .../sun/crypto/provider/RC2Parameters.java | 4 +- .../sun/security/provider/DSAParameters.java | 4 +- .../sun/security/rsa/PSSParameters.java | 4 +- .../sun/security/util/GCMParameters.java | 4 +- .../security/spec/IsAssignableFromOrder.java | 117 ++++++++++++ 15 files changed, 141 insertions(+), 191 deletions(-) delete mode 100644 src/java.base/share/classes/com/sun/crypto/provider/PBKDF2HmacSHA1Factory.java create mode 100644 test/jdk/java/security/spec/IsAssignableFromOrder.java diff --git a/src/java.base/share/classes/com/sun/crypto/provider/BlockCipherParamsCore.java b/src/java.base/share/classes/com/sun/crypto/provider/BlockCipherParamsCore.java index 20af0c78309..738b34d3aeb 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/BlockCipherParamsCore.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/BlockCipherParamsCore.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2022, 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 @@ -108,7 +108,7 @@ final class BlockCipherParamsCore { T getParameterSpec(Class paramSpec) throws InvalidParameterSpecException { - if (IvParameterSpec.class.isAssignableFrom(paramSpec)) { + if (paramSpec.isAssignableFrom(IvParameterSpec.class)) { return paramSpec.cast(new IvParameterSpec(this.iv)); } else { throw new InvalidParameterSpecException diff --git a/src/java.base/share/classes/com/sun/crypto/provider/ChaCha20Poly1305Parameters.java b/src/java.base/share/classes/com/sun/crypto/provider/ChaCha20Poly1305Parameters.java index ad31fb6f691..762827d0152 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/ChaCha20Poly1305Parameters.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/ChaCha20Poly1305Parameters.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2022, 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 @@ -147,7 +147,7 @@ public final class ChaCha20Poly1305Parameters extends AlgorithmParametersSpi { T engineGetParameterSpec(Class paramSpec) throws InvalidParameterSpecException { - if (IvParameterSpec.class.isAssignableFrom(paramSpec)) { + if (paramSpec.isAssignableFrom(IvParameterSpec.class)) { return paramSpec.cast(new IvParameterSpec(nonce)); } else { throw new InvalidParameterSpecException diff --git a/src/java.base/share/classes/com/sun/crypto/provider/DHParameters.java b/src/java.base/share/classes/com/sun/crypto/provider/DHParameters.java index da3129805b6..859c64dc405 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/DHParameters.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/DHParameters.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -98,7 +98,7 @@ public final class DHParameters extends AlgorithmParametersSpi { T engineGetParameterSpec(Class paramSpec) throws InvalidParameterSpecException { - if (DHParameterSpec.class.isAssignableFrom(paramSpec)) { + if (paramSpec.isAssignableFrom(DHParameterSpec.class)) { return paramSpec.cast(new DHParameterSpec(this.p, this.g, this.l)); } else { throw new InvalidParameterSpecException diff --git a/src/java.base/share/classes/com/sun/crypto/provider/GCMParameters.java b/src/java.base/share/classes/com/sun/crypto/provider/GCMParameters.java index 911ccc55824..8060ca9b7de 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/GCMParameters.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/GCMParameters.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2022, 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 @@ -107,7 +107,7 @@ public final class GCMParameters extends AlgorithmParametersSpi { T engineGetParameterSpec(Class paramSpec) throws InvalidParameterSpecException { - if (GCMParameterSpec.class.isAssignableFrom(paramSpec)) { + if (paramSpec.isAssignableFrom(GCMParameterSpec.class)) { return paramSpec.cast(new GCMParameterSpec(tLen * 8, iv)); } else { throw new InvalidParameterSpecException diff --git a/src/java.base/share/classes/com/sun/crypto/provider/OAEPParameters.java b/src/java.base/share/classes/com/sun/crypto/provider/OAEPParameters.java index bdb1da97b63..fb8ff87cf2d 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/OAEPParameters.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/OAEPParameters.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, 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 @@ -148,7 +148,7 @@ public final class OAEPParameters extends AlgorithmParametersSpi { protected T engineGetParameterSpec(Class paramSpec) throws InvalidParameterSpecException { - if (OAEPParameterSpec.class.isAssignableFrom(paramSpec)) { + if (paramSpec.isAssignableFrom(OAEPParameterSpec.class)) { return paramSpec.cast( new OAEPParameterSpec(mdName, "MGF1", mgfSpec, new PSource.PSpecified(p))); diff --git a/src/java.base/share/classes/com/sun/crypto/provider/PBEKeyFactory.java b/src/java.base/share/classes/com/sun/crypto/provider/PBEKeyFactory.java index ea2dfbf31ae..ed09fe94118 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/PBEKeyFactory.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/PBEKeyFactory.java @@ -243,7 +243,7 @@ abstract class PBEKeyFactory extends SecretKeyFactorySpi { // Check if requested key spec is amongst the valid ones if ((keySpecCl != null) - && PBEKeySpec.class.isAssignableFrom(keySpecCl)) { + && keySpecCl.isAssignableFrom(PBEKeySpec.class)) { byte[] passwdBytes = key.getEncoded(); char[] passwdChars = new char[passwdBytes.length]; for (int i=0; i paramSpec) throws InvalidParameterSpecException { - if (PBEParameterSpec.class.isAssignableFrom(paramSpec)) { + if (paramSpec.isAssignableFrom(PBEParameterSpec.class)) { return paramSpec.cast( new PBEParameterSpec(this.salt, this.iCount, this.cipherParam)); } else { diff --git a/src/java.base/share/classes/com/sun/crypto/provider/PBES2Parameters.java b/src/java.base/share/classes/com/sun/crypto/provider/PBES2Parameters.java index a26c95b16d3..4e3c7e44a38 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/PBES2Parameters.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/PBES2Parameters.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022, 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 @@ -334,7 +334,7 @@ abstract class PBES2Parameters extends AlgorithmParametersSpi { T engineGetParameterSpec(Class paramSpec) throws InvalidParameterSpecException { - if (PBEParameterSpec.class.isAssignableFrom(paramSpec)) { + if (paramSpec.isAssignableFrom(PBEParameterSpec.class)) { return paramSpec.cast( new PBEParameterSpec(this.salt, this.iCount, this.cipherParam)); } else { diff --git a/src/java.base/share/classes/com/sun/crypto/provider/PBKDF2Core.java b/src/java.base/share/classes/com/sun/crypto/provider/PBKDF2Core.java index 87207c778ec..c9e75468582 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/PBKDF2Core.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/PBKDF2Core.java @@ -92,7 +92,7 @@ abstract class PBKDF2Core extends SecretKeyFactorySpi { if (key instanceof javax.crypto.interfaces.PBEKey) { // Check if requested key spec is amongst the valid ones if ((keySpecCl != null) - && PBEKeySpec.class.isAssignableFrom(keySpecCl)) { + && keySpecCl.isAssignableFrom(PBEKeySpec.class)) { javax.crypto.interfaces.PBEKey pKey = (javax.crypto.interfaces.PBEKey) key; char[] passwd = pKey.getPassword(); diff --git a/src/java.base/share/classes/com/sun/crypto/provider/PBKDF2HmacSHA1Factory.java b/src/java.base/share/classes/com/sun/crypto/provider/PBKDF2HmacSHA1Factory.java deleted file mode 100644 index d8070e968b6..00000000000 --- a/src/java.base/share/classes/com/sun/crypto/provider/PBKDF2HmacSHA1Factory.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.crypto.provider; - -import java.security.InvalidKeyException; -import java.security.spec.KeySpec; -import java.security.spec.InvalidKeySpecException; -import java.util.Arrays; -import javax.crypto.SecretKey; -import javax.crypto.SecretKeyFactorySpi; -import javax.crypto.spec.PBEKeySpec; - -/** - * This class implements a key factory for PBE keys derived using - * PBKDF2 with HmacSHA1 psuedo random function(PRF) as defined in - * PKCS#5 v2.0. - * - * @author Valerie Peng - * - */ -public final class PBKDF2HmacSHA1Factory extends SecretKeyFactorySpi { - - /** - * Empty constructor - */ - public PBKDF2HmacSHA1Factory() { - } - - /** - * Generates a SecretKey object from the provided key - * specification (key material). - * - * @param keySpec the specification (key material) of the secret key - * - * @return the secret key - * - * @exception InvalidKeySpecException if the given key specification - * is inappropriate for this key factory to produce a public key. - */ - protected SecretKey engineGenerateSecret(KeySpec keySpec) - throws InvalidKeySpecException - { - if (!(keySpec instanceof PBEKeySpec)) { - throw new InvalidKeySpecException("Invalid key spec"); - } - PBEKeySpec ks = (PBEKeySpec) keySpec; - return new PBKDF2KeyImpl(ks, "HmacSHA1"); - } - - /** - * Returns a specification (key material) of the given key - * in the requested format. - * - * @param key the key - * - * @param keySpecCl the requested format in which the key material shall be - * returned - * - * @return the underlying key specification (key material) in the - * requested format - * - * @exception InvalidKeySpecException if the requested key - * specification is inappropriate for the given key, or the - * given key cannot be processed (e.g., the given key has an - * unrecognized algorithm or format). - */ - protected KeySpec engineGetKeySpec(SecretKey key, Class keySpecCl) - throws InvalidKeySpecException { - if (key instanceof javax.crypto.interfaces.PBEKey) { - // Check if requested key spec is amongst the valid ones - if ((keySpecCl != null) - && PBEKeySpec.class.isAssignableFrom(keySpecCl)) { - javax.crypto.interfaces.PBEKey pKey = - (javax.crypto.interfaces.PBEKey) key; - char[] passwd = pKey.getPassword(); - byte[] encoded = pKey.getEncoded(); - try { - return new PBEKeySpec(passwd, pKey.getSalt(), - pKey.getIterationCount(), encoded.length * 8); - } finally { - if (passwd != null) { - Arrays.fill(passwd, (char) 0); - } - Arrays.fill(encoded, (byte)0); - } - } else { - throw new InvalidKeySpecException("Invalid key spec"); - } - } else { - throw new InvalidKeySpecException("Invalid key " + - "format/algorithm"); - } - } - - /** - * Translates a SecretKey object, whose provider may be - * unknown or potentially untrusted, into a corresponding - * SecretKey object of this key factory. - * - * @param key the key whose provider is unknown or untrusted - * - * @return the translated key - * - * @exception InvalidKeyException if the given key cannot be processed by - * this key factory. - */ - protected SecretKey engineTranslateKey(SecretKey key) - throws InvalidKeyException { - if ((key != null) && - (key.getAlgorithm().equalsIgnoreCase("PBKDF2WithHmacSHA1")) && - (key.getFormat().equalsIgnoreCase("RAW"))) { - - // Check if key originates from this factory - if (key instanceof com.sun.crypto.provider.PBKDF2KeyImpl) { - return key; - } - // Check if key implements the PBEKey - if (key instanceof javax.crypto.interfaces.PBEKey) { - javax.crypto.interfaces.PBEKey pKey = - (javax.crypto.interfaces.PBEKey) key; - char[] password = pKey.getPassword(); - byte[] encoding = pKey.getEncoded(); - PBEKeySpec spec = - new PBEKeySpec(password, - pKey.getSalt(), - pKey.getIterationCount(), - encoding.length*8); - try { - return new PBKDF2KeyImpl(spec, "HmacSHA1"); - } catch (InvalidKeySpecException re) { - throw new InvalidKeyException - ("Invalid key component(s)", re); - } finally { - if (password != null) { - Arrays.fill(password, (char) 0); - spec.clearPassword(); - } - Arrays.fill(encoding, (byte)0); - } - } - } - throw new InvalidKeyException("Invalid key format/algorithm"); - } -} diff --git a/src/java.base/share/classes/com/sun/crypto/provider/RC2Parameters.java b/src/java.base/share/classes/com/sun/crypto/provider/RC2Parameters.java index e33ab101d70..919e1e7b2e9 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/RC2Parameters.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/RC2Parameters.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, 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 @@ -180,7 +180,7 @@ public final class RC2Parameters extends AlgorithmParametersSpi { T engineGetParameterSpec(Class paramSpec) throws InvalidParameterSpecException { - if (RC2ParameterSpec.class.isAssignableFrom(paramSpec)) { + if (paramSpec.isAssignableFrom(RC2ParameterSpec.class)) { return paramSpec.cast((iv == null ? new RC2ParameterSpec(effectiveKeySize) : new RC2ParameterSpec(effectiveKeySize, iv))); diff --git a/src/java.base/share/classes/sun/security/provider/DSAParameters.java b/src/java.base/share/classes/sun/security/provider/DSAParameters.java index 9a71ae1df86..9b848689462 100644 --- a/src/java.base/share/classes/sun/security/provider/DSAParameters.java +++ b/src/java.base/share/classes/sun/security/provider/DSAParameters.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 DSAParameters extends AlgorithmParametersSpi { try { Class dsaParamSpec = Class.forName ("java.security.spec.DSAParameterSpec"); - if (dsaParamSpec.isAssignableFrom(paramSpec)) { + if (paramSpec.isAssignableFrom(dsaParamSpec)) { return paramSpec.cast( new DSAParameterSpec(this.p, this.q, this.g)); } else { diff --git a/src/java.base/share/classes/sun/security/rsa/PSSParameters.java b/src/java.base/share/classes/sun/security/rsa/PSSParameters.java index fef496ed50c..67dd269648f 100644 --- a/src/java.base/share/classes/sun/security/rsa/PSSParameters.java +++ b/src/java.base/share/classes/sun/security/rsa/PSSParameters.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2022, 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 @@ -180,7 +180,7 @@ public final class PSSParameters extends AlgorithmParametersSpi { protected T engineGetParameterSpec(Class paramSpec) throws InvalidParameterSpecException { - if (PSSParameterSpec.class.isAssignableFrom(paramSpec)) { + if (paramSpec.isAssignableFrom(PSSParameterSpec.class)) { return paramSpec.cast(spec); } else { throw new InvalidParameterSpecException diff --git a/src/java.base/share/classes/sun/security/util/GCMParameters.java b/src/java.base/share/classes/sun/security/util/GCMParameters.java index 02390777a03..d54965f975d 100644 --- a/src/java.base/share/classes/sun/security/util/GCMParameters.java +++ b/src/java.base/share/classes/sun/security/util/GCMParameters.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, 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 @@ -111,7 +111,7 @@ public final class GCMParameters extends AlgorithmParametersSpi { T engineGetParameterSpec(Class paramSpec) throws InvalidParameterSpecException { - if (GCMParameterSpec.class.isAssignableFrom(paramSpec)) { + if (paramSpec.isAssignableFrom(GCMParameterSpec.class)) { return paramSpec.cast(new GCMParameterSpec(tLen * 8, iv)); } else { throw new InvalidParameterSpecException diff --git a/test/jdk/java/security/spec/IsAssignableFromOrder.java b/test/jdk/java/security/spec/IsAssignableFromOrder.java new file mode 100644 index 00000000000..db2b7652830 --- /dev/null +++ b/test/jdk/java/security/spec/IsAssignableFromOrder.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2022, 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 sun.security.util.CurveDB; + +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.DESKeySpec; +import javax.crypto.spec.DESedeKeySpec; +import javax.crypto.spec.DHParameterSpec; +import javax.crypto.spec.GCMParameterSpec; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.OAEPParameterSpec; +import javax.crypto.spec.PBEKeySpec; +import javax.crypto.spec.PBEParameterSpec; +import javax.crypto.spec.RC2ParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import java.math.BigInteger; +import java.nio.charset.StandardCharsets; +import java.security.AlgorithmParameters; +import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.DSAParameterSpec; +import java.security.spec.ECGenParameterSpec; +import java.security.spec.ECParameterSpec; +import java.security.spec.KeySpec; +import java.security.spec.PSSParameterSpec; + +/** + * @test + * @bug 8279800 + * @modules java.base/sun.security.util + * @summary isAssignableFrom checks in AlgorithmParametersSpi.engineGetParameterSpec appear to be backwards + */ + +public class IsAssignableFromOrder { + + public static void main(String[] args) throws Exception { + + // AlgorithmParameters + testAlgSpec("AES", new IvParameterSpec(new byte[16])); + testAlgSpec("ChaCha20-Poly1305", new IvParameterSpec(new byte[12])); + testAlgSpec("DiffieHellman", new DHParameterSpec(BigInteger.ONE, BigInteger.TWO)); + testAlgSpec("GCM", new GCMParameterSpec(96, new byte[16])); + testAlgSpec("OAEP", OAEPParameterSpec.DEFAULT); + testAlgSpec("PBEWithSHA1AndDESede", new PBEParameterSpec( + "saltsalt".getBytes(StandardCharsets.UTF_8), 10000)); + testAlgSpec("PBEWithHmacSHA256AndAES_256", new PBEParameterSpec( + "saltsalt".getBytes(StandardCharsets.UTF_8), 10000, + new IvParameterSpec(new byte[16]))); + testAlgSpec("RC2", new RC2ParameterSpec(256, new byte[32])); + testAlgSpec("DSA", new DSAParameterSpec( + BigInteger.ONE, BigInteger.TWO, BigInteger.TEN)); + testAlgSpec("RSASSA-PSS", PSSParameterSpec.DEFAULT); + testAlgSpec("EC", new ECGenParameterSpec("secp256r1")); + testAlgSpec("EC", CurveDB.lookup("secp256r1"), + ECParameterSpec.class, AlgorithmParameterSpec.class); + + // SecretKeyFactory + var spec = new PBEKeySpec( + "password".toCharArray(), + "saltsalt".getBytes(StandardCharsets.UTF_8), + 10000, + 32); + + testKeySpec("PBE", spec, PBEKeySpec.class); + testKeySpec("PBEWithHmacSHA256AndAES_256", spec, PBEKeySpec.class); + testKeySpec("PBKDF2WithHmacSHA1", spec, PBEKeySpec.class); + + testKeySpec("DES", new SecretKeySpec(new byte[8], "DES"), DESKeySpec.class); + testKeySpec("DESede", new SecretKeySpec(new byte[24], "DESede"), DESedeKeySpec.class); + } + + + static void testAlgSpec(String algorithm, AlgorithmParameterSpec spec, + Class... classes) throws Exception { + System.out.println(algorithm); + var ap1 = AlgorithmParameters.getInstance(algorithm); + ap1.init(spec); + var ap2 = AlgorithmParameters.getInstance(algorithm); + ap2.init(ap1.getEncoded()); + if (classes.length == 0) { + classes = new Class[]{spec.getClass(), AlgorithmParameterSpec.class}; + } + for (var c : classes) { + ap1.getParameterSpec(c); + ap2.getParameterSpec(c); + } + } + + static void testKeySpec(String algorithm, KeySpec spec, Class clazz) + throws Exception { + System.out.println(algorithm); + var kf = SecretKeyFactory.getInstance(algorithm); + var key = kf.generateSecret(spec); + kf.getKeySpec(key, KeySpec.class); + kf.getKeySpec(key, clazz); + } +} -- GitLab From 485194805966e8dbb76473fa26276e5ba26d8097 Mon Sep 17 00:00:00 2001 From: John Jiang Date: Thu, 13 Jan 2022 02:16:50 +0000 Subject: [PATCH 093/564] 8279903: Redundant modulo operation in ECDHKeyAgreement Reviewed-by: weijun, xuelei --- .../share/classes/sun/security/ec/ECDHKeyAgreement.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/ECDHKeyAgreement.java b/src/jdk.crypto.ec/share/classes/sun/security/ec/ECDHKeyAgreement.java index 8f69da0ac7a..79eb9a1f774 100644 --- a/src/jdk.crypto.ec/share/classes/sun/security/ec/ECDHKeyAgreement.java +++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/ECDHKeyAgreement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2022, 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 @@ -197,7 +197,7 @@ public final class ECDHKeyAgreement extends KeyAgreementSpi { EllipticCurve curve = spec.getCurve(); BigInteger rhs = x.modPow(BigInteger.valueOf(3), p).add(curve.getA() .multiply(x)).add(curve.getB()).mod(p); - BigInteger lhs = y.modPow(BigInteger.valueOf(2), p).mod(p); + BigInteger lhs = y.modPow(BigInteger.TWO, p); if (!rhs.equals(lhs)) { throw new InvalidKeyException("Point is not on curve"); } -- GitLab From 65eb066b630b892f22492457e0f86165e5ef4765 Mon Sep 17 00:00:00 2001 From: Christian Hagedorn Date: Thu, 13 Jan 2022 07:13:22 +0000 Subject: [PATCH 094/564] 8279837: C2: assert(is_Loop()) failed: invalid node class: Region Reviewed-by: kvn, thartmann --- src/hotspot/share/opto/loopTransform.cpp | 5 ++ .../TestIterationSplitWithRegionHead.java | 82 +++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 test/hotspot/jtreg/compiler/loopopts/TestIterationSplitWithRegionHead.java diff --git a/src/hotspot/share/opto/loopTransform.cpp b/src/hotspot/share/opto/loopTransform.cpp index 30562826eac..22cdb1cb6ea 100644 --- a/src/hotspot/share/opto/loopTransform.cpp +++ b/src/hotspot/share/opto/loopTransform.cpp @@ -3425,6 +3425,11 @@ bool IdealLoopTree::do_one_iteration_loop(PhaseIdealLoop *phase) { //============================================================================= //------------------------------iteration_split_impl--------------------------- bool IdealLoopTree::iteration_split_impl(PhaseIdealLoop *phase, Node_List &old_new) { + if (!_head->is_Loop()) { + // Head could be a region with a NeverBranch that was added in beautify loops but the region was not + // yet transformed into a LoopNode. Bail out and wait until beautify loops turns it into a Loop node. + return false; + } // Compute loop trip count if possible. compute_trip_count(phase); diff --git a/test/hotspot/jtreg/compiler/loopopts/TestIterationSplitWithRegionHead.java b/test/hotspot/jtreg/compiler/loopopts/TestIterationSplitWithRegionHead.java new file mode 100644 index 00000000000..7a29be60908 --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/TestIterationSplitWithRegionHead.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2022, 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 + * @requires vm.compiler2.enabled + * @bug 8279837 + * @summary Tests infinite loop with region head in iteration split. + * @run main/othervm -Xcomp -XX:-TieredCompilation + * -XX:CompileCommand=compileonly,compiler.loopopts.TestIterationSplitWithRegionHead::test + * -XX:CompileCommand=dontinline,compiler.loopopts.TestIterationSplitWithRegionHead::* + * compiler.loopopts.TestIterationSplitWithRegionHead + */ + +package compiler.loopopts; + +public class TestIterationSplitWithRegionHead { + + static boolean flagFalse = false; + + public static void main(String[] args) { + test(); + } + + public static void test() { + // 1) The loop tree is built. We find that nested loop N2 is an infinite loop and add a NeverBranch + // to the inner loop to make it reachable. But the current loop tree does not have N2, yet. The + // resulting loop tree is: + // + // Loop: N0/N0 has_call has_sfpt + // Loop: N77/N121 has_call // N1 outer + // Loop: N77/N111 has_call sfpts={ 111 97 } // N1 inner + // + // 2) beautify_loops() finds that the outer loop head of N1 is shared and thus adds a new region + // in merge_many_backedges(). As a result, the loop tree is built again. This time, the NeverBranch + // in the inner loop of N2 allows that a loop tree can be built for it: + // + // Loop: N0/N0 has_call has_sfpt + // Loop: N216/N213 limit_check profile_predicated predicated has_call sfpts={ 111 97 } // N1 shared loop head + // Loop: N196/N201 sfpts={ 201 } // N2 inner loop now discovered with the new NeverBranch + // + // However, a LoopNode is only added by beautify_loops() which won't be called until the next iteration of loop opts. + // This means that we have a Region node (N196) as head in the loop tree which cannot be handled by iteration_split_impl() + // resulting in an assertion failure. + + // Nested loop N1 + while (flagFalse) { + while (dontInlineFalse()) { + } + } + dontInlineFalse(); + + // Nested loop N2 + while (flagFalse) { + while (true) ; // Detected as infinite inner loop by C2 -> NeverBranch added + } + } + + public static boolean dontInlineFalse() { + return false; + } +} -- GitLab From 33814791d917b0c09909bf19b432dd8dfc6cd9db Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Thu, 13 Jan 2022 08:42:17 +0000 Subject: [PATCH 095/564] 8274007: [REDO] VM Exit does not abort concurrent mark Reviewed-by: sjohanss, iwalulya --- src/hotspot/share/gc/g1/g1ConcurrentMark.cpp | 28 ++++++++++++++----- src/hotspot/share/gc/g1/g1ConcurrentMark.hpp | 5 ++++ .../share/gc/g1/g1ConcurrentMarkThread.cpp | 9 ++++++ 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp index ece2ac0452a..c57b68c1f37 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp @@ -2008,13 +2008,21 @@ void G1ConcurrentMark::print_stats() { } void G1ConcurrentMark::concurrent_cycle_abort() { - if (!cm_thread()->in_progress() || _has_aborted) { - // We haven't started a concurrent cycle or we have already aborted it. No need to do anything. + // We haven't started a concurrent cycle no need to do anything; we might have + // aborted the marking because of shutting down though. In this case the marking + // might have already completed the abort (leading to in_progress() below to + // return false), however this still left marking state particularly in the + // shared marking bitmap that must be cleaned up. + // If there are multiple full gcs during shutdown we do this work repeatedly for + // nothing, but this situation should be extremely rare (a full gc after shutdown + // has been signalled is alredy rare), and this work should be negligible compared + // to actual full gc work. + if (!cm_thread()->in_progress() && !_g1h->concurrent_mark_is_terminating()) { return; } - // Clear all marks in the next bitmap for the next marking cycle. This will allow us to skip the next - // concurrent bitmap clearing. + // Clear all marks in the next bitmap for this full gc as it has been used by the + // marking that is interrupted by this full gc. { GCTraceTime(Debug, gc) debug("Clear Next Bitmap"); clear_next_bitmap(_g1h->workers()); @@ -2028,9 +2036,8 @@ void G1ConcurrentMark::concurrent_cycle_abort() { for (uint i = 0; i < _max_num_tasks; ++i) { _tasks[i]->clear_region_fields(); } - _first_overflow_barrier_sync.abort(); - _second_overflow_barrier_sync.abort(); - _has_aborted = true; + + abort_marking_threads(); SATBMarkQueueSet& satb_mq_set = G1BarrierSet::satb_mark_queue_set(); satb_mq_set.abandon_partial_marking(); @@ -2041,6 +2048,13 @@ void G1ConcurrentMark::concurrent_cycle_abort() { satb_mq_set.is_active() /* expected_active */); } +void G1ConcurrentMark::abort_marking_threads() { + assert(!_root_regions.scan_in_progress(), "still doing root region scan"); + _has_aborted = true; + _first_overflow_barrier_sync.abort(); + _second_overflow_barrier_sync.abort(); +} + static void print_ms_time_info(const char* prefix, const char* name, NumberSeq& ns) { log_trace(gc, marking)("%s%5d %12s: total time = %8.2f s (avg = %8.2f ms).", diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp b/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp index 28752225f13..206136bd068 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp @@ -496,6 +496,11 @@ public: void concurrent_cycle_abort(); void concurrent_cycle_end(); + // Notifies marking threads to abort. This is a best-effort notification. Does not + // guarantee or update any state after the call. Root region scan must not be + // running. + void abort_marking_threads(); + void update_accum_task_vtime(int i, double vtime) { _accum_task_vtime[i] += vtime; } diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.cpp b/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.cpp index dde620e9398..2e4a2501ab8 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.cpp @@ -159,6 +159,15 @@ void G1ConcurrentMarkThread::run_service() { } void G1ConcurrentMarkThread::stop_service() { + if (in_progress()) { + // We are not allowed to abort the marking threads during root region scan. + // Needs to be done separately. + _cm->root_regions()->abort(); + _cm->root_regions()->wait_until_scan_finished(); + + _cm->abort_marking_threads(); + } + MutexLocker ml(CGC_lock, Mutex::_no_safepoint_check_flag); CGC_lock->notify_all(); } -- GitLab From 14a90e536b86a8fb8d5f0272ec03359e44638da5 Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Thu, 13 Jan 2022 08:51:35 +0000 Subject: [PATCH 096/564] 8279370: jdk.jpackage/share/native/applauncher/JvmLauncher.cpp fails to build with GCC 6.3.0 Reviewed-by: almatvee, asemenyuk --- src/jdk.jpackage/share/native/applauncher/JvmLauncher.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/jdk.jpackage/share/native/applauncher/JvmLauncher.cpp b/src/jdk.jpackage/share/native/applauncher/JvmLauncher.cpp index 105b512b260..db01cd164bc 100644 --- a/src/jdk.jpackage/share/native/applauncher/JvmLauncher.cpp +++ b/src/jdk.jpackage/share/native/applauncher/JvmLauncher.cpp @@ -23,6 +23,7 @@ * questions. */ +#include #include #include "tstrings.h" #include "JvmLauncher.h" -- GitLab From 693393463385a966f9bf8a4569074c185c1f2863 Mon Sep 17 00:00:00 2001 From: Kevin Walls Date: Thu, 13 Jan 2022 09:29:05 +0000 Subject: [PATCH 097/564] 8278597: Remove outdated comments regarding RMISecurityManager in HotSpotAgent.java Reviewed-by: rriggs, sspitsyn --- .../share/classes/sun/jvm/hotspot/HotSpotAgent.java | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/HotSpotAgent.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/HotSpotAgent.java index aa021510567..04db854c84d 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/HotSpotAgent.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/HotSpotAgent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2021, Azul Systems, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -390,17 +390,6 @@ public class HotSpotAgent { // Remote mode (client attaching to server) // - // Create and install a security manager - - // FIXME: currently commented out because we were having - // security problems since we're "in the sun.* hierarchy" here. - // Perhaps a permissive policy file would work around this. In - // the long run, will probably have to move into com.sun.*. - - // if (System.getSecurityManager() == null) { - // System.setSecurityManager(new RMISecurityManager()); - // } - connectRemoteDebugger(); } } -- GitLab From b61a4af719ec2f6be446612baea11245e222d6fa Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Thu, 13 Jan 2022 09:46:33 +0000 Subject: [PATCH 098/564] 8259774: Deprecate -XX:FlightRecorderOptions:samplethreads Reviewed-by: mgronlun --- src/hotspot/share/jfr/dcmd/jfrDcmds.cpp | 15 ++++++++------- src/hotspot/share/jfr/jni/jfrJniMethod.cpp | 4 ---- src/hotspot/share/jfr/jni/jfrJniMethod.hpp | 2 -- .../jfr/jni/jfrJniMethodRegistration.cpp | 1 - .../jfr/recorder/service/jfrOptionSet.cpp | 9 --------- .../jfr/recorder/service/jfrOptionSet.hpp | 3 --- src/java.base/share/man/java.1 | 8 -------- .../share/classes/jdk/jfr/FlightRecorder.java | 1 - .../share/classes/jdk/jfr/internal/JVM.java | 9 --------- .../classes/jdk/jfr/internal/Options.java | 12 ------------ .../jdk/jfr/internal/dcmd/DCmdConfigure.java | 19 ++----------------- test/jdk/jdk/jfr/jcmd/TestJcmdConfigure.java | 4 ---- 12 files changed, 10 insertions(+), 77 deletions(-) diff --git a/src/hotspot/share/jfr/dcmd/jfrDcmds.cpp b/src/hotspot/share/jfr/dcmd/jfrDcmds.cpp index 319d1c1a4e8..9b295536657 100644 --- a/src/hotspot/share/jfr/dcmd/jfrDcmds.cpp +++ b/src/hotspot/share/jfr/dcmd/jfrDcmds.cpp @@ -420,9 +420,6 @@ void JfrConfigureFlightRecorderDCmd::print_help(const char* name) const { out->print_cr(" performance and is not recommended. This value cannot be changed"); out->print_cr(" once JFR has been initialized. (STRING, 8k)"); out->print_cr(""); - out->print_cr(" samplethreads (Optional) Flag for activating thread sampling. This value cannot"); - out->print_cr(" be changed once JFR has been initialized. (BOOLEAN, true)"); - out->print_cr(""); out->print_cr("Options must be specified using the or = syntax."); out->print_cr(""); out->print_cr("Example usage:"); @@ -477,7 +474,6 @@ void JfrConfigureFlightRecorderDCmd::execute(DCmdSource source, TRAPS) { jobject thread_buffer_size = NULL; jobject max_chunk_size = NULL; jobject memory_size = NULL; - jobject sample_threads = NULL; if (!JfrRecorder::is_created()) { if (_stack_depth.is_set()) { @@ -499,7 +495,13 @@ void JfrConfigureFlightRecorderDCmd::execute(DCmdSource source, TRAPS) { memory_size = JfrJavaSupport::new_java_lang_Long(_memory_size.value()._size, CHECK); } if (_sample_threads.is_set()) { - sample_threads = JfrJavaSupport::new_java_lang_Boolean(_sample_threads.value(), CHECK); + bool startup = DCmd_Source_Internal == source; + if (startup) { + log_warning(jfr,startup)("%s", "Option samplethreads is deprecated. Use -XX:StartFlightRecording:method-profiling="); + } else { + output()->print_cr("%s", "Option samplethreads is deprecated. Use JFR.start method-profiling="); + output()->print_cr(""); + } } } @@ -507,7 +509,7 @@ void JfrConfigureFlightRecorderDCmd::execute(DCmdSource source, TRAPS) { static const char method[] = "execute"; static const char signature[] = "(ZLjava/lang/String;Ljava/lang/String;Ljava/lang/Integer;" "Ljava/lang/Long;Ljava/lang/Long;Ljava/lang/Long;Ljava/lang/Long;" - "Ljava/lang/Long;Ljava/lang/Boolean;)[Ljava/lang/String;"; + "Ljava/lang/Long;)[Ljava/lang/String;"; JfrJavaArguments execute_args(&result, klass, method, signature, CHECK); execute_args.set_receiver(h_dcmd_instance); @@ -522,7 +524,6 @@ void JfrConfigureFlightRecorderDCmd::execute(DCmdSource source, TRAPS) { execute_args.push_jobject(thread_buffer_size); execute_args.push_jobject(memory_size); execute_args.push_jobject(max_chunk_size); - execute_args.push_jobject(sample_threads); JfrJavaSupport::call_virtual(&execute_args, THREAD); handle_dcmd_result(output(), result.get_oop(), source, THREAD); diff --git a/src/hotspot/share/jfr/jni/jfrJniMethod.cpp b/src/hotspot/share/jfr/jni/jfrJniMethod.cpp index 690b02ef36d..afbfaec6a96 100644 --- a/src/hotspot/share/jfr/jni/jfrJniMethod.cpp +++ b/src/hotspot/share/jfr/jni/jfrJniMethod.cpp @@ -121,10 +121,6 @@ NO_TRANSITION(void, jfr_set_file_notification(JNIEnv* env, jobject jvm, jlong th JfrChunkRotation::set_threshold(threshold); NO_TRANSITION_END -NO_TRANSITION(void, jfr_set_sample_threads(JNIEnv* env, jobject jvm, jboolean sampleThreads)) - JfrOptionSet::set_sample_threads(sampleThreads); -NO_TRANSITION_END - NO_TRANSITION(void, jfr_set_stack_depth(JNIEnv* env, jobject jvm, jint depth)) JfrOptionSet::set_stackdepth((jlong)depth); NO_TRANSITION_END diff --git a/src/hotspot/share/jfr/jni/jfrJniMethod.hpp b/src/hotspot/share/jfr/jni/jfrJniMethod.hpp index 946ef04470d..49286eed76f 100644 --- a/src/hotspot/share/jfr/jni/jfrJniMethod.hpp +++ b/src/hotspot/share/jfr/jni/jfrJniMethod.hpp @@ -87,8 +87,6 @@ void JNICALL jfr_set_method_sampling_interval(JNIEnv* env, jobject jvm, jlong ty void JNICALL jfr_set_output(JNIEnv* env, jobject jvm, jstring path); -void JNICALL jfr_set_sample_threads(JNIEnv* env, jobject jvm, jboolean sampleThreads); - void JNICALL jfr_set_stack_depth(JNIEnv* env, jobject jvm, jint depth); void JNICALL jfr_set_stacktrace_enabled(JNIEnv* env, jobject jvm, jlong event_type_id, jboolean enabled); diff --git a/src/hotspot/share/jfr/jni/jfrJniMethodRegistration.cpp b/src/hotspot/share/jfr/jni/jfrJniMethodRegistration.cpp index 5bc8a95a826..d71e2b4f25a 100644 --- a/src/hotspot/share/jfr/jni/jfrJniMethodRegistration.cpp +++ b/src/hotspot/share/jfr/jni/jfrJniMethodRegistration.cpp @@ -59,7 +59,6 @@ JfrJniMethodRegistration::JfrJniMethodRegistration(JNIEnv* env) { (char*)"setGlobalBufferSize", (char*)"(J)V", (void*)jfr_set_global_buffer_size, (char*)"setMethodSamplingInterval", (char*)"(JJ)V", (void*)jfr_set_method_sampling_interval, (char*)"setOutput", (char*)"(Ljava/lang/String;)V", (void*)jfr_set_output, - (char*)"setSampleThreads", (char*)"(Z)V", (void*)jfr_set_sample_threads, (char*)"setStackDepth", (char*)"(I)V", (void*)jfr_set_stack_depth, (char*)"setStackTraceEnabled", (char*)"(JZ)V", (void*)jfr_set_stacktrace_enabled, (char*)"setThreadBufferSize", (char*)"(J)V", (void*)jfr_set_thread_buffer_size, diff --git a/src/hotspot/share/jfr/recorder/service/jfrOptionSet.cpp b/src/hotspot/share/jfr/recorder/service/jfrOptionSet.cpp index 7f9dfcee4ff..a23ab95acbe 100644 --- a/src/hotspot/share/jfr/recorder/service/jfrOptionSet.cpp +++ b/src/hotspot/share/jfr/recorder/service/jfrOptionSet.cpp @@ -118,14 +118,6 @@ void JfrOptionSet::set_stackdepth(u4 depth) { } } -bool JfrOptionSet::sample_threads() { - return _sample_threads == JNI_TRUE; -} - -void JfrOptionSet::set_sample_threads(jboolean sample) { - _sample_threads = sample; -} - bool JfrOptionSet::can_retransform() { return _retransform == JNI_TRUE; } @@ -315,7 +307,6 @@ jlong JfrOptionSet::_memory_size = 0; jlong JfrOptionSet::_num_global_buffers = 0; jlong JfrOptionSet::_old_object_queue_size = 0; u4 JfrOptionSet::_stack_depth = STACK_DEPTH_DEFAULT; -jboolean JfrOptionSet::_sample_threads = JNI_TRUE; jboolean JfrOptionSet::_retransform = JNI_TRUE; #ifdef ASSERT jboolean JfrOptionSet::_sample_protection = JNI_FALSE; diff --git a/src/hotspot/share/jfr/recorder/service/jfrOptionSet.hpp b/src/hotspot/share/jfr/recorder/service/jfrOptionSet.hpp index c0549e30e7b..9e1dd6cef11 100644 --- a/src/hotspot/share/jfr/recorder/service/jfrOptionSet.hpp +++ b/src/hotspot/share/jfr/recorder/service/jfrOptionSet.hpp @@ -45,7 +45,6 @@ class JfrOptionSet : public AllStatic { static jlong _num_global_buffers; static jlong _old_object_queue_size; static u4 _stack_depth; - static jboolean _sample_threads; static jboolean _retransform; static jboolean _sample_protection; @@ -68,8 +67,6 @@ class JfrOptionSet : public AllStatic { static void set_old_object_queue_size(jlong value); static u4 stackdepth(); static void set_stackdepth(u4 depth); - static bool sample_threads(); - static void set_sample_threads(jboolean sample); static bool can_retransform(); static void set_retransform(jboolean value); static bool compressed_integers(); diff --git a/src/java.base/share/man/java.1 b/src/java.base/share/man/java.1 index 442e4a9dfb4..a7b1c81e51b 100644 --- a/src/java.base/share/man/java.1 +++ b/src/java.base/share/man/java.1 @@ -1431,14 +1431,6 @@ By default, this parameter is enabled. .RS .RE .TP -.B \f[CB]samplethreads=\f[R]{\f[CB]true\f[R]|\f[CB]false\f[R]} -Specifies whether thread sampling is enabled. -Thread sampling occurs only if the sampling event is enabled along with -this parameter. -By default, this parameter is enabled. -.RS -.RE -.TP .B \f[CB]stackdepth=\f[R]\f[I]depth\f[R] Stack depth for stack traces. By default, the depth is set to 64 method calls. diff --git a/src/jdk.jfr/share/classes/jdk/jfr/FlightRecorder.java b/src/jdk.jfr/share/classes/jdk/jfr/FlightRecorder.java index b7f558a17cb..5e2bac1ba74 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/FlightRecorder.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/FlightRecorder.java @@ -192,7 +192,6 @@ public final class FlightRecorder { Logger.log(JFR, DEBUG, "globalbuffersize: " + Options.getGlobalBufferSize()+ " bytes"); Logger.log(JFR, DEBUG, "globalbuffercount: " + Options.getGlobalBufferCount()); Logger.log(JFR, DEBUG, "dumppath: " + Options.getDumpPath()); - Logger.log(JFR, DEBUG, "samplethreads: " + Options.getSampleThreads()); Logger.log(JFR, DEBUG, "stackdepth: " + Options.getStackDepth()); Logger.log(JFR, DEBUG, "threadbuffersize: " + Options.getThreadBufferSize()); } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/JVM.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/JVM.java index ff84b31b0cd..0739a0bfacb 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/JVM.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/JVM.java @@ -301,15 +301,6 @@ public final class JVM { */ public native void setForceInstrumentation(boolean force); - /** - * Turn on/off thread sampling. - * - * @param sampleThreads true if threads should be sampled, false otherwise. - * - * @throws IllegalStateException if state can't be changed. - */ - public native void setSampleThreads(boolean sampleThreads) throws IllegalStateException; - /** * Turn on/off compressed integers. * diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/Options.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/Options.java index 204badc4242..efd3ce64807 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/Options.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/Options.java @@ -53,7 +53,6 @@ public final class Options { private static final long DEFAULT_MEMORY_SIZE = DEFAULT_GLOBAL_BUFFER_COUNT * DEFAULT_GLOBAL_BUFFER_SIZE; private static long DEFAULT_THREAD_BUFFER_SIZE; private static final int DEFAULT_STACK_DEPTH = 64; - private static final boolean DEFAULT_SAMPLE_THREADS = true; private static final long DEFAULT_MAX_CHUNK_SIZE = 12 * 1024 * 1024; private static final SafePath DEFAULT_DUMP_PATH = null; @@ -62,7 +61,6 @@ public final class Options { private static long globalBufferCount; private static long threadBufferSize; private static int stackDepth; - private static boolean sampleThreads; private static long maxChunkSize; static { @@ -143,15 +141,6 @@ public final class Options { return stackDepth; } - public static synchronized void setSampleThreads(Boolean sample) { - jvm.setSampleThreads(sample); - sampleThreads = sample; - } - - public static synchronized boolean getSampleThreads() { - return sampleThreads; - } - private static synchronized void reset() { setMaxChunkSize(DEFAULT_MAX_CHUNK_SIZE); setMemorySize(DEFAULT_MEMORY_SIZE); @@ -162,7 +151,6 @@ public final class Options { } catch (IOException e) { // Ignore (depends on default value in JVM: it would be NULL) } - setSampleThreads(DEFAULT_SAMPLE_THREADS); setStackDepth(DEFAULT_STACK_DEPTH); setThreadBufferSize(DEFAULT_THREAD_BUFFER_SIZE); } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdConfigure.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdConfigure.java index edcb1530474..69a0bd88378 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdConfigure.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdConfigure.java @@ -69,8 +69,7 @@ final class DCmdConfigure extends AbstractDCmd { Long globalBufferSize, Long threadBufferSize, Long memorySize, - Long maxChunkSize, - Boolean sampleThreads + Long maxChunkSize ) throws DCmdException { if (Logger.shouldLog(LogTag.JFR_DCMD, LogLevel.DEBUG)) { @@ -81,8 +80,7 @@ final class DCmdConfigure extends AbstractDCmd { ", globalbuffersize=" + globalBufferSize + ", thread_buffer_size=" + threadBufferSize + ", memorysize=" + memorySize + - ", maxchunksize=" + maxChunkSize + - ", samplethreads=" + sampleThreads); + ", maxchunksize=" + maxChunkSize); } @@ -172,14 +170,6 @@ final class DCmdConfigure extends AbstractDCmd { updated = true; } - if (sampleThreads != null) { - Options.setSampleThreads(sampleThreads); - Logger.log(LogTag.JFR, LogLevel.INFO, "Sample threads set to " + sampleThreads); - if (verbose) { - printSampleThreads(); - } - updated = true; - } if (!verbose) { return new String[0]; } @@ -194,7 +184,6 @@ final class DCmdConfigure extends AbstractDCmd { printThreadBufferSize(); printMemorySize(); printMaxChunkSize(); - printSampleThreads(); } return getResult(); } @@ -211,10 +200,6 @@ final class DCmdConfigure extends AbstractDCmd { println(); } - private void printSampleThreads() { - println("Sample threads: " + Options.getSampleThreads()); - } - private void printStackDepth() { println("Stack depth: " + Options.getStackDepth()); } diff --git a/test/jdk/jdk/jfr/jcmd/TestJcmdConfigure.java b/test/jdk/jdk/jfr/jcmd/TestJcmdConfigure.java index a43e0da065a..aa76f501483 100644 --- a/test/jdk/jdk/jfr/jcmd/TestJcmdConfigure.java +++ b/test/jdk/jdk/jfr/jcmd/TestJcmdConfigure.java @@ -52,7 +52,6 @@ public class TestJcmdConfigure { private static final String GLOBAL_BUFFER_SIZE = "globalbuffersize"; private static final String THREAD_BUFFER_SIZE = "thread_buffer_size"; private static final String MAX_CHUNK_SIZE = "maxchunksize"; - private static final String SAMPLE_THREADS = "samplethreads"; private static final String UNSUPPORTED_OPTION = "unsupportedoption"; private static final String REPOSITORYPATH_1 = "." + File.pathSeparator + "repo1"; @@ -80,8 +79,6 @@ public class TestJcmdConfigure { test(GLOBAL_BUFFER_SIZE, 6); test(THREAD_BUFFER_SIZE, 5); test(MAX_CHUNK_SIZE, 14 * 1000 * 1000); - test(SAMPLE_THREADS, false); - test(SAMPLE_THREADS, true); testNegative(UNSUPPORTED_OPTION, 100000); testNegative(MAX_CHUNK_SIZE, -500); @@ -125,7 +122,6 @@ public class TestJcmdConfigure { case GLOBAL_BUFFER_SIZE: return Options.getGlobalBufferSize(); case THREAD_BUFFER_SIZE: return Options.getThreadBufferSize(); case MAX_CHUNK_SIZE: return Options.getMaxChunkSize(); - case SAMPLE_THREADS: return Options.getSampleThreads(); default: throw new RuntimeException("Unknown option " + name); } } -- GitLab From c17a0122c4b5f17b85dc0bee0777b2a831debf6d Mon Sep 17 00:00:00 2001 From: Jaikiran Pai Date: Thu, 13 Jan 2022 13:23:57 +0000 Subject: [PATCH 099/564] 8278961: Enable debug logging in java/net/DatagramSocket/SendDatagramToBadAddress.java Reviewed-by: dfuchs, msheppar --- .../net/DatagramSocket/SendDatagramToBadAddress.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/test/jdk/java/net/DatagramSocket/SendDatagramToBadAddress.java b/test/jdk/java/net/DatagramSocket/SendDatagramToBadAddress.java index 0656dca9083..b0c0afdbd61 100644 --- a/test/jdk/java/net/DatagramSocket/SendDatagramToBadAddress.java +++ b/test/jdk/java/net/DatagramSocket/SendDatagramToBadAddress.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,7 @@ * * @summary DatagramSocket.send should throw exception when connected * to an invalid destination (on platforms that support it). - * @run main/othervm SendDatagramToBadAddress + * @run main/othervm SendDatagramToBadAddress -d */ import java.net.*; @@ -70,6 +70,8 @@ public class SendDatagramToBadAddress { for (int i=0; i Date: Thu, 13 Jan 2022 14:41:55 +0000 Subject: [PATCH 100/564] 8262442: (windows) Use all proxy configuration sources when java.net.useSystemProxies=true Reviewed-by: dfuchs --- .../native/libnet/DefaultProxySelector.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/java.base/windows/native/libnet/DefaultProxySelector.c b/src/java.base/windows/native/libnet/DefaultProxySelector.c index 74efd4ab91e..d9107e738b3 100644 --- a/src/java.base/windows/native/libnet/DefaultProxySelector.c +++ b/src/java.base/windows/native/libnet/DefaultProxySelector.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2022, 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 @@ -230,16 +230,12 @@ Java_sun_net_spi_DefaultProxySelector_getSystemProxies(JNIEnv *env, auto_proxy_options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT; auto_proxy_options.fAutoLogonIfChallenged = TRUE; use_auto_proxy = TRUE; - } else if (ie_proxy_config.lpszAutoConfigUrl != NULL) { + } + if (ie_proxy_config.lpszAutoConfigUrl != NULL) { /* Windows uses PAC file */ auto_proxy_options.lpszAutoConfigUrl = ie_proxy_config.lpszAutoConfigUrl; - auto_proxy_options.dwFlags = WINHTTP_AUTOPROXY_CONFIG_URL; + auto_proxy_options.dwFlags |= WINHTTP_AUTOPROXY_CONFIG_URL; use_auto_proxy = TRUE; - } else if (ie_proxy_config.lpszProxy != NULL) { - /* Windows uses manually entered proxy. */ - use_auto_proxy = FALSE; - win_bypass_proxy = ie_proxy_config.lpszProxyBypass; - win_proxy = ie_proxy_config.lpszProxy; } if (use_auto_proxy) { @@ -254,6 +250,12 @@ Java_sun_net_spi_DefaultProxySelector_getSystemProxies(JNIEnv *env, } } + if (!use_auto_proxy && ie_proxy_config.lpszProxy != NULL) { + /* Windows uses manually entered proxy. */ + win_bypass_proxy = ie_proxy_config.lpszProxyBypass; + win_proxy = ie_proxy_config.lpszProxy; + } + /* Check the bypass entry. */ if (NULL != win_bypass_proxy) { /* -- GitLab From ff8565931115d581afff679ea85b1a2d80c03b99 Mon Sep 17 00:00:00 2001 From: Claes Redestad Date: Thu, 13 Jan 2022 15:25:16 +0000 Subject: [PATCH 101/564] 8279833: Loop optimization issue in String.encodeUTF8_UTF16 Reviewed-by: rriggs Backport-of: c3d0a94040d9bd0f4b99da97b89fbfce252a41c0 --- .../share/classes/java/lang/String.java | 11 +- .../openjdk/bench/java/lang/StringEncode.java | 116 ++++++++++++------ 2 files changed, 84 insertions(+), 43 deletions(-) diff --git a/src/java.base/share/classes/java/lang/String.java b/src/java.base/share/classes/java/lang/String.java index abb35ebaeb1..756b8efacda 100644 --- a/src/java.base/share/classes/java/lang/String.java +++ b/src/java.base/share/classes/java/lang/String.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2022, 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 @@ -1284,14 +1284,17 @@ public final class String int sp = 0; int sl = val.length >> 1; byte[] dst = new byte[sl * 3]; - char c; - while (sp < sl && (c = StringUTF16.getChar(val, sp)) < '\u0080') { + while (sp < sl) { // ascii fast loop; + char c = StringUTF16.getChar(val, sp); + if (c >= '\u0080') { + break; + } dst[dp++] = (byte)c; sp++; } while (sp < sl) { - c = StringUTF16.getChar(val, sp++); + char c = StringUTF16.getChar(val, sp++); if (c < 0x80) { dst[dp++] = (byte)c; } else if (c < 0x800) { diff --git a/test/micro/org/openjdk/bench/java/lang/StringEncode.java b/test/micro/org/openjdk/bench/java/lang/StringEncode.java index 4cf5032a0da..6e67d3e8cee 100644 --- a/test/micro/org/openjdk/bench/java/lang/StringEncode.java +++ b/test/micro/org/openjdk/bench/java/lang/StringEncode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,59 +30,97 @@ import java.util.concurrent.TimeUnit; @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.NANOSECONDS) -@Fork(value = 3, jvmArgs = "-Xmx1g") +@Fork(value = 3) @Warmup(iterations = 5, time = 2) @Measurement(iterations = 5, time = 3) @State(Scope.Thread) public class StringEncode { - @BenchmarkMode(Mode.AverageTime) - @OutputTimeUnit(TimeUnit.NANOSECONDS) - @Fork(value = 3, jvmArgs = "-Xmx1g") - @Warmup(iterations = 5, time = 2) - @Measurement(iterations = 5, time = 2) - @State(Scope.Thread) - public static class WithCharset { + @Param({"US-ASCII", "ISO-8859-1", "UTF-8", "MS932", "ISO-8859-6"}) + private String charsetName; + private Charset charset; + private String asciiString; + private String utf16String; + private String longUtf16String; + private String longUtf16StartString; - @Param({"US-ASCII", "ISO-8859-1", "UTF-8", "MS932", "ISO-8859-6"}) - private String charsetName; + @Setup + public void setup() { + charset = Charset.forName(charsetName); + asciiString = "ascii string"; + utf16String = "UTF-\uFF11\uFF16 string"; + longUtf16String = """ + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam ac sem eu + urna egestas placerat. Etiam finibus ipsum nulla, non mattis dolor cursus a. + Nulla nec nisl consectetur, lacinia neque id, accumsan ante. Curabitur et + sapien in magna porta ultricies. Sed vel pellentesque nibh. Pellentesque dictum + dignissim diam eu ultricies. Class aptent taciti sociosqu ad litora torquent + per conubia nostra, per inceptos himenaeos. Suspendisse erat diam, fringilla + sed massa sed, posuere viverra orci. Suspendisse tempor libero non gravida + efficitur. Vivamus lacinia risus non orci viverra, at consectetur odio laoreet. + Suspendisse potenti. - private Charset charset; - private String asciiString; - private String utf16String; + Phasellus vel nisi iaculis, accumsan quam sed, bibendum eros. Sed venenatis + nulla tortor, et eleifend urna sodales id. Nullam tempus ac metus sit amet + sollicitudin. Nam sed ex diam. Praesent vitae eros et neque condimentum + consectetur eget non tortor. Praesent bibendum vel felis nec dignissim. + Maecenas a enim diam. Suspendisse quis ligula at nisi accumsan lacinia id + hendrerit sapien. Donec aliquam mattis lectus eu ultrices. Duis eu nisl + euismod, blandit mauris vel, placerat urna. Etiam malesuada enim purus, + tristique mollis odio blandit quis. Vivamus posuere. + \uFF11 + """; + longUtf16StartString = """ + \uFF11 + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam ac sem eu + urna egestas placerat. Etiam finibus ipsum nulla, non mattis dolor cursus a. + Nulla nec nisl consectetur, lacinia neque id, accumsan ante. Curabitur et + sapien in magna porta ultricies. Sed vel pellentesque nibh. Pellentesque dictum + dignissim diam eu ultricies. Class aptent taciti sociosqu ad litora torquent + per conubia nostra, per inceptos himenaeos. Suspendisse erat diam, fringilla + sed massa sed, posuere viverra orci. Suspendisse tempor libero non gravida + efficitur. Vivamus lacinia risus non orci viverra, at consectetur odio laoreet. + Suspendisse potenti. - @Setup - public void setup() { - charset = Charset.forName(charsetName); - asciiString = "ascii string"; - utf16String = "UTF-\uFF11\uFF16 string"; - } + Phasellus vel nisi iaculis, accumsan quam sed, bibendum eros. Sed venenatis + nulla tortor, et eleifend urna sodales id. Nullam tempus ac metus sit amet + sollicitudin. Nam sed ex diam. Praesent vitae eros et neque condimentum + consectetur eget non tortor. Praesent bibendum vel felis nec dignissim. + Maecenas a enim diam. Suspendisse quis ligula at nisi accumsan lacinia id + hendrerit sapien. Donec aliquam mattis lectus eu ultrices. Duis eu nisl + euismod, blandit mauris vel, placerat urna. Etiam malesuada enim purus, + tristique mollis odio blandit quis. Vivamus posuere. + """; + } - @Benchmark - public void encodeCharsetName(Blackhole bh) throws Exception { - bh.consume(asciiString.getBytes(charsetName)); - bh.consume(utf16String.getBytes(charsetName)); - } + @Benchmark + public byte[] encodeAsciiCharsetName() throws Exception { + return asciiString.getBytes(charset); + } + + @Benchmark + public byte[] encodeAscii() throws Exception { + return asciiString.getBytes(charset); + } - @Benchmark - public void encodeCharset(Blackhole bh) throws Exception { - bh.consume(asciiString.getBytes(charset)); - bh.consume(utf16String.getBytes(charset)); - } + @Benchmark + public void encodeMix(Blackhole bh) throws Exception { + bh.consume(asciiString.getBytes(charset)); + bh.consume(utf16String.getBytes(charset)); } - private String asciiDefaultString; - private String utf16DefaultString; + @Benchmark + public byte[] encodeUTF16LongEnd() throws Exception { + return longUtf16String.getBytes(charset); + } - @Setup - public void setup() { - asciiDefaultString = "ascii string"; - utf16DefaultString = "UTF-\uFF11\uFF16 string"; + @Benchmark + public byte[] encodeUTF16LongStart() throws Exception { + return longUtf16StartString.getBytes(charset); } @Benchmark - public void encodeDefault(Blackhole bh) throws Exception { - bh.consume(asciiDefaultString.getBytes()); - bh.consume(utf16DefaultString.getBytes()); + public byte[] encodeUTF16() throws Exception { + return utf16String.getBytes(charset); } } -- GitLab From 0a839b434b8454e22d6e5084af6e45cab3daa538 Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Thu, 13 Jan 2022 15:26:41 +0000 Subject: [PATCH 102/564] 8279801: EC KeyFactory and KeyPairGenerator do not have aliases for OID format Reviewed-by: xuelei, valeriep --- .../share/classes/sun/security/ec/SunEC.java | 12 +++-- test/jdk/sun/security/ec/OidInstance.java | 45 +++++++++++++++++++ 2 files changed, 50 insertions(+), 7 deletions(-) create mode 100644 test/jdk/sun/security/ec/OidInstance.java diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/SunEC.java b/src/jdk.crypto.ec/share/classes/sun/security/ec/SunEC.java index 8c9e4f9dbe6..200ed63634f 100644 --- a/src/jdk.crypto.ec/share/classes/sun/security/ec/SunEC.java +++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/SunEC.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2022, 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 @@ -208,9 +208,8 @@ public final class SunEC extends Provider { /* * Key Factory engine */ - putService(new ProviderService(this, "KeyFactory", - "EC", "sun.security.ec.ECKeyFactory", - List.of("EllipticCurve"), ATTRS)); + putService(new ProviderServiceA(this, "KeyFactory", + "EC", "sun.security.ec.ECKeyFactory", ATTRS)); /* * Algorithm Parameter engine @@ -319,9 +318,8 @@ public final class SunEC extends Provider { /* * Key Pair Generator engine */ - putService(new ProviderService(this, "KeyPairGenerator", - "EC", "sun.security.ec.ECKeyPairGenerator", - List.of("EllipticCurve"), ATTRS)); + putService(new ProviderServiceA(this, "KeyPairGenerator", + "EC", "sun.security.ec.ECKeyPairGenerator", ATTRS)); /* * Key Agreement engine diff --git a/test/jdk/sun/security/ec/OidInstance.java b/test/jdk/sun/security/ec/OidInstance.java new file mode 100644 index 00000000000..972c8e1026a --- /dev/null +++ b/test/jdk/sun/security/ec/OidInstance.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2022, 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 8279801 + * @summary EC KeyFactory and KeyPairGenerator do not have aliases for OID format + * @modules java.base/sun.security.util + * jdk.crypto.ec + */ + +import sun.security.util.KnownOIDs; + +import java.security.AlgorithmParameters; +import java.security.KeyFactory; +import java.security.KeyPairGenerator; + +public class OidInstance { + public static void main(String[] args) throws Exception { + String oid = KnownOIDs.EC.value(); + KeyFactory.getInstance(oid, "SunEC"); + KeyPairGenerator.getInstance(oid, "SunEC"); + AlgorithmParameters.getInstance(oid, "SunEC"); + } +} -- GitLab From 9209e6d6aeee002c5de3b29cfed1e91c61c37868 Mon Sep 17 00:00:00 2001 From: Daniel Jelinski Date: Thu, 13 Jan 2022 16:17:50 +0000 Subject: [PATCH 103/564] 8279877: Document IDEA IDE setup in docs/ide.md Reviewed-by: lancea, erikj --- doc/ide.html | 12 +++++++++--- doc/ide.md | 31 ++++++++++++++++++++++++++++--- 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/doc/ide.html b/doc/ide.html index 1730eb0bef5..288a477e538 100644 --- a/doc/ide.html +++ b/doc/ide.html @@ -41,14 +41,20 @@

    make vscode-project-clangd

    Additional instructions for configuring the given indexer will be displayed after the workspace has been generated.

    Visual Studio

    -

    This section is a work in progress.

    -
    make ide-project
    +

    The make system can generate a Visual Studio project for the Hotspot native source. After configuring, the project is generated using:

    +
    make hotspot-ide-project
    +

    This creates a file named jvm.vcxproj in ide\hotspot-visualstudio subfolder of the build output folder. The file can be opened in Visual Studio via File -> Open -> Project/Solution.

    Compilation Database

    The make system can generate generic native code indexing support in the form of a Compilation Database that can be used by many different IDEs and source code indexers.

    make compile-commands

    It's also possible to generate the Compilation Database for the HotSpot source code only, which is a bit faster as it includes less information.

    make compile-commands-hotspot

    IDE support for Java code

    -

    This section is a work in progress.

    +

    IntelliJ IDEA

    +

    The JDK project has a script that can be used for indexing the project with IntelliJ. After configuring and building the JDK, an IntelliJ workspace can be generated by running the following command in the top-level folder of the cloned repository:

    +
    bash bin/idea.sh
    +

    To use it, choose File -> Open... in IntelliJ and select the folder where you ran the above script.

    +

    Next, configure the project SDK in IntelliJ. Open File -> Project Structure -> Project and select build/<config>/images/jdk as the SDK to use.

    +

    In order to run the tests from the IDE, you can use the JTReg plugin. Instructions for building and using the plugin can be found here.

    diff --git a/doc/ide.md b/doc/ide.md index 4a692efd22f..f0a419c948b 100644 --- a/doc/ide.md +++ b/doc/ide.md @@ -45,12 +45,17 @@ after the workspace has been generated. #### Visual Studio -This section is a work in progress. +The make system can generate a Visual Studio project for the Hotspot +native source. After configuring, the project is generated using: ```shell -make ide-project +make hotspot-ide-project ``` +This creates a file named `jvm.vcxproj` in `ide\hotspot-visualstudio` +subfolder of the build output folder. The file can be opened in Visual Studio +via `File -> Open -> Project/Solution`. + #### Compilation Database The make system can generate generic native code indexing support in the form of @@ -70,4 +75,24 @@ make compile-commands-hotspot ### IDE support for Java code -This section is a work in progress. \ No newline at end of file +#### IntelliJ IDEA + +The JDK project has a script that can be used for indexing the project +with IntelliJ. After configuring and building the JDK, an IntelliJ workspace +can be generated by running the following command in the top-level folder +of the cloned repository: + +```shell +bash bin/idea.sh +``` + +To use it, choose `File -> Open...` in IntelliJ and select the folder where +you ran the above script. + +Next, configure the project SDK in IntelliJ. Open +`File -> Project Structure -> Project` and select `build//images/jdk` +as the SDK to use. + +In order to run the tests from the IDE, you can use the JTReg plugin. +Instructions for building and using the plugin can be found +[here](https://github.com/openjdk/jtreg/tree/master/plugins/idea). -- GitLab From 237f861e8245749cb260fa81e7797d337dc15e22 Mon Sep 17 00:00:00 2001 From: Patricio Chilano Mateo Date: Thu, 13 Jan 2022 17:49:01 +0000 Subject: [PATCH 104/564] 8273143: Transition to _thread_in_vm when handling a polling page exception Reviewed-by: rehn, dcubed, coleenp, rrich --- .../interpreter/zero/bytecodeInterpreter.cpp | 15 +++--- src/hotspot/share/runtime/handshake.cpp | 9 ++-- .../share/runtime/interfaceSupport.inline.hpp | 35 +++---------- src/hotspot/share/runtime/safepoint.cpp | 6 ++- src/hotspot/share/runtime/safepoint.hpp | 6 +-- .../share/runtime/safepointMechanism.cpp | 4 +- src/hotspot/share/runtime/thread.cpp | 52 ++++--------------- 7 files changed, 39 insertions(+), 88 deletions(-) diff --git a/src/hotspot/share/interpreter/zero/bytecodeInterpreter.cpp b/src/hotspot/share/interpreter/zero/bytecodeInterpreter.cpp index a70b0092cba..ee3648eaa61 100644 --- a/src/hotspot/share/interpreter/zero/bytecodeInterpreter.cpp +++ b/src/hotspot/share/interpreter/zero/bytecodeInterpreter.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2022, 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 @@ -99,6 +99,9 @@ #undef PREFETCH_OPCCODE #define PREFETCH_OPCCODE +JRT_ENTRY(void, at_safepoint(JavaThread* current)) {} +JRT_END + /* Interpreter safepoint: it is expected that the interpreter will have no live handles of its own creation live at an interpreter safepoint. Therefore we @@ -107,12 +110,10 @@ There really shouldn't be any handles remaining to trash but this is cheap in relation to a safepoint. */ -#define RETURN_SAFEPOINT \ - if (SafepointMechanism::should_process(THREAD)) { \ - HandleMarkCleaner __hmc(THREAD); \ - CALL_VM(SafepointMechanism::process_if_requested_with_exit_check(THREAD, true /* check asyncs */), \ - handle_exception); \ - } \ +#define RETURN_SAFEPOINT \ + if (SafepointMechanism::should_process(THREAD)) { \ + CALL_VM(at_safepoint(THREAD), handle_exception); \ + } /* * VM_JAVA_ERROR - Macro for throwing a java exception from diff --git a/src/hotspot/share/runtime/handshake.cpp b/src/hotspot/share/runtime/handshake.cpp index 2605cee98fd..05306bd6f3a 100644 --- a/src/hotspot/share/runtime/handshake.cpp +++ b/src/hotspot/share/runtime/handshake.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022, 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 @@ -488,10 +488,11 @@ void HandshakeState::remove_op(HandshakeOperation* op) { bool HandshakeState::process_by_self(bool allow_suspend) { assert(Thread::current() == _handshakee, "should call from _handshakee"); assert(!_handshakee->is_terminated(), "should not be a terminated thread"); - assert(_handshakee->thread_state() != _thread_blocked, "should not be in a blocked state"); - assert(_handshakee->thread_state() != _thread_in_native, "should not be in native"); - ThreadInVMForHandshake tivm(_handshakee); + _handshakee->frame_anchor()->make_walkable(_handshakee); + // Threads shouldn't block if they are in the middle of printing, but... + ttyLocker::break_tty_lock_for_safepoint(os::current_thread_id()); + // Handshakes cannot safely safepoint. // The exception to this rule is the asynchronous suspension handshake. // It by-passes the NSV by manually doing the transition. diff --git a/src/hotspot/share/runtime/interfaceSupport.inline.hpp b/src/hotspot/share/runtime/interfaceSupport.inline.hpp index efa794c481b..26a0cfe608e 100644 --- a/src/hotspot/share/runtime/interfaceSupport.inline.hpp +++ b/src/hotspot/share/runtime/interfaceSupport.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2021, Azul Systems, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -120,29 +120,6 @@ class ThreadStateTransition : public StackObj { } }; -class ThreadInVMForHandshake : public ThreadStateTransition { - const JavaThreadState _original_state; - public: - ThreadInVMForHandshake(JavaThread* thread) : ThreadStateTransition(thread), - _original_state(thread->thread_state()) { - - if (thread->has_last_Java_frame()) { - thread->frame_anchor()->make_walkable(thread); - } - - thread->set_thread_state(_thread_in_vm); - - // Threads shouldn't block if they are in the middle of printing, but... - ttyLocker::break_tty_lock_for_safepoint(os::current_thread_id()); - } - - ~ThreadInVMForHandshake() { - assert(_thread->thread_state() == _thread_in_vm, "should only call when leaving VM after handshake"); - _thread->set_thread_state(_original_state); - } - -}; - class ThreadInVMfromJava : public ThreadStateTransition { bool _check_asyncs; public: @@ -222,7 +199,7 @@ class ThreadBlockInVMPreprocess : public ThreadStateTransition { PRE_PROC& _pr; bool _allow_suspend; public: - ThreadBlockInVMPreprocess(JavaThread* thread, PRE_PROC& pr = emptyOp, bool allow_suspend = false) + ThreadBlockInVMPreprocess(JavaThread* thread, PRE_PROC& pr, bool allow_suspend = false) : ThreadStateTransition(thread), _pr(pr), _allow_suspend(allow_suspend) { transition_from_vm(thread, _thread_blocked); } @@ -236,12 +213,16 @@ class ThreadBlockInVMPreprocess : public ThreadStateTransition { SafepointMechanism::process_if_requested(_thread, _allow_suspend); } } +}; +class ThreadBlockInVM : public ThreadBlockInVMPreprocess<> { + public: + ThreadBlockInVM(JavaThread* thread, bool allow_suspend = false) + : ThreadBlockInVMPreprocess(thread, emptyOp, allow_suspend) {} + private: static void emptyOp(JavaThread* current) {} }; -typedef ThreadBlockInVMPreprocess<> ThreadBlockInVM; - // Debug class instantiated in JRT_ENTRY macro. // Can be used to verify properties on enter/exit of the VM. diff --git a/src/hotspot/share/runtime/safepoint.cpp b/src/hotspot/share/runtime/safepoint.cpp index 064a9f64b75..44240f85b71 100644 --- a/src/hotspot/share/runtime/safepoint.cpp +++ b/src/hotspot/share/runtime/safepoint.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -754,6 +754,7 @@ void SafepointSynchronize::block(JavaThread *thread) { void SafepointSynchronize::handle_polling_page_exception(JavaThread *thread) { assert(thread->thread_state() == _thread_in_Java, "should come from Java code"); + thread->set_thread_state(_thread_in_vm); // Enable WXWrite: the function is called implicitly from java code. MACOS_AARCH64_ONLY(ThreadWXEnable wx(WXWrite, thread)); @@ -765,6 +766,8 @@ void SafepointSynchronize::handle_polling_page_exception(JavaThread *thread) { ThreadSafepointState* state = thread->safepoint_state(); state->handle_polling_page_exception(); + + thread->set_thread_state(_thread_in_Java); } @@ -970,7 +973,6 @@ void ThreadSafepointState::handle_polling_page_exception() { // If we have a pending async exception deoptimize the frame // as otherwise we may never deliver it. if (self->has_async_exception_condition()) { - ThreadInVMfromJava __tiv(self, false /* check asyncs */); Deoptimization::deoptimize_frame(self, caller_fr.id()); } diff --git a/src/hotspot/share/runtime/safepoint.hpp b/src/hotspot/share/runtime/safepoint.hpp index 268a315dd7b..8024ade2520 100644 --- a/src/hotspot/share/runtime/safepoint.hpp +++ b/src/hotspot/share/runtime/safepoint.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -126,10 +126,6 @@ class SafepointSynchronize : AllStatic { JavaThread *thread, uint64_t safepoint_count); - static bool is_a_block_safe_state(JavaThreadState state) { - // Check that we have a valid thread_state before blocking for safepoints - return state == _thread_in_vm || state == _thread_in_Java; - } // Called when a thread voluntarily blocks static void block(JavaThread *thread); diff --git a/src/hotspot/share/runtime/safepointMechanism.cpp b/src/hotspot/share/runtime/safepointMechanism.cpp index b092f050539..0a4d9a436c0 100644 --- a/src/hotspot/share/runtime/safepointMechanism.cpp +++ b/src/hotspot/share/runtime/safepointMechanism.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022, 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 @@ -119,7 +119,7 @@ void SafepointMechanism::process(JavaThread *thread, bool allow_suspend) { bool need_rechecking; do { JavaThreadState state = thread->thread_state(); - guarantee(SafepointSynchronize::is_a_block_safe_state(state), "Illegal threadstate encountered: %d", state); + guarantee(state == _thread_in_vm, "Illegal threadstate encountered: %d", state); if (global_poll()) { // Any load in ::block() must not pass the global poll load. // Otherwise we might load an old safepoint counter (for example). diff --git a/src/hotspot/share/runtime/thread.cpp b/src/hotspot/share/runtime/thread.cpp index cb86541b810..e25d44f4f06 100644 --- a/src/hotspot/share/runtime/thread.cpp +++ b/src/hotspot/share/runtime/thread.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2021, Azul Systems, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -1646,24 +1646,10 @@ void JavaThread::check_and_handle_async_exceptions() { // We may be at method entry which requires we save the do-not-unlock flag. UnlockFlagSaver fs(this); - switch (thread_state()) { - case _thread_in_vm: { - JavaThread* THREAD = this; - Exceptions::throw_unsafe_access_internal_error(THREAD, __FILE__, __LINE__, "a fault occurred in an unsafe memory access operation"); - // We might have blocked in a ThreadBlockInVM wrapper in the call above so make sure we process pending - // suspend requests and object reallocation operations if any since we might be going to Java after this. - SafepointMechanism::process_if_requested_with_exit_check(this, true /* check asyncs */); - return; - } - case _thread_in_Java: { - ThreadInVMfromJava tiv(this); - JavaThread* THREAD = this; - Exceptions::throw_unsafe_access_internal_error(THREAD, __FILE__, __LINE__, "a fault occurred in an unsafe memory access operation in compiled Java code"); - return; - } - default: - ShouldNotReachHere(); - } + Exceptions::throw_unsafe_access_internal_error(this, __FILE__, __LINE__, "a fault occurred in an unsafe memory access operation"); + // We might have blocked in a ThreadBlockInVM wrapper in the call above so make sure we process pending + // suspend requests and object reallocation operations if any since we might be going to Java after this. + SafepointMechanism::process_if_requested_with_exit_check(this, true /* check asyncs */); } } @@ -1770,27 +1756,19 @@ bool JavaThread::java_resume() { } // Wait for another thread to perform object reallocation and relocking on behalf of -// this thread. -// Raw thread state transition to _thread_blocked and back again to the original -// state before returning are performed. The current thread is required to -// change to _thread_blocked in order to be seen to be safepoint/handshake safe -// whilst suspended and only after becoming handshake safe, the other thread can -// complete the handshake used to synchronize with this thread and then perform -// the reallocation and relocking. We cannot use the thread state transition -// helpers because we arrive here in various states and also because the helpers -// indirectly call this method. After leaving _thread_blocked we have to check -// for safepoint/handshake, except if _thread_in_native. The thread is safe -// without blocking then. Allowed states are enumerated in -// SafepointSynchronize::block(). See also EscapeBarrier::sync_and_suspend_*() +// this thread. The current thread is required to change to _thread_blocked in order +// to be seen to be safepoint/handshake safe whilst suspended and only after becoming +// handshake safe, the other thread can complete the handshake used to synchronize +// with this thread and then perform the reallocation and relocking. +// See EscapeBarrier::sync_and_suspend_*() void JavaThread::wait_for_object_deoptimization() { assert(!has_last_Java_frame() || frame_anchor()->walkable(), "should have walkable stack"); assert(this == Thread::current(), "invariant"); - JavaThreadState state = thread_state(); bool spin_wait = os::is_MP(); do { - set_thread_state(_thread_blocked); + ThreadBlockInVM tbivm(this, true /* allow_suspend */); // Wait for object deoptimization if requested. if (spin_wait) { // A single deoptimization is typically very short. Microbenchmarks @@ -1808,14 +1786,6 @@ void JavaThread::wait_for_object_deoptimization() { ml.wait(); } } - // The current thread could have been suspended again. We have to check for - // suspend after restoring the saved state. Without this the current thread - // might return to _thread_in_Java and execute bytecode. - set_thread_state_fence(state); - - if (state != _thread_in_native) { - SafepointMechanism::process_if_requested(this); - } // A handshake for obj. deoptimization suspend could have been processed so // we must check after processing. } while (is_obj_deopt_suspend()); -- GitLab From 35172cdaf38d83cd3ed57a5436bf985dde2d802b Mon Sep 17 00:00:00 2001 From: Ioi Lam Date: Thu, 13 Jan 2022 18:28:03 +0000 Subject: [PATCH 105/564] 8278951: containers/cgroup/PlainRead.java fails on Ubuntu 21.10 Reviewed-by: hseigel, sgehwolf --- src/hotspot/os/linux/cgroupSubsystem_linux.hpp | 4 +++- src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/hotspot/os/linux/cgroupSubsystem_linux.hpp b/src/hotspot/os/linux/cgroupSubsystem_linux.hpp index 644d8adf00a..5fc376a304e 100644 --- a/src/hotspot/os/linux/cgroupSubsystem_linux.hpp +++ b/src/hotspot/os/linux/cgroupSubsystem_linux.hpp @@ -157,8 +157,10 @@ PRAGMA_DIAG_POP NULL, \ scan_fmt, \ &variable); \ - if (err != 0) \ + if (err != 0) { \ + log_trace(os, container)(logstring, (return_type) OSCONTAINER_ERROR); \ return (return_type) OSCONTAINER_ERROR; \ + } \ \ log_trace(os, container)(logstring, variable); \ } diff --git a/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp b/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp index 25146373532..0b1bc9c6cdd 100644 --- a/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp +++ b/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2021, Red Hat Inc. + * Copyright (c) 2020, 2022, Red Hat Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,7 +36,7 @@ */ int CgroupV2Subsystem::cpu_shares() { GET_CONTAINER_INFO(int, _unified, "/cpu.weight", - "Raw value for CPU shares is: %d", "%d", shares); + "Raw value for CPU Shares is: %d", "%d", shares); // Convert default value of 100 to no shares setup if (shares == 100) { log_debug(os, container)("CPU Shares is: %d", -1); -- GitLab From 064ee6ae135366d59e9485b449a41d2b55811bbe Mon Sep 17 00:00:00 2001 From: Naoto Sato Date: Thu, 13 Jan 2022 22:05:52 +0000 Subject: [PATCH 106/564] 8278434: timeouts in test java/time/test/java/time/format/TestZoneTextPrinterParser.java Backport-of: 8dc4437d002db5d025b47f48e7420e3bae55bdec --- .../cldr/CLDRTimeZoneNameProviderImpl.java | 21 +++++---- .../format/TestZoneTextPrinterParser.java | 15 ++++--- .../openjdk/bench/java/text/ZoneStrings.java | 44 +++++++++++++++++++ 3 files changed, 66 insertions(+), 14 deletions(-) create mode 100644 test/micro/org/openjdk/bench/java/text/ZoneStrings.java diff --git a/src/java.base/share/classes/sun/util/cldr/CLDRTimeZoneNameProviderImpl.java b/src/java.base/share/classes/sun/util/cldr/CLDRTimeZoneNameProviderImpl.java index d03e753a0a4..f97888a6977 100644 --- a/src/java.base/share/classes/sun/util/cldr/CLDRTimeZoneNameProviderImpl.java +++ b/src/java.base/share/classes/sun/util/cldr/CLDRTimeZoneNameProviderImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2022, 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 @@ -151,8 +151,8 @@ public class CLDRTimeZoneNameProviderImpl extends TimeZoneNameProviderImpl { // Check parent locales first if (!exists(names, index)) { - CLDRLocaleProviderAdapter clpa = (CLDRLocaleProviderAdapter)LocaleProviderAdapter.forType(Type.CLDR); - var cands = clpa.getCandidateLocales("", locale); + var cands = ((CLDRLocaleProviderAdapter)LocaleProviderAdapter.forType(Type.CLDR)) + .getCandidateLocales("", locale); for (int i = 1; i < cands.size() ; i++) { String[] parentNames = super.getDisplayNameArray(id, cands.get(i)); if (parentNames != null && !parentNames[index].isEmpty()) { @@ -162,11 +162,6 @@ public class CLDRTimeZoneNameProviderImpl extends TimeZoneNameProviderImpl { } } - // Region Fallback - if (regionFormatFallback(names, index, locale)) { - return; - } - // Type Fallback if (noDST && typeFallback(names, index)) { return; @@ -185,6 +180,11 @@ public class CLDRTimeZoneNameProviderImpl extends TimeZoneNameProviderImpl { } } + // Region Fallback + if (regionFormatFallback(names, index, locale)) { + return; + } + // last resort names[index] = toGMTFormat(id, index == INDEX_DST_LONG || index == INDEX_DST_SHORT, @@ -230,6 +230,11 @@ public class CLDRTimeZoneNameProviderImpl extends TimeZoneNameProviderImpl { } private boolean regionFormatFallback(String[] names, int index, Locale l) { + if (index % 2 == 0) { + // ignore short names + return false; + } + String id = names[INDEX_TZID]; LocaleResources lr = LocaleProviderAdapter.forType(Type.CLDR).getLocaleResources(l); ResourceBundle fd = lr.getJavaTimeFormatData(); diff --git a/test/jdk/java/time/test/java/time/format/TestZoneTextPrinterParser.java b/test/jdk/java/time/test/java/time/format/TestZoneTextPrinterParser.java index 7981d769907..2686ea02b25 100644 --- a/test/jdk/java/time/test/java/time/format/TestZoneTextPrinterParser.java +++ b/test/jdk/java/time/test/java/time/format/TestZoneTextPrinterParser.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022, 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 @@ -51,7 +51,7 @@ import org.testng.annotations.Test; /* * @test - * @bug 8081022 8151876 8166875 8177819 8189784 8206980 8277049 + * @bug 8081022 8151876 8166875 8177819 8189784 8206980 8277049 8278434 * @key randomness */ @@ -61,6 +61,11 @@ import org.testng.annotations.Test; @Test public class TestZoneTextPrinterParser extends AbstractTestPrinterParser { + private static final Locale[] SAMPLE_LOCALES = { + Locale.US, Locale.UK, Locale.FRANCE, Locale.GERMANY, Locale.ITALY, Locale.forLanguageTag("es"), + Locale.forLanguageTag("pt-BR"), Locale.forLanguageTag("ru"), + Locale.CHINA, Locale.TAIWAN, Locale.JAPAN, Locale.KOREA, Locale.ROOT}; + protected static DateTimeFormatter getFormatter(Locale locale, TextStyle style) { return new DateTimeFormatterBuilder().appendZoneText(style) .toFormatter(locale) @@ -70,7 +75,6 @@ public class TestZoneTextPrinterParser extends AbstractTestPrinterParser { public void test_printText() { Random r = RandomFactory.getRandom(); int N = 8; - Locale[] locales = Locale.getAvailableLocales(); Set zids = ZoneRulesProvider.getAvailableZoneIds(); ZonedDateTime zdt = ZonedDateTime.now(); @@ -85,7 +89,7 @@ public class TestZoneTextPrinterParser extends AbstractTestPrinterParser { zdt = zdt.withZoneSameLocal(ZoneId.of(zid)); TimeZone tz = TimeZone.getTimeZone(zid); boolean isDST = tz.inDaylightTime(new Date(zdt.toInstant().toEpochMilli())); - for (Locale locale : locales) { + for (Locale locale : SAMPLE_LOCALES) { String longDisplayName = tz.getDisplayName(isDST, TimeZone.LONG, locale); String shortDisplayName = tz.getDisplayName(isDST, TimeZone.SHORT, locale); if ((longDisplayName.startsWith("GMT+") && shortDisplayName.startsWith("GMT+")) @@ -118,9 +122,8 @@ public class TestZoneTextPrinterParser extends AbstractTestPrinterParser { } public void test_ParseText() { - Locale[] locales = new Locale[] { Locale.ENGLISH, Locale.JAPANESE, Locale.FRENCH }; Set zids = ZoneRulesProvider.getAvailableZoneIds(); - for (Locale locale : locales) { + for (Locale locale : SAMPLE_LOCALES) { parseText(zids, locale, TextStyle.FULL, false); parseText(zids, locale, TextStyle.FULL, true); parseText(zids, locale, TextStyle.SHORT, false); diff --git a/test/micro/org/openjdk/bench/java/text/ZoneStrings.java b/test/micro/org/openjdk/bench/java/text/ZoneStrings.java new file mode 100644 index 00000000000..383cc8e0b20 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/text/ZoneStrings.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2022, 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.java.text; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; + +import java.text.DateFormatSymbols; +import java.util.Locale; + +@BenchmarkMode(Mode.SingleShotTime) +@State(Scope.Thread) +public class ZoneStrings { + + @Benchmark + public void testZoneStrings() { + for (Locale l : Locale.getAvailableLocales()) { + new DateFormatSymbols(l).getZoneStrings(); + } + } +} -- GitLab From 45f20633f66af51f017b884dc85637e8f3547d85 Mon Sep 17 00:00:00 2001 From: Hao Sun Date: Thu, 13 Jan 2022 23:56:27 +0000 Subject: [PATCH 107/564] 8279597: [TESTBUG] ReturnBlobToWrongHeapTest.java fails with -XX:TieredStopAtLevel=1 on machines with many cores Reviewed-by: kvn --- .../compiler/codecache/stress/ReturnBlobToWrongHeapTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/hotspot/jtreg/compiler/codecache/stress/ReturnBlobToWrongHeapTest.java b/test/hotspot/jtreg/compiler/codecache/stress/ReturnBlobToWrongHeapTest.java index 37d570e460f..1ef65182a0e 100644 --- a/test/hotspot/jtreg/compiler/codecache/stress/ReturnBlobToWrongHeapTest.java +++ b/test/hotspot/jtreg/compiler/codecache/stress/ReturnBlobToWrongHeapTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,6 +37,7 @@ * -XX:+SegmentedCodeCache * -XX:ReservedCodeCacheSize=16M * -XX:CodeCacheMinBlockLength=1 + * -XX:CICompilerCount=2 * compiler.codecache.stress.ReturnBlobToWrongHeapTest */ -- GitLab From 965c64bca713446e7e513170aa9138a8a5eec5de Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Fri, 14 Jan 2022 07:47:08 +0000 Subject: [PATCH 108/564] 8279699: Parallel: More precise boundary in ObjectStartArray::object_starts_in_range Reviewed-by: sjohanss, mli --- src/hotspot/share/gc/parallel/objectStartArray.cpp | 4 ++-- src/hotspot/share/gc/parallel/objectStartArray.hpp | 8 +++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/hotspot/share/gc/parallel/objectStartArray.cpp b/src/hotspot/share/gc/parallel/objectStartArray.cpp index 827ff73fb58..5383ea99cb9 100644 --- a/src/hotspot/share/gc/parallel/objectStartArray.cpp +++ b/src/hotspot/share/gc/parallel/objectStartArray.cpp @@ -133,9 +133,9 @@ bool ObjectStartArray::object_starts_in_range(HeapWord* start_addr, p2i(start_addr), p2i(end_addr)); jbyte* start_block = block_for_addr(start_addr); - jbyte* end_block = block_for_addr(end_addr); + jbyte* end_block = block_for_addr(align_up(end_addr, _card_size)); - for (jbyte* block = start_block; block <= end_block; block++) { + for (jbyte* block = start_block; block < end_block; block++) { if (*block != clean_block) { return true; } diff --git a/src/hotspot/share/gc/parallel/objectStartArray.hpp b/src/hotspot/share/gc/parallel/objectStartArray.hpp index be91b51cd94..624b3b075e6 100644 --- a/src/hotspot/share/gc/parallel/objectStartArray.hpp +++ b/src/hotspot/share/gc/parallel/objectStartArray.hpp @@ -165,9 +165,11 @@ class ObjectStartArray : public CHeapObj { return *block != clean_block; } - // Return true if an object starts in the range of heap addresses. - // If an object starts at an address corresponding to - // "start", the method will return true. + // Return true iff an object starts in + // [start_addr_aligned_down, end_addr_aligned_up) + // where + // start_addr_aligned_down = align_down(start_addr, _card_size) + // end_addr_aligned_up = align_up(end_addr, _card_size) bool object_starts_in_range(HeapWord* start_addr, HeapWord* end_addr) const; }; -- GitLab From 84976b45315feb6c37a9f3db6e1e62812c9b0a37 Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Fri, 14 Jan 2022 09:51:15 +0000 Subject: [PATCH 109/564] 8278549: UNIX sun/font coding misses SUSE distro detection on recent distro SUSE 15 Reviewed-by: mdoerr, lucy --- .../classes/sun/font/FcFontConfiguration.java | 18 +++++++++++++++++- .../classes/sun/font/MFontConfiguration.java | 18 +++++++++++++++++- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/java.desktop/unix/classes/sun/font/FcFontConfiguration.java b/src/java.desktop/unix/classes/sun/font/FcFontConfiguration.java index d839731bb2f..24eafee31a5 100644 --- a/src/java.desktop/unix/classes/sun/font/FcFontConfiguration.java +++ b/src/java.desktop/unix/classes/sun/font/FcFontConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2022, 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 @@ -295,6 +295,12 @@ public class FcFontConfiguration extends FontConfiguration { return null; } + private String extractOsInfo(String s) { + if (s.startsWith("\"")) s = s.substring(1); + if (s.endsWith("\"")) s = s.substring(0, s.length()-1); + return s; + } + /** * Sets the OS name and version from environment information. */ @@ -331,6 +337,16 @@ public class FcFontConfiguration extends FontConfiguration { } else if ((f = new File("/etc/fedora-release")).canRead()) { osName = "Fedora"; osVersion = getVersionString(f); + } else if ((f = new File("/etc/os-release")).canRead()) { + Properties props = new Properties(); + try (FileInputStream fis = new FileInputStream(f)) { + props.load(fis); + } + osName = props.getProperty("NAME"); + osVersion = props.getProperty("VERSION_ID"); + osName = extractOsInfo(osName); + if (osName.equals("SLES")) osName = "SuSE"; + osVersion = extractOsInfo(osVersion); } } catch (Exception e) { if (FontUtilities.debugFonts()) { diff --git a/src/java.desktop/unix/classes/sun/font/MFontConfiguration.java b/src/java.desktop/unix/classes/sun/font/MFontConfiguration.java index e0e58cf167b..73c61428059 100644 --- a/src/java.desktop/unix/classes/sun/font/MFontConfiguration.java +++ b/src/java.desktop/unix/classes/sun/font/MFontConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2022, 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 @@ -114,6 +114,16 @@ public class MFontConfiguration extends FontConfiguration { } osName = props.getProperty("DISTRIB_ID"); osVersion = props.getProperty("DISTRIB_RELEASE"); + } else if ((f = new File("/etc/os-release")).canRead()) { + Properties props = new Properties(); + try (FileInputStream fis = new FileInputStream(f)) { + props.load(fis); + } + osName = props.getProperty("NAME"); + osVersion = props.getProperty("VERSION_ID"); + osName = extractOsInfo(osName); + if (osName.equals("SLES")) osName = "SuSE"; + osVersion = extractOsInfo(osVersion); } } catch (Exception e) { } @@ -134,6 +144,12 @@ public class MFontConfiguration extends FontConfiguration { return null; } + private String extractOsInfo(String s) { + if (s.startsWith("\"")) s = s.substring(1); + if (s.endsWith("\"")) s = s.substring(0, s.length()-1); + return s; + } + private static final String fontsDirPrefix = "$JRE_LIB_FONTS"; protected String mapFileName(String fileName) { -- GitLab From c6b027559c6e055b1475ada4001ef483b1a12d24 Mon Sep 17 00:00:00 2001 From: Maurizio Cimadamore Date: Fri, 14 Jan 2022 11:15:16 +0000 Subject: [PATCH 110/564] 8279930: Synthetic cast causes generation of store barriers when using heap segments Reviewed-by: psandoz --- .../jdk/incubator/foreign/MemorySegment.java | 2 +- .../foreign/HeapMemorySegmentImpl.java | 60 ++-- .../jdk/incubator/foreign/LoopOverSlice.java | 259 ++++++++++++++++++ 3 files changed, 292 insertions(+), 29 deletions(-) create mode 100644 test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverSlice.java diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemorySegment.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemorySegment.java index 40cee4cf7d7..3d3401ef05b 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemorySegment.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemorySegment.java @@ -266,7 +266,7 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory *

    * The returned spliterator splits this segment according to the specified element layout; that is, * if the supplied layout has size N, then calling {@link Spliterator#trySplit()} will result in a spliterator serving - * approximately {@code S/N/2} elements (depending on whether N is even or not), where {@code S} is the size of + * approximately {@code S/N} elements (depending on whether N is even or not), where {@code S} is the size of * this segment. As such, splitting is possible as long as {@code S/N >= 2}. The spliterator returns segments that * are associated with the same scope as this segment. *

    diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/HeapMemorySegmentImpl.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/HeapMemorySegmentImpl.java index b10b278c0ca..4d2249261a3 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/HeapMemorySegmentImpl.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/HeapMemorySegmentImpl.java @@ -36,13 +36,17 @@ import java.nio.ByteBuffer; import java.util.Objects; /** - * Implementation for heap memory segments. An heap memory segment is composed by an offset and + * Implementation for heap memory segments. A heap memory segment is composed by an offset and * a base object (typically an array). To enhance performances, the access to the base object needs to feature * sharp type information, as well as sharp null-check information. For this reason, many concrete subclasses * of {@link HeapMemorySegmentImpl} are defined (e.g. {@link OfFloat}, so that each subclass can override the - * {@link HeapMemorySegmentImpl#base()} method so that it returns an array of the correct (sharp) type. + * {@link HeapMemorySegmentImpl#base()} method so that it returns an array of the correct (sharp) type. Note that + * the field type storing the 'base' coordinate is just Object; similarly, all the constructor in the subclasses + * accept an Object 'base' parameter instead of a sharper type (e.g. {@code byte[]}). This is deliberate, as + * using sharper types would require use of type-conversions, which in turn would inhibit some C2 optimizations, + * such as the elimination of store barriers in methods like {@link HeapMemorySegmentImpl#dup(long, long, int, ResourceScopeImpl)}. */ -public abstract class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl { +public abstract class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl { private static final Unsafe UNSAFE = Unsafe.getUnsafe(); private static final int BYTE_ARR_BASE = UNSAFE.arrayBaseOffset(byte[].class); @@ -53,17 +57,17 @@ public abstract class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl private static final long MAX_ALIGN_8 = 8; final long offset; - final H base; + final Object base; @ForceInline - HeapMemorySegmentImpl(long offset, H base, long length, int mask) { + HeapMemorySegmentImpl(long offset, Object base, long length, int mask) { super(length, mask, ResourceScopeImpl.GLOBAL); this.offset = offset; this.base = base; } @Override - abstract H base(); + abstract Object base(); @Override long min() { @@ -71,7 +75,7 @@ public abstract class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl } @Override - abstract HeapMemorySegmentImpl dup(long offset, long size, int mask, ResourceScopeImpl scope); + abstract HeapMemorySegmentImpl dup(long offset, long size, int mask, ResourceScopeImpl scope); @Override ByteBuffer makeByteBuffer() { @@ -84,9 +88,9 @@ public abstract class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl // factories - public static class OfByte extends HeapMemorySegmentImpl { + public static class OfByte extends HeapMemorySegmentImpl { - OfByte(long offset, byte[] base, long length, int mask) { + OfByte(long offset, Object base, long length, int mask) { super(offset, base, length, mask); } @@ -97,7 +101,7 @@ public abstract class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl @Override byte[] base() { - return Objects.requireNonNull(base); + return (byte[])Objects.requireNonNull(base); } public static MemorySegment fromArray(byte[] arr) { @@ -112,9 +116,9 @@ public abstract class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl } } - public static class OfChar extends HeapMemorySegmentImpl { + public static class OfChar extends HeapMemorySegmentImpl { - OfChar(long offset, char[] base, long length, int mask) { + OfChar(long offset, Object base, long length, int mask) { super(offset, base, length, mask); } @@ -125,7 +129,7 @@ public abstract class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl @Override char[] base() { - return Objects.requireNonNull(base); + return (char[])Objects.requireNonNull(base); } public static MemorySegment fromArray(char[] arr) { @@ -140,9 +144,9 @@ public abstract class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl } } - public static class OfShort extends HeapMemorySegmentImpl { + public static class OfShort extends HeapMemorySegmentImpl { - OfShort(long offset, short[] base, long length, int mask) { + OfShort(long offset, Object base, long length, int mask) { super(offset, base, length, mask); } @@ -153,7 +157,7 @@ public abstract class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl @Override short[] base() { - return Objects.requireNonNull(base); + return (short[])Objects.requireNonNull(base); } public static MemorySegment fromArray(short[] arr) { @@ -168,9 +172,9 @@ public abstract class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl } } - public static class OfInt extends HeapMemorySegmentImpl { + public static class OfInt extends HeapMemorySegmentImpl { - OfInt(long offset, int[] base, long length, int mask) { + OfInt(long offset, Object base, long length, int mask) { super(offset, base, length, mask); } @@ -181,7 +185,7 @@ public abstract class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl @Override int[] base() { - return Objects.requireNonNull(base); + return (int[])Objects.requireNonNull(base); } public static MemorySegment fromArray(int[] arr) { @@ -196,9 +200,9 @@ public abstract class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl } } - public static class OfLong extends HeapMemorySegmentImpl { + public static class OfLong extends HeapMemorySegmentImpl { - OfLong(long offset, long[] base, long length, int mask) { + OfLong(long offset, Object base, long length, int mask) { super(offset, base, length, mask); } @@ -209,7 +213,7 @@ public abstract class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl @Override long[] base() { - return Objects.requireNonNull(base); + return (long[])Objects.requireNonNull(base); } public static MemorySegment fromArray(long[] arr) { @@ -224,9 +228,9 @@ public abstract class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl } } - public static class OfFloat extends HeapMemorySegmentImpl { + public static class OfFloat extends HeapMemorySegmentImpl { - OfFloat(long offset, float[] base, long length, int mask) { + OfFloat(long offset, Object base, long length, int mask) { super(offset, base, length, mask); } @@ -237,7 +241,7 @@ public abstract class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl @Override float[] base() { - return Objects.requireNonNull(base); + return (float[])Objects.requireNonNull(base); } public static MemorySegment fromArray(float[] arr) { @@ -252,9 +256,9 @@ public abstract class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl } } - public static class OfDouble extends HeapMemorySegmentImpl { + public static class OfDouble extends HeapMemorySegmentImpl { - OfDouble(long offset, double[] base, long length, int mask) { + OfDouble(long offset, Object base, long length, int mask) { super(offset, base, length, mask); } @@ -265,7 +269,7 @@ public abstract class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl @Override double[] base() { - return Objects.requireNonNull(base); + return (double[])Objects.requireNonNull(base); } public static MemorySegment fromArray(double[] arr) { diff --git a/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverSlice.java b/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverSlice.java new file mode 100644 index 00000000000..ff5000f89c9 --- /dev/null +++ b/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverSlice.java @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2022, 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.jdk.incubator.foreign; + +import jdk.incubator.foreign.MemorySegment; +import jdk.incubator.foreign.ResourceScope; +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.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; +import org.openjdk.jmh.annotations.Warmup; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.IntBuffer; +import java.util.Iterator; +import java.util.concurrent.TimeUnit; + +import static jdk.incubator.foreign.MemoryLayout.PathElement.sequenceElement; +import static jdk.incubator.foreign.ValueLayout.JAVA_INT; + +@BenchmarkMode(Mode.AverageTime) +@Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) +@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) +@State(org.openjdk.jmh.annotations.Scope.Thread) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@Fork(value = 3, jvmArgsAppend = { "--add-modules=jdk.incubator.foreign", "--enable-native-access=ALL-UNNAMED" }) + +public class LoopOverSlice { + + static final int ELEM_SIZE = 1_000_000; + static final int CARRIER_SIZE = (int)JAVA_INT.byteSize(); + static final int ALLOC_SIZE = ELEM_SIZE * CARRIER_SIZE; + + MemorySegment nativeSegment, heapSegment; + IntBuffer nativeBuffer, heapBuffer; + ResourceScope scope; + + @Setup + public void setup() { + scope = ResourceScope.newConfinedScope(); + nativeSegment = MemorySegment.allocateNative(ALLOC_SIZE, scope); + heapSegment = MemorySegment.ofArray(new int[ELEM_SIZE]); + nativeBuffer = ByteBuffer.allocateDirect(ALLOC_SIZE).order(ByteOrder.LITTLE_ENDIAN).asIntBuffer(); + heapBuffer = IntBuffer.wrap(new int[ELEM_SIZE]); + } + + @TearDown + public void tearDown() { + scope.close(); + } + + @Benchmark + public void native_segment_slice_loop() { + new NativeSegmentWrapper(nativeSegment).forEach(NativeSegmentWrapper.Element::get); + } + + @Benchmark + public void native_buffer_slice_loop() { + new NativeBufferWrapper(nativeBuffer).forEach(NativeBufferWrapper.Element::get); + } + + @Benchmark + public void heap_segment_slice_loop() { + new HeapSegmentWrapper(heapSegment).forEach(HeapSegmentWrapper.Element::get); + } + + @Benchmark + public void heap_buffer_slice_loop() { + new HeapBufferWrapper(heapBuffer).forEach(HeapBufferWrapper.Element::get); + } + + class HeapSegmentWrapper implements Iterable { + final MemorySegment segment; + + public HeapSegmentWrapper(MemorySegment segment) { + this.segment = segment; + } + + @Override + public Iterator iterator() { + return new Iterator() { + + MemorySegment current = segment; + + @Override + public boolean hasNext() { + return current.byteSize() > 4; + } + + @Override + public Element next() { + Element element = new Element(current); + current = current.asSlice(4); + return element; + } + }; + } + + static class Element { + final MemorySegment segment; + + public Element(MemorySegment segment) { + this.segment = segment; + } + + int get() { + return segment.getAtIndex(JAVA_INT, 0); + } + } + } + + class NativeSegmentWrapper implements Iterable { + final MemorySegment segment; + + public NativeSegmentWrapper(MemorySegment segment) { + this.segment = segment; + } + + @Override + public Iterator iterator() { + return new Iterator() { + + MemorySegment current = segment; + + @Override + public boolean hasNext() { + return current.byteSize() > 4; + } + + @Override + public Element next() { + Element element = new Element(current); + current = current.asSlice(4); + return element; + } + }; + } + + static class Element { + final MemorySegment segment; + + public Element(MemorySegment segment) { + this.segment = segment; + } + + int get() { + return segment.getAtIndex(JAVA_INT, 0); + } + } + } + + class NativeBufferWrapper implements Iterable { + final IntBuffer buffer; + + public NativeBufferWrapper(IntBuffer buffer) { + this.buffer = buffer; + } + + @Override + public Iterator iterator() { + return new Iterator() { + + IntBuffer current = buffer; + + @Override + public boolean hasNext() { + return current.position() < current.limit(); + } + + @Override + public Element next() { + Element element = new Element(current); + int lim = current.limit(); + current = current.slice(1, lim - 1); + return element; + } + }; + } + + static class Element { + final IntBuffer buffer; + + public Element(IntBuffer segment) { + this.buffer = segment; + } + + int get() { + return buffer.get( 0); + } + } + } + + class HeapBufferWrapper implements Iterable { + final IntBuffer buffer; + + public HeapBufferWrapper(IntBuffer buffer) { + this.buffer = buffer; + } + + @Override + public Iterator iterator() { + return new Iterator() { + + IntBuffer current = buffer; + + @Override + public boolean hasNext() { + return current.position() < current.limit(); + } + + @Override + public Element next() { + Element element = new Element(current); + int lim = current.limit(); + current = current.slice(1, lim - 1); + return element; + } + }; + } + + static class Element { + final IntBuffer buffer; + + public Element(IntBuffer segment) { + this.buffer = segment; + } + + int get() { + return buffer.get( 0); + } + } + } +} -- GitLab From dd76a28d441e01b1993a71de67ace58bcb67acc8 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Fri, 14 Jan 2022 12:35:51 +0000 Subject: [PATCH 111/564] 8280000: Remove unused CardTable::find_covering_region_containing Reviewed-by: tschatzl, sjohanss --- src/hotspot/share/gc/shared/cardTable.cpp | 10 ---------- src/hotspot/share/gc/shared/cardTable.hpp | 4 ---- 2 files changed, 14 deletions(-) diff --git a/src/hotspot/share/gc/shared/cardTable.cpp b/src/hotspot/share/gc/shared/cardTable.cpp index 2ff5f8d31c3..b7f7ab81c36 100644 --- a/src/hotspot/share/gc/shared/cardTable.cpp +++ b/src/hotspot/share/gc/shared/cardTable.cpp @@ -162,16 +162,6 @@ int CardTable::find_covering_region_by_base(HeapWord* base) { return res; } -int CardTable::find_covering_region_containing(HeapWord* addr) { - for (int i = 0; i < _cur_covered_regions; i++) { - if (_covered[i].contains(addr)) { - return i; - } - } - assert(0, "address outside of heap?"); - return -1; -} - HeapWord* CardTable::largest_prev_committed_end(int ind) const { HeapWord* max_end = NULL; for (int j = 0; j < ind; j++) { diff --git a/src/hotspot/share/gc/shared/cardTable.hpp b/src/hotspot/share/gc/shared/cardTable.hpp index 075b961b3cd..ca6d1ef51dd 100644 --- a/src/hotspot/share/gc/shared/cardTable.hpp +++ b/src/hotspot/share/gc/shared/cardTable.hpp @@ -78,10 +78,6 @@ protected: // covered regions defined in the constructor are ever in use. int find_covering_region_by_base(HeapWord* base); - // Same as above, but finds the region containing the given address - // instead of starting at a given base address. - int find_covering_region_containing(HeapWord* addr); - // Returns the leftmost end of a committed region corresponding to a // covered region before covered region "ind", or else "NULL" if "ind" is // the first covered region. -- GitLab From 9f30ec174faae10484766308996cab136a779658 Mon Sep 17 00:00:00 2001 From: Julia Boes Date: Fri, 14 Jan 2022 12:48:03 +0000 Subject: [PATCH 112/564] 8278398: jwebserver: Add test to confirm maximum request time Reviewed-by: dfuchs, michaelm --- .../sun/net/httpserver/ServerImpl.java | 14 +- .../jwebserver/MaxRequestTimeTest.java | 207 ++++++++++++++++++ 2 files changed, 220 insertions(+), 1 deletion(-) create mode 100644 test/jdk/com/sun/net/httpserver/simpleserver/jwebserver/MaxRequestTimeTest.java diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java index ec6b99ab8be..03082fdb59b 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2022, 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 @@ -521,6 +521,18 @@ class ServerImpl implements TimeSource { public void run () { /* context will be null for new connections */ logger.log(Level.TRACE, "exchange started"); + + if (dispatcherThread == Thread.currentThread()) { + try { + // call selector to process cancelled keys + selector.selectNow(); + } catch (IOException ioe) { + logger.log(Level.DEBUG, "processing of cancelled keys failed: closing"); + closeConnection(connection); + return; + } + } + context = connection.getHttpContext(); boolean newconnection; SSLEngine engine = null; diff --git a/test/jdk/com/sun/net/httpserver/simpleserver/jwebserver/MaxRequestTimeTest.java b/test/jdk/com/sun/net/httpserver/simpleserver/jwebserver/MaxRequestTimeTest.java new file mode 100644 index 00000000000..697e7381a37 --- /dev/null +++ b/test/jdk/com/sun/net/httpserver/simpleserver/jwebserver/MaxRequestTimeTest.java @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2022, 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 8278398 + * @summary Tests the jwebserver's maximum request time + * @modules jdk.httpserver + * @library /test/lib + * @run testng/othervm MaxRequestTimeTest + */ + +import java.io.IOException; +import java.net.InetAddress; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLHandshakeException; +import jdk.test.lib.Platform; +import jdk.test.lib.net.SimpleSSLContext; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.util.FileUtils; +import org.testng.annotations.AfterTest; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; +import static java.lang.System.out; +import static java.net.http.HttpClient.Builder.NO_PROXY; +import static org.testng.Assert.*; + +/** + * This test confirms that the jwebserver does not wait indefinitely for + * a request to arrive. + * + * The jwebserver has a maximum request time of 5 seconds, which is set with the + * "sun.net.httpserver.maxReqTime" system property. If this threshold is + * reached, for example in the case of an HTTPS request where the server keeps + * waiting for a plaintext request, the server closes the connection. Subsequent + * requests are expected to be handled as normal. + * + * The test checks in the following order that: + * 1. an HTTP request is handled successfully, + * 2. an HTTPS request fails due to the server closing the connection + * 3. another HTTP request is handled successfully. + */ +public class MaxRequestTimeTest { + static final Path JAVA_HOME = Path.of(System.getProperty("java.home")); + static final String JWEBSERVER = getJwebserver(JAVA_HOME); + static final Path CWD = Path.of(".").toAbsolutePath().normalize(); + static final Path TEST_DIR = CWD.resolve("MaxRequestTimeTest"); + static final String LOOPBACK_ADDR = InetAddress.getLoopbackAddress().getHostAddress(); + static final AtomicInteger PORT = new AtomicInteger(); + + static SSLContext sslContext; + + @BeforeTest + public void setup() throws IOException { + if (Files.exists(TEST_DIR)) { + FileUtils.deleteFileTreeWithRetry(TEST_DIR); + } + Files.createDirectories(TEST_DIR); + + sslContext = new SimpleSSLContext().get(); + if (sslContext == null) + throw new AssertionError("Unexpected null sslContext"); + } + + @Test + public void testMaxRequestTime() throws Throwable { + final var sb = new StringBuffer(); // stdout & stderr + final var p = startProcess("jwebserver", sb); + try { + sendHTTPSRequest(); // server expected to terminate connection + sendHTTPRequest(); // server expected to respond successfully + sendHTTPSRequest(); // server expected to terminate connection + sendHTTPRequest(); // server expected to respond successfully + } finally { + p.destroy(); + int exitCode = p.waitFor(); + checkOutput(sb, exitCode); + } + } + + static String expectedBody = """ + + + + + + +

    Directory listing for /

    +
      +
    + + + """; + + void sendHTTPRequest() throws IOException, InterruptedException { + out.println("\n--- sendHTTPRequest"); + var client = HttpClient.newBuilder() + .proxy(NO_PROXY) + .build(); + var request = HttpRequest.newBuilder(URI.create("http://localhost:" + PORT.get() + "/")).build(); + var response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(response.body(), expectedBody); + } + + void sendHTTPSRequest() throws IOException, InterruptedException { + out.println("\n--- sendHTTPSRequest"); + var client = HttpClient.newBuilder() + .sslContext(sslContext) + .proxy(NO_PROXY) + .build(); + var request = HttpRequest.newBuilder(URI.create("https://localhost:" + PORT.get() + "/")).build(); + try { + client.send(request, HttpResponse.BodyHandlers.ofString()); + throw new RuntimeException("Expected SSLHandshakeException not thrown"); + } catch (SSLHandshakeException expected) { // server closes connection when max request time is reached + expected.printStackTrace(System.out); + } + } + + @AfterTest + public void teardown() throws IOException { + if (Files.exists(TEST_DIR)) { + FileUtils.deleteFileTreeWithRetry(TEST_DIR); + } + } + + // --- infra --- + + static String getJwebserver(Path image) { + boolean isWindows = System.getProperty("os.name").startsWith("Windows"); + Path jwebserver = image.resolve("bin").resolve(isWindows ? "jwebserver.exe" : "jwebserver"); + if (Files.notExists(jwebserver)) + throw new RuntimeException(jwebserver + " not found"); + return jwebserver.toAbsolutePath().toString(); + } + + // The stdout/stderr output line to wait for when starting the jwebserver + static final String REGULAR_STARTUP_LINE_STRING_1 = "URL http://"; + static final String REGULAR_STARTUP_LINE_STRING_2 = "Serving "; + + static void parseAndSetPort(String line) { + PORT.set(Integer.parseInt(line.split(" port ")[1])); + } + + static Process startProcess(String name, StringBuffer sb) throws Throwable { + // starts the process, parses the port and awaits startup line before sending requests + return ProcessTools.startProcess(name, + new ProcessBuilder(JWEBSERVER, "-p", "0").directory(TEST_DIR.toFile()), + line -> { + if (line.startsWith(REGULAR_STARTUP_LINE_STRING_2)) { parseAndSetPort(line); } + sb.append(line + "\n"); + }, + line -> line.startsWith(REGULAR_STARTUP_LINE_STRING_1), + 30, // suitably high default timeout, not expected to timeout + TimeUnit.SECONDS); + } + + static final int SIGTERM = 15; + static final int NORMAL_EXIT_CODE = normalExitCode(); + + static int normalExitCode() { + if (Platform.isWindows()) { + return 1; // expected process destroy exit code + } else { + // signal terminated exit code on Unix is 128 + signal value + return 128 + SIGTERM; + } + } + + static void checkOutput(StringBuffer sb, int exitCode) { + out.println("\n--- server output: \n" + sb); + var outputAnalyser = new OutputAnalyzer(sb.toString(), "", exitCode); + outputAnalyser.shouldHaveExitValue(NORMAL_EXIT_CODE) + .shouldContain("Binding to loopback by default. For all interfaces use \"-b 0.0.0.0\" or \"-b ::\".") + .shouldContain("Serving " + TEST_DIR + " and subdirectories on " + LOOPBACK_ADDR + " port " + PORT) + .shouldContain("URL http://" + LOOPBACK_ADDR); + } +} -- GitLab From 4b520f0001be5f33996d5ab7d9ad75773a847e54 Mon Sep 17 00:00:00 2001 From: Johannes Bechberger Date: Fri, 14 Jan 2022 13:53:53 +0000 Subject: [PATCH 113/564] 8279702: [macosx] ignore xcodebuild warnings on M1 Reviewed-by: goetz, erikj --- make/autoconf/toolchain.m4 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/make/autoconf/toolchain.m4 b/make/autoconf/toolchain.m4 index 9666d9a6d9d..5280520b78b 100644 --- a/make/autoconf/toolchain.m4 +++ b/make/autoconf/toolchain.m4 @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2022, 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 @@ -234,7 +234,7 @@ AC_DEFUN_ONCE([TOOLCHAIN_DETERMINE_TOOLCHAIN_TYPE], if test "x$OPENJDK_TARGET_OS" = xmacosx; then if test -n "$XCODEBUILD"; then # On Mac OS X, default toolchain to clang after Xcode 5 - XCODE_VERSION_OUTPUT=`"$XCODEBUILD" -version 2>&1 | $HEAD -n 1` + XCODE_VERSION_OUTPUT=`"$XCODEBUILD" -version | $HEAD -n 1` $ECHO "$XCODE_VERSION_OUTPUT" | $GREP "Xcode " > /dev/null if test $? -ne 0; then AC_MSG_NOTICE([xcodebuild output: $XCODE_VERSION_OUTPUT]) -- GitLab From c809d34f9ec0d8e9f77adc73ee772ce90efbe58d Mon Sep 17 00:00:00 2001 From: Martin Doerr Date: Fri, 14 Jan 2022 14:12:38 +0000 Subject: [PATCH 114/564] 8279924: [PPC64, s390] implement frame::is_interpreted_frame_valid checks Reviewed-by: rrich, mbaesken --- src/hotspot/cpu/ppc/frame_ppc.cpp | 55 ++++++++++++++++++++++++++--- src/hotspot/cpu/s390/frame_s390.cpp | 55 ++++++++++++++++++++++++++--- 2 files changed, 102 insertions(+), 8 deletions(-) diff --git a/src/hotspot/cpu/ppc/frame_ppc.cpp b/src/hotspot/cpu/ppc/frame_ppc.cpp index 870345789d6..31a2b287442 100644 --- a/src/hotspot/cpu/ppc/frame_ppc.cpp +++ b/src/hotspot/cpu/ppc/frame_ppc.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2021 SAP SE. All rights reserved. + * Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022 SAP SE. 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 @@ -294,9 +294,56 @@ void frame::patch_pc(Thread* thread, address pc) { } bool frame::is_interpreted_frame_valid(JavaThread* thread) const { - // Is there anything to do? assert(is_interpreted_frame(), "Not an interpreted frame"); - return true; + // These are reasonable sanity checks + if (fp() == 0 || (intptr_t(fp()) & (wordSize-1)) != 0) { + return false; + } + if (sp() == 0 || (intptr_t(sp()) & (wordSize-1)) != 0) { + return false; + } + if (fp() - (abi_minframe_size + ijava_state_size) < sp()) { + return false; + } + // These are hacks to keep us out of trouble. + // The problem with these is that they mask other problems + if (fp() <= sp()) { // this attempts to deal with unsigned comparison above + return false; + } + + // do some validation of frame elements + + // first the method + + Method* m = *interpreter_frame_method_addr(); + + // validate the method we'd find in this potential sender + if (!Method::is_valid_method(m)) return false; + + // stack frames shouldn't be much larger than max_stack elements + // this test requires the use of unextended_sp which is the sp as seen by + // the current frame, and not sp which is the "raw" pc which could point + // further because of local variables of the callee method inserted after + // method arguments + if (fp() - unextended_sp() > 1024 + m->max_stack()*Interpreter::stackElementSize) { + return false; + } + + // validate bci/bcx + + address bcp = interpreter_frame_bcp(); + if (m->validate_bci_from_bcp(bcp) < 0) { + return false; + } + + // validate constantPoolCache* + ConstantPoolCache* cp = *interpreter_frame_cache_addr(); + if (MetaspaceObj::is_valid(cp) == false) return false; + + // validate locals + + address locals = (address) *interpreter_frame_locals_addr(); + return thread->is_in_stack_range_incl(locals, (address)fp()); } BasicType frame::interpreter_frame_result(oop* oop_result, jvalue* value_result) { diff --git a/src/hotspot/cpu/s390/frame_s390.cpp b/src/hotspot/cpu/s390/frame_s390.cpp index d29227bb32e..72e1dffe57d 100644 --- a/src/hotspot/cpu/s390/frame_s390.cpp +++ b/src/hotspot/cpu/s390/frame_s390.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016, 2019 SAP SE. All rights reserved. + * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022 SAP SE. 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 @@ -298,9 +298,56 @@ void frame::patch_pc(Thread* thread, address pc) { } bool frame::is_interpreted_frame_valid(JavaThread* thread) const { - // Is there anything to do? assert(is_interpreted_frame(), "Not an interpreted frame"); - return true; + // These are reasonable sanity checks + if (fp() == 0 || (intptr_t(fp()) & (wordSize-1)) != 0) { + return false; + } + if (sp() == 0 || (intptr_t(sp()) & (wordSize-1)) != 0) { + return false; + } + if (fp() - (z_abi_16_size + z_ijava_state_size) < sp()) { + return false; + } + // These are hacks to keep us out of trouble. + // The problem with these is that they mask other problems + if (fp() <= sp()) { // this attempts to deal with unsigned comparison above + return false; + } + + // do some validation of frame elements + + // first the method + + Method* m = *interpreter_frame_method_addr(); + + // validate the method we'd find in this potential sender + if (!Method::is_valid_method(m)) return false; + + // stack frames shouldn't be much larger than max_stack elements + // this test requires the use of unextended_sp which is the sp as seen by + // the current frame, and not sp which is the "raw" pc which could point + // further because of local variables of the callee method inserted after + // method arguments + if (fp() - unextended_sp() > 1024 + m->max_stack()*Interpreter::stackElementSize) { + return false; + } + + // validate bci/bcx + + address bcp = interpreter_frame_bcp(); + if (m->validate_bci_from_bcp(bcp) < 0) { + return false; + } + + // validate constantPoolCache* + ConstantPoolCache* cp = *interpreter_frame_cache_addr(); + if (MetaspaceObj::is_valid(cp) == false) return false; + + // validate locals + + address locals = (address) *interpreter_frame_locals_addr(); + return thread->is_in_stack_range_incl(locals, (address)fp()); } BasicType frame::interpreter_frame_result(oop* oop_result, jvalue* value_result) { -- GitLab From e8f494cd5f2e7ef345cd145ad7836419efa1a059 Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Fri, 14 Jan 2022 14:31:42 +0000 Subject: [PATCH 115/564] 8279825: JFR: JFCModel shouldn't need FilePermission to read predefined .jfc files Reviewed-by: mgronlun --- .../classes/jdk/jfr/internal/jfc/JFC.java | 13 +++++++ .../jdk/jfr/internal/jfc/model/JFCModel.java | 36 +++++++++++-------- .../jdk/jfr/internal/jfc/model/Parser.java | 11 +++--- .../jdk/jfr/internal/tool/Configure.java | 2 +- 4 files changed, 40 insertions(+), 22 deletions(-) diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/JFC.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/JFC.java index 6d798e294dd..6a37bea34ad 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/JFC.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/JFC.java @@ -25,9 +25,11 @@ package jdk.jfr.internal.jfc; +import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.Reader; +import java.io.StringReader; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.NoSuchFileException; @@ -62,9 +64,11 @@ public final class JFC { private final String content; private final String filename; private final String name; + private final SafePath path; private Configuration configuration; public KnownConfiguration(SafePath knownPath) throws IOException { + this.path = knownPath; this.content = readContent(knownPath); this.name = nameFromPath(knownPath.toPath()); this.filename = nullSafeFileName(knownPath.toPath()); @@ -270,4 +274,13 @@ public final class JFC { } throw new NoSuchFileException("Could not locate configuration with name " + name); } + + public static Reader newReader(SafePath sf) throws IOException { + for (KnownConfiguration c : getKnownConfigurations()) { + if (c.path.equals(sf)) { + return new StringReader(c.content); + } + } + return new FileReader(sf.toFile(), StandardCharsets.UTF_8); + } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/model/JFCModel.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/model/JFCModel.java index 0623b4d25dd..746954a3e71 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/model/JFCModel.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/model/JFCModel.java @@ -26,6 +26,7 @@ package jdk.jfr.internal.jfc.model; import java.io.IOException; import java.io.PrintWriter; +import java.io.Reader; import java.text.ParseException; import java.util.ArrayList; import java.util.Collections; @@ -35,6 +36,7 @@ import java.util.Map; import java.util.function.Consumer; import jdk.jfr.internal.SecuritySupport.SafePath; +import jdk.jfr.internal.jfc.JFC; import static java.nio.charset.StandardCharsets.UTF_8; @@ -43,9 +45,13 @@ public final class JFCModel { private final Map> controls = new LinkedHashMap<>(); private final XmlConfiguration configuration; - public JFCModel(SafePath file, Consumer logger) throws ParseException, IOException { - this.configuration = createConfiguration(file); - this.configuration.validate(); + private JFCModel(XmlConfiguration configuration) throws ParseException { + configuration.validate(); + this.configuration = configuration; + } + + public JFCModel(Reader reader, Consumer logger) throws ParseException, IOException { + this(Parser.parse(reader)); addControls(); wireConditions(); wireSettings(logger); @@ -55,7 +61,7 @@ public final class JFCModel { this.configuration = new XmlConfiguration(); this.configuration.setAttribute("version", "2.0"); for (SafePath file : files) { - JFCModel model = new JFCModel(file, logger); + JFCModel model = JFCModel.create(file, logger); for (var entry : model.controls.entrySet()) { String name = entry.getKey(); // Fail-fast checks that prevents an ambiguous file to be written later @@ -70,6 +76,18 @@ public final class JFCModel { } } + public static JFCModel create(SafePath file, Consumer logger) throws ParseException, IOException { + if (file.toString().equals("none")) { + XmlConfiguration configuration = new XmlConfiguration(); + configuration.setAttribute("version", "2.0"); + configuration.setAttribute("label", "None"); + return new JFCModel(configuration); + } + try (Reader r = JFC.newReader(file)) { + return new JFCModel(r, logger); + } + } + public void setLabel(String label) { configuration.setAttribute("label", label); } @@ -205,14 +223,4 @@ public final class JFCModel { private void add(ControlElement control) { controls.computeIfAbsent(control.getName(), x -> new ArrayList<>()).add(control); } - - private XmlConfiguration createConfiguration(SafePath file) throws ParseException, IOException { - if (file.toString().equals("none")) { - XmlConfiguration configuration = new XmlConfiguration(); - configuration.setAttribute("version", "2.0"); - configuration.setAttribute("label", "None"); - return configuration; - } - return Parser.parse(file.toPath()); - } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/model/Parser.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/model/Parser.java index 78fd246ca7e..3b6aa05d9bd 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/model/Parser.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/model/Parser.java @@ -24,9 +24,8 @@ */ package jdk.jfr.internal.jfc.model; -import java.io.FileReader; import java.io.IOException; -import java.nio.file.Path; +import java.io.Reader; import java.text.ParseException; import java.util.ArrayDeque; import java.util.Deque; @@ -38,15 +37,13 @@ import jdk.internal.org.xml.sax.helpers.DefaultHandler; import jdk.internal.util.xml.SAXParser; import jdk.internal.util.xml.impl.SAXParserImpl; -import static java.nio.charset.StandardCharsets.UTF_8; - final class Parser { - static XmlConfiguration parse(Path path) throws ParseException, IOException { - try (FileReader r = new FileReader(path.toFile(), UTF_8)) { + static XmlConfiguration parse(Reader reader) throws ParseException, IOException { + try { SAXParser saxParser = new SAXParserImpl(); ConfigurationHandler handler = new ConfigurationHandler(); - saxParser.parse(new InputSource(r), handler); + saxParser.parse(new InputSource(reader), handler); return handler.configuration; } catch (SAXException sp) { ParseException pe = new ParseException(sp.getMessage(), -1); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Configure.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Configure.java index 6281b0f1595..551264c6889 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Configure.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Configure.java @@ -127,7 +127,7 @@ final class Configure extends Command { } private void displayParameters(PrintStream stream, SafePath path, String name) throws ParseException, IOException { - JFCModel parameters = new JFCModel(path, l -> stream.println("Warning! " + l)); + JFCModel parameters = JFCModel.create(path, l -> stream.println("Warning! " + l)); stream.println(); stream.println("Options for " + name + ":"); stream.println(); -- GitLab From 35734ad0805b9ecaf6eb72a4b1513b8de53ed72c Mon Sep 17 00:00:00 2001 From: Harold Seigel Date: Fri, 14 Jan 2022 14:41:12 +0000 Subject: [PATCH 116/564] 8279545: Buffer overrun in reverse_words of sharedRuntime_x86_64.cpp:3517 Reviewed-by: coleenp, lfoltan --- src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp | 8 +++++--- src/hotspot/cpu/s390/sharedRuntime_s390.cpp | 8 +++++--- src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp | 8 +++++--- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp b/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp index a834fa1af36..315ca3f7062 100644 --- a/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp +++ b/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2021 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -3216,8 +3216,9 @@ void SharedRuntime::montgomery_multiply(jint *a_ints, jint *b_ints, jint *n_ints // Make very sure we don't use so much space that the stack might // overflow. 512 jints corresponds to an 16384-bit integer and // will use here a total of 8k bytes of stack space. + int divisor = sizeof(unsigned long) * 4; + guarantee(longwords <= 8192 / divisor, "must be"); int total_allocation = longwords * sizeof (unsigned long) * 4; - guarantee(total_allocation <= 8192, "must be"); unsigned long *scratch = (unsigned long *)alloca(total_allocation); // Local scratch arrays @@ -3246,8 +3247,9 @@ void SharedRuntime::montgomery_square(jint *a_ints, jint *n_ints, // Make very sure we don't use so much space that the stack might // overflow. 512 jints corresponds to an 16384-bit integer and // will use here a total of 6k bytes of stack space. + int divisor = sizeof(unsigned long) * 3; + guarantee(longwords <= (8192 / divisor), "must be"); int total_allocation = longwords * sizeof (unsigned long) * 3; - guarantee(total_allocation <= 8192, "must be"); unsigned long *scratch = (unsigned long *)alloca(total_allocation); // Local scratch arrays diff --git a/src/hotspot/cpu/s390/sharedRuntime_s390.cpp b/src/hotspot/cpu/s390/sharedRuntime_s390.cpp index 2b310f6e44f..107ec979ffd 100644 --- a/src/hotspot/cpu/s390/sharedRuntime_s390.cpp +++ b/src/hotspot/cpu/s390/sharedRuntime_s390.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2019 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -3219,8 +3219,9 @@ void SharedRuntime::montgomery_multiply(jint *a_ints, jint *b_ints, jint *n_ints // Make very sure we don't use so much space that the stack might // overflow. 512 jints corresponds to an 16384-bit integer and // will use here a total of 8k bytes of stack space. + int divisor = sizeof(unsigned long) * 4; + guarantee(longwords <= 8192 / divisor, "must be"); int total_allocation = longwords * sizeof (unsigned long) * 4; - guarantee(total_allocation <= 8192, "must be"); unsigned long *scratch = (unsigned long *)alloca(total_allocation); // Local scratch arrays @@ -3249,8 +3250,9 @@ void SharedRuntime::montgomery_square(jint *a_ints, jint *n_ints, // Make very sure we don't use so much space that the stack might // overflow. 512 jints corresponds to an 16384-bit integer and // will use here a total of 6k bytes of stack space. + int divisor = sizeof(unsigned long) * 3; + guarantee(longwords <= (8192 / divisor), "must be"); int total_allocation = longwords * sizeof (unsigned long) * 3; - guarantee(total_allocation <= 8192, "must be"); unsigned long *scratch = (unsigned long *)alloca(total_allocation); // Local scratch arrays diff --git a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp index cf1e3760a37..6597c91bb42 100644 --- a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp +++ b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, 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 @@ -3542,8 +3542,9 @@ void SharedRuntime::montgomery_multiply(jint *a_ints, jint *b_ints, jint *n_ints // Make very sure we don't use so much space that the stack might // overflow. 512 jints corresponds to an 16384-bit integer and // will use here a total of 8k bytes of stack space. + int divisor = sizeof(julong) * 4; + guarantee(longwords <= 8192 / divisor, "must be"); int total_allocation = longwords * sizeof (julong) * 4; - guarantee(total_allocation <= 8192, "must be"); julong *scratch = (julong *)alloca(total_allocation); // Local scratch arrays @@ -3571,8 +3572,9 @@ void SharedRuntime::montgomery_square(jint *a_ints, jint *n_ints, // Make very sure we don't use so much space that the stack might // overflow. 512 jints corresponds to an 16384-bit integer and // will use here a total of 6k bytes of stack space. + int divisor = sizeof(julong) * 3; + guarantee(longwords <= (8192 / divisor), "must be"); int total_allocation = longwords * sizeof (julong) * 3; - guarantee(total_allocation <= 8192, "must be"); julong *scratch = (julong *)alloca(total_allocation); // Local scratch arrays -- GitLab From 61b8944327e3d12cf58dc3f6bc45ecbeba4ef611 Mon Sep 17 00:00:00 2001 From: Sean Mullan Date: Fri, 14 Jan 2022 15:22:31 +0000 Subject: [PATCH 117/564] 8278851: Correct signer logic for jars signed with multiple digestalgs Reviewed-by: coffeys, weijun --- .../classes/java/util/jar/JarVerifier.java | 10 +- .../security/util/ManifestEntryVerifier.java | 115 +++++++----- .../JarWithOneNonDisabledDigestAlg.java | 169 ++++++++++++++++++ 3 files changed, 244 insertions(+), 50 deletions(-) create mode 100644 test/jdk/jdk/security/jarsigner/JarWithOneNonDisabledDigestAlg.java diff --git a/src/java.base/share/classes/java/util/jar/JarVerifier.java b/src/java.base/share/classes/java/util/jar/JarVerifier.java index 280d64e9d37..e6a217b424c 100644 --- a/src/java.base/share/classes/java/util/jar/JarVerifier.java +++ b/src/java.base/share/classes/java/util/jar/JarVerifier.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -96,6 +96,10 @@ class JarVerifier { /** collect -DIGEST-MANIFEST values for deny list */ private List manifestDigests; + /* A cache mapping code signers to the algorithms used to digest jar + entries, and whether or not the algorithms are permitted. */ + private Map> signersToAlgs; + public JarVerifier(String name, byte[] rawBytes) { manifestName = name; manifestRawBytes = rawBytes; @@ -105,6 +109,7 @@ class JarVerifier { pendingBlocks = new ArrayList<>(); baos = new ByteArrayOutputStream(); manifestDigests = new ArrayList<>(); + signersToAlgs = new HashMap<>(); } /** @@ -244,7 +249,8 @@ class JarVerifier { if (!parsingBlockOrSF) { JarEntry je = mev.getEntry(); if ((je != null) && (je.signers == null)) { - je.signers = mev.verify(verifiedSigners, sigFileSigners); + je.signers = mev.verify(verifiedSigners, sigFileSigners, + signersToAlgs); je.certs = mapSignersToCertArray(je.signers); } } else { diff --git a/src/java.base/share/classes/sun/security/util/ManifestEntryVerifier.java b/src/java.base/share/classes/sun/security/util/ManifestEntryVerifier.java index 14a56e33f38..187922cc8f2 100644 --- a/src/java.base/share/classes/sun/security/util/ManifestEntryVerifier.java +++ b/src/java.base/share/classes/sun/security/util/ManifestEntryVerifier.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -192,7 +192,8 @@ public class ManifestEntryVerifier { * */ public CodeSigner[] verify(Hashtable verifiedSigners, - Hashtable sigFileSigners) + Hashtable sigFileSigners, + Map> signersToAlgs) throws JarException { if (skip) { @@ -207,38 +208,60 @@ public class ManifestEntryVerifier { return signers; } - JarConstraintsParameters params = - getParams(verifiedSigners, sigFileSigners); + CodeSigner[] entrySigners = sigFileSigners.get(name); + Map algsPermittedStatus = + algsPermittedStatusForSigners(signersToAlgs, entrySigners); + // Flag that indicates if only disabled algorithms are used and jar + // entry should be treated as unsigned. + boolean disabledAlgs = true; + JarConstraintsParameters params = null; for (int i=0; i < digests.size(); i++) { MessageDigest digest = digests.get(i); - if (params != null) { - try { - params.setExtendedExceptionMsg(JarFile.MANIFEST_NAME, - name + " entry"); - DisabledAlgorithmConstraints.jarConstraints() - .permits(digest.getAlgorithm(), params, false); - } catch (GeneralSecurityException e) { - if (debug != null) { - debug.println("Digest algorithm is restricted: " + e); + String digestAlg = digest.getAlgorithm(); + + // Check if this algorithm is permitted, skip if false. + if (algsPermittedStatus != null) { + Boolean permitted = algsPermittedStatus.get(digestAlg); + if (permitted == null) { + if (params == null) { + params = new JarConstraintsParameters(entrySigners); } - return null; + if (!checkConstraints(digestAlg, params)) { + algsPermittedStatus.put(digestAlg, Boolean.FALSE); + continue; + } else { + algsPermittedStatus.put(digestAlg, Boolean.TRUE); + } + } else if (!permitted) { + continue; } } + + // A non-disabled algorithm was used. + disabledAlgs = false; + byte [] manHash = manifestHashes.get(i); byte [] theHash = digest.digest(); if (debug != null) { debug.println("Manifest Entry: " + - name + " digest=" + digest.getAlgorithm()); + name + " digest=" + digestAlg); debug.println(" manifest " + HexFormat.of().formatHex(manHash)); debug.println(" computed " + HexFormat.of().formatHex(theHash)); debug.println(); } - if (!MessageDigest.isEqual(theHash, manHash)) - throw new SecurityException(digest.getAlgorithm()+ + if (!MessageDigest.isEqual(theHash, manHash)) { + throw new SecurityException(digestAlg + " digest error for "+name); + } + } + + // If there were only disabled algorithms used, return null and jar + // entry will be treated as unsigned. + if (disabledAlgs) { + return null; } // take it out of sigFileSigners and put it in verifiedSigners... @@ -249,40 +272,36 @@ public class ManifestEntryVerifier { return signers; } - /** - * Get constraints parameters for JAR. The constraints should be - * checked against all code signers. Returns the parameters, - * or null if the signers for this entry have already been checked - * or there are no signers for this entry. - */ - private JarConstraintsParameters getParams( - Map verifiedSigners, - Map sigFileSigners) { - - // verifiedSigners is usually preloaded with the Manifest's signers. - // If verifiedSigners contains the Manifest, then it will have all of - // the signers of the JAR. But if it doesn't then we need to fallback - // and check verifiedSigners to see if the signers of this entry have - // been checked already. - if (verifiedSigners.containsKey(manifestFileName)) { - if (verifiedSigners.size() > 1) { - // this means we already checked it previously - return null; - } else { - return new JarConstraintsParameters( - verifiedSigners.get(manifestFileName)); + // Gets the algorithms permitted status for the signers of this entry. + private static Map algsPermittedStatusForSigners( + Map> signersToAlgs, + CodeSigner[] signers) { + if (signers != null) { + Map algs = signersToAlgs.get(signers); + // create new HashMap if absent + if (algs == null) { + algs = new HashMap<>(); + signersToAlgs.put(signers, algs); } - } else { + return algs; + } + return null; + } + + // Checks the algorithm constraints against the signers of this entry. + private boolean checkConstraints(String algorithm, + JarConstraintsParameters params) { + try { + params.setExtendedExceptionMsg(JarFile.MANIFEST_NAME, + name + " entry"); + DisabledAlgorithmConstraints.jarConstraints() + .permits(algorithm, params, false); + return true; + } catch (GeneralSecurityException e) { if (debug != null) { - debug.println(manifestFileName + " not present in verifiedSigners"); - } - CodeSigner[] signers = sigFileSigners.get(name); - if (signers == null || verifiedSigners.containsValue(signers)) { - return null; - } else { - return new JarConstraintsParameters(signers); + debug.println("Digest algorithm is restricted: " + e); } + return false; } } } - diff --git a/test/jdk/jdk/security/jarsigner/JarWithOneNonDisabledDigestAlg.java b/test/jdk/jdk/security/jarsigner/JarWithOneNonDisabledDigestAlg.java new file mode 100644 index 00000000000..899500672ad --- /dev/null +++ b/test/jdk/jdk/security/jarsigner/JarWithOneNonDisabledDigestAlg.java @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2022, 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 8278851 + * @summary Check that jar entry with at least one non-disabled digest + * algorithm in manifest is treated as signed + * @modules java.base/sun.security.tools.keytool + * @library /test/lib + * @build jdk.test.lib.util.JarUtils + * jdk.test.lib.security.SecurityUtils + * @run main/othervm JarWithOneNonDisabledDigestAlg + */ + +import java.io.InputStream; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.security.CodeSigner; +import java.security.KeyStore; +import java.util.Enumeration; +import java.util.List; +import java.util.Locale; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.zip.ZipFile; +import jdk.security.jarsigner.JarSigner; + +import jdk.test.lib.util.JarUtils; +import jdk.test.lib.security.SecurityUtils; + +public class JarWithOneNonDisabledDigestAlg { + + private static final String PASS = "changeit"; + private static final String TESTFILE1 = "testfile1"; + private static final String TESTFILE2 = "testfile2"; + + public static void main(String[] args) throws Exception { + SecurityUtils.removeFromDisabledAlgs("jdk.jar.disabledAlgorithms", + List.of("SHA1")); + Files.write(Path.of(TESTFILE1), TESTFILE1.getBytes()); + JarUtils.createJarFile(Path.of("unsigned.jar"), Path.of("."), + Path.of(TESTFILE1)); + + genkeypair("-alias SHA1 -sigalg SHA1withRSA"); + genkeypair("-alias SHA256 -sigalg SHA256withRSA"); + + KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); + try (FileInputStream fis = new FileInputStream("keystore")) { + ks.load(fis, PASS.toCharArray()); + } + + // Sign JAR twice with same signer but different digest algorithms + // so that each entry in manifest file contains two digest values. + signJarFile(ks, "SHA1", "MD5", "unsigned.jar", "signed.jar"); + signJarFile(ks, "SHA1", "SHA1", "signed.jar", "signed2.jar"); + checkThatJarIsSigned("signed2.jar", false); + + // add another file to the JAR + Files.write(Path.of(TESTFILE2), "testFile2".getBytes()); + JarUtils.updateJarFile(Path.of("signed2.jar"), Path.of("."), + Path.of(TESTFILE2)); + + // Sign again with different signer (SHA256) and SHA-1 digestalg. + // TESTFILE1 should have two signers and TESTFILE2 should have one + // signer. + signJarFile(ks, "SHA256", "SHA1", "signed2.jar", "multi-signed.jar"); + + checkThatJarIsSigned("multi-signed.jar", true); + } + + private static KeyStore.PrivateKeyEntry getEntry(KeyStore ks, String alias) + throws Exception { + + return (KeyStore.PrivateKeyEntry) + ks.getEntry(alias, + new KeyStore.PasswordProtection(PASS.toCharArray())); + } + + private static void genkeypair(String cmd) throws Exception { + cmd = "-genkeypair -keystore keystore -storepass " + PASS + + " -keypass " + PASS + " -keyalg rsa -dname CN=Duke " + cmd; + sun.security.tools.keytool.Main.main(cmd.split(" ")); + } + + private static void signJarFile(KeyStore ks, String alias, + String digestAlg, String inputFile, String outputFile) + throws Exception { + + JarSigner signer = new JarSigner.Builder(getEntry(ks, alias)) + .digestAlgorithm(digestAlg) + .signerName(alias) + .build(); + + try (ZipFile in = new ZipFile(inputFile); + FileOutputStream out = new FileOutputStream(outputFile)) { + signer.sign(in, out); + } + } + + private static void checkThatJarIsSigned(String jarFile, boolean multi) + throws Exception { + + try (JarFile jf = new JarFile(jarFile, true)) { + Enumeration entries = jf.entries(); + while (entries.hasMoreElements()) { + JarEntry entry = entries.nextElement(); + if (entry.isDirectory() || isSigningRelated(entry.getName())) { + continue; + } + InputStream is = jf.getInputStream(entry); + while (is.read() != -1); + CodeSigner[] signers = entry.getCodeSigners(); + if (signers == null) { + throw new Exception("JarEntry " + entry.getName() + + " is not signed"); + } else if (multi) { + if (entry.getName().equals(TESTFILE1) && + signers.length != 2) { + throw new Exception("Unexpected number of signers " + + "for " + entry.getName() + ": " + signers.length); + } else if (entry.getName().equals(TESTFILE2) && + signers.length != 1) { + throw new Exception("Unexpected number of signers " + + "for " + entry.getName() + ": " + signers.length); + } + } + } + } + } + + private static boolean isSigningRelated(String name) { + name = name.toUpperCase(Locale.ENGLISH); + if (!name.startsWith("META-INF/")) { + return false; + } + name = name.substring(9); + if (name.indexOf('/') != -1) { + return false; + } + return name.endsWith(".SF") + || name.endsWith(".DSA") + || name.endsWith(".RSA") + || name.endsWith(".EC") + || name.equals("MANIFEST.MF"); + } +} -- GitLab From ac98b22040f854de79813a1c2a97fc399d3bcc42 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Fri, 14 Jan 2022 15:54:31 +0000 Subject: [PATCH 118/564] 8280028: [BACKOUT] Parallel: More precise boundary in ObjectStartArray::object_starts_in_range Reviewed-by: sjohanss --- src/hotspot/share/gc/parallel/objectStartArray.cpp | 4 ++-- src/hotspot/share/gc/parallel/objectStartArray.hpp | 8 +++----- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/hotspot/share/gc/parallel/objectStartArray.cpp b/src/hotspot/share/gc/parallel/objectStartArray.cpp index 5383ea99cb9..827ff73fb58 100644 --- a/src/hotspot/share/gc/parallel/objectStartArray.cpp +++ b/src/hotspot/share/gc/parallel/objectStartArray.cpp @@ -133,9 +133,9 @@ bool ObjectStartArray::object_starts_in_range(HeapWord* start_addr, p2i(start_addr), p2i(end_addr)); jbyte* start_block = block_for_addr(start_addr); - jbyte* end_block = block_for_addr(align_up(end_addr, _card_size)); + jbyte* end_block = block_for_addr(end_addr); - for (jbyte* block = start_block; block < end_block; block++) { + for (jbyte* block = start_block; block <= end_block; block++) { if (*block != clean_block) { return true; } diff --git a/src/hotspot/share/gc/parallel/objectStartArray.hpp b/src/hotspot/share/gc/parallel/objectStartArray.hpp index 624b3b075e6..be91b51cd94 100644 --- a/src/hotspot/share/gc/parallel/objectStartArray.hpp +++ b/src/hotspot/share/gc/parallel/objectStartArray.hpp @@ -165,11 +165,9 @@ class ObjectStartArray : public CHeapObj { return *block != clean_block; } - // Return true iff an object starts in - // [start_addr_aligned_down, end_addr_aligned_up) - // where - // start_addr_aligned_down = align_down(start_addr, _card_size) - // end_addr_aligned_up = align_up(end_addr, _card_size) + // Return true if an object starts in the range of heap addresses. + // If an object starts at an address corresponding to + // "start", the method will return true. bool object_starts_in_range(HeapWord* start_addr, HeapWord* end_addr) const; }; -- GitLab From f1805309352a22119ae2edf8bfbb596f00936224 Mon Sep 17 00:00:00 2001 From: Pavel Rappo Date: Fri, 14 Jan 2022 16:10:14 +0000 Subject: [PATCH 119/564] 8279918: Fix various doc typos Reviewed-by: kevinw, lancea, mullan, sspitsyn, naoto, jlahoda, azvegint, egahlin, jjg --- .../share/classes/java/io/DataInput.java | 4 ++-- .../classes/java/io/ObjectInputStream.java | 4 ++-- .../classes/java/io/PipedInputStream.java | 4 ++-- .../share/classes/java/lang/Class.java | 4 ++-- .../share/classes/java/math/BigDecimal.java | 4 ++-- .../classes/java/text/MessageFormat.java | 4 ++-- .../share/classes/java/util/Locale.java | 4 ++-- .../share/classes/java/util/zip/ZipFile.java | 4 ++-- .../sun/text/RuleBasedBreakIterator.java | 6 +++--- .../spi/JavaTimeDateTimePatternProvider.java | 8 ++++---- .../classes/com/sun/beans/TypeResolver.java | 4 ++-- .../share/classes/java/awt/List.java | 4 ++-- .../share/classes/java/awt/MenuComponent.java | 4 ++-- .../java/awt/font/GlyphJustificationInfo.java | 4 ++-- .../share/classes/java/awt/geom/Arc2D.java | 4 ++-- .../imageio/stream/ImageInputStream.java | 4 ++-- .../attribute/standard/JobStateReason.java | 4 ++-- .../classes/javax/sound/midi/Sequencer.java | 4 ++-- .../javax/swing/text/html/AccessibleHTML.java | 4 ++-- .../classes/java/util/logging/LogRecord.java | 4 ++-- .../classes/javax/management/MXBean.java | 4 ++-- .../javax/security/sasl/SaslServer.java | 4 ++-- .../java/sql/BatchUpdateException.java | 20 +++++++++---------- .../share/classes/java/sql/Connection.java | 12 +++++------ .../classes/java/sql/DatabaseMetaData.java | 6 +++--- .../share/classes/java/sql/Statement.java | 6 +++--- .../javax/xml/stream/XMLStreamReader.java | 4 ++-- .../classes/org/xml/sax/ext/DeclHandler.java | 4 ++-- .../sun/tools/javac/comp/ArgumentAttr.java | 6 +++--- .../classes/com/sun/tools/sjavac/Package.java | 4 ++-- .../com/sun/tools/sjavac/Transformer.java | 4 ++-- .../doclets/toolkit/taglets/ParamTaglet.java | 4 ++-- .../com/sun/jdi/VirtualMachineManager.java | 6 +++--- .../jdk/jfr/internal/SecuritySupport.java | 2 +- .../auth/module/KeyStoreLoginModule.java | 4 ++-- 35 files changed, 88 insertions(+), 88 deletions(-) diff --git a/src/java.base/share/classes/java/io/DataInput.java b/src/java.base/share/classes/java/io/DataInput.java index b8088ff78da..9fdc6bbaf52 100644 --- a/src/java.base/share/classes/java/io/DataInput.java +++ b/src/java.base/share/classes/java/io/DataInput.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2022, 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 @@ -493,7 +493,7 @@ public interface DataInput { * is encountered, it is discarded and reading * ceases. If the character {@code '\r'} * is encountered, it is discarded and, if - * the following byte converts to the + * the following byte converts to the * character {@code '\n'}, then that is * discarded also; reading then ceases. If * end of file is encountered before either diff --git a/src/java.base/share/classes/java/io/ObjectInputStream.java b/src/java.base/share/classes/java/io/ObjectInputStream.java index 8fdc3ac8d51..704960f1107 100644 --- a/src/java.base/share/classes/java/io/ObjectInputStream.java +++ b/src/java.base/share/classes/java/io/ObjectInputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2022, 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 @@ -738,7 +738,7 @@ public class ObjectInputStream * restored a final set of validations can be performed. * * @param obj the object to receive the validation callback. - * @param prio controls the order of callbacks;zero is a good default. + * @param prio controls the order of callbacks; zero is a good default. * Use higher numbers to be called back earlier, lower numbers for * later callbacks. Within a priority, callbacks are processed in * no particular order. diff --git a/src/java.base/share/classes/java/io/PipedInputStream.java b/src/java.base/share/classes/java/io/PipedInputStream.java index c6034e193cf..0d733fa4c74 100644 --- a/src/java.base/share/classes/java/io/PipedInputStream.java +++ b/src/java.base/share/classes/java/io/PipedInputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2022, 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 @@ -222,7 +222,7 @@ public class PipedInputStream extends InputStream { * @param len the maximum number of bytes received * @throws IOException If the pipe is broken, * {@link #connect(java.io.PipedOutputStream) unconnected}, - * closed,or if an I/O error occurs. + * closed, or if an I/O error occurs. */ synchronized void receive(byte[] b, int off, int len) throws IOException { checkStateForReceive(); diff --git a/src/java.base/share/classes/java/lang/Class.java b/src/java.base/share/classes/java/lang/Class.java index 670321ccca9..fb936b14989 100644 --- a/src/java.base/share/classes/java/lang/Class.java +++ b/src/java.base/share/classes/java/lang/Class.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2022, 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 @@ -1582,7 +1582,7 @@ public final class Class implements java.io.Serializable, * representing the class in which it was declared. This method returns * null if this class or interface is not a member of any other class. If * this {@code Class} object represents an array class, a primitive - * type, or void,then this method returns null. + * type, or void, then this method returns null. * * @return the declaring class for this class * @throws SecurityException diff --git a/src/java.base/share/classes/java/math/BigDecimal.java b/src/java.base/share/classes/java/math/BigDecimal.java index b13906ebae9..c491346f9f5 100644 --- a/src/java.base/share/classes/java/math/BigDecimal.java +++ b/src/java.base/share/classes/java/math/BigDecimal.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2022, 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 @@ -1791,7 +1791,7 @@ public class BigDecimal extends Number implements Comparable { * @throws ArithmeticException if the result is inexact but the * rounding mode is {@code UNNECESSARY} or * {@code mc.precision == 0} and the quotient has a - * non-terminating decimal expansion,including dividing by zero + * non-terminating decimal expansion, including dividing by zero * @since 1.5 */ public BigDecimal divide(BigDecimal divisor, MathContext mc) { diff --git a/src/java.base/share/classes/java/text/MessageFormat.java b/src/java.base/share/classes/java/text/MessageFormat.java index e304d072411..98f9d1a144d 100644 --- a/src/java.base/share/classes/java/text/MessageFormat.java +++ b/src/java.base/share/classes/java/text/MessageFormat.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2022, 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 @@ -778,7 +778,7 @@ public class MessageFormat extends Format { * {@code null} or has fewer than argumentIndex+1 elements. * * - * + * * * * * * diff --git a/src/java.base/share/classes/sun/text/spi/JavaTimeDateTimePatternProvider.java b/src/java.base/share/classes/sun/text/spi/JavaTimeDateTimePatternProvider.java index c8fd888e2b2..a3835c6ac82 100644 --- a/src/java.base/share/classes/sun/text/spi/JavaTimeDateTimePatternProvider.java +++ b/src/java.base/share/classes/sun/text/spi/JavaTimeDateTimePatternProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, 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 @@ -46,12 +46,12 @@ public abstract class JavaTimeDateTimePatternProvider extends LocaleServiceProvi * Concrete implementation of this method will retrieve * a java.time specific dateTime Pattern from selected Locale Provider. * - * @param timeStyle an {@code int} value representing FormatStyle constant, -1 + * @param timeStyle an {@code int} value, representing FormatStyle constant, -1 * for date-only pattern - * @param dateStyle an {@code int} value,representing FormatStyle constant, -1 + * @param dateStyle an {@code int} value, representing FormatStyle constant, -1 * for time-only pattern * @param locale {@code locale}, non-null - * @param calType a {@code String},non-null representing CalendarType such as "japanese", + * @param calType a {@code String}, non-null representing CalendarType such as "japanese", * "iso8601" * @return formatting pattern {@code String} * @see java.time.format.DateTimeFormatterBuilder#convertStyle(java.time.format.FormatStyle) diff --git a/src/java.desktop/share/classes/com/sun/beans/TypeResolver.java b/src/java.desktop/share/classes/com/sun/beans/TypeResolver.java index 25f07947310..c8f2d1891dc 100644 --- a/src/java.desktop/share/classes/com/sun/beans/TypeResolver.java +++ b/src/java.desktop/share/classes/com/sun/beans/TypeResolver.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, 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 @@ -104,7 +104,7 @@ public final class TypeResolver { * of those parameters. For example, Map<K,V> is a generic class, and * a corresponding ParameterizedType might look like * Map<K=String,V=Integer>. Given such a ParameterizedType, this method - * will replace K with String, or List<K> with List<String;, or + * will replace K with String, or List<K> with List<String>, or * List<? super K> with List<? super String>.

    * *

    The {@code actual} argument to this method can also be a Class. diff --git a/src/java.desktop/share/classes/java/awt/List.java b/src/java.desktop/share/classes/java/awt/List.java index 3877fcd3b3d..f29374ab6bc 100644 --- a/src/java.desktop/share/classes/java/awt/List.java +++ b/src/java.desktop/share/classes/java/awt/List.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2022, 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 @@ -1750,7 +1750,7 @@ public class List extends Component implements ItemSelectable, Accessible { /** * Get the Font of this object. * - * @return the Font,if supported, for the object; otherwise, null + * @return the Font, if supported, for the object; otherwise, null * @see #setFont */ public Font getFont() { diff --git a/src/java.desktop/share/classes/java/awt/MenuComponent.java b/src/java.desktop/share/classes/java/awt/MenuComponent.java index 0e7ab46cedf..2550eea7f52 100644 --- a/src/java.desktop/share/classes/java/awt/MenuComponent.java +++ b/src/java.desktop/share/classes/java/awt/MenuComponent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2022, 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 @@ -742,7 +742,7 @@ public abstract class MenuComponent implements java.io.Serializable { /** * Gets the {@code Font} of this object. * - * @return the {@code Font},if supported, for the object; + * @return the {@code Font}, if supported, for the object; * otherwise, {@code null} */ public Font getFont() { diff --git a/src/java.desktop/share/classes/java/awt/font/GlyphJustificationInfo.java b/src/java.desktop/share/classes/java/awt/font/GlyphJustificationInfo.java index c4a8a7452b6..f9cc5d547f3 100644 --- a/src/java.desktop/share/classes/java/awt/font/GlyphJustificationInfo.java +++ b/src/java.desktop/share/classes/java/awt/font/GlyphJustificationInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 1999, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -193,7 +193,7 @@ public final class GlyphJustificationInfo { public final int shrinkPriority; /** - * If {@code true},this glyph absorbs all remaining shrinkage at + * If {@code true}, this glyph absorbs all remaining shrinkage at * this and lower priority levels as it shrinks. */ public final boolean shrinkAbsorb; diff --git a/src/java.desktop/share/classes/java/awt/geom/Arc2D.java b/src/java.desktop/share/classes/java/awt/geom/Arc2D.java index 849cc470379..16a891b2cc4 100644 --- a/src/java.desktop/share/classes/java/awt/geom/Arc2D.java +++ b/src/java.desktop/share/classes/java/awt/geom/Arc2D.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -777,7 +777,7 @@ public abstract class Arc2D extends RectangularShape { * elliptical boundary of the arc. * * @return A {@code Point2D} object representing the - * x,y coordinates of the ending point of the arc. + * x,y coordinates of the ending point of the arc. * @since 1.2 */ public Point2D getEndPoint() { diff --git a/src/java.desktop/share/classes/javax/imageio/stream/ImageInputStream.java b/src/java.desktop/share/classes/javax/imageio/stream/ImageInputStream.java index 6c05a7183c9..d8999d4a884 100644 --- a/src/java.desktop/share/classes/javax/imageio/stream/ImageInputStream.java +++ b/src/java.desktop/share/classes/javax/imageio/stream/ImageInputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2022, 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 @@ -393,7 +393,7 @@ public interface ImageInputStream extends DataInput, Closeable { * zero-extension. If the character {@code '\n'} is * encountered, it is discarded and reading ceases. If the * character {@code '\r'} is encountered, it is discarded - * and, if the following byte converts to the character + * and, if the following byte converts to the character * {@code '\n'}, then that is discarded also; reading then * ceases. If end of file is encountered before either of the * characters {@code '\n'} and {@code '\r'} is diff --git a/src/java.desktop/share/classes/javax/print/attribute/standard/JobStateReason.java b/src/java.desktop/share/classes/javax/print/attribute/standard/JobStateReason.java index f5ab4103098..2f8526cb7b1 100644 --- a/src/java.desktop/share/classes/javax/print/attribute/standard/JobStateReason.java +++ b/src/java.desktop/share/classes/javax/print/attribute/standard/JobStateReason.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -89,7 +89,7 @@ public class JobStateReason extends EnumSyntax implements Attribute { /** * The printer could not access one or more documents passed by reference * (i.e., the print data representation object is a {@code URL}). This - * reason is intended to cover any file access problem,including file does + * reason is intended to cover any file access problem, including file does * not exist and access denied because of an access control problem. Whether * the printer aborts the job and moves the job to the {@code ABORTED} job * state or prints all documents that are accessible and moves the job to diff --git a/src/java.desktop/share/classes/javax/sound/midi/Sequencer.java b/src/java.desktop/share/classes/javax/sound/midi/Sequencer.java index 4ee2cbcfd5a..f51cb373427 100644 --- a/src/java.desktop/share/classes/javax/sound/midi/Sequencer.java +++ b/src/java.desktop/share/classes/javax/sound/midi/Sequencer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2022, 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 @@ -472,7 +472,7 @@ public interface Sequencer extends MidiDevice { /** * Registers a meta-event listener to receive notification whenever a * meta-event is encountered in the sequence and processed by the sequencer. - * This method can fail if, for instance,this class of sequencer does not + * This method can fail if, for instance, this class of sequencer does not * support meta-event notification. * * @param listener listener to add diff --git a/src/java.desktop/share/classes/javax/swing/text/html/AccessibleHTML.java b/src/java.desktop/share/classes/javax/swing/text/html/AccessibleHTML.java index ba8465d4570..12cd5a74a72 100644 --- a/src/java.desktop/share/classes/javax/swing/text/html/AccessibleHTML.java +++ b/src/java.desktop/share/classes/javax/swing/text/html/AccessibleHTML.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2022, 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 @@ -464,7 +464,7 @@ class AccessibleHTML implements Accessible { /** * Gets the Font of this object. * - * @return the Font,if supported, for the object; otherwise, null + * @return the Font, if supported, for the object; otherwise, null * @see #setFont */ public Font getFont() { diff --git a/src/java.logging/share/classes/java/util/logging/LogRecord.java b/src/java.logging/share/classes/java/util/logging/LogRecord.java index 5549789664a..6d680d7f606 100644 --- a/src/java.logging/share/classes/java/util/logging/LogRecord.java +++ b/src/java.logging/share/classes/java/util/logging/LogRecord.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2022, 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 @@ -179,7 +179,7 @@ public class LogRecord implements java.io.Serializable { /** * Synthesizes a pseudo unique integer value from a long {@code id} value. - * For backward compatibility with previous releases,the returned integer is + * For backward compatibility with previous releases, the returned integer is * such that for any positive long less than or equals to {@code Integer.MAX_VALUE}, * the returned integer is equal to the original value. * Otherwise - it is synthesized with a best effort hashing algorithm, diff --git a/src/java.management/share/classes/javax/management/MXBean.java b/src/java.management/share/classes/javax/management/MXBean.java index f583ba62eaa..e1d740d39be 100644 --- a/src/java.management/share/classes/javax/management/MXBean.java +++ b/src/java.management/share/classes/javax/management/MXBean.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2022, 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 @@ -929,7 +929,7 @@ public interface ModuleMXBean {

  • Otherwise, if J has at least one public constructor with either {@link javax.management.ConstructorParameters @javax.management.ConstructorParameters} or - {@code @java.beans.ConstructoProperties} annotation, then one of those + {@code @java.beans.ConstructorProperties} annotation, then one of those constructors (not necessarily always the same one) will be called to reconstruct an instance of J. If a constructor is annotated with both diff --git a/src/java.security.sasl/share/classes/javax/security/sasl/SaslServer.java b/src/java.security.sasl/share/classes/javax/security/sasl/SaslServer.java index 697b790deed..1e2d08aa8a1 100644 --- a/src/java.security.sasl/share/classes/javax/security/sasl/SaslServer.java +++ b/src/java.security.sasl/share/classes/javax/security/sasl/SaslServer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -105,7 +105,7 @@ public abstract interface SaslServer { * by sending a challenge to the client, or if the authentication has * succeeded but challenge data needs to be processed by the client. * {@code isComplete()} should be called - * after each call to {@code evaluateResponse()},to determine if any further + * after each call to {@code evaluateResponse()}, to determine if any further * response is needed from the client. * * @param response The non-null (but possibly empty) response sent diff --git a/src/java.sql/share/classes/java/sql/BatchUpdateException.java b/src/java.sql/share/classes/java/sql/BatchUpdateException.java index c94f0788e11..3e480102952 100644 --- a/src/java.sql/share/classes/java/sql/BatchUpdateException.java +++ b/src/java.sql/share/classes/java/sql/BatchUpdateException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -55,7 +55,7 @@ import java.util.Arrays; *

    * A JDBC driver implementation should use * the constructor {@code BatchUpdateException(String reason, String SQLState, - * int vendorCode, long []updateCounts,Throwable cause) } instead of + * int vendorCode, long []updateCounts, Throwable cause) } instead of * constructors that take {@code int[]} for the update counts to avoid the * possibility of overflow. *

    @@ -78,7 +78,7 @@ public class BatchUpdateException extends SQLException { * Note: There is no validation of {@code updateCounts} for * overflow and because of this it is recommended that you use the constructor * {@code BatchUpdateException(String reason, String SQLState, - * int vendorCode, long []updateCounts,Throwable cause) }. + * int vendorCode, long []updateCounts, Throwable cause) }. *

    * @param reason a description of the error * @param SQLState an XOPEN or SQL:2003 code identifying the exception @@ -115,7 +115,7 @@ public class BatchUpdateException extends SQLException { * Note: There is no validation of {@code updateCounts} for * overflow and because of this it is recommended that you use the constructor * {@code BatchUpdateException(String reason, String SQLState, - * int vendorCode, long []updateCounts,Throwable cause) }. + * int vendorCode, long []updateCounts, Throwable cause) }. *

    * @param reason a description of the exception * @param SQLState an XOPEN or SQL:2003 code identifying the exception @@ -148,7 +148,7 @@ public class BatchUpdateException extends SQLException { * Note: There is no validation of {@code updateCounts} for * overflow and because of this it is recommended that you use the constructor * {@code BatchUpdateException(String reason, String SQLState, - * int vendorCode, long []updateCounts,Throwable cause) }. + * int vendorCode, long []updateCounts, Throwable cause) }. *

    * @param reason a description of the exception * @param updateCounts an array of {@code int}, with each element @@ -178,7 +178,7 @@ public class BatchUpdateException extends SQLException { * Note: There is no validation of {@code updateCounts} for * overflow and because of this it is recommended that you use the constructor * {@code BatchUpdateException(String reason, String SQLState, - * int vendorCode, long []updateCounts,Throwable cause) }. + * int vendorCode, long []updateCounts, Throwable cause) }. *

    * @param updateCounts an array of {@code int}, with each element * indicating the update count, {@code Statement.SUCCESS_NO_INFO} or @@ -244,7 +244,7 @@ public class BatchUpdateException extends SQLException { * Note: There is no validation of {@code updateCounts} for * overflow and because of this it is recommended that you use the constructor * {@code BatchUpdateException(String reason, String SQLState, - * int vendorCode, long []updateCounts,Throwable cause) }. + * int vendorCode, long []updateCounts, Throwable cause) }. *

    * @param updateCounts an array of {@code int}, with each element * indicating the update count, {@code Statement.SUCCESS_NO_INFO} or @@ -274,7 +274,7 @@ public class BatchUpdateException extends SQLException { * Note: There is no validation of {@code updateCounts} for * overflow and because of this it is recommended that you use the constructor * {@code BatchUpdateException(String reason, String SQLState, - * int vendorCode, long []updateCounts,Throwable cause) }. + * int vendorCode, long []updateCounts, Throwable cause) }. *

    * @param reason a description of the exception * @param updateCounts an array of {@code int}, with each element @@ -315,7 +315,7 @@ public class BatchUpdateException extends SQLException { * Note: There is no validation of {@code updateCounts} for * overflow and because of this it is recommended that you use the constructor * {@code BatchUpdateException(String reason, String SQLState, - * int vendorCode, long []updateCounts,Throwable cause) }. + * int vendorCode, long []updateCounts, Throwable cause) }. *

    * @param cause the underlying reason for this {@code SQLException} * (which is saved for later retrieval by the {@code getCause()} method); @@ -351,7 +351,7 @@ public class BatchUpdateException extends SQLException { * Note: There is no validation of {@code updateCounts} for * overflow and because of this it is recommended that you use the constructor * {@code BatchUpdateException(String reason, String SQLState, - * int vendorCode, long []updateCounts,Throwable cause) }. + * int vendorCode, long []updateCounts, Throwable cause) }. *

    * @param cause the underlying reason for this {@code SQLException} (which is saved for later retrieval by the {@code getCause()} method); * may be null indicating diff --git a/src/java.sql/share/classes/java/sql/Connection.java b/src/java.sql/share/classes/java/sql/Connection.java index 0221696ee8f..0a5429d302f 100644 --- a/src/java.sql/share/classes/java/sql/Connection.java +++ b/src/java.sql/share/classes/java/sql/Connection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2022, 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 @@ -634,7 +634,7 @@ public interface Connection extends Wrapper, AutoCloseable { * custom mapping of SQL structured types and distinct types. *

    * You must set the values for the {@code TypeMap} prior to - * callng {@code setMap} as a JDBC driver may create an internal copy + * calling {@code setMap} as a JDBC driver may create an internal copy * of the {@code TypeMap}: * *

    @@ -1594,7 +1594,7 @@ throws SQLException;
         /**
          * Sets and validates the sharding keys for this connection. A {@code null}
          * value may be specified for the sharding Key. The validity
    -     * of a {@code null} sharding key is vendor-specific. Consult your vendor's
    +     * of a {@code null} sharding key is vendor-specific. Consult your vendor's
          * documentation for additional information.
          * @implSpec
          * The default implementation will throw a
    @@ -1616,7 +1616,7 @@ throws SQLException;
          * and set on this connection; false if the sharding keys are not valid or
          * the timeout period expires before the operation completes.
          * @throws SQLException if an error occurs while performing this validation;
    -     * a {@code superSharedingKey} is specified
    +     * a {@code superShardingKey} is specified
          * without a {@code shardingKey};
          * this method is called on a closed {@code connection}; or
          * the {@code timeout} value is negative.
    @@ -1634,7 +1634,7 @@ throws SQLException;
         /**
          * Sets and validates the sharding key for this connection. A {@code null}
          * value may be specified for the sharding Key. The validity
    -     * of a {@code null} sharding key is vendor-specific. Consult your vendor's
    +     * of a {@code null} sharding key is vendor-specific. Consult your vendor's
          * documentation for additional information.
          * @implSpec
          * The default implementation will throw a
    @@ -1680,7 +1680,7 @@ throws SQLException;
          * The super sharding key may be {@code null}
          * @throws SQLException if an error  occurs setting the sharding keys;
          * this method is called on a closed {@code connection}; or
    -     * a {@code superSharedingKey} is specified without a {@code shardingKey}
    +     * a {@code superShardingKey} is specified without a {@code shardingKey}
          * @throws SQLFeatureNotSupportedException if the driver does not support sharding
          * @since 9
          * @see ShardingKey
    diff --git a/src/java.sql/share/classes/java/sql/DatabaseMetaData.java b/src/java.sql/share/classes/java/sql/DatabaseMetaData.java
    index 532c37ee4bb..6f63c2989b8 100644
    --- a/src/java.sql/share/classes/java/sql/DatabaseMetaData.java
    +++ b/src/java.sql/share/classes/java/sql/DatabaseMetaData.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 1996, 2022, 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
    @@ -1513,7 +1513,7 @@ public interface DatabaseMetaData extends Wrapper {
          * @param tableNamePattern a table name pattern; must match the
          *        table name as it is stored in the database
          * @param types a list of table types, which must be from the list of table types
    -     *         returned from {@link #getTableTypes},to include; {@code null} returns
    +     *         returned from {@link #getTableTypes}, to include; {@code null} returns
          * all types
          * @return {@code ResultSet} - each row is a table description
          * @throws SQLException if a database access error occurs
    @@ -3044,7 +3044,7 @@ public interface DatabaseMetaData extends Wrapper {
          *  
  • SCOPE_TABLE String {@code =>} table name that is the scope of a * reference attribute ({@code null} if the DATA_TYPE isn't REF) *
  • SOURCE_DATA_TYPE short {@code =>} source type of a distinct type or user-generated - * Ref type,SQL type from java.sql.Types ({@code null} if DATA_TYPE + * Ref type, SQL type from java.sql.Types ({@code null} if DATA_TYPE * isn't DISTINCT or user-generated REF) * * @param catalog a catalog name; must match the catalog name as it diff --git a/src/java.sql/share/classes/java/sql/Statement.java b/src/java.sql/share/classes/java/sql/Statement.java index 10c8d9e12c6..bb5a5cfd64d 100644 --- a/src/java.sql/share/classes/java/sql/Statement.java +++ b/src/java.sql/share/classes/java/sql/Statement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2022, 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 @@ -779,7 +779,7 @@ public interface Statement extends Wrapper, AutoCloseable { * * @throws SQLException if a database access error occurs, * this method is called on a closed {@code Statement}, the SQL - * statement returns a {@code ResultSet} object,the second argument + * statement returns a {@code ResultSet} object, the second argument * supplied to this method is not an * {@code int} array whose elements are valid column indexes, the method is called on a * {@code PreparedStatement} or {@code CallableStatement} @@ -960,7 +960,7 @@ public interface Statement extends Wrapper, AutoCloseable { * object; {@code false} if it is an update count or there * are no more results * @throws SQLException if a database access error occurs, - * this method is called on a closed {@code Statement},the + * this method is called on a closed {@code Statement}, the * elements of the {@code String} array passed to this * method are not valid column names, the method is called on a * {@code PreparedStatement} or {@code CallableStatement} diff --git a/src/java.xml/share/classes/javax/xml/stream/XMLStreamReader.java b/src/java.xml/share/classes/javax/xml/stream/XMLStreamReader.java index c2a230fe285..a40b4c9142b 100644 --- a/src/java.xml/share/classes/javax/xml/stream/XMLStreamReader.java +++ b/src/java.xml/share/classes/javax/xml/stream/XMLStreamReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -85,7 +85,7 @@ import javax.xml.namespace.QName; *
  • * diff --git a/src/java.xml/share/classes/org/xml/sax/ext/DeclHandler.java b/src/java.xml/share/classes/org/xml/sax/ext/DeclHandler.java index 7d5944656f2..f0ce5b63ae2 100644 --- a/src/java.xml/share/classes/org/xml/sax/ext/DeclHandler.java +++ b/src/java.xml/share/classes/org/xml/sax/ext/DeclHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2022, 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 @@ -67,7 +67,7 @@ public interface DeclHandler * string "ANY", or a parenthesised group, optionally followed * by an occurrence indicator. The model will be normalized so * that all parameter entities are fully resolved and all whitespace - * is removed,and will include the enclosing parentheses. Other + * is removed, and will include the enclosing parentheses. Other * normalization (such as removing redundant parentheses or * simplifying occurrence indicators) is at the discretion of the * parser.

    diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ArgumentAttr.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ArgumentAttr.java index fe0f1432305..99d0cae240e 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ArgumentAttr.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ArgumentAttr.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, 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 @@ public class ArgumentAttr extends JCTree.Visitor { /** * Checks a type in the speculative tree against a given result; the type can be either a plain - * type or an argument type,in which case a more complex check is required. + * type or an argument type, in which case a more complex check is required. */ Type checkSpeculative(JCTree expr, ResultInfo resultInfo) { return checkSpeculative(expr, expr.type, resultInfo); @@ -151,7 +151,7 @@ public class ArgumentAttr extends JCTree.Visitor { /** * Checks a type in the speculative tree against a given result; the type can be either a plain - * type or an argument type,in which case a more complex check is required. + * type or an argument type, in which case a more complex check is required. */ Type checkSpeculative(DiagnosticPosition pos, Type t, ResultInfo resultInfo) { if (t.hasTag(DEFERRED)) { diff --git a/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Package.java b/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Package.java index 8a9f1cbb301..f10d1b4fa69 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Package.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Package.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,7 +44,7 @@ import com.sun.tools.sjavac.pubapi.PubApi; /** * The Package class maintains meta information about a package. - * For example its sources, dependents,its pubapi and its artifacts. + * For example its sources, dependents, its pubapi and its artifacts. * * It might look odd that we track dependents/pubapi/artifacts on * a package level, but it makes sense since recompiling a full package diff --git a/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Transformer.java b/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Transformer.java index c9e2c62865c..4f2ea5d0c7e 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Transformer.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Transformer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,7 +38,7 @@ import com.sun.tools.sjavac.pubapi.PubApi; * The transform interface is used to transform content inside a package, from one form to another. * Usually the output form is an unpredictable number of output files. (eg class files) * but can also be an unpredictable number of generated source files (eg idl2java) - * or a single predictable output file (eg when copying,cleaning or compiling a properties file). + * or a single predictable output file (eg when copying, cleaning or compiling a properties file). * *

    This is NOT part of any supported API. * If you write code that depends on this, you do so at your own risk. diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/ParamTaglet.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/ParamTaglet.java index b41260743ee..2552eb137a7 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/ParamTaglet.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/ParamTaglet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2022, 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 @@ -152,7 +152,7 @@ public class ParamTaglet extends BaseTaglet implements InheritableTaglet { } /** - * Given an array of {@code @param DocTree}s,return its string representation. + * Given an array of {@code @param DocTree}s, return its string representation. * Try to inherit the param tags that are missing. * * @param holder the element that holds the param tags. diff --git a/src/jdk.jdi/share/classes/com/sun/jdi/VirtualMachineManager.java b/src/jdk.jdi/share/classes/com/sun/jdi/VirtualMachineManager.java index 8b5957dc0d9..eee09ded39b 100644 --- a/src/jdk.jdi/share/classes/com/sun/jdi/VirtualMachineManager.java +++ b/src/jdk.jdi/share/classes/com/sun/jdi/VirtualMachineManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2022, 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 @@ -97,7 +97,7 @@ import com.sun.jdi.event.VMStartEvent; * {@code -agentlib:jdwp=transport=xxx,server=y} * *

  • - * Target VM generates and outputs the tranport-specific address at which it will + * Target VM generates and outputs the transport-specific address at which it will * listen for a connection.
  • *
  • * Debugger is launched. Debugger selects a connector in the list @@ -158,7 +158,7 @@ import com.sun.jdi.event.VMStartEvent; *
  • *
  • * Later, an uncaught exception is thrown in the target VM. The target - * VM generates the tranport-specific address at which it will + * VM generates the transport-specific address at which it will * listen for a connection. *
  • Target VM launches the debugger with the following items concatenated * together (separated by spaces) to form the command line: diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/SecuritySupport.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/SecuritySupport.java index a3d6f24cd1a..ee30821dcf8 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/SecuritySupport.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/SecuritySupport.java @@ -149,7 +149,7 @@ public final class SecuritySupport { } /** - * Path created by the default file provider,and not + * Path created by the default file provider, and not * a malicious provider. * */ diff --git a/src/jdk.security.auth/share/classes/com/sun/security/auth/module/KeyStoreLoginModule.java b/src/jdk.security.auth/share/classes/com/sun/security/auth/module/KeyStoreLoginModule.java index 44692bdd219..a3994474050 100644 --- a/src/jdk.security.auth/share/classes/com/sun/security/auth/module/KeyStoreLoginModule.java +++ b/src/jdk.security.auth/share/classes/com/sun/security/auth/module/KeyStoreLoginModule.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2022, 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 @@ -712,7 +712,7 @@ public class KeyStoreLoginModule implements LoginModule { * {@code login} method), then this method associates a * {@code X500Principal} for the subject distinguished name of the * first certificate in the alias's credentials in the subject's - * principals,the alias's certificate path in the subject's public + * principals, the alias's certificate path in the subject's public * credentials, and a {@code X500PrivateCredential} whose certificate * is the first certificate in the alias's certificate path and whose * private key is the alias's private key in the subject's private -- GitLab From cf283e2a33a053407eac65ea35baa61a3a23c8d5 Mon Sep 17 00:00:00 2001 From: Christian Hagedorn Date: Fri, 14 Jan 2022 16:17:01 +0000 Subject: [PATCH 120/564] 8279570: IGV: Add source/destination property for load and store nodes with an associated field Reviewed-by: kvn, thartmann --- src/hotspot/share/opto/idealGraphPrinter.cpp | 91 +++++++++++++++++++- src/hotspot/share/opto/idealGraphPrinter.hpp | 4 + 2 files changed, 94 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/opto/idealGraphPrinter.cpp b/src/hotspot/share/opto/idealGraphPrinter.cpp index d80f6eec3f3..1aeea01c9c0 100644 --- a/src/hotspot/share/opto/idealGraphPrinter.cpp +++ b/src/hotspot/share/opto/idealGraphPrinter.cpp @@ -482,6 +482,8 @@ void IdealGraphPrinter::visit_node(Node *n, bool edges, VectorSet* temp_set) { print_prop("idealOpcode", (const char *)NodeClassNames[node->as_Mach()->ideal_Opcode()]); } + print_field(node); + buffer[0] = 0; stringStream s2(buffer, sizeof(buffer) - 1); @@ -630,9 +632,96 @@ void IdealGraphPrinter::visit_node(Node *n, bool edges, VectorSet* temp_set) { } } -void IdealGraphPrinter::walk_nodes(Node *start, bool edges, VectorSet* temp_set) { +void IdealGraphPrinter::print_field(const Node* node) { + buffer[0] = 0; + stringStream ss(buffer, sizeof(buffer) - 1); + ciField* field = get_field(node); + uint depth = 0; + if (field == NULL) { + depth++; + field = find_source_field_of_array_access(node, depth); + } + + if (field != NULL) { + // Either direct field access or array access + field->print_name_on(&ss); + for (uint i = 0; i < depth; i++) { + // For arrays: Add [] for each dimension + ss.print("[]"); + } + if (node->is_Store()) { + print_prop("destination", buffer); + } else { + print_prop("source", buffer); + } + } +} + +ciField* IdealGraphPrinter::get_field(const Node* node) { + const TypePtr* adr_type = node->adr_type(); + Compile::AliasType* atp = NULL; + if (C->have_alias_type(adr_type)) { + atp = C->alias_type(adr_type); + } + if (atp != NULL) { + ciField* field = atp->field(); + if (field != NULL) { + // Found field associated with 'node'. + return field; + } + } + return NULL; +} + +// Try to find the field that is associated with a memory node belonging to an array access. +ciField* IdealGraphPrinter::find_source_field_of_array_access(const Node* node, uint& depth) { + if (!node->is_Mem()) { + // Not an array access + return NULL; + } + + do { + if (node->adr_type() != NULL && node->adr_type()->isa_aryptr()) { + // Only process array accesses. Pattern match to find actual field source access. + node = get_load_node(node); + if (node != NULL) { + ciField* field = get_field(node); + if (field != NULL) { + return field; + } + // Could be a multi-dimensional array. Repeat loop. + depth++; + continue; + } + } + // Not an array access with a field source. + break; + } while (depth < 256); // Cannot have more than 255 dimensions + return NULL; +} + +// Pattern match on the inputs of 'node' to find load node for the field access. +Node* IdealGraphPrinter::get_load_node(const Node* node) { + Node* load = NULL; + Node* addr = node->as_Mem()->in(MemNode::Address); + if (addr != NULL && addr->is_AddP()) { + Node* base = addr->as_AddP()->base_node(); + if (base != NULL) { + base = base->uncast(); + if (base->is_Load()) { + // Mem(AddP([ConstraintCast*](LoadP))) for non-compressed oops. + load = base; + } else if (base->is_DecodeN() && base->in(1)->is_Load()) { + // Mem(AddP([ConstraintCast*](DecodeN(LoadN)))) for compressed oops. + load = base->in(1); + } + } + } + return load; +} +void IdealGraphPrinter::walk_nodes(Node* start, bool edges, VectorSet* temp_set) { VectorSet visited; GrowableArray nodeStack(Thread::current()->resource_area(), 0, 0, NULL); nodeStack.push(start); diff --git a/src/hotspot/share/opto/idealGraphPrinter.hpp b/src/hotspot/share/opto/idealGraphPrinter.hpp index c3c33e5b5c9..6f845d5b048 100644 --- a/src/hotspot/share/opto/idealGraphPrinter.hpp +++ b/src/hotspot/share/opto/idealGraphPrinter.hpp @@ -99,6 +99,10 @@ class IdealGraphPrinter : public CHeapObj { void print_method(ciMethod *method, int bci, InlineTree *tree); void print_inline_tree(InlineTree *tree); void visit_node(Node *n, bool edges, VectorSet* temp_set); + void print_field(const Node* node); + ciField* get_field(const Node* node); + ciField* find_source_field_of_array_access(const Node* node, uint& depth); + static Node* get_load_node(const Node* node); void walk_nodes(Node *start, bool edges, VectorSet* temp_set); void begin_elem(const char *s); void end_elem(); -- GitLab From d9dd485b95e1796822c0dcfaed8a28328b0a976a Mon Sep 17 00:00:00 2001 From: Thomas Stuefe Date: Fri, 14 Jan 2022 16:17:48 +0000 Subject: [PATCH 121/564] 8280019: Remove unused code from metaspace Reviewed-by: coleenp, hseigel --- src/hotspot/share/memory/metaspace/blockTree.cpp | 5 ++--- src/hotspot/share/memory/metaspace/chunkManager.cpp | 5 ++--- src/hotspot/share/memory/metaspace/chunkManager.hpp | 13 ++----------- src/hotspot/share/memory/metaspace/commitMask.hpp | 5 ++--- src/hotspot/share/memory/metaspace/counters.hpp | 6 ++---- .../share/memory/metaspace/freeChunkList.cpp | 5 ++--- .../share/memory/metaspace/rootChunkArea.cpp | 9 ++------- 7 files changed, 14 insertions(+), 34 deletions(-) diff --git a/src/hotspot/share/memory/metaspace/blockTree.cpp b/src/hotspot/share/memory/metaspace/blockTree.cpp index ed296453403..056bc6e52d5 100644 --- a/src/hotspot/share/memory/metaspace/blockTree.cpp +++ b/src/hotspot/share/memory/metaspace/blockTree.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2020 SAP SE. All rights reserved. + * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022 SAP SE. 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,6 @@ void BlockTree::verify() const { // Traverse the tree and test that all nodes are in the correct order. MemRangeCounter counter; - int longest_edge = 0; if (_root != NULL) { ResourceMark rm; diff --git a/src/hotspot/share/memory/metaspace/chunkManager.cpp b/src/hotspot/share/memory/metaspace/chunkManager.cpp index b2c4c5bd452..6c80ee8898b 100644 --- a/src/hotspot/share/memory/metaspace/chunkManager.cpp +++ b/src/hotspot/share/memory/metaspace/chunkManager.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2018, 2021 SAP SE. All rights reserved. + * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2022 SAP SE. 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 @@ -88,7 +88,6 @@ void ChunkManager::split_chunk_and_add_splinters(Metachunk* c, chunklevel_t targ DEBUG_ONLY(size_t committed_words_before = c->committed_words();) - const chunklevel_t orig_level = c->level(); c->vsnode()->split(target_level, c, &_chunks); // Splitting should never fail. diff --git a/src/hotspot/share/memory/metaspace/chunkManager.hpp b/src/hotspot/share/memory/metaspace/chunkManager.hpp index 93fe40c818a..979db86b206 100644 --- a/src/hotspot/share/memory/metaspace/chunkManager.hpp +++ b/src/hotspot/share/memory/metaspace/chunkManager.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2018, 2020 SAP SE. All rights reserved. + * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2022 SAP SE. 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 @@ -95,12 +95,6 @@ class ChunkManager : public CHeapObj { // chunks. void split_chunk_and_add_splinters(Metachunk* c, chunklevel_t target_level); - // See get_chunk(s,s,s) - Metachunk* get_chunk_locked(size_t preferred_word_size, size_t min_word_size, size_t min_committed_words); - - // Uncommit all chunks equal or below the given level. - void uncommit_free_chunks(chunklevel_t max_level); - // Return a single chunk to the freelist without doing any merging, and adjust accounting. void return_chunk_simple_locked(Metachunk* c); @@ -161,9 +155,6 @@ public: DEBUG_ONLY(void verify() const;) DEBUG_ONLY(void verify_locked() const;) - // Returns the name of this chunk manager. - const char* name() const { return _name; } - // Returns total number of chunks int total_num_chunks() const { return _chunks.num_chunks(); } diff --git a/src/hotspot/share/memory/metaspace/commitMask.hpp b/src/hotspot/share/memory/metaspace/commitMask.hpp index d1edc0282dd..15f7ab3244c 100644 --- a/src/hotspot/share/memory/metaspace/commitMask.hpp +++ b/src/hotspot/share/memory/metaspace/commitMask.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2020 SAP SE. All rights reserved. + * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022 SAP SE. 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 @@ -94,7 +94,6 @@ public: const MetaWord* base() const { return _base; } size_t word_size() const { return _word_size; } - const MetaWord* end() const { return _base + word_size(); } // Given an address, returns true if the address is committed, false if not. bool is_committed_address(const MetaWord* p) const { diff --git a/src/hotspot/share/memory/metaspace/counters.hpp b/src/hotspot/share/memory/metaspace/counters.hpp index 066d36279a6..163b33edca7 100644 --- a/src/hotspot/share/memory/metaspace/counters.hpp +++ b/src/hotspot/share/memory/metaspace/counters.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2020 SAP SE. All rights reserved. + * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022 SAP SE. 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 @@ -70,8 +70,6 @@ public: _c -= v; } - void reset() { _c = 0; } - #ifdef ASSERT void check(T expected) const { assert(_c == expected, "Counter mismatch: %d, expected: %d.", diff --git a/src/hotspot/share/memory/metaspace/freeChunkList.cpp b/src/hotspot/share/memory/metaspace/freeChunkList.cpp index 7c06c003e3a..62c67d595c8 100644 --- a/src/hotspot/share/memory/metaspace/freeChunkList.cpp +++ b/src/hotspot/share/memory/metaspace/freeChunkList.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2020 SAP SE. All rights reserved. + * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022 SAP SE. 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 @@ -70,7 +70,6 @@ void FreeChunkList::verify() const { } else { assert(_last != NULL, "Sanity"); int num = 0; - bool uncommitted = (_first->committed_words() == 0); for (Metachunk* c = _first; c != NULL; c = c->next()) { assert(c->is_free(), "Chunks in freelist should be free"); assert(c->used_words() == 0, "Chunk in freelist should have not used words."); diff --git a/src/hotspot/share/memory/metaspace/rootChunkArea.cpp b/src/hotspot/share/memory/metaspace/rootChunkArea.cpp index 0df97ef87ff..4c74fe3149a 100644 --- a/src/hotspot/share/memory/metaspace/rootChunkArea.cpp +++ b/src/hotspot/share/memory/metaspace/rootChunkArea.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2020, 2021 SAP SE. All rights reserved. + * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022 SAP SE. 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,8 +103,6 @@ void RootChunkArea::split(chunklevel_t target_level, Metachunk* c, FreeChunkList DEBUG_ONLY(chunklevel::check_valid_level(target_level)); assert(target_level > c->level(), "Wrong target level"); - const chunklevel_t starting_level = c->level(); - while (c->level() < target_level) { log_trace(metaspace)("Splitting chunk: " METACHUNK_FULL_FORMAT ".", METACHUNK_FULL_FORMAT_ARGS(c)); @@ -199,8 +197,6 @@ Metachunk* RootChunkArea::merge(Metachunk* c, FreeChunkListVector* freelists) { log_trace(metaspace)("Attempting to merge chunk " METACHUNK_FORMAT ".", METACHUNK_FORMAT_ARGS(c)); - const chunklevel_t starting_level = c->level(); - bool stop = false; Metachunk* result = NULL; @@ -389,7 +385,6 @@ void RootChunkArea::verify() const { const Metachunk* c = _first_chunk; const MetaWord* expected_next_base = _base; - const MetaWord* const area_end = _base + word_size(); while (c != NULL) { assrt_(c->is_free() || c->is_in_use(), -- GitLab From fb8fdc0fbf17dd7e900cb688df4917b97b26b9ab Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Fri, 14 Jan 2022 17:47:35 +0000 Subject: [PATCH 122/564] 8279990: (fs) Awkward verbiage in description of Files.createTempFile(Path,String,String,FileAttribute) Reviewed-by: lancea --- src/java.base/share/classes/java/nio/file/Files.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/java.base/share/classes/java/nio/file/Files.java b/src/java.base/share/classes/java/nio/file/Files.java index 9c1f92614fa..b0184395af0 100644 --- a/src/java.base/share/classes/java/nio/file/Files.java +++ b/src/java.base/share/classes/java/nio/file/Files.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2022, 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 @@ -823,12 +823,11 @@ public final class Files { * names in the same manner as the {@link * java.io.File#createTempFile(String,String,File)} method. * - *

    As with the {@code File.createTempFile} methods, this method is only - * part of a temporary-file facility. Where used as a work files, - * the resulting file may be opened using the {@link + *

    The file may be opened using the {@link * StandardOpenOption#DELETE_ON_CLOSE DELETE_ON_CLOSE} option so that the - * file is deleted when the appropriate {@code close} method is invoked. - * Alternatively, a {@link Runtime#addShutdownHook shutdown-hook}, or the + * file is deleted when the appropriate {@code close} method is invoked + * either explicitly or via a try-with-resources statement. Alternatively, + * a {@link Runtime#addShutdownHook shutdown-hook}, or the * {@link java.io.File#deleteOnExit} mechanism may be used to delete the * file automatically. * -- GitLab From 09d61b6187425ba528c568fb637087817ffb10c0 Mon Sep 17 00:00:00 2001 From: "Daniel D. Daugherty" Date: Fri, 14 Jan 2022 17:49:54 +0000 Subject: [PATCH 123/564] 8280034: ProblemList jdk/jfr/api/consumer/recordingstream/TestOnEvent.java on linux-x64 Reviewed-by: ccheung --- test/jdk/ProblemList.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index dec007c4896..2949b1bf109 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -829,6 +829,7 @@ jdk/jfr/event/os/TestThreadContextSwitches.java 8247776 windows- jdk/jfr/startupargs/TestStartName.java 8214685 windows-x64 jdk/jfr/startupargs/TestStartDuration.java 8214685 windows-x64 jdk/jfr/event/oldobject/TestLargeRootSet.java 8276333 macosx-x64,windows-x64 +jdk/jfr/api/consumer/recordingstream/TestOnEvent.java 8255404 linux-x64 ############################################################################ -- GitLab From c359c358c8ebaf7b1dddbc4b499a7aae65ba6736 Mon Sep 17 00:00:00 2001 From: Thomas Stuefe Date: Fri, 14 Jan 2022 19:40:10 +0000 Subject: [PATCH 124/564] 8280002: jmap -histo may leak stream Reviewed-by: shade, sspitsyn --- src/hotspot/share/services/attachListener.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/services/attachListener.cpp b/src/hotspot/share/services/attachListener.cpp index 957b34112d5..f916f43849f 100644 --- a/src/hotspot/share/services/attachListener.cpp +++ b/src/hotspot/share/services/attachListener.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2022, 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 @@ -292,6 +292,7 @@ static jint heap_inspection(AttachOperation* op, outputStream* out) { uintx num; if (!Arguments::parse_uintx(num_str, &num, 0)) { out->print_cr("Invalid parallel thread number: [%s]", num_str); + delete fs; return JNI_ERR; } parallel_thread_num = num == 0 ? parallel_thread_num : (uint)num; -- GitLab From 0d1a97f793309919bd6d67085630049eaafcced1 Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Fri, 14 Jan 2022 20:44:22 +0000 Subject: [PATCH 125/564] 8279064: New options for ktab to provide non-default salt Reviewed-by: valeriep --- .../security/krb5/internal/ktab/KeyTab.java | 27 ++++++- .../security/krb5/internal/tools/Ktab.java | 40 +++++++--- test/jdk/sun/security/krb5/auto/Context.java | 17 +++- .../security/krb5/auto/tools/KtabSalt.java | 78 +++++++++++++++++++ .../sun/security/krb5/tools/KtabCheck.java | 18 ++--- 5 files changed, 157 insertions(+), 23 deletions(-) create mode 100644 test/jdk/sun/security/krb5/auto/tools/KtabSalt.java diff --git a/src/java.security.jgss/share/classes/sun/security/krb5/internal/ktab/KeyTab.java b/src/java.security.jgss/share/classes/sun/security/krb5/internal/ktab/KeyTab.java index a2d2c683b97..e7d3ebdfda6 100644 --- a/src/java.security.jgss/share/classes/sun/security/krb5/internal/ktab/KeyTab.java +++ b/src/java.security.jgss/share/classes/sun/security/krb5/internal/ktab/KeyTab.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2022, 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 @@ -376,12 +376,33 @@ public class KeyTab implements KeyTabConstants { addEntry(service, service.getSalt(), psswd, kvno, append); } - // Called by KDC test + /** + * Adds a new entry in the key table. + * @param service the service which will have a new entry in the key table. + * @param salt specified non default salt, cannot be null + * @param psswd the password which generates the key. + * @param kvno the kvno to use, -1 means automatic increasing + * @param append false if entries with old kvno would be removed. + * Note: if kvno is not -1, entries with the same kvno are always removed + */ public void addEntry(PrincipalName service, String salt, char[] psswd, int kvno, boolean append) throws KrbException { EncryptionKey[] encKeys = EncryptionKey.acquireSecretKeys( - psswd, salt); + psswd, salt); + addEntry(service, encKeys, kvno, append); + } + + /** + * Adds a new entry in the key table. + * @param service the service which will have a new entry in the key table. + * @param encKeys the keys to be added + * @param kvno the kvno to use, -1 means automatic increasing + * @param append false if entries with old kvno would be removed. + * Note: if kvno is not -1, entries with the same kvno are always removed + */ + public void addEntry(PrincipalName service, EncryptionKey[] encKeys, + int kvno, boolean append) throws KrbException { // There should be only one maximum KVNO value for all etypes, so that // all added keys can have the same KVNO. diff --git a/src/java.security.jgss/windows/classes/sun/security/krb5/internal/tools/Ktab.java b/src/java.security.jgss/windows/classes/sun/security/krb5/internal/tools/Ktab.java index d09e4665b08..108cd4c24bb 100644 --- a/src/java.security.jgss/windows/classes/sun/security/krb5/internal/tools/Ktab.java +++ b/src/java.security.jgss/windows/classes/sun/security/krb5/internal/tools/Ktab.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,7 +35,6 @@ import sun.security.krb5.internal.ktab.*; import java.io.IOException; import java.io.BufferedReader; import java.io.InputStreamReader; -import java.io.File; import java.text.DateFormat; import java.util.Arrays; import java.util.Date; @@ -61,10 +60,12 @@ public class Ktab { int etype = -1; char[] password = null; - boolean forced = false; // true if delete without prompt. Default false + boolean fopt = false; // true if delete without prompt or + // add by contacting KDC. Default false boolean append = false; // true if new keys are appended. Default false int vDel = -1; // kvno to delete, -1 all, -2 old. Default -1 int vAdd = -1; // kvno to add. Default -1, means auto incremented + String salt = null; // salt to use. Default null, means default salt /** * The main program that can be invoked at command line. @@ -186,6 +187,12 @@ public class Ktab { error(args[i] + " is not valid after -" + action); } break; + case "-s": // salt for -a + if (++i >= args.length || args[i].startsWith("-")) { + error("A salt string must be specified after -s"); + } + salt = args[i]; + break; case "-n": // kvno for -a if (++i >= args.length || args[i].startsWith("-")) { error("A KVNO must be specified after -n"); @@ -213,8 +220,8 @@ public class Ktab { case "-t": // list timestamps showTime = true; break; - case "-f": // force delete, no prompt - forced = true; + case "-f": // force delete or get salt from KDC + fopt = true; break; case "-append": // -a, new keys append to file append = true; @@ -258,6 +265,10 @@ public class Ktab { * a new key table. */ void addEntry() { + if (salt != null && fopt) { + System.err.println("-s and -f cannot coexist when adding a keytab entry."); + System.exit(-1); + } PrincipalName pname = null; try { pname = new PrincipalName(principal); @@ -283,7 +294,15 @@ public class Ktab { } try { // admin.addEntry(pname, password); - table.addEntry(pname, password, vAdd, append); + if (fopt) { + KrbAsReqBuilder builder = new KrbAsReqBuilder(pname, password); + builder.action(); + table.addEntry(pname, builder.getKeys(true), vAdd, append); + } else if (salt != null) { + table.addEntry(pname, salt, password, vAdd, append); + } else { + table.addEntry(pname, password, vAdd, append); + } Arrays.fill(password, '0'); // clear password // admin.save(); table.save(); @@ -367,7 +386,7 @@ public class Ktab { PrincipalName pname = null; try { pname = new PrincipalName(principal); - if (!forced) { + if (!fopt) { String answer; BufferedReader cis = new BufferedReader(new InputStreamReader(System.in)); @@ -424,6 +443,7 @@ public class Ktab { printHelp(); System.exit(-1); } + /** * Prints out the help information. */ @@ -434,11 +454,13 @@ public class Ktab { System.out.println(); System.out.println("-l [-e] [-t]\n" + " list the keytab name and entries. -e with etype, -t with timestamp."); - System.out.println("-a [] [-n ] [-append]\n" + System.out.println("-a [] [-n ] [-f | -s ] [-append]\n" + " add new key entries to the keytab for the given principal name with\n" + " optional . If a is specified, new keys' Key Version\n" + " Numbers equal to the value, otherwise, automatically incrementing\n" - + " the Key Version Numbers. If -append is specified, new keys are\n" + + " the Key Version Numbers. If is specified, it will be used\n" + + " instead of the default salt. If -f is specified, the KDC will be\n" + + " contacted to fetch the salt. If -append is specified, new keys are\n" + " appended to the keytab, otherwise, old keys for the\n" + " same principal are removed."); System.out.println("-d [-f] [-e ] [ | all | old]\n" diff --git a/test/jdk/sun/security/krb5/auto/Context.java b/test/jdk/sun/security/krb5/auto/Context.java index ed8bab0e3d6..c18dbe9690f 100644 --- a/test/jdk/sun/security/krb5/auto/Context.java +++ b/test/jdk/sun/security/krb5/auto/Context.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2022, 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 @@ -207,13 +207,26 @@ public class Context { */ public static Context fromUserKtab(Subject s, String user, String ktab, boolean storeKey) throws Exception { + return fromUserKtab(s, user, ktab, false, storeKey); + } + + /** + * Logins with username/keytab as a client. + */ + public static Context fromUserKtabAsClient( + String user, String ktab, boolean storeKey) throws Exception { + return fromUserKtab(new Subject(), user, ktab, true, storeKey); + } + + private static Context fromUserKtab(Subject s, + String user, String ktab, boolean isInitiator, boolean storeKey) throws Exception { Context out = new Context(); out.name = user; out.s = s; Krb5LoginModule krb5 = new Krb5LoginModule(); Map map = new HashMap<>(); - map.put("isInitiator", "false"); + map.put("isInitiator", Boolean.toString(isInitiator)); map.put("doNotPrompt", "true"); map.put("useTicketCache", "false"); map.put("useKeyTab", "true"); diff --git a/test/jdk/sun/security/krb5/auto/tools/KtabSalt.java b/test/jdk/sun/security/krb5/auto/tools/KtabSalt.java new file mode 100644 index 00000000000..af504d5eab7 --- /dev/null +++ b/test/jdk/sun/security/krb5/auto/tools/KtabSalt.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2022, 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 8279064 + * @summary New options for ktab to provide non-default salt + * @requires os.family == "windows" + * @library /test/lib + * @library /sun/security/krb5/auto + * @compile -XDignore.symbol.file KtabSalt.java + * @run main jdk.test.lib.FileInstaller ../TestHosts TestHosts + * @run main/othervm -Djdk.net.hosts.file=TestHosts KtabSalt + */ + +import jdk.test.lib.SecurityTools; +import jdk.test.lib.Utils; +import jdk.test.lib.process.OutputAnalyzer; + +import javax.security.auth.login.LoginException; + +public class KtabSalt { + + public static void main(String[] args) throws Exception { + + OneKDC kdc = new OneKDC(null).writeJAASConf(); + kdc.addPrincipal("u1", "password".toCharArray(), + "this_is_my_salt", null); + + // Using password works + Context.fromUserPass("u1", "password".toCharArray(), true); + + // Using KDC's keytab works + kdc.writeKtab("ktab0"); + Context.fromUserKtabAsClient("u1", "ktab0", true); + + // Self-created keytab with default salt does not work + ktab("-a u1 password -k ktab1"); + Utils.runAndCheckException( + () -> Context.fromUserKtabAsClient("u1", "ktab1", true), + LoginException.class); + + // Self-creating keytab with specified salt works + ktab("-a u1 password -s this_is_my_salt -k ktab2"); + Context.fromUserKtabAsClient("u1", "ktab2", true); + + // Self-creating keytab with salt from KDC works + ktab("-a u1 password -f -k ktab3"); + Context.fromUserKtabAsClient("u1", "ktab3", true); + } + + static OutputAnalyzer ktab(String cmdLine) throws Exception { + String fullCmdLine = String.format( + "-J-Djava.security.krb5.conf=%s -J-Djdk.net.hosts.file=TestHosts %s", + OneKDC.KRB5_CONF, cmdLine); + return SecurityTools.ktab(fullCmdLine).shouldHaveExitValue(0); + } +} diff --git a/test/jdk/sun/security/krb5/tools/KtabCheck.java b/test/jdk/sun/security/krb5/tools/KtabCheck.java index 8924b70ec93..3b9c42ebff1 100644 --- a/test/jdk/sun/security/krb5/tools/KtabCheck.java +++ b/test/jdk/sun/security/krb5/tools/KtabCheck.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2022, 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 @@ -69,31 +69,31 @@ public class KtabCheck { check(3,17,3,18,3,19,4,17,4,18,4,19,5,17,5,18,5,19); ktab("-a me mine -n 6 -append"); check(3,17,3,18,3,19,4,17,4,18,4,19,5,17,5,18,5,19,6,17,6,18,6,19); - ktab("-d me 3"); + ktab("-d me -f 3"); check(4,17,4,18,4,19,5,17,5,18,5,19,6,17,6,18,6,19); - ktab("-d me -e 17 6"); + ktab("-d me -f -e 17 6"); check(4,17,4,18,4,19,5,17,5,18,5,19,6,18,6,19); - ktab("-d me -e 19 6"); + ktab("-d me -f -e 19 6"); check(4,17,4,18,4,19,5,17,5,18,5,19,6,18); - ktab("-d me -e 17 5"); + ktab("-d me -f -e 17 5"); check(4,17,4,18,4,19,5,18,5,19,6,18); - ktab("-d me old"); + ktab("-d me -f old"); check(4,17,5,19,6,18); try { - ktab("-d me old"); + ktab("-d me -f old"); throw new Exception("Should fail"); } catch (Exception e) { // no-op } check(4,17,5,19,6,18); - ktab("-d me"); + ktab("-d me -f"); check(); } static void ktab(String s) throws Exception { File conf = new File(System.getProperty("test.src"), "onlythree.conf"); SecurityTools.ktab("-J-Djava.security.krb5.conf=" + conf - + " -k " + KEYTAB + " -f " + s).shouldHaveExitValue(0); + + " -k " + KEYTAB + " " + s).shouldHaveExitValue(0); } /** -- GitLab From eab4e6d6701f2e217374c073c2578f029fa58393 Mon Sep 17 00:00:00 2001 From: "Daniel D. Daugherty" Date: Fri, 14 Jan 2022 22:24:39 +0000 Subject: [PATCH 126/564] 8280045: ProblemList 2 AppCDS tests until JDK-8279970 is fixed Reviewed-by: ccheung --- 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 b05f3317527..938bd46172a 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -103,6 +103,8 @@ runtime/os/TestTracePageSizes.java#G1 8267460 linux-aarch64 runtime/os/TestTracePageSizes.java#Parallel 8267460 linux-aarch64 runtime/os/TestTracePageSizes.java#Serial 8267460 linux-aarch64 runtime/ErrorHandling/CreateCoredumpOnCrash.java 8267433 macosx-x64 +runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchive.java 8279970 generic-all +runtime/cds/appcds/loaderConstraints/DynamicLoaderConstraintsTest.java#custom-cl-zgc 8279970 generic-all applications/jcstress/copy.java 8229852 linux-all -- GitLab From 9b0f68955770d017d727a423e46140033317f273 Mon Sep 17 00:00:00 2001 From: Jie Fu Date: Fri, 14 Jan 2022 23:13:05 +0000 Subject: [PATCH 127/564] 8279947: Remove two redundant gvn.transform calls in Parse::do_one_bytecode() Reviewed-by: kvn --- src/hotspot/share/opto/parse2.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/hotspot/share/opto/parse2.cpp b/src/hotspot/share/opto/parse2.cpp index ee9c67fa944..e461d3ee978 100644 --- a/src/hotspot/share/opto/parse2.cpp +++ b/src/hotspot/share/opto/parse2.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2022, 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 @@ -2295,8 +2295,7 @@ void Parse::do_one_bytecode() { // out to memory to round, the machine instruction that implements // ConvL2D is responsible for rounding. // c = precision_rounding(b); - c = _gvn.transform(b); - push(c); + push(b); } else { l2f(); } @@ -2307,8 +2306,7 @@ void Parse::do_one_bytecode() { b = _gvn.transform( new ConvL2DNode(a)); // For x86_32.ad, rounding is always necessary (see _l2f above). // c = dprecision_rounding(b); - c = _gvn.transform(b); - push_pair(c); + push_pair(b); break; case Bytecodes::_f2l: -- GitLab From 22b7295e75d3bc7ba2c2cd7b871bb2bb5bf290eb Mon Sep 17 00:00:00 2001 From: Masanori Yano Date: Sat, 15 Jan 2022 02:17:46 +0000 Subject: [PATCH 128/564] 7001973: java/awt/Graphics2D/CopyAreaOOB.java fails Reviewed-by: serb --- test/jdk/ProblemList.txt | 1 - test/jdk/java/awt/Graphics2D/CopyAreaOOB.java | 66 ++++++------------- 2 files changed, 21 insertions(+), 46 deletions(-) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 33e66e317a3..b9c0b857480 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -242,7 +242,6 @@ sun/awt/shell/ShellFolderMemoryLeak.java 8197794 windows-all sun/java2d/DirectX/OnScreenRenderingResizeTest/OnScreenRenderingResizeTest.java 8022403 generic-all sun/java2d/DirectX/OverriddenInsetsTest/OverriddenInsetsTest.java 8196102 generic-all sun/java2d/DirectX/RenderingToCachedGraphicsTest/RenderingToCachedGraphicsTest.java 8196180 windows-all,macosx-all -java/awt/Graphics2D/CopyAreaOOB.java 7001973 windows-all,macosx-all sun/java2d/SunGraphics2D/EmptyClipRenderingTest.java 8144029 macosx-all,linux-all sun/java2d/SunGraphics2D/DrawImageBilinear.java 8191406 generic-all sun/java2d/SunGraphics2D/PolyVertTest.java 6986565 generic-all diff --git a/test/jdk/java/awt/Graphics2D/CopyAreaOOB.java b/test/jdk/java/awt/Graphics2D/CopyAreaOOB.java index d4f9533f096..0ebda98042a 100644 --- a/test/jdk/java/awt/Graphics2D/CopyAreaOOB.java +++ b/test/jdk/java/awt/Graphics2D/CopyAreaOOB.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2021 Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,15 +36,9 @@ import java.awt.image.*; public class CopyAreaOOB extends Canvas { - private static boolean done; + private static Robot robot = null; public void paint(Graphics g) { - synchronized (this) { - if (done) { - return; - } - } - int w = getWidth(); int h = getHeight(); @@ -64,10 +58,23 @@ public class CopyAreaOOB extends Canvas { Toolkit.getDefaultToolkit().sync(); - synchronized (this) { - done = true; - notifyAll(); + BufferedImage capture = null; + try { + Thread.sleep(500); + if (robot == null) robot = new Robot(); + Point pt1 = getLocationOnScreen(); + Rectangle rect = new Rectangle(pt1.x, pt1.y, 400, 400); + capture = robot.createScreenCapture(rect); + } catch (Exception e) { + throw new RuntimeException("Problems handling Robot"); } + // Test pixels + testRegion(capture, "green", 0, 0, 400, 10, 0xff00ff00); + testRegion(capture, "original red", 0, 10, 50, 400, 0xffff0000); + testRegion(capture, "background", 50, 10, 60, 400, 0xff000000); + testRegion(capture, "in-between", 60, 10, 110, 20, 0xff000000); + testRegion(capture, "copied red", 60, 20, 110, 400, 0xffff0000); + testRegion(capture, "background", 110, 10, 400, 400, 0xff000000); } public Dimension getPreferredSize() { @@ -105,42 +112,11 @@ public class CopyAreaOOB extends Canvas { frame.setLocationRelativeTo(null); frame.setVisible(true); - // Wait until the component's been painted - synchronized (test) { - while (!done) { - try { - test.wait(); - } catch (InterruptedException e) { - throw new RuntimeException("Failed: Interrupted"); - } - } - } - try { - Thread.sleep(2000); + Thread.sleep(3000); } catch (InterruptedException ex) {} - - // Grab the screen region - BufferedImage capture = null; - try { - Robot robot = new Robot(); - Point pt1 = test.getLocationOnScreen(); - Rectangle rect = new Rectangle(pt1.x, pt1.y, 400, 400); - capture = robot.createScreenCapture(rect); - } catch (Exception e) { - throw new RuntimeException("Problems creating Robot"); - } finally { - if (!show) { - frame.dispose(); - } + if (!show) { + frame.dispose(); } - - // Test pixels - testRegion(capture, "green", 0, 0, 400, 10, 0xff00ff00); - testRegion(capture, "original red", 0, 10, 50, 400, 0xffff0000); - testRegion(capture, "background", 50, 10, 60, 400, 0xff000000); - testRegion(capture, "in-between", 60, 10, 110, 20, 0xff000000); - testRegion(capture, "copied red", 60, 20, 110, 400, 0xffff0000); - testRegion(capture, "background", 110, 10, 400, 400, 0xff000000); } } -- GitLab From 9a18190a4f8e31801d1442d97f247f074a3fd5c0 Mon Sep 17 00:00:00 2001 From: Mikael Vidstedt Date: Sat, 15 Jan 2022 03:20:34 +0000 Subject: [PATCH 129/564] 8280048: Missing comma in copyright header Reviewed-by: prr --- test/jdk/java/awt/Graphics2D/CopyAreaOOB.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/jdk/java/awt/Graphics2D/CopyAreaOOB.java b/test/jdk/java/awt/Graphics2D/CopyAreaOOB.java index 0ebda98042a..8d218d9f189 100644 --- a/test/jdk/java/awt/Graphics2D/CopyAreaOOB.java +++ b/test/jdk/java/awt/Graphics2D/CopyAreaOOB.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2021 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2021, 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 -- GitLab From fef8f2d30004ea75c663752ae6c61b214fb8abc8 Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Sat, 15 Jan 2022 07:01:55 +0000 Subject: [PATCH 130/564] 8279797: JFR: Show .jfc options in JFR.start help Reviewed-by: mgronlun --- .../jdk/jfr/internal/dcmd/DCmdStart.java | 31 +++++++++++++++++-- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStart.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStart.java index 32b7f670b6f..5d7f70c2a34 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStart.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStart.java @@ -42,10 +42,14 @@ import java.util.Set; import jdk.jfr.FlightRecorder; import jdk.jfr.Recording; import jdk.jfr.internal.JVM; +import jdk.jfr.internal.LogLevel; +import jdk.jfr.internal.LogTag; +import jdk.jfr.internal.Logger; import jdk.jfr.internal.OldObjectSample; import jdk.jfr.internal.PlatformRecording; import jdk.jfr.internal.PrivateAccess; import jdk.jfr.internal.SecuritySupport.SafePath; +import jdk.jfr.internal.SecuritySupport; import jdk.jfr.internal.Type; import jdk.jfr.internal.jfc.JFC; import jdk.jfr.internal.jfc.model.JFCModel; @@ -364,7 +368,7 @@ final class DCmdStart extends AbstractDCmd { Turn on this flag only when you have an application that you suspect has a memory leak. If the settings parameter is set to 'profile', then the information collected includes the stack - trace from where the potential leaking object wasallocated. + trace from where the potential leaking object was allocated. (BOOLEAN, false) settings (Optional) Name of the settings file that identifies which events @@ -394,7 +398,7 @@ final class DCmdStart extends AbstractDCmd { take precedence. The whitespace character can be omitted for timespan values, i.e. 20s. For more information about the settings syntax, see Javadoc of the jdk.jfr package. - + %s Options must be specified using the or = syntax. Example usage: @@ -414,7 +418,28 @@ final class DCmdStart extends AbstractDCmd { Note, if the default event settings are modified, overhead may exceed 1%%. - """.formatted(exampleDirectory()).lines().toArray(String[]::new); + """.formatted(jfcOptions(), exampleDirectory()).lines().toArray(String[]::new); + } + + private static String jfcOptions() { + try { + StringBuilder sb = new StringBuilder(); + for (SafePath s : SecuritySupport.getPredefinedJFCFiles()) { + String name = JFC.nameFromPath(s.toPath()); + JFCModel model = JFCModel.create(s, l -> {}); + sb.append('\n'); + sb.append("Options for ").append(name).append(":\n"); + sb.append('\n'); + for (XmlInput input : model.getInputs()) { + sb.append(" ").append(input.getOptionSyntax()).append('\n'); + sb.append('\n'); + } + } + return sb.toString(); + } catch (IOException | ParseException e) { + Logger.log(LogTag.JFR_DCMD, LogLevel.DEBUG, "Could not list .jfc options for JFR.start. " + e.getMessage()); + return ""; + } } @Override -- GitLab From c6196662b8a15276916badd333291057980a6552 Mon Sep 17 00:00:00 2001 From: Fei Gao Date: Mon, 17 Jan 2022 02:16:45 +0000 Subject: [PATCH 131/564] 8276673: Optimize abs operations in C2 compiler Reviewed-by: thartmann, jiefu --- src/hotspot/share/opto/subnode.cpp | 60 ++++- src/hotspot/share/opto/subnode.hpp | 5 +- src/hotspot/share/opto/type.hpp | 6 +- .../jtreg/compiler/c2/irTests/TestIRAbs.java | 231 ++++++++++++++++++ .../compiler/lib/ir_framework/IRNode.java | 6 + 5 files changed, 303 insertions(+), 5 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/c2/irTests/TestIRAbs.java diff --git a/src/hotspot/share/opto/subnode.cpp b/src/hotspot/share/opto/subnode.cpp index d7bcf7629d6..67b60f74c60 100644 --- a/src/hotspot/share/opto/subnode.cpp +++ b/src/hotspot/share/opto/subnode.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -1847,6 +1847,64 @@ bool BoolNode::is_counted_loop_exit_test() { return false; } +//============================================================================= +//------------------------------Value------------------------------------------ +const Type* AbsNode::Value(PhaseGVN* phase) const { + const Type* t1 = phase->type(in(1)); + if (t1 == Type::TOP) return Type::TOP; + + switch (t1->base()) { + case Type::Int: { + const TypeInt* ti = t1->is_int(); + if (ti->is_con()) { + return TypeInt::make(uabs(ti->get_con())); + } + break; + } + case Type::Long: { + const TypeLong* tl = t1->is_long(); + if (tl->is_con()) { + return TypeLong::make(uabs(tl->get_con())); + } + break; + } + case Type::FloatCon: + return TypeF::make(abs(t1->getf())); + case Type::DoubleCon: + return TypeD::make(abs(t1->getd())); + default: + break; + } + + return bottom_type(); +} + +//------------------------------Identity---------------------------------------- +Node* AbsNode::Identity(PhaseGVN* phase) { + Node* in1 = in(1); + // No need to do abs for non-negative values + if (phase->type(in1)->higher_equal(TypeInt::POS) || + phase->type(in1)->higher_equal(TypeLong::POS)) { + return in1; + } + // Convert "abs(abs(x))" into "abs(x)" + if (in1->Opcode() == Opcode()) { + return in1; + } + return this; +} + +//------------------------------Ideal------------------------------------------ +Node* AbsNode::Ideal(PhaseGVN* phase, bool can_reshape) { + Node* in1 = in(1); + // Convert "abs(0-x)" into "abs(x)" + if (in1->is_Sub() && phase->type(in1->in(1))->is_zero_type()) { + set_req_X(1, in1->in(2), phase); + return this; + } + return NULL; +} + //============================================================================= //------------------------------Value------------------------------------------ // Compute sqrt diff --git a/src/hotspot/share/opto/subnode.hpp b/src/hotspot/share/opto/subnode.hpp index 398b219e646..55b0e90a387 100644 --- a/src/hotspot/share/opto/subnode.hpp +++ b/src/hotspot/share/opto/subnode.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -347,6 +347,9 @@ public: class AbsNode : public Node { public: AbsNode( Node *value ) : Node(0,value) {} + virtual Node* Identity(PhaseGVN* phase); + virtual Node* Ideal(PhaseGVN* phase, bool can_reshape); + virtual const Type* Value(PhaseGVN* phase) const; }; //------------------------------AbsINode--------------------------------------- diff --git a/src/hotspot/share/opto/type.hpp b/src/hotspot/share/opto/type.hpp index f525a75b14e..0007ed0c5e0 100644 --- a/src/hotspot/share/opto/type.hpp +++ b/src/hotspot/share/opto/type.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -593,7 +593,7 @@ public: // Check for single integer bool is_con() const { return _lo==_hi; } - bool is_con(int i) const { return is_con() && _lo == i; } + bool is_con(jint i) const { return is_con() && _lo == i; } jint get_con() const { assert(is_con(), "" ); return _lo; } virtual bool is_finite() const; // Has a finite value @@ -661,7 +661,7 @@ public: // Check for single integer bool is_con() const { return _lo==_hi; } - bool is_con(int i) const { return is_con() && _lo == i; } + bool is_con(jlong i) const { return is_con() && _lo == i; } jlong get_con() const { assert(is_con(), "" ); return _lo; } // Check for positive 32-bit value. diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestIRAbs.java b/test/hotspot/jtreg/compiler/c2/irTests/TestIRAbs.java new file mode 100644 index 00000000000..fc8362b1e1f --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/irTests/TestIRAbs.java @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package compiler.c2.irTests; + +import jdk.test.lib.Asserts; +import compiler.lib.ir_framework.*; + +/* + * @test + * @bug 8276673 + * @summary Test abs nodes optimization in C2. + * @library /test/lib / + * @run driver compiler.c2.irTests.TestIRAbs + */ + +public class TestIRAbs { + + public static char [] cspecial = { + 0, 42, 128, 256, 1024, 4096, 65535 + }; + + public static int [] ispecial = { + 0, Integer.MAX_VALUE, Integer.MIN_VALUE, -42, 42, -1, 1 + }; + + public static long [] lspecial = { + 0, Long.MAX_VALUE, Long.MIN_VALUE, -42, 42, -1, 1 + }; + + public static float [] fspecial = { + 0.0f, + -0.0f, + Float.MAX_VALUE, + Float.MIN_VALUE, + -Float.MAX_VALUE, + -Float.MIN_VALUE, + Float.NaN, + Float.POSITIVE_INFINITY, + Float.NEGATIVE_INFINITY, + Integer.MAX_VALUE, + Integer.MIN_VALUE, + Long.MAX_VALUE, + Long.MIN_VALUE, + -1.0f, + 1.0f, + -42.0f, + 42.0f + }; + + public static double [] dspecial = { + 0.0, + -0.0, + Double.MAX_VALUE, + Double.MIN_VALUE, + -Double.MAX_VALUE, + -Double.MIN_VALUE, + Double.NaN, + Double.POSITIVE_INFINITY, + Double.NEGATIVE_INFINITY, + Integer.MAX_VALUE, + Integer.MIN_VALUE, + Long.MIN_VALUE, + Long.MAX_VALUE, + -1, + 1, + 42, + -42, + Math.PI, + Math.E, + Float.MAX_VALUE, + Float.MIN_VALUE, + -Float.MAX_VALUE, + -Float.MIN_VALUE, + Float.NaN, + Float.POSITIVE_INFINITY, + Float.NEGATIVE_INFINITY + }; + + public static void main(String[] args) { + TestFramework.run(); + } + + @Test + @IR(failOn = {IRNode.ABS_I, IRNode.ABS_L, IRNode.ABS_F, IRNode.ABS_D}) + public void testAbsConstant() { + // Test abs(constant) optimization for int + Asserts.assertEquals(Integer.MAX_VALUE, Math.abs(Integer.MAX_VALUE)); + Asserts.assertEquals(Integer.MIN_VALUE, Math.abs(Integer.MIN_VALUE)); + Asserts.assertEquals(Integer.MAX_VALUE, Math.abs(-Integer.MAX_VALUE)); + + // Test abs(constant) optimization for long + Asserts.assertEquals(Long.MAX_VALUE, Math.abs(Long.MAX_VALUE)); + Asserts.assertEquals(Long.MIN_VALUE, Math.abs(Long.MIN_VALUE)); + Asserts.assertEquals(Long.MAX_VALUE, Math.abs(-Long.MAX_VALUE)); + + // Test abs(constant) optimization for float + Asserts.assertTrue(Float.isNaN(Math.abs(Float.NaN))); + Asserts.assertEquals(Float.POSITIVE_INFINITY, Math.abs(Float.NEGATIVE_INFINITY)); + Asserts.assertEquals(Float.POSITIVE_INFINITY, Math.abs(Float.POSITIVE_INFINITY)); + Asserts.assertEquals(0.0f, Math.abs(0.0f)); + Asserts.assertEquals(0.0f, Math.abs(-0.0f)); + Asserts.assertEquals(Float.MAX_VALUE, Math.abs(Float.MAX_VALUE)); + Asserts.assertEquals(Float.MIN_VALUE, Math.abs(Float.MIN_VALUE)); + Asserts.assertEquals(Float.MAX_VALUE, Math.abs(-Float.MAX_VALUE)); + Asserts.assertEquals(Float.MIN_VALUE, Math.abs(-Float.MIN_VALUE)); + + // Test abs(constant) optimization for double + Asserts.assertTrue(Double.isNaN(Math.abs(Double.NaN))); + Asserts.assertEquals(Double.POSITIVE_INFINITY, Math.abs(Double.NEGATIVE_INFINITY)); + Asserts.assertEquals(Double.POSITIVE_INFINITY, Math.abs(Double.POSITIVE_INFINITY)); + Asserts.assertEquals(0.0, Math.abs(0.0)); + Asserts.assertEquals(0.0, Math.abs(-0.0)); + Asserts.assertEquals(Double.MAX_VALUE, Math.abs(Double.MAX_VALUE)); + Asserts.assertEquals(Double.MIN_VALUE, Math.abs(Double.MIN_VALUE)); + Asserts.assertEquals(Double.MAX_VALUE, Math.abs(-Double.MAX_VALUE)); + Asserts.assertEquals(Double.MIN_VALUE, Math.abs(-Double.MIN_VALUE)); + } + + @Test + @IR(counts = {IRNode.ABS_I, "1"}) + public int testInt0(int x) { + return Math.abs(Math.abs(x)); // transformed to Math.abs(x) + } + + @Test + @IR(failOn = {IRNode.SUB_I}) + @IR(counts = {IRNode.ABS_I, "1"}) + public int testInt1(int x) { + return Math.abs(0 - x); // transformed to Math.abs(x) + } + + @Run(test = {"testInt0", "testInt1"}) + public void checkTestInt(RunInfo info) { + for (int i = 0; i < ispecial.length; i++) { + Asserts.assertEquals(Math.abs(ispecial[i]), testInt0(ispecial[i])); + Asserts.assertEquals(Math.abs(ispecial[i]), testInt1(ispecial[i])); + } + } + + @Test + @IR(counts = {IRNode.ABS_L, "1"}) + public long testLong0(long x) { + return Math.abs(Math.abs(x)); // transformed to Math.abs(x) + } + + @Test + @IR(failOn = {IRNode.SUB_L}) + @IR(counts = {IRNode.ABS_L, "1"}) + public long testLong1(long x) { + return Math.abs(0 - x); // transformed to Math.abs(x) + } + + @Run(test = {"testLong0", "testLong1"}) + public void checkTestLong(RunInfo info) { + for (int i = 0; i < lspecial.length; i++) { + Asserts.assertEquals(Math.abs(lspecial[i]), testLong0(lspecial[i])); + Asserts.assertEquals(Math.abs(lspecial[i]), testLong1(lspecial[i])); + } + } + + @Test + @IR(counts = {IRNode.ABS_F, "1"}) + public float testFloat0(float x) { + return Math.abs(Math.abs(x)); // transformed to Math.abs(x) + } + + @Test + @IR(failOn = {IRNode.SUB_F}) + @IR(counts = {IRNode.ABS_F, "1"}) + public float testFloat1(float x) { + return Math.abs(0 - x); // transformed to Math.abs(x) + } + + @Run(test = {"testFloat0", "testFloat1"}) + public void checkTestFloat(RunInfo info) { + for (int i = 0; i < fspecial.length; i++) { + Asserts.assertEquals(Math.abs(fspecial[i]), testFloat0(fspecial[i])); + Asserts.assertEquals(Math.abs(fspecial[i]), testFloat1(fspecial[i])); + } + } + + @Test + @IR(counts = {IRNode.ABS_D, "1"}) + public double testDouble0(double x) { + return Math.abs(Math.abs(x)); // transformed to Math.abs(x) + } + + @Test + @IR(failOn = {IRNode.SUB_D}) + @IR(counts = {IRNode.ABS_D, "1"}) + public double testDouble1(double x) { + return Math.abs(0 - x); // transformed to Math.abs(x) + } + + @Run(test = {"testDouble0", "testDouble1"}) + public void checkTestDouble(RunInfo info) { + for (int i = 0; i < dspecial.length; i++) { + Asserts.assertEquals(Math.abs(dspecial[i]), testDouble0(dspecial[i])); + Asserts.assertEquals(Math.abs(dspecial[i]), testDouble1(dspecial[i])); + } + } + + @Test + @IR(failOn = {IRNode.ABS_I}) + public void testChar() { + for (int i = 0; i < cspecial.length; i++) { + Asserts.assertEquals(cspecial[i], (char) Math.abs(cspecial[i])); + } + } + } diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java index 46428c2a05f..315dfa350b7 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java @@ -136,6 +136,10 @@ public class IRNode { public static final String SCOPE_OBJECT = "(.*# ScObj.*" + END; public static final String MEMBAR = START + "MemBar" + MID + END; + public static final String ABS_I = START + "AbsI" + MID + END; + public static final String ABS_L = START + "AbsL" + MID + END; + public static final String ABS_F = START + "AbsF" + MID + END; + public static final String ABS_D = START + "AbsD" + MID + END; public static final String AND_I = START + "AndI" + MID + END; public static final String AND_L = START + "AndL" + MID + END; public static final String LSHIFT_I = START + "LShiftI" + MID + END; @@ -145,6 +149,8 @@ public class IRNode { public static final String ADD_VD = START + "AddVD" + MID + END; public static final String SUB_I = START + "SubI" + MID + END; public static final String SUB_L = START + "SubL" + MID + END; + public static final String SUB_F = START + "SubF" + MID + END; + public static final String SUB_D = START + "SubD" + MID + END; public static final String MUL_I = START + "MulI" + MID + END; public static final String MUL_L = START + "MulL" + MID + END; public static final String CONV_I2L = START + "ConvI2L" + MID + END; -- GitLab From 590eb86033d5445018cd0e961e8721a20de4bb0c Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Mon, 17 Jan 2022 08:17:49 +0000 Subject: [PATCH 132/564] 8280016: gc/g1/TestShrinkAuxiliaryData30 test fails on large machines Reviewed-by: tschatzl, ayang --- ...liaryData30.java => TestShrinkAuxiliaryData27.java} | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) rename test/hotspot/jtreg/gc/g1/{TestShrinkAuxiliaryData30.java => TestShrinkAuxiliaryData27.java} (86%) diff --git a/test/hotspot/jtreg/gc/g1/TestShrinkAuxiliaryData30.java b/test/hotspot/jtreg/gc/g1/TestShrinkAuxiliaryData27.java similarity index 86% rename from test/hotspot/jtreg/gc/g1/TestShrinkAuxiliaryData30.java rename to test/hotspot/jtreg/gc/g1/TestShrinkAuxiliaryData27.java index 960fce63afa..7324cad9f3c 100644 --- a/test/hotspot/jtreg/gc/g1/TestShrinkAuxiliaryData30.java +++ b/test/hotspot/jtreg/gc/g1/TestShrinkAuxiliaryData27.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ package gc.g1; /** - * @test TestShrinkAuxiliaryData30 + * @test TestShrinkAuxiliaryData27 * @key randomness * @bug 8038423 8061715 8078405 * @summary Checks that decommitment occurs for JVM with different @@ -36,11 +36,11 @@ package gc.g1; * java.management * @build sun.hotspot.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox - * @run main/timeout=720 gc.g1.TestShrinkAuxiliaryData30 + * @run main/timeout=720 gc.g1.TestShrinkAuxiliaryData27 */ -public class TestShrinkAuxiliaryData30 { +public class TestShrinkAuxiliaryData27 { public static void main(String[] args) throws Exception { - new TestShrinkAuxiliaryData(30).test(); + new TestShrinkAuxiliaryData(27).test(); } } -- GitLab From a30aa52b77931bcea38213cf3d243d18a37dc858 Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Mon, 17 Jan 2022 08:19:08 +0000 Subject: [PATCH 133/564] 8279958: Provide configure hints for Alpine/apk package managers Reviewed-by: erikj --- make/autoconf/help.m4 | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/make/autoconf/help.m4 b/make/autoconf/help.m4 index f36aa2819df..09e82e36c94 100644 --- a/make/autoconf/help.m4 +++ b/make/autoconf/help.m4 @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2022, 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 @@ AC_DEFUN_ONCE([HELP_SETUP_DEPENDENCY_HELP], [ - UTIL_LOOKUP_PROGS(PKGHANDLER, zypper apt-get yum brew port pkgutil pkgadd pacman) + UTIL_LOOKUP_PROGS(PKGHANDLER, zypper apt-get yum brew port pkgutil pkgadd pacman apk) ]) AC_DEFUN([HELP_MSG_MISSING_DEPENDENCY], @@ -58,6 +58,8 @@ AC_DEFUN([HELP_MSG_MISSING_DEPENDENCY], zypper_help $MISSING_DEPENDENCY ;; *pacman) pacman_help $MISSING_DEPENDENCY ;; + *apk) + apk_help $MISSING_DEPENDENCY ;; esac if test "x$PKGHANDLER_COMMAND" != x; then @@ -192,6 +194,27 @@ pkgadd_help() { PKGHANDLER_COMMAND="" } +apk_help() { + case $1 in + devkit) + PKGHANDLER_COMMAND="sudo apk add alpine-sdk linux-headers" ;; + alsa) + PKGHANDLER_COMMAND="sudo apk add alsa-lib-dev" ;; + cups) + PKGHANDLER_COMMAND="sudo apk add cups-dev" ;; + fontconfig) + PKGHANDLER_COMMAND="sudo apk add fontconfig-dev" ;; + freetype) + PKGHANDLER_COMMAND="sudo apk add freetype-dev" ;; + harfbuzz) + PKGHANDLER_COMMAND="sudo apk add harfbuzz-dev" ;; + x11) + PKGHANDLER_COMMAND="sudo apk add libxtst-dev libxt-dev libxrender-dev libxrandr-dev" ;; + ccache) + PKGHANDLER_COMMAND="sudo apk add ccache" ;; + esac +} + # This function will check if we're called from the "configure" wrapper while # printing --help. If so, we will print out additional information that can # only be extracted within the autoconf script, and then exit. This must be -- GitLab From 4d9b3f4ceef4b514ec943e1a5dd1147618376ad8 Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Mon, 17 Jan 2022 08:20:23 +0000 Subject: [PATCH 134/564] 8279998: PPC64 debug builds fail with "untested: RangeCheckStub: predicate_failed_trap_id" Reviewed-by: goetz, mdoerr --- src/hotspot/cpu/ppc/c1_CodeStubs_ppc.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/hotspot/cpu/ppc/c1_CodeStubs_ppc.cpp b/src/hotspot/cpu/ppc/c1_CodeStubs_ppc.cpp index 4f329d2e633..109372bb1a4 100644 --- a/src/hotspot/cpu/ppc/c1_CodeStubs_ppc.cpp +++ b/src/hotspot/cpu/ppc/c1_CodeStubs_ppc.cpp @@ -81,8 +81,6 @@ void RangeCheckStub::emit_code(LIR_Assembler* ce) { if (_info->deoptimize_on_exception()) { address a = Runtime1::entry_for(Runtime1::predicate_failed_trap_id); - // May be used by optimizations like LoopInvariantCodeMotion or RangeCheckEliminator. - DEBUG_ONLY( __ untested("RangeCheckStub: predicate_failed_trap_id"); ) //__ load_const_optimized(R0, a); __ add_const_optimized(R0, R29_TOC, MacroAssembler::offset_to_global_toc(a)); __ mtctr(R0); -- GitLab From 431bd9a66d759fcd014e9bfc15a0e12976802f06 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Mon, 17 Jan 2022 08:56:40 +0000 Subject: [PATCH 135/564] 8280001: Serial: Add documentation to heap memory layout Reviewed-by: mli, sjohanss, tschatzl --- src/hotspot/share/gc/serial/serialHeap.hpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/hotspot/share/gc/serial/serialHeap.hpp b/src/hotspot/share/gc/serial/serialHeap.hpp index 208a997ad5f..0451a9679a4 100644 --- a/src/hotspot/share/gc/serial/serialHeap.hpp +++ b/src/hotspot/share/gc/serial/serialHeap.hpp @@ -35,6 +35,26 @@ class MemoryPool; class OopIterateClosure; class TenuredGeneration; +// SerialHeap is the implementation of CollectedHeap for Serial GC. +// +// The heap is reserved up-front in a single contiguous block, split into two +// parts, the young and old generation. The young generation resides at lower +// addresses, the old generation at higher addresses. The boundary address +// between the generations is fixed. Within a generation, committed memory +// grows towards higher addresses. +// +// +// low high +// +// +-- generation boundary (fixed after startup) +// | +// |<- young gen (reserved MaxNewSize) ->|<- old gen (reserved MaxOldSize) ->| +// +-----------------+--------+--------+--------+---------------+-------------------+ +// | eden | from | to | | old | | +// | | (to) | (from) | | | | +// +-----------------+--------+--------+--------+---------------+-------------------+ +// |<- committed ->| |<- committed ->| +// class SerialHeap : public GenCollectedHeap { private: MemoryPool* _eden_pool; -- GitLab From 71ca85f5a6741a2db55a529192564f94b269fbd9 Mon Sep 17 00:00:00 2001 From: Claes Redestad Date: Mon, 17 Jan 2022 11:01:55 +0000 Subject: [PATCH 136/564] 8278831: Use table lookup for the last two bytes in Integer.getChars Reviewed-by: jlaskey, rriggs --- .../share/classes/java/lang/Integer.java | 10 +++------- .../share/classes/java/lang/Long.java | 10 +++------- .../share/classes/java/lang/StringUTF16.java | 20 ++++++------------- .../org/openjdk/bench/java/lang/Integers.java | 17 +++++++++++++--- 4 files changed, 26 insertions(+), 31 deletions(-) diff --git a/src/java.base/share/classes/java/lang/Integer.java b/src/java.base/share/classes/java/lang/Integer.java index 7d200e7edf5..9ec9d3941f8 100644 --- a/src/java.base/share/classes/java/lang/Integer.java +++ b/src/java.base/share/classes/java/lang/Integer.java @@ -517,13 +517,9 @@ public final class Integer extends Number } // We know there are at most two digits left at this point. - q = i / 10; - r = (q * 10) - i; - buf[--charPos] = (byte)('0' + r); - - // Whatever left is the remaining digit. - if (q < 0) { - buf[--charPos] = (byte)('0' - q); + buf[--charPos] = DigitOnes[-i]; + if (i < -9) { + buf[--charPos] = DigitTens[-i]; } if (negative) { diff --git a/src/java.base/share/classes/java/lang/Long.java b/src/java.base/share/classes/java/lang/Long.java index 630b9e242b8..2a5a230b321 100644 --- a/src/java.base/share/classes/java/lang/Long.java +++ b/src/java.base/share/classes/java/lang/Long.java @@ -565,13 +565,9 @@ public final class Long extends Number } // We know there are at most two digits left at this point. - q2 = i2 / 10; - r = (q2 * 10) - i2; - buf[--charPos] = (byte)('0' + r); - - // Whatever left is the remaining digit. - if (q2 < 0) { - buf[--charPos] = (byte)('0' - q2); + buf[--charPos] = Integer.DigitOnes[-i2]; + if (i2 < -9) { + buf[--charPos] = Integer.DigitTens[-i2]; } if (negative) { diff --git a/src/java.base/share/classes/java/lang/StringUTF16.java b/src/java.base/share/classes/java/lang/StringUTF16.java index 29287aaa22c..b59b21fd180 100644 --- a/src/java.base/share/classes/java/lang/StringUTF16.java +++ b/src/java.base/share/classes/java/lang/StringUTF16.java @@ -1549,13 +1549,9 @@ final class StringUTF16 { } // We know there are at most two digits left at this point. - q = i / 10; - r = (q * 10) - i; - putChar(buf, --charPos, '0' + r); - - // Whatever left is the remaining digit. - if (q < 0) { - putChar(buf, --charPos, '0' - q); + putChar(buf, --charPos, Integer.DigitOnes[-i]); + if (i < -9) { + putChar(buf, --charPos, Integer.DigitTens[-i]); } if (negative) { @@ -1604,13 +1600,9 @@ final class StringUTF16 { } // We know there are at most two digits left at this point. - q2 = i2 / 10; - r = (q2 * 10) - i2; - putChar(buf, --charPos, '0' + r); - - // Whatever left is the remaining digit. - if (q2 < 0) { - putChar(buf, --charPos, '0' - q2); + putChar(buf, --charPos, Integer.DigitOnes[-i2]); + if (i2 < -9) { + putChar(buf, --charPos, Integer.DigitTens[-i2]); } if (negative) { diff --git a/test/micro/org/openjdk/bench/java/lang/Integers.java b/test/micro/org/openjdk/bench/java/lang/Integers.java index c238ae5d735..221dc79ee4c 100644 --- a/test/micro/org/openjdk/bench/java/lang/Integers.java +++ b/test/micro/org/openjdk/bench/java/lang/Integers.java @@ -53,17 +53,20 @@ public class Integers { private int size; private String[] strings; + private int[] intsTiny; private int[] intsSmall; private int[] intsBig; @Setup public void setup() { - Random r = new Random(0); - strings = new String[size]; + Random r = new Random(0); + strings = new String[size]; + intsTiny = new int[size]; intsSmall = new int[size]; - intsBig = new int[size]; + intsBig = new int[size]; for (int i = 0; i < size; i++) { strings[i] = "" + (r.nextInt(10000) - (5000)); + intsTiny[i] = r.nextInt(99); intsSmall[i] = 100 * i + i + 103; intsBig[i] = ((100 * i + i) << 24) + 4543 + i * 4; } @@ -91,6 +94,14 @@ public class Integers { } } + /** Performs toString on very small values, just one or two digits. */ + @Benchmark + public void toStringTiny(Blackhole bh) { + for (int i : intsTiny) { + bh.consume(Integer.toString(i)); + } + } + /** Performs toString on large values, roughly 10 digits. */ @Benchmark public void toStringBig(Blackhole bh) { -- GitLab From 9e536b64705f841b224d0e64cad0f1609ebf5bca Mon Sep 17 00:00:00 2001 From: Claes Redestad Date: Mon, 17 Jan 2022 11:03:10 +0000 Subject: [PATCH 137/564] 8280032: Update jib-profiles.js to use JMH 1.34 devkit Reviewed-by: erikj, iris --- make/conf/jib-profiles.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make/conf/jib-profiles.js b/make/conf/jib-profiles.js index 24aeea9893d..5603678d4b8 100644 --- a/make/conf/jib-profiles.js +++ b/make/conf/jib-profiles.js @@ -1165,7 +1165,7 @@ var getJibProfilesDependencies = function (input, common) { jmh: { organization: common.organization, ext: "tar.gz", - revision: "1.33+1.0" + revision: "1.34+1.0" }, jcov: { -- GitLab From 3edcb13272c7d1a587e17fc16be523b3d73053ac Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Mon, 17 Jan 2022 13:17:24 +0000 Subject: [PATCH 138/564] 8280018: Remove obsolete VM_GenCollectFullConcurrent Reviewed-by: tschatzl --- src/hotspot/share/gc/shared/gcVMOperations.hpp | 2 -- src/hotspot/share/gc/shared/genCollectedHeap.hpp | 1 - src/hotspot/share/runtime/vmOperation.hpp | 1 - 3 files changed, 4 deletions(-) diff --git a/src/hotspot/share/gc/shared/gcVMOperations.hpp b/src/hotspot/share/gc/shared/gcVMOperations.hpp index ce071ee16a7..91443005658 100644 --- a/src/hotspot/share/gc/shared/gcVMOperations.hpp +++ b/src/hotspot/share/gc/shared/gcVMOperations.hpp @@ -42,7 +42,6 @@ // VM_GC_HeapInspection // VM_PopulateDynamicDumpSharedSpace // VM_GenCollectFull -// VM_GenCollectFullConcurrent // VM_ParallelGCSystemGC // VM_CollectForAllocation // VM_GenCollectForAllocation @@ -71,7 +70,6 @@ // allocate afterwards; // // VM_GenCollectFull -// VM_GenCollectFullConcurrent // VM_ParallelGCSystemGC // - these operations preform full collection of heaps of // different kind diff --git a/src/hotspot/share/gc/shared/genCollectedHeap.hpp b/src/hotspot/share/gc/shared/genCollectedHeap.hpp index 28ed627b80f..1cce08f4b0c 100644 --- a/src/hotspot/share/gc/shared/genCollectedHeap.hpp +++ b/src/hotspot/share/gc/shared/genCollectedHeap.hpp @@ -48,7 +48,6 @@ class GenCollectedHeap : public CollectedHeap { friend class GenMarkSweep; friend class VM_GenCollectForAllocation; friend class VM_GenCollectFull; - friend class VM_GenCollectFullConcurrent; friend class VM_GC_HeapInspection; friend class VM_HeapDumper; friend class HeapInspection; diff --git a/src/hotspot/share/runtime/vmOperation.hpp b/src/hotspot/share/runtime/vmOperation.hpp index c872ee11d3c..bd453df5979 100644 --- a/src/hotspot/share/runtime/vmOperation.hpp +++ b/src/hotspot/share/runtime/vmOperation.hpp @@ -52,7 +52,6 @@ template(CollectForMetadataAllocation) \ template(GC_HeapInspection) \ template(GenCollectFull) \ - template(GenCollectFullConcurrent) \ template(GenCollectForAllocation) \ template(ParallelGCFailedAllocation) \ template(ParallelGCSystemGC) \ -- GitLab From 5d52bf9987445b3a6033d66e8644ed77c4d761bd Mon Sep 17 00:00:00 2001 From: Hamlin Li Date: Mon, 17 Jan 2022 14:33:23 +0000 Subject: [PATCH 139/564] 8279910: G1: Simplify HeapRegionRemSet::add_reference Reviewed-by: tschatzl, ayang --- src/hotspot/share/gc/g1/g1OopClosures.inline.hpp | 4 +++- src/hotspot/share/gc/g1/heapRegionRemSet.inline.hpp | 5 +---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1OopClosures.inline.hpp b/src/hotspot/share/gc/g1/g1OopClosures.inline.hpp index 2cd41d4255f..c368130bfca 100644 --- a/src/hotspot/share/gc/g1/g1OopClosures.inline.hpp +++ b/src/hotspot/share/gc/g1/g1OopClosures.inline.hpp @@ -274,7 +274,9 @@ template void G1RebuildRemSetClosure::do_oop_work(T* p) { HeapRegion* to = _g1h->heap_region_containing(obj); HeapRegionRemSet* rem_set = to->rem_set(); - rem_set->add_reference(p, _worker_id); + if (rem_set->is_tracked()) { + rem_set->add_reference(p, _worker_id); + } } #endif // SHARE_GC_G1_G1OOPCLOSURES_INLINE_HPP diff --git a/src/hotspot/share/gc/g1/heapRegionRemSet.inline.hpp b/src/hotspot/share/gc/g1/heapRegionRemSet.inline.hpp index cd48da2a5bf..4bb8e6c4ff9 100644 --- a/src/hotspot/share/gc/g1/heapRegionRemSet.inline.hpp +++ b/src/hotspot/share/gc/g1/heapRegionRemSet.inline.hpp @@ -123,10 +123,7 @@ void HeapRegionRemSet::split_card(OopOrNarrowOopStar from, uint& card_region, ui } void HeapRegionRemSet::add_reference(OopOrNarrowOopStar from, uint tid) { - RemSetState state = _state; - if (state == Untracked) { - return; - } + assert(_state != Untracked, "must be"); uint cur_idx = _hr->hrm_index(); uintptr_t from_card = uintptr_t(from) >> CardTable::card_shift(); -- GitLab From 7b6738fa02023825ed9e602555bd5ed2b87a6ca6 Mon Sep 17 00:00:00 2001 From: Ana Marsh Date: Mon, 17 Jan 2022 16:36:43 +0000 Subject: [PATCH 140/564] 8278885: Remove Windows ARM64 int8_t workaround in G1 Reviewed-by: erikj, tschatzl, mli --- doc/building.html | 2 +- doc/building.md | 7 ++++--- make/autoconf/toolchain_microsoft.m4 | 1 + src/hotspot/share/gc/g1/g1HeapRegionAttr.hpp | 6 ------ 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/doc/building.html b/doc/building.html index 97c9b2a4bb6..6b99cf03ef2 100644 --- a/doc/building.html +++ b/doc/building.html @@ -298,7 +298,7 @@

    It is advisable to keep an older version of Xcode for building the JDK when updating Xcode. This blog page has good suggestions on managing multiple Xcode versions. To use a specific version of Xcode, use xcode-select -s before running configure, or use --with-toolchain-path to point to the version of Xcode to use, e.g. configure --with-toolchain-path=/Applications/Xcode8.app/Contents/Developer/usr/bin

    If you have recently (inadvertently) updated your OS and/or Xcode version, and the JDK can no longer be built, please see the section on Problems with the Build Environment, and Getting Help to find out if there are any recent, non-merged patches available for this update.

    Microsoft Visual Studio

    -

    The minimum accepted version of Visual Studio is 2017. Older versions will not be accepted by configure and will not work. The maximum accepted version of Visual Studio is 2019.

    +

    For aarch64 machines running Windows the minimum accepted version is Visual Studio 2019 (16.8 or higher). For all other platforms the minimum accepted version of Visual Studio is 2017. Older versions will not be accepted by configure and will not work. For all platforms the maximum accepted version of Visual Studio is 2022.

    If you have multiple versions of Visual Studio installed, configure will by default pick the latest. You can request a specific version to be used by setting --with-toolchain-version, e.g. --with-toolchain-version=2017.

    If you have Visual Studio installed but configure fails to detect it, it may be because of spaces in path.

    IBM XL C/C++

    diff --git a/doc/building.md b/doc/building.md index 033f99d3f5a..3ae4a28ac1f 100644 --- a/doc/building.md +++ b/doc/building.md @@ -374,9 +374,10 @@ available for this update. ### Microsoft Visual Studio -The minimum accepted version of Visual Studio is 2017. Older versions will not -be accepted by `configure` and will not work. The maximum accepted -version of Visual Studio is 2019. +For aarch64 machines running Windows the minimum accepted version is Visual Studio 2019 +(16.8 or higher). For all other platforms the minimum accepted version of +Visual Studio is 2017. Older versions will not be accepted by `configure` and will +not work. For all platforms the maximum accepted version of Visual Studio is 2022. If you have multiple versions of Visual Studio installed, `configure` will by default pick the latest. You can request a specific version to be used by diff --git a/make/autoconf/toolchain_microsoft.m4 b/make/autoconf/toolchain_microsoft.m4 index 2600b431cfb..2e02c531da7 100644 --- a/make/autoconf/toolchain_microsoft.m4 +++ b/make/autoconf/toolchain_microsoft.m4 @@ -103,6 +103,7 @@ AC_DEFUN([TOOLCHAIN_CHECK_POSSIBLE_VISUAL_STUDIO_ROOT], vc/auxiliary/build/vcvarsx86_amd64.bat vc/auxiliary/build/vcvars64.bat" elif test "x$TARGET_CPU" = xaarch64; then # for host x86-64, target aarch64 + # aarch64 requires Visual Studio 16.8 or higher VCVARSFILES="vc/auxiliary/build/vcvarsamd64_arm64.bat \ vc/auxiliary/build/vcvarsx86_arm64.bat" fi diff --git a/src/hotspot/share/gc/g1/g1HeapRegionAttr.hpp b/src/hotspot/share/gc/g1/g1HeapRegionAttr.hpp index 2b8fb3532ee..d59d7e1c0fb 100644 --- a/src/hotspot/share/gc/g1/g1HeapRegionAttr.hpp +++ b/src/hotspot/share/gc/g1/g1HeapRegionAttr.hpp @@ -32,13 +32,7 @@ // lookups for that information all over the place. struct G1HeapRegionAttr { public: -#if defined(_M_ARM64)&& defined(_MSC_VER) && _MSC_VER <= 1927 - // workaround for MSCV ARM64 bug - // https://developercommunity.visualstudio.com/content/problem/1079221/arm64-bad-code-generation-around-signed-char-arith.html - typedef int32_t region_type_t; -#else typedef int8_t region_type_t; -#endif // remset_is_tracked_t is essentially bool, but we need precise control // on the size, and sizeof(bool) is implementation specific. typedef uint8_t remset_is_tracked_t; -- GitLab From 262f2efd6ce546b4ee8c9c045916c1a23ad14676 Mon Sep 17 00:00:00 2001 From: David Holmes Date: Tue, 18 Jan 2022 00:47:27 +0000 Subject: [PATCH 141/564] 8280059: Incorrect glibc version is used in a comment in os_linux.cpp Reviewed-by: jiefu --- src/hotspot/os/linux/os_linux.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index 2ebdfa0a832..31b110efcbc 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -806,7 +806,7 @@ bool os::create_thread(Thread* thread, ThreadType thr_type, // Calculate stack size if it's not specified by caller. size_t stack_size = os::Posix::get_initial_stack_size(thr_type, req_stack_size); - // In glibc versions prior to 2.7 the guard size mechanism + // In glibc versions prior to 2.27 the guard size mechanism // is not implemented properly. The posix standard requires adding // the size of the guard pages to the stack size, instead Linux // takes the space out of 'stacksize'. Thus we adapt the requested -- GitLab From 48c5f3c71519826d3510e5ac55980d10be763b17 Mon Sep 17 00:00:00 2001 From: Nils Eliasson Date: Tue, 18 Jan 2022 07:58:11 +0000 Subject: [PATCH 142/564] 8280026: Cleanup of IGV printing Reviewed-by: chagedorn, thartmann --- src/hotspot/share/opto/compile.cpp | 71 +++++++++++++++++++----------- src/hotspot/share/opto/compile.hpp | 35 +++------------ src/hotspot/share/opto/matcher.cpp | 2 +- 3 files changed, 51 insertions(+), 57 deletions(-) diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index 8e184164b77..1f1b438f796 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -2080,7 +2080,7 @@ void Compile::Optimize() { NOT_PRODUCT( verify_graph_edges(); ) - print_method(PHASE_AFTER_PARSING); + print_method(PHASE_AFTER_PARSING, 1); { // Iterative Global Value Numbering, including ideal transforms @@ -2846,7 +2846,7 @@ void Compile::Code_Gen() { output.install(); } - print_method(PHASE_FINAL_CODE); + print_method(PHASE_FINAL_CODE, 1); // He's dead, Jim. _cfg = (PhaseCFG*)((intptr_t)0xdeadbeef); @@ -4078,7 +4078,7 @@ void Compile::record_failure(const char* reason) { } if (!C->failure_reason_is(C2Compiler::retry_no_subsuming_loads())) { - C->print_method(PHASE_FAILURE); + C->print_method(PHASE_FAILURE, 1); } _root = NULL; // flush the graph, too } @@ -4808,7 +4808,23 @@ void Compile::sort_macro_nodes() { } } -void Compile::print_method(CompilerPhaseType cpt, const char *name, int level) { +void Compile::print_method(CompilerPhaseType cpt, int level) { + print_method_impl(cpt, CompilerPhaseTypeHelper::to_string(cpt), level); +} + +void Compile::print_method(CompilerPhaseType cpt, Node* n, int level) { + ResourceMark rm; + stringStream ss; + ss.print_raw(CompilerPhaseTypeHelper::to_string(cpt)); + if (n != NULL) { + ss.print(": %d %s ", n->_idx, NodeClassNames[n->Opcode()]); + } else { + ss.print_raw(": NULL"); + } + C->print_method_impl(cpt, ss.as_string(), level); +} + +void Compile::print_method_impl(CompilerPhaseType cpt, const char *name, int level) { EventCompilerPhase event; if (event.should_commit()) { CompilerEvent::PhaseEvent::post(event, C->_latest_stage_start_counter, cpt, C->_compile_id, level); @@ -4821,43 +4837,46 @@ void Compile::print_method(CompilerPhaseType cpt, const char *name, int level) { C->_latest_stage_start_counter.stamp(); } -void Compile::print_method(CompilerPhaseType cpt, int level, int idx) { - char output[1024]; +// Only used from CompileWrapper +void Compile::begin_method() { #ifndef PRODUCT - if (idx != 0) { - jio_snprintf(output, sizeof(output), "%s:%d", CompilerPhaseTypeHelper::to_string(cpt), idx); - } else { - jio_snprintf(output, sizeof(output), "%s", CompilerPhaseTypeHelper::to_string(cpt)); + if (_method != NULL && should_print(1)) { + _printer->begin_method(); } #endif - print_method(cpt, output, level); -} - -void Compile::print_method(CompilerPhaseType cpt, Node* n, int level) { - ResourceMark rm; - stringStream ss; - ss.print_raw(CompilerPhaseTypeHelper::to_string(cpt)); - if (n != NULL) { - ss.print(": %d %s ", n->_idx, NodeClassNames[n->Opcode()]); - } else { - ss.print_raw(": NULL"); - } - C->print_method(cpt, ss.as_string(), level); + C->_latest_stage_start_counter.stamp(); } -void Compile::end_method(int level) { +// Only used from CompileWrapper +void Compile::end_method() { EventCompilerPhase event; if (event.should_commit()) { - CompilerEvent::PhaseEvent::post(event, C->_latest_stage_start_counter, PHASE_END, C->_compile_id, level); + CompilerEvent::PhaseEvent::post(event, C->_latest_stage_start_counter, PHASE_END, C->_compile_id, 1); } #ifndef PRODUCT - if (_method != NULL && should_print(level)) { + if (_method != NULL && should_print(1)) { _printer->end_method(); } #endif } +bool Compile::should_print(int level) { +#ifndef PRODUCT + if (PrintIdealGraphLevel < 0) { // disabled by the user + return false; + } + + bool need = directive()->IGVPrintLevelOption >= level; + if (need && _printer == nullptr) { + _printer = IdealGraphPrinter::printer(); + _printer->set_compile(this); + } + return need; +#else + return false; +#endif +} #ifndef PRODUCT IdealGraphPrinter* Compile::_debug_file_printer = NULL; diff --git a/src/hotspot/share/opto/compile.hpp b/src/hotspot/share/opto/compile.hpp index 175c49dd016..0e6355715d4 100644 --- a/src/hotspot/share/opto/compile.hpp +++ b/src/hotspot/share/opto/compile.hpp @@ -650,36 +650,13 @@ class Compile : public Phase { Ticks _latest_stage_start_counter; - void begin_method(int level = 1) { -#ifndef PRODUCT - if (_method != NULL && should_print(level)) { - _printer->begin_method(); - } -#endif - C->_latest_stage_start_counter.stamp(); - } + void begin_method(); + void end_method(); + bool should_print(int level); - bool should_print(int level = 1) { -#ifndef PRODUCT - if (PrintIdealGraphLevel < 0) { // disabled by the user - return false; - } - - bool need = directive()->IGVPrintLevelOption >= level; - if (need && !_printer) { - _printer = IdealGraphPrinter::printer(); - assert(_printer != NULL, "_printer is NULL when we need it!"); - _printer->set_compile(this); - } - return need; -#else - return false; -#endif - } - - void print_method(CompilerPhaseType cpt, const char *name, int level = 1); - void print_method(CompilerPhaseType cpt, int level = 1, int idx = 0); + void print_method(CompilerPhaseType cpt, int level); void print_method(CompilerPhaseType cpt, Node* n, int level = 3); + void print_method_impl(CompilerPhaseType cpt, const char *name, int level); #ifndef PRODUCT void igv_print_method_to_file(const char* phase_name = "Debug", bool append = false); @@ -688,8 +665,6 @@ class Compile : public Phase { static IdealGraphPrinter* debug_network_printer() { return _debug_network_printer; } #endif - void end_method(int level = 1); - int macro_count() const { return _macro_nodes.length(); } int predicate_count() const { return _predicate_opaqs.length(); } int skeleton_predicate_count() const { return _skeleton_predicate_opaqs.length(); } diff --git a/src/hotspot/share/opto/matcher.cpp b/src/hotspot/share/opto/matcher.cpp index ca5c8d03380..35ccf26e7cb 100644 --- a/src/hotspot/share/opto/matcher.cpp +++ b/src/hotspot/share/opto/matcher.cpp @@ -322,7 +322,7 @@ void Matcher::match( ) { find_shared( C->root() ); find_shared( C->top() ); - C->print_method(PHASE_BEFORE_MATCHING); + C->print_method(PHASE_BEFORE_MATCHING, 1); // Create new ideal node ConP #NULL even if it does exist in old space // to avoid false sharing if the corresponding mach node is not used. -- GitLab From 945226265234b790b175ea312f7af1126984db68 Mon Sep 17 00:00:00 2001 From: Masanori Yano Date: Tue, 18 Jan 2022 09:04:09 +0000 Subject: [PATCH 143/564] 8278892: java.naming module description is missing @uses tags to document the services that it uses Reviewed-by: aefimov, alanb --- src/java.naming/share/classes/module-info.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/java.naming/share/classes/module-info.java b/src/java.naming/share/classes/module-info.java index f7d0ace806d..43be8eb6299 100644 --- a/src/java.naming/share/classes/module-info.java +++ b/src/java.naming/share/classes/module-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2022, 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 @@ -104,9 +104,11 @@ *
  • DNS Naming Provider
  • *
  • RMI Naming Provider
  • * - * @provides javax.naming.ldap.spi.LdapDnsProvider + * @provides java.security.Provider * + * @uses javax.naming.ldap.StartTlsResponse * @uses javax.naming.ldap.spi.LdapDnsProvider + * @uses javax.naming.spi.InitialContextFactory * * @moduleGraph * @since 9 -- GitLab From eb9499535cde140c6bf16b3c4a8e9ee55412d0c3 Mon Sep 17 00:00:00 2001 From: Hamlin Li Date: Tue, 18 Jan 2022 09:16:24 +0000 Subject: [PATCH 144/564] 8280070: G1: Fix template parameters in G1SegmentedArraySegment Reviewed-by: ayang, tschatzl --- src/hotspot/share/gc/g1/g1SegmentedArray.inline.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1SegmentedArray.inline.hpp b/src/hotspot/share/gc/g1/g1SegmentedArray.inline.hpp index 1829f47e216..17be55fe6ab 100644 --- a/src/hotspot/share/gc/g1/g1SegmentedArray.inline.hpp +++ b/src/hotspot/share/gc/g1/g1SegmentedArray.inline.hpp @@ -34,12 +34,12 @@ template G1SegmentedArraySegment::G1SegmentedArraySegment(uint slot_size, uint num_slots, G1SegmentedArraySegment* next) : _slot_size(slot_size), _num_slots(num_slots), _next(next), _next_allocate(0) { - _segment = NEW_C_HEAP_ARRAY(char, (size_t)_num_slots * slot_size, mtGCCardSet); + _segment = NEW_C_HEAP_ARRAY(char, (size_t)_num_slots * slot_size, flag); } template G1SegmentedArraySegment::~G1SegmentedArraySegment() { - FREE_C_HEAP_ARRAY(mtGCCardSet, _segment); + FREE_C_HEAP_ARRAY(flag, _segment); } template -- GitLab From 645b38d586b38252faa4663aca0453e3079fc30d Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Tue, 18 Jan 2022 12:13:44 +0000 Subject: [PATCH 145/564] 8280089: compiler/c2/irTests/TestIRAbs.java fails on some arches Reviewed-by: jiefu, thartmann, chagedorn, fgao --- test/hotspot/jtreg/compiler/c2/irTests/TestIRAbs.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestIRAbs.java b/test/hotspot/jtreg/compiler/c2/irTests/TestIRAbs.java index fc8362b1e1f..8ba786d6f20 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/TestIRAbs.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/TestIRAbs.java @@ -28,8 +28,9 @@ import compiler.lib.ir_framework.*; /* * @test - * @bug 8276673 + * @bug 8276673 8280089 * @summary Test abs nodes optimization in C2. + * @requires os.arch=="amd64" | os.arch=="x86_64" | os.arch=="aarch64" * @library /test/lib / * @run driver compiler.c2.irTests.TestIRAbs */ -- GitLab From e38df21641f13d7ae92f72cf8e72660072d3e5fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Gr=C3=B6nlund?= Date: Tue, 18 Jan 2022 13:16:51 +0000 Subject: [PATCH 146/564] 8256291: RunThese30M fails "assert(_class_unload ? true : ((((JfrTraceIdBits::load(class_loader_klass)) & ((1 << 4) << 8)) != 0))) failed: invariant" Reviewed-by: egahlin --- .../types/traceid/jfrTraceIdLoadBarrier.inline.hpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdLoadBarrier.inline.hpp b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdLoadBarrier.inline.hpp index 29bade3def6..9b7ddcd1273 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdLoadBarrier.inline.hpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdLoadBarrier.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, 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 @@ -109,7 +109,14 @@ inline traceid JfrTraceIdLoadBarrier::load(const PackageEntry* package) { inline traceid JfrTraceIdLoadBarrier::load(const ClassLoaderData* cld) { assert(cld != NULL, "invariant"); - return cld->has_class_mirror_holder() ? 0 : set_used_and_get(cld); + if (cld->has_class_mirror_holder()) { + return 0; + } + const Klass* const class_loader_klass = cld->class_loader_klass(); + if (class_loader_klass != nullptr && should_tag(class_loader_klass)) { + load_barrier(class_loader_klass); + } + return set_used_and_get(cld); } inline traceid JfrTraceIdLoadBarrier::load_leakp(const Klass* klass, const Method* method) { -- GitLab From 1725f77bcd6528d56960a0796fcea3725cc98b6a Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Tue, 18 Jan 2022 14:40:39 +0000 Subject: [PATCH 147/564] 8280029: G1: "Overflow during reference processing, can not continue" on x86_32 Reviewed-by: tschatzl, ayang --- src/hotspot/share/gc/g1/g1ConcurrentMark.cpp | 7 ++++--- src/hotspot/share/gc/shared/gc_globals.hpp | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp index c57b68c1f37..c2800aacfbc 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp @@ -1646,9 +1646,10 @@ void G1ConcurrentMark::weak_refs_work() { if (has_overflown()) { // We can not trust g1_is_alive and the contents of the heap if the marking stack // overflowed while processing references. Exit the VM. - fatal("Overflow during reference processing, can not continue. Please " - "increase MarkStackSizeMax (current value: " SIZE_FORMAT ") and " - "restart.", MarkStackSizeMax); + fatal("Overflow during reference processing, can not continue. Current mark stack depth: " + SIZE_FORMAT ", MarkStackSize: " SIZE_FORMAT ", MarkStackSizeMax: " SIZE_FORMAT ". " + "Please increase MarkStackSize and/or MarkStackSizeMax and restart.", + _global_mark_stack.size(), MarkStackSize, MarkStackSizeMax); return; } diff --git a/src/hotspot/share/gc/shared/gc_globals.hpp b/src/hotspot/share/gc/shared/gc_globals.hpp index 684357297d8..555170a091a 100644 --- a/src/hotspot/share/gc/shared/gc_globals.hpp +++ b/src/hotspot/share/gc/shared/gc_globals.hpp @@ -208,7 +208,7 @@ "Maximum size of marking stack") \ range(1, (max_jint - 1)) \ \ - product(size_t, MarkStackSize, NOT_LP64(32*K) LP64_ONLY(4*M), \ + product(size_t, MarkStackSize, NOT_LP64(64*K) LP64_ONLY(4*M), \ "Size of marking stack") \ constraint(MarkStackSizeConstraintFunc,AfterErgo) \ range(1, (max_jint - 1)) \ -- GitLab From d175d33f44e996d2927f953dac2ad4fef542f2a0 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Tue, 18 Jan 2022 14:53:42 +0000 Subject: [PATCH 148/564] 8280079: Serial: Remove empty Generation::prepare_for_verify Reviewed-by: tschatzl, iwalulya --- src/hotspot/share/gc/serial/tenuredGeneration.cpp | 3 --- src/hotspot/share/gc/serial/tenuredGeneration.hpp | 2 -- src/hotspot/share/gc/shared/cardGeneration.cpp | 3 --- src/hotspot/share/gc/shared/cardGeneration.hpp | 2 -- src/hotspot/share/gc/shared/genCollectedHeap.cpp | 8 -------- src/hotspot/share/gc/shared/generation.hpp | 4 ---- 6 files changed, 22 deletions(-) diff --git a/src/hotspot/share/gc/serial/tenuredGeneration.cpp b/src/hotspot/share/gc/serial/tenuredGeneration.cpp index 1aec978b382..fd135529157 100644 --- a/src/hotspot/share/gc/serial/tenuredGeneration.cpp +++ b/src/hotspot/share/gc/serial/tenuredGeneration.cpp @@ -212,9 +212,6 @@ void TenuredGeneration::assert_correct_size_change_locking() { assert_locked_or_safepoint(ExpandHeap_lock); } -// Currently nothing to do. -void TenuredGeneration::prepare_for_verify() {} - void TenuredGeneration::object_iterate(ObjectClosure* blk) { _the_space->object_iterate(blk); } diff --git a/src/hotspot/share/gc/serial/tenuredGeneration.hpp b/src/hotspot/share/gc/serial/tenuredGeneration.hpp index 44153320f6c..410981de758 100644 --- a/src/hotspot/share/gc/serial/tenuredGeneration.hpp +++ b/src/hotspot/share/gc/serial/tenuredGeneration.hpp @@ -97,8 +97,6 @@ class TenuredGeneration: public CardGeneration { HeapWord* expand_and_allocate(size_t size, bool is_tlab); - virtual void prepare_for_verify(); - virtual void gc_prologue(bool full); virtual void gc_epilogue(bool full); diff --git a/src/hotspot/share/gc/shared/cardGeneration.cpp b/src/hotspot/share/gc/shared/cardGeneration.cpp index 1ba0ecc5ad5..523f65c8cc3 100644 --- a/src/hotspot/share/gc/shared/cardGeneration.cpp +++ b/src/hotspot/share/gc/shared/cardGeneration.cpp @@ -301,9 +301,6 @@ void CardGeneration::compute_new_size() { } } -// Currently nothing to do. -void CardGeneration::prepare_for_verify() {} - void CardGeneration::space_iterate(SpaceClosure* blk, bool usedOnly) { blk->do_space(space()); diff --git a/src/hotspot/share/gc/shared/cardGeneration.hpp b/src/hotspot/share/gc/shared/cardGeneration.hpp index 82c5fa5acb5..084737a6146 100644 --- a/src/hotspot/share/gc/shared/cardGeneration.hpp +++ b/src/hotspot/share/gc/shared/cardGeneration.hpp @@ -73,8 +73,6 @@ class CardGeneration: public Generation { virtual void invalidate_remembered_set(); - virtual void prepare_for_verify(); - // Grow generation with specified size (returns false if unable to grow) bool grow_by(size_t bytes); // Grow generation to reserved size. diff --git a/src/hotspot/share/gc/shared/genCollectedHeap.cpp b/src/hotspot/share/gc/shared/genCollectedHeap.cpp index 473e5abc1df..c840e5a6667 100644 --- a/src/hotspot/share/gc/shared/genCollectedHeap.cpp +++ b/src/hotspot/share/gc/shared/genCollectedHeap.cpp @@ -1045,16 +1045,8 @@ void GenCollectedHeap::release_scratch() { _old_gen->reset_scratch(); } -class GenPrepareForVerifyClosure: public GenCollectedHeap::GenClosure { - void do_generation(Generation* gen) { - gen->prepare_for_verify(); - } -}; - void GenCollectedHeap::prepare_for_verify() { ensure_parsability(false); // no need to retire TLABs - GenPrepareForVerifyClosure blk; - generation_iterate(&blk, false); } void GenCollectedHeap::generation_iterate(GenClosure* cl, diff --git a/src/hotspot/share/gc/shared/generation.hpp b/src/hotspot/share/gc/shared/generation.hpp index 7f8a82e4939..b9183ec2898 100644 --- a/src/hotspot/share/gc/shared/generation.hpp +++ b/src/hotspot/share/gc/shared/generation.hpp @@ -364,10 +364,6 @@ class Generation: public CHeapObj { virtual void post_compact() { ShouldNotReachHere(); } #endif - // Some generations may require some cleanup actions before allowing - // a verification. - virtual void prepare_for_verify() {} - // Accessing "marks". // This function gives a generation a chance to note a point between -- GitLab From 64c0c0e109f9853072f1d306fef1a2e31568ec9e Mon Sep 17 00:00:00 2001 From: Andrew Haley Date: Tue, 18 Jan 2022 15:27:18 +0000 Subject: [PATCH 149/564] 8276563: Undefined Behaviour in class Assembler Reviewed-by: jvernee, stuefe --- src/hotspot/cpu/aarch64/assembler_aarch64.hpp | 2 +- .../cpu/aarch64/foreign_globals_aarch64.cpp | 2 +- .../cpu/aarch64/globalDefinitions_aarch64.hpp | 2 + .../aarch64/jvmciCodeInstaller_aarch64.cpp | 2 +- src/hotspot/cpu/aarch64/register_aarch64.cpp | 10 ++- src/hotspot/cpu/aarch64/register_aarch64.hpp | 83 ++++++++++--------- .../cpu/aarch64/vmreg_aarch64.inline.hpp | 6 +- src/hotspot/share/asm/register.hpp | 39 ++++++++- 8 files changed, 96 insertions(+), 50 deletions(-) diff --git a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp index fb4b7b87141..05234a31157 100644 --- a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp @@ -1726,7 +1726,7 @@ void mvnw(Register Rd, Register Rm, #define INSN(NAME, op) \ void NAME(Register Rn, Register Rm, int imm, Condition cond) { \ - int regNumber = (Rm == zr ? 31 : (uintptr_t)Rm); \ + int regNumber = (Rm == zr ? 31 : Rm->encoding()); \ conditional_compare(op, 0, 0, 0, Rn, regNumber, imm, cond); \ } \ \ diff --git a/src/hotspot/cpu/aarch64/foreign_globals_aarch64.cpp b/src/hotspot/cpu/aarch64/foreign_globals_aarch64.cpp index d08afc79a52..4334a395571 100644 --- a/src/hotspot/cpu/aarch64/foreign_globals_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/foreign_globals_aarch64.cpp @@ -45,7 +45,7 @@ bool ABIDescriptor::is_volatile_reg(FloatRegister reg) const { const ABIDescriptor ForeignGlobals::parse_abi_descriptor_impl(jobject jabi) const { oop abi_oop = JNIHandles::resolve_non_null(jabi); ABIDescriptor abi; - const Register (*to_Register)(int) = as_Register; + constexpr Register (*to_Register)(int) = as_Register; objArrayOop inputStorage = cast(abi_oop->obj_field(ABI.inputStorage_offset)); loadArray(inputStorage, INTEGER_TYPE, abi._integer_argument_registers, to_Register); diff --git a/src/hotspot/cpu/aarch64/globalDefinitions_aarch64.hpp b/src/hotspot/cpu/aarch64/globalDefinitions_aarch64.hpp index 3c779bb11b1..fe88f7b887c 100644 --- a/src/hotspot/cpu/aarch64/globalDefinitions_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/globalDefinitions_aarch64.hpp @@ -67,4 +67,6 @@ const bool CCallingConventionRequiresIntsAsLongs = false; #define NOT_R18_RESERVED(code) code #endif +#define USE_POINTERS_TO_REGISTER_IMPL_ARRAY + #endif // CPU_AARCH64_GLOBALDEFINITIONS_AARCH64_HPP diff --git a/src/hotspot/cpu/aarch64/jvmciCodeInstaller_aarch64.cpp b/src/hotspot/cpu/aarch64/jvmciCodeInstaller_aarch64.cpp index 17b9780129d..aacca26a36c 100644 --- a/src/hotspot/cpu/aarch64/jvmciCodeInstaller_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/jvmciCodeInstaller_aarch64.cpp @@ -186,7 +186,7 @@ VMReg CodeInstaller::get_hotspot_reg(jint jvmci_reg, JVMCI_TRAPS) { if (jvmci_reg < RegisterImpl::number_of_registers) { return as_Register(jvmci_reg)->as_VMReg(); } else { - jint floatRegisterNumber = jvmci_reg - RegisterImpl::number_of_registers_for_jvmci; + jint floatRegisterNumber = jvmci_reg - RegisterImpl::number_of_declared_registers; if (floatRegisterNumber >= 0 && floatRegisterNumber < FloatRegisterImpl::number_of_registers) { return as_FloatRegister(floatRegisterNumber)->as_VMReg(); } diff --git a/src/hotspot/cpu/aarch64/register_aarch64.cpp b/src/hotspot/cpu/aarch64/register_aarch64.cpp index b785457ae29..096e480a824 100644 --- a/src/hotspot/cpu/aarch64/register_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/register_aarch64.cpp @@ -26,6 +26,10 @@ #include "precompiled.hpp" #include "register_aarch64.hpp" +REGISTER_IMPL_DEFINITION(Register, RegisterImpl, RegisterImpl::number_of_declared_registers); +REGISTER_IMPL_DEFINITION(FloatRegister, FloatRegisterImpl, FloatRegisterImpl::number_of_registers); +REGISTER_IMPL_DEFINITION(PRegister, PRegisterImpl, PRegisterImpl::number_of_registers); + const int ConcreteRegisterImpl::max_gpr = RegisterImpl::number_of_registers * RegisterImpl::max_slots_per_register; @@ -38,7 +42,7 @@ const int ConcreteRegisterImpl::max_pr PRegisterImpl::number_of_registers * PRegisterImpl::max_slots_per_register; const char* RegisterImpl::name() const { - const char* names[number_of_registers] = { + static const char *const names[number_of_registers] = { "c_rarg0", "c_rarg1", "c_rarg2", "c_rarg3", "c_rarg4", "c_rarg5", "c_rarg6", "c_rarg7", "rscratch1", "rscratch2", "r10", "r11", "r12", "r13", "r14", "r15", "r16", @@ -50,7 +54,7 @@ const char* RegisterImpl::name() const { } const char* FloatRegisterImpl::name() const { - const char* names[number_of_registers] = { + static const char *const names[number_of_registers] = { "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23", @@ -60,7 +64,7 @@ const char* FloatRegisterImpl::name() const { } const char* PRegisterImpl::name() const { - const char* names[number_of_registers] = { + static const char *const names[number_of_registers] = { "p0", "p1", "p2", "p3", "p4", "p5", "p6", "p7", "p8", "p9", "p10", "p11", "p12", "p13", "p14", "p15" }; diff --git a/src/hotspot/cpu/aarch64/register_aarch64.hpp b/src/hotspot/cpu/aarch64/register_aarch64.hpp index 7b472856dc4..7e531710c1d 100644 --- a/src/hotspot/cpu/aarch64/register_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/register_aarch64.hpp @@ -34,42 +34,42 @@ typedef VMRegImpl* VMReg; // Use Register as shortcut class RegisterImpl; -typedef RegisterImpl* Register; +typedef const RegisterImpl* Register; -inline const Register as_Register(int encoding) { - return (Register)(intptr_t) encoding; -} +inline constexpr Register as_Register(int encoding); class RegisterImpl: public AbstractRegisterImpl { - public: + static constexpr Register first(); + +public: enum { number_of_registers = 32, - number_of_byte_registers = 32, - number_of_registers_for_jvmci = 34, // Including SP and ZR. + number_of_declared_registers = 34, // Including SP and ZR. max_slots_per_register = 2 }; // derived registers, offsets, and addresses - Register successor() const { return as_Register(encoding() + 1); } + const Register successor() const { return this + 1; } // construction - inline friend const Register as_Register(int encoding); + inline friend constexpr Register as_Register(int encoding); - VMReg as_VMReg(); + VMReg as_VMReg() const; // accessors - int encoding() const { assert(is_valid(), "invalid register"); return (intptr_t)this; } - bool is_valid() const { return 0 <= (intptr_t)this && (intptr_t)this < number_of_registers; } - bool has_byte_register() const { return 0 <= (intptr_t)this && (intptr_t)this < number_of_byte_registers; } + int encoding() const { assert(is_valid(), "invalid register"); return encoding_nocheck(); } + bool is_valid() const { return (unsigned)encoding_nocheck() < number_of_registers; } const char* name() const; - int encoding_nocheck() const { return (intptr_t)this; } + int encoding_nocheck() const { return this - first(); } }; + +REGISTER_IMPL_DECLARATION(Register, RegisterImpl, RegisterImpl::number_of_declared_registers); + // The integer registers of the aarch64 architecture CONSTANT_REGISTER_DECLARATION(Register, noreg, (-1)); - CONSTANT_REGISTER_DECLARATION(Register, r0, (0)); CONSTANT_REGISTER_DECLARATION(Register, r1, (1)); CONSTANT_REGISTER_DECLARATION(Register, r2, (2)); @@ -126,15 +126,15 @@ const Register dummy_reg = r31_sp; // Use FloatRegister as shortcut class FloatRegisterImpl; -typedef FloatRegisterImpl* FloatRegister; +typedef const FloatRegisterImpl* FloatRegister; -inline FloatRegister as_FloatRegister(int encoding) { - return (FloatRegister)(intptr_t) encoding; -} +inline constexpr FloatRegister as_FloatRegister(int encoding); // The implementation of floating point registers for the architecture class FloatRegisterImpl: public AbstractRegisterImpl { - public: + static constexpr FloatRegister first(); + +public: enum { number_of_registers = 32, max_slots_per_register = 8, @@ -144,21 +144,25 @@ class FloatRegisterImpl: public AbstractRegisterImpl { }; // construction - inline friend FloatRegister as_FloatRegister(int encoding); + inline friend constexpr FloatRegister as_FloatRegister(int encoding); - VMReg as_VMReg(); + VMReg as_VMReg() const; // derived registers, offsets, and addresses - FloatRegister successor() const { return as_FloatRegister((encoding() + 1) % 32); } + FloatRegister successor() const { + return as_FloatRegister((encoding() + 1) % (unsigned)number_of_registers); + } // accessors - int encoding() const { assert(is_valid(), "invalid register"); return (intptr_t)this; } - int encoding_nocheck() const { return (intptr_t)this; } - bool is_valid() const { return 0 <= (intptr_t)this && (intptr_t)this < number_of_registers; } + int encoding() const { assert(is_valid(), "invalid register"); return encoding_nocheck(); } + bool is_valid() const { return (unsigned)encoding_nocheck() < number_of_registers; } const char* name() const; - + int encoding_nocheck() const { return this - first(); } }; +REGISTER_IMPL_DECLARATION(FloatRegister, FloatRegisterImpl, FloatRegisterImpl::number_of_registers); + + // The float registers of the AARCH64 architecture CONSTANT_REGISTER_DECLARATION(FloatRegister, fnoreg , (-1)); @@ -232,13 +236,13 @@ CONSTANT_REGISTER_DECLARATION(FloatRegister, z31 , (31)); class PRegisterImpl; -typedef PRegisterImpl* PRegister; -inline PRegister as_PRegister(int encoding) { - return (PRegister)(intptr_t)encoding; -} +typedef const PRegisterImpl* PRegister; +inline constexpr PRegister as_PRegister(int encoding); // The implementation of predicate registers for the architecture class PRegisterImpl: public AbstractRegisterImpl { + static constexpr PRegister first(); + public: enum { number_of_registers = 16, @@ -252,21 +256,24 @@ class PRegisterImpl: public AbstractRegisterImpl { }; // construction - inline friend PRegister as_PRegister(int encoding); + inline friend constexpr PRegister as_PRegister(int encoding); - VMReg as_VMReg(); + VMReg as_VMReg() const; // derived registers, offsets, and addresses - PRegister successor() const { return as_PRegister(encoding() + 1); } + PRegister successor() const { return this + 1; } // accessors - int encoding() const { assert(is_valid(), "invalid register"); return (intptr_t)this; } - int encoding_nocheck() const { return (intptr_t)this; } - bool is_valid() const { return 0 <= (intptr_t)this && (intptr_t)this < number_of_registers; } - bool is_governing() const { return 0 <= (intptr_t)this && (intptr_t)this < number_of_governing_registers; } + int encoding() const { assert(is_valid(), "invalid register"); return encoding_nocheck(); } + int encoding_nocheck() const { return this - first(); } + bool is_valid() const { return (unsigned)encoding_nocheck() < number_of_registers; } + bool is_governing() const { return first() <= this && this - first() < number_of_governing_registers; } const char* name() const; }; + +REGISTER_IMPL_DECLARATION(PRegister, PRegisterImpl, PRegisterImpl::number_of_registers); + // The predicate registers of SVE. CONSTANT_REGISTER_DECLARATION(PRegister, pnoreg, (-1)); diff --git a/src/hotspot/cpu/aarch64/vmreg_aarch64.inline.hpp b/src/hotspot/cpu/aarch64/vmreg_aarch64.inline.hpp index 8452417b6cf..aa750104896 100644 --- a/src/hotspot/cpu/aarch64/vmreg_aarch64.inline.hpp +++ b/src/hotspot/cpu/aarch64/vmreg_aarch64.inline.hpp @@ -26,17 +26,17 @@ #ifndef CPU_AARCH64_VMREG_AARCH64_INLINE_HPP #define CPU_AARCH64_VMREG_AARCH64_INLINE_HPP -inline VMReg RegisterImpl::as_VMReg() { +inline VMReg RegisterImpl::as_VMReg() const { if( this==noreg ) return VMRegImpl::Bad(); return VMRegImpl::as_VMReg(encoding() * RegisterImpl::max_slots_per_register); } -inline VMReg FloatRegisterImpl::as_VMReg() { +inline VMReg FloatRegisterImpl::as_VMReg() const { return VMRegImpl::as_VMReg((encoding() * FloatRegisterImpl::max_slots_per_register) + ConcreteRegisterImpl::max_gpr); } -inline VMReg PRegisterImpl::as_VMReg() { +inline VMReg PRegisterImpl::as_VMReg() const { return VMRegImpl::as_VMReg(encoding() + ConcreteRegisterImpl::max_fpr); } diff --git a/src/hotspot/share/asm/register.hpp b/src/hotspot/share/asm/register.hpp index 861c43b2c84..06a8735f520 100644 --- a/src/hotspot/share/asm/register.hpp +++ b/src/hotspot/share/asm/register.hpp @@ -45,15 +45,48 @@ class AbstractRegisterImpl { int value() const { return (int)(intx)this; } }; + +// Macros to help define all kinds of registers + +#ifndef USE_POINTERS_TO_REGISTER_IMPL_ARRAY + #define AS_REGISTER(type,name) ((type)name##_##type##EnumValue) -#define CONSTANT_REGISTER_DECLARATION(type, name, value) \ -const type name = ((type)value); \ +#define CONSTANT_REGISTER_DECLARATION(type, name, value) \ +const type name = ((type)value); \ enum { name##_##type##EnumValue = (value) } -#define REGISTER_DECLARATION(type, name, value) \ +#else // USE_POINTERS_TO_REGISTER_IMPL_ARRAY + +#define REGISTER_IMPL_DECLARATION(type, impl_type, reg_count) \ +inline constexpr type as_ ## type(int encoding) { \ + return impl_type::first() + encoding; \ +} \ +extern impl_type all_ ## type ## s[reg_count + 1] INTERNAL_VISIBILITY; \ +inline constexpr type impl_type::first() { return all_ ## type ## s + 1; } + +#define REGISTER_IMPL_DEFINITION(type, impl_type, reg_count) \ +impl_type all_ ## type ## s[reg_count + 1]; + +#define CONSTANT_REGISTER_DECLARATION(type, name, value) \ +constexpr type name = as_ ## type(value); + +#endif // USE_POINTERS_TO_REGISTER_IMPL_ARRAY + + +#define REGISTER_DECLARATION(type, name, value) \ const type name = ((type)value) + +// For definitions of RegisterImpl* instances. To be redefined in an +// OS-specific way. +#ifdef __GNUC__ +#define INTERNAL_VISIBILITY __attribute__ ((visibility ("internal"))) +#else +#define INTERNAL_VISIBILITY +#endif + + #define REGISTER_DEFINITION(type, name) #include CPU_HEADER(register) -- GitLab From 9eb50a5ee4a069fbb248748ebee09132e2450420 Mon Sep 17 00:00:00 2001 From: Andrey Turbanov Date: Tue, 18 Jan 2022 15:49:03 +0000 Subject: [PATCH 150/564] 8280010: Remove double buffering of InputStream for Properties.load Reviewed-by: amenkov, sspitsyn, serb --- .../share/classes/java/security/Security.java | 13 ++++++------- .../share/classes/sun/net/NetProperties.java | 5 ++--- .../share/classes/sun/net/www/MimeTable.java | 4 ++-- .../share/classes/sun/print/PSPrinterJob.java | 6 ++---- .../share/classes/java/util/logging/LogManager.java | 8 +++----- .../internal/functions/FuncSystemProperty.java | 7 ++----- .../share/classes/jdk/internal/agent/Agent.java | 3 +-- .../management/jmxremote/ConnectorBootstrap.java | 3 +-- 8 files changed, 19 insertions(+), 30 deletions(-) diff --git a/src/java.base/share/classes/java/security/Security.java b/src/java.base/share/classes/java/security/Security.java index 2ee706c2448..352dc5e7fac 100644 --- a/src/java.base/share/classes/java/security/Security.java +++ b/src/java.base/share/classes/java/security/Security.java @@ -91,8 +91,7 @@ public final class Security { if (propFile.exists()) { InputStream is = null; try { - FileInputStream fis = new FileInputStream(propFile); - is = new BufferedInputStream(fis); + is = new FileInputStream(propFile); props.load(is); loadedProps = true; @@ -140,7 +139,7 @@ public final class Security { // now load the user-specified file so its values // will win if they conflict with the earlier values if (extraPropFile != null) { - BufferedInputStream bis = null; + InputStream is = null; try { URL propURL; @@ -152,8 +151,8 @@ public final class Security { } else { propURL = new URL(extraPropFile); } - bis = new BufferedInputStream(propURL.openStream()); - props.load(bis); + is = propURL.openStream(); + props.load(is); loadedProps = true; if (sdebug != null) { @@ -172,9 +171,9 @@ public final class Security { e.printStackTrace(); } } finally { - if (bis != null) { + if (is != null) { try { - bis.close(); + is.close(); } catch (IOException ioe) { if (sdebug != null) { sdebug.println("unable to close input stream"); diff --git a/src/java.base/share/classes/sun/net/NetProperties.java b/src/java.base/share/classes/sun/net/NetProperties.java index 34c50404eda..d3f0bd4905b 100644 --- a/src/java.base/share/classes/sun/net/NetProperties.java +++ b/src/java.base/share/classes/sun/net/NetProperties.java @@ -68,9 +68,8 @@ public class NetProperties { File f = new File(fname, "conf"); f = new File(f, "net.properties"); fname = f.getCanonicalPath(); - try (FileInputStream in = new FileInputStream(fname); - BufferedInputStream bin = new BufferedInputStream(in)) { - props.load(bin); + try (FileInputStream in = new FileInputStream(fname)) { + props.load(in); } } catch (Exception e) { // Do nothing. We couldn't find or access the file diff --git a/src/java.base/share/classes/sun/net/www/MimeTable.java b/src/java.base/share/classes/sun/net/www/MimeTable.java index 08590b3a9e0..14149a637b3 100644 --- a/src/java.base/share/classes/sun/net/www/MimeTable.java +++ b/src/java.base/share/classes/sun/net/www/MimeTable.java @@ -244,8 +244,8 @@ public class MimeTable implements FileNameMap { throw new InternalError("default mime table not found"); } - try (BufferedInputStream bin = new BufferedInputStream(in)) { - entries.load(bin); + try (in) { + entries.load(in); } catch (IOException e) { System.err.println("Warning: " + e.getMessage()); } diff --git a/src/java.desktop/share/classes/sun/print/PSPrinterJob.java b/src/java.desktop/share/classes/sun/print/PSPrinterJob.java index e0252aad226..61450e49553 100644 --- a/src/java.desktop/share/classes/sun/print/PSPrinterJob.java +++ b/src/java.desktop/share/classes/sun/print/PSPrinterJob.java @@ -394,10 +394,8 @@ public class PSPrinterJob extends RasterPrinterJob { // Load property file Properties props = new Properties(); - try (FileInputStream is = new FileInputStream(f.getPath()); - BufferedInputStream bis = new BufferedInputStream(is)) - { - props.load(bis); + try (FileInputStream in = new FileInputStream(f.getPath())) { + props.load(in); } return props; } catch (Exception e){ diff --git a/src/java.logging/share/classes/java/util/logging/LogManager.java b/src/java.logging/share/classes/java/util/logging/LogManager.java index a6d11b64517..59950865283 100644 --- a/src/java.logging/share/classes/java/util/logging/LogManager.java +++ b/src/java.logging/share/classes/java/util/logging/LogManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2022, 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 @@ -1381,8 +1381,7 @@ public class LogManager { String fname = getConfigurationFileName(); try (final InputStream in = new FileInputStream(fname)) { - final BufferedInputStream bin = new BufferedInputStream(in); - readConfiguration(bin); + readConfiguration(in); } } @@ -1877,8 +1876,7 @@ public class LogManager { String fname = getConfigurationFileName(); try (final InputStream in = new FileInputStream(fname)) { - final BufferedInputStream bin = new BufferedInputStream(in); - updateConfiguration(bin, mapper); + updateConfiguration(in, mapper); } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/functions/FuncSystemProperty.java b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/functions/FuncSystemProperty.java index bad9cf1a311..819faa61b9c 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/functions/FuncSystemProperty.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/functions/FuncSystemProperty.java @@ -164,11 +164,8 @@ public class FuncSystemProperty extends FunctionOneArg try { // Use SecuritySupport class to provide privileged access to property file - InputStream is = SecuritySupport.getResourceAsStream(XSLT_PROPERTIES); - - // get a buffered version - try (BufferedInputStream bis = new BufferedInputStream(is)) { - target.load(bis); // and load up the property bag from this + try (InputStream is = SecuritySupport.getResourceAsStream(XSLT_PROPERTIES)) { + target.load(is); // and load up the property bag from this } } catch (Exception ex) diff --git a/src/jdk.management.agent/share/classes/jdk/internal/agent/Agent.java b/src/jdk.management.agent/share/classes/jdk/internal/agent/Agent.java index 06856f97278..2d261bfb3a7 100644 --- a/src/jdk.management.agent/share/classes/jdk/internal/agent/Agent.java +++ b/src/jdk.management.agent/share/classes/jdk/internal/agent/Agent.java @@ -564,8 +564,7 @@ public class Agent { InputStream in = null; try { in = new FileInputStream(configFile); - BufferedInputStream bin = new BufferedInputStream(in); - p.load(bin); + p.load(in); } catch (FileNotFoundException e) { error(CONFIG_FILE_OPEN_FAILED, e.getMessage()); } catch (IOException e) { diff --git a/src/jdk.management.agent/share/classes/sun/management/jmxremote/ConnectorBootstrap.java b/src/jdk.management.agent/share/classes/sun/management/jmxremote/ConnectorBootstrap.java index 6630124f374..aaa32944ddf 100644 --- a/src/jdk.management.agent/share/classes/sun/management/jmxremote/ConnectorBootstrap.java +++ b/src/jdk.management.agent/share/classes/sun/management/jmxremote/ConnectorBootstrap.java @@ -692,8 +692,7 @@ public final class ConnectorBootstrap { // Load the SSL keystore properties from the config file Properties p = new Properties(); try (InputStream in = new FileInputStream(sslConfigFileName)) { - BufferedInputStream bin = new BufferedInputStream(in); - p.load(bin); + p.load(in); } String keyStore = p.getProperty("javax.net.ssl.keyStore"); -- GitLab From 9e3f68d8f41ff632ebf28a6f488f6a06754a088f Mon Sep 17 00:00:00 2001 From: Vicente Romero Date: Tue, 18 Jan 2022 15:50:22 +0000 Subject: [PATCH 151/564] 8279290: symbol not found error, implicit lambdas and diamond constructor invocations Reviewed-by: jlahoda --- .../com/sun/tools/javac/comp/Attr.java | 3 +- ...indSymbolImplicitLambdaAndDiamondTest.java | 54 +++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 test/langtools/tools/javac/lambda/CantFindSymbolImplicitLambdaAndDiamondTest.java diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java index ae489536ec4..230539f6e0e 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java @@ -2922,6 +2922,7 @@ public class Attr extends JCTree.Visitor { && ((tree.constructorType != null && inferenceContext.free(tree.constructorType)) || (tree.clazz.type != null && inferenceContext.free(tree.clazz.type)))) { final ResultInfo resultInfoForClassDefinition = this.resultInfo; + Env dupLocalEnv = localEnv.dup(localEnv.tree, localEnv.info.dup(localEnv.info.scope.dupUnshared())); inferenceContext.addFreeTypeListener(List.of(tree.constructorType, tree.clazz.type), instantiatedContext -> { tree.constructorType = instantiatedContext.asInstType(tree.constructorType); @@ -2930,7 +2931,7 @@ public class Attr extends JCTree.Visitor { try { this.resultInfo = resultInfoForClassDefinition; visitAnonymousClassDefinition(tree, clazz, clazz.type, cdef, - localEnv, argtypes, typeargtypes, pkind); + dupLocalEnv, argtypes, typeargtypes, pkind); } finally { this.resultInfo = prevResult; } diff --git a/test/langtools/tools/javac/lambda/CantFindSymbolImplicitLambdaAndDiamondTest.java b/test/langtools/tools/javac/lambda/CantFindSymbolImplicitLambdaAndDiamondTest.java new file mode 100644 index 00000000000..a053d7f27ab --- /dev/null +++ b/test/langtools/tools/javac/lambda/CantFindSymbolImplicitLambdaAndDiamondTest.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2022, 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 + * @summary symbol not found error, implicit lambdas and diamond constructor invocations + * @compile CantFindSymbolImplicitLambdaAndDiamondTest.java + */ + +import java.util.function.Consumer; + +class CantFindSymbolImplicitLambdaAndDiamondTest { + static class B{} + + static class A1 { + A1(Consumer cons) {} + } + + static class A2 { + A2(Consumer cons) {} + } + + public void mount() { + new A1(inHours -> + new B<>() {{ + System.out.println(inHours); + }}); + + new A2<>(inHours -> + new B<>() {{ + System.out.println(inHours); + }}); + } +} -- GitLab From 88a8b239aa9fbda3705c39dca7a102a19fc57659 Mon Sep 17 00:00:00 2001 From: Nils Eliasson Date: Tue, 18 Jan 2022 16:48:37 +0000 Subject: [PATCH 152/564] 8280076: Unify IGV and IR printing Reviewed-by: chagedorn, thartmann, vlivanov --- .../share/compiler/compilerDirectives.hpp | 1 + src/hotspot/share/compiler/compilerOracle.hpp | 3 +- src/hotspot/share/opto/c2_globals.hpp | 5 ++ src/hotspot/share/opto/compile.cpp | 69 +++++++++++-------- src/hotspot/share/opto/compile.hpp | 11 +-- src/hotspot/share/opto/idealGraphPrinter.cpp | 2 +- src/hotspot/share/opto/parse2.cpp | 4 +- 7 files changed, 56 insertions(+), 39 deletions(-) diff --git a/src/hotspot/share/compiler/compilerDirectives.hpp b/src/hotspot/share/compiler/compilerDirectives.hpp index d51aa28e28c..7daa034a8d0 100644 --- a/src/hotspot/share/compiler/compilerDirectives.hpp +++ b/src/hotspot/share/compiler/compilerDirectives.hpp @@ -67,6 +67,7 @@ NOT_PRODUCT(cflags(TraceOptoPipelining, bool, TraceOptoPipelining, TraceOptoPipelining)) \ NOT_PRODUCT(cflags(TraceOptoOutput, bool, TraceOptoOutput, TraceOptoOutput)) \ NOT_PRODUCT(cflags(PrintIdeal, bool, PrintIdeal, PrintIdeal)) \ +NOT_PRODUCT(cflags(PrintIdealLevel, uintx, PrintIdealLevel, PrintIdealLevel)) \ cflags(TraceSpilling, bool, TraceSpilling, TraceSpilling) \ cflags(Vectorize, bool, false, Vectorize) \ cflags(CloneMapDebug, bool, false, CloneMapDebug) \ diff --git a/src/hotspot/share/compiler/compilerOracle.hpp b/src/hotspot/share/compiler/compilerOracle.hpp index 858e5c79406..e5be64cbdd4 100644 --- a/src/hotspot/share/compiler/compilerOracle.hpp +++ b/src/hotspot/share/compiler/compilerOracle.hpp @@ -79,7 +79,8 @@ class methodHandle; option(TraceOptoPipelining, "TraceOptoPipelining", Bool) \ option(TraceOptoOutput, "TraceOptoOutput", Bool) \ option(TraceSpilling, "TraceSpilling", Bool) \ - option(PrintIdeal, "PrintIdeal", Bool) \ + option(PrintIdeal, "PrintIdeal", Bool) \ + option(PrintIdealLevel, "PrintIdealLevel", Uintx) \ option(IGVPrintLevel, "IGVPrintLevel", Intx) \ option(Vectorize, "Vectorize", Bool) \ option(VectorizeDebug, "VectorizeDebug", Uintx) \ diff --git a/src/hotspot/share/opto/c2_globals.hpp b/src/hotspot/share/opto/c2_globals.hpp index cc6d1d762da..0fcc3e92aff 100644 --- a/src/hotspot/share/opto/c2_globals.hpp +++ b/src/hotspot/share/opto/c2_globals.hpp @@ -112,6 +112,11 @@ notproduct(bool, PrintIdeal, false, \ "Print ideal graph before code generation") \ \ + notproduct(uintx, PrintIdealLevel, 0, \ + "Print ideal IR on stdout. " \ + "Same levels as PrintIdealGraphLevel") \ + range(0, 4) \ + \ notproduct(uintx, PrintIdealIndentThreshold, 0, \ "A depth threshold of ideal graph. Indentation is disabled " \ "when users attempt to dump an ideal graph deeper than it.") \ diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index 1f1b438f796..b0a2b3241e7 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -535,6 +535,26 @@ void Compile::print_compile_messages() { #endif } +#ifndef PRODUCT +void Compile::print_ideal_ir(const char* phase_name) { + ttyLocker ttyl; + // keep the following output all in one block + // This output goes directly to the tty, not the compiler log. + // To enable tools to match it up with the compilation activity, + // be sure to tag this tty output with the compile ID. + if (xtty != NULL) { + xtty->head("ideal compile_id='%d'%s compile_phase='%s'", + compile_id(), + is_osr_compilation() ? " compile_kind='osr'" : "", + phase_name); + } + root()->dump(9999); + if (xtty != NULL) { + xtty->tail("ideal"); + } +} +#endif + // ============================================================================ //------------------------------Compile standard------------------------------- debug_only( int Compile::_debug_idx = 100000; ) @@ -563,7 +583,6 @@ Compile::Compile( ciEnv* ci_env, ciMethod* target, int osr_bci, #ifndef PRODUCT _igv_idx(0), _trace_opto_output(directive->TraceOptoOutputOption), - _print_ideal(directive->PrintIdealOption), #endif _has_method_handle_invokes(false), _clinit_barrier_on_entry(false), @@ -582,7 +601,7 @@ Compile::Compile( ciEnv* ci_env, ciMethod* target, int osr_bci, _for_post_loop_igvn(comp_arena(), 8, 0, NULL), _coarsened_locks (comp_arena(), 8, 0, NULL), _congraph(NULL), - NOT_PRODUCT(_printer(NULL) COMMA) + NOT_PRODUCT(_igv_printer(NULL) COMMA) _dead_node_list(comp_arena()), _dead_node_count(0), _node_arena(mtCompiler), @@ -764,8 +783,8 @@ Compile::Compile( ciEnv* ci_env, ciMethod* target, int osr_bci, set_default_node_notes(NULL); #ifndef PRODUCT - if (should_print(1)) { - _printer->print_inlining(); + if (should_print_igv(1)) { + _igv_printer->print_inlining(); } #endif @@ -792,20 +811,8 @@ Compile::Compile( ciEnv* ci_env, ciMethod* target, int osr_bci, NOT_PRODUCT( verify_graph_edges(); ) #ifndef PRODUCT - if (print_ideal()) { - ttyLocker ttyl; // keep the following output all in one block - // This output goes directly to the tty, not the compiler log. - // To enable tools to match it up with the compilation activity, - // be sure to tag this tty output with the compile ID. - if (xtty != NULL) { - xtty->head("ideal compile_id='%d'%s", compile_id(), - is_osr_compilation() ? " compile_kind='osr'" : - ""); - } - root()->dump(9999); - if (xtty != NULL) { - xtty->tail("ideal"); - } + if (should_print_ideal()) { + print_ideal_ir("print_ideal"); } #endif @@ -861,7 +868,6 @@ Compile::Compile( ciEnv* ci_env, #ifndef PRODUCT _igv_idx(0), _trace_opto_output(directive->TraceOptoOutputOption), - _print_ideal(directive->PrintIdealOption), #endif _has_method_handle_invokes(false), _clinit_barrier_on_entry(false), @@ -873,7 +879,7 @@ Compile::Compile( ciEnv* ci_env, _log(ci_env->log()), _failure_reason(NULL), _congraph(NULL), - NOT_PRODUCT(_printer(NULL) COMMA) + NOT_PRODUCT(_igv_printer(NULL) COMMA) _dead_node_list(comp_arena()), _dead_node_count(0), _node_arena(mtCompiler), @@ -4830,8 +4836,11 @@ void Compile::print_method_impl(CompilerPhaseType cpt, const char *name, int lev CompilerEvent::PhaseEvent::post(event, C->_latest_stage_start_counter, cpt, C->_compile_id, level); } #ifndef PRODUCT - if (should_print(level)) { - _printer->print_method(name, level); + if (should_print_igv(level)) { + _igv_printer->print_method(name, level); + } + if (should_print_ideal(level)) { + print_ideal_ir(name); } #endif C->_latest_stage_start_counter.stamp(); @@ -4840,8 +4849,8 @@ void Compile::print_method_impl(CompilerPhaseType cpt, const char *name, int lev // Only used from CompileWrapper void Compile::begin_method() { #ifndef PRODUCT - if (_method != NULL && should_print(1)) { - _printer->begin_method(); + if (_method != NULL && should_print_igv(1)) { + _igv_printer->begin_method(); } #endif C->_latest_stage_start_counter.stamp(); @@ -4855,22 +4864,22 @@ void Compile::end_method() { } #ifndef PRODUCT - if (_method != NULL && should_print(1)) { - _printer->end_method(); + if (_method != NULL && should_print_igv(1)) { + _igv_printer->end_method(); } #endif } -bool Compile::should_print(int level) { +bool Compile::should_print_igv(int level) { #ifndef PRODUCT if (PrintIdealGraphLevel < 0) { // disabled by the user return false; } bool need = directive()->IGVPrintLevelOption >= level; - if (need && _printer == nullptr) { - _printer = IdealGraphPrinter::printer(); - _printer->set_compile(this); + if (need && !_igv_printer) { + _igv_printer = IdealGraphPrinter::printer(); + _igv_printer->set_compile(this); } return need; #else diff --git a/src/hotspot/share/opto/compile.hpp b/src/hotspot/share/opto/compile.hpp index 0e6355715d4..9b2fd80b589 100644 --- a/src/hotspot/share/opto/compile.hpp +++ b/src/hotspot/share/opto/compile.hpp @@ -327,7 +327,6 @@ class Compile : public Phase { #ifndef PRODUCT uint _igv_idx; // Counter for IGV node identifiers bool _trace_opto_output; - bool _print_ideal; bool _parsed_irreducible_loop; // True if ciTypeFlow detected irreducible loops during parsing #endif bool _has_irreducible_loop; // Found irreducible loops @@ -354,7 +353,7 @@ class Compile : public Phase { GrowableArray _coarsened_locks; // List of coarsened Lock and Unlock nodes ConnectionGraph* _congraph; #ifndef PRODUCT - IdealGraphPrinter* _printer; + IdealGraphPrinter* _igv_printer; static IdealGraphPrinter* _debug_file_printer; static IdealGraphPrinter* _debug_network_printer; #endif @@ -489,7 +488,7 @@ class Compile : public Phase { } #ifndef PRODUCT - IdealGraphPrinter* printer() { return _printer; } + IdealGraphPrinter* igv_printer() { return _igv_printer; } #endif void log_late_inline(CallGenerator* cg); @@ -636,7 +635,9 @@ class Compile : public Phase { #ifndef PRODUCT uint next_igv_idx() { return _igv_idx++; } bool trace_opto_output() const { return _trace_opto_output; } - bool print_ideal() const { return _print_ideal; } + void print_ideal_ir(const char* phase_name); + bool should_print_ideal() const { return _directive->PrintIdealOption; } + bool should_print_ideal(uint level) const { return _directive->PrintIdealLevelOption >= level; } bool parsed_irreducible_loop() const { return _parsed_irreducible_loop; } void set_parsed_irreducible_loop(bool z) { _parsed_irreducible_loop = z; } int _in_dump_cnt; // Required for dumping ir nodes. @@ -652,7 +653,7 @@ class Compile : public Phase { void begin_method(); void end_method(); - bool should_print(int level); + bool should_print_igv(int level); void print_method(CompilerPhaseType cpt, int level); void print_method(CompilerPhaseType cpt, Node* n, int level = 3); diff --git a/src/hotspot/share/opto/idealGraphPrinter.cpp b/src/hotspot/share/opto/idealGraphPrinter.cpp index 1aeea01c9c0..b5d1759dc43 100644 --- a/src/hotspot/share/opto/idealGraphPrinter.cpp +++ b/src/hotspot/share/opto/idealGraphPrinter.cpp @@ -762,7 +762,7 @@ void IdealGraphPrinter::walk_nodes(Node* start, bool edges, VectorSet* temp_set) } void IdealGraphPrinter::print_method(const char *name, int level) { - if (C->should_print(level)) { + if (C->should_print_igv(level)) { print(name, (Node *) C->root()); } } diff --git a/src/hotspot/share/opto/parse2.cpp b/src/hotspot/share/opto/parse2.cpp index e461d3ee978..183994ecb0d 100644 --- a/src/hotspot/share/opto/parse2.cpp +++ b/src/hotspot/share/opto/parse2.cpp @@ -2752,8 +2752,8 @@ void Parse::do_one_bytecode() { } #ifndef PRODUCT - if (C->should_print(1)) { - IdealGraphPrinter* printer = C->printer(); + if (C->should_print_igv(1)) { + IdealGraphPrinter* printer = C->igv_printer(); char buffer[256]; jio_snprintf(buffer, sizeof(buffer), "Bytecode %d: %s", bci(), Bytecodes::name(bc())); bool old = printer->traverse_outs(); -- GitLab From bd35f9740dce8865b9a8cdb582c771279ab02d76 Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Tue, 18 Jan 2022 16:55:06 +0000 Subject: [PATCH 153/564] 8278628: jdk/jfr/jmx/streaming/TestMaxSize.java Expected only one or two chunks Reviewed-by: mgronlun --- .../jdk/jfr/jmx/streaming/TestMaxSize.java | 32 ++++++++++++------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/test/jdk/jdk/jfr/jmx/streaming/TestMaxSize.java b/test/jdk/jdk/jfr/jmx/streaming/TestMaxSize.java index af7493212ca..7bf389c75ad 100644 --- a/test/jdk/jdk/jfr/jmx/streaming/TestMaxSize.java +++ b/test/jdk/jdk/jfr/jmx/streaming/TestMaxSize.java @@ -70,12 +70,17 @@ public class TestMaxSize { while (directorySize(dir) < 50_000_000) { emitEvents(500_000); } + System.out.println("Before setMaxSize(1_000_000)"); + fileCount(dir); e.setMaxSize(1_000_000); + System.out.println("After setMaxSize(1_000_000)"); long count = fileCount(dir); - if (count > 2) { - // Two chunks can happen when header of new chunk is written and previous - // chunk is not finalized. - throw new Exception("Expected only one or two chunks with setMaxSize(1_000_000). Found " + count); + if (count > 3) { + // Three files can happen when: + // File 1: Header of new chunk is written to disk + // File 2: Previous chunk is not yet finalized and added to list of DiskChunks + // File 3: Previous previous file is in the list of DiskChunks. + throw new Exception("Expected at most three chunks with setMaxSize(1_000_000). Found " + count); } finished.set(true); } @@ -94,21 +99,24 @@ public class TestMaxSize { System.out.println("Files:"); AtomicInteger count = new AtomicInteger(); Files.list(dir).forEach(p -> { - System.out.println(p); + System.out.println(p + " " + fileSize(p)); count.incrementAndGet(); }); return count.get(); } private static long directorySize(Path dir) throws IOException { - long p = Files.list(dir).mapToLong(f -> { - try { - return Files.size(f); - } catch (IOException e) { - return 0; - } - }).sum(); + long p = Files.list(dir).mapToLong(f -> fileSize(f)).sum(); System.out.println("Directory size: " + p); return p; } + + private static long fileSize(Path p) { + try { + return Files.size(p); + } catch (IOException e) { + System.out.println("Could not determine file size for " + p); + return 0; + } + } } -- GitLab From 7acc4c7dfe4b79e2bf1c993e84fd5fcd6855f292 Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Tue, 18 Jan 2022 17:14:42 +0000 Subject: [PATCH 154/564] 8280058: JFR: StreamUtils::getJfrRepository(Process) should print stdout and stderr Reviewed-by: mgronlun --- test/lib/jdk/test/lib/jfr/StreamingUtils.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/lib/jdk/test/lib/jfr/StreamingUtils.java b/test/lib/jdk/test/lib/jfr/StreamingUtils.java index 7461cfd0b63..427a4eb4262 100644 --- a/test/lib/jdk/test/lib/jfr/StreamingUtils.java +++ b/test/lib/jdk/test/lib/jfr/StreamingUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, 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 @@ -43,8 +43,10 @@ public class StreamingUtils { public static Path getJfrRepository(Process process) throws Exception { while (true) { if (!process.isAlive()) { - String msg = String.format("Process (pid = %d) is no longer alive, exit value = %d", + String msg = String.format("Process (pid = %d) is no longer alive, exit value = %d\n", process.pid(), process.exitValue()); + msg += "Stderr: " + new String(process.getErrorStream().readAllBytes()) + "\n"; + msg += "Stdout: " + new String(process.getInputStream().readAllBytes()) + "\n"; throw new RuntimeException(msg); } -- GitLab From b734dc86ee261ecb4a5fbf4db7b3d9905c94191f Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Tue, 18 Jan 2022 17:57:12 +0000 Subject: [PATCH 155/564] 8280055: JFR: Improve ObjectContext implementation Reviewed-by: mgronlun --- .../jdk/jfr/consumer/RecordedObject.java | 11 +---- .../jfr/internal/consumer/ObjectContext.java | 46 +++++++++++++------ 2 files changed, 32 insertions(+), 25 deletions(-) diff --git a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedObject.java b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedObject.java index a2d2976e125..d9def94ff8a 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedObject.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedObject.java @@ -150,16 +150,7 @@ public class RecordedObject { JdkJfrConsumer.setAccess(access); } - private static final class UnsignedValue { - private final Object o; - - UnsignedValue(Object o) { - this.o = o; - } - - Object value() { - return o; - } + private static final record UnsignedValue(Object value) { } final Object[] objects; diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ObjectContext.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ObjectContext.java index 3c946ba2097..e855d0212a2 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ObjectContext.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ObjectContext.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,8 @@ package jdk.jfr.internal.consumer; import java.time.ZoneId; -import java.util.HashMap; +import java.util.ArrayDeque; +import java.util.IdentityHashMap; import java.util.List; import java.util.Map; @@ -34,33 +35,48 @@ import jdk.jfr.EventType; import jdk.jfr.ValueDescriptor; public final class ObjectContext { - private final Map contextLookup; + private Map contextLookup; private final TimeConverter timeConverter; - public final EventType eventType; public final List fields; ObjectContext(EventType eventType, List fields, TimeConverter timeConverter) { - this.contextLookup = new HashMap<>(); this.eventType = eventType; this.fields = fields; this.timeConverter = timeConverter; } - private ObjectContext(ObjectContext parent, ValueDescriptor descriptor) { - this.eventType = parent.eventType; - this.contextLookup = parent.contextLookup; - this.timeConverter = parent.timeConverter; - this.fields = descriptor.getFields(); + private ObjectContext(Map contextLookup, EventType eventType, List fields, TimeConverter timeConverter) { + this.eventType = eventType; + this.contextLookup = contextLookup; + this.timeConverter = timeConverter; + this.fields = fields; } public ObjectContext getInstance(ValueDescriptor descriptor) { - ObjectContext context = contextLookup.get(descriptor); - if (context == null) { - context = new ObjectContext(this, descriptor); - contextLookup.put(descriptor, context); + if (contextLookup == null) { + // Lazy, only needed when accessing nested structures. + contextLookup = buildContextLookup(fields); + } + return contextLookup.get(descriptor); + } + + // Create mapping from ValueDescriptor to ObjectContext for all reachable + // ValueDescriptors. + public Map buildContextLookup(List fields) { + Map lookup = new IdentityHashMap<>(); + ArrayDeque q = new ArrayDeque<>(fields); + while (!q.isEmpty()) { + ValueDescriptor vd = q.pop(); + if (!lookup.containsKey(vd)) { + List children = vd.getFields(); + lookup.put(vd, new ObjectContext(lookup, eventType, children, timeConverter)); + for (ValueDescriptor v : children) { + q.add(v); + } + } } - return context; + return lookup; } public long convertTimestamp(long ticks) { -- GitLab From 848b16a3f933c1cffbce93337a5d9b4e48ce4b45 Mon Sep 17 00:00:00 2001 From: Masanori Yano Date: Tue, 18 Jan 2022 18:20:57 +0000 Subject: [PATCH 156/564] 8272746: ZipFile can't open big file (NegativeArraySizeException) Reviewed-by: lancea --- .../share/classes/java/util/zip/ZipFile.java | 3 + .../util/zip/ZipFile/TestTooManyEntries.java | 89 +++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 test/jdk/java/util/zip/ZipFile/TestTooManyEntries.java diff --git a/src/java.base/share/classes/java/util/zip/ZipFile.java b/src/java.base/share/classes/java/util/zip/ZipFile.java index c08281779ca..1e5e92e4370 100644 --- a/src/java.base/share/classes/java/util/zip/ZipFile.java +++ b/src/java.base/share/classes/java/util/zip/ZipFile.java @@ -1497,6 +1497,9 @@ public class ZipFile implements ZipConstants, Closeable { zerror("invalid END header (bad central directory offset)"); } // read in the CEN and END + if (end.cenlen + ENDHDR >= Integer.MAX_VALUE) { + zerror("invalid END header (central directory size too large)"); + } cen = this.cen = new byte[(int)(end.cenlen + ENDHDR)]; if (readFullyAt(cen, 0, cen.length, cenpos) != end.cenlen + ENDHDR) { zerror("read CEN tables failed"); diff --git a/test/jdk/java/util/zip/ZipFile/TestTooManyEntries.java b/test/jdk/java/util/zip/ZipFile/TestTooManyEntries.java new file mode 100644 index 00000000000..07ed760c1b7 --- /dev/null +++ b/test/jdk/java/util/zip/ZipFile/TestTooManyEntries.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2022, 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 8272746 + * @summary ZipFile can't open big file (NegativeArraySizeException) + * @requires (sun.arch.data.model == "64" & os.maxMemory > 8g) + * @run testng/manual/othervm -Xmx8g TestTooManyEntries + */ + +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import java.io.File; +import java.io.BufferedOutputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.zip.ZipEntry; +import java.util.zip.ZipException; +import java.util.zip.ZipFile; +import java.util.zip.ZipOutputStream; +import java.util.UUID; + +import static org.testng.Assert.assertThrows; + +public class TestTooManyEntries { + // Number of directories in the zip file + private static final int DIR_COUNT = 25000; + // Number of entries per directory + private static final int ENTRIES_IN_DIR = 1000; + + // Zip file to create for testing + private File hugeZipFile; + + /** + * Create a zip file and add entries that exceed the CEN limit. + * @throws IOException if an error occurs creating the ZIP File + */ + @BeforeTest + public void setup() throws IOException { + hugeZipFile = File.createTempFile("hugeZip", ".zip", new File(".")); + hugeZipFile.deleteOnExit(); + long startTime = System.currentTimeMillis(); + try (ZipOutputStream zip = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(hugeZipFile)))) { + for (int dirN = 0; dirN < DIR_COUNT; dirN++) { + String dirName = UUID.randomUUID() + "/"; + for (int fileN = 0; fileN < ENTRIES_IN_DIR; fileN++) { + ZipEntry entry = new ZipEntry(dirName + UUID.randomUUID()); + zip.putNextEntry(entry); + zip.closeEntry(); // all files are empty + } + if ((dirN + 1) % 1000 == 0) { + System.out.printf("%s / %s of entries written, file size is %sMb (%ss)%n", + (dirN + 1) * ENTRIES_IN_DIR, DIR_COUNT * ENTRIES_IN_DIR, hugeZipFile.length() / 1024 / 1024, + (System.currentTimeMillis() - startTime) / 1000); + } + } + } + } + + /** + * Validates that the ZipException is thrown when the ZipFile class + * is initialized with a zip file whose entries exceed the CEN limit. + */ + @Test + public void test() { + assertThrows(ZipException.class, () -> new ZipFile(hugeZipFile)); + } +} -- GitLab From 20ef954158bc5a339118640946b39047fe853ae4 Mon Sep 17 00:00:00 2001 From: Aleksandr Veselov Date: Tue, 18 Jan 2022 18:51:58 +0000 Subject: [PATCH 157/564] 8279227: Access Bridge: Wrong frame position and hit test result on HiDPI display Reviewed-by: ant, kizune, aivanov --- .../accessibility/internal/AccessBridge.java | 185 ++++++++++++++++++ 1 file changed, 185 insertions(+) diff --git a/src/jdk.accessibility/windows/classes/com/sun/java/accessibility/internal/AccessBridge.java b/src/jdk.accessibility/windows/classes/com/sun/java/accessibility/internal/AccessBridge.java index 853be197754..e178e646d7d 100644 --- a/src/jdk.accessibility/windows/classes/com/sun/java/accessibility/internal/AccessBridge.java +++ b/src/jdk.accessibility/windows/classes/com/sun/java/accessibility/internal/AccessBridge.java @@ -27,6 +27,7 @@ package com.sun.java.accessibility.internal; import java.awt.*; import java.awt.event.*; +import java.awt.geom.AffineTransform; import java.util.*; import java.lang.*; import java.lang.reflect.*; @@ -478,6 +479,9 @@ public final class AccessBridge { if (parent == null) { return null; } + Point userSpaceXY = AccessibilityGraphicsEnvironment.toUserSpace(x, y); + x = userSpaceXY.x; + y = userSpaceXY.y; if (windowHandleToContextMap != null && windowHandleToContextMap.containsValue(getRootAccessibleContext(parent))) { // Path for applications that register their top-level @@ -1593,6 +1597,8 @@ public final class AccessBridge { if (p != null) { r.x = p.x; r.y = p.y; + + r = AccessibilityGraphicsEnvironment.toDeviceSpaceAbs(r); return r; } } catch (Exception e) { @@ -2257,6 +2263,7 @@ public final class AccessBridge { if (s != null && s.equals("\n")) { rect.width = 0; } + rect = AccessibilityGraphicsEnvironment.toDeviceSpaceAbs(rect); return rect; } } @@ -7338,4 +7345,182 @@ public final class AccessBridge { } } } + + /** + * A helper class to handle coordinate conversion between screen and user spaces. + * See {@link sun.java2d.SunGraphicsEnvironment} + */ + private static abstract class AccessibilityGraphicsEnvironment extends GraphicsEnvironment { + /** + * Returns the graphics configuration which bounds contain the given point in the user's space. + * + * See {@link sun.java2d.SunGraphicsEnvironment#getGraphicsConfigurationAtPoint(GraphicsConfiguration, double, double)} + * + * @param x the x coordinate of the given point in the user's space + * @param y the y coordinate of the given point in the user's space + * @return the graphics configuration + */ + public static GraphicsConfiguration getGraphicsConfigurationAtPoint(double x, double y) { + GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment() + .getDefaultScreenDevice().getDefaultConfiguration(); + return getGraphicsConfigurationAtPoint(gc, x, y); + } + + /** + * Returns the graphics configuration which bounds contain the given point in the user's space. + * + * See {@link sun.java2d.SunGraphicsEnvironment#getGraphicsConfigurationAtPoint(GraphicsConfiguration, double, double)} + * + * @param current the default configuration which is checked in the first + * place + * @param x the x coordinate of the given point in the user's space + * @param y the y coordinate of the given point in the user's space + * @return the graphics configuration + */ + public static GraphicsConfiguration getGraphicsConfigurationAtPoint( + GraphicsConfiguration current, double x, double y) { + if (containsUserSpacePoint(current, x, y)) { + return current; + } + GraphicsEnvironment env = getLocalGraphicsEnvironment(); + for (GraphicsDevice device : env.getScreenDevices()) { + GraphicsConfiguration config = device.getDefaultConfiguration(); + if (containsUserSpacePoint(config, x, y)) { + return config; + } + } + return current; + } + + /** + * Returns the graphics configuration which bounds contain the given point in the device space. + * + * @param x the x coordinate of the given point in the device space + * @param y the y coordinate of the given point in the device space + * @return the graphics configuration + */ + public static GraphicsConfiguration getGraphicsConfigurationAtDevicePoint(double x, double y) { + GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment() + .getDefaultScreenDevice().getDefaultConfiguration(); + return getGraphicsConfigurationAtDevicePoint(gc, x, y); + } + + /** + * Returns the graphics configuration which bounds contain the given point in the device space. + * + * @param current the default configuration which is checked in the first + * place + * @param x the x coordinate of the given point in the device space + * @param y the y coordinate of the given point in the device space + * @return the graphics configuration + */ + public static GraphicsConfiguration getGraphicsConfigurationAtDevicePoint( + GraphicsConfiguration current, double x, double y) { + if (containsDeviceSpacePoint(current, x, y)) { + return current; + } + GraphicsEnvironment env = getLocalGraphicsEnvironment(); + for (GraphicsDevice device : env.getScreenDevices()) { + GraphicsConfiguration config = device.getDefaultConfiguration(); + if (containsDeviceSpacePoint(config, x, y)) { + return config; + } + } + return current; + } + + private static boolean containsDeviceSpacePoint(GraphicsConfiguration config, double x, double y) { + Rectangle bounds = config.getBounds(); + bounds = toDeviceSpaceAbs(config, bounds.x, bounds.y, bounds.width, bounds.height); + return bounds.contains(x, y); + } + + private static boolean containsUserSpacePoint(GraphicsConfiguration config, double x, double y) { + Rectangle bounds = config.getBounds(); + return bounds.contains(x, y); + } + + /** + * Converts absolute coordinates from the device + * space to the user's space space using appropriate device transformation. + * + * @param x absolute x coordinate in the device's space + * @param y absolute y coordinate in the device's space + * @return the corresponding coordinates in user's space + */ + public static Point toUserSpace(int x, int y) { + GraphicsConfiguration gc = getGraphicsConfigurationAtDevicePoint(x, y); + return toUserSpace(gc, x, y); + } + + /** + * Converts absolute coordinates from the device + * space to the user's space using passed graphics configuration. + * + * @param gc the graphics configuration to be used for transformation + * @param x absolute x coordinate in the device's space + * @param y absolute y coordinate in the device's space + * @return the corresponding coordinates in user's space + */ + public static Point toUserSpace(GraphicsConfiguration gc, int x, int y) { + AffineTransform tx = gc.getDefaultTransform(); + Rectangle screen = gc.getBounds(); + int userX = screen.x + clipRound((x - screen.x) / tx.getScaleX()); + int userY = screen.y + clipRound((y - screen.y) / tx.getScaleY()); + return new Point(userX, userY); + } + + /** + * Converts the rectangle from the user's space to the device space using + * appropriate device transformation. + * + * See {@link sun.java2d.SunGraphicsEnvironment#toDeviceSpaceAbs(Rectangle)} + * + * @param rect the rectangle in the user's space + * @return the rectangle which uses device space (pixels) + */ + public static Rectangle toDeviceSpaceAbs(Rectangle rect) { + GraphicsConfiguration gc = getGraphicsConfigurationAtPoint(rect.x, rect.y); + return toDeviceSpaceAbs(gc, rect.x, rect.y, rect.width, rect.height); + } + + /** + * Converts absolute coordinates (x, y) and the size (w, h) from the user's + * space to the device space using passed graphics configuration. + * + * See {@link sun.java2d.SunGraphicsEnvironment#toDeviceSpaceAbs(GraphicsConfiguration, int, int, int, int)} + * + * @param gc the graphics configuration to be used for transformation + * @param x absolute coordinate in the user's space + * @param y absolute coordinate in the user's space + * @param w the width in the user's space + * @param h the height in the user's space + * @return the rectangle which uses device space (pixels) + */ + public static Rectangle toDeviceSpaceAbs(GraphicsConfiguration gc, + int x, int y, int w, int h) { + AffineTransform tx = gc.getDefaultTransform(); + Rectangle screen = gc.getBounds(); + return new Rectangle( + screen.x + clipRound((x - screen.x) * tx.getScaleX()), + screen.y + clipRound((y - screen.y) * tx.getScaleY()), + clipRound(w * tx.getScaleX()), + clipRound(h * tx.getScaleY()) + ); + } + + /** + * See {@link sun.java2d.pipe.Region#clipRound} + */ + private static int clipRound(final double coordinate) { + final double newv = coordinate - 0.5; + if (newv < Integer.MIN_VALUE) { + return Integer.MIN_VALUE; + } + if (newv > Integer.MAX_VALUE) { + return Integer.MAX_VALUE; + } + return (int) Math.ceil(newv); + } + } } -- GitLab From fd9fb9a4af149177c2a8d6ab20782d7a0b5bc113 Mon Sep 17 00:00:00 2001 From: Chris Plummer Date: Tue, 18 Jan 2022 19:20:20 +0000 Subject: [PATCH 158/564] 8279194: Add Annotated Memory Viewer feature to SA's HSDB Reviewed-by: sspitsyn, ysuenaga --- .../share/classes/sun/jvm/hotspot/HSDB.java | 17 +++- .../sun/jvm/hotspot/ui/MemoryPanel.java | 78 +++++++++++++++---- .../sun/jvm/hotspot/ui/MemoryViewer.java | 6 +- 3 files changed, 82 insertions(+), 19 deletions(-) diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/HSDB.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/HSDB.java index c530cb67b35..4baa00fc000 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/HSDB.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/HSDB.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2022, 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 @@ -337,6 +337,15 @@ public class HSDB implements ObjectHistogramPanel.Listener, SAListener { item.setMnemonic(KeyEvent.VK_M); toolsMenu.add(item); + item = createMenuItem("Annotated Memory Viewer", + new ActionListener() { + public void actionPerformed(ActionEvent e) { + showAnnotatedMemoryViewer(); + } + }); + item.setMnemonic(KeyEvent.VK_W); + toolsMenu.add(item); + item = createMenuItem("Monitor Cache Dump", new ActionListener() { public void actionPerformed(ActionEvent e) { @@ -1611,7 +1620,11 @@ public class HSDB implements ObjectHistogramPanel.Listener, SAListener { } public void showMemoryViewer() { - showPanel("Memory Viewer", new MemoryViewer(agent.getDebugger(), agent.getTypeDataBase().getAddressSize() == 8)); + showPanel("Memory Viewer", new MemoryViewer(agent.getDebugger(), false, agent.getTypeDataBase().getAddressSize() == 8)); + } + + public void showAnnotatedMemoryViewer() { + showPanel("Annotated Memory Viewer", new MemoryViewer(agent.getDebugger(), true, agent.getTypeDataBase().getAddressSize() == 8)); } public void showCommandLineFlags() { diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/MemoryPanel.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/MemoryPanel.java index 20408f4add4..76522a6676c 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/MemoryPanel.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/MemoryPanel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,9 @@ package sun.jvm.hotspot.ui; import java.awt.*; import java.awt.datatransfer.*; import java.awt.event.*; +import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.PrintStream; import java.math.*; import java.util.*; import javax.swing.*; @@ -35,9 +37,12 @@ import javax.swing.event.*; import javax.swing.table.*; import sun.jvm.hotspot.debugger.*; import sun.jvm.hotspot.ui.*; +import sun.jvm.hotspot.utilities.PointerFinder; +import sun.jvm.hotspot.utilities.PointerLocation; public class MemoryPanel extends JPanel { private boolean is64Bit; + private boolean isAnnotated; private Debugger debugger; private int addressSize; private String unmappedAddrString; @@ -78,10 +83,11 @@ public class MemoryPanel extends JPanel { } } - public MemoryPanel(final Debugger debugger, boolean is64Bit) { + public MemoryPanel(final Debugger debugger, boolean isAnnotated, boolean is64Bit) { super(); this.debugger = debugger; this.is64Bit = is64Bit; + this.isAnnotated = isAnnotated; if (is64Bit) { addressSize = 8; unmappedAddrString = "??????????????????"; @@ -98,23 +104,58 @@ public class MemoryPanel extends JPanel { return numVisibleRows; } public int getColumnCount() { - return 2; + return isAnnotated ? 1 : 2; } public Object getValueAt(int row, int column) { - switch (column) { - case 0: return bigIntToHexString(startVal.add(new BigInteger(Integer.toString((row * addressSize))))); - case 1: { - try { - Address addr = bigIntToAddress(startVal.add(new BigInteger(Integer.toString((row * addressSize))))); + // When not annotated, we just display the address followed by its contents in two + // separate columns. When annotated the format is just one column which contains: + //
    : + // For example: + // 0x00007f7eb010c330: 0x00007f7eb6c9dfb0 vtable for os::PlatformMonitor + 0x10 + if (!isAnnotated) { + switch (column) { + case 0: return bigIntToHexString(startVal.add(new BigInteger(Integer.toString((row * addressSize))))); + case 1: { + try { + Address addr = bigIntToAddress(startVal.add(new BigInteger(Integer.toString((row * addressSize))))); + if (addr != null) { + return addressToString(addr.getAddressAt(0)); + } + return unmappedAddrString; + } catch (UnmappedAddressException e) { + return unmappedAddrString; + } + } + default: throw new RuntimeException("Column " + column + " out of bounds"); + } + } else { + switch (column) { + case 0: { + BigInteger bigaddr = startVal.add(new BigInteger(Integer.toString((row * addressSize)))); + Address addr = bigIntToAddress(bigaddr); + + String col1 = bigIntToHexString(bigaddr); + String col2 = unmappedAddrString; + String col3 = ""; + if (addr != null) { - return addressToString(addr.getAddressAt(0)); + try { + col2 = addressToString(addr.getAddressAt(0)); + PointerLocation loc = PointerFinder.find(addr.getAddressAt(0)); + if (!loc.isUnknown()) { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + PrintStream tty = new PrintStream(bos); + loc.printOn(tty, false, false); + col3 = bos.toString(); + } + } catch (UnmappedAddressException e) { + } } - return unmappedAddrString; - } catch (UnmappedAddressException e) { - return unmappedAddrString; + + return col1 + ": " + col2 + " " + col3; + } + default: throw new RuntimeException("Column " + column + " out of bounds"); } - } - default: throw new RuntimeException("Column " + column + " out of bounds"); } } public boolean isCellEditable(int row, int col) { @@ -198,6 +239,15 @@ public class MemoryPanel extends JPanel { private void handleImport(JComponent c, String str) { // do whatever you want with the string here try { + // If someone drag-n-dropped a selection from the Annotated Memory Viewer, + // window, it will look like this: + // 0x00007f7eb010c330: 0x00007f7eb6c9dfb0 vtable for os::PlatformMonitor + 0x10 + // We need to grab the second address. + int secondAddrStartIndex = str.indexOf("0x", 2); + if (secondAddrStartIndex != -1) { + str = str.substring(secondAddrStartIndex); + str = str.split("\\s")[0]; + } makeVisible(debugger.parseAddress(str)); clearSelection(); table.clearSelection(); diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/MemoryViewer.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/MemoryViewer.java index f6193a37f16..e475292c29c 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/MemoryViewer.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/MemoryViewer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, 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 @@ -33,9 +33,9 @@ import sun.jvm.hotspot.debugger.*; address. */ public class MemoryViewer extends JPanel { - public MemoryViewer(final Debugger debugger, boolean is64Bit) { + public MemoryViewer(final Debugger debugger, boolean isAnnotated, boolean is64Bit) { super(); - final MemoryPanel memory = new MemoryPanel(debugger, is64Bit); + final MemoryPanel memory = new MemoryPanel(debugger, isAnnotated, is64Bit); memory.setBorder(GraphicsUtilities.newBorder(5)); JPanel addressPanel = new JPanel(); addressPanel.setLayout(new BoxLayout(addressPanel, BoxLayout.X_AXIS)); -- GitLab From bdfa15d92cb0e795d04431f82168644dee2da128 Mon Sep 17 00:00:00 2001 From: Chris Plummer Date: Tue, 18 Jan 2022 19:21:13 +0000 Subject: [PATCH 159/564] 8250801: Add clhsdb "threadcontext" command Reviewed-by: sspitsyn, kevinw --- .../sun/jvm/hotspot/CommandProcessor.java | 43 ++++++- .../sun/jvm/hotspot/runtime/JavaThread.java | 21 +++- .../sa/ClhsdbThreadContext.java | 108 ++++++++++++++++++ 3 files changed, 167 insertions(+), 5 deletions(-) create mode 100644 test/hotspot/jtreg/serviceability/sa/ClhsdbThreadContext.java diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/CommandProcessor.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/CommandProcessor.java index 085bc3d8799..7693a1493a0 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/CommandProcessor.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/CommandProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2022, 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 @@ -1671,19 +1671,54 @@ public class CommandProcessor { } } }, + new Command("threadcontext", "threadcontext [-v] { -a | id }", false) { + public void doit(Tokens t) { + boolean verbose = false; + if (t.countTokens() == 2) { + if (t.nextToken().equals("-v")) { + verbose = true; + } else { + usage(); + return; + } + } + if (t.countTokens() != 1) { + usage(); + return; + } + String id = t.nextToken(); + Threads threads = VM.getVM().getThreads(); + boolean all = id.equals("-a"); + for (int i = 0; i < threads.getNumberOfThreads(); i++) { + JavaThread thread = threads.getJavaThreadAt(i); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + thread.printThreadIDOn(new PrintStream(bos)); + if (all || bos.toString().equals(id)) { + out.format("Thread \"%s\" id=%s Address=%s\n", + thread.getThreadName(), bos.toString(), thread.getAddress()); + thread.printThreadContextOn(out, verbose); + out.println(" "); + if (!all) return; + } + } + if (!all) { + out.println("Couldn't find thread " + id); + } + } + }, new Command("thread", "thread { -a | id }", false) { public void doit(Tokens t) { if (t.countTokens() != 1) { usage(); } else { - String name = t.nextToken(); + String id = t.nextToken(); Threads threads = VM.getVM().getThreads(); - boolean all = name.equals("-a"); + boolean all = id.equals("-a"); for (int i = 0; i < threads.getNumberOfThreads(); i++) { JavaThread thread = threads.getJavaThreadAt(i); ByteArrayOutputStream bos = new ByteArrayOutputStream(); thread.printThreadIDOn(new PrintStream(bos)); - if (all || bos.toString().equals(name)) { + if (all || bos.toString().equals(id)) { out.println("Thread " + bos.toString() + " Address " + thread.getAddress()); thread.printInfoOn(out); out.println(" "); diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThread.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThread.java index e11e336d436..00adf9c285b 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThread.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThread.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2022, 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 @@ -481,6 +481,25 @@ public class JavaThread extends Thread { return access.getLastSP(addr); } + // Print the contents of all registers in the thread's context + public void printThreadContextOn(PrintStream out, boolean verbose){ + ThreadContext tc = getThreadProxy().getContext(); + for (int r = 0; r < tc.getNumRegisters(); r++) { + Address regAddr = tc.getRegisterAsAddress(r); + System.out.format("%s: %s", tc.getRegisterName(r), regAddr); + if (regAddr == null) { + System.out.println(); + } else { + PointerLocation l = PointerFinder.find(regAddr); + if (l.isUnknown()) { + System.out.println(); + } else { + System.out.print(": "); + l.printOn(System.out, false, verbose); + } + } + } + } public void printThreadInfoOn(PrintStream out){ Oop threadOop = this.getThreadObj(); diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbThreadContext.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbThreadContext.java new file mode 100644 index 00000000000..207978ba5c6 --- /dev/null +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbThreadContext.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import jdk.test.lib.apps.LingeredApp; +import jtreg.SkippedException; + +/** + * @test + * @summary Test clhsdb where command + * @requires vm.hasSA + * @library /test/lib + * @run main/othervm ClhsdbThreadContext + */ + +public class ClhsdbThreadContext { + public static void main(String[] args) throws Exception { + System.out.println("Starting ClhsdbThreadContext test"); + + LingeredApp theApp = null; + try { + ClhsdbLauncher test = new ClhsdbLauncher(); + theApp = LingeredApp.startApp(); + System.out.println("Started LingeredApp with pid " + theApp.getPid()); + + // Run threadcontext on all threads + String cmdStr = "threadcontext -a"; + List cmds = List.of(cmdStr); + Map> expStrMap = new HashMap<>(); + expStrMap.put(cmdStr, List.of( + "Thread \"Common-Cleaner\"", + "Thread \"Service Thread\"", + "Thread \"Finalizer\"", + "Thread \"SteadyStateThread\"", + "In java stack for thread \"SteadyStateThread\"")); + String cmdOutput = test.run(theApp.getPid(), cmds, expStrMap, null); + + // Run threadcontext on all threads in verbose mode + cmdStr = "threadcontext -v -a"; + cmds = List.of(cmdStr); + expStrMap = new HashMap<>(); + expStrMap.put(cmdStr, List.of( + "Thread \"Common-Cleaner\"", + "Thread \"Service Thread\"", + "Thread \"Finalizer\"", + "Thread \"SteadyStateThread\"")); + Map> unexpStrMap = new HashMap<>(); + unexpStrMap.put(cmdStr, List.of( + "In java stack for thread \"SteadyStateThread\"")); + test.run(theApp.getPid(), cmds, expStrMap, unexpStrMap); + + // Look for a line like the following and parse the threadID out of it. + // Thread "SteadyStateThread" id=18010 Address=0x000014bf103eaf50 + String[] parts = cmdOutput.split("Thread \"SteadyStateThread\" id="); + String[] tokens = parts[1].split(" "); + String threadID = tokens[0]; + + // Run threadcontext on the SteadyStateThread in verbose mode + cmdStr = "threadcontext -v " + threadID; + cmds = List.of(cmdStr); + expStrMap = new HashMap<>(); + expStrMap.put(cmdStr, List.of( + "Thread \"SteadyStateThread\"", + "java.lang.Thread.State: BLOCKED", + "In java stack \\[0x\\p{XDigit}+,0x\\p{XDigit}+,0x\\p{XDigit}+\\] for thread")); + unexpStrMap = new HashMap<>(); + unexpStrMap.put(cmdStr, List.of( + "Thread \"Common-Cleaner\"", + "Thread \"Service Thread\"", + "Thread \"Finalizer\"")); + test.run(theApp.getPid(), cmds, expStrMap, unexpStrMap); + + // Run threadcontext on all threads in verbose mode + + } catch (SkippedException se) { + throw se; + } catch (Exception ex) { + throw new RuntimeException("Test ERROR " + ex, ex); + } finally { + LingeredApp.stopApp(theApp); + } + + System.out.println("Test PASSED"); + } +} -- GitLab From e314a4cfda30cc680b3f0aef8c62b75ff81bdbb1 Mon Sep 17 00:00:00 2001 From: Claes Redestad Date: Tue, 18 Jan 2022 19:28:12 +0000 Subject: [PATCH 160/564] 8280124: Reduce branches decoding latin-1 chars from UTF-8 encoded bytes Reviewed-by: rriggs, alanb, naoto --- .../share/classes/java/lang/String.java | 6 +- .../openjdk/bench/java/lang/StringDecode.java | 145 +++++++++++++----- 2 files changed, 105 insertions(+), 46 deletions(-) diff --git a/src/java.base/share/classes/java/lang/String.java b/src/java.base/share/classes/java/lang/String.java index 756b8efacda..43c76d5eb3e 100644 --- a/src/java.base/share/classes/java/lang/String.java +++ b/src/java.base/share/classes/java/lang/String.java @@ -541,8 +541,7 @@ public final class String offset++; continue; } - if ((b1 == (byte)0xc2 || b1 == (byte)0xc3) && - offset + 1 < sl) { + if ((b1 & 0xfe) == 0xc2 && offset + 1 < sl) { // b1 either 0xc2 or 0xc3 int b2 = bytes[offset + 1]; if (!isNotContinuation(b2)) { dst[dp++] = (byte)decode2(b1, b2); @@ -698,8 +697,7 @@ public final class String offset++; continue; } - if ((b1 == (byte) 0xc2 || b1 == (byte) 0xc3) && - offset + 1 < sl) { + if ((b1 & 0xfe) == 0xc2 && offset + 1 < sl) { // b1 either 0xc2 or 0xc3 int b2 = bytes[offset + 1]; if (!isNotContinuation(b2)) { dst[dp++] = (byte) decode2(b1, b2); diff --git a/test/micro/org/openjdk/bench/java/lang/StringDecode.java b/test/micro/org/openjdk/bench/java/lang/StringDecode.java index ace4252c7a3..186d2aed6d9 100644 --- a/test/micro/org/openjdk/bench/java/lang/StringDecode.java +++ b/test/micro/org/openjdk/bench/java/lang/StringDecode.java @@ -40,59 +40,120 @@ import java.util.concurrent.TimeUnit; @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.NANOSECONDS) -@Fork(value = 3, jvmArgs = "-Xmx1g") +@Fork(value = 3) @Warmup(iterations = 5, time = 2) @Measurement(iterations = 5, time = 3) @State(Scope.Thread) public class StringDecode { - @BenchmarkMode(Mode.AverageTime) - @OutputTimeUnit(TimeUnit.NANOSECONDS) - @Fork(value = 3, jvmArgs = "-Xmx1g") - @Warmup(iterations = 5, time = 2) - @Measurement(iterations = 5, time = 2) - @State(Scope.Thread) - public static class WithCharset { - - @Param({"US-ASCII", "ISO-8859-1", "UTF-8", "MS932", "ISO-8859-6", "ISO-2022-KR"}) - private String charsetName; - - private Charset charset; - private byte[] asciiString; - private byte[] utf16String; - - @Setup - public void setup() { - charset = Charset.forName(charsetName); - asciiString = "ascii string".getBytes(charset); - utf16String = "UTF-\uFF11\uFF16 string".getBytes(charset); - } - - @Benchmark - public void decodeCharsetName(Blackhole bh) throws Exception { - bh.consume(new String(asciiString, charsetName)); - bh.consume(new String(utf16String, charsetName)); - } - - @Benchmark - public void decodeCharset(Blackhole bh) throws Exception { - bh.consume(new String(asciiString, charset)); - bh.consume(new String(utf16String, charset)); - } - } + @Param({"US-ASCII", "ISO-8859-1", "UTF-8", "MS932", "ISO-8859-6", "ISO-2022-KR"}) + private String charsetName; - private byte[] asciiDefaultString; - private byte[] utf16DefaultString; + private Charset charset; + private byte[] asciiString; + private byte[] utf16String; + private byte[] longUtf16String; + private byte[] longUtf16StartString; + private byte[] longLatin1String; @Setup public void setup() { - asciiDefaultString = "ascii string".getBytes(); - utf16DefaultString = "UTF-\uFF11\uFF16 string".getBytes(); + charset = Charset.forName(charsetName); + asciiString = "ascii string".getBytes(charset); + utf16String = "UTF-\uFF11\uFF16 string".getBytes(charset); + longUtf16String = """ + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam ac sem eu + urna egestas placerat. Etiam finibus ipsum nulla, non mattis dolor cursus a. + Nulla nec nisl consectetur, lacinia neque id, accumsan ante. Curabitur et + sapien in magna porta ultricies. Sed vel pellentesque nibh. Pellentesque dictum + dignissim diam eu ultricies. Class aptent taciti sociosqu ad litora torquent + per conubia nostra, per inceptos himenaeos. Suspendisse erat diam, fringilla + sed massa sed, posuere viverra orci. Suspendisse tempor libero non gravida + efficitur. Vivamus lacinia risus non orci viverra, at consectetur odio laoreet. + Suspendisse potenti. + + Phasellus vel nisi iaculis, accumsan quam sed, bibendum eros. Sed venenatis + nulla tortor, et eleifend urna sodales id. Nullam tempus ac metus sit amet + sollicitudin. Nam sed ex diam. Praesent vitae eros et neque condimentum + consectetur eget non tortor. Praesent bibendum vel felis nec dignissim. + Maecenas a enim diam. Suspendisse quis ligula at nisi accumsan lacinia id + hendrerit sapien. \uFF11Donec aliquam mattis lectus eu ultrices. Duis eu nisl\uFF11 + euismod, blandit mauris vel, \uFF11placerat urna. Etiam malesuada enim purus, + tristique mollis odio blandit quis.\uFF11 Vivamus posuere. \uFF11 + \uFF11 + """.getBytes(charset); + longUtf16StartString = """ + \uFF11 + Lorem ipsum dolor sit amet, \uFF11consectetur adipiscing elit. Aliquam ac sem eu + urna egestas \uFF11placerat. Etiam finibus ipsum nulla, non mattis dolor cursus a. + Nulla \uFF11nec nisl consectetur, lacinia neque id, accumsan ante. Curabitur et + sapien in \uFF11magna porta ultricies. \uFF11Sed vel pellentesque nibh. Pellentesque dictum + dignissim diam eu ultricies. Class aptent taciti sociosqu ad litora torquent + per conubia nostra, per inceptos himenaeos. Suspendisse erat diam, fringilla + sed massa sed, posuere viverra orci. Suspendisse tempor libero non gravida + efficitur. Vivamus lacinia risus non orci viverra, at consectetur odio laoreet. + Suspendisse potenti. + + Phasellus vel nisi iaculis, accumsan quam sed, bibendum eros. Sed venenatis + nulla tortor, et eleifend urna sodales id. Nullam tempus ac metus sit amet + sollicitudin. Nam sed ex diam. Praesent vitae eros et neque condimentum + consectetur eget non tortor. Praesent bibendum vel felis nec dignissim. + Maecenas a enim diam. Suspendisse quis ligula at nisi accumsan lacinia id + hendrerit sapien. Donec aliquam mattis lectus eu ultrices. Duis eu nisl + euismod, blandit mauris vel, placerat urna. Etiam malesuada enim purus, + tristique mollis odio blandit quis. Vivamus posuere. + """.getBytes(charset); + + longLatin1String = """ + a\u00B6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6 + b\u00F6\u00F6\u00B6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6 + c\u00F6\u00F6\u00F6\u00B6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6 + d\u00F6\u00F6\u00F6\u00F6\u00B6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6 + e\u00F6\u00F6\u00F6\u00F6\u00F6\u00B6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6 + f\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00B6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6 + g\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00B6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6 + h\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00B6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6 + i\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00B6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6 + j\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00B6\u00F6\u00F6\u00F6\u00F6\u00F6 + k\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00B6\u00F6\u00F6\u00F6\u00F6 + l\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00B6\u00F6\u00F6\u00F6 + m\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00B6\u00F6\u00F6 + """.getBytes(charset); + } + + @Benchmark + public String decodeAsciiCharsetName() throws Exception { + return new String(asciiString, charsetName); + } + + @Benchmark + public String decodeAscii() throws Exception { + return new String(asciiString, charset); + } + + @Benchmark + public String decodeLatin1Long() throws Exception { + return new String(longLatin1String, charset); + } + + @Benchmark + public String decodeUTF16Short() throws Exception { + return new String(utf16String, charset); + } + + @Benchmark + public String decodeUTF16LongEnd() throws Exception { + return new String(longUtf16String, charset); + } + + @Benchmark + public String decodeUTF16LongStart() throws Exception { + return new String(longUtf16StartString, charset); } @Benchmark - public void decodeDefault(Blackhole bh) throws Exception { - bh.consume(new String(asciiDefaultString)); - bh.consume(new String(utf16DefaultString)); + public void decodeUTF16LongMixed(Blackhole bh) throws Exception { + bh.consume(new String(longUtf16StartString, charset)); + bh.consume(new String(longUtf16String, charset)); } } -- GitLab From 46fd683820bb7149c0605a0ba03f59e76de69c16 Mon Sep 17 00:00:00 2001 From: Chris Plummer Date: Tue, 18 Jan 2022 19:31:16 +0000 Subject: [PATCH 161/564] 8176567: nsk/jdi/ReferenceType/instances/instances002: TestFailure: Unexpected size of referenceType.instances(nsk.share.jdi.TestInterfaceImplementer1): 11, expected: 10 Reviewed-by: sspitsyn, amenkov --- .../share/native/libjdwp/invoker.c | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/src/jdk.jdwp.agent/share/native/libjdwp/invoker.c b/src/jdk.jdwp.agent/share/native/libjdwp/invoker.c index fdc7a0bc613..42e6741d467 100644 --- a/src/jdk.jdwp.agent/share/native/libjdwp/invoker.c +++ b/src/jdk.jdwp.agent/share/native/libjdwp/invoker.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2022, 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 @@ -752,7 +752,9 @@ invoker_completeInvokeRequest(jthread thread) } id = request->id; exc = request->exception; + request->exception = NULL; returnValue = request->returnValue; + request->returnValue.l = NULL; /* Release return value and exception references, but delay the release * until after the return packet was sent. */ @@ -790,23 +792,20 @@ invoker_completeInvokeRequest(jthread thread) (void)outStream_writeValue(env, &out, tag, returnValue); (void)outStream_writeObjectTag(env, &out, exc); (void)outStream_writeObjectRef(env, &out, exc); + /* + * Delete potentially saved global references for return value + * and exception. This must be done before sending the reply or + * these objects will briefly be viewable by the debugger as live + * when they shouldn't be. + */ + if (mustReleaseReturnValue && returnValue.l != NULL) { + tossGlobalRef(env, &returnValue.l); + } + if (exc != NULL) { + tossGlobalRef(env, &exc); + } outStream_sendReply(&out); } - - /* - * Delete potentially saved global references of return value - * and exception - */ - eventHandler_lock(); // for proper lock order - debugMonitorEnter(invokerLock); - if (mustReleaseReturnValue && returnValue.l != NULL) { - tossGlobalRef(env, &returnValue.l); - } - if (exc != NULL) { - tossGlobalRef(env, &exc); - } - debugMonitorExit(invokerLock); - eventHandler_unlock(); } jboolean -- GitLab From 1a206287576ec55d50d33c68b54647efc7fe32b0 Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Tue, 18 Jan 2022 21:56:40 +0000 Subject: [PATCH 162/564] 8248404: AArch64: Remove uses of long and unsigned long Reviewed-by: kbarrett --- src/hotspot/cpu/aarch64/assembler_aarch64.hpp | 20 +++++++------------ .../cpu/aarch64/macroAssembler_aarch64.hpp | 16 +++++---------- .../aarch64/macroAssembler_aarch64_log.cpp | 3 ++- .../universalUpcallHandler_aarch64.cpp | 3 ++- 4 files changed, 16 insertions(+), 26 deletions(-) diff --git a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp index 05234a31157..3717756d9d9 100644 --- a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2021, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -27,6 +27,7 @@ #define CPU_AARCH64_ASSEMBLER_AARCH64_HPP #include "asm/register.hpp" +#include "metaprogramming/enableIf.hpp" #ifdef __GNUC__ @@ -404,18 +405,11 @@ class Address { : _mode(no_mode) { } Address(Register r) : _base(r), _index(noreg), _offset(0), _mode(base_plus_offset), _target(0) { } - Address(Register r, int o) - : _base(r), _index(noreg), _offset(o), _mode(base_plus_offset), _target(0) { } - Address(Register r, long o) - : _base(r), _index(noreg), _offset(o), _mode(base_plus_offset), _target(0) { } - Address(Register r, long long o) - : _base(r), _index(noreg), _offset(o), _mode(base_plus_offset), _target(0) { } - Address(Register r, unsigned int o) - : _base(r), _index(noreg), _offset(o), _mode(base_plus_offset), _target(0) { } - Address(Register r, unsigned long o) - : _base(r), _index(noreg), _offset(o), _mode(base_plus_offset), _target(0) { } - Address(Register r, unsigned long long o) - : _base(r), _index(noreg), _offset(o), _mode(base_plus_offset), _target(0) { } + + template::value)> + Address(Register r, T o) + : _base(r), _index(noreg), _offset(o), _mode(base_plus_offset), _target(0) {} + Address(Register r, ByteSize disp) : Address(r, in_bytes(disp)) { } Address(Register r, Register r1, extend ext = lsl()) diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp index 8a2521f629c..dcef7b34d73 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2021, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -27,6 +27,7 @@ #define CPU_AARCH64_MACROASSEMBLER_AARCH64_HPP #include "asm/assembler.inline.hpp" +#include "metaprogramming/enableIf.hpp" #include "oops/compressedOops.hpp" #include "runtime/vm_version.hpp" #include "utilities/powerOfTwo.hpp" @@ -493,17 +494,10 @@ public: inline void mov(Register dst, address addr) { mov_immediate64(dst, (uint64_t)addr); } - inline void mov(Register dst, int imm64) { mov_immediate64(dst, (uint64_t)imm64); } - inline void mov(Register dst, long imm64) { mov_immediate64(dst, (uint64_t)imm64); } - inline void mov(Register dst, long long imm64) { mov_immediate64(dst, (uint64_t)imm64); } - inline void mov(Register dst, unsigned int imm64) { mov_immediate64(dst, (uint64_t)imm64); } - inline void mov(Register dst, unsigned long imm64) { mov_immediate64(dst, (uint64_t)imm64); } - inline void mov(Register dst, unsigned long long imm64) { mov_immediate64(dst, (uint64_t)imm64); } + template::value)> + inline void mov(Register dst, T o) { mov_immediate64(dst, (uint64_t)o); } - inline void movw(Register dst, uint32_t imm32) - { - mov_immediate32(dst, imm32); - } + inline void movw(Register dst, uint32_t imm32) { mov_immediate32(dst, imm32); } void mov(Register dst, RegisterOrConstant src) { if (src.is_register()) diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64_log.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64_log.cpp index d65c3df226d..45772ff1afd 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64_log.cpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64_log.cpp @@ -297,7 +297,8 @@ void MacroAssembler::fast_log(FloatRegister vtmp0, FloatRegister vtmp1, bind(MAIN); fmovs(tmp3, vtmp5); // int intB0 = AS_INT_BITS(B); mov(tmp5, 0x3FE0); - mov(rscratch1, 0xffffe00000000000); + uint64_t mask = UCONST64(0xffffe00000000000); + mov(rscratch1, mask); andr(tmp2, tmp2, tmp1, LSR, 48); // hiWord & 0x7FF0 sub(tmp2, tmp2, tmp5); // tmp2 = hiWord & 0x7FF0 - 0x3FE0 scvtfwd(vtmp5, tmp2); // vtmp5 = (double)tmp2; diff --git a/src/hotspot/cpu/aarch64/universalUpcallHandler_aarch64.cpp b/src/hotspot/cpu/aarch64/universalUpcallHandler_aarch64.cpp index 41bb34e40ab..e3287652891 100644 --- a/src/hotspot/cpu/aarch64/universalUpcallHandler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/universalUpcallHandler_aarch64.cpp @@ -71,7 +71,8 @@ address ProgrammableUpcallHandler::generate_upcall_stub(jobject rec, jobject jab // Capture prev stack pointer (stack arguments base) __ add(rscratch1, rfp, 16); // Skip saved FP and LR - __ str(rscratch1, Address(sp, layout.stack_args)); + Address slot = __ legitimize_address(Address(sp, layout.stack_args), wordSize, rscratch2); + __ str(rscratch1, slot); // Call upcall helper __ ldr(c_rarg0, rec_adr); -- GitLab From 3a421e4b78ae5e7116ac68128504b65fa00e1f7f Mon Sep 17 00:00:00 2001 From: John Jiang Date: Tue, 18 Jan 2022 22:40:14 +0000 Subject: [PATCH 163/564] 8280122: SupportedGroupsExtension should output "named groups" rather than "versions" Reviewed-by: weijun, xuelei --- .../classes/sun/security/ssl/SupportedGroupsExtension.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/java.base/share/classes/sun/security/ssl/SupportedGroupsExtension.java b/src/java.base/share/classes/sun/security/ssl/SupportedGroupsExtension.java index 94ff8801fab..3cf357254aa 100644 --- a/src/java.base/share/classes/sun/security/ssl/SupportedGroupsExtension.java +++ b/src/java.base/share/classes/sun/security/ssl/SupportedGroupsExtension.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -112,7 +112,7 @@ final class SupportedGroupsExtension { @Override public String toString() { MessageFormat messageFormat = new MessageFormat( - "\"versions\": '['{0}']'", Locale.ENGLISH); + "\"named groups\": '['{0}']'", Locale.ENGLISH); if (namedGroupsIds == null || namedGroupsIds.length == 0) { Object[] messageFields = { -- GitLab From feff0e5578769c003af5bb817c2be89c8121708d Mon Sep 17 00:00:00 2001 From: Roger Riggs Date: Wed, 9 Jun 2021 14:29:38 +0000 Subject: [PATCH 164/564] 8264934: Enhance cross VM serialization Reviewed-by: smarks, rhalade, chegar --- .../classes/java/io/ObjectInputStream.java | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/java.base/share/classes/java/io/ObjectInputStream.java b/src/java.base/share/classes/java/io/ObjectInputStream.java index de339627d5b..d6541b371d7 100644 --- a/src/java.base/share/classes/java/io/ObjectInputStream.java +++ b/src/java.base/share/classes/java/io/ObjectInputStream.java @@ -1320,6 +1320,8 @@ public class ObjectInputStream *
  • each object reference previously deserialized from the stream * (class is {@code null}, arrayLength is -1), *
  • each regular class (class is not {@code null}, arrayLength is -1), + *
  • each interface class explicitly referenced in the stream + * (it is not called for interfaces implemented by classes in the stream), *
  • each interface of a dynamic proxy and the dynamic proxy class itself * (class is not {@code null}, arrayLength is -1), *
  • each array is filtered using the array type and length of the array @@ -2082,6 +2084,30 @@ public class ObjectInputStream totalObjectRefs++; depth++; desc.initNonProxy(readDesc, cl, resolveEx, readClassDesc(false)); + + if (cl != null) { + // Check that serial filtering has been done on the local class descriptor's superclass, + // in case it does not appear in the stream. + + // Find the next super descriptor that has a local class descriptor. + // Descriptors for which there is no local class are ignored. + ObjectStreamClass superLocal = null; + for (ObjectStreamClass sDesc = desc.getSuperDesc(); sDesc != null; sDesc = sDesc.getSuperDesc()) { + if ((superLocal = sDesc.getLocalDesc()) != null) { + break; + } + } + + // Scan local descriptor superclasses for a match with the local descriptor of the super found above. + // For each super descriptor before the match, invoke the serial filter on the class. + // The filter is invoked for each class that has not already been filtered + // but would be filtered if the instance had been serialized by this Java runtime. + for (ObjectStreamClass lDesc = desc.getLocalDesc().getSuperDesc(); + lDesc != null && lDesc != superLocal; + lDesc = lDesc.getSuperDesc()) { + filterCheck(lDesc.forClass(), -1); + } + } } finally { depth--; } -- GitLab From 29f61b3b0a5b2dcfef125363da3b5338dcc7de94 Mon Sep 17 00:00:00 2001 From: Patrick Concannon Date: Wed, 14 Jul 2021 13:41:38 +0000 Subject: [PATCH 165/564] 8269944: Better HTTP transport redux Reviewed-by: dfuchs, chegar, rhalade, ahgross --- .../classes/sun/net/httpserver/FixedLengthInputStream.java | 3 +++ .../classes/sun/net/httpserver/FixedLengthOutputStream.java | 3 +++ .../share/classes/sun/net/httpserver/Request.java | 6 ++++-- .../share/classes/sun/net/httpserver/ServerImpl.java | 5 +++++ 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/FixedLengthInputStream.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/FixedLengthInputStream.java index c875a1ab9b4..ac6fb7be005 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/FixedLengthInputStream.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/FixedLengthInputStream.java @@ -41,6 +41,9 @@ class FixedLengthInputStream extends LeftOverInputStream { FixedLengthInputStream (ExchangeImpl t, InputStream src, long len) { super (t, src); + if (len < 0) { + throw new IllegalArgumentException("Content-Length: " + len); + } this.remaining = len; } diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/FixedLengthOutputStream.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/FixedLengthOutputStream.java index 8b431645ceb..4935214c2e1 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/FixedLengthOutputStream.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/FixedLengthOutputStream.java @@ -47,6 +47,9 @@ class FixedLengthOutputStream extends FilterOutputStream FixedLengthOutputStream (ExchangeImpl t, OutputStream src, long len) { super (src); + if (len < 0) { + throw new IllegalArgumentException("Content-Length: " + len); + } this.t = t; this.remaining = len; } diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/Request.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/Request.java index 265b5c82718..92b2f709c34 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/Request.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/Request.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2021, 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 @@ -208,7 +208,9 @@ class Request { "sun.net.httpserver.maxReqHeaders) exceeded, " + ServerConfig.getMaxReqHeaders() + "."); } - + if (k == null) { // Headers disallows null keys, use empty string + k = ""; // instead to represent invalid key + } hdrs.add (k,v); len = 0; } diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java index ec6b99ab8be..d5bd8025788 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java @@ -618,6 +618,11 @@ class ServerImpl implements TimeSource { headerValue = headers.getFirst("Content-Length"); if (headerValue != null) { clen = Long.parseLong(headerValue); + if (clen < 0) { + reject(Code.HTTP_BAD_REQUEST, requestLine, + "Illegal Content-Length value"); + return; + } } if (clen == 0) { requestCompleted(connection); -- GitLab From f18deeb69e8d2fa34b9c747226bbe3567116ae8f Mon Sep 17 00:00:00 2001 From: Valerie Peng Date: Fri, 23 Jul 2021 18:04:54 +0000 Subject: [PATCH 166/564] 8268488: More valuable DerValues Reviewed-by: weijun, ahgross, rhalade --- .../com/sun/crypto/provider/KeyProtector.java | 4 ++++ .../com/sun/crypto/provider/OAEPParameters.java | 13 +++++++++++-- .../share/classes/sun/security/pkcs/SignerInfo.java | 12 ++++++++++-- .../classes/sun/security/rsa/PSSParameters.java | 9 +++++++-- 4 files changed, 32 insertions(+), 6 deletions(-) diff --git a/src/java.base/share/classes/com/sun/crypto/provider/KeyProtector.java b/src/java.base/share/classes/com/sun/crypto/provider/KeyProtector.java index b13a1a905d7..570aca63e09 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/KeyProtector.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/KeyProtector.java @@ -177,6 +177,10 @@ final class KeyProtector { byte[] encodedParams = encrInfo.getAlgorithm().getEncodedParams(); + if (encodedParams == null) { + throw new IOException("Missing PBE parameters"); + } + // parse the PBE parameters into the corresponding spec AlgorithmParameters pbeParams = AlgorithmParameters.getInstance("PBE"); diff --git a/src/java.base/share/classes/com/sun/crypto/provider/OAEPParameters.java b/src/java.base/share/classes/com/sun/crypto/provider/OAEPParameters.java index bdb1da97b63..ce9c2ea044b 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/OAEPParameters.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/OAEPParameters.java @@ -107,8 +107,12 @@ public final class OAEPParameters extends AlgorithmParametersSpi { if (!val.getOID().equals(OID_MGF1)) { throw new IOException("Only MGF1 mgf is supported"); } + byte[] encodedParams = val.getEncodedParams(); + if (encodedParams == null) { + throw new IOException("Missing MGF1 parameters"); + } AlgorithmId params = AlgorithmId.parse( - new DerValue(val.getEncodedParams())); + new DerValue(encodedParams)); mgfSpec = switch (params.getName()) { case "SHA-1" -> MGF1ParameterSpec.SHA1; case "SHA-224" -> MGF1ParameterSpec.SHA224; @@ -129,7 +133,12 @@ public final class OAEPParameters extends AlgorithmParametersSpi { if (!val.getOID().equals(OID_PSpecified)) { throw new IOException("Wrong OID for pSpecified"); } - p = DerValue.wrap(val.getEncodedParams()).getOctetString(); + byte[] encodedParams = val.getEncodedParams(); + if (encodedParams == null) { + throw new IOException("Missing pSpecified label"); + } + + p = DerValue.wrap(encodedParams).getOctetString(); } else { p = new byte[0]; } diff --git a/src/java.base/share/classes/sun/security/pkcs/SignerInfo.java b/src/java.base/share/classes/sun/security/pkcs/SignerInfo.java index 868babb2b44..af466e66156 100644 --- a/src/java.base/share/classes/sun/security/pkcs/SignerInfo.java +++ b/src/java.base/share/classes/sun/security/pkcs/SignerInfo.java @@ -383,8 +383,15 @@ public class SignerInfo implements DerEncoder { if (digestAlgName.equals("SHAKE256") || digestAlgName.equals("SHAKE256-LEN")) { if (digestAlgName.equals("SHAKE256-LEN")) { - int v = new DerValue(digestAlgorithmId - .getEncodedParams()).getInteger(); + // RFC8419: for EdDSA in CMS, the id-shake256-len + // algorithm id must contain parameter value 512 + // encoded as a positive integer value + byte[] params = digestAlgorithmId.getEncodedParams(); + if (params == null) { + throw new SignatureException( + "id-shake256-len oid missing length"); + } + int v = new DerValue(params).getInteger(); if (v != 512) { throw new SignatureException( "Unsupported id-shake256-" + v); @@ -527,6 +534,7 @@ public class SignerInfo implements DerEncoder { if (spec == null) { throw new NoSuchAlgorithmException("Missing PSSParameterSpec for RSASSA-PSS algorithm"); } + if (!AlgorithmId.get(spec.getDigestAlgorithm()).equals(digAlgId)) { throw new NoSuchAlgorithmException("Incompatible digest algorithm"); } diff --git a/src/java.base/share/classes/sun/security/rsa/PSSParameters.java b/src/java.base/share/classes/sun/security/rsa/PSSParameters.java index fef496ed50c..c2f4039a3ea 100644 --- a/src/java.base/share/classes/sun/security/rsa/PSSParameters.java +++ b/src/java.base/share/classes/sun/security/rsa/PSSParameters.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2021, 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,8 +102,13 @@ public final class PSSParameters extends AlgorithmParametersSpi { if (!val.getOID().equals(AlgorithmId.MGF1_oid)) { throw new IOException("Only MGF1 mgf is supported"); } + + byte[] encodedParams = val.getEncodedParams(); + if (encodedParams == null) { + throw new IOException("Missing MGF1 parameters"); + } AlgorithmId params = AlgorithmId.parse( - new DerValue(val.getEncodedParams())); + new DerValue(encodedParams)); String mgfDigestName = params.getName(); switch (mgfDigestName) { case "SHA-1": -- GitLab From e069a3b8bfe67a7ffda635e92b4777e9cfeaf136 Mon Sep 17 00:00:00 2001 From: Hai-May Chao Date: Thu, 29 Jul 2021 19:20:45 +0000 Subject: [PATCH 167/564] 8268512: More content for ContentInfo Reviewed-by: ahgross, weijun, rhalade --- .../share/classes/sun/security/pkcs/ContentInfo.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/java.base/share/classes/sun/security/pkcs/ContentInfo.java b/src/java.base/share/classes/sun/security/pkcs/ContentInfo.java index 125da2c9e2c..fbc6a46fc00 100644 --- a/src/java.base/share/classes/sun/security/pkcs/ContentInfo.java +++ b/src/java.base/share/classes/sun/security/pkcs/ContentInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2021, 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 @@ -127,7 +127,9 @@ public class ContentInfo { if (oldStyle) { // JDK1.1.x-style encoding - content = typeAndContent[1]; + if (typeAndContent.length > 1) { // content is OPTIONAL + content = typeAndContent[1]; + } } else { // This is the correct, standards-compliant encoding. // Parse the content (OPTIONAL field). -- GitLab From 7ee905a8a09c92b9534a440660d37c28cf5d797b Mon Sep 17 00:00:00 2001 From: Joe Wang Date: Thu, 5 Aug 2021 19:05:09 +0000 Subject: [PATCH 168/564] 8270498: Improve SAX Parser configuration management Reviewed-by: ahgross, lancea, rhalade, naoto --- .../internal/impl/XMLEntityManager.java | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java index 7dbdf607513..8a01f74e790 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java @@ -91,7 +91,7 @@ import org.xml.sax.InputSource; * @author K.Venugopal SUN Microsystems * @author Neeraj Bajaj SUN Microsystems * @author Sunitha Reddy SUN Microsystems - * @LastModified: May 2021 + * @LastModified: Aug 2021 */ public class XMLEntityManager implements XMLComponent, XMLEntityResolver { @@ -1235,7 +1235,7 @@ public class XMLEntityManager implements XMLComponent, XMLEntityResolver { externalEntity = (Entity.ExternalEntity)entity; extLitSysId = (externalEntity.entityLocation != null ? externalEntity.entityLocation.getLiteralSystemId() : null); extBaseSysId = (externalEntity.entityLocation != null ? externalEntity.entityLocation.getBaseSystemId() : null); - expandedSystemId = expandSystemId(extLitSysId, extBaseSysId); + expandedSystemId = expandSystemId(extLitSysId, extBaseSysId, fStrictURI); boolean unparsed = entity.isUnparsed(); boolean parameter = entityName.startsWith("%"); boolean general = !parameter; @@ -1312,15 +1312,13 @@ public class XMLEntityManager implements XMLComponent, XMLEntityResolver { */ xmlInputSource = staxInputSource.getXMLInputSource() ; if (!fISCreatedByResolver) { - //let the not-LoadExternalDTD or not-SupportDTD process to handle the situation - if (fLoadExternalDTD) { - String accessError = SecuritySupport.checkAccess(expandedSystemId, fAccessExternalDTD, JdkConstants.ACCESS_EXTERNAL_ALL); - if (accessError != null) { - fErrorReporter.reportError(this.getEntityScanner(),XMLMessageFormatter.XML_DOMAIN, - "AccessExternalEntity", - new Object[] { SecuritySupport.sanitizePath(expandedSystemId), accessError }, - XMLErrorReporter.SEVERITY_FATAL_ERROR); - } + String accessError = SecuritySupport.checkAccess(expandedSystemId, + fAccessExternalDTD, JdkConstants.ACCESS_EXTERNAL_ALL); + if (accessError != null) { + fErrorReporter.reportError(this.getEntityScanner(),XMLMessageFormatter.XML_DOMAIN, + "AccessExternalEntity", + new Object[] { SecuritySupport.sanitizePath(expandedSystemId), accessError }, + XMLErrorReporter.SEVERITY_FATAL_ERROR); } } } -- GitLab From 1fddb03d93a024b66ce02598e1057b2b09a5073f Mon Sep 17 00:00:00 2001 From: Harold Seigel Date: Wed, 11 Aug 2021 16:48:14 +0000 Subject: [PATCH 169/564] 8271968: Better canonical naming Reviewed-by: coleenp, lfoltan, mschoene, ahgross --- .../share/classfile/classFileParser.cpp | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/hotspot/share/classfile/classFileParser.cpp b/src/hotspot/share/classfile/classFileParser.cpp index 368e3534184..05438517ecc 100644 --- a/src/hotspot/share/classfile/classFileParser.cpp +++ b/src/hotspot/share/classfile/classFileParser.cpp @@ -3051,6 +3051,7 @@ static int inner_classes_jump_to_outer(const Array* inner_classes, int inner static bool inner_classes_check_loop_through_outer(const Array* inner_classes, int idx, const ConstantPool* cp, int length) { int slow = inner_classes->at(idx + InstanceKlass::inner_class_inner_class_info_offset); int fast = inner_classes->at(idx + InstanceKlass::inner_class_outer_class_info_offset); + while (fast != -1 && fast != 0) { if (slow != 0 && (cp->klass_name_at(slow) == cp->klass_name_at(fast))) { return true; // found a circularity @@ -3080,14 +3081,15 @@ bool ClassFileParser::check_inner_classes_circularity(const ConstantPool* cp, in for (int y = idx + InstanceKlass::inner_class_next_offset; y < length; y += InstanceKlass::inner_class_next_offset) { - // To maintain compatibility, throw an exception if duplicate inner classes - // entries are found. - guarantee_property((_inner_classes->at(idx) != _inner_classes->at(y) || - _inner_classes->at(idx+1) != _inner_classes->at(y+1) || - _inner_classes->at(idx+2) != _inner_classes->at(y+2) || - _inner_classes->at(idx+3) != _inner_classes->at(y+3)), - "Duplicate entry in InnerClasses attribute in class file %s", - CHECK_(true)); + // 4347400: make sure there's no duplicate entry in the classes array + if (_major_version >= JAVA_1_5_VERSION) { + guarantee_property((_inner_classes->at(idx) != _inner_classes->at(y) || + _inner_classes->at(idx+1) != _inner_classes->at(y+1) || + _inner_classes->at(idx+2) != _inner_classes->at(y+2) || + _inner_classes->at(idx+3) != _inner_classes->at(y+3)), + "Duplicate entry in InnerClasses attribute in class file %s", + CHECK_(true)); + } // Return true if there are two entries with the same inner_class_info_index. if (_inner_classes->at(y) == _inner_classes->at(idx)) { return true; @@ -3180,10 +3182,9 @@ u2 ClassFileParser::parse_classfile_inner_classes_attribute(const ClassFileStrea inner_classes->at_put(index++, inner_access_flags.as_short()); } - // 4347400: make sure there's no duplicate entry in the classes array - // Also, check for circular entries. + // Check for circular and duplicate entries. bool has_circularity = false; - if (_need_verify && _major_version >= JAVA_1_5_VERSION) { + if (_need_verify) { has_circularity = check_inner_classes_circularity(cp, length * 4, CHECK_0); if (has_circularity) { // If circularity check failed then ignore InnerClasses attribute. -- GitLab From 9a94fbc793feb855e974c3814fe030f2671ed830 Mon Sep 17 00:00:00 2001 From: Phil Race Date: Mon, 16 Aug 2021 18:19:08 +0000 Subject: [PATCH 170/564] 8270952: Improve TIFF file handling Reviewed-by: jdv, psadhukhan, mschoene, rhalade --- .../plugins/tiff/TIFFNullDecompressor.java | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFNullDecompressor.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFNullDecompressor.java index 6ffc1f0acb7..9b5a746eec1 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFNullDecompressor.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFNullDecompressor.java @@ -136,12 +136,7 @@ public class TIFFNullDecompressor extends TIFFDecompressor { int lastRow = activeSrcHeight - 1; for (int y = 0; y < activeSrcHeight; y++) { - int bytesRead = stream.read(b, dstOffset, activeBytesPerRow); - if (bytesRead < 0) { - throw new EOFException(); - } else if (bytesRead != activeBytesPerRow) { - break; - } + stream.readFully(b, dstOffset, activeBytesPerRow); dstOffset += scanlineStride; // Skip unneeded bytes (row suffix + row prefix). @@ -154,17 +149,10 @@ public class TIFFNullDecompressor extends TIFFDecompressor { stream.seek(offset); int bytesPerRow = (srcWidth*bitsPerPixel + 7)/8; if(bytesPerRow == scanlineStride) { - if (stream.read(b, dstOffset, bytesPerRow*srcHeight) < 0) { - throw new EOFException(); - } + stream.readFully(b, dstOffset, bytesPerRow*srcHeight); } else { for (int y = 0; y < srcHeight; y++) { - int bytesRead = stream.read(b, dstOffset, bytesPerRow); - if (bytesRead < 0) { - throw new EOFException(); - } else if (bytesRead != bytesPerRow) { - break; - } + stream.readFully(b, dstOffset, bytesPerRow); dstOffset += scanlineStride; } } -- GitLab From fa47c368d470f59f3c98e6e8a7ff82371d3389df Mon Sep 17 00:00:00 2001 From: Ioi Lam Date: Mon, 16 Aug 2021 19:37:15 +0000 Subject: [PATCH 171/564] 8270386: Better verification of scan methods Reviewed-by: hseigel, coleenp, mschoene, rhalade --- src/hotspot/share/oops/instanceKlass.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp index fafc58fa9fd..e635b82f2ce 100644 --- a/src/hotspot/share/oops/instanceKlass.cpp +++ b/src/hotspot/share/oops/instanceKlass.cpp @@ -2417,7 +2417,9 @@ void InstanceKlass::metaspace_pointers_do(MetaspaceClosure* it) { } else { it->push(&_default_vtable_indices); } - it->push(&_fields); + + // _fields might be written into by Rewriter::scan_method() -> fd.set_has_initialized_final_update() + it->push(&_fields, MetaspaceClosure::_writable); if (itable_length() > 0) { itableOffsetEntry* ioe = (itableOffsetEntry*)start_of_itable(); -- GitLab From b02ea6dc3ca2e2a8c21ed76f28422a6f8bf2fa00 Mon Sep 17 00:00:00 2001 From: Joe Wang Date: Tue, 17 Aug 2021 04:34:17 +0000 Subject: [PATCH 172/564] 8270646: Improved scanning of XML entities Reviewed-by: naoto, lancea, mschoene, rhalade --- .../impl/XML11DocumentScannerImpl.java | 14 +- .../internal/impl/XML11EntityScanner.java | 210 +---------- .../internal/impl/XMLEntityScanner.java | 355 ++++++------------ .../xerces/internal/impl/XMLScanner.java | 10 +- .../xerces/internal/util/XMLStringBuffer.java | 88 +---- .../apache/xerces/internal/xni/XMLString.java | 81 +++- 6 files changed, 209 insertions(+), 549 deletions(-) diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XML11DocumentScannerImpl.java b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XML11DocumentScannerImpl.java index 1ec084e93a6..67f6478f135 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XML11DocumentScannerImpl.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XML11DocumentScannerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -54,7 +54,7 @@ import com.sun.org.apache.xerces.internal.xni.XNIException; * @author Andy Clark, IBM * @author Arnaud Le Hors, IBM * @author Eric Ye, IBM - * + * @LastModified: Aug 2021 */ public class XML11DocumentScannerImpl extends XMLDocumentScannerImpl { @@ -278,16 +278,6 @@ public class XML11DocumentScannerImpl + fStringBuffer.toString() + "\""); } } - // note that none of these characters should ever get through - // XML11EntityScanner. Not sure why - // this check was originally necessary. - NG - else if (c == '\n' || c == '\r' || c == 0x85 || c == 0x2028) { - fEntityScanner.scanChar(null); - fStringBuffer.append(' '); - if (entityDepth == fEntityDepth) { - fStringBuffer2.append('\n'); - } - } else if (c != -1 && XMLChar.isHighSurrogate(c)) { fStringBuffer3.clear(); if (scanSurrogates(fStringBuffer3)) { diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XML11EntityScanner.java b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XML11EntityScanner.java index 4be8d68e153..332aeb54206 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XML11EntityScanner.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XML11EntityScanner.java @@ -21,6 +21,7 @@ package com.sun.org.apache.xerces.internal.impl; +import static com.sun.org.apache.xerces.internal.impl.Constants.XML_VERSION_1_1; import com.sun.org.apache.xerces.internal.impl.XMLScanner.NameType; import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter; import com.sun.org.apache.xerces.internal.util.XML11Char; @@ -40,7 +41,7 @@ import java.io.IOException; * @author Michael Glavassevich, IBM * @author Neil Graham, IBM * - * @LastModified: Apr 2021 + * @LastModified: Aug 2021 */ public class XML11EntityScanner @@ -116,7 +117,7 @@ public class XML11EntityScanner load(1, false, false); offset = 0; } - if (c == '\r' && external) { + if (c == '\r' && external && fCurrentEntity.position < fCurrentEntity.count) { int cc = fCurrentEntity.ch[fCurrentEntity.position++]; if (cc != '\n' && cc != 0x85) { fCurrentEntity.position--; @@ -761,71 +762,12 @@ public class XML11EntityScanner } // normalize newlines - int offset = fCurrentEntity.position; - int c = fCurrentEntity.ch[offset]; - int newlines = 0; - boolean counted = false; - boolean external = fCurrentEntity.isExternal(); - if (c == '\n' || ((c == '\r' || c == 0x85 || c == 0x2028) && external)) { - do { - c = fCurrentEntity.ch[fCurrentEntity.position++]; - if ((c == '\r' ) && external) { - newlines++; - fCurrentEntity.lineNumber++; - fCurrentEntity.columnNumber = 1; - if (fCurrentEntity.position == fCurrentEntity.count) { - checkEntityLimit(null, fCurrentEntity, offset, newlines); - offset = 0; - fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition); - fCurrentEntity.position = newlines; - fCurrentEntity.startPosition = newlines; - if (load(newlines, false, true)) { - counted = true; - break; - } - } - int cc = fCurrentEntity.ch[fCurrentEntity.position]; - if (cc == '\n' || cc == 0x85) { - fCurrentEntity.position++; - offset++; - } - /*** NEWLINE NORMALIZATION ***/ - else { - newlines++; - } - } - else if (c == '\n' || ((c == 0x85 || c == 0x2028) && external)) { - newlines++; - fCurrentEntity.lineNumber++; - fCurrentEntity.columnNumber = 1; - if (fCurrentEntity.position == fCurrentEntity.count) { - checkEntityLimit(null, fCurrentEntity, offset, newlines); - offset = 0; - fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition); - fCurrentEntity.position = newlines; - fCurrentEntity.startPosition = newlines; - if (load(newlines, false, true)) { - counted = true; - break; - } - } - } - else { - fCurrentEntity.position--; - break; - } - } while (fCurrentEntity.position < fCurrentEntity.count - 1); - for (int i = offset; i < fCurrentEntity.position; i++) { - fCurrentEntity.ch[i] = '\n'; - } - int length = fCurrentEntity.position - offset; - if (fCurrentEntity.position == fCurrentEntity.count - 1) { - checkEntityLimit(null, fCurrentEntity, offset, length); - content.setValues(fCurrentEntity.ch, offset, length); - return -1; - } + if (normalizeNewlines(XML_VERSION_1_1, content, false, false, null)) { + return -1; } + int c; + boolean external = fCurrentEntity.isExternal(); // inner loop, scanning for content if (external) { while (fCurrentEntity.position < fCurrentEntity.count) { @@ -913,65 +855,12 @@ public class XML11EntityScanner } // normalize newlines - int offset = fCurrentEntity.position; - int c = fCurrentEntity.ch[offset]; - int newlines = 0; - boolean external = fCurrentEntity.isExternal(); - if (c == '\n' || ((c == '\r' || c == 0x85 || c == 0x2028) && external)) { - do { - c = fCurrentEntity.ch[fCurrentEntity.position++]; - if ((c == '\r' ) && external) { - newlines++; - fCurrentEntity.lineNumber++; - fCurrentEntity.columnNumber = 1; - if (fCurrentEntity.position == fCurrentEntity.count) { - offset = 0; - fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition); - fCurrentEntity.position = newlines; - fCurrentEntity.startPosition = newlines; - if (load(newlines, false, true)) { - break; - } - } - int cc = fCurrentEntity.ch[fCurrentEntity.position]; - if (cc == '\n' || cc == 0x85) { - fCurrentEntity.position++; - offset++; - } - /*** NEWLINE NORMALIZATION ***/ - else { - newlines++; - } - } - else if (c == '\n' || ((c == 0x85 || c == 0x2028) && external)) { - newlines++; - fCurrentEntity.lineNumber++; - fCurrentEntity.columnNumber = 1; - if (fCurrentEntity.position == fCurrentEntity.count) { - offset = 0; - fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition); - fCurrentEntity.position = newlines; - fCurrentEntity.startPosition = newlines; - if (load(newlines, false, true)) { - break; - } - } - } - else { - fCurrentEntity.position--; - break; - } - } while (fCurrentEntity.position < fCurrentEntity.count - 1); - for (int i = offset; i < fCurrentEntity.position; i++) { - fCurrentEntity.ch[i] = '\n'; - } - int length = fCurrentEntity.position - offset; - if (fCurrentEntity.position == fCurrentEntity.count - 1) { - content.setValues(fCurrentEntity.ch, offset, length); - return -1; - } + if (normalizeNewlines(XML_VERSION_1_1, content, false, true, null)) { + return -1; } + int c; + boolean external = fCurrentEntity.isExternal(); // scan literal value if (external) { while (fCurrentEntity.position < fCurrentEntity.count) { @@ -1093,66 +982,11 @@ public class XML11EntityScanner } // normalize newlines - int offset = fCurrentEntity.position; - int c = fCurrentEntity.ch[offset]; - int newlines = 0; - if (c == '\n' || ((c == '\r' || c == 0x85 || c == 0x2028) && external)) { - do { - c = fCurrentEntity.ch[fCurrentEntity.position++]; - if ((c == '\r' ) && external) { - newlines++; - fCurrentEntity.lineNumber++; - fCurrentEntity.columnNumber = 1; - if (fCurrentEntity.position == fCurrentEntity.count) { - offset = 0; - fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition); - fCurrentEntity.position = newlines; - fCurrentEntity.startPosition = newlines; - if (load(newlines, false, true)) { - break; - } - } - int cc = fCurrentEntity.ch[fCurrentEntity.position]; - if (cc == '\n' || cc == 0x85) { - fCurrentEntity.position++; - offset++; - } - /*** NEWLINE NORMALIZATION ***/ - else { - newlines++; - } - } - else if (c == '\n' || ((c == 0x85 || c == 0x2028) && external)) { - newlines++; - fCurrentEntity.lineNumber++; - fCurrentEntity.columnNumber = 1; - if (fCurrentEntity.position == fCurrentEntity.count) { - offset = 0; - fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition); - fCurrentEntity.position = newlines; - fCurrentEntity.startPosition = newlines; - fCurrentEntity.count = newlines; - if (load(newlines, false, true)) { - break; - } - } - } - else { - fCurrentEntity.position--; - break; - } - } while (fCurrentEntity.position < fCurrentEntity.count - 1); - for (int i = offset; i < fCurrentEntity.position; i++) { - fCurrentEntity.ch[i] = '\n'; - } - int length = fCurrentEntity.position - offset; - if (fCurrentEntity.position == fCurrentEntity.count - 1) { - checkEntityLimit(NameType.COMMENT, fCurrentEntity, offset, length); - buffer.append(fCurrentEntity.ch, offset, length); - return true; - } + if (normalizeNewlines(XML_VERSION_1_1, buffer, true, false, NameType.COMMENT)) { + return true; } + int c; // iterate over buffer looking for delimiter OUTER: while (fCurrentEntity.position < fCurrentEntity.count) { c = fCurrentEntity.ch[fCurrentEntity.position++]; @@ -1256,22 +1090,6 @@ public class XML11EntityScanner checkEntityLimit(nt, fCurrentEntity, offset, fCurrentEntity.position - offset); return true; } - else if (c == '\n' && (cc == '\r' ) && fCurrentEntity.isExternal()) { - // handle newlines - if (fCurrentEntity.position == fCurrentEntity.count) { - invokeListeners(1); - fCurrentEntity.ch[0] = (char)cc; - load(1, false, false); - } - int ccc = fCurrentEntity.ch[++fCurrentEntity.position]; - if (ccc == '\n' || ccc == 0x85) { - fCurrentEntity.position++; - } - fCurrentEntity.lineNumber++; - fCurrentEntity.columnNumber = 1; - checkEntityLimit(nt, fCurrentEntity, offset, fCurrentEntity.position - offset); - return true; - } // character was not skipped return false; diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityScanner.java b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityScanner.java index c48ed8f70be..89adb81b05b 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityScanner.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityScanner.java @@ -21,6 +21,8 @@ package com.sun.org.apache.xerces.internal.impl; +import static com.sun.org.apache.xerces.internal.impl.Constants.XML_VERSION_1_0; +import static com.sun.org.apache.xerces.internal.impl.Constants.XML_VERSION_1_1; import com.sun.org.apache.xerces.internal.impl.XMLScanner.NameType; import com.sun.org.apache.xerces.internal.impl.io.ASCIIReader; import com.sun.org.apache.xerces.internal.impl.io.UCSReader; @@ -55,7 +57,7 @@ import java.util.Locale; * @author Arnaud Le Hors, IBM * @author K.Venugopal Sun Microsystems * - * @LastModified: Apr 2021 + * @LastModified: Aug 2021 */ public class XMLEntityScanner implements XMLLocator { @@ -149,6 +151,15 @@ public class XMLEntityScanner implements XMLLocator { // indicates that the operation is for detecting XML version boolean detectingVersion = false; + // offset of the current cursor position + int offset = 0; + + // number of newlines in the current process + int newlines = 0; + + // indicating whether the content has been counted towards limit + boolean counted = false; + // // Constructors // @@ -553,7 +564,7 @@ public class XMLEntityScanner implements XMLLocator { } // scan character - int offset = fCurrentEntity.position; + offset = fCurrentEntity.position; int c = fCurrentEntity.ch[fCurrentEntity.position++]; if (c == '\n' || (c == '\r' && isExternal)) { fCurrentEntity.lineNumber++; @@ -561,10 +572,10 @@ public class XMLEntityScanner implements XMLLocator { if (fCurrentEntity.position == fCurrentEntity.count) { invokeListeners(1); fCurrentEntity.ch[0] = (char)c; - load(1, false, false); + load(1, true, false); offset = 0; } - if (c == '\r' && isExternal) { + if (c == '\r' && isExternal && fCurrentEntity.position < fCurrentEntity.count) { if (fCurrentEntity.ch[fCurrentEntity.position++] != '\n') { fCurrentEntity.position--; } @@ -614,7 +625,7 @@ public class XMLEntityScanner implements XMLLocator { } // scan nmtoken - int offset = fCurrentEntity.position; + offset = fCurrentEntity.position; boolean vc = false; char c; while (true){ @@ -695,7 +706,7 @@ public class XMLEntityScanner implements XMLLocator { } // scan name - int offset = fCurrentEntity.position; + offset = fCurrentEntity.position; int length; if (XMLChar.isNameStart(fCurrentEntity.ch[offset])) { if (++fCurrentEntity.position == fCurrentEntity.count) { @@ -788,7 +799,7 @@ public class XMLEntityScanner implements XMLLocator { } // scan qualified name - int offset = fCurrentEntity.position; + offset = fCurrentEntity.position; //making a check if if the specified character is a valid name start character //as defined by production [5] in the XML 1.0 specification. @@ -1043,81 +1054,11 @@ public class XMLEntityScanner implements XMLLocator { } // normalize newlines - int offset = fCurrentEntity.position; - int c = fCurrentEntity.ch[offset]; - int newlines = 0; - boolean counted = false; - if (c == '\n' || (c == '\r' && isExternal)) { - if (DEBUG_BUFFER) { - System.out.print("[newline, "+offset+", "+fCurrentEntity.position+": "); - print(); - System.out.println(); - } - do { - c = fCurrentEntity.ch[fCurrentEntity.position++]; - if (c == '\r' && isExternal) { - newlines++; - fCurrentEntity.lineNumber++; - fCurrentEntity.columnNumber = 1; - if (fCurrentEntity.position == fCurrentEntity.count) { - checkEntityLimit(null, fCurrentEntity, offset, newlines); - offset = 0; - fCurrentEntity.position = newlines; - if (load(newlines, false, true)) { - counted = true; - break; - } - } - if (fCurrentEntity.ch[fCurrentEntity.position] == '\n') { - fCurrentEntity.position++; - offset++; - } - /*** NEWLINE NORMALIZATION ***/ - else { - newlines++; - } - } else if (c == '\n') { - newlines++; - fCurrentEntity.lineNumber++; - fCurrentEntity.columnNumber = 1; - if (fCurrentEntity.position == fCurrentEntity.count) { - checkEntityLimit(null, fCurrentEntity, offset, newlines); - offset = 0; - fCurrentEntity.position = newlines; - if (load(newlines, false, true)) { - counted = true; - break; - } - } - } else { - fCurrentEntity.position--; - break; - } - } while (fCurrentEntity.position < fCurrentEntity.count - 1); - for (int i = offset; i < fCurrentEntity.position; i++) { - fCurrentEntity.ch[i] = '\n'; - } - int length = fCurrentEntity.position - offset; - if (fCurrentEntity.position == fCurrentEntity.count - 1) { - checkEntityLimit(null, fCurrentEntity, offset, length); - //CHANGED: dont replace the value.. append to the buffer. This gives control to the callee - //on buffering the data.. - content.setValues(fCurrentEntity.ch, offset, length); - //content.append(fCurrentEntity.ch, offset, length); - if (DEBUG_BUFFER) { - System.out.print("]newline, "+offset+", "+fCurrentEntity.position+": "); - print(); - System.out.println(); - } - return -1; - } - if (DEBUG_BUFFER) { - System.out.print("]newline, "+offset+", "+fCurrentEntity.position+": "); - print(); - System.out.println(); - } + if (normalizeNewlines(XML_VERSION_1_0, content, false, false, null)) { + return -1; } + int c; while (fCurrentEntity.position < fCurrentEntity.count) { c = fCurrentEntity.ch[fCurrentEntity.position++]; if (!XMLChar.isContent(c)) { @@ -1202,85 +1143,14 @@ public class XMLEntityScanner implements XMLLocator { } // normalize newlines - int offset = fCurrentEntity.position; - int c = fCurrentEntity.ch[offset]; - int newlines = 0; if(whiteSpaceInfoNeeded) whiteSpaceLen=0; - if (c == '\n' || (c == '\r' && isExternal)) { - if (DEBUG_BUFFER) { - System.out.print("[newline, "+offset+", "+fCurrentEntity.position+": "); - print(); - System.out.println(); - } - do { - c = fCurrentEntity.ch[fCurrentEntity.position++]; - if (c == '\r' && isExternal) { - newlines++; - fCurrentEntity.lineNumber++; - fCurrentEntity.columnNumber = 1; - if (fCurrentEntity.position == fCurrentEntity.count) { - offset = 0; - fCurrentEntity.position = newlines; - if (load(newlines, false, true)) { - break; - } - } - if (fCurrentEntity.ch[fCurrentEntity.position] == '\n') { - fCurrentEntity.position++; - offset++; - } - /*** NEWLINE NORMALIZATION ***/ - else { - newlines++; - } - /***/ - } else if (c == '\n') { - newlines++; - fCurrentEntity.lineNumber++; - fCurrentEntity.columnNumber = 1; - if (fCurrentEntity.position == fCurrentEntity.count) { - offset = 0; - fCurrentEntity.position = newlines; - if (load(newlines, false, true)) { - break; - } - } - /*** NEWLINE NORMALIZATION *** - * if (fCurrentEntity.ch[fCurrentEntity.position] == '\r' - * && external) { - * fCurrentEntity.position++; - * offset++; - * } - * /***/ - } else { - fCurrentEntity.position--; - break; - } - } while (fCurrentEntity.position < fCurrentEntity.count - 1); - int i=0; - for ( i = offset; i < fCurrentEntity.position; i++) { - fCurrentEntity.ch[i] = '\n'; - storeWhiteSpace(i); - } - int length = fCurrentEntity.position - offset; - if (fCurrentEntity.position == fCurrentEntity.count - 1) { - content.setValues(fCurrentEntity.ch, offset, length); - if (DEBUG_BUFFER) { - System.out.print("]newline, "+offset+", "+fCurrentEntity.position+": "); - print(); - System.out.println(); - } - return -1; - } - if (DEBUG_BUFFER) { - System.out.print("]newline, "+offset+", "+fCurrentEntity.position+": "); - print(); - System.out.println(); - } + if (normalizeNewlines(XML_VERSION_1_0, content, false, true, null)) { + return -1; } + int c; // scan literal value for (; fCurrentEntity.position= whiteSpaceLookup.length) { int [] tmp = new int[whiteSpaceLookup.length + 100]; System.arraycopy(whiteSpaceLookup, 0, tmp, 0, whiteSpaceLookup.length); @@ -1415,75 +1285,11 @@ public class XMLEntityScanner implements XMLLocator { return false; } - // normalize newlines - int offset = fCurrentEntity.position; - int c = fCurrentEntity.ch[offset]; - int newlines = 0; - if (c == '\n' || (c == '\r' && isExternal)) { - if (DEBUG_BUFFER) { - System.out.print("[newline, "+offset+", "+fCurrentEntity.position+": "); - print(); - System.out.println(); - } - do { - c = fCurrentEntity.ch[fCurrentEntity.position++]; - if (c == '\r' && isExternal) { - newlines++; - fCurrentEntity.lineNumber++; - fCurrentEntity.columnNumber = 1; - if (fCurrentEntity.position == fCurrentEntity.count) { - offset = 0; - fCurrentEntity.position = newlines; - if (load(newlines, false, true)) { - break; - } - } - if (fCurrentEntity.ch[fCurrentEntity.position] == '\n') { - fCurrentEntity.position++; - offset++; - } - /*** NEWLINE NORMALIZATION ***/ - else { - newlines++; - } - } else if (c == '\n') { - newlines++; - fCurrentEntity.lineNumber++; - fCurrentEntity.columnNumber = 1; - if (fCurrentEntity.position == fCurrentEntity.count) { - offset = 0; - fCurrentEntity.position = newlines; - fCurrentEntity.count = newlines; - if (load(newlines, false, true)) { - break; - } - } - } else { - fCurrentEntity.position--; - break; - } - } while (fCurrentEntity.position < fCurrentEntity.count - 1); - for (int i = offset; i < fCurrentEntity.position; i++) { - fCurrentEntity.ch[i] = '\n'; - } - int length = fCurrentEntity.position - offset; - if (fCurrentEntity.position == fCurrentEntity.count - 1) { - checkEntityLimit(NameType.COMMENT, fCurrentEntity, offset, length); - buffer.append(fCurrentEntity.ch, offset, length); - if (DEBUG_BUFFER) { - System.out.print("]newline, "+offset+", "+fCurrentEntity.position+": "); - print(); - System.out.println(); - } - return true; - } - if (DEBUG_BUFFER) { - System.out.print("]newline, "+offset+", "+fCurrentEntity.position+": "); - print(); - System.out.println(); - } + if (normalizeNewlines(XML_VERSION_1_0, buffer, true, false, NameType.COMMENT)) { + return true; } + int c; // iterate over buffer looking for delimiter OUTER: while (fCurrentEntity.position < fCurrentEntity.count) { c = fCurrentEntity.ch[fCurrentEntity.position++]; @@ -1570,7 +1376,7 @@ public class XMLEntityScanner implements XMLLocator { } // skip character - int offset = fCurrentEntity.position; + offset = fCurrentEntity.position; int cc = fCurrentEntity.ch[fCurrentEntity.position]; if (cc == c) { fCurrentEntity.position++; @@ -1587,26 +1393,6 @@ public class XMLEntityScanner implements XMLLocator { } checkEntityLimit(nt, fCurrentEntity, offset, fCurrentEntity.position - offset); return true; - } else if (c == '\n' && cc == '\r' && isExternal) { - // handle newlines - if (fCurrentEntity.position == fCurrentEntity.count) { - invokeListeners(1); - fCurrentEntity.ch[0] = (char)cc; - load(1, false, false); - } - fCurrentEntity.position++; - if (fCurrentEntity.ch[fCurrentEntity.position] == '\n') { - fCurrentEntity.position++; - } - fCurrentEntity.lineNumber++; - fCurrentEntity.columnNumber = 1; - if (DEBUG_BUFFER) { - System.out.print(")skipChar, '"+(char)c+"': "); - print(); - System.out.println(" -> true"); - } - checkEntityLimit(nt, fCurrentEntity, offset, fCurrentEntity.position - offset); - return true; } // character was not skipped @@ -1659,7 +1445,7 @@ public class XMLEntityScanner implements XMLLocator { // skip spaces int c = fCurrentEntity.ch[fCurrentEntity.position]; - int offset = fCurrentEntity.position - 1; + offset = fCurrentEntity.position - 1; if (XMLChar.isSpace(c)) { do { boolean entityChanged = false; @@ -2332,5 +2118,86 @@ public class XMLEntityScanner implements XMLLocator { } // skipDeclSpaces():boolean + /** + * Normalizes newlines. As specified in XML specification, this method + * converts newlines, '\n', '\r' and '\r\n' to '\n' as 2.11 End-of-Line Handling. + * Further, it may put them in a cache for later process as needed, for example + * as specified in 3.3.3 Attribute-Value Normalization. + * + * @ImplNote this method does not limit to processing external parsed entities + * as 2.11 required. It handles all cases where newlines need to be processed. + * + * @param buffer the current content buffer + * @param append a flag indicating whether to append to the buffer + * @param storeWS a flag indicating whether the whitespaces need to be stored + * for later processing + * @param nt the type of the entity + * @return true if the cursor is at the end of the current entity, false otherwise. + * @throws IOException + */ + protected boolean normalizeNewlines(short version, XMLString buffer, boolean append, + boolean storeWS, NameType nt) + throws IOException { + // normalize newlines + offset = fCurrentEntity.position; + int c = fCurrentEntity.ch[offset]; + newlines = 0; + // how this information is used is determined by the caller of this method + counted = false; + if ((c == '\n' || c == '\r') || + (version == XML_VERSION_1_1 && (c == 0x85 || c == 0x2028))) { + do { + c = fCurrentEntity.ch[fCurrentEntity.position++]; + if ((c == '\n' || c == '\r') || + (version == XML_VERSION_1_1 && (c == 0x85 || c == 0x2028))) { + newlines++; + fCurrentEntity.lineNumber++; + fCurrentEntity.columnNumber = 1; + if (fCurrentEntity.position == fCurrentEntity.count) { + checkEntityLimit(nt, fCurrentEntity, offset, newlines); + offset = 0; + fCurrentEntity.position = newlines; + if (load(newlines, false, true)) { + counted = true; + break; + } + } + if (c == '\r') { + int cc = fCurrentEntity.ch[fCurrentEntity.position]; + if (cc == '\n' || (version == XML_VERSION_1_1 && cc == 0x85)) { + fCurrentEntity.position++; + offset++; + } + /*** NEWLINE NORMALIZATION ***/ + else { + newlines++; + } + } + } else { + fCurrentEntity.position--; + break; + } + } while (fCurrentEntity.position < fCurrentEntity.count - 1); + + for (int i = offset; i < fCurrentEntity.position; i++) { + fCurrentEntity.ch[i] = '\n'; + if (storeWS) { + storeWhiteSpace(i); + } + } + int length = fCurrentEntity.position - offset; + if (fCurrentEntity.position == fCurrentEntity.count - 1) { + checkEntityLimit(nt, fCurrentEntity, offset, length); + if (append) { + buffer.append(fCurrentEntity.ch, offset, length); + } else { + buffer.setValues(fCurrentEntity.ch, offset, length); + } + + return true; + } + } + return false; + } } // class XMLEntityScanner diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLScanner.java b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLScanner.java index 6a6362199c5..2102b8558fa 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLScanner.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLScanner.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -67,7 +67,7 @@ import com.sun.xml.internal.stream.Entity; * @author Eric Ye, IBM * @author K.Venugopal SUN Microsystems * @author Sunitha Reddy, SUN Microsystems - * @LastModified: Feb 2020 + * @LastModified: Aug 2021 */ public abstract class XMLScanner implements XMLComponent { @@ -956,12 +956,6 @@ public abstract class XMLScanner System.out.println("** valueF: \"" + stringBuffer.toString() + "\""); } - } else if (c == '\n' || c == '\r') { - fEntityScanner.scanChar(null); - stringBuffer.append(' '); - if (entityDepth == fEntityDepth && fNeedNonNormalizedValue) { - fStringBuffer2.append('\n'); - } } else if (c != -1 && XMLChar.isHighSurrogate(c)) { fStringBuffer3.clear(); if (scanSurrogates(fStringBuffer3)) { diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/XMLStringBuffer.java b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/XMLStringBuffer.java index 9e915738423..118aeb7ad96 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/XMLStringBuffer.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/XMLStringBuffer.java @@ -1,6 +1,5 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -41,19 +40,11 @@ import com.sun.org.apache.xerces.internal.xni.XMLString; * * @author Andy Clark, IBM * @author Eric Ye, IBM - * + * @LastModified: Aug 2021 */ public class XMLStringBuffer extends XMLString { - // - // Constants - // - - - /** Default buffer size (32). */ - public static final int DEFAULT_SIZE = 32; - // // Data // @@ -112,79 +103,4 @@ extends XMLString { length = 0; } - /** - * append - * - * @param c - */ - public void append(char c) { - if(this.length + 1 > this.ch.length){ - int newLength = this.ch.length * 2 ; - if(newLength < this.ch.length + DEFAULT_SIZE){ - newLength = this.ch.length + DEFAULT_SIZE; - } - char [] tmp = new char[newLength]; - System.arraycopy(this.ch, 0, tmp, 0, this.length); - this.ch = tmp; - } - this.ch[this.length] = c ; - this.length++; - } // append(char) - - /** - * append - * - * @param s - */ - public void append(String s) { - int length = s.length(); - if (this.length + length > this.ch.length) { - int newLength = this.ch.length * 2 ; - if(newLength < this.ch.length + length + DEFAULT_SIZE){ - newLength = this.ch.length + length+ DEFAULT_SIZE; - } - - char[] newch = new char[newLength]; - System.arraycopy(this.ch, 0, newch, 0, this.length); - this.ch = newch; - } - s.getChars(0, length, this.ch, this.length); - this.length += length; - } // append(String) - - /** - * append - * - * @param ch - * @param offset - * @param length - */ - public void append(char[] ch, int offset, int length) { - if (this.length + length > this.ch.length) { - int newLength = this.ch.length * 2 ; - if(newLength < this.ch.length + length + DEFAULT_SIZE){ - newLength = this.ch.length + length + DEFAULT_SIZE; - } - char[] newch = new char[newLength]; - System.arraycopy(this.ch, 0, newch, 0, this.length); - this.ch = newch; - } - //making the code more robust as it would handle null or 0 length data, - //add the data only when it contains some thing - if(ch != null && length > 0){ - System.arraycopy(ch, offset, this.ch, this.length, length); - this.length += length; - } - } // append(char[],int,int) - - /** - * append - * - * @param s - */ - public void append(XMLString s) { - append(s.ch, s.offset, s.length); - } // append(XMLString) - - } // class XMLStringBuffer diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/xni/XMLString.java b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/xni/XMLString.java index f63e1d20aa6..9d26c252651 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/xni/XMLString.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/xni/XMLString.java @@ -1,6 +1,5 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -42,9 +41,11 @@ package com.sun.org.apache.xerces.internal.xni; * * @author Eric Ye, IBM * @author Andy Clark, IBM - * + * @LastModified: Aug 2021 */ public class XMLString { + /** Default buffer size (32). */ + public static final int DEFAULT_SIZE = 32; // // Data @@ -189,4 +190,78 @@ public class XMLString { return length > 0 ? new String(ch, offset, length) : ""; } // toString():String + /** + * Appends a char to the buffer. + * + * @param c the char + */ + public void append(char c) { + if(this.length + 1 > this.ch.length){ + int newLength = this.ch.length * 2 ; + if(newLength < this.ch.length + DEFAULT_SIZE){ + newLength = this.ch.length + DEFAULT_SIZE; + } + char [] tmp = new char[newLength]; + System.arraycopy(this.ch, 0, tmp, 0, this.length); + this.ch = tmp; + } + this.ch[this.length] = c ; + this.length++; + } // append(char) + + /** + * Appends a string to the buffer. + * + * @param s the string + */ + public void append(String s) { + int length = s.length(); + if (this.length + length > this.ch.length) { + int newLength = this.ch.length * 2 ; + if(newLength < this.ch.length + length + DEFAULT_SIZE){ + newLength = this.ch.length + length+ DEFAULT_SIZE; + } + + char[] newch = new char[newLength]; + System.arraycopy(this.ch, 0, newch, 0, this.length); + this.ch = newch; + } + s.getChars(0, length, this.ch, this.length); + this.length += length; + } // append(String) + + /** + * Appends a number of characters to the buffer. + * + * @param ch the char array + * @param offset the offset + * @param length the length + */ + public void append(char[] ch, int offset, int length) { + if (this.length + length > this.ch.length) { + int newLength = this.ch.length * 2 ; + if(newLength < this.ch.length + length + DEFAULT_SIZE){ + newLength = this.ch.length + length + DEFAULT_SIZE; + } + char[] newch = new char[newLength]; + System.arraycopy(this.ch, 0, newch, 0, this.length); + this.ch = newch; + } + //making the code more robust as it would handle null or 0 length data, + //add the data only when it contains some thing + if(ch != null && length > 0){ + System.arraycopy(ch, offset, this.ch, this.length, length); + this.length += length; + } + } // append(char[],int,int) + + /** + * Appends another buffer to this buffer + * + * @param s another buffer + */ + public void append(XMLString s) { + append(s.ch, s.offset, s.length); + } // append(XMLString) + } // class XMLString -- GitLab From afd0dc76b684f03d2de665f3150c93ce17bafbe0 Mon Sep 17 00:00:00 2001 From: Phil Race Date: Tue, 17 Aug 2021 20:56:54 +0000 Subject: [PATCH 173/564] 8271962: Better TrueType font loading Reviewed-by: psadhukhan, jdv, mschoene, rhalade --- .../share/classes/sun/font/TrueTypeFont.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/java.desktop/share/classes/sun/font/TrueTypeFont.java b/src/java.desktop/share/classes/sun/font/TrueTypeFont.java index b3afe089132..856297643cf 100644 --- a/src/java.desktop/share/classes/sun/font/TrueTypeFont.java +++ b/src/java.desktop/share/classes/sun/font/TrueTypeFont.java @@ -503,7 +503,9 @@ public class TrueTypeFont extends FileFont { /* checksum */ ibuffer.get(); table.offset = ibuffer.get() & 0x7FFFFFFF; table.length = ibuffer.get() & 0x7FFFFFFF; - if (table.offset + table.length > fileSize) { + if ((table.offset + table.length < table.length) || + (table.offset + table.length > fileSize)) + { throw new FontFormatException("bad table, tag="+table.tag); } } @@ -798,8 +800,11 @@ public class TrueTypeFont extends FileFont { break; } } + if (entry == null || entry.length == 0 || - entry.offset+entry.length > fileSize) { + (entry.offset + entry.length < entry.length) || + (entry.offset + entry.length > fileSize)) + { return null; } @@ -888,6 +893,9 @@ public class TrueTypeFont extends FileFont { return false; } ByteBuffer eblcTable = getTableBuffer(EBLCTag); + if (eblcTable == null) { + return false; + } int numSizes = eblcTable.getInt(4); /* The bitmapSizeTable's start at offset of 8. * Each bitmapSizeTable entry is 48 bytes. -- GitLab From 518160353a96a75fd666f0e426ad649fb58f5fc5 Mon Sep 17 00:00:00 2001 From: Kevin Walls Date: Fri, 20 Aug 2021 07:46:35 +0000 Subject: [PATCH 174/564] 8272272: Enhance jcmd communication Reviewed-by: amenkov --- src/jdk.attach/windows/native/libattach/VirtualMachineImpl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/jdk.attach/windows/native/libattach/VirtualMachineImpl.c b/src/jdk.attach/windows/native/libattach/VirtualMachineImpl.c index a21ce9fa73b..f08a7c004b3 100644 --- a/src/jdk.attach/windows/native/libattach/VirtualMachineImpl.c +++ b/src/jdk.attach/windows/native/libattach/VirtualMachineImpl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2021, 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 @@ -399,6 +399,7 @@ JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_enqueue /* * Setup data to copy to target process */ + memset(&data, 0, sizeof(data)); data._GetModuleHandle = _GetModuleHandle; data._GetProcAddress = _GetProcAddress; -- GitLab From c372990f5f520f03159a6586862191e3f15ef6df Mon Sep 17 00:00:00 2001 From: Vladimir Ivanov Date: Fri, 20 Aug 2021 11:09:25 +0000 Subject: [PATCH 175/564] 8268494: Better inlining of inlined interfaces Reviewed-by: thartmann, jcm, ahgross, rhalade --- src/hotspot/share/c1/c1_GraphBuilder.cpp | 12 +++++----- src/hotspot/share/code/dependencies.cpp | 28 ++++++++++++++++++++++++ src/hotspot/share/code/dependencies.hpp | 12 ++++++++-- src/hotspot/share/opto/doCall.cpp | 4 +++- 4 files changed, 47 insertions(+), 9 deletions(-) diff --git a/src/hotspot/share/c1/c1_GraphBuilder.cpp b/src/hotspot/share/c1/c1_GraphBuilder.cpp index 0274505f8fe..abd7af1a62d 100644 --- a/src/hotspot/share/c1/c1_GraphBuilder.cpp +++ b/src/hotspot/share/c1/c1_GraphBuilder.cpp @@ -2036,19 +2036,19 @@ void GraphBuilder::invoke(Bytecodes::Code code) { cha_monomorphic_target = target->find_monomorphic_target(calling_klass, declared_interface, singleton); if (cha_monomorphic_target != NULL) { if (cha_monomorphic_target->holder() != compilation()->env()->Object_klass()) { - // If CHA is able to bind this invoke then update the class - // to match that class, otherwise klass will refer to the - // interface. - klass = cha_monomorphic_target->holder(); + ciInstanceKlass* holder = cha_monomorphic_target->holder(); + ciInstanceKlass* constraint = (holder->is_subtype_of(singleton) ? holder : singleton); // avoid upcasts actual_recv = declared_interface; // insert a check it's really the expected class. - CheckCast* c = new CheckCast(klass, receiver, copy_state_for_exception()); + CheckCast* c = new CheckCast(constraint, receiver, copy_state_for_exception()); c->set_incompatible_class_change_check(); - c->set_direct_compare(klass->is_final()); + c->set_direct_compare(constraint->is_final()); // pass the result of the checkcast so that the compiler has // more accurate type info in the inlinee better_receiver = append_split(c); + + dependency_recorder()->assert_unique_implementor(declared_interface, singleton); } else { cha_monomorphic_target = NULL; // subtype check against Object is useless } diff --git a/src/hotspot/share/code/dependencies.cpp b/src/hotspot/share/code/dependencies.cpp index 8ca9c59fc82..e150b300b7b 100644 --- a/src/hotspot/share/code/dependencies.cpp +++ b/src/hotspot/share/code/dependencies.cpp @@ -116,6 +116,12 @@ void Dependencies::assert_unique_concrete_method(ciKlass* ctxk, ciMethod* uniqm, } } +void Dependencies::assert_unique_implementor(ciInstanceKlass* ctxk, ciInstanceKlass* uniqk) { + check_ctxk(ctxk); + check_unique_implementor(ctxk, uniqk); + assert_common_2(unique_implementor, ctxk, uniqk); +} + void Dependencies::assert_has_no_finalizable_subclasses(ciKlass* ctxk) { check_ctxk(ctxk); assert_common_1(no_finalizable_subclasses, ctxk); @@ -173,6 +179,13 @@ void Dependencies::assert_abstract_with_unique_concrete_subtype(Klass* ctxk, Kla assert_common_2(abstract_with_unique_concrete_subtype, ctxk_dv, conck_dv); } +void Dependencies::assert_unique_implementor(InstanceKlass* ctxk, InstanceKlass* uniqk) { + check_ctxk(ctxk); + assert(ctxk->is_interface(), "not an interface"); + assert(ctxk->implementor() == uniqk, "not a unique implementor"); + assert_common_2(unique_implementor, DepValue(_oop_recorder, ctxk), DepValue(_oop_recorder, uniqk)); +} + void Dependencies::assert_unique_concrete_method(Klass* ctxk, Method* uniqm) { check_ctxk(ctxk); check_unique_method(ctxk, uniqm); @@ -580,6 +593,7 @@ const char* Dependencies::_dep_name[TYPE_LIMIT] = { "abstract_with_unique_concrete_subtype", "unique_concrete_method_2", "unique_concrete_method_4", + "unique_implementor", "no_finalizable_subclasses", "call_site_target_value" }; @@ -591,6 +605,7 @@ int Dependencies::_dep_args[TYPE_LIMIT] = { 2, // abstract_with_unique_concrete_subtype ctxk, k 2, // unique_concrete_method_2 ctxk, m 4, // unique_concrete_method_4 ctxk, m, resolved_klass, resolved_method + 2, // unique_implementor ctxk, implementor 1, // no_finalizable_subclasses ctxk 2 // call_site_target_value call_site, method_handle }; @@ -1813,6 +1828,16 @@ Klass* Dependencies::check_unique_concrete_method(InstanceKlass* ctxk, return NULL; } +Klass* Dependencies::check_unique_implementor(InstanceKlass* ctxk, Klass* uniqk, NewKlassDepChange* changes) { + assert(ctxk->is_interface(), "sanity"); + assert(ctxk->nof_implementors() > 0, "no implementors"); + if (ctxk->nof_implementors() == 1) { + assert(ctxk->implementor() == uniqk, "sanity"); + return NULL; + } + return ctxk; // no unique implementor +} + // Search for AME. // There are two version of checks. // 1) Spot checking version(Classload time). Newly added class is checked for AME. @@ -2062,6 +2087,9 @@ Klass* Dependencies::DepStream::check_new_klass_dependency(NewKlassDepChange* ch case unique_concrete_method_4: witness = check_unique_concrete_method(context_type(), method_argument(1), type_argument(2), method_argument(3), changes); break; + case unique_implementor: + witness = check_unique_implementor(context_type(), type_argument(1), changes); + break; case no_finalizable_subclasses: witness = check_has_no_finalizable_subclasses(context_type(), changes); break; diff --git a/src/hotspot/share/code/dependencies.hpp b/src/hotspot/share/code/dependencies.hpp index 104fc9ee649..0d8fa9fa48c 100644 --- a/src/hotspot/share/code/dependencies.hpp +++ b/src/hotspot/share/code/dependencies.hpp @@ -143,6 +143,9 @@ class Dependencies: public ResourceObj { // of the analysis. unique_concrete_method_4, // one unique concrete method under CX + // This dependency asserts that interface CX has a unique implementor class. + unique_implementor, // one unique implementor under CX + // This dependency asserts that no instances of class or it's // subclasses require finalization registration. no_finalizable_subclasses, @@ -329,7 +332,10 @@ class Dependencies: public ResourceObj { assert(!is_concrete_klass(ctxk->as_instance_klass()), "must be abstract"); } static void check_unique_method(ciKlass* ctxk, ciMethod* m) { - assert(!m->can_be_statically_bound(ctxk->as_instance_klass()), "redundant"); + assert(!m->can_be_statically_bound(ctxk->as_instance_klass()) || ctxk->is_interface(), "redundant"); + } + static void check_unique_implementor(ciInstanceKlass* ctxk, ciInstanceKlass* uniqk) { + assert(ctxk->implementor() == uniqk, "not a unique implementor"); } void assert_common_1(DepType dept, ciBaseObject* x); @@ -343,9 +349,9 @@ class Dependencies: public ResourceObj { void assert_abstract_with_unique_concrete_subtype(ciKlass* ctxk, ciKlass* conck); void assert_unique_concrete_method(ciKlass* ctxk, ciMethod* uniqm); void assert_unique_concrete_method(ciKlass* ctxk, ciMethod* uniqm, ciKlass* resolved_klass, ciMethod* resolved_method); + void assert_unique_implementor(ciInstanceKlass* ctxk, ciInstanceKlass* uniqk); void assert_has_no_finalizable_subclasses(ciKlass* ctxk); void assert_call_site_target_value(ciCallSite* call_site, ciMethodHandle* method_handle); - #if INCLUDE_JVMCI private: static void check_ctxk(Klass* ctxk) { @@ -366,6 +372,7 @@ class Dependencies: public ResourceObj { void assert_evol_method(Method* m); void assert_has_no_finalizable_subclasses(Klass* ctxk); void assert_leaf_type(Klass* ctxk); + void assert_unique_implementor(InstanceKlass* ctxk, InstanceKlass* uniqk); void assert_unique_concrete_method(Klass* ctxk, Method* uniqm); void assert_abstract_with_unique_concrete_subtype(Klass* ctxk, Klass* conck); void assert_call_site_target_value(oop callSite, oop methodHandle); @@ -413,6 +420,7 @@ class Dependencies: public ResourceObj { static Klass* check_evol_method(Method* m); static Klass* check_leaf_type(InstanceKlass* ctxk); static Klass* check_abstract_with_unique_concrete_subtype(InstanceKlass* ctxk, Klass* conck, NewKlassDepChange* changes = NULL); + static Klass* check_unique_implementor(InstanceKlass* ctxk, Klass* uniqk, NewKlassDepChange* changes = NULL); static Klass* check_unique_concrete_method(InstanceKlass* ctxk, Method* uniqm, NewKlassDepChange* changes = NULL); static Klass* check_unique_concrete_method(InstanceKlass* ctxk, Method* uniqm, Klass* resolved_klass, Method* resolved_method, KlassDepChange* changes = NULL); static Klass* check_has_no_finalizable_subclasses(InstanceKlass* ctxk, NewKlassDepChange* changes = NULL); diff --git a/src/hotspot/share/opto/doCall.cpp b/src/hotspot/share/opto/doCall.cpp index f666af6b9ab..f034aacae62 100644 --- a/src/hotspot/share/opto/doCall.cpp +++ b/src/hotspot/share/opto/doCall.cpp @@ -332,8 +332,10 @@ CallGenerator* Compile::call_generator(ciMethod* callee, int vtable_index, bool CallGenerator* miss_cg = CallGenerator::for_uncommon_trap(callee, Deoptimization::Reason_class_check, Deoptimization::Action_none); - CallGenerator* cg = CallGenerator::for_guarded_call(holder, miss_cg, hit_cg); + ciKlass* constraint = (holder->is_subclass_of(singleton) ? holder : singleton); // avoid upcasts + CallGenerator* cg = CallGenerator::for_guarded_call(constraint, miss_cg, hit_cg); if (hit_cg != NULL && cg != NULL) { + dependencies()->assert_unique_implementor(declared_interface, singleton); dependencies()->assert_unique_concrete_method(declared_interface, cha_monomorphic_target, declared_interface, callee); return cg; } -- GitLab From 6b6f829b46ef158775e66f36336895080cab9df6 Mon Sep 17 00:00:00 2001 From: Anthony Scarpino Date: Mon, 23 Aug 2021 16:06:31 +0000 Subject: [PATCH 176/564] 8269151: Better construction of EncryptedPrivateKeyInfo Reviewed-by: jnimeh, mschoene, rhalade --- .../javax/crypto/EncryptedPrivateKeyInfo.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/java.base/share/classes/javax/crypto/EncryptedPrivateKeyInfo.java b/src/java.base/share/classes/javax/crypto/EncryptedPrivateKeyInfo.java index 59b4a07f349..09c69748d5a 100644 --- a/src/java.base/share/classes/javax/crypto/EncryptedPrivateKeyInfo.java +++ b/src/java.base/share/classes/javax/crypto/EncryptedPrivateKeyInfo.java @@ -77,15 +77,18 @@ public class EncryptedPrivateKeyInfo { * @exception NullPointerException if the encoded is null. * @exception IOException if error occurs when parsing the ASN.1 encoding. */ - public EncryptedPrivateKeyInfo(byte[] encoded) - throws IOException { + public EncryptedPrivateKeyInfo(byte[] encoded) throws IOException { if (encoded == null) { throw new NullPointerException("the encoded parameter " + - "must be non-null"); + "must be non-null"); } - this.encoded = encoded.clone(); - DerValue val = new DerValue(this.encoded); + DerValue val = new DerValue(encoded); + if (val.tag != DerValue.tag_Sequence) { + throw new IOException("DER header error: no SEQ tag"); + } + + this.encoded = encoded.clone(); DerValue[] seq = new DerValue[2]; seq[0] = val.data.getDerValue(); -- GitLab From 5832a3440489d0967dc3b0542c1ace51eed292d6 Mon Sep 17 00:00:00 2001 From: Julia Boes Date: Wed, 25 Aug 2021 11:41:26 +0000 Subject: [PATCH 177/564] 8270416: Enhance construction of Identity maps Reviewed-by: dfuchs, chegar, rhalade, ahgross, smarks, robm --- .../share/classes/java/util/Hashtable.java | 37 +++++++++++++------ .../classes/java/util/IdentityHashMap.java | 22 ++++++----- .../util/Hashtable/DeserializedLength.java | 4 +- 3 files changed, 41 insertions(+), 22 deletions(-) diff --git a/src/java.base/share/classes/java/util/Hashtable.java b/src/java.base/share/classes/java/util/Hashtable.java index c103df55790..2b6f6e72540 100644 --- a/src/java.base/share/classes/java/util/Hashtable.java +++ b/src/java.base/share/classes/java/util/Hashtable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2021, 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 @@ -1254,7 +1254,7 @@ public class Hashtable * Reconstitute the Hashtable from a stream (i.e., deserialize it). */ @java.io.Serial - private void readObject(java.io.ObjectInputStream s) + private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { readHashtable(s); } @@ -1263,14 +1263,16 @@ public class Hashtable * Perform deserialization of the Hashtable from an ObjectInputStream. * The Properties class overrides this method. */ - void readHashtable(java.io.ObjectInputStream s) + void readHashtable(ObjectInputStream s) throws IOException, ClassNotFoundException { - // Read in the threshold and loadFactor - s.defaultReadObject(); - // Validate loadFactor (ignore threshold - it will be re-computed) - if (loadFactor <= 0 || Float.isNaN(loadFactor)) - throw new StreamCorruptedException("Illegal Load: " + loadFactor); + ObjectInputStream.GetField fields = s.readFields(); + + // Read and validate loadFactor (ignore threshold - it will be re-computed) + float lf = fields.get("loadFactor", 0.75f); + if (lf <= 0 || Float.isNaN(lf)) + throw new StreamCorruptedException("Illegal load factor: " + lf); + lf = Math.min(Math.max(0.25f, lf), 4.0f); // Read the original length of the array and number of elements int origlength = s.readInt(); @@ -1282,13 +1284,13 @@ public class Hashtable // Clamp original length to be more than elements / loadFactor // (this is the invariant enforced with auto-growth) - origlength = Math.max(origlength, (int)(elements / loadFactor) + 1); + origlength = Math.max(origlength, (int)(elements / lf) + 1); // Compute new length with a bit of room 5% + 3 to grow but // no larger than the clamped original length. Make the length // odd if it's large enough, this helps distribute the entries. // Guard against the length ending up zero, that's not valid. - int length = (int)((elements + elements / 20) / loadFactor) + 3; + int length = (int)((elements + elements / 20) / lf) + 3; if (length > elements && (length & 1) == 0) length--; length = Math.min(length, origlength); @@ -1300,8 +1302,9 @@ public class Hashtable // Check Map.Entry[].class since it's the nearest public type to // what we're actually creating. SharedSecrets.getJavaObjectInputStreamAccess().checkArray(s, Map.Entry[].class, length); + Hashtable.UnsafeHolder.putLoadFactor(this, lf); table = new Entry[length]; - threshold = (int)Math.min(length * loadFactor, MAX_ARRAY_SIZE + 1); + threshold = (int)Math.min(length * lf, MAX_ARRAY_SIZE + 1); count = 0; // Read the number of elements and then all the key/value objects @@ -1315,6 +1318,18 @@ public class Hashtable } } + // Support for resetting final field during deserializing + private static final class UnsafeHolder { + private UnsafeHolder() { throw new InternalError(); } + private static final jdk.internal.misc.Unsafe unsafe + = jdk.internal.misc.Unsafe.getUnsafe(); + private static final long LF_OFFSET + = unsafe.objectFieldOffset(Hashtable.class, "loadFactor"); + static void putLoadFactor(Hashtable table, float lf) { + unsafe.putFloat(table, LF_OFFSET, lf); + } + } + /** * The put method used by readObject. This is provided because put * is overridable and should not be called in readObject since the diff --git a/src/java.base/share/classes/java/util/IdentityHashMap.java b/src/java.base/share/classes/java/util/IdentityHashMap.java index 34d6722ac09..4795c30b3d5 100644 --- a/src/java.base/share/classes/java/util/IdentityHashMap.java +++ b/src/java.base/share/classes/java/util/IdentityHashMap.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,8 @@ package java.util; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.lang.reflect.Array; import java.util.function.BiConsumer; import java.util.function.BiFunction; @@ -1267,12 +1269,12 @@ public class IdentityHashMap * particular order. */ @java.io.Serial - private void writeObject(java.io.ObjectOutputStream s) + private void writeObject(ObjectOutputStream s) throws java.io.IOException { - // Write out and any hidden stuff + // Write out size (number of mappings) and any hidden stuff s.defaultWriteObject(); - // Write out size (number of Mappings) + // Write out size again (maintained for backward compatibility) s.writeInt(size); // Write out keys and values (alternating) @@ -1291,18 +1293,20 @@ public class IdentityHashMap * deserializes it). */ @java.io.Serial - private void readObject(java.io.ObjectInputStream s) + private void readObject(ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { - // Read in any hidden stuff - s.defaultReadObject(); + // Size (number of mappings) is written to the stream twice + // Read first size value and ignore it + s.readFields(); - // Read in size (number of Mappings) + // Read second size value, validate and assign to size field int size = s.readInt(); if (size < 0) throw new java.io.StreamCorruptedException ("Illegal mappings count: " + size); int cap = capacity(size); - SharedSecrets.getJavaObjectInputStreamAccess().checkArray(s, Object[].class, cap); + SharedSecrets.getJavaObjectInputStreamAccess().checkArray(s, Object[].class, cap*2); + this.size = size; init(cap); // Read the keys and values, and put the mappings in the table diff --git a/test/jdk/java/util/Hashtable/DeserializedLength.java b/test/jdk/java/util/Hashtable/DeserializedLength.java index 376c1f026d0..d515878fd36 100644 --- a/test/jdk/java/util/Hashtable/DeserializedLength.java +++ b/test/jdk/java/util/Hashtable/DeserializedLength.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2021, 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 @@ -100,7 +100,7 @@ public class DeserializedLength { ); for (int elements : new int[]{10, 50, 500, 5000}) { - for (float loadFactor : new float[]{0.15f, 0.5f, 0.75f, 1.0f, 2.5f}) { + for (float loadFactor : new float[]{0.25f, 0.5f, 0.75f, 1.0f, 2.5f}) { ok &= testDeserializedLength(elements, loadFactor); } } -- GitLab From 4be02d31554b8d3bb84789923cf64a7dc4707eff Mon Sep 17 00:00:00 2001 From: Harold Seigel Date: Thu, 2 Sep 2021 18:09:33 +0000 Subject: [PATCH 178/564] 8271987: Manifest improved manifest entries Reviewed-by: rhalade, dholmes --- src/hotspot/share/classfile/classLoader.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/hotspot/share/classfile/classLoader.cpp b/src/hotspot/share/classfile/classLoader.cpp index d5ac1c308fd..f42b1fe4751 100644 --- a/src/hotspot/share/classfile/classLoader.cpp +++ b/src/hotspot/share/classfile/classLoader.cpp @@ -303,13 +303,19 @@ u1* ClassPathZipEntry::open_entry(JavaThread* current, const char* name, jint* f } // read contents into resource array - int size = (*filesize) + ((nul_terminate) ? 1 : 0); + size_t size = (uint32_t)(*filesize); + if (nul_terminate) { + if (sizeof(size) == sizeof(uint32_t) && size == UINT_MAX) { + return NULL; // 32-bit integer overflow will occur. + } + size++; + } buffer = NEW_RESOURCE_ARRAY(u1, size); if (!(*ReadEntry)(_zip, entry, buffer, filename)) return NULL; // return result if (nul_terminate) { - buffer[*filesize] = 0; + buffer[size - 1] = 0; } return buffer; } -- GitLab From aa28430bdd8a5778f2e4307f198177b69eac9410 Mon Sep 17 00:00:00 2001 From: Ian Graves Date: Thu, 2 Sep 2021 19:20:30 +0000 Subject: [PATCH 179/564] 8268813: Better String matching Reviewed-by: mschoene, rhalade, smarks --- src/java.base/share/classes/java/util/regex/Pattern.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/java.base/share/classes/java/util/regex/Pattern.java b/src/java.base/share/classes/java/util/regex/Pattern.java index d52a2b92af9..352763a0f1f 100644 --- a/src/java.base/share/classes/java/util/regex/Pattern.java +++ b/src/java.base/share/classes/java/util/regex/Pattern.java @@ -3438,8 +3438,8 @@ loop: for(int x=0, offset=0; x= 0 && index < seq.length()); + if (lengthInCodePoints == 1 && index >= 0 && index < seq.length() && + !Character.isHighSurrogate(seq.charAt(index))) { return 1; } int length = seq.length(); -- GitLab From 3adc1117661ac0e9c819d6d9b32dd8a8a19a61ed Mon Sep 17 00:00:00 2001 From: Roger Riggs Date: Fri, 3 Sep 2021 19:10:21 +0000 Subject: [PATCH 180/564] 8272236: Improve serial forms for transport Reviewed-by: bchristi, rhalade, smarks --- src/java.base/share/classes/java/io/ObjectInputStream.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/java.base/share/classes/java/io/ObjectInputStream.java b/src/java.base/share/classes/java/io/ObjectInputStream.java index d6541b371d7..278ba9ce1d1 100644 --- a/src/java.base/share/classes/java/io/ObjectInputStream.java +++ b/src/java.base/share/classes/java/io/ObjectInputStream.java @@ -2566,6 +2566,13 @@ public class ObjectInputStream throw new InternalError(); } clear(); + // Check that an object follows the TC_EXCEPTION typecode + byte tc = bin.peekByte(); + if (tc != TC_OBJECT && + tc != TC_REFERENCE) { + throw new StreamCorruptedException( + String.format("invalid type code: %02X", tc)); + } return (IOException) readObject0(Object.class, false); } -- GitLab From 78b2c8419bc69436873e6fc9c542480949d140c5 Mon Sep 17 00:00:00 2001 From: Joe Wang Date: Thu, 9 Sep 2021 17:41:56 +0000 Subject: [PATCH 181/564] 8270492: Better resolution of URIs Reviewed-by: lancea, naoto, ahgross, rhalade --- .../internal/xsltc/dom/LoadDocument.java | 5 ++- .../xsltc/runtime/AbstractTranslet.java | 19 +++++++++++- .../internal/xsltc/trax/TransformerImpl.java | 31 +++++++++++++++++-- .../xml/internal/utils/SystemIDResolver.java | 7 +++-- 4 files changed, 54 insertions(+), 8 deletions(-) diff --git a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/LoadDocument.java b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/LoadDocument.java index bc7194411f0..39084c87f0b 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/LoadDocument.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/LoadDocument.java @@ -39,7 +39,7 @@ import jdk.xml.internal.SecuritySupport; /** * @author Morten Jorgensen - * @LastModified: May 2021 + * @LastModified: Sept 2021 */ public final class LoadDocument { @@ -190,6 +190,9 @@ public final class LoadDocument { if (cache != null) { newdom = cache.retrieveDocument(base, originalUri, translet); if (newdom == null) { + if (translet.getAccessError() != null) { + throw new Exception(translet.getAccessError()); + } final Exception e = new FileNotFoundException(originalUri); throw new TransletException(e); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/AbstractTranslet.java b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/AbstractTranslet.java index 58b8f433e8e..1612fd61923 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/AbstractTranslet.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/AbstractTranslet.java @@ -54,7 +54,7 @@ import org.w3c.dom.Document; * @author Morten Jorgensen * @author G. Todd Miller * @author John Howard, JohnH@schemasoft.com - * @LastModified: May 2021 + * @LastModified: Sept 2021 */ public abstract class AbstractTranslet implements Translet { @@ -116,6 +116,9 @@ public abstract class AbstractTranslet implements Translet { */ private String _accessExternalStylesheet = JdkConstants.EXTERNAL_ACCESS_DEFAULT; + // The error message when access to exteranl resources is rejected + private String _accessErr = null; + /************************************************************************ * Debugging ************************************************************************/ @@ -786,6 +789,20 @@ public abstract class AbstractTranslet implements Translet { _accessExternalStylesheet = protocols; } + /** + * Returns the access error. + */ + public String getAccessError() { + return _accessErr; + } + + /** + * Sets the access error. + */ + public void setAccessError(String accessErr) { + this._accessErr = accessErr; + } + /************************************************************************ * DOMImplementation caching for basis library ************************************************************************/ diff --git a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerImpl.java b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerImpl.java index 9e266eec28f..b58eabc54d5 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerImpl.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerImpl.java @@ -101,7 +101,7 @@ import org.xml.sax.ext.LexicalHandler; * @author Morten Jorgensen * @author G. Todd Miller * @author Santiago Pericas-Geertsen - * @LastModified: June 2021 + * @LastModified: Sept 2021 */ public final class TransformerImpl extends Transformer implements DOMCache @@ -1351,8 +1351,33 @@ public final class TransformerImpl extends Transformer } if (resolvedSource == null) { - StreamSource streamSource = new StreamSource( - SystemIDResolver.getAbsoluteURI(href, baseURI)); + /** + * Uses the translet to carry over error msg. + * Performs the access check without any interface changes + * (e.g. Translet and DOMCache). + */ + @SuppressWarnings("unchecked") //AbstractTranslet is the sole impl. + AbstractTranslet t = (AbstractTranslet)translet; + String systemId = SystemIDResolver.getAbsoluteURI(href, baseURI); + String errMsg = null; + try { + String accessError = SecuritySupport.checkAccess(systemId, + t.getAllowedProtocols(), + JdkConstants.ACCESS_EXTERNAL_ALL); + if (accessError != null) { + ErrorMsg msg = new ErrorMsg(ErrorMsg.ACCESSING_XSLT_TARGET_ERR, + SecuritySupport.sanitizePath(href), accessError); + errMsg = msg.toString(); + } + } catch (IOException ioe) { + errMsg = ioe.getMessage(); + } + if (errMsg != null) { + t.setAccessError(errMsg); + return null; + } + + StreamSource streamSource = new StreamSource(systemId); return getDOM(streamSource) ; } diff --git a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/utils/SystemIDResolver.java b/src/java.xml/share/classes/com/sun/org/apache/xml/internal/utils/SystemIDResolver.java index de383ca3e9d..caf2a4b1ba7 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/utils/SystemIDResolver.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xml/internal/utils/SystemIDResolver.java @@ -1,6 +1,5 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -35,6 +34,8 @@ import com.sun.org.apache.xml.internal.utils.URI.MalformedURIException; * fact that it's declared to throw TransformerException. Please * see code comments for details on how resolution is performed.

    * @xsl.usage internal + * + * @LastModified: Sept 2021 */ public class SystemIDResolver { @@ -275,7 +276,7 @@ public class SystemIDResolver public static String getAbsoluteURI(String urlString, String base) throws TransformerException { - if (base == null) + if (base == null || base.length() == 0) return getAbsoluteURI(urlString); String absoluteBase = getAbsoluteURI(base); -- GitLab From ae7877df2e417acecb2fd8d03dec2e5eac4e8879 Mon Sep 17 00:00:00 2001 From: Alexander Zuev Date: Tue, 14 Sep 2021 23:19:33 +0000 Subject: [PATCH 182/564] 8273290: Enhance sound handling Reviewed-by: rhalade, ahgross, prr, jdv --- .../classes/com/sun/media/sound/StandardMidiFileReader.java | 4 ++++ .../classes/com/sun/media/sound/WaveFloatFileReader.java | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/java.desktop/share/classes/com/sun/media/sound/StandardMidiFileReader.java b/src/java.desktop/share/classes/com/sun/media/sound/StandardMidiFileReader.java index e13bae6ce92..6f5a4bbf3c9 100644 --- a/src/java.desktop/share/classes/com/sun/media/sound/StandardMidiFileReader.java +++ b/src/java.desktop/share/classes/com/sun/media/sound/StandardMidiFileReader.java @@ -392,6 +392,10 @@ final class SMFParser { // meta int metaType = readUnsigned(); int metaLength = (int) readVarInt(); + if (metaLength < 0) { + throw new InvalidMidiDataException("length out of bounds: " + + metaLength); + } final byte[] metaData; try { metaData = new byte[metaLength]; diff --git a/src/java.desktop/share/classes/com/sun/media/sound/WaveFloatFileReader.java b/src/java.desktop/share/classes/com/sun/media/sound/WaveFloatFileReader.java index 2c3be1507fc..f8365f71780 100644 --- a/src/java.desktop/share/classes/com/sun/media/sound/WaveFloatFileReader.java +++ b/src/java.desktop/share/classes/com/sun/media/sound/WaveFloatFileReader.java @@ -73,6 +73,10 @@ public final class WaveFloatFileReader extends SunFileReader { samplerate = chunk.readUnsignedInt(); /* framerate = */chunk.readUnsignedInt(); framesize = chunk.readUnsignedShort(); + if (framesize == 0) { + throw new UnsupportedAudioFileException( + "Can not process audio format with 0 frame size"); + } bits = chunk.readUnsignedShort(); } if (chunk.getFormat().equals("data")) { -- GitLab From cb7482d5bdb7e0e275ae179ae57b56e881180523 Mon Sep 17 00:00:00 2001 From: Christian Hagedorn Date: Mon, 20 Sep 2021 07:35:25 +0000 Subject: [PATCH 183/564] 8272014: Better array indexing Reviewed-by: thartmann, rhalade, ahgross, kvn --- .../cpu/aarch64/c1_LIRGenerator_aarch64.cpp | 28 +++++++++++++++++-- src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp | 28 +++++++++++++++++-- 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp index 0a97872900e..11f3ce45e7f 100644 --- a/src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp @@ -207,8 +207,32 @@ LIR_Address* LIRGenerator::emit_array_address(LIR_Opr array_opr, LIR_Opr index_o LIR_Address* addr; if (index_opr->is_constant()) { - addr = new LIR_Address(array_opr, - offset_in_bytes + (intx)(index_opr->as_jint()) * elem_size, type); +#ifdef _LP64 + jint index = index_opr->as_jint(); + jlong disp = offset_in_bytes + (jlong)(index) * elem_size; + if (disp > max_jint) { + // Displacement overflow. Cannot directly use instruction with 32-bit displacement for 64-bit addresses. + // Convert array index to long to do array offset computation with 64-bit values. + index_opr = new_register(T_LONG); + __ move(LIR_OprFact::longConst(index), index_opr); + addr = new LIR_Address(array_opr, index_opr, LIR_Address::scale(type), offset_in_bytes, type); + } else { + addr = new LIR_Address(array_opr, (intx)disp, type); + } +#else + // A displacement overflow can also occur for x86 but that is not a problem due to the 32-bit address range! + // Let's assume an array 'a' and an access with displacement 'disp'. When disp overflows, then "a + disp" will + // always be negative (i.e. underflows the 32-bit address range): + // Let N = 2^32: a + signed_overflow(disp) = a + disp - N. + // "a + disp" is always smaller than N. If an index was chosen which would point to an address beyond N, then + // range checks would catch that and throw an exception. Thus, a + disp < 0 holds which means that it always + // underflows the 32-bit address range: + // unsigned_underflow(a + signed_overflow(disp)) = unsigned_underflow(a + disp - N) + // = (a + disp - N) + N = a + disp + // This shows that we still end up at the correct address with a displacement overflow due to the 32-bit address + // range limitation. This overflow only needs to be handled if addresses can be larger as on 64-bit platforms. + addr = new LIR_Address(array_opr, offset_in_bytes + (intx)(index_opr->as_jint()) * elem_size, type); +#endif // _LP64 } else { if (offset_in_bytes) { LIR_Opr tmp = new_pointer_register(); diff --git a/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp b/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp index 0b62108c79f..819c36957b3 100644 --- a/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp +++ b/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp @@ -192,8 +192,32 @@ LIR_Address* LIRGenerator::emit_array_address(LIR_Opr array_opr, LIR_Opr index_o LIR_Address* addr; if (index_opr->is_constant()) { int elem_size = type2aelembytes(type); - addr = new LIR_Address(array_opr, - offset_in_bytes + (intx)(index_opr->as_jint()) * elem_size, type); +#ifdef _LP64 + jint index = index_opr->as_jint(); + jlong disp = offset_in_bytes + (jlong)(index) * elem_size; + if (disp > max_jint) { + // Displacement overflow. Cannot directly use instruction with 32-bit displacement for 64-bit addresses. + // Convert array index to long to do array offset computation with 64-bit values. + index_opr = new_register(T_LONG); + __ move(LIR_OprFact::longConst(index), index_opr); + addr = new LIR_Address(array_opr, index_opr, LIR_Address::scale(type), offset_in_bytes, type); + } else { + addr = new LIR_Address(array_opr, (intx)disp, type); + } +#else + // A displacement overflow can also occur for x86 but that is not a problem due to the 32-bit address range! + // Let's assume an array 'a' and an access with displacement 'disp'. When disp overflows, then "a + disp" will + // always be negative (i.e. underflows the 32-bit address range): + // Let N = 2^32: a + signed_overflow(disp) = a + disp - N. + // "a + disp" is always smaller than N. If an index was chosen which would point to an address beyond N, then + // range checks would catch that and throw an exception. Thus, a + disp < 0 holds which means that it always + // underflows the 32-bit address range: + // unsigned_underflow(a + signed_overflow(disp)) = unsigned_underflow(a + disp - N) + // = (a + disp - N) + N = a + disp + // This shows that we still end up at the correct address with a displacement overflow due to the 32-bit address + // range limitation. This overflow only needs to be handled if addresses can be larger as on 64-bit platforms. + addr = new LIR_Address(array_opr, offset_in_bytes + (intx)(index_opr->as_jint()) * elem_size, type); +#endif // _LP64 } else { #ifdef _LP64 if (index_opr->type() == T_INT) { -- GitLab From 4d3663a6d0620103f10b2f7fad50ae84d38f33e2 Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Mon, 20 Sep 2021 15:12:15 +0000 Subject: [PATCH 184/564] 8272026: Verify Jar Verification Reviewed-by: rhalade, valeriep, mschoene --- .../classes/java/util/jar/Attributes.java | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/java.base/share/classes/java/util/jar/Attributes.java b/src/java.base/share/classes/java/util/jar/Attributes.java index a33d1086285..3b59f74275f 100644 --- a/src/java.base/share/classes/java/util/jar/Attributes.java +++ b/src/java.base/share/classes/java/util/jar/Attributes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ package java.util.jar; +import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.IOException; import java.util.Collection; @@ -366,7 +367,7 @@ public class Attributes implements Map, Cloneable { int read(Manifest.FastInputStream is, byte[] lbuf, String filename, int lineNumber) throws IOException { String name = null, value; - byte[] lastline = null; + ByteArrayOutputStream fullLine = new ByteArrayOutputStream(); int len; while ((len = is.readLine(lbuf)) != -1) { @@ -392,15 +393,12 @@ public class Attributes implements Map, Cloneable { + Manifest.getErrorPosition(filename, lineNumber) + ")"); } lineContinued = true; - byte[] buf = new byte[lastline.length + len - 1]; - System.arraycopy(lastline, 0, buf, 0, lastline.length); - System.arraycopy(lbuf, 1, buf, lastline.length, len - 1); + fullLine.write(lbuf, 1, len - 1); if (is.peek() == ' ') { - lastline = buf; continue; } - value = new String(buf, 0, buf.length, UTF_8.INSTANCE); - lastline = null; + value = fullLine.toString(UTF_8.INSTANCE); + fullLine.reset(); } else { while (lbuf[i++] != ':') { if (i >= len) { @@ -414,8 +412,8 @@ public class Attributes implements Map, Cloneable { } name = new String(lbuf, 0, i - 2, UTF_8.INSTANCE); if (is.peek() == ' ') { - lastline = new byte[len - i]; - System.arraycopy(lbuf, i, lastline, 0, len - i); + fullLine.reset(); + fullLine.write(lbuf, i, len - i); continue; } value = new String(lbuf, i, len - i, UTF_8.INSTANCE); -- GitLab From 12034273c7b3f9da565da6a12a26b9493d813cf8 Mon Sep 17 00:00:00 2001 From: Alexander Zuev Date: Wed, 22 Sep 2021 17:39:28 +0000 Subject: [PATCH 185/564] 8272462: Enhance image handling Reviewed-by: jdv, ahgross, rhalade, prr --- .../com/sun/imageio/plugins/gif/GIFImageReader.java | 7 ++++++- .../com/sun/imageio/plugins/jpeg/JPEGImageReader.java | 7 +++++++ .../com/sun/imageio/plugins/png/PNGImageReader.java | 7 +++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageReader.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageReader.java index 2bedc9440ee..9632e37d1d4 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageReader.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2021, 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 @@ -1007,6 +1007,11 @@ public class GIFImageReader extends ImageReader { } } + if (tableIndex >= prefix.length) { + throw new IIOException("Code buffer limit reached," + + " no End of Image tag present, possibly data is corrupted. "); + } + int ti = tableIndex; int oc = oldCode; diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java index ab15bdfc6b8..a7edf73cb80 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java @@ -1156,6 +1156,13 @@ public class JPEGImageReader extends ImageReader { throw new IIOException("Unsupported Image Type"); } + if ((long)width * height > Integer.MAX_VALUE - 2) { + // We are not able to properly decode image that has number + // of pixels greater than Integer.MAX_VALUE - 2 + throw new IIOException("Can not read image of the size " + + width + " by " + height); + } + image = getDestination(param, imageTypes, width, height); imRas = image.getRaster(); diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java index fc731506af3..6daabab1988 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java @@ -1424,6 +1424,13 @@ public class PNGImageReader extends ImageReader { int width = metadata.IHDR_width; int height = metadata.IHDR_height; + if ((long)width * height > Integer.MAX_VALUE - 2) { + // We are not able to properly decode image that has number + // of pixels greater than Integer.MAX_VALUE - 2 + throw new IIOException("Can not read image of the size " + + width + " by " + height); + } + // Init default values sourceXSubsampling = 1; sourceYSubsampling = 1; -- GitLab From 9c02c4c55f571363cbc430a26d795d10cff93819 Mon Sep 17 00:00:00 2001 From: Jayathirth D V Date: Thu, 23 Sep 2021 12:34:20 +0000 Subject: [PATCH 186/564] 8273756: Enhance BMP image support Reviewed-by: prr, rhalade, kizune, mschoene --- .../imageio/plugins/bmp/BMPImageReader.java | 43 ++++++++++++++----- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java index df283e8102c..8271c5cf263 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java @@ -52,6 +52,7 @@ import java.security.AccessController; import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Iterator; +import java.util.List; import javax.imageio.IIOException; import javax.imageio.ImageIO; import javax.imageio.ImageReadParam; @@ -223,6 +224,33 @@ public class BMPImageReader extends ImageReader implements BMPConstants { } } + private void readColorPalette(int sizeOfPalette) throws IOException { + final int UNIT_SIZE = 1024000; + if (sizeOfPalette < UNIT_SIZE) { + palette = new byte[sizeOfPalette]; + iis.readFully(palette, 0, sizeOfPalette); + } else { + int bytesToRead = sizeOfPalette; + int bytesRead = 0; + List bufs = new ArrayList<>(); + while (bytesToRead != 0) { + int sz = Math.min(bytesToRead, UNIT_SIZE); + byte[] unit = new byte[sz]; + iis.readFully(unit, 0, sz); + bufs.add(unit); + bytesRead += sz; + bytesToRead -= sz; + } + byte[] paletteData = new byte[bytesRead]; + int copiedBytes = 0; + for (byte[] ba : bufs) { + System.arraycopy(ba, 0, paletteData, copiedBytes, ba.length); + copiedBytes += ba.length; + } + palette = paletteData; + } + } + /** * Process the image header. * @@ -305,8 +333,7 @@ public class BMPImageReader extends ImageReader implements BMPConstants { // Read in the palette int numberOfEntries = (int)((bitmapOffset - 14 - size) / 3); int sizeOfPalette = numberOfEntries*3; - palette = new byte[sizeOfPalette]; - iis.readFully(palette, 0, sizeOfPalette); + readColorPalette(sizeOfPalette); metadata.palette = palette; metadata.paletteSize = numberOfEntries; } else { @@ -343,8 +370,7 @@ public class BMPImageReader extends ImageReader implements BMPConstants { } int numberOfEntries = (int)((bitmapOffset-14-size) / 4); int sizeOfPalette = numberOfEntries * 4; - palette = new byte[sizeOfPalette]; - iis.readFully(palette, 0, sizeOfPalette); + readColorPalette(sizeOfPalette); metadata.palette = palette; metadata.paletteSize = numberOfEntries; @@ -404,8 +430,7 @@ public class BMPImageReader extends ImageReader implements BMPConstants { if (colorsUsed != 0) { // there is a palette sizeOfPalette = (int)colorsUsed*4; - palette = new byte[sizeOfPalette]; - iis.readFully(palette, 0, sizeOfPalette); + readColorPalette(sizeOfPalette); metadata.palette = palette; metadata.paletteSize = (int)colorsUsed; @@ -430,8 +455,7 @@ public class BMPImageReader extends ImageReader implements BMPConstants { // Read in the palette int numberOfEntries = (int)((bitmapOffset-14-size) / 4); int sizeOfPalette = numberOfEntries*4; - palette = new byte[sizeOfPalette]; - iis.readFully(palette, 0, sizeOfPalette); + readColorPalette(sizeOfPalette); metadata.palette = palette; metadata.paletteSize = numberOfEntries; @@ -529,8 +553,7 @@ public class BMPImageReader extends ImageReader implements BMPConstants { // Read in the palette int numberOfEntries = (int)((bitmapOffset-14-size) / 4); int sizeOfPalette = numberOfEntries*4; - palette = new byte[sizeOfPalette]; - iis.readFully(palette, 0, sizeOfPalette); + readColorPalette(sizeOfPalette); metadata.palette = palette; metadata.paletteSize = numberOfEntries; -- GitLab From abf6fdd75a5362970d3d4bb5f46bbb4815d6b458 Mon Sep 17 00:00:00 2001 From: Joe Wang Date: Fri, 24 Sep 2021 18:55:03 +0000 Subject: [PATCH 187/564] 8273968: JCK javax_xml tests fail in CI Reviewed-by: naoto, lancea --- .../sun/org/apache/xerces/internal/impl/XMLEntityScanner.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityScanner.java b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityScanner.java index 89adb81b05b..33ffe9831b8 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityScanner.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityScanner.java @@ -57,7 +57,7 @@ import java.util.Locale; * @author Arnaud Le Hors, IBM * @author K.Venugopal Sun Microsystems * - * @LastModified: Aug 2021 + * @LastModified: Sep 2021 */ public class XMLEntityScanner implements XMLLocator { @@ -2145,7 +2145,7 @@ public class XMLEntityScanner implements XMLLocator { // how this information is used is determined by the caller of this method counted = false; if ((c == '\n' || c == '\r') || - (version == XML_VERSION_1_1 && (c == 0x85 || c == 0x2028))) { + (version == XML_VERSION_1_1 && (c == 0x85 || c == 0x2028) && isExternal)) { do { c = fCurrentEntity.ch[fCurrentEntity.position++]; if ((c == '\n' || c == '\r') || -- GitLab From 4525a4b94dc2e856e74101ab3cbc1f6ffe365f37 Mon Sep 17 00:00:00 2001 From: Julia Boes Date: Mon, 27 Sep 2021 08:59:16 +0000 Subject: [PATCH 188/564] 8270392: Improve String constructions Reviewed-by: rhalade, dfuchs, robm, ahgross, smarks --- .../share/classes/java/lang/StringBuffer.java | 55 +++++++++++-------- .../classes/java/lang/StringBuilder.java | 24 +++++--- 2 files changed, 48 insertions(+), 31 deletions(-) diff --git a/src/java.base/share/classes/java/lang/StringBuffer.java b/src/java.base/share/classes/java/lang/StringBuffer.java index e2ca48fdaf6..1ba12bd29bc 100644 --- a/src/java.base/share/classes/java/lang/StringBuffer.java +++ b/src/java.base/share/classes/java/lang/StringBuffer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,12 @@ package java.lang; import java.io.IOException; -import java.util.Arrays; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.ObjectStreamField; +import java.io.Serial; +import java.io.Serializable; +import java.io.StreamCorruptedException; import jdk.internal.vm.annotation.IntrinsicCandidate; /** @@ -106,7 +111,7 @@ import jdk.internal.vm.annotation.IntrinsicCandidate; */ public final class StringBuffer extends AbstractStringBuilder - implements java.io.Serializable, Comparable, CharSequence + implements Serializable, Comparable, CharSequence { /** @@ -116,7 +121,7 @@ import jdk.internal.vm.annotation.IntrinsicCandidate; private transient String toStringCache; /** use serialVersionUID from JDK 1.0.2 for interoperability */ - @java.io.Serial + @Serial static final long serialVersionUID = 3388685877147921107L; /** @@ -725,25 +730,25 @@ import jdk.internal.vm.annotation.IntrinsicCandidate; * A flag indicating whether the backing array is shared. * The value is ignored upon deserialization. */ - @java.io.Serial - private static final java.io.ObjectStreamField[] serialPersistentFields = + @Serial + private static final ObjectStreamField[] serialPersistentFields = { - new java.io.ObjectStreamField("value", char[].class), - new java.io.ObjectStreamField("count", Integer.TYPE), - new java.io.ObjectStreamField("shared", Boolean.TYPE), + new ObjectStreamField("value", char[].class), + new ObjectStreamField("count", Integer.TYPE), + new ObjectStreamField("shared", Boolean.TYPE), }; /** - * The {@code writeObject} method is called to write the state of the {@code StringBuffer} to - * a stream. + * The {@code writeObject} method is called to write the state of the + * {@code StringBuffer} to a stream. * * @param s the {@code ObjectOutputStream} to which data is written * @throws IOException if an I/O error occurs */ - @java.io.Serial - private synchronized void writeObject(java.io.ObjectOutputStream s) - throws java.io.IOException { - java.io.ObjectOutputStream.PutField fields = s.putFields(); + @Serial + private synchronized void writeObject(ObjectOutputStream s) + throws IOException { + ObjectOutputStream.PutField fields = s.putFields(); char[] val = new char[capacity()]; if (isLatin1()) { StringLatin1.getChars(value, 0, count, val, 0); @@ -757,20 +762,26 @@ import jdk.internal.vm.annotation.IntrinsicCandidate; } /** - * The {@code readObject} method is called to restore the state of the {@code StringBuffer} from - * a stream. + * The {@code readObject} method is called to restore the state of the + * {@code StringBuffer} from a stream. * * @param s the {@code ObjectInputStream} from which data is read * @throws IOException if an I/O error occurs * @throws ClassNotFoundException if a serialized class cannot be loaded */ - @java.io.Serial - private void readObject(java.io.ObjectInputStream s) - throws java.io.IOException, ClassNotFoundException { - java.io.ObjectInputStream.GetField fields = s.readFields(); + @Serial + private void readObject(ObjectInputStream s) + throws IOException, ClassNotFoundException { + ObjectInputStream.GetField fields = s.readFields(); + char[] val = (char[])fields.get("value", null); + int c = fields.get("count", 0); + if (c < 0 || c > val.length) { + throw new StreamCorruptedException("count value invalid"); + } initBytes(val, 0, val.length); - count = fields.get("count", 0); + count = c; + // ignore shared field } synchronized void getBytes(byte[] dst, int dstBegin, byte coder) { diff --git a/src/java.base/share/classes/java/lang/StringBuilder.java b/src/java.base/share/classes/java/lang/StringBuilder.java index b22ed99dbfc..8e759c213a9 100644 --- a/src/java.base/share/classes/java/lang/StringBuilder.java +++ b/src/java.base/share/classes/java/lang/StringBuilder.java @@ -28,6 +28,10 @@ package java.lang; import jdk.internal.vm.annotation.IntrinsicCandidate; import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serial; +import java.io.StreamCorruptedException; /** * A mutable sequence of characters. This class provides an API compatible @@ -90,7 +94,7 @@ public final class StringBuilder { /** use serialVersionUID for interoperability */ - @java.io.Serial + @Serial static final long serialVersionUID = 4383685877147921099L; /** @@ -464,9 +468,8 @@ public final class StringBuilder * @param s the {@code ObjectOutputStream} to which data is written * @throws IOException if an I/O error occurs */ - @java.io.Serial - private void writeObject(java.io.ObjectOutputStream s) - throws java.io.IOException { + @Serial + private void writeObject(ObjectOutputStream s) throws IOException { s.defaultWriteObject(); s.writeInt(count); char[] val = new char[capacity()]; @@ -486,13 +489,16 @@ public final class StringBuilder * @throws IOException if an I/O error occurs * @throws ClassNotFoundException if a serialized class cannot be loaded */ - @java.io.Serial - private void readObject(java.io.ObjectInputStream s) - throws IOException, ClassNotFoundException { + @Serial + private void readObject(ObjectInputStream s) + throws IOException, ClassNotFoundException { s.defaultReadObject(); - count = s.readInt(); + int c = s.readInt(); char[] val = (char[]) s.readObject(); + if (c < 0 || c > val.length) { + throw new StreamCorruptedException("count value invalid"); + } initBytes(val, 0, val.length); + count = c; } - } -- GitLab From a6fd2c311457db024cb699adabd195302885034a Mon Sep 17 00:00:00 2001 From: Jayathirth D V Date: Tue, 28 Sep 2021 03:05:14 +0000 Subject: [PATCH 189/564] 8273838: Enhanced BMP processing Reviewed-by: rhalade, ahgross, prr, kizune, azvegint, mschoene --- .../classes/com/sun/imageio/plugins/bmp/BMPImageReader.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java index 8271c5cf263..2e1c2db03ca 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java @@ -615,7 +615,7 @@ public class BMPImageReader extends ImageReader implements BMPConstants { } if (metadata.compression == BI_RGB) { - long imageDataSize = (width * height * (bitsPerPixel / 8)); + long imageDataSize = ((long)width * height * (bitsPerPixel / 8)); if (imageDataSize > (bitmapFileSize - bitmapOffset)) { throw new IIOException(I18N.getString("BMPImageReader9")); } -- GitLab From 3603e754cedb5d77a8563ba9da7846ba3b335712 Mon Sep 17 00:00:00 2001 From: Christian Hagedorn Date: Wed, 29 Sep 2021 08:33:39 +0000 Subject: [PATCH 190/564] 8274374: Additional fix for JDK-8272014 Reviewed-by: kvn, thartmann --- .../cpu/aarch64/c1_LIRGenerator_aarch64.cpp | 28 ++----------------- 1 file changed, 2 insertions(+), 26 deletions(-) diff --git a/src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp index 11f3ce45e7f..0a97872900e 100644 --- a/src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp @@ -207,32 +207,8 @@ LIR_Address* LIRGenerator::emit_array_address(LIR_Opr array_opr, LIR_Opr index_o LIR_Address* addr; if (index_opr->is_constant()) { -#ifdef _LP64 - jint index = index_opr->as_jint(); - jlong disp = offset_in_bytes + (jlong)(index) * elem_size; - if (disp > max_jint) { - // Displacement overflow. Cannot directly use instruction with 32-bit displacement for 64-bit addresses. - // Convert array index to long to do array offset computation with 64-bit values. - index_opr = new_register(T_LONG); - __ move(LIR_OprFact::longConst(index), index_opr); - addr = new LIR_Address(array_opr, index_opr, LIR_Address::scale(type), offset_in_bytes, type); - } else { - addr = new LIR_Address(array_opr, (intx)disp, type); - } -#else - // A displacement overflow can also occur for x86 but that is not a problem due to the 32-bit address range! - // Let's assume an array 'a' and an access with displacement 'disp'. When disp overflows, then "a + disp" will - // always be negative (i.e. underflows the 32-bit address range): - // Let N = 2^32: a + signed_overflow(disp) = a + disp - N. - // "a + disp" is always smaller than N. If an index was chosen which would point to an address beyond N, then - // range checks would catch that and throw an exception. Thus, a + disp < 0 holds which means that it always - // underflows the 32-bit address range: - // unsigned_underflow(a + signed_overflow(disp)) = unsigned_underflow(a + disp - N) - // = (a + disp - N) + N = a + disp - // This shows that we still end up at the correct address with a displacement overflow due to the 32-bit address - // range limitation. This overflow only needs to be handled if addresses can be larger as on 64-bit platforms. - addr = new LIR_Address(array_opr, offset_in_bytes + (intx)(index_opr->as_jint()) * elem_size, type); -#endif // _LP64 + addr = new LIR_Address(array_opr, + offset_in_bytes + (intx)(index_opr->as_jint()) * elem_size, type); } else { if (offset_in_bytes) { LIR_Opr tmp = new_pointer_register(); -- GitLab From 82d6afe6759b3768748126171ff3c6d59e8724d5 Mon Sep 17 00:00:00 2001 From: Jayathirth D V Date: Mon, 11 Oct 2021 15:52:40 +0000 Subject: [PATCH 191/564] 8274096: Improve decoding of image files Reviewed-by: prr, kizune, rhalade, mschoene --- .../imageio/plugins/common/ReaderUtil.java | 47 ++++++++++++++++++- .../plugins/tiff/TIFFDecompressor.java | 8 +++- .../plugins/tiff/TIFFFaxDecompressor.java | 7 +-- .../plugins/tiff/TIFFLZWDecompressor.java | 8 ++-- .../tiff/TIFFPackBitsDecompressor.java | 7 +-- .../plugins/tiff/TIFFYCbCrDecompressor.java | 4 +- 6 files changed, 66 insertions(+), 15 deletions(-) diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/common/ReaderUtil.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/common/ReaderUtil.java index 0f8d1d66a28..906aa3a8a38 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/common/ReaderUtil.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/common/ReaderUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,8 @@ package com.sun.imageio.plugins.common; import java.awt.Point; import java.awt.Rectangle; import java.io.IOException; +import java.util.List; +import java.util.ArrayList; import javax.imageio.stream.ImageInputStream; /** @@ -213,4 +215,47 @@ public class ReaderUtil { } return result; } + + /** + * An utility method to allocate and initialize a byte array + * step by step with pre-defined limit, instead of allocating + * a large array up-front based on the length derived from + * an image header. + * + * @param iis a {@code ImageInputStream} to decode data and store + * it in byte array. + * @param length the size of data to decode + * + * @return array of size length when decode succeeeds + * + * @throws IOException if decoding of stream fails + */ + public static byte[] staggeredReadByteStream(ImageInputStream iis, + int length) throws IOException { + final int UNIT_SIZE = 1024000; + byte[] decodedData; + if (length < UNIT_SIZE) { + decodedData = new byte[length]; + iis.readFully(decodedData, 0, length); + } else { + int bytesToRead = length; + int bytesRead = 0; + List bufs = new ArrayList<>(); + while (bytesToRead != 0) { + int sz = Math.min(bytesToRead, UNIT_SIZE); + byte[] unit = new byte[sz]; + iis.readFully(unit, 0, sz); + bufs.add(unit); + bytesRead += sz; + bytesToRead -= sz; + } + decodedData = new byte[bytesRead]; + int copiedBytes = 0; + for (byte[] ba : bufs) { + System.arraycopy(ba, 0, decodedData, copiedBytes, ba.length); + copiedBytes += ba.length; + } + } + return decodedData; + } } diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFDecompressor.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFDecompressor.java index a1b04390977..4516ce0ad82 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFDecompressor.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFDecompressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2021, 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 @@ -1438,7 +1438,11 @@ public abstract class TIFFDecompressor { * * @param byteCount the number of bytes of compressed data. */ - public void setByteCount(int byteCount) { + public void setByteCount(int byteCount) throws IOException{ + if (byteCount < 0) { + throw new IIOException("Strip byte count can't be" + + " negative: " + byteCount); + } this.byteCount = byteCount; } diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFFaxDecompressor.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFFaxDecompressor.java index 22ebda2187a..4d64072075a 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFFaxDecompressor.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFFaxDecompressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,7 @@ import java.io.EOFException; import javax.imageio.IIOException; import javax.imageio.plugins.tiff.BaselineTIFFTagSet; import javax.imageio.plugins.tiff.TIFFField; +import com.sun.imageio.plugins.common.ReaderUtil; class TIFFFaxDecompressor extends TIFFDecompressor { @@ -637,14 +638,14 @@ class TIFFFaxDecompressor extends TIFFDecompressor { this.bitsPerScanline = scanlineStride*8; this.lineBitNum = 8*dstOffset; - this.data = new byte[byteCount]; this.bitPointer = 0; this.bytePointer = 0; this.prevChangingElems = new int[w + 1]; this.currChangingElems = new int[w + 1]; stream.seek(offset); - stream.readFully(data); + this.data = ReaderUtil. + staggeredReadByteStream(stream, byteCount); if (compression == BaselineTIFFTagSet.COMPRESSION_CCITT_RLE) { decodeRLE(); diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFLZWDecompressor.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFLZWDecompressor.java index 9010674bdb1..fc682589ce2 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFLZWDecompressor.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFLZWDecompressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ package com.sun.imageio.plugins.tiff; import java.io.IOException; import javax.imageio.IIOException; import javax.imageio.plugins.tiff.BaselineTIFFTagSet; +import com.sun.imageio.plugins.common.ReaderUtil; class TIFFLZWDecompressor extends TIFFDecompressor { @@ -95,9 +96,8 @@ class TIFFLZWDecompressor extends TIFFDecompressor { } stream.seek(offset); - - byte[] sdata = new byte[byteCount]; - stream.readFully(sdata); + byte[] sdata = ReaderUtil. + staggeredReadByteStream(stream, byteCount); if (flipBits) { for (int i = 0; i < byteCount; i++) { diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFPackBitsDecompressor.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFPackBitsDecompressor.java index 42a44a43eee..0a5dfe8308e 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFPackBitsDecompressor.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFPackBitsDecompressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ package com.sun.imageio.plugins.tiff; import java.io.IOException; +import com.sun.imageio.plugins.common.ReaderUtil; public class TIFFPackBitsDecompressor extends TIFFDecompressor { @@ -77,8 +78,8 @@ public class TIFFPackBitsDecompressor extends TIFFDecompressor { int scanlineStride) throws IOException { stream.seek(offset); - byte[] srcData = new byte[byteCount]; - stream.readFully(srcData); + byte[] srcData = ReaderUtil. + staggeredReadByteStream(stream, byteCount); int bytesPerRow = (srcWidth*bitsPerPixel + 7)/8; byte[] buf; diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFYCbCrDecompressor.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFYCbCrDecompressor.java index 11151d8e6c8..0f10904cab4 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFYCbCrDecompressor.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFYCbCrDecompressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2021, 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 @@ -180,7 +180,7 @@ public class TIFFYCbCrDecompressor extends TIFFDecompressor { super.setOffset(offset); } - public void setByteCount(int byteCount) { + public void setByteCount(int byteCount) throws IOException { if(decompressor != null) { decompressor.setByteCount(byteCount); } -- GitLab From 6d3fd860d748a092a65ab9700b47686099b81bf4 Mon Sep 17 00:00:00 2001 From: Christian Hagedorn Date: Tue, 4 Jan 2022 10:48:28 +0000 Subject: [PATCH 192/564] 8278417: Closed test fails after JDK-8276108 on aarch64 Reviewed-by: kvn, iveresov, dlong --- .../cpu/aarch64/c1_LIRGenerator_aarch64.cpp | 23 +++---------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp index 0a97872900e..9f60e493d6a 100644 --- a/src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp @@ -148,7 +148,7 @@ LIR_Address* LIRGenerator::generate_address(LIR_Opr base, LIR_Opr index, if (index->is_constant()) { LIR_Const *constant = index->as_constant_ptr(); if (constant->type() == T_INT) { - large_disp += index->as_jint() << shift; + large_disp += ((intx)index->as_jint()) << shift; } else { assert(constant->type() == T_LONG, "should be"); jlong c = index->as_jlong() << shift; @@ -194,7 +194,7 @@ LIR_Address* LIRGenerator::generate_address(LIR_Opr base, LIR_Opr index, if (large_disp == 0 && index->is_register()) { return new LIR_Address(base, index, type); } else { - assert(Address::offset_ok_for_immed(large_disp, 0), "must be"); + assert(Address::offset_ok_for_immed(large_disp, shift), "failed for large_disp: " INTPTR_FORMAT " and shift %d", large_disp, shift); return new LIR_Address(base, large_disp, type); } } @@ -204,24 +204,7 @@ LIR_Address* LIRGenerator::emit_array_address(LIR_Opr array_opr, LIR_Opr index_o int offset_in_bytes = arrayOopDesc::base_offset_in_bytes(type); int elem_size = type2aelembytes(type); int shift = exact_log2(elem_size); - - LIR_Address* addr; - if (index_opr->is_constant()) { - addr = new LIR_Address(array_opr, - offset_in_bytes + (intx)(index_opr->as_jint()) * elem_size, type); - } else { - if (offset_in_bytes) { - LIR_Opr tmp = new_pointer_register(); - __ add(array_opr, LIR_OprFact::intConst(offset_in_bytes), tmp); - array_opr = tmp; - offset_in_bytes = 0; - } - addr = new LIR_Address(array_opr, - index_opr, - LIR_Address::scale(type), - offset_in_bytes, type); - } - return addr; + return generate_address(array_opr, index_opr, shift, offset_in_bytes, type); } LIR_Opr LIRGenerator::load_immediate(int x, BasicType type) { -- GitLab From af6c9abafaa3b8f9bdcc938fec465aeeed8b30ed Mon Sep 17 00:00:00 2001 From: Fei Gao Date: Wed, 19 Jan 2022 01:20:53 +0000 Subject: [PATCH 193/564] 8279654: jdk/incubator/vector/Vector256ConversionTests.java crashes randomly with SVE Reviewed-by: njian, kvn --- src/hotspot/cpu/aarch64/aarch64.ad | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/hotspot/cpu/aarch64/aarch64.ad b/src/hotspot/cpu/aarch64/aarch64.ad index 970ddecf3bd..0a00d522b05 100644 --- a/src/hotspot/cpu/aarch64/aarch64.ad +++ b/src/hotspot/cpu/aarch64/aarch64.ad @@ -1,5 +1,5 @@ // -// Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. // Copyright (c) 2014, 2021, Red Hat, Inc. All rights reserved. // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. // @@ -2732,11 +2732,8 @@ bool is_vector_arith_imm_pattern(Node* n, Node* m) { // Should the matcher clone input 'm' of node 'n'? bool Matcher::pd_clone_node(Node* n, Node* m, Matcher::MStack& mstack) { // ShiftV src (ShiftCntV con) - // StoreVector (VectorStoreMask src) // Binary src (Replicate con) - if (is_vshift_con_pattern(n, m) || - (UseSVE > 0 && m->Opcode() == Op_VectorStoreMask && n->Opcode() == Op_StoreVector) || - is_vector_arith_imm_pattern(n, m)) { + if (is_vshift_con_pattern(n, m) || is_vector_arith_imm_pattern(n, m)) { mstack.push(m, Visit); return true; } -- GitLab From 4f4da3b172bb6ed5dd80a144e8eeb17b90bd7cdf Mon Sep 17 00:00:00 2001 From: Ioi Lam Date: Wed, 19 Jan 2022 01:35:06 +0000 Subject: [PATCH 194/564] 8275318: loaded_classes_do may see ArrayKlass before InstanceKlass is loaded Reviewed-by: coleenp, ccheung --- .../share/classfile/classLoaderData.cpp | 30 ++++++++++++++----- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/src/hotspot/share/classfile/classLoaderData.cpp b/src/hotspot/share/classfile/classLoaderData.cpp index 252daee1969..e3a3ada3e8a 100644 --- a/src/hotspot/share/classfile/classLoaderData.cpp +++ b/src/hotspot/share/classfile/classLoaderData.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022, 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 @@ -67,6 +67,7 @@ #include "memory/universe.hpp" #include "oops/access.inline.hpp" #include "oops/klass.inline.hpp" +#include "oops/objArrayKlass.hpp" #include "oops/oop.inline.hpp" #include "oops/oopHandle.inline.hpp" #include "oops/weakHandle.inline.hpp" @@ -358,15 +359,28 @@ void ClassLoaderData::loaded_classes_do(KlassClosure* klass_closure) { // Lock-free access requires load_acquire for (Klass* k = Atomic::load_acquire(&_klasses); k != NULL; k = k->next_link()) { - // Do not filter ArrayKlass oops here... - if (k->is_array_klass() || (k->is_instance_klass() && InstanceKlass::cast(k)->is_loaded())) { + // Filter out InstanceKlasses (or their ObjArrayKlasses) that have not entered the + // loaded state. + if (k->is_instance_klass()) { + if (!InstanceKlass::cast(k)->is_loaded()) { + continue; + } + } else if (k->is_shared() && k->is_objArray_klass()) { + Klass* bottom = ObjArrayKlass::cast(k)->bottom_klass(); + if (bottom->is_instance_klass() && !InstanceKlass::cast(bottom)->is_loaded()) { + // This could happen if is a shared class that has been restored + // but is not yet marked as loaded. All archived array classes of the + // bottom class are already restored and placed in the _klasses list. + continue; + } + } + #ifdef ASSERT - oop m = k->java_mirror(); - assert(m != NULL, "NULL mirror"); - assert(m->is_a(vmClasses::Class_klass()), "invalid mirror"); + oop m = k->java_mirror(); + assert(m != NULL, "NULL mirror"); + assert(m->is_a(vmClasses::Class_klass()), "invalid mirror"); #endif - klass_closure->do_klass(k); - } + klass_closure->do_klass(k); } } -- GitLab From 4eb4f94db09cbd204fa228fc1eaac5153dfe3521 Mon Sep 17 00:00:00 2001 From: sunguoyun Date: Wed, 19 Jan 2022 02:08:02 +0000 Subject: [PATCH 195/564] 8279956: Useless method Scheduling::ComputeLocalLatenciesForward() Reviewed-by: jiefu, neliasso --- src/hotspot/share/opto/output.cpp | 63 +------------------------------ 1 file changed, 1 insertion(+), 62 deletions(-) diff --git a/src/hotspot/share/opto/output.cpp b/src/hotspot/share/opto/output.cpp index 98f9fdec423..78d1c23a2ce 100644 --- a/src/hotspot/share/opto/output.cpp +++ b/src/hotspot/share/opto/output.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2022, 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 @@ -96,10 +96,6 @@ private: // Free list for pinch nodes. Node_List _pinch_free_list; - // Latency from the beginning of the containing basic block (base 1) - // for each node. - unsigned short *_node_latency; - // Number of uses of this node within the containing basic block. short *_uses; @@ -162,10 +158,6 @@ public: // Do the scheduling void DoScheduling(); - // Compute the local latencies walking forward over the list of - // nodes for a basic block - void ComputeLocalLatenciesForward(const Block *bb); - // Compute the register antidependencies within a basic block void ComputeRegisterAntidependencies(Block *bb); void verify_do_def( Node *n, OptoReg::Name def, const char *msg ); @@ -2027,7 +2019,6 @@ Scheduling::Scheduling(Arena *arena, Compile &compile) _node_bundling_base = NEW_ARENA_ARRAY(compile.comp_arena(), Bundle, node_max); // Allocate space for fixed-size arrays - _node_latency = NEW_ARENA_ARRAY(arena, unsigned short, node_max); _uses = NEW_ARENA_ARRAY(arena, short, node_max); _current_latency = NEW_ARENA_ARRAY(arena, unsigned short, node_max); @@ -2035,7 +2026,6 @@ Scheduling::Scheduling(Arena *arena, Compile &compile) for (uint i = 0; i < node_max; i++) { ::new (&_node_bundling_base[i]) Bundle(); } - memset(_node_latency, 0, node_max * sizeof(unsigned short)); memset(_uses, 0, node_max * sizeof(short)); memset(_current_latency, 0, node_max * sizeof(unsigned short)); @@ -2141,54 +2131,6 @@ void PhaseOutput::ScheduleAndBundle() { #endif } -// Compute the latency of all the instructions. This is fairly simple, -// because we already have a legal ordering. Walk over the instructions -// from first to last, and compute the latency of the instruction based -// on the latency of the preceding instruction(s). -void Scheduling::ComputeLocalLatenciesForward(const Block *bb) { -#ifndef PRODUCT - if (_cfg->C->trace_opto_output()) - tty->print("# -> ComputeLocalLatenciesForward\n"); -#endif - - // Walk over all the schedulable instructions - for( uint j=_bb_start; j < _bb_end; j++ ) { - - // This is a kludge, forcing all latency calculations to start at 1. - // Used to allow latency 0 to force an instruction to the beginning - // of the bb - uint latency = 1; - Node *use = bb->get_node(j); - uint nlen = use->len(); - - // Walk over all the inputs - for ( uint k=0; k < nlen; k++ ) { - Node *def = use->in(k); - if (!def) - continue; - - uint l = _node_latency[def->_idx] + use->latency(k); - if (latency < l) - latency = l; - } - - _node_latency[use->_idx] = latency; - -#ifndef PRODUCT - if (_cfg->C->trace_opto_output()) { - tty->print("# latency %4d: ", latency); - use->dump(); - } -#endif - } - -#ifndef PRODUCT - if (_cfg->C->trace_opto_output()) - tty->print("# <- ComputeLocalLatenciesForward\n"); -#endif - -} // end ComputeLocalLatenciesForward - // See if this node fits into the present instruction bundle bool Scheduling::NodeFitsInBundle(Node *n) { uint n_idx = n->_idx; @@ -2764,9 +2706,6 @@ void Scheduling::DoScheduling() { ComputeRegisterAntidependencies(bb); if (C->failing()) return; // too many D-U pinch points - // Compute intra-bb latencies for the nodes - ComputeLocalLatenciesForward(bb); - // Compute the usage within the block, and set the list of all nodes // in the block that have no uses within the block. ComputeUseCount(bb); -- GitLab From b0496b0df60cf19a0666f1f1c382f7bcd01e15bb Mon Sep 17 00:00:00 2001 From: Yumin Qi Date: Wed, 19 Jan 2022 03:21:19 +0000 Subject: [PATCH 196/564] 8279970: two AppCDS tests fail after JDK-8261455 Reviewed-by: ccheung, iklam --- test/hotspot/jtreg/ProblemList.txt | 2 -- .../cds/appcds/dynamicArchive/DynamicArchiveTestBase.java | 7 ++++++- .../appcds/dynamicArchive/TestAutoCreateSharedArchive.java | 6 +++++- .../loaderConstraints/DynamicLoaderConstraintsTest.java | 5 +++-- 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index 938bd46172a..b05f3317527 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -103,8 +103,6 @@ runtime/os/TestTracePageSizes.java#G1 8267460 linux-aarch64 runtime/os/TestTracePageSizes.java#Parallel 8267460 linux-aarch64 runtime/os/TestTracePageSizes.java#Serial 8267460 linux-aarch64 runtime/ErrorHandling/CreateCoredumpOnCrash.java 8267433 macosx-x64 -runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchive.java 8279970 generic-all -runtime/cds/appcds/loaderConstraints/DynamicLoaderConstraintsTest.java#custom-cl-zgc 8279970 generic-all applications/jcstress/copy.java 8229852 linux-all diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/DynamicArchiveTestBase.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/DynamicArchiveTestBase.java index f97a7b4a70f..6cbfec37175 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/DynamicArchiveTestBase.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/DynamicArchiveTestBase.java @@ -38,6 +38,7 @@ class DynamicArchiveTestBase { private static boolean executedIn_run = false; private static boolean autoMode = false; // -Xshare:auto private static final WhiteBox WB = WhiteBox.getWhiteBox(); + private static String[] baseArchiveOptions = new String[] {}; public static interface DynamicArchiveTest { public void run() throws Exception; @@ -95,6 +96,10 @@ class DynamicArchiveTestBase { return TestCommon.getNewArchiveName(stem); } + public static void setBaseArchiveOptions(String... opts) { + baseArchiveOptions = opts; + } + /** * Excute a JVM to dump a base archive by * -Xshare:dump -XX:SharedArchiveFile=baseArchiveName @@ -286,7 +291,7 @@ class DynamicArchiveTestBase { private static String getTempBaseArchive() throws Exception { if (tempBaseArchive == null) { tempBaseArchive = getNewArchiveName("tempBaseArchive"); - TestCommon.dumpBaseArchive(tempBaseArchive); + TestCommon.dumpBaseArchive(tempBaseArchive, baseArchiveOptions); } return tempBaseArchive; } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchive.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchive.java index dd38cbfec08..e06a4c98c37 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchive.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchive.java @@ -101,7 +101,6 @@ import java.io.IOException; import java.io.File; - import java.nio.file.attribute.FileTime; import java.nio.file.Files; import java.nio.file.Paths; @@ -111,6 +110,8 @@ import jdk.test.lib.cds.CDSArchiveUtils; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.helpers.ClassFileInstaller; +import jtreg.SkippedException; + public class TestAutoCreateSharedArchive extends DynamicArchiveTestBase { private static final String BASE_NAME = CDSTestUtils.getOutputFileName("base.jsa"); private static final String TOP_NAME = CDSTestUtils.getOutputFileName("top.jsa"); @@ -123,6 +124,9 @@ public class TestAutoCreateSharedArchive extends DynamicArchiveTestBase { private static int currentCDSVersion = CDSArchiveUtils.getCurrentCDSArchiveVersion(); public static void main(String[] args) throws Exception { + if (isUseSharedSpacesDisabled()) { + throw new SkippedException("Skipped -- This test is not applicable when JTREG tests are executed with -Xshare:off, or if the JDK doesn't have a default archive."); + } if (args.length != 1 || (!args[0].equals("verifySharedSpacesOff") && !args[0].equals("verifySharedSpacesOn"))) { throw new RuntimeException("Must run with verifySharedSpacesOff or verifySharedSpacesOn"); } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/loaderConstraints/DynamicLoaderConstraintsTest.java b/test/hotspot/jtreg/runtime/cds/appcds/loaderConstraints/DynamicLoaderConstraintsTest.java index e983b5a7aec..67cc06e38ca 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/loaderConstraints/DynamicLoaderConstraintsTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/loaderConstraints/DynamicLoaderConstraintsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, 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 @@ -130,7 +130,7 @@ public class DynamicLoaderConstraintsTest extends DynamicArchiveTestBase { static void doTest(boolean errorInDump) throws Exception { for (int i = 1; i <= 3; i++) { System.out.println("========================================"); - System.out.println("errorInDump: " + errorInDump + ", useCustomLoader: " + useCustomLoader + ", case: " + i); + System.out.println("errorInDump: " + errorInDump + ", useCustomLoader: " + useCustomLoader + ", useZGC: " + useZGC + ", case: " + i); System.out.println("========================================"); String topArchiveName = getNewArchiveName(); String testCase = Integer.toString(i); @@ -148,6 +148,7 @@ public class DynamicLoaderConstraintsTest extends DynamicArchiveTestBase { cmdLine = TestCommon.concat(cmdLine, "-cp", loaderJar, "-XX:+UseZGC", "-XX:ZCollectionInterval=0.01", loaderMainClass, appJar); + setBaseArchiveOptions("-XX:+UseZGC", "-Xlog:cds"); } else { cmdLine = TestCommon.concat(cmdLine, "-cp", loaderJar, loaderMainClass, appJar); -- GitLab From 69cfa9cb36ab2b5490c231c30306f682665faab4 Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Wed, 19 Jan 2022 04:37:09 +0000 Subject: [PATCH 197/564] 8273383: vmTestbase/vm/gc/containers/Combination05/TestDescription.java crashes verifying length of DCQS Reviewed-by: tschatzl, sjohanss --- src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp b/src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp index 9819328ee66..8f704fce350 100644 --- a/src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp +++ b/src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2022, 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 @@ -123,7 +123,13 @@ void G1DirtyCardQueueSet::enqueue_completed_buffer(BufferNode* cbn) { // Increment _num_cards before adding to queue, so queue removal doesn't // need to deal with _num_cards possibly going negative. size_t new_num_cards = Atomic::add(&_num_cards, buffer_size() - cbn->index()); - _completed.push(*cbn); + { + // Perform push in CS. The old tail may be popped while the push is + // observing it (attaching it to the new buffer). We need to ensure it + // can't be reused until the push completes, to avoid ABA problems. + GlobalCounter::CriticalSection cs(Thread::current()); + _completed.push(*cbn); + } if ((new_num_cards > process_cards_threshold()) && (_primary_refinement_thread != NULL)) { _primary_refinement_thread->activate(); -- GitLab From 44fe958c8a924dda436125716b164a335199e22b Mon Sep 17 00:00:00 2001 From: TejeshR13 Date: Wed, 19 Jan 2022 05:33:24 +0000 Subject: [PATCH 198/564] 6465404: some problems in CellEditor related API docs Reviewed-by: psadhukhan, aivanov, kizune, serb, prr --- .../classes/javax/swing/table/TableCellEditor.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/java.desktop/share/classes/javax/swing/table/TableCellEditor.java b/src/java.desktop/share/classes/javax/swing/table/TableCellEditor.java index a0bcb391ba3..21b7034a55c 100644 --- a/src/java.desktop/share/classes/javax/swing/table/TableCellEditor.java +++ b/src/java.desktop/share/classes/javax/swing/table/TableCellEditor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 1999, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,13 +27,11 @@ package javax.swing.table; import java.awt.Component; import javax.swing.CellEditor; -import javax.swing.*; +import javax.swing.JTable; /** - * This interface defines the method any object that would like to be - * an editor of values for components such as JListBox, - * JComboBox, JTree, or JTable - * needs to implement. + * This interface must be implemented to provide an editor of cell values + * for a {@code JTable}. * * @author Alan Chung */ -- GitLab From f37bfeadcf036a75defc64ad7f4a9f5596cd7407 Mon Sep 17 00:00:00 2001 From: Martin Doerr Date: Wed, 19 Jan 2022 08:28:31 +0000 Subject: [PATCH 199/564] 8280155: [PPC64, s390] frame size checks are not yet correct Reviewed-by: mbaesken, lucy --- src/hotspot/cpu/ppc/frame_ppc.cpp | 3 ++- src/hotspot/cpu/s390/frame_s390.cpp | 3 ++- src/hotspot/os_cpu/linux_ppc/thread_linux_ppc.cpp | 11 ++++++----- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/hotspot/cpu/ppc/frame_ppc.cpp b/src/hotspot/cpu/ppc/frame_ppc.cpp index 31a2b287442..b8e6433913b 100644 --- a/src/hotspot/cpu/ppc/frame_ppc.cpp +++ b/src/hotspot/cpu/ppc/frame_ppc.cpp @@ -302,7 +302,8 @@ bool frame::is_interpreted_frame_valid(JavaThread* thread) const { if (sp() == 0 || (intptr_t(sp()) & (wordSize-1)) != 0) { return false; } - if (fp() - (abi_minframe_size + ijava_state_size) < sp()) { + int min_frame_slots = (abi_minframe_size + ijava_state_size) / sizeof(intptr_t); + if (fp() - min_frame_slots < sp()) { return false; } // These are hacks to keep us out of trouble. diff --git a/src/hotspot/cpu/s390/frame_s390.cpp b/src/hotspot/cpu/s390/frame_s390.cpp index 72e1dffe57d..bfb38ffcdaf 100644 --- a/src/hotspot/cpu/s390/frame_s390.cpp +++ b/src/hotspot/cpu/s390/frame_s390.cpp @@ -306,7 +306,8 @@ bool frame::is_interpreted_frame_valid(JavaThread* thread) const { if (sp() == 0 || (intptr_t(sp()) & (wordSize-1)) != 0) { return false; } - if (fp() - (z_abi_16_size + z_ijava_state_size) < sp()) { + int min_frame_slots = (z_abi_16_size + z_ijava_state_size) / sizeof(intptr_t); + if (fp() - min_frame_slots < sp()) { return false; } // These are hacks to keep us out of trouble. diff --git a/src/hotspot/os_cpu/linux_ppc/thread_linux_ppc.cpp b/src/hotspot/os_cpu/linux_ppc/thread_linux_ppc.cpp index d09608c6aa7..15f6220fc81 100644 --- a/src/hotspot/os_cpu/linux_ppc/thread_linux_ppc.cpp +++ b/src/hotspot/os_cpu/linux_ppc/thread_linux_ppc.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2019 SAP SE. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -58,14 +58,15 @@ bool JavaThread::pd_get_top_frame_for_profiling(frame* fr_addr, void* ucontext, // if we were running Java code when SIGPROF came in. if (isInJava) { ucontext_t* uc = (ucontext_t*) ucontext; - frame ret_frame((intptr_t*)uc->uc_mcontext.regs->gpr[1/*REG_SP*/], - (address)uc->uc_mcontext.regs->nip); + address pc = (address)uc->uc_mcontext.regs->nip; - if (ret_frame.pc() == NULL) { + if (pc == NULL) { // ucontext wasn't useful return false; } + frame ret_frame((intptr_t*)uc->uc_mcontext.regs->gpr[1/*REG_SP*/], pc); + if (ret_frame.fp() == NULL) { // The found frame does not have a valid frame pointer. // Bail out because this will create big trouble later on, either -- GitLab From 5af7f258144d9f753ebe6ebfada42f33aaed108b Mon Sep 17 00:00:00 2001 From: Andrey Turbanov Date: Wed, 19 Jan 2022 10:59:40 +0000 Subject: [PATCH 200/564] 8274811: Remove superfluous use of boxing in java.base Reviewed-by: lancea --- .../linux/classes/sun/nio/fs/LinuxFileStore.java | 4 ++-- .../share/classes/java/util/ResourceBundle.java | 2 +- .../classes/sun/security/tools/keytool/Main.java | 12 ++++++------ .../sun/util/locale/provider/LocaleResources.java | 4 ++-- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/java.base/linux/classes/sun/nio/fs/LinuxFileStore.java b/src/java.base/linux/classes/sun/nio/fs/LinuxFileStore.java index 1b6fce47fc7..6ff8fe4bbf8 100644 --- a/src/java.base/linux/classes/sun/nio/fs/LinuxFileStore.java +++ b/src/java.base/linux/classes/sun/nio/fs/LinuxFileStore.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -112,7 +112,7 @@ class LinuxFileStore int[] majorMinorMicro = new int[3]; int length = Math.min(matches.length, majorMinorMicro.length); for (int i = 0; i < length; i++) { - majorMinorMicro[i] = Integer.valueOf(matches[i]); + majorMinorMicro[i] = Integer.parseInt(matches[i]); } return majorMinorMicro; } diff --git a/src/java.base/share/classes/java/util/ResourceBundle.java b/src/java.base/share/classes/java/util/ResourceBundle.java index 8f57d782d47..052de0555c7 100644 --- a/src/java.base/share/classes/java/util/ResourceBundle.java +++ b/src/java.base/share/classes/java/util/ResourceBundle.java @@ -3729,7 +3729,7 @@ public abstract class ResourceBundle { } - private static final boolean TRACE_ON = Boolean.valueOf( + private static final boolean TRACE_ON = Boolean.parseBoolean( GetPropertyAction.privilegedGetProperty("resource.bundle.debug", "false")); private static void trace(String format, Object... params) { diff --git a/src/java.base/share/classes/sun/security/tools/keytool/Main.java b/src/java.base/share/classes/sun/security/tools/keytool/Main.java index 74f0bd5c255..8cf77c96e69 100644 --- a/src/java.base/share/classes/sun/security/tools/keytool/Main.java +++ b/src/java.base/share/classes/sun/security/tools/keytool/Main.java @@ -4161,18 +4161,18 @@ public final class Main { } if (date != null) { if (date.matches("\\d\\d\\d\\d\\/\\d\\d\\/\\d\\d")) { - c.set(Integer.valueOf(date.substring(0, 4)), - Integer.valueOf(date.substring(5, 7))-1, - Integer.valueOf(date.substring(8, 10))); + c.set(Integer.parseInt(date.substring(0, 4)), + Integer.parseInt(date.substring(5, 7))-1, + Integer.parseInt(date.substring(8, 10))); } else { throw ioe; } } if (time != null) { if (time.matches("\\d\\d:\\d\\d:\\d\\d")) { - c.set(Calendar.HOUR_OF_DAY, Integer.valueOf(time.substring(0, 2))); - c.set(Calendar.MINUTE, Integer.valueOf(time.substring(3, 5))); - c.set(Calendar.SECOND, Integer.valueOf(time.substring(6, 8))); + c.set(Calendar.HOUR_OF_DAY, Integer.parseInt(time.substring(0, 2))); + c.set(Calendar.MINUTE, Integer.parseInt(time.substring(3, 5))); + c.set(Calendar.SECOND, Integer.parseInt(time.substring(6, 8))); c.set(Calendar.MILLISECOND, 0); } else { throw ioe; diff --git a/src/java.base/share/classes/sun/util/locale/provider/LocaleResources.java b/src/java.base/share/classes/sun/util/locale/provider/LocaleResources.java index b6351cf1aca..fe84b66b167 100644 --- a/src/java.base/share/classes/sun/util/locale/provider/LocaleResources.java +++ b/src/java.base/share/classes/sun/util/locale/provider/LocaleResources.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2021, 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 @@ -605,7 +605,7 @@ public class LocaleResources { } } - private static final boolean TRACE_ON = Boolean.valueOf( + private static final boolean TRACE_ON = Boolean.parseBoolean( GetPropertyAction.privilegedGetProperty("locale.resources.debug", "false")); public static void trace(String format, Object... params) { -- GitLab From 39b1d75f25ff2cc348f8b69d4e280847c6843ae2 Mon Sep 17 00:00:00 2001 From: Thomas Stuefe Date: Wed, 19 Jan 2022 11:16:00 +0000 Subject: [PATCH 201/564] 8277822: Remove debug-only heap overrun checks in os::malloc and friends Reviewed-by: coleenp, zgu --- src/hotspot/share/runtime/globals.hpp | 2 +- src/hotspot/share/runtime/os.cpp | 197 ++++++------------ src/hotspot/share/runtime/os.hpp | 7 - test/hotspot/jtreg/gtest/NMTGtests.java | 17 +- .../runtime/NMT/JcmdWithNMTDisabled.java | 11 +- .../PrintNMTStatisticsWithNMTDisabled.java | 2 +- 6 files changed, 85 insertions(+), 151 deletions(-) diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index fad671e3d26..c963a69fa60 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -543,7 +543,7 @@ const intx ObjectAlignmentInBytes = 8; "compression. Otherwise the level must be between 1 and 9.") \ range(0, 9) \ \ - product(ccstr, NativeMemoryTracking, "off", \ + product(ccstr, NativeMemoryTracking, DEBUG_ONLY("summary") NOT_DEBUG("off"), \ "Native memory tracking options") \ \ product(bool, PrintNMTStatistics, false, DIAGNOSTIC, \ diff --git a/src/hotspot/share/runtime/os.cpp b/src/hotspot/share/runtime/os.cpp index 8263480c11d..bc78d28c43d 100644 --- a/src/hotspot/share/runtime/os.cpp +++ b/src/hotspot/share/runtime/os.cpp @@ -38,7 +38,6 @@ #include "logging/log.hpp" #include "logging/logStream.hpp" #include "memory/allocation.inline.hpp" -#include "memory/guardedMemory.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.hpp" #include "oops/compressedOops.inline.hpp" @@ -83,13 +82,6 @@ int os::_processor_count = 0; int os::_initial_active_processor_count = 0; os::PageSizes os::_page_sizes; -#ifndef PRODUCT -julong os::num_mallocs = 0; // # of calls to malloc/realloc -julong os::alloc_bytes = 0; // # of bytes allocated -julong os::num_frees = 0; // # of calls to free -julong os::free_bytes = 0; // # of bytes freed -#endif - static size_t cur_malloc_words = 0; // current size for MallocMaxTestWords DEBUG_ONLY(bool os::_mutex_init_done = false;) @@ -603,30 +595,11 @@ char* os::strdup_check_oom(const char* str, MEMFLAGS flags) { return p; } - -#define paranoid 0 /* only set to 1 if you suspect checking code has bug */ - -#ifdef ASSERT - -static void verify_memory(void* ptr) { - GuardedMemory guarded(ptr); - if (!guarded.verify_guards()) { - LogTarget(Warning, malloc, free) lt; - ResourceMark rm; - LogStream ls(lt); - ls.print_cr("## nof_mallocs = " UINT64_FORMAT ", nof_frees = " UINT64_FORMAT, os::num_mallocs, os::num_frees); - ls.print_cr("## memory stomp:"); - guarded.print_on(&ls); - fatal("memory stomping error"); - } -} - -#endif - // // This function supports testing of the malloc out of memory // condition without really running the system out of memory. // + static bool has_reached_max_malloc_test_peak(size_t alloc_size) { if (MallocMaxTestWords > 0) { size_t words = (alloc_size / BytesPerWord); @@ -639,13 +612,24 @@ static bool has_reached_max_malloc_test_peak(size_t alloc_size) { return false; } +#ifdef ASSERT +static void check_crash_protection() { + assert(!os::ThreadCrashProtection::is_crash_protected(Thread::current_or_null()), + "not allowed when crash protection is set"); +} +static void break_if_ptr_caught(void* ptr) { + if (p2i(ptr) == (intptr_t)MallocCatchPtr) { + log_warning(malloc, free)("ptr caught: " PTR_FORMAT, p2i(ptr)); + breakpoint(); + } +} +#endif // ASSERT + void* os::malloc(size_t size, MEMFLAGS flags) { return os::malloc(size, flags, CALLER_PC); } void* os::malloc(size_t size, MEMFLAGS memflags, const NativeCallStack& stack) { - NOT_PRODUCT(inc_stat_counter(&num_mallocs, 1)); - NOT_PRODUCT(inc_stat_counter(&alloc_bytes, size)); #if INCLUDE_NMT { @@ -656,58 +640,35 @@ void* os::malloc(size_t size, MEMFLAGS memflags, const NativeCallStack& stack) { } #endif - // Since os::malloc can be called when the libjvm.{dll,so} is - // first loaded and we don't have a thread yet we must accept NULL also here. - assert(!os::ThreadCrashProtection::is_crash_protected(Thread::current_or_null()), - "malloc() not allowed when crash protection is set"); + DEBUG_ONLY(check_crash_protection()); - if (size == 0) { - // return a valid pointer if size is zero - // if NULL is returned the calling functions assume out of memory. - size = 1; - } - - // NMT support - NMT_TrackingLevel level = MemTracker::tracking_level(); - const size_t nmt_overhead = - MemTracker::malloc_header_size(level) + MemTracker::malloc_footer_size(level); - -#ifndef ASSERT - const size_t alloc_size = size + nmt_overhead; -#else - const size_t alloc_size = GuardedMemory::get_total_size(size + nmt_overhead); - if (size + nmt_overhead > alloc_size) { // Check for rollover. - return NULL; - } -#endif + // On malloc(0), implementators of malloc(3) have the choice to return either + // NULL or a unique non-NULL pointer. To unify libc behavior across our platforms + // we chose the latter. + size = MAX2((size_t)1, size); // For the test flag -XX:MallocMaxTestWords if (has_reached_max_malloc_test_peak(size)) { return NULL; } - u_char* ptr; - ptr = (u_char*)::malloc(alloc_size); + const NMT_TrackingLevel level = MemTracker::tracking_level(); + const size_t nmt_overhead = + MemTracker::malloc_header_size(level) + MemTracker::malloc_footer_size(level); + + const size_t outer_size = size + nmt_overhead; -#ifdef ASSERT - if (ptr == NULL) { + void* const outer_ptr = (u_char*)::malloc(outer_size); + if (outer_ptr == NULL) { return NULL; } - // Wrap memory with guard - GuardedMemory guarded(ptr, size + nmt_overhead); - ptr = guarded.get_user_ptr(); - if ((intptr_t)ptr == (intptr_t)MallocCatchPtr) { - log_warning(malloc, free)("os::malloc caught, " SIZE_FORMAT " bytes --> " PTR_FORMAT, size, p2i(ptr)); - breakpoint(); - } - if (paranoid) { - verify_memory(ptr); - } -#endif + void* inner_ptr = MemTracker::record_malloc((address)outer_ptr, size, memflags, stack, level); - // we do not track guard memory - return MemTracker::record_malloc((address)ptr, size, memflags, stack, level); + DEBUG_ONLY(::memset(inner_ptr, uninitBlockPad, size);) + DEBUG_ONLY(break_if_ptr_caught(inner_ptr);) + + return inner_ptr; } void* os::realloc(void *memblock, size_t size, MEMFLAGS flags) { @@ -725,59 +686,41 @@ void* os::realloc(void *memblock, size_t size, MEMFLAGS memflags, const NativeCa } #endif + if (memblock == NULL) { + return os::malloc(size, memflags, stack); + } + + DEBUG_ONLY(check_crash_protection()); + + // On realloc(p, 0), implementators of realloc(3) have the choice to return either + // NULL or a unique non-NULL pointer. To unify libc behavior across our platforms + // we chose the latter. + size = MAX2((size_t)1, size); + // For the test flag -XX:MallocMaxTestWords if (has_reached_max_malloc_test_peak(size)) { return NULL; } - if (size == 0) { - // return a valid pointer if size is zero - // if NULL is returned the calling functions assume out of memory. - size = 1; - } - -#ifndef ASSERT - NOT_PRODUCT(inc_stat_counter(&num_mallocs, 1)); - NOT_PRODUCT(inc_stat_counter(&alloc_bytes, size)); - // NMT support - NMT_TrackingLevel level = MemTracker::tracking_level(); - void* membase = MemTracker::record_free(memblock, level); + const NMT_TrackingLevel level = MemTracker::tracking_level(); const size_t nmt_overhead = MemTracker::malloc_header_size(level) + MemTracker::malloc_footer_size(level); - void* ptr = ::realloc(membase, size + nmt_overhead); - return MemTracker::record_malloc(ptr, size, memflags, stack, level); -#else - if (memblock == NULL) { - return os::malloc(size, memflags, stack); - } - if ((intptr_t)memblock == (intptr_t)MallocCatchPtr) { - log_warning(malloc, free)("os::realloc caught " PTR_FORMAT, p2i(memblock)); - breakpoint(); - } - // NMT support - void* membase = MemTracker::malloc_base(memblock); - verify_memory(membase); - // always move the block - void* ptr = os::malloc(size, memflags, stack); - // Copy to new memory if malloc didn't fail - if (ptr != NULL ) { - GuardedMemory guarded(MemTracker::malloc_base(memblock)); - // Guard's user data contains NMT header - NMT_TrackingLevel level = MemTracker::tracking_level(); - const size_t nmt_overhead = - MemTracker::malloc_header_size(level) + MemTracker::malloc_footer_size(level); - size_t memblock_size = guarded.get_user_size() - nmt_overhead; - memcpy(ptr, memblock, MIN2(size, memblock_size)); - if (paranoid) { - verify_memory(MemTracker::malloc_base(ptr)); - } - os::free(memblock); - } - return ptr; -#endif + + const size_t new_outer_size = size + nmt_overhead; + + // If NMT is enabled, this checks for heap overwrites, then de-accounts the old block. + void* const old_outer_ptr = MemTracker::record_free(memblock, level); + + void* const new_outer_ptr = ::realloc(old_outer_ptr, new_outer_size); + + // If NMT is enabled, this checks for heap overwrites, then de-accounts the old block. + void* const new_inner_ptr = MemTracker::record_malloc(new_outer_ptr, size, memflags, stack, level); + + DEBUG_ONLY(break_if_ptr_caught(new_inner_ptr);) + + return new_inner_ptr; } -// handles NULL pointers void os::free(void *memblock) { #if INCLUDE_NMT @@ -786,25 +729,17 @@ void os::free(void *memblock) { } #endif - NOT_PRODUCT(inc_stat_counter(&num_frees, 1)); -#ifdef ASSERT - if (memblock == NULL) return; - if ((intptr_t)memblock == (intptr_t)MallocCatchPtr) { - log_warning(malloc, free)("os::free caught " PTR_FORMAT, p2i(memblock)); - breakpoint(); + if (memblock == NULL) { + return; } - void* membase = MemTracker::record_free(memblock, MemTracker::tracking_level()); - verify_memory(membase); - GuardedMemory guarded(membase); - size_t size = guarded.get_user_size(); - inc_stat_counter(&free_bytes, size); - membase = guarded.release_for_freeing(); - ::free(membase); -#else - void* membase = MemTracker::record_free(memblock, MemTracker::tracking_level()); - ::free(membase); -#endif + DEBUG_ONLY(break_if_ptr_caught(memblock);) + + const NMT_TrackingLevel level = MemTracker::tracking_level(); + + // If NMT is enabled, this checks for heap overwrites, then de-accounts the old block. + void* const old_outer_ptr = MemTracker::record_free(memblock, level); + ::free(old_outer_ptr); } void os::init_random(unsigned int initval) { diff --git a/src/hotspot/share/runtime/os.hpp b/src/hotspot/share/runtime/os.hpp index 67e427fd947..d3e48cb54f4 100644 --- a/src/hotspot/share/runtime/os.hpp +++ b/src/hotspot/share/runtime/os.hpp @@ -784,13 +784,6 @@ class os: AllStatic { // Like strdup, but exit VM when strdup() returns NULL static char* strdup_check_oom(const char*, MEMFLAGS flags = mtInternal); -#ifndef PRODUCT - static julong num_mallocs; // # of calls to malloc/realloc - static julong alloc_bytes; // # of bytes allocated - static julong num_frees; // # of calls to free - static julong free_bytes; // # of bytes freed -#endif - // SocketInterface (ex HPI SocketInterface ) static int socket(int domain, int type, int protocol); static int socket_close(int fd); diff --git a/test/hotspot/jtreg/gtest/NMTGtests.java b/test/hotspot/jtreg/gtest/NMTGtests.java index b79f46395fb..57666680b6b 100644 --- a/test/hotspot/jtreg/gtest/NMTGtests.java +++ b/test/hotspot/jtreg/gtest/NMTGtests.java @@ -24,10 +24,15 @@ */ /* - * This tests NMT by running gtests with NMT enabled. - * - * To save time, we just run them for debug builds (where we would catch assertions) and only a selection of tests - * (namely, NMT tests themselves, and - for the detail statistics - os tests, since those reserve a lot and stress NMT) + * This tests NMT by running gtests with NMT enabled (only those which are relevant for NMT) + */ + +/* @test id=nmt-off + * @summary Run NMT-related gtests with NMT switched off + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.xml + * @run main/native GTestWrapper --gtest_filter=NMT*:os* -XX:NativeMemoryTracking=off */ /* @test id=nmt-summary @@ -35,8 +40,7 @@ * @library /test/lib * @modules java.base/jdk.internal.misc * java.xml - * @requires vm.debug - * @run main/native GTestWrapper --gtest_filter=NMT* -XX:NativeMemoryTracking=summary + * @run main/native GTestWrapper --gtest_filter=NMT*:os* -XX:NativeMemoryTracking=summary */ /* @test id=nmt-detail @@ -44,6 +48,5 @@ * @library /test/lib * @modules java.base/jdk.internal.misc * java.xml - * @requires vm.debug * @run main/native GTestWrapper --gtest_filter=NMT*:os* -XX:NativeMemoryTracking=detail */ diff --git a/test/hotspot/jtreg/runtime/NMT/JcmdWithNMTDisabled.java b/test/hotspot/jtreg/runtime/NMT/JcmdWithNMTDisabled.java index 891f82be0bd..da1dd497975 100644 --- a/test/hotspot/jtreg/runtime/NMT/JcmdWithNMTDisabled.java +++ b/test/hotspot/jtreg/runtime/NMT/JcmdWithNMTDisabled.java @@ -30,6 +30,7 @@ * @run driver JcmdWithNMTDisabled 1 */ +import jdk.test.lib.Platform; import jdk.test.lib.process.ProcessTools; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.JDKToolFinder; @@ -47,10 +48,12 @@ public class JcmdWithNMTDisabled { OutputAnalyzer output; String testjdkPath = System.getProperty("test.jdk"); - // First run without enabling NMT - pb = ProcessTools.createJavaProcessBuilder("-Dtest.jdk=" + testjdkPath, "JcmdWithNMTDisabled"); - output = new OutputAnalyzer(pb.start()); - output.shouldHaveExitValue(0); + // First run without enabling NMT (not in debug, where NMT is by default on) + if (!Platform.isDebugBuild()) { + pb = ProcessTools.createJavaProcessBuilder("-Dtest.jdk=" + testjdkPath, "JcmdWithNMTDisabled"); + output = new OutputAnalyzer(pb.start()); + output.shouldHaveExitValue(0); + } // Then run with explicitly disabling NMT, should not be any difference pb = ProcessTools.createJavaProcessBuilder("-Dtest.jdk=" + testjdkPath, "-XX:NativeMemoryTracking=off", "JcmdWithNMTDisabled"); diff --git a/test/hotspot/jtreg/runtime/NMT/PrintNMTStatisticsWithNMTDisabled.java b/test/hotspot/jtreg/runtime/NMT/PrintNMTStatisticsWithNMTDisabled.java index 7e45c3f16d7..31ab2537fe1 100644 --- a/test/hotspot/jtreg/runtime/NMT/PrintNMTStatisticsWithNMTDisabled.java +++ b/test/hotspot/jtreg/runtime/NMT/PrintNMTStatisticsWithNMTDisabled.java @@ -38,7 +38,7 @@ public class PrintNMTStatisticsWithNMTDisabled { public static void main(String args[]) throws Exception { ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( "-XX:+UnlockDiagnosticVMOptions", - "-XX:+PrintNMTStatistics", + "-XX:+PrintNMTStatistics", "-XX:NativeMemoryTracking=off", "-version"); OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldContain("warning: PrintNMTStatistics is disabled, because native memory tracking is not enabled"); -- GitLab From 68b40ec28658a2dd829c77281b0025e16095c170 Mon Sep 17 00:00:00 2001 From: Emanuel Peter Date: Wed, 19 Jan 2022 11:47:17 +0000 Subject: [PATCH 202/564] 8273139: C2: assert(f <= 1 && f >= 0) failed: Incorrect frequency Reviewed-by: thartmann, chagedorn, roland --- src/hotspot/share/opto/loopPredicate.cpp | 31 +++++++++++------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/src/hotspot/share/opto/loopPredicate.cpp b/src/hotspot/share/opto/loopPredicate.cpp index d190b3db759..b7f1ce6ff7e 100644 --- a/src/hotspot/share/opto/loopPredicate.cpp +++ b/src/hotspot/share/opto/loopPredicate.cpp @@ -1024,13 +1024,15 @@ private: GrowableArray _freqs; // cache frequencies PhaseIdealLoop* _phase; - void set_rounding(int mode) { - // fesetround is broken on windows - NOT_WINDOWS(fesetround(mode);) - } - - void check_frequency(float f) { - NOT_WINDOWS(assert(f <= 1 && f >= 0, "Incorrect frequency");) + float check_and_truncate_frequency(float f) { + assert(f >= 0, "Incorrect frequency"); + // We do not perform an exact (f <= 1) check + // this would be error prone with rounding of floats. + // Performing a check like (f <= 1+eps) would be of benefit, + // however, it is not evident how to determine such an eps, + // given that an arbitrary number of add/mul operations + // are performed on these frequencies. + return (f > 1) ? 1 : f; } public: @@ -1040,7 +1042,6 @@ public: float to(Node* n) { // post order walk on the CFG graph from n to _dom - set_rounding(FE_TOWARDZERO); // make sure rounding doesn't push frequency above 1 IdealLoopTree* loop = _phase->get_loop(_dom); Node* c = n; for (;;) { @@ -1067,14 +1068,12 @@ public: inner_head = inner_loop->_head->as_Loop(); inner_head->verify_strip_mined(1); } - set_rounding(FE_UPWARD); // make sure rounding doesn't push frequency above 1 float loop_exit_cnt = 0.0f; for (uint i = 0; i < inner_loop->_body.size(); i++) { Node *n = inner_loop->_body[i]; float c = inner_loop->compute_profile_trip_cnt_helper(n); loop_exit_cnt += c; } - set_rounding(FE_TOWARDZERO); float cnt = -1; if (n->in(0)->is_If()) { IfNode* iff = n->in(0)->as_If(); @@ -1094,9 +1093,9 @@ public: cnt = p * jmp->_fcnt; } float this_exit_f = cnt > 0 ? cnt / loop_exit_cnt : 0; - check_frequency(this_exit_f); + this_exit_f = check_and_truncate_frequency(this_exit_f); f = f * this_exit_f; - check_frequency(f); + f = check_and_truncate_frequency(f); } else { float p = -1; if (n->in(0)->is_If()) { @@ -1109,7 +1108,7 @@ public: p = n->in(0)->as_Jump()->_probs[n->as_JumpProj()->_con]; } f = f * p; - check_frequency(f); + f = check_and_truncate_frequency(f); } _freqs.at_put_grow(n->_idx, (float)f, -1); _stack.pop(); @@ -1117,7 +1116,7 @@ public: float prev_f = _freqs_stack.pop(); float new_f = f; f = new_f + prev_f; - check_frequency(f); + f = check_and_truncate_frequency(f); uint i = _stack.index(); if (i < n->req()) { c = n->in(i); @@ -1130,9 +1129,7 @@ public: } } if (_stack.size() == 0) { - set_rounding(FE_TONEAREST); - check_frequency(f); - return f; + return check_and_truncate_frequency(f); } } else if (c->is_Loop()) { ShouldNotReachHere(); -- GitLab From 28e02fa2cb40267136c88a507696ec3e610e95a3 Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Wed, 19 Jan 2022 12:01:05 +0000 Subject: [PATCH 203/564] 8280234: AArch64 "core" variant does not build after JDK-8270947 Reviewed-by: adinn, aph --- src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp index 07e3fdad17b..5641c1b1417 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp @@ -29,6 +29,7 @@ #include "jvm.h" #include "asm/assembler.hpp" #include "asm/assembler.inline.hpp" +#include "ci/ciEnv.hpp" #include "gc/shared/barrierSet.hpp" #include "gc/shared/barrierSetAssembler.hpp" #include "gc/shared/cardTableBarrierSet.hpp" -- GitLab From 8931c12258a39cabda2cd1b92f54afcb216b882e Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Wed, 19 Jan 2022 12:01:10 +0000 Subject: [PATCH 204/564] 8280157: wrong texts Falied in a couple of tests Reviewed-by: egahlin, aivanov --- .../TranslucentShapedFrameTest.form | 2 +- .../TranslucentShapedFrameTest.java | 4 ++-- test/jdk/java/io/OutputStreamWriter/WriteAfterClose.java | 4 ++-- test/jdk/jdk/jfr/api/consumer/TestRecordedFullStackTrace.java | 4 ++-- test/jdk/jdk/jfr/event/profiling/TestFullStackTrace.java | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/test/jdk/java/awt/Window/TranslucentShapedFrameTest/TranslucentShapedFrameTest.form b/test/jdk/java/awt/Window/TranslucentShapedFrameTest/TranslucentShapedFrameTest.form index 4291e0eeaac..6735391ad38 100644 --- a/test/jdk/java/awt/Window/TranslucentShapedFrameTest/TranslucentShapedFrameTest.form +++ b/test/jdk/java/awt/Window/TranslucentShapedFrameTest/TranslucentShapedFrameTest.form @@ -158,7 +158,7 @@ - + diff --git a/test/jdk/java/awt/Window/TranslucentShapedFrameTest/TranslucentShapedFrameTest.java b/test/jdk/java/awt/Window/TranslucentShapedFrameTest/TranslucentShapedFrameTest.java index bdcf99c3a3c..b87c44d9078 100644 --- a/test/jdk/java/awt/Window/TranslucentShapedFrameTest/TranslucentShapedFrameTest.java +++ b/test/jdk/java/awt/Window/TranslucentShapedFrameTest/TranslucentShapedFrameTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2022, 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 @@ -122,7 +122,7 @@ public class TranslucentShapedFrameTest extends javax.swing.JFrame { jTextArea1.setColumns(20); jTextArea1.setRows(5); - jTextArea1.setText("Create translucent and/or shaped, or\nnon-opaque frame. Make sure it behaves\ncorrectly (no artifacts left on the screen\nwhen dragging - if dragging is possible).\nClick \"Passed\" if the test behaves correctly,\n\"Falied\" otherwise."); + jTextArea1.setText("Create translucent and/or shaped, or\nnon-opaque frame. Make sure it behaves\ncorrectly (no artifacts left on the screen\nwhen dragging - if dragging is possible).\nClick \"Passed\" if the test behaves correctly,\n\"Failed\" otherwise."); jScrollPane1.setViewportView(jTextArea1); jLabel2.setText("Instructions:"); diff --git a/test/jdk/java/io/OutputStreamWriter/WriteAfterClose.java b/test/jdk/java/io/OutputStreamWriter/WriteAfterClose.java index 0982df62a6d..d2bdd362065 100644 --- a/test/jdk/java/io/OutputStreamWriter/WriteAfterClose.java +++ b/test/jdk/java/io/OutputStreamWriter/WriteAfterClose.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2022, 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 @@ -74,7 +74,7 @@ public class WriteAfterClose { try { wtr.write("a", 0, 1); - System.out.println("FALIED: Allows string buf write on a closed stream"); + System.out.println("FAILED: Allows string buf write on a closed stream"); failed = true; } catch (Exception e) { } diff --git a/test/jdk/jdk/jfr/api/consumer/TestRecordedFullStackTrace.java b/test/jdk/jdk/jfr/api/consumer/TestRecordedFullStackTrace.java index 1487d2e0258..6993fe31001 100644 --- a/test/jdk/jdk/jfr/api/consumer/TestRecordedFullStackTrace.java +++ b/test/jdk/jdk/jfr/api/consumer/TestRecordedFullStackTrace.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2022, 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 @@ -119,7 +119,7 @@ public class TestRecordedFullStackTrace { if (!isEventFound[i]) { // no assertion, let's retry. // Could be race condition, i.e safe point during Thread.sleep - System.out.println("Falied to validate all threads, will retry."); + System.out.println("Failed to validate all threads, will retry."); return false; } } diff --git a/test/jdk/jdk/jfr/event/profiling/TestFullStackTrace.java b/test/jdk/jdk/jfr/event/profiling/TestFullStackTrace.java index 3306f5c0d31..b9f23ebed86 100644 --- a/test/jdk/jdk/jfr/event/profiling/TestFullStackTrace.java +++ b/test/jdk/jdk/jfr/event/profiling/TestFullStackTrace.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2022, 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 @@ -111,7 +111,7 @@ public class TestFullStackTrace { if(!isEventFound[i]) { // no assertion, let's retry. // Could be race condition, i.e safe point during Thread.sleep - System.out.println("Falied to validate all threads, will retry."); + System.out.println("Failed to validate all threads, will retry."); return false; } } -- GitLab From cc2f474c18082413420b353528198883055de73a Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Wed, 19 Jan 2022 12:02:42 +0000 Subject: [PATCH 205/564] 8280024: Parallel: Remove unnecessary region resizing methods in PSCardTable Reviewed-by: tschatzl, mli --- src/hotspot/share/gc/parallel/psCardTable.cpp | 278 ------------------ src/hotspot/share/gc/parallel/psCardTable.hpp | 21 -- 2 files changed, 299 deletions(-) diff --git a/src/hotspot/share/gc/parallel/psCardTable.cpp b/src/hotspot/share/gc/parallel/psCardTable.cpp index cecb3aa97cb..8f851d9f26e 100644 --- a/src/hotspot/share/gc/parallel/psCardTable.cpp +++ b/src/hotspot/share/gc/parallel/psCardTable.cpp @@ -411,284 +411,6 @@ bool PSCardTable::addr_is_marked_precise(void *addr) { return false; } -// Assumes that only the base or the end changes. This allows indentification -// of the region that is being resized. The -// CardTable::resize_covered_region() is used for the normal case -// where the covered regions are growing or shrinking at the high end. -// The method resize_covered_region_by_end() is analogous to -// CardTable::resize_covered_region() but -// for regions that grow or shrink at the low end. -void PSCardTable::resize_covered_region(MemRegion new_region) { - for (int i = 0; i < _cur_covered_regions; i++) { - if (_covered[i].start() == new_region.start()) { - // Found a covered region with the same start as the - // new region. The region is growing or shrinking - // from the start of the region. - resize_covered_region_by_start(new_region); - return; - } - if (_covered[i].start() > new_region.start()) { - break; - } - } - - int changed_region = -1; - for (int j = 0; j < _cur_covered_regions; j++) { - if (_covered[j].end() == new_region.end()) { - changed_region = j; - // This is a case where the covered region is growing or shrinking - // at the start of the region. - assert(changed_region != -1, "Don't expect to add a covered region"); - assert(_covered[changed_region].byte_size() != new_region.byte_size(), - "The sizes should be different here"); - resize_covered_region_by_end(changed_region, new_region); - return; - } - } - // This should only be a new covered region (where no existing - // covered region matches at the start or the end). - assert(_cur_covered_regions < _max_covered_regions, - "An existing region should have been found"); - resize_covered_region_by_start(new_region); -} - -void PSCardTable::resize_covered_region_by_start(MemRegion new_region) { - CardTable::resize_covered_region(new_region); - debug_only(verify_guard();) -} - -void PSCardTable::resize_covered_region_by_end(int changed_region, - MemRegion new_region) { - assert(SafepointSynchronize::is_at_safepoint(), - "Only expect an expansion at the low end at a GC"); - debug_only(verify_guard();) -#ifdef ASSERT - for (int k = 0; k < _cur_covered_regions; k++) { - if (_covered[k].end() == new_region.end()) { - assert(changed_region == k, "Changed region is incorrect"); - break; - } - } -#endif - - // Commit new or uncommit old pages, if necessary. - if (resize_commit_uncommit(changed_region, new_region)) { - // Set the new start of the committed region - resize_update_committed_table(changed_region, new_region); - } - - // Update card table entries - resize_update_card_table_entries(changed_region, new_region); - - // Update the covered region - resize_update_covered_table(changed_region, new_region); - - int ind = changed_region; - log_trace(gc, barrier)("CardTable::resize_covered_region: "); - log_trace(gc, barrier)(" _covered[%d].start(): " INTPTR_FORMAT " _covered[%d].last(): " INTPTR_FORMAT, - ind, p2i(_covered[ind].start()), ind, p2i(_covered[ind].last())); - log_trace(gc, barrier)(" _committed[%d].start(): " INTPTR_FORMAT " _committed[%d].last(): " INTPTR_FORMAT, - ind, p2i(_committed[ind].start()), ind, p2i(_committed[ind].last())); - log_trace(gc, barrier)(" byte_for(start): " INTPTR_FORMAT " byte_for(last): " INTPTR_FORMAT, - p2i(byte_for(_covered[ind].start())), p2i(byte_for(_covered[ind].last()))); - log_trace(gc, barrier)(" addr_for(start): " INTPTR_FORMAT " addr_for(last): " INTPTR_FORMAT, - p2i(addr_for((CardValue*) _committed[ind].start())), p2i(addr_for((CardValue*) _committed[ind].last()))); - - debug_only(verify_guard();) -} - -bool PSCardTable::resize_commit_uncommit(int changed_region, - MemRegion new_region) { - bool result = false; - // Commit new or uncommit old pages, if necessary. - MemRegion cur_committed = _committed[changed_region]; - assert(_covered[changed_region].end() == new_region.end(), - "The ends of the regions are expected to match"); - // Extend the start of this _committed region to - // to cover the start of any previous _committed region. - // This forms overlapping regions, but never interior regions. - HeapWord* min_prev_start = lowest_prev_committed_start(changed_region); - if (min_prev_start < cur_committed.start()) { - // Only really need to set start of "cur_committed" to - // the new start (min_prev_start) but assertion checking code - // below use cur_committed.end() so make it correct. - MemRegion new_committed = - MemRegion(min_prev_start, cur_committed.end()); - cur_committed = new_committed; - } -#ifdef ASSERT - ParallelScavengeHeap* heap = ParallelScavengeHeap::heap(); - assert(cur_committed.start() == align_up(cur_committed.start(), os::vm_page_size()), - "Starts should have proper alignment"); -#endif - - CardValue* new_start = byte_for(new_region.start()); - // Round down because this is for the start address - HeapWord* new_start_aligned = align_down((HeapWord*)new_start, os::vm_page_size()); - // The guard page is always committed and should not be committed over. - // This method is used in cases where the generation is growing toward - // lower addresses but the guard region is still at the end of the - // card table. That still makes sense when looking for writes - // off the end of the card table. - if (new_start_aligned < cur_committed.start()) { - // Expand the committed region - // - // Case A - // |+ guard +| - // |+ cur committed +++++++++| - // |+ new committed +++++++++++++++++| - // - // Case B - // |+ guard +| - // |+ cur committed +| - // |+ new committed +++++++| - // - // These are not expected because the calculation of the - // cur committed region and the new committed region - // share the same end for the covered region. - // Case C - // |+ guard +| - // |+ cur committed +| - // |+ new committed +++++++++++++++++| - // Case D - // |+ guard +| - // |+ cur committed +++++++++++| - // |+ new committed +++++++| - - HeapWord* new_end_for_commit = - MIN2(cur_committed.end(), _guard_region.start()); - if(new_start_aligned < new_end_for_commit) { - MemRegion new_committed = - MemRegion(new_start_aligned, new_end_for_commit); - os::commit_memory_or_exit((char*)new_committed.start(), - new_committed.byte_size(), !ExecMem, - "card table expansion"); - } - result = true; - } else if (new_start_aligned > cur_committed.start()) { - // Shrink the committed region -#if 0 // uncommitting space is currently unsafe because of the interactions - // of growing and shrinking regions. One region A can uncommit space - // that it owns but which is being used by another region B (maybe). - // Region B has not committed the space because it was already - // committed by region A. - MemRegion uncommit_region = committed_unique_to_self(changed_region, - MemRegion(cur_committed.start(), new_start_aligned)); - if (!uncommit_region.is_empty()) { - if (!os::uncommit_memory((char*)uncommit_region.start(), - uncommit_region.byte_size())) { - // If the uncommit fails, ignore it. Let the - // committed table resizing go even though the committed - // table will over state the committed space. - } - } -#else - assert(!result, "Should be false with current workaround"); -#endif - } - assert(_committed[changed_region].end() == cur_committed.end(), - "end should not change"); - return result; -} - -void PSCardTable::resize_update_committed_table(int changed_region, - MemRegion new_region) { - - CardValue* new_start = byte_for(new_region.start()); - // Set the new start of the committed region - HeapWord* new_start_aligned = align_down((HeapWord*)new_start, os::vm_page_size()); - MemRegion new_committed = MemRegion(new_start_aligned, - _committed[changed_region].end()); - _committed[changed_region] = new_committed; - _committed[changed_region].set_start(new_start_aligned); -} - -void PSCardTable::resize_update_card_table_entries(int changed_region, - MemRegion new_region) { - debug_only(verify_guard();) - MemRegion original_covered = _covered[changed_region]; - // Initialize the card entries. Only consider the - // region covered by the card table (_whole_heap) - CardValue* entry; - if (new_region.start() < _whole_heap.start()) { - entry = byte_for(_whole_heap.start()); - } else { - entry = byte_for(new_region.start()); - } - CardValue* end = byte_for(original_covered.start()); - // If _whole_heap starts at the original covered regions start, - // this loop will not execute. - while (entry < end) { *entry++ = clean_card; } -} - -void PSCardTable::resize_update_covered_table(int changed_region, - MemRegion new_region) { - // Update the covered region - _covered[changed_region].set_start(new_region.start()); - _covered[changed_region].set_word_size(new_region.word_size()); - - // reorder regions. There should only be at most 1 out - // of order. - for (int i = _cur_covered_regions-1 ; i > 0; i--) { - if (_covered[i].start() < _covered[i-1].start()) { - MemRegion covered_mr = _covered[i-1]; - _covered[i-1] = _covered[i]; - _covered[i] = covered_mr; - MemRegion committed_mr = _committed[i-1]; - _committed[i-1] = _committed[i]; - _committed[i] = committed_mr; - break; - } - } -#ifdef ASSERT - for (int m = 0; m < _cur_covered_regions-1; m++) { - assert(_covered[m].start() <= _covered[m+1].start(), - "Covered regions out of order"); - assert(_committed[m].start() <= _committed[m+1].start(), - "Committed regions out of order"); - } -#endif -} - -// Returns the start of any committed region that is lower than -// the target committed region (index ind) and that intersects the -// target region. If none, return start of target region. -// -// ------------- -// | | -// ------------- -// ------------ -// | target | -// ------------ -// ------------- -// | | -// ------------- -// ^ returns this -// -// ------------- -// | | -// ------------- -// ------------ -// | target | -// ------------ -// ------------- -// | | -// ------------- -// ^ returns this - -HeapWord* PSCardTable::lowest_prev_committed_start(int ind) const { - assert(_cur_covered_regions >= 0, "Expecting at least on region"); - HeapWord* min_start = _committed[ind].start(); - for (int j = 0; j < ind; j++) { - HeapWord* this_start = _committed[j].start(); - if ((this_start < min_start) && - !(_committed[j].intersection(_committed[ind])).is_empty()) { - min_start = this_start; - } - } - return min_start; -} - bool PSCardTable::is_in_young(oop obj) const { return ParallelScavengeHeap::heap()->is_in_young(obj); } diff --git a/src/hotspot/share/gc/parallel/psCardTable.hpp b/src/hotspot/share/gc/parallel/psCardTable.hpp index d912c656741..bfbaab7d7fc 100644 --- a/src/hotspot/share/gc/parallel/psCardTable.hpp +++ b/src/hotspot/share/gc/parallel/psCardTable.hpp @@ -34,14 +34,6 @@ class PSPromotionManager; class PSCardTable: public CardTable { private: - // Support methods for resizing the card table. - // resize_commit_uncommit() returns true if the pages were committed or - // uncommitted - bool resize_commit_uncommit(int changed_region, MemRegion new_region); - void resize_update_card_table_entries(int changed_region, - MemRegion new_region); - void resize_update_committed_table(int changed_region, MemRegion new_region); - void resize_update_covered_table(int changed_region, MemRegion new_region); void verify_all_young_refs_precise_helper(MemRegion mr); @@ -84,19 +76,6 @@ class PSCardTable: public CardTable { // ReduceInitialCardMarks support bool is_in_young(oop obj) const; - // Adaptive size policy support - // Allows adjustment of the base and size of the covered regions - void resize_covered_region(MemRegion new_region); - // Finds the covered region to resize based on the start address - // of the covered regions. - void resize_covered_region_by_start(MemRegion new_region); - // Finds the covered region to resize based on the end address - // of the covered regions. - void resize_covered_region_by_end(int changed_region, MemRegion new_region); - // Finds the lowest start address of a covered region that is - // previous (i.e., lower index) to the covered region with index "ind". - HeapWord* lowest_prev_committed_start(int ind) const; - #ifdef ASSERT bool is_valid_card_address(CardValue* addr) { return (addr >= _byte_map) && (addr < _byte_map + _byte_map_size); -- GitLab From 96114315cf91b03aeca7e12f225e4c76862f1be7 Mon Sep 17 00:00:00 2001 From: Harold Seigel Date: Wed, 19 Jan 2022 13:51:23 +0000 Subject: [PATCH 206/564] 8279936: Change shared code to use os:: system API's Reviewed-by: dholmes, kbarrett --- src/hotspot/share/cds/filemap.cpp | 14 +++++++------- src/hotspot/share/classfile/compactHashtable.cpp | 4 ++-- src/hotspot/share/compiler/compileLog.cpp | 8 ++++---- src/hotspot/share/utilities/vmError.cpp | 2 +- test/hotspot/gtest/logging/logTestUtils.inline.hpp | 6 +++--- test/hotspot/gtest/logging/test_asynclog.cpp | 3 ++- test/hotspot/gtest/logging/test_log.cpp | 4 ++-- .../gtest/logging/test_logTagSetDescriptions.cpp | 4 ++-- 8 files changed, 23 insertions(+), 22 deletions(-) diff --git a/src/hotspot/share/cds/filemap.cpp b/src/hotspot/share/cds/filemap.cpp index 0011157e7f7..5c684e960f1 100644 --- a/src/hotspot/share/cds/filemap.cpp +++ b/src/hotspot/share/cds/filemap.cpp @@ -1091,7 +1091,7 @@ public: // First read the generic header so we know the exact size of the actual header. GenericCDSFileMapHeader gen_header; size_t size = sizeof(GenericCDSFileMapHeader); - lseek(fd, 0, SEEK_SET); + os::lseek(fd, 0, SEEK_SET); size_t n = os::read(fd, (void*)&gen_header, (unsigned int)size); if (n != size) { FileMapInfo::fail_continue("Unable to read generic CDS file map header from shared archive"); @@ -1124,7 +1124,7 @@ public: // Read the actual header and perform more checks size = gen_header._header_size; _header = (GenericCDSFileMapHeader*)NEW_C_HEAP_ARRAY(char, size, mtInternal); - lseek(fd, 0, SEEK_SET); + os::lseek(fd, 0, SEEK_SET); n = os::read(fd, (void*)_header, (unsigned int)size); if (n != size) { FileMapInfo::fail_continue("Unable to read actual CDS file map header from shared archive"); @@ -1277,7 +1277,7 @@ bool FileMapInfo::init_from_file(int fd) { } _header = (FileMapHeader*)os::malloc(gen_header->_header_size, mtInternal); - lseek(fd, 0, SEEK_SET); // reset to begin of the archive + os::lseek(fd, 0, SEEK_SET); // reset to begin of the archive size_t size = gen_header->_header_size; size_t n = os::read(fd, (void*)_header, (unsigned int)size); if (n != size) { @@ -1327,7 +1327,7 @@ bool FileMapInfo::init_from_file(int fd) { if (is_static()) { // just checking the last region is sufficient since the archive is written // in sequential order - size_t len = lseek(fd, 0, SEEK_END); + size_t len = os::lseek(fd, 0, SEEK_END); FileMapRegion* si = space_at(MetaspaceShared::last_valid_region); // The last space might be empty if (si->file_offset() > len || len - si->file_offset() < si->used()) { @@ -1340,7 +1340,7 @@ bool FileMapInfo::init_from_file(int fd) { } void FileMapInfo::seek_to_position(size_t pos) { - if (lseek(_fd, (long)pos, SEEK_SET) < 0) { + if (os::lseek(_fd, (long)pos, SEEK_SET) < 0) { fail_stop("Unable to seek to position " SIZE_FORMAT, pos); } } @@ -1650,7 +1650,7 @@ void FileMapInfo::write_bytes_aligned(const void* buffer, size_t nbytes) { void FileMapInfo::close() { if (_file_open) { - if (::close(_fd) < 0) { + if (os::close(_fd) < 0) { fail_stop("Unable to close the shared archive file."); } _file_open = false; @@ -1741,7 +1741,7 @@ bool FileMapInfo::read_region(int i, char* base, size_t size, bool do_commit) { return false; } } - if (lseek(_fd, (long)si->file_offset(), SEEK_SET) != (int)si->file_offset() || + if (os::lseek(_fd, (long)si->file_offset(), SEEK_SET) != (int)si->file_offset() || read_bytes(base, size) != size) { return false; } diff --git a/src/hotspot/share/classfile/compactHashtable.cpp b/src/hotspot/share/classfile/compactHashtable.cpp index dc21ee4e7f3..b6fe339d4ce 100644 --- a/src/hotspot/share/classfile/compactHashtable.cpp +++ b/src/hotspot/share/classfile/compactHashtable.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -252,7 +252,7 @@ HashtableTextDump::HashtableTextDump(const char* filename) : _fd(-1) { HashtableTextDump::~HashtableTextDump() { os::unmap_memory((char*)_base, _size); if (_fd >= 0) { - close(_fd); + os::close(_fd); } } diff --git a/src/hotspot/share/compiler/compileLog.cpp b/src/hotspot/share/compiler/compileLog.cpp index eb52c5f5fb1..d5e9a52645a 100644 --- a/src/hotspot/share/compiler/compileLog.cpp +++ b/src/hotspot/share/compiler/compileLog.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2022, 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 @@ -225,7 +225,7 @@ void CompileLog::finish_log_on_error(outputStream* file, char* buf, int buflen) if (to_read < (julong)buflen) nr = (size_t)to_read; else nr = buflen; - bytes_read = read(partial_fd, buf, (int)nr); + bytes_read = os::read(partial_fd, buf, (int)nr); if (bytes_read <= 0) break; nr = bytes_read; to_read -= (julong)nr; @@ -235,7 +235,7 @@ void CompileLog::finish_log_on_error(outputStream* file, char* buf, int buflen) // Copy any remaining data inside a quote: bool saw_slop = false; int end_cdata = 0; // state machine [0..2] watching for too many "]]" - while ((bytes_read = read(partial_fd, buf, buflen-1)) > 0) { + while ((bytes_read = os::read(partial_fd, buf, buflen-1)) > 0) { nr = bytes_read; buf[buflen-1] = '\0'; if (!saw_slop) { @@ -285,7 +285,7 @@ void CompileLog::finish_log_on_error(outputStream* file, char* buf, int buflen) file->print_raw_cr(""); } file->print_raw_cr(""); - close(partial_fd); + os::close(partial_fd); } CompileLog* next_log = log->_next; delete log; // Removes partial file diff --git a/src/hotspot/share/utilities/vmError.cpp b/src/hotspot/share/utilities/vmError.cpp index 3fa50cc8ccb..e1d6581ca06 100644 --- a/src/hotspot/share/utilities/vmError.cpp +++ b/src/hotspot/share/utilities/vmError.cpp @@ -1654,7 +1654,7 @@ void VMError::report_and_die(int id, const char* message, const char* detail_fmt _current_step_info = ""; if (fd_log > 3) { - close(fd_log); + os::close(fd_log); fd_log = -1; } diff --git a/test/hotspot/gtest/logging/logTestUtils.inline.hpp b/test/hotspot/gtest/logging/logTestUtils.inline.hpp index 4295c6a000f..3e49c610b41 100644 --- a/test/hotspot/gtest/logging/logTestUtils.inline.hpp +++ b/test/hotspot/gtest/logging/logTestUtils.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -138,8 +138,8 @@ static inline char* read_line(FILE* fp) { static bool file_contains_substrings_in_order(const char* filename, const char* substrs[]) { AsyncLogWriter::flush(); - FILE* fp = fopen(filename, "r"); - assert(fp != NULL, "error opening file %s: %s", filename, strerror(errno)); + FILE* fp = os::fopen(filename, "r"); + assert(fp != NULL, "error opening file %s: %s", filename, os::strerror(errno)); size_t idx = 0; while (substrs[idx] != NULL) { diff --git a/test/hotspot/gtest/logging/test_asynclog.cpp b/test/hotspot/gtest/logging/test_asynclog.cpp index 2525f40ec4e..16bdd6e18c7 100644 --- a/test/hotspot/gtest/logging/test_asynclog.cpp +++ b/test/hotspot/gtest/logging/test_asynclog.cpp @@ -1,5 +1,6 @@ /* * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -85,7 +86,7 @@ LOG_LEVEL_LIST // stdout/stderr support bool write_to_file(const std::string& output) { - FILE* f = fopen(TestLogFileName, "w"); + FILE* f = os::fopen(TestLogFileName, "w"); if (f != NULL) { size_t sz = output.size(); diff --git a/test/hotspot/gtest/logging/test_log.cpp b/test/hotspot/gtest/logging/test_log.cpp index ccd928474d4..7ae276aad37 100644 --- a/test/hotspot/gtest/logging/test_log.cpp +++ b/test/hotspot/gtest/logging/test_log.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, 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 @@ -60,7 +60,7 @@ TEST_VM_F(LogTest, large_message) { AsyncLogWriter::flush(); ResourceMark rm; - FILE* fp = fopen(TestLogFileName, "r"); + FILE* fp = os::fopen(TestLogFileName, "r"); ASSERT_NE((void*)NULL, fp); char* output = read_line(fp); fclose(fp); diff --git a/test/hotspot/gtest/logging/test_logTagSetDescriptions.cpp b/test/hotspot/gtest/logging/test_logTagSetDescriptions.cpp index 7cb37ff4349..84253e19433 100644 --- a/test/hotspot/gtest/logging/test_logTagSetDescriptions.cpp +++ b/test/hotspot/gtest/logging/test_logTagSetDescriptions.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,7 +50,7 @@ TEST_VM(LogTagSetDescriptions, describe) { TEST_VM(LogTagSetDescriptions, command_line_help) { ResourceMark rm; const char* filename = prepend_temp_dir("logtagset_descriptions"); - FILE* fp = fopen(filename, "w+"); + FILE* fp = os::fopen(filename, "w+"); ASSERT_NE((void*)NULL, fp); fileStream stream(fp); LogConfiguration::print_command_line_help(&stream); -- GitLab From b20b11cf8215238e5cd51a1d3a331d5cbfdad710 Mon Sep 17 00:00:00 2001 From: Daniel Jelinski Date: Wed, 19 Jan 2022 14:18:14 +0000 Subject: [PATCH 207/564] 8258240: make vscode-project on Windows generates jdk.code-workspace file with unescaped '\' in paths Reviewed-by: erikj --- .../vscode/hotspot/CreateVSCodeProject.gmk | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/make/ide/vscode/hotspot/CreateVSCodeProject.gmk b/make/ide/vscode/hotspot/CreateVSCodeProject.gmk index 8b82c38a751..bc56e878de6 100644 --- a/make/ide/vscode/hotspot/CreateVSCodeProject.gmk +++ b/make/ide/vscode/hotspot/CreateVSCodeProject.gmk @@ -29,6 +29,13 @@ default: all include $(SPEC) include MakeBase.gmk +################################################################################ +# SedEscape +# +# Escape special characters for use in SED replacement string +################################################################################ +SedEscape = $(subst !,\!,$(subst \,\\,$1)) + ################################################################################ # Return the full path to an indexer-specific file fragment. # @@ -78,15 +85,15 @@ define CreateFromTemplate $(SED) -e '/{{INDEXER_EXTENSIONS}}/r $(call GetIndexerFragment,extensions)' \ -e '/{{INDEXER_SETTINGS}}/r $(call GetIndexerFragment,settings)' \ -e '/{{EXTRA_WORKSPACE_ROOT}}/r $(call GetExtraWorkspaceRoot)' $1 | \ - $(SED) -e 's!{{TOPDIR}}!$(call FixPath,$(TOPDIR))!g' \ - -e 's!{{TOPDIR_RELATIVE}}!$(call FixPath,$(strip \ - $(call RelativePath,$(OUTPUTDIR),$(TOPDIR))))!g' \ - -e 's!{{WORKSPACE_ROOT}}!$(call FixPath,$(WORKSPACE_ROOT))!g' \ - -e 's!{{OUTPUTDIR}}!$(call FixPath,$(OUTPUTDIR))!g' \ + $(SED) -e 's!{{TOPDIR}}!$(call SedEscape,$(call FixPath,$(TOPDIR)))!g' \ + -e 's!{{TOPDIR_RELATIVE}}!$(call SedEscape,$(call FixPath,$(strip \ + $(call RelativePath,$(OUTPUTDIR),$(TOPDIR)))))!g' \ + -e 's!{{WORKSPACE_ROOT}}!$(call SedEscape,$(call FixPath,$(WORKSPACE_ROOT)))!g' \ + -e 's!{{OUTPUTDIR}}!$(call SedEscape,$(call FixPath,$(OUTPUTDIR)))!g' \ -e 's!{{CONF_NAME}}!$(CONF_NAME)!g' \ - -e 's!{{COMPILER}}!$(call FixPath,$(CXX)) $(SYSROOT_CFLAGS)!g' \ - -e 's!{{MAKE}}!$(call FixPath,$(MAKE))!g' \ - -e 's!{{PATH}}!$(call FixPath,$(PATH))!g' \ + -e 's!{{COMPILER}}!$(call SedEscape,$(call FixPath,$(CXX))) $(SYSROOT_CFLAGS)!g' \ + -e 's!{{MAKE}}!$(call SedEscape,$(call FixPath,$(MAKE)))!g' \ + -e 's!{{PATH}}!$(call SedEscape,$(call FixPath,$(PATH)))!g' \ -e 's!{{DEBUGENGINENAME}}!$(call DebugEngineName)!g' \ -e '/{{INDEXER_EXTENSIONS}}/d' \ -e '/{{INDEXER_SETTINGS}}/d' \ -- GitLab From e20c6bf972a106105733c395877d11d9c894eb28 Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Wed, 19 Jan 2022 15:35:57 +0000 Subject: [PATCH 208/564] 8280189: JFR: TestPrintXML should print mismatching XML Reviewed-by: mgronlun --- test/jdk/jdk/jfr/tool/TestPrintXML.java | 27 +++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/test/jdk/jdk/jfr/tool/TestPrintXML.java b/test/jdk/jdk/jfr/tool/TestPrintXML.java index 4480c23c788..dd53955e401 100644 --- a/test/jdk/jdk/jfr/tool/TestPrintXML.java +++ b/test/jdk/jdk/jfr/tool/TestPrintXML.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, 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,6 +47,7 @@ import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; import org.xml.sax.XMLReader; +import org.xml.sax.Locator; import org.xml.sax.helpers.DefaultHandler; import jdk.jfr.Timespan; @@ -105,7 +106,14 @@ public class TestPrintXML { System.out.println(); System.out.println("Was (XML)"); System.out.println("----------------------"); - System.out.println(xmlEvent); + if (xmlEvent.begin > 0 && xmlEvent.end > 0) { + String lines[] = xml.split("\\r?\\n"); + for (int i = xmlEvent.begin - 1; i < xmlEvent.end; i++) { + System.out.println(i + " " + lines[i]); + } + } else { + System.out.println("Could not locate XML position"); + } System.out.println(); throw new Exception("Event doesn't match"); } @@ -164,6 +172,8 @@ public class TestPrintXML { static class XMLEvent { String name; private Map values = new HashMap<>(); + private int begin = -1; + private int end = -1; XMLEvent(String name) { this.name = name; @@ -172,10 +182,15 @@ public class TestPrintXML { public static final class RecordingHandler extends DefaultHandler { + private Locator locator; private Stack objects = new Stack<>(); private Stack> elements = new Stack<>(); private List events = new ArrayList<>(); + public void setDocumentLocator(Locator locator) { + this.locator = locator; + } + @Override public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException { elements.push(new SimpleEntry<>(attrs.getValue("name"), attrs.getValue("index"))); @@ -187,7 +202,9 @@ public class TestPrintXML { switch (qName) { case "event": - objects.push(new XMLEvent(attrs.getValue("type"))); + XMLEvent event = new XMLEvent(attrs.getValue("type")); + event.begin = locator.getLineNumber(); + objects.push(event); break; case "struct": objects.push(new HashMap()); @@ -223,7 +240,9 @@ public class TestPrintXML { String name = element.getKey(); Object value = objects.pop(); if (objects.isEmpty()) { - events.add((XMLEvent) value); + XMLEvent event = (XMLEvent) value; + event.end = locator.getLineNumber(); + events.add(event); return; } if (value instanceof StringBuilder) { -- GitLab From f5de6fa7995fa1e82c8d969692392465b963ac35 Mon Sep 17 00:00:00 2001 From: "Daniel D. Daugherty" Date: Wed, 19 Jan 2022 17:37:36 +0000 Subject: [PATCH 209/564] 8272058: 25 Null pointer dereference defect groups in 4 files Reviewed-by: gziemski, coleenp, dlong --- .../cpu/aarch64/macroAssembler_aarch64.cpp | 15 +++++++++------ .../cpu/aarch64/macroAssembler_aarch64.hpp | 7 ++++++- src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp | 6 +++--- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp index 5641c1b1417..135f2ac6f03 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2021, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -160,8 +160,7 @@ int MacroAssembler::pd_patch_instruction_size(address branch, address target) { Instruction_aarch64::patch(branch+8, 20, 5, (dest >>= 16) & 0xffff); assert(target_addr_for_insn(branch) == target, "should be"); instructions = 3; - } else if (Instruction_aarch64::extract(insn, 31, 22) == 0b1011100101 && - Instruction_aarch64::extract(insn, 4, 0) == 0b11111) { + } else if (NativeInstruction::is_ldrw_to_zr(address(&insn))) { // nothing to do assert(target == 0, "did not expect to relocate target for polling page load"); } else { @@ -284,15 +283,19 @@ address MacroAssembler::target_addr_for_insn(address insn_addr, unsigned insn) { return address(uint64_t(Instruction_aarch64::extract(insns[0], 20, 5)) + (uint64_t(Instruction_aarch64::extract(insns[1], 20, 5)) << 16) + (uint64_t(Instruction_aarch64::extract(insns[2], 20, 5)) << 32)); - } else if (Instruction_aarch64::extract(insn, 31, 22) == 0b1011100101 && - Instruction_aarch64::extract(insn, 4, 0) == 0b11111) { - return 0; } else { ShouldNotReachHere(); } return address(((uint64_t)insn_addr + (offset << 2))); } +address MacroAssembler::target_addr_for_insn_or_null(address insn_addr, unsigned insn) { + if (NativeInstruction::is_ldrw_to_zr(address(&insn))) { + return 0; + } + return MacroAssembler::target_addr_for_insn(insn_addr, insn); +} + void MacroAssembler::safepoint_poll(Label& slow_path, bool at_return, bool acquire, bool in_nmethod) { if (acquire) { lea(rscratch1, Address(rthread, JavaThread::polling_word_offset())); diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp index a9ebc8bdc69..551d548364b 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2021, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -606,10 +606,15 @@ public: static bool uses_implicit_null_check(void* address); static address target_addr_for_insn(address insn_addr, unsigned insn); + static address target_addr_for_insn_or_null(address insn_addr, unsigned insn); static address target_addr_for_insn(address insn_addr) { unsigned insn = *(unsigned*)insn_addr; return target_addr_for_insn(insn_addr, insn); } + static address target_addr_for_insn_or_null(address insn_addr) { + unsigned insn = *(unsigned*)insn_addr; + return target_addr_for_insn_or_null(insn_addr, insn); + } // Required platform-specific helpers for Label::patch_instructions. // They _shadow_ the declarations in AbstractAssembler, which are undefined. diff --git a/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp b/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp index d808e4b5b53..7599c21c2fc 100644 --- a/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -315,7 +315,7 @@ void NativeMovRegMem::set_offset(int x) { void NativeMovRegMem::verify() { #ifdef ASSERT - address dest = MacroAssembler::target_addr_for_insn(instruction_address()); + address dest = MacroAssembler::target_addr_for_insn_or_null(instruction_address()); #endif } @@ -329,7 +329,7 @@ void NativeJump::check_verified_entry_alignment(address entry, address verified_ address NativeJump::jump_destination() const { - address dest = MacroAssembler::target_addr_for_insn(instruction_address()); + address dest = MacroAssembler::target_addr_for_insn_or_null(instruction_address()); // We use jump to self as the unresolved address which the inline // cache code (and relocs) know about -- GitLab From 610a12904d834507754e6d6171a4b8df7e6aa6b0 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Wed, 19 Jan 2022 17:56:25 +0000 Subject: [PATCH 210/564] 8268831: Improve javadoc tool handling of streams. Reviewed-by: hannesw --- .../javadoc/internal/tool/ElementsTable.java | 4 +-- .../jdk/javadoc/internal/tool/JavadocLog.java | 31 +++++++++---------- .../javadoc/internal/tool/JavadocTool.java | 6 ++-- .../jdk/javadoc/internal/tool/Start.java | 29 +++++++++++------ .../internal/tool/ToolEnvironment.java | 28 +++-------------- 5 files changed, 44 insertions(+), 54 deletions(-) diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ElementsTable.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ElementsTable.java index 20362f6a09d..e92176cbd85 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ElementsTable.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ElementsTable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2022, 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 @@ -793,7 +793,7 @@ public class ElementsTable { Collection collection, boolean recurse) throws ToolException { for (ModulePackage modpkg : collection) { - toolEnv.notice("main.Loading_source_files_for_package", modpkg.toString()); + toolEnv.printInfo("main.Loading_source_files_for_package", modpkg.toString()); List files = getFiles(modpkg, recurse); if (files.isEmpty()) { String text = log.getText("main.no_source_files_for_package", diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocLog.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocLog.java index 8409169968b..04f24fcde9c 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocLog.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocLog.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -292,12 +292,6 @@ public class JavadocLog extends Log implements Reporter { report(dt, flags, ds, dp, message); } - private int getSourcePos(DocTreePath path, int offset) { - DCTree.DCDocComment docComment = (DCTree.DCDocComment) path.getDocComment(); - DCTree tree = (DCTree) path.getLeaf(); - return docComment.getSourcePosition(tree.getStartPosition() + offset); - } - @Override // Reporter public void print(Kind kind, Element element, String message) { DiagnosticType dt = getDiagnosticType(kind); @@ -450,22 +444,27 @@ public class JavadocLog extends Log implements Reporter { } /** - * Prints a "notice" message to the standard writer. + * Prints a "notice" message. * - * @param key the resource key for the message - * @param args the arguments for the message + * @param message the message */ - public void noticeUsingKey(String key, Object... args) { - printRawLines(getStandardWriter(), getText(key, args)); + public void printNote(String message) { + // Ideally, for consistency with errors and warnings, we would use the following: + // report(Kind.NOTE, null, null, message); + // but the default formatting in Log for Kind.NOTE is to prefix the line with "Note:" + // which is undesirable and inconsistent with existing javadoc output. + // For now, to avoid the prefix, we write directly to the underlying stream. + printRawLines(WriterKind.NOTICE, message); } /** - * Prints a "notice" message to the standard writer. + * Prints a "notice" message. * - * @param message the message + * @param key the resource key for the message + * @param args the arguments for the message */ - public void notice(String message) { - printRawLines(getStandardWriter(), message); + public void printNoteUsingKey(String key, Object... args) { + printNote(getText(key, args)); } /** diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocTool.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocTool.java index 16f9ce2ca68..94d3d214131 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocTool.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocTool.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2022, 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 @@ -207,7 +207,7 @@ public class JavadocTool extends com.sun.tools.javac.main.JavaCompiler { } // Enter symbols for all files - toolEnv.notice("main.Building_tree"); + toolEnv.printInfo("main.Building_tree"); javadocEnter.main(allTrees.toList()); if (log.hasErrors()) { @@ -284,7 +284,7 @@ public class JavadocTool extends com.sun.tools.javac.main.JavaCompiler { for (JavaFileObject fo: files) { if (uniquefiles.add(fo)) { // ignore duplicates if (trace) - toolEnv.notice("main.Loading_source_file", fo.getName()); + toolEnv.printInfo("main.Loading_source_file", fo.getName()); trees.append(parse(fo)); } } 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 231130b071f..4d25ac5f22a 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, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -196,7 +196,7 @@ public class Start { } private void showUsage(String headerKey, ToolOption.Kind kind, String footerKey) { - log.noticeUsingKey(headerKey); + showLinesUsingKey(headerKey); showToolOptions(kind); // let doclet print usage information @@ -205,12 +205,13 @@ public class Start { ? Option.Kind.EXTENDED : Option.Kind.STANDARD); } - if (footerKey != null) - log.noticeUsingKey(footerKey); + if (footerKey != null) { + showLinesUsingKey(footerKey); + } } private void showVersion(String labelKey, String value) { - log.noticeUsingKey(labelKey, log.programName, value); + showLinesUsingKey(labelKey, log.programName, value); } private void showToolOptions(ToolOption.Kind kind) { @@ -253,7 +254,7 @@ public class Start { if (options.isEmpty()) { return; } - log.noticeUsingKey("main.doclet.usage.header", name); + showLinesUsingKey("main.doclet.usage.header", name); Comparator comp = new Comparator() { final Collator collator = Collator.getInstance(Locale.US); @@ -308,22 +309,30 @@ public class Start { if (synopses.length() < DEFAULT_SYNOPSIS_WIDTH && !description.contains("\n") && (SMALL_INDENT.length() + DEFAULT_SYNOPSIS_WIDTH + 1 + description.length() <= DEFAULT_MAX_LINE_LENGTH)) { - log.notice(String.format(COMPACT_FORMAT, synopses, description)); + showLines(String.format(COMPACT_FORMAT, synopses, description)); return; } // If option synopses fit on a single line of reasonable length, show that; // otherwise, show 1 per line if (synopses.length() <= DEFAULT_MAX_LINE_LENGTH) { - log.notice(SMALL_INDENT + synopses); + showLines(SMALL_INDENT + synopses); } else { for (String name: names) { - log.notice(SMALL_INDENT + name + parameters); + showLines(SMALL_INDENT + name + parameters); } } // Finally, show the description - log.notice(LARGE_INDENT + description.replace("\n", "\n" + LARGE_INDENT)); + showLines(LARGE_INDENT + description.replace("\n", "\n" + LARGE_INDENT)); + } + + private void showLinesUsingKey(String key, Object... args) { + showLines(log.getText(key, args)); + } + + private void showLines(String message) { + log.printRawLines(Log.WriterKind.STDOUT, message); } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ToolEnvironment.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ToolEnvironment.java index ef6f1b74940..b42245da5a9 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ToolEnvironment.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ToolEnvironment.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2022, 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 @@ -191,28 +191,14 @@ public class ToolEnvironment { } /** - * Print a notice, iff quiet is not specified. + * Prints a notice unless {@code -quiet} was specified. * * @param key selects message from resource */ - public void notice(String key) { - if (quiet) { - return; + public void printInfo(String key, Object... args) { + if (!quiet) { + log.printNoteUsingKey(key, args); } - JavadocLog.printRawLines(log.getDiagnosticWriter(), log.getText(key)); - } - - /** - * Print a notice, iff quiet is not specified. - * - * @param key selects message from resource - * @param a1 first argument - */ - public void notice(String key, String a1) { - if (quiet) { - return; - } - JavadocLog.printRawLines(log.getDiagnosticWriter(), log.getText(key, a1)); } TreePath getTreePath(JCCompilationUnit tree) { @@ -247,8 +233,4 @@ public class ToolEnvironment { public Env getEnv(ClassSymbol tsym) { return enter.getEnv(tsym); } - - public boolean isQuiet() { - return quiet; - } } -- GitLab From be0538d7c8e2cbfa599dbcb4c5c69533678a8421 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Wed, 19 Jan 2022 19:03:02 +0000 Subject: [PATCH 211/564] 8278834: Error "Cannot read field "sym" because "this.lvar[od]" is null" when compiling Reviewed-by: vromero --- .../sun/tools/javac/comp/TransPatterns.java | 3 + .../javac/patterns/BindingsInitializer.java | 164 ++++++++++++++++++ 2 files changed, 167 insertions(+) create mode 100644 test/langtools/tools/javac/patterns/BindingsInitializer.java diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransPatterns.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransPatterns.java index 56fdc73e02e..48a575658b3 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransPatterns.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransPatterns.java @@ -665,11 +665,14 @@ public class TransPatterns extends TreeTranslator { @Override public void visitClassDef(JCClassDecl tree) { ClassSymbol prevCurrentClass = currentClass; + MethodSymbol prevMethodSym = currentMethodSym; try { currentClass = tree.sym; + currentMethodSym = null; super.visitClassDef(tree); } finally { currentClass = prevCurrentClass; + currentMethodSym = prevMethodSym; } } diff --git a/test/langtools/tools/javac/patterns/BindingsInitializer.java b/test/langtools/tools/javac/patterns/BindingsInitializer.java new file mode 100644 index 00000000000..eaf550c3daf --- /dev/null +++ b/test/langtools/tools/javac/patterns/BindingsInitializer.java @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2022, 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 8278834 + * @summary Verify pattern matching nested inside initializers of classes nested in methods + * works correctly. + * @library /tools/lib /tools/javac/lib + * @modules + * jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.file + * jdk.compiler/com.sun.tools.javac.main + * jdk.compiler/com.sun.tools.javac.util + * @build toolbox.ToolBox toolbox.JavacTask + * @build combo.ComboTestHelper + * @compile BindingsInitializer.java + * @run main BindingsInitializer + */ + +import combo.ComboInstance; +import combo.ComboParameter; +import combo.ComboTask; +import combo.ComboTestHelper; +import java.nio.file.Path; +import java.nio.file.Paths; +import toolbox.ToolBox; + +public class BindingsInitializer extends ComboInstance { + protected ToolBox tb; + + BindingsInitializer() { + super(); + tb = new ToolBox(); + } + + public static void main(String... args) throws Exception { + new ComboTestHelper() + .withDimension("OUTER", (x, outer) -> x.outer = outer, Outer.values()) + .withDimension("MIDDLE", (x, middle) -> x.middle = middle, Middle.values()) + .withDimension("INNER", (x, inner) -> x.inner = inner, Inner.values()) + .withDimension("TEST", (x, test) -> x.test = test, Test.values()) + .run(BindingsInitializer::new); + } + + private Outer outer; + private Middle middle; + private Inner inner; + private Test test; + + private static final String MAIN_TEMPLATE = + """ + public class Test { + private static Object obj = ""; + #{OUTER} + } + """; + + @Override + protected void doWork() throws Throwable { + Path base = Paths.get("."); + + ComboTask task = newCompilationTask() + .withSourceFromTemplate(MAIN_TEMPLATE, pname -> switch (pname) { + case "OUTER" -> outer; + case "MIDDLE" -> middle; + case "INNER" -> inner; + case "TESST" -> test; + default -> throw new UnsupportedOperationException(pname); + }); + + task.generate(result -> { + if (result.hasErrors()) { + throw new AssertionError("Unexpected result: " + result.compilationInfo()); + } + }); + } + + public enum Outer implements ComboParameter { + NONE("#{MIDDLE}"), + STATIC_CLASS("static class Nested { #{MIDDLE} }"), + CLASS("class Inner { #{MIDDLE} }"); + private final String code; + + private Outer(String code) { + this.code = code; + } + + @Override + public String expand(String optParameter) { + return code; + } + } + + public enum Middle implements ComboParameter { + STATIC_INIT("static { #{INNER} }"), + INIT("{ #{INNER} }"), + METHOD("void test() { #{INNER} }"); + private final String code; + + private Middle(String code) { + this.code = code; + } + + @Override + public String expand(String optParameter) { + return code; + } + } + + public enum Inner implements ComboParameter { + DIRECT("#{TEST}"), + CLASS_STATIC_INIT("class C { static { #{TEST} } }"), + CLASS_INIT("class C { { #{TEST} } }"), + CLASS_METHOD("class C { void t() { #{TEST} } }"), + ANNONYMOUS_CLASS_STATIC_INIT("new Object() { static { #{TEST} } };"), + ANNONYMOUS_CLASS_INIT("new Object() { { #{TEST} } };"), + ANNONYMOUS_CLASS_METHOD("new Object() { void t() { #{TEST} } };"); + private final String code; + + private Inner(String code) { + this.code = code; + } + + @Override + public String expand(String optParameter) { + return code; + } + } + + public enum Test implements ComboParameter { + TEST("if (obj instanceof String str) System.err.println(str);"); + private final String code; + + private Test(String code) { + this.code = code; + } + + @Override + public String expand(String optParameter) { + return code; + } + } +} -- GitLab From 84fa0d8c7d0e1be19e48464801d81efa8c263793 Mon Sep 17 00:00:00 2001 From: Alisen Chung Date: Wed, 19 Jan 2022 19:12:35 +0000 Subject: [PATCH 212/564] 8190264: JScrollBar ignores its border when using macOS Mac OS X Aqua look and feel Co-authored-by: Alexey Ivanov Reviewed-by: kizune, serb, aivanov --- .../com/apple/laf/AquaScrollBarUI.java | 26 ++- .../ScrollBarBorderTest.java | 194 ++++++++++++++++++ 2 files changed, 213 insertions(+), 7 deletions(-) create mode 100644 test/jdk/java/awt/Scrollbar/AquaLFScrollbarTest/ScrollBarBorderTest.java diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaScrollBarUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaScrollBarUI.java index 9d87013c48e..ea239d83a23 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaScrollBarUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaScrollBarUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -144,7 +144,8 @@ public class AquaScrollBarUI extends ScrollBarUI { public void paint(final Graphics g, final JComponent c) { syncState(c); - painter.paint(g, c, 0, 0, fScrollBar.getWidth(), fScrollBar.getHeight()); + Rectangle trackBounds = getTrackBounds(); + painter.paint(g, c, trackBounds.x, trackBounds.y, trackBounds.width, trackBounds.height); } protected State getState(final JComponent c, final ScrollBarPart pressedPart) { @@ -188,11 +189,17 @@ public class AquaScrollBarUI extends ScrollBarUI { } protected Rectangle getTrackBounds() { - return new Rectangle(0, 0, fScrollBar.getWidth(), fScrollBar.getHeight()); + Insets insets = fScrollBar.getInsets(); + return new Rectangle(insets.left, insets.top, + fScrollBar.getWidth() - (insets.left + insets.right), + fScrollBar.getHeight() - (insets.top + insets.bottom)); } protected Rectangle getDragBounds() { - return new Rectangle(0, 0, fScrollBar.getWidth(), fScrollBar.getHeight()); + Insets insets = fScrollBar.getInsets(); + return new Rectangle(insets.left, insets.top, + fScrollBar.getWidth() - (insets.left + insets.right), + fScrollBar.getHeight() - (insets.top + insets.bottom)); } protected void startTimer(final boolean initial) { @@ -228,7 +235,10 @@ public class AquaScrollBarUI extends ScrollBarUI { protected Hit getPartHit(final int x, final int y) { syncState(fScrollBar); - return JRSUIUtils.HitDetection.getHitForPoint(painter.getControl(), 0, 0, fScrollBar.getWidth(), fScrollBar.getHeight(), x, y); + Insets insets = fScrollBar.getInsets(); + return JRSUIUtils.HitDetection.getHitForPoint(painter.getControl(), insets.left, insets.top, + fScrollBar.getWidth() - (insets.left + insets.right), + fScrollBar.getHeight() - (insets.top + insets.bottom), x, y); } protected class PropertyChangeHandler implements PropertyChangeListener { @@ -344,7 +354,9 @@ public class AquaScrollBarUI extends ScrollBarUI { // scroller goes 0-100 with a visible area of 20 we are getting a ratio of the // remaining 80. syncState(fScrollBar); - final double offsetChange = JRSUIUtils.ScrollBar.getNativeOffsetChange(painter.getControl(), 0, 0, fScrollBar.getWidth(), fScrollBar.getHeight(), offsetWeCareAbout, visibleAmt, extent); + final Rectangle limitRect = getDragBounds(); // GetThemeTrackDragRect + final double offsetChange = JRSUIUtils.ScrollBar.getNativeOffsetChange(painter.getControl(), + limitRect.x, limitRect.y, limitRect.width, limitRect.height, offsetWeCareAbout, visibleAmt, extent); // the scrollable area is the extent - visible amount; final int scrollableArea = extent - visibleAmt; @@ -597,7 +609,7 @@ public class AquaScrollBarUI extends ScrollBarUI { // determine the bounding rectangle for our thumb region syncState(fScrollBar); double[] rect = new double[4]; - JRSUIUtils.ScrollBar.getPartBounds(rect, painter.getControl(), 0, 0, fScrollBar.getWidth(), fScrollBar.getHeight(), ScrollBarPart.THUMB); + JRSUIUtils.ScrollBar.getPartBounds(rect, painter.getControl(), limitRect.x, limitRect.y, limitRect.width, limitRect.height, ScrollBarPart.THUMB); final Rectangle r = new Rectangle((int)rect[0], (int)rect[1], (int)rect[2], (int)rect[3]); // figure out the scroll-to-here start location based on our orientation, the diff --git a/test/jdk/java/awt/Scrollbar/AquaLFScrollbarTest/ScrollBarBorderTest.java b/test/jdk/java/awt/Scrollbar/AquaLFScrollbarTest/ScrollBarBorderTest.java new file mode 100644 index 00000000000..9fbea551b83 --- /dev/null +++ b/test/jdk/java/awt/Scrollbar/AquaLFScrollbarTest/ScrollBarBorderTest.java @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Insets; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import javax.imageio.ImageIO; +import javax.swing.JScrollBar; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; +import javax.swing.border.Border; + +import static java.awt.image.BufferedImage.TYPE_INT_ARGB; + +/* + * @test + * @bug 8190264 + * @summary JScrollBar ignores its border when using macOS Mac OS X Aqua look and feel + * @run main ScrollBarBorderTest + */ +public class ScrollBarBorderTest { + private static JScrollBar scrollBar; + public static final int BORDER_WIDTH = 150; + public static final int WIDTH = BORDER_WIDTH + 200; + public static final int HEIGHT = 20; + + public static void main(String[] args) throws Exception { + for (UIManager.LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels()) { + SwingUtilities.invokeAndWait(() -> setLookAndFeel(laf)); + SwingUtilities.invokeAndWait(ScrollBarBorderTest::testHorizontal); + SwingUtilities.invokeAndWait(ScrollBarBorderTest::testVertical); + } + } + + public static void testHorizontal() { + // create scroll bar + scrollBar = new JScrollBar(JScrollBar.HORIZONTAL); + scrollBar.setSize(WIDTH, HEIGHT); + scrollBar.setBorder(new HorizontalCustomBorder()); + + // paint image with thumb set to default value + BufferedImage image1 = new BufferedImage(WIDTH, HEIGHT, TYPE_INT_ARGB); + Graphics2D graphics2D = image1.createGraphics(); + scrollBar.paint(graphics2D); + graphics2D.dispose(); + + // paint image with thumb set to max value + scrollBar.setValue(Integer.MAX_VALUE); + BufferedImage image2 = new BufferedImage(WIDTH, HEIGHT, TYPE_INT_ARGB); + Graphics2D graphics2D2 = image2.createGraphics(); + scrollBar.paint(graphics2D2); + graphics2D2.dispose(); + + // check border for thumb + for (int x = WIDTH - BORDER_WIDTH; x < WIDTH; x++) { + for (int y = 0; y < HEIGHT; y++) { + int c1 = image1.getRGB(x, y); + int c2 = image2.getRGB(x, y); + if (c1 != c2) { + System.out.println(x + " " + y + " " + "Color1: " + + Integer.toHexString(c1)); + System.out.println(x + " " + y + " " + "Color2: " + + Integer.toHexString(c2)); + saveImage(image1, "himage1.png"); + saveImage(image2, "himage2.png"); + throw new RuntimeException("Horizontal border has a thumb in it"); + } + } + } + } + + public static void testVertical() { + // create scroll bar + scrollBar = new JScrollBar(JScrollBar.VERTICAL); + scrollBar.setSize(HEIGHT, WIDTH); + scrollBar.setBorder(new VerticalCustomBorder()); + + // paint image with thumb set to 0 + scrollBar.setValue(0); + BufferedImage image1 = new BufferedImage(HEIGHT, WIDTH, TYPE_INT_ARGB); + Graphics2D graphics2D = image1.createGraphics(); + scrollBar.paint(graphics2D); + graphics2D.dispose(); + + // paint image with thumb set to max value + scrollBar.setValue(Integer.MAX_VALUE); + BufferedImage image2 = new BufferedImage(HEIGHT, WIDTH, TYPE_INT_ARGB); + Graphics2D graphics2D2 = image2.createGraphics(); + scrollBar.paint(graphics2D2); + graphics2D2.dispose(); + + // check border for thumb + for (int y = WIDTH - BORDER_WIDTH; y < WIDTH; y++) { + for (int x = 0; x < HEIGHT; x++) { + int c1 = image1.getRGB(x, y); + int c2 = image2.getRGB(x, y); + if (c1 != c2) { + System.out.println(x + " " + y + " " + "Color1: " + + Integer.toHexString(c1)); + System.out.println(x + " " + y + " " + "Color2: " + + Integer.toHexString(c2)); + saveImage(image1, "vimage1.png"); + saveImage(image2, "vimage2.png"); + throw new RuntimeException("Vertical border has a thumb in it"); + } + } + } + } + + private static void setLookAndFeel(UIManager.LookAndFeelInfo laf) { + try { + UIManager.setLookAndFeel(laf.getClassName()); + System.out.println(laf.getName()); + } catch (UnsupportedLookAndFeelException ignored){ + System.out.println("Unsupported LookAndFeel: " + laf.getClassName()); + } catch (ClassNotFoundException | InstantiationException | + IllegalAccessException e) { + throw new RuntimeException(e); + } + } + + private static void saveImage(BufferedImage image, String filename) { + try { + ImageIO.write(image, "png", new File(filename)); + } catch (IOException e) { + // Don't propagate the exception + e.printStackTrace(); + } + } + + // custom border + private static class HorizontalCustomBorder implements Border { + @Override + public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { + g.setColor(new Color(255, 0, 0, 100)); + g.fillRect(width - BORDER_WIDTH, y, width, height); + } + + @Override + public Insets getBorderInsets(Component c) { + return new Insets(0, 0, 0, BORDER_WIDTH); + } + + @Override + public boolean isBorderOpaque() { + return true; + } + } + + // custom border + private static class VerticalCustomBorder implements Border { + @Override + public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { + g.setColor(new Color(255, 0, 0, 100)); + g.fillRect(x, height - BORDER_WIDTH, width, height); + } + + @Override + public Insets getBorderInsets(Component c) { + return new Insets(0, 0, BORDER_WIDTH, 0); + } + + @Override + public boolean isBorderOpaque() { + return true; + } + } +} -- GitLab From 03680bea1cca1113ea23a1eb7a413b93dd73c381 Mon Sep 17 00:00:00 2001 From: Michael McMahon Date: Wed, 19 Jan 2022 19:48:37 +0000 Subject: [PATCH 213/564] 8280233: Temporarily disable Unix domain sockets in Windows PipeImpl Reviewed-by: alanb --- .../windows/classes/sun/nio/ch/PipeImpl.java | 28 ++----------------- 1 file changed, 3 insertions(+), 25 deletions(-) diff --git a/src/java.base/windows/classes/sun/nio/ch/PipeImpl.java b/src/java.base/windows/classes/sun/nio/ch/PipeImpl.java index 8b786f04d12..b78ac0e3a20 100644 --- a/src/java.base/windows/classes/sun/nio/ch/PipeImpl.java +++ b/src/java.base/windows/classes/sun/nio/ch/PipeImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,8 +32,6 @@ import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketAddress; -import java.net.UnixDomainSocketAddress; -import java.net.StandardProtocolFamily; import java.net.StandardSocketOptions; import java.nio.*; import java.nio.channels.*; @@ -164,10 +162,6 @@ class PipeImpl try { if (ssc != null) ssc.close(); - if (sa instanceof UnixDomainSocketAddress) { - Path path = ((UnixDomainSocketAddress) sa).getPath(); - Files.deleteIfExists(path); - } } catch (IOException e2) {} } } @@ -184,8 +178,7 @@ class PipeImpl /** * Creates Pipe implementation that supports optionally buffering. * - * @implNote The pipe uses Unix domain sockets where possible. It uses a - * loopback connection on older editions of Windows. When buffering is + * @implNote Uses a loopback connection. When buffering is * disabled then it sets TCP_NODELAY on the sink channel. */ @SuppressWarnings("removal") @@ -212,23 +205,8 @@ class PipeImpl return sink; } - private static volatile boolean noUnixDomainSockets; - private static ServerSocketChannel createListener() throws IOException { - ServerSocketChannel listener = null; - if (!noUnixDomainSockets) { - try { - listener = ServerSocketChannel.open(StandardProtocolFamily.UNIX); - return listener.bind(null); - } catch (UnsupportedOperationException | IOException e) { - // IOException is most likely to be caused by the temporary directory - // name being too long. Possibly should log this. - noUnixDomainSockets = true; - if (listener != null) - listener.close(); - } - } - listener = ServerSocketChannel.open(); + ServerSocketChannel listener = ServerSocketChannel.open(); InetAddress lb = InetAddress.getLoopbackAddress(); listener.bind(new InetSocketAddress(lb, 0)); return listener; -- GitLab From dac15efc1be8fe49d2f6365f9adfb31dc3ea74ba Mon Sep 17 00:00:00 2001 From: Liam Miller-Cushon Date: Wed, 19 Jan 2022 20:17:14 +0000 Subject: [PATCH 214/564] 8280182: HotSpot Style Guide has stale link to chromium style guide Reviewed-by: dholmes --- doc/hotspot-style.html | 2 +- doc/hotspot-style.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/hotspot-style.html b/doc/hotspot-style.html index fe72cbbdf80..5e8f0e9e174 100644 --- a/doc/hotspot-style.html +++ b/doc/hotspot-style.html @@ -195,7 +195,7 @@ while ( test_foo(args...) ) { // No, excess spaces around controlSimilar discussions for some other projects:

    diff --git a/doc/hotspot-style.md b/doc/hotspot-style.md index 6d167cad9d6..57c0c38e2b0 100644 --- a/doc/hotspot-style.md +++ b/doc/hotspot-style.md @@ -409,7 +409,7 @@ Similar discussions for some other projects: * [Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html) — Currently (2020) targeting C++17. -* [C++11 and C++14 use in Chromium](https://chromium.googlesource.com/chromium/src/+/main/styleguide/c++/c++11.md) — +* [C++11 and C++14 use in Chromium](https://chromium.googlesource.com/chromium/src/+/main/styleguide/c++/c++-features.md) — Categorizes features as allowed, banned, or to be discussed. * [llvm Coding Standards](https://llvm.org/docs/CodingStandards.html) — -- GitLab From 5523ddebd572f38c3f960950d114ffead33266ae Mon Sep 17 00:00:00 2001 From: Alexandre Iline Date: Wed, 19 Jan 2022 21:02:08 +0000 Subject: [PATCH 215/564] 8279641: Create manual JTReg tests for Swing accessibility Reviewed-by: serb, prr --- .../accessibility/manual/ButtonDemo.html | 80 +++++++++ .../accessibility/manual/ButtonDemo.java | 28 +++ .../accessibility/manual/ComboBoxDemo.html | 75 +++++++++ .../accessibility/manual/ComboBoxDemo.java | 28 +++ .../accessibility/manual/DemoSelection.html | 66 ++++++++ .../accessibility/manual/DemoSelection.java | 28 +++ .../accessibility/manual/OptionPaneDemo.html | 78 +++++++++ .../accessibility/manual/OptionPaneDemo.java | 29 ++++ test/jdk/javax/accessibility/manual/README.md | 79 +++++++++ .../accessibility/manual/SwingSetTest.java | 59 +++++++ .../javax/accessibility/manual/TableDemo.html | 81 +++++++++ .../javax/accessibility/manual/TableDemo.java | 28 +++ .../javax/accessibility/manual/TabsDemo.html | 67 ++++++++ .../javax/accessibility/manual/TabsDemo.java | 29 ++++ .../javax/accessibility/manual/TreeDemo.html | 65 +++++++ .../javax/accessibility/manual/TreeDemo.java | 28 +++ .../manual/lib/DescriptionPane.java | 53 ++++++ .../manual/lib/FailureReasonPane.java | 73 ++++++++ .../manual/lib/ManualTestFrame.java | 159 ++++++++++++++++++ .../manual/lib/PassFailPane.java | 74 ++++++++ .../manual/lib/ScreenImagePane.java | 124 ++++++++++++++ .../accessibility/manual/lib/TestResult.java | 79 +++++++++ .../accessibility/manual/resource/btn.png | Bin 0 -> 560 bytes .../accessibility/manual/resource/cmb.png | Bin 0 -> 1628 bytes .../accessibility/manual/resource/dep.png | Bin 0 -> 37538 bytes .../accessibility/manual/resource/dms.png | Bin 0 -> 19806 bytes .../accessibility/manual/resource/hc.jpg | Bin 0 -> 90039 bytes .../accessibility/manual/resource/if.png | Bin 0 -> 96100 bytes .../accessibility/manual/resource/ifm.png | Bin 0 -> 4626 bytes .../accessibility/manual/resource/list.png | Bin 0 -> 73654 bytes .../accessibility/manual/resource/op.png | Bin 0 -> 759 bytes .../accessibility/manual/resource/rbtn.png | Bin 0 -> 780 bytes .../accessibility/manual/resource/tbl.png | Bin 0 -> 154905 bytes .../accessibility/manual/resource/tbld.png | Bin 0 -> 185 bytes .../accessibility/manual/resource/tree.png | Bin 0 -> 264 bytes 35 files changed, 1410 insertions(+) create mode 100644 test/jdk/javax/accessibility/manual/ButtonDemo.html create mode 100644 test/jdk/javax/accessibility/manual/ButtonDemo.java create mode 100644 test/jdk/javax/accessibility/manual/ComboBoxDemo.html create mode 100644 test/jdk/javax/accessibility/manual/ComboBoxDemo.java create mode 100644 test/jdk/javax/accessibility/manual/DemoSelection.html create mode 100644 test/jdk/javax/accessibility/manual/DemoSelection.java create mode 100644 test/jdk/javax/accessibility/manual/OptionPaneDemo.html create mode 100644 test/jdk/javax/accessibility/manual/OptionPaneDemo.java create mode 100644 test/jdk/javax/accessibility/manual/README.md create mode 100644 test/jdk/javax/accessibility/manual/SwingSetTest.java create mode 100644 test/jdk/javax/accessibility/manual/TableDemo.html create mode 100644 test/jdk/javax/accessibility/manual/TableDemo.java create mode 100644 test/jdk/javax/accessibility/manual/TabsDemo.html create mode 100644 test/jdk/javax/accessibility/manual/TabsDemo.java create mode 100644 test/jdk/javax/accessibility/manual/TreeDemo.html create mode 100644 test/jdk/javax/accessibility/manual/TreeDemo.java create mode 100644 test/jdk/javax/accessibility/manual/lib/DescriptionPane.java create mode 100644 test/jdk/javax/accessibility/manual/lib/FailureReasonPane.java create mode 100644 test/jdk/javax/accessibility/manual/lib/ManualTestFrame.java create mode 100644 test/jdk/javax/accessibility/manual/lib/PassFailPane.java create mode 100644 test/jdk/javax/accessibility/manual/lib/ScreenImagePane.java create mode 100644 test/jdk/javax/accessibility/manual/lib/TestResult.java create mode 100644 test/jdk/javax/accessibility/manual/resource/btn.png create mode 100644 test/jdk/javax/accessibility/manual/resource/cmb.png create mode 100644 test/jdk/javax/accessibility/manual/resource/dep.png create mode 100644 test/jdk/javax/accessibility/manual/resource/dms.png create mode 100644 test/jdk/javax/accessibility/manual/resource/hc.jpg create mode 100644 test/jdk/javax/accessibility/manual/resource/if.png create mode 100644 test/jdk/javax/accessibility/manual/resource/ifm.png create mode 100644 test/jdk/javax/accessibility/manual/resource/list.png create mode 100644 test/jdk/javax/accessibility/manual/resource/op.png create mode 100644 test/jdk/javax/accessibility/manual/resource/rbtn.png create mode 100644 test/jdk/javax/accessibility/manual/resource/tbl.png create mode 100644 test/jdk/javax/accessibility/manual/resource/tbld.png create mode 100644 test/jdk/javax/accessibility/manual/resource/tree.png diff --git a/test/jdk/javax/accessibility/manual/ButtonDemo.html b/test/jdk/javax/accessibility/manual/ButtonDemo.html new file mode 100644 index 00000000000..c815fad3a9e --- /dev/null +++ b/test/jdk/javax/accessibility/manual/ButtonDemo.html @@ -0,0 +1,80 @@ + + + + + + + + + +
  • Examples of subformat,argument,and formatted textExamples of subformat, argument, and formatted text
    Subformat diff --git a/src/java.base/share/classes/java/util/Locale.java b/src/java.base/share/classes/java/util/Locale.java index 90a242984f1..2da179a5dd7 100644 --- a/src/java.base/share/classes/java/util/Locale.java +++ b/src/java.base/share/classes/java/util/Locale.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2022, 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 @@ -2003,7 +2003,7 @@ public final class Locale implements Cloneable, Serializable { /** * Returns a name for the locale that is appropriate for display * to the user. This will be the values returned by - * getDisplayLanguage(), getDisplayScript(),getDisplayCountry() + * getDisplayLanguage(), getDisplayScript(), getDisplayCountry(), * getDisplayVariant(), and optional * Unicode extensions assembled into a single string. The non-empty * values are used in order, with the second and subsequent names in diff --git a/src/java.base/share/classes/java/util/zip/ZipFile.java b/src/java.base/share/classes/java/util/zip/ZipFile.java index 47edf1ffae1..c08281779ca 100644 --- a/src/java.base/share/classes/java/util/zip/ZipFile.java +++ b/src/java.base/share/classes/java/util/zip/ZipFile.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2022, 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 @@ -208,7 +208,7 @@ public class ZipFile implements ZipConstants, Closeable { * * @throws SecurityException * if a security manager exists and its {@code checkRead} - * method doesn't allow read access to the file,or its + * method doesn't allow read access to the file, or its * {@code checkDelete} method doesn't allow deleting the * file when the {@code OPEN_DELETE} flag is set * diff --git a/src/java.base/share/classes/sun/text/RuleBasedBreakIterator.java b/src/java.base/share/classes/sun/text/RuleBasedBreakIterator.java index b3abf812f29..4d46cbd1c9c 100644 --- a/src/java.base/share/classes/sun/text/RuleBasedBreakIterator.java +++ b/src/java.base/share/classes/sun/text/RuleBasedBreakIterator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2022, 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 @@ -70,7 +70,7 @@ import sun.text.SupplementaryCharacterData; * expression defines a set of characters (the "ignore characters") that * will be transparent to the BreakIterator.  A sequence of characters will break the * same way it would if any ignore characters it contains are taken out.  Break - * positions never occur befoer ignore characters.

    + * positions never occur before ignore characters.

    * *

    A regular expression uses a subset of the normal Unix regular-expression syntax, and * defines a sequence of characters to be kept together. With one significant exception, the @@ -151,7 +151,7 @@ import sun.text.SupplementaryCharacterData; *

    If ! appears at the beginning of a regular expression, it tells the regexp * parser that this expression specifies the backwards-iteration behavior of the iterator, * and not its normal iteration behavior.  This is generally only used in situations - * where the automatically-generated backwards-iteration brhavior doesn't produce + * where the automatically-generated backwards-iteration behavior doesn't produce * satisfactory results and must be supplemented with extra client-specified rules.
    getProperty(), hasNext(), require(), close(), * getNamespaceURI(), isStartElement(), * isEndElement(), isCharacters(), isWhiteSpace(), - * getNamespaceContext(), getEventType(),getLocation(), + * getNamespaceContext(), getEventType(), getLocation(), * hasText(), hasName() *
    + + + + + + + + + + + + + + + + + + + + +
    S.NoTestScenario
    1Button Demo +
      +
    1. Tab until the Button Demo icon has focus. Press 'space' to + choose.
      +
    2. Tab until the "Button Demo" tab has focus. Press 'space'. Press 'tab'.
      +
    3. Use the arrow keys to navigate between "Buttons", "Radio Buttons", and "Check Boxes".
      +
    4. Tab to enter the demo pane. Tab & Shift-Tab to move between each button.
      +
    5. Press 'space' to trigger (i.e. "press") a button.
      +
    6. Repeat steps 1 through 5 for the Radio Button & Check Boxes tabs.
      +
    +
    Expected Result
    +
      +
    1. Verify that as you navigate, the focus is shown, e.g.
    2. + +
    3. As you press 'space' to trigger each button, verify that you see each button visually depress. + e.g.: +
    4. + +
    +
    Note: actual component appearence may vary depending on look and + feel.
    + + + diff --git a/test/jdk/javax/accessibility/manual/ButtonDemo.java b/test/jdk/javax/accessibility/manual/ButtonDemo.java new file mode 100644 index 00000000000..0c352ebf906 --- /dev/null +++ b/test/jdk/javax/accessibility/manual/ButtonDemo.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2022, 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 +@key headful +@summary manual test for accessibility button demo +@run main/manual SwingSetTest ButtonDemo +*/ diff --git a/test/jdk/javax/accessibility/manual/ComboBoxDemo.html b/test/jdk/javax/accessibility/manual/ComboBoxDemo.html new file mode 100644 index 00000000000..aeb6e8f681a --- /dev/null +++ b/test/jdk/javax/accessibility/manual/ComboBoxDemo.html @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    S.NoTestScenario
    1ComboBox Demo +
      +
    1. Tab until ComboBox icon has focus. Press 'Space' to choose.
    2. +
    3. Tab until the "ComboBox Demo" tab has focus. Press 'space'. Press 'tab'.
    4. +
    5. Use Tab and Shift-Tab to move between the four ComboBox widgets. +
    6. Use the space and down arrow keys to bring up the drop-down list.
    7. +
    8. Use the up and down arrows to navigate up and down the list.
    9. +
    10. Use the 'space' key to make a the selection.
    11. +
    12. Repeat 4,5 but hit Esc key to cancel the drop-down.
    13. +
    +
    Expected Result
    +
      +
    1. Verify that space and down arrow bring up the drop-down list.
    2. + +
    3. Verify that up and down arrows move up and down the list.
    4. +
    5. Verify that 'space' makes the selection (the drop-down list should collapse).
    6. +
    +
    + + + + \ No newline at end of file diff --git a/test/jdk/javax/accessibility/manual/ComboBoxDemo.java b/test/jdk/javax/accessibility/manual/ComboBoxDemo.java new file mode 100644 index 00000000000..0522d3caa77 --- /dev/null +++ b/test/jdk/javax/accessibility/manual/ComboBoxDemo.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2022, 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 +@key headful +@summary manual test for accessibility button demo +@run main/manual SwingSetTest ComboBoxDemo +*/ diff --git a/test/jdk/javax/accessibility/manual/DemoSelection.html b/test/jdk/javax/accessibility/manual/DemoSelection.html new file mode 100644 index 00000000000..7f9a28b05a9 --- /dev/null +++ b/test/jdk/javax/accessibility/manual/DemoSelection.html @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    S.NoTestScenario
    1Demo SelectionMove between demos with 'tab' and 'shift-tab', and left and right arrows. Type 'space' to activate a demo. + +
    Expected Result
    + Verify that there is visible focus as you tab (or arrow) between demo icons. Typing 'space' should change + the selected demo. +
    Note: actual component appearence may vary depending on look and + feel.
    + + + diff --git a/test/jdk/javax/accessibility/manual/DemoSelection.java b/test/jdk/javax/accessibility/manual/DemoSelection.java new file mode 100644 index 00000000000..f3e31aa88ec --- /dev/null +++ b/test/jdk/javax/accessibility/manual/DemoSelection.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2022, 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 +@key headful +@summary manual test for accessibility button demo +@run main/manual SwingSetTest DemoSelection +*/ diff --git a/test/jdk/javax/accessibility/manual/OptionPaneDemo.html b/test/jdk/javax/accessibility/manual/OptionPaneDemo.html new file mode 100644 index 00000000000..23693043b5d --- /dev/null +++ b/test/jdk/javax/accessibility/manual/OptionPaneDemo.html @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + +
    S.NoTestScenario
    1OptionPane Demo +
      +
    1. Tab until the OptionPane icon has focus. Press 'space' to choose. +
    2. Tab until the "OptionPane Demo" tab has focus. Press 'space'. Press 'tab'. The 'Show Input Dialog' + button should have focus. +
    3. Press 'space'. An Input dialog should pop up. Type some text, and hit return. The dialog should + change to a Message dialog with text saying "That was a pretty good movie!" Press return. +
    4. Bring up the dialog again (space). Press 'esc' and confirm that the dialog goes away without the + Message from above. +
    5. Press Tab to move down through the buttons, and select "Component Dialog Example" (press space). A + dialog should appear. Tab to ensure that you can navigate through all the components:
      + a. Textfield
      + b. ComboBox
      + c. All 4 buttons: "Cancel", "Probably", "Maybe", "No", "Yes".
      + d. Press 'esc' to cancel the dialog.
      +
    +
    + Expected Result +
    + When a popup window is created, focus must be on the popup window; when the window is closed, focus must + return to the previous focus point. +
    + + + + \ No newline at end of file diff --git a/test/jdk/javax/accessibility/manual/OptionPaneDemo.java b/test/jdk/javax/accessibility/manual/OptionPaneDemo.java new file mode 100644 index 00000000000..42d3bade529 --- /dev/null +++ b/test/jdk/javax/accessibility/manual/OptionPaneDemo.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2022, 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 +@key headful +@summary manual test for accessibility button demo +@run main/manual SwingSetTest OptionPaneDemo +*/ + diff --git a/test/jdk/javax/accessibility/manual/README.md b/test/jdk/javax/accessibility/manual/README.md new file mode 100644 index 00000000000..3b96515c632 --- /dev/null +++ b/test/jdk/javax/accessibility/manual/README.md @@ -0,0 +1,79 @@ + + +# Manual javax.accessibility test suite + +## Configure environment + +### Swing Set 2 + +Prepare an appropriate version of Swing Set 2 from JDK demos. + +### Acessibility frameworks + +Testing can be performed without an accessibility framework or with one of these frameworks: + +1. Windows + 1. JAWS + 2. NVDA +2. Mac OS X + 1. Voice over + +## Executing a test run + +* Start the required accessibility framework, if necessary +* Swing Set 2 jar default location is +<tested jdk>/demo/jfc/SwingSet2/SwingSet2.jar +* To override Swing Set 2 jar use SWINGSET2_JAR environment variable: + + + jtreg ... -e:SWINGSET2_JAR= -m .../javax/accessibility/manual/... + + +## Performing tests + +When a test a started, a UI appears consisting of two frames: test framework frame and Swing Set 2 frame. Test framework +frame will contain a name of the test in the title and detailed instructions. + +1. Follow the test instructions +2. If everything goes as expected + 1. Push "Pass" + 2. UI for this test closes +3. If something goes not accordding to the instructions: + 1. Push "Fail" + 2. A screenshot is taken automatically + 3. Describe the problem + 4. Retake the screenshot, if necessary + 1. Interract with the Swing Set 2 UI to make it showing the failure. Hit "Retake screenshot" + 2. If to demonstrate the failure the UI need to be in a state which prevents using test framework UI, such as model dialogs need to be opened or menu expanded + 1. Enter delay (in seconds) + 2. Push "Retake screenshot" + 3. Prepare the UI + 4. Wait for the screenshot to be retaken + 5. Push "Fail" button again + 6. Screenshot and the description are saved for further analysis + 7. Test UI closes + +**Wasning: Do not close any window directly, all windows will be closed once the test is finished as passed or failed.** + +**Note: Keyboard navigation is supported throughout the test framework UI.** diff --git a/test/jdk/javax/accessibility/manual/SwingSetTest.java b/test/jdk/javax/accessibility/manual/SwingSetTest.java new file mode 100644 index 00000000000..33bc2ff430a --- /dev/null +++ b/test/jdk/javax/accessibility/manual/SwingSetTest.java @@ -0,0 +1,59 @@ +/** + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +import lib.ManualTestFrame; +import lib.TestResult; + +import javax.imageio.ImageIO; +import java.io.File; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.Files; +import java.util.function.Supplier; + +import static java.io.File.separator; + +public class SwingSetTest { + + public static void main(String[] args) throws IOException, InterruptedException, + ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { + System.out.println("test image " + System.getenv("TEST_IMAGE_DIR")); + Supplier resultSupplier = ManualTestFrame.showUI(args[0], + "Wait for SwingSet2 to load, follow the instructions, select pass or fail. " + + "Do not close windows manually.", + SwingSetTest.class.getResource(args[0] + ".html")); + String swingSetJar = System.getenv("SWINGSET2_JAR"); + if (swingSetJar == null) { + swingSetJar = "file://" + System.getProperty("java.home") + + separator + "demo" + + separator + "jfc" + + separator + "SwingSet2" + + separator + "SwingSet2.jar"; + } + System.out.println("Loading SwingSet2 from " + swingSetJar); + ClassLoader ss = new URLClassLoader(new URL[]{new URL(swingSetJar)}); + ss.loadClass("SwingSet2").getMethod("main", String[].class).invoke(null, (Object)new String[0]); + //this will block until user decision to pass or fail the test + TestResult result = resultSupplier.get(); + if (result != null) { + System.err.println("Failure reason: \n" + result.getFailureDescription()); + if (result.getScreenCapture() != null) { + File screenDump = new File(System.getProperty("test.classes") + separator + args[0] + ".png"); + System.err.println("Saving screen image to " + screenDump.getAbsolutePath()); + ImageIO.write(result.getScreenCapture(), "png", screenDump); + } + Throwable e = result.getException(); + if (e != null) { + throw new RuntimeException(e); + } else { + if (!result.getStatus()) throw new RuntimeException("Test failed!"); + } + } else { + throw new RuntimeException("No result returned!"); + } + } +} \ No newline at end of file diff --git a/test/jdk/javax/accessibility/manual/TableDemo.html b/test/jdk/javax/accessibility/manual/TableDemo.html new file mode 100644 index 00000000000..1f0b821b410 --- /dev/null +++ b/test/jdk/javax/accessibility/manual/TableDemo.html @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    S.NoTestScenario
    1Table Demo (tests table navigation, as well as textfield input) +
      +
    1. Tab until the Table icon has focus. Press 'space' to choose. +
    2. Tab until the "Table Demo" tab has focus. Press 'space'. Press 'tab'. "Reordering allowed" should + have focus. +
    3. Tab to the Printing/Header textfield. Verify that you can type in some text. +
    4. Continue tabbing until focus moves to the table. The table should show focus. +
    5. Press the down arrow. "Mike Albers" should have focus. +
    6. Use the right and left arrow keys to navigate between cells. +
    7. Set focus to a text cell (e.g. someone's first name). Press space to edit. Type some text. Hit + 'enter' and verify the text has been changed. After editing a text cell and hitting 'enter', the + focus could remain on the current cell or go to the next line. +
    8. Press the 'Page Up' and 'Page Down' keys (if available on your keyboard); verify that the Table + scrolls up and down, page by page. +

        + +
    + Expected Result +
    + See above test description. +
    Note: actual component appearence may vary depending on look and + feel.
    + + + + \ No newline at end of file diff --git a/test/jdk/javax/accessibility/manual/TableDemo.java b/test/jdk/javax/accessibility/manual/TableDemo.java new file mode 100644 index 00000000000..ff56bcec4e8 --- /dev/null +++ b/test/jdk/javax/accessibility/manual/TableDemo.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2022, 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 +@key headful +@summary manual test for accessibility button demo +@run main/manual SwingSetTest TableDemo +*/ diff --git a/test/jdk/javax/accessibility/manual/TabsDemo.html b/test/jdk/javax/accessibility/manual/TabsDemo.html new file mode 100644 index 00000000000..06a055d0229 --- /dev/null +++ b/test/jdk/javax/accessibility/manual/TabsDemo.html @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    S.NoTestScenario
    1Tabs within demos (tests table navigation, as well as textfield input) + Continue tabbing to enter a demo's pane. When the top demo tabs have focus, the left and right arrow keys + move between tabs.
    + +
    + Expected Result +
    + Verify that the selected tab changes, e.g. between 'Internal Frame Demo' and "Source Code'. +
    Note: actual component appearence may vary depending on look and + feel.
    + + \ No newline at end of file diff --git a/test/jdk/javax/accessibility/manual/TabsDemo.java b/test/jdk/javax/accessibility/manual/TabsDemo.java new file mode 100644 index 00000000000..35fad6abf82 --- /dev/null +++ b/test/jdk/javax/accessibility/manual/TabsDemo.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2022, 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 +@key headful +@summary manual test for accessibility button demo +@run main/manual SwingSetTest TabsDemo +*/ + diff --git a/test/jdk/javax/accessibility/manual/TreeDemo.html b/test/jdk/javax/accessibility/manual/TreeDemo.html new file mode 100644 index 00000000000..c418b3e5404 --- /dev/null +++ b/test/jdk/javax/accessibility/manual/TreeDemo.html @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + +
    S.NoTestScenario
    1Tree Demo + Tab until the Tree icon has focus. Press 'space' to choose. + Tab until the "Tree Demo" tab has focus. Press 'space'. Press 'tab'. Press the down arrow. "Music" should + have focus. + Navigate up and down the tree using the up and down arrow keys. + Expand and collapse folders using the right and left arrow keys. +
    + Expected Result +
    + See above test description. +
    + + \ No newline at end of file diff --git a/test/jdk/javax/accessibility/manual/TreeDemo.java b/test/jdk/javax/accessibility/manual/TreeDemo.java new file mode 100644 index 00000000000..1f38f9e9f73 --- /dev/null +++ b/test/jdk/javax/accessibility/manual/TreeDemo.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2022, 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 +@key headful +@summary manual test for accessibility button demo +@run main/manual SwingSetTest TreeDemo +*/ diff --git a/test/jdk/javax/accessibility/manual/lib/DescriptionPane.java b/test/jdk/javax/accessibility/manual/lib/DescriptionPane.java new file mode 100644 index 00000000000..bdd0e23e788 --- /dev/null +++ b/test/jdk/javax/accessibility/manual/lib/DescriptionPane.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2022, 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 lib; + +import javax.swing.JEditorPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.io.IOException; +import java.net.URL; + +/** + * Displays instructions provided through a URL. + */ +class DescriptionPane extends JPanel { + + DescriptionPane(URL instructions) throws IOException { + JEditorPane editorPane = new JEditorPane(); + editorPane.setFocusable(false); + editorPane.setContentType("text/html"); + editorPane.setPage(instructions); + editorPane.setEditable(false); + + JScrollPane esp = new JScrollPane(editorPane); + esp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); + esp.setPreferredSize(new Dimension(250, 350)); + + setLayout(new BorderLayout()); + + add(esp); + } +} diff --git a/test/jdk/javax/accessibility/manual/lib/FailureReasonPane.java b/test/jdk/javax/accessibility/manual/lib/FailureReasonPane.java new file mode 100644 index 00000000000..b1cfc0d32cb --- /dev/null +++ b/test/jdk/javax/accessibility/manual/lib/FailureReasonPane.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2022, 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 lib; + +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextArea; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import java.awt.BorderLayout; +import java.util.function.Consumer; + +import static java.awt.BorderLayout.CENTER; +import static java.awt.BorderLayout.NORTH; + +/** + * Allows to enter reason for the test failure. + */ +class FailureReasonPane extends JPanel { + + private final JTextArea text; + + FailureReasonPane(Consumer listener) { + setLayout(new BorderLayout(10, 10)); + add(new JLabel("Failure reason:"), NORTH); + text = new JTextArea(3, 10); + text.getDocument().addDocumentListener(new DocumentListener() { + @Override + public void insertUpdate(DocumentEvent e) { + listener.accept(text.getText()); + } + + @Override + public void removeUpdate(DocumentEvent e) { + listener.accept(text.getText()); + } + + @Override + public void changedUpdate(DocumentEvent e) { + listener.accept(text.getText()); + } + }); + add(text, CENTER); + } + + public String getReason() { + return text.getText(); + } + + public void requestFocus() { + text.requestFocus(); + } +} diff --git a/test/jdk/javax/accessibility/manual/lib/ManualTestFrame.java b/test/jdk/javax/accessibility/manual/lib/ManualTestFrame.java new file mode 100644 index 00000000000..57117790b57 --- /dev/null +++ b/test/jdk/javax/accessibility/manual/lib/ManualTestFrame.java @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2022, 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 lib; + +import javax.swing.BorderFactory; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JSplitPane; +import javax.swing.JTextArea; +import javax.swing.border.BevelBorder; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.GridLayout; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.net.URL; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Consumer; +import java.util.function.Supplier; + +import static java.awt.BorderLayout.*; +import static javax.swing.SwingUtilities.invokeAndWait; + +/** + * A frame which can be used to display manual test descriptions as well as, in case of a failure, + * enter failure reason and capture the screen. + */ +public class ManualTestFrame extends JFrame { + + private boolean alreadyFailed = false; + + private ManualTestFrame(String testName, String headerText, URL instructions, Consumer listener) throws IOException { + + super(testName); + + JLabel statusLabel = new JLabel("Follow test description, select \"Pass\" or \"Fail\""); + statusLabel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); + + JSplitPane split = new JSplitPane(JSplitPane.VERTICAL_SPLIT); + PassFailPane[] passFail = new PassFailPane[1]; + FailureReasonPane failureReason = new FailureReasonPane(reason -> { + passFail[0].setFailEnabled(!reason.isEmpty()); + }); + ScreenImagePane image = new ScreenImagePane(e -> { + listener.accept(new TestResult(e)); + dispose(); + }); + + JPanel failureInfoPane = new JPanel(); + failureInfoPane.setLayout(new GridLayout(1, 2, 10, 10)); + failureInfoPane.add(failureReason); + failureInfoPane.add(image); + failureInfoPane.setVisible(false); + + JPanel main = new JPanel(); + main.setLayout(new BorderLayout(10, 10)); + DescriptionPane description = new DescriptionPane(instructions); + main.add(description, CENTER); + passFail[0] = new PassFailPane((status) -> { + if (status) { + listener.accept(new TestResult()); + dispose(); + } else { + if (!alreadyFailed) { + alreadyFailed = true; + split.setDividerLocation(.5); + failureInfoPane.setVisible(true); + pack(); + image.capture(); + failureReason.requestFocus(); + statusLabel.setText("Enter failure reason, re-take screenshot, push \"Fail\""); + } else { + listener.accept(new TestResult(failureReason.getReason(), image.getImage())); + dispose(); + } + } + }); + main.add(passFail[0], SOUTH); + + split.setLeftComponent(main); + split.setRightComponent(failureInfoPane); + split.setDividerLocation(1.); + + getContentPane().setLayout(new BorderLayout()); + + if (headerText != null) { + JTextArea warningLabel = new JTextArea(headerText); + warningLabel.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED)); + warningLabel.setEditable(false); + warningLabel.setFocusable(false); + getContentPane().add(warningLabel, NORTH); + } + + getContentPane().add(statusLabel, SOUTH); + getContentPane().add(split, CENTER); + + setPreferredSize(new Dimension(800, 600)); + pack(); + setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); + setVisible(true); + } + + /** + * Show a test control frame which allows a user to either pass or fail the test. + * @param testName + * @param headerText + * @param instructions + * @return Returning supplier blocks till the test is passed or failed by the user. + * @throws InterruptedException + * @throws InvocationTargetException + */ + public static Supplier showUI(String testName, String headerText, URL instructions) + throws InterruptedException, InvocationTargetException { + AtomicReference resultContainer = new AtomicReference<>(); + CountDownLatch latch = new CountDownLatch(1); + invokeAndWait(() -> { + try { + new ManualTestFrame(testName, headerText, instructions, (status) -> { + resultContainer.set(status); + latch.countDown(); + }); + } catch (IOException e) { + resultContainer.set(new TestResult(e)); + e.printStackTrace(); + } + }); + return () -> { + try { + latch.await(); + } catch (InterruptedException e) { + return new TestResult(e); + } + return resultContainer.get(); + }; + } + +} diff --git a/test/jdk/javax/accessibility/manual/lib/PassFailPane.java b/test/jdk/javax/accessibility/manual/lib/PassFailPane.java new file mode 100644 index 00000000000..0cc99353ef1 --- /dev/null +++ b/test/jdk/javax/accessibility/manual/lib/PassFailPane.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2022, 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 lib; + +import javax.swing.JButton; +import javax.swing.JPanel; +import java.awt.HeadlessException; +import java.io.IOException; +import java.util.function.Consumer; + +/** + * Allows to chose if a test fails or passes. It is a multi-use component. A chosen answer can be confirmed later + * upon providing additional information. + */ +class PassFailPane extends JPanel { + private final Consumer listener; + + private final JButton btnPass = new JButton("Pass"); + private final JButton btnFail = new JButton("Fail"); + + /** + * @param listener gets called with true (pass) or false (fail). + * @throws HeadlessException + */ + PassFailPane(Consumer listener) + throws HeadlessException, IOException { + this.listener = listener; + + add(btnPass); + add(btnFail); + + btnPass.requestFocus(); + + btnPass.addActionListener((e) -> { + disableButtons(); + listener.accept(true); + }); + + btnFail.addActionListener((e) -> { + disableButtons(); + listener.accept(false); + }); + } + + private void disableButtons() { + btnFail.setEnabled(false); + btnPass.setEnabled(false); + } + + public void setFailEnabled(boolean enabled) { + btnFail.setEnabled(enabled); + } + +} diff --git a/test/jdk/javax/accessibility/manual/lib/ScreenImagePane.java b/test/jdk/javax/accessibility/manual/lib/ScreenImagePane.java new file mode 100644 index 00000000000..1d35b740dad --- /dev/null +++ b/test/jdk/javax/accessibility/manual/lib/ScreenImagePane.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2022, 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 lib; + +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JFormattedTextField; +import javax.swing.JLabel; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.Image; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.Toolkit; +import java.awt.image.BufferedImage; +import java.text.NumberFormat; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Consumer; + +import static java.awt.BorderLayout.CENTER; +import static java.awt.BorderLayout.NORTH; +import static java.lang.String.format; +import static javax.swing.SwingUtilities.invokeAndWait; +import static javax.swing.SwingUtilities.invokeLater; + +/** + * Allows ti take screenshot, possible with a delay to preapare the UI. + */ +class ScreenImagePane extends JPanel { + private final JPanel imagePanel; + private final JLabel imageLabel; + private final AtomicReference image = new AtomicReference<>(); + private final Rectangle screenRect; + private final JFormattedTextField delayField; + private final Consumer exceptionHandler; + + /** + * + * @param handler should an exception appear on other threads + */ + ScreenImagePane(Consumer handler) { + exceptionHandler = handler; + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + screenRect = new Rectangle(0, 0, screenSize.width, screenSize.height); + JPanel controls = new JPanel(); + delayField = new JFormattedTextField(NumberFormat.getNumberInstance()); + delayField.setText("0"); + delayField.setColumns(3); + JButton capture = new JButton("Retake screenshot"); + controls.add(new JLabel("in ")); + controls.add(delayField); + controls.add(new JLabel(" seconds ")); + controls.add(capture); + capture.addActionListener((e) -> capture()); + imagePanel = new JPanel(); + imageLabel = new JLabel(); + imagePanel.add(imageLabel); + + setLayout(new BorderLayout()); + add(controls, NORTH); + add(imagePanel, CENTER); + } + + public void capture() { + new Thread(() -> { + try { + int delay = Integer.parseInt(delayField.getText()); + invokeAndWait(() -> imageLabel.setIcon(null)); + while (delay > 0) { + String message = format("Retaking screenshot in %d seconds", delay); + invokeLater(() -> imageLabel.setText(message)); + delay--; + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + } + } + BufferedImage image = new Robot().createScreenCapture(screenRect); + ScreenImagePane.this.image.set(image); + int newWidth = imagePanel.getWidth(); + int newHeight = imagePanel.getHeight(); + float xratio = (float) newWidth / (float) image.getWidth(); + float yratio = (float) newHeight / (float) image.getHeight(); + if (xratio < yratio) { + newHeight = (int) (image.getHeight() * xratio); + } else { + newWidth = (int) (image.getWidth() * yratio); + } + Image scaled = image.getScaledInstance(newWidth, newHeight, Image.SCALE_FAST); + invokeAndWait(() -> { + imageLabel.setText(null); + imageLabel.setIcon(new ImageIcon(scaled)); + }); + } catch (Throwable e) { + exceptionHandler.accept(e); + } + }).start(); + } + + public BufferedImage getImage() { + return image.get(); + } +} diff --git a/test/jdk/javax/accessibility/manual/lib/TestResult.java b/test/jdk/javax/accessibility/manual/lib/TestResult.java new file mode 100644 index 00000000000..42e5c72a49e --- /dev/null +++ b/test/jdk/javax/accessibility/manual/lib/TestResult.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2022, 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 lib; + +import java.awt.image.BufferedImage; + +public final class TestResult { + private final boolean status; + private final String failureDescription; + private final BufferedImage screenCapture; + private final Throwable exception; + + /** + * Failed due to an exception. + */ + public TestResult(Throwable exception) { + status = false; + failureDescription = exception.getMessage(); + screenCapture = null; + this.exception = exception; + } + + /** + * Failed by used decision. + */ + public TestResult(String description, BufferedImage capture) { + status = false; + failureDescription = description; + screenCapture = capture; + exception = null; + } + + /** + * Passed. + */ + public TestResult() { + this.status = true; + failureDescription = null; + screenCapture = null; + exception = null; + } + + /** + * true - pass, false - no pass. + */ + public boolean getStatus() { + return status; + } + + public String getFailureDescription() { + return failureDescription; + } + + public BufferedImage getScreenCapture() { + return screenCapture; + } + + public Throwable getException() {return exception;} +} diff --git a/test/jdk/javax/accessibility/manual/resource/btn.png b/test/jdk/javax/accessibility/manual/resource/btn.png new file mode 100644 index 0000000000000000000000000000000000000000..0523db95125a121f77cbc2918a38b5937bb9a368 GIT binary patch literal 560 zcmV-00?+-4P)(k6vyX(qWoA$vhibKX-A|8D`hbok)qisE2C@-Qc_Zil#SRJ3Z)cweujVHOy^s3 zYo?}m@xIObzH`sw+r8&J=iHt?eV?a$@AGiK-%0dqJqQE=C7=Y9fD%vwN+h8EJgCQ~ zXI1I9K&izs0!l#rAW$#e*KgH-4eGlbA)o}5fch|bhr>Y{jpj=&77GEzlV7b?G@s8Q zx7!UklgUKMT`m^^^?C9hj|ZR*hl7%<)oSE&xd4>oYPE`ZG#Vjpx7!pBhjG7LE-4rc zlF4Kuo6SbqY?e-^lR7|+$7AFwl?q}8!ErvHM;wpGDV?Dqh#Ug5UyB(G&J8n9iQnT5_ zcr+SS#~$@AtJRAAX20Jf_IkajWr*)J{eB-CI_KF*p-_l6n~l7gf2Hkqi+xKzVdPs+ yK*|3o`NJuo1k_&vCFgo_QY=U60!l#r`+5Vc=i-wu{RYSY0000>S|f?5q$_l%JNFlghxL zF)=wILCaG|<3wU&Lc)o&+L~NNnor}FZ$tu_C|%+}8=3RAV(@wJh$+$*clh?!ZLeZt&1L38GCr#xr4 zX?2p-Rn_4ek3#hJJxdsl*fFMbi!jP^q}*rRcv?ia(qz^P)KJ0q%&Viuo6B~AWvhB27YGCcK@aW`O;!-?C z>;k6^DhzfQXc){emN1AgdSPTSZAsXa1`(_0;vr(G%hIQ4STH%8g&wrD-@agr%2p5e zgU0%i{_Y1)9Js)+gij=0V6i=Wqi?#1b-%#r_!9>bR-QR<;7+rE_pD|L^Z^{KowFjRPNpN_pmko@^n0U_8vu42dX-@b$4u&d=3LOvz75)vL%Y0LBvo zgH44MkeQoWlBiITo0C^;Rbi_HR$&EXgM{^!6u?SKvTc4x_fn~>KqYn>wJ1!HW`Y;9trZ1i@jv*18Z)e)(Uv`iV6b??c|PH$g^6oKRFoESgsc?elI?0a(*8g@#bdFV-F?~r&ku<{{-s;Q zvF?fcrrLeackaIb_x;g6<+j5Mmr5rjZH&0XaiPFQE_na_{<#8s zv*Y6g_r((*7ccPK^|NN)o?M?_QW}$G|Npqjap3p%{Mf>jrcLIOC8B!|yF}^iJiIO2 z^lH_u(D-J$uT(_Z9DcdE_!n*{`?Onnx1`Agr9tG&U7SVe{P^Iy+Dy)({2C125E`un9f%s&=9P@g;@R>*B(h|k0u z$FrUvJ>vYjefq*l%Qj4?_^NDh+)Fex?9%IU_q^hBE0gE)di>vFIAP*$u|IipM1R}- zjfjXz(k)Hlb)C;ICuX)mJN+ZiJyF-zvZxDOO1UDJw02F55p9Zg)$Z65=&|~RTTv*- zx!RUx`~AaKyq@2d()90r|Bgu8f80~--bP0l+XkKFA1kx literal 0 HcmV?d00001 diff --git a/test/jdk/javax/accessibility/manual/resource/dep.png b/test/jdk/javax/accessibility/manual/resource/dep.png new file mode 100644 index 0000000000000000000000000000000000000000..89d15e2b5dbde4c621ed8b6611f89f1a87ab7648 GIT binary patch literal 37538 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%0Asw6<{&W$>Ft!9Q4@G)e`p`w=N0E<3 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 U0?~7}bZ2o(_s)$XZM%^F0YyEpUH||9 literal 0 HcmV?d00001 diff --git a/test/jdk/javax/accessibility/manual/resource/dms.png b/test/jdk/javax/accessibility/manual/resource/dms.png new file mode 100644 index 0000000000000000000000000000000000000000..63809383c5e7aa7a1595b4ed2dbaaeea3567d7bd GIT binary patch literal 19806 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%0Ap zq&%8hp4>&JH>jvZUyW{$3WNB+M&f^bdy;pmUMIx@3jDTPVcQg)$-r_5Un@!I!6n;U zmSn2c`2~Ua8BmC?K>M8<&DY7qe1rj>P;mBW-Ehu41Ji!KS1Ra&^@z#%<>4Cj4Z(f! zAz}ebOI@Ppgi3}39Md682jKu)%Wj6Xz1~%omsY;|_fO#ktk~7(A`6;G1Td-63wqr} z7YW9N?NJ%MWp>r16GtAjod#O%qab$_38_PhUt<>BDNJ)U#|z~q|8{g*MKdhPy(GH6 zt|L^BZDd2_w*bZLwJXwcGgxP0!FhOKpcVzzn79|$aEWe5%MWrWxUQTkP{^5l3wR#;gPpxZZnRx_=A^dsrp~7(^)J%; zz}-H?VKJ2-YP)H8G^Hu!P-K2R|O zpz@ywy4Bj<#%RJSN{YkVupdN#!H-<81F0tuV z_YU^X34AXTLJOT8&N3{#$1Nv0ADkZcC&SW>2gO|tgC7+QJ3 zw-8?7q;5?PSuR|T#==_U-%G{kJ8|Et&%t!E82mh#KY-i2S>xx_i7zm$wY>br-dmAv zUVVdTfUf7Hy{Mp4s+9x3?{%rY_?@}AsoZ7r1c#$vB_JN9_h7(_;}#H_#p~s%dLO?d%@nQv-&CMNKx{ zG)c*qOQ^Dvl1X^H`tinvINd(E>rEOUu)?7A~Wfv(l|C4g!g$7o3aX zUKf@z?03hNU%X0mYxC))(SFCO773~hZ^{3bnHdl0UjllS+N~VkXjuniW@8*3TmOw9 z*AwPDo5e5{43l^IWqryxbe)wdv2m~hf#~*(-IiE`1iBz14ux+=js+=F3FGQOK59s+6XAP|(9j7ys%Z2H;vEsp+yV_1-+`#!H3= zM7>hV%F5uSS?k}vQ-7xz3x>DIr;bs!4{+}iA>KxqpCD`3k(j$;hmKV}ziNWAfFhZA(E-LYK98GoiL8o( zW4^7cMyC7(4v&hV-( z99E~Qq?I3sfu>)=j6OA2J_QsDmqHHdU+Iya={Sv*1cMeQ6uV&waqWbw8^Pwx7Xfqwm(gt1`y-=!O_BJ6UCu< iqp*Ku8>P$f?uw33{V!27#IyI}xNNL0Sk{?)C;SavcKq@H literal 0 HcmV?d00001 diff --git a/test/jdk/javax/accessibility/manual/resource/hc.jpg b/test/jdk/javax/accessibility/manual/resource/hc.jpg new file mode 100644 index 0000000000000000000000000000000000000000..773ca040dcb8439dcbb23ea6dc42dcd30d0154d1 GIT binary patch literal 90039 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

    rQg~euBsD0I$yeK<`S@8Uv1| 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⪙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

    1zdIZtyO|{ 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 QEdT%j07*qoM6N<$g7p4S7ytkO literal 0 HcmV?d00001 diff --git a/test/jdk/javax/accessibility/manual/resource/op.png b/test/jdk/javax/accessibility/manual/resource/op.png new file mode 100644 index 0000000000000000000000000000000000000000..82ff0253d6eb107b46e81ceab768ac3f2e13f882 GIT binary patch literal 759 zcmVU;2Q{RyD2CC6qlq-4$ejjG(S9uk+oakq zOlT^!Hb@iG<`R##N^LWUZo2rk?@LFHeg!PZYmc~|64zzvr&CeoEx8SdKpx9 zrzm>pRYS2eW#`MVscPdg>4xG!4-Wjy3q=pTYN+s37~AT$3K66vp!{Qg0mdU!fUJ+L z|MvK(-uJy?mI!3&um~XUsJHlot_7tv=v3ci9~>_nFt?vV&rpx(o>D97m5}}Rt#l=D z*!kuuohk}c_T|ZA;`~rt=ej)AP&_h4MT1)FXXdZp=q3F@Rx8+T&%4nZrv&%$I!&=w zRH&Dp+h{v;Ks;9h3SYU3bo)I`v8D#o1+_3gho-8%7zrH_PsX``7F{m<2!%Aoni@dms002ovPDHLkV1nFLZGHd% literal 0 HcmV?d00001 diff --git a/test/jdk/javax/accessibility/manual/resource/rbtn.png b/test/jdk/javax/accessibility/manual/resource/rbtn.png new file mode 100644 index 0000000000000000000000000000000000000000..807f29b58c14b69d2140ddbf5346d414cdd9fabb GIT binary patch literal 780 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%0AKuXW;|$HICsY^_}|FKnvGU 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 B?63d; literal 0 HcmV?d00001 diff --git a/test/jdk/javax/accessibility/manual/resource/tbld.png b/test/jdk/javax/accessibility/manual/resource/tbld.png new file mode 100644 index 0000000000000000000000000000000000000000..8e2a3b77d1a2387f57054bed52f0d663ad278ac0 GIT binary patch literal 185 zcmeAS@N?(olHy`uVBq!ia0vp^sz9vH!3HEd!Wub%RD-9BV@SoVy85}Sb4q9e0Lu+XzW@LL literal 0 HcmV?d00001 diff --git a/test/jdk/javax/accessibility/manual/resource/tree.png b/test/jdk/javax/accessibility/manual/resource/tree.png new file mode 100644 index 0000000000000000000000000000000000000000..9e7f1daa06466e7dd30e675ef5a9d95defb0606c GIT binary patch literal 264 zcmV+j0r&oiP)&>k|GjTjH~WRb~)IriPRIA+1A8jwI{j9dU=CxEWMOl$=J O0000 Date: Wed, 19 Jan 2022 22:23:51 +0000 Subject: [PATCH 216/564] 8266410: jdk/jfr/javaagent/TestLoadedAgent.java failed with "Mismatch in TestEvent count" Reviewed-by: mgronlun --- .../jdk/jfr/javaagent/EventEmitterAgent.java | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/test/jdk/jdk/jfr/javaagent/EventEmitterAgent.java b/test/jdk/jdk/jfr/javaagent/EventEmitterAgent.java index 5a4cd4f534f..ee829a412ed 100644 --- a/test/jdk/jdk/jfr/javaagent/EventEmitterAgent.java +++ b/test/jdk/jdk/jfr/javaagent/EventEmitterAgent.java @@ -24,6 +24,7 @@ package jdk.jfr.javaagent; import java.lang.instrument.Instrumentation; +import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -31,6 +32,7 @@ import jdk.jfr.Configuration; import jdk.jfr.Event; import jdk.jfr.Name; import jdk.jfr.Recording; +import jdk.jfr.consumer.RecordedEvent; import jdk.jfr.consumer.RecordingFile; import jdk.test.lib.Asserts; import jdk.test.lib.jfr.EventNames; @@ -38,7 +40,7 @@ import jdk.test.lib.jfr.EventNames; // Java agent that emits events public class EventEmitterAgent { - private static final long EVENTS = 150_000; + private static final long EVENTS = 15_000; private static final Path DUMP_PATH = Paths.get("dump.jfr").toAbsolutePath(); // Called when agent is loaded from command line @@ -88,10 +90,21 @@ public class EventEmitterAgent { } public static void validateRecording() throws Exception { - long testEventCount = RecordingFile.readAllEvents(DUMP_PATH) - .stream() - .filter(e -> e.getEventType().getName().equals("Test")) - .count(); + long testEventCount = 0; + try (RecordingFile rf = new RecordingFile(DUMP_PATH)) { + while (rf.hasMoreEvents()) { + RecordedEvent e = rf.readEvent(); + switch (e.getEventType().getName()) { + case "Test": + testEventCount++; + break; + case "jdk.DataLoss": + System.out.println(e); + break; + } + } + } + System.out.println("File size: " + Files.size(DUMP_PATH)); Asserts.assertEquals(testEventCount, EVENTS, "Mismatch in TestEvent count"); } } -- GitLab From d1efb0cc56127a40f2b23ccc608b27be2b39a389 Mon Sep 17 00:00:00 2001 From: Gerard Ziemski Date: Wed, 19 Jan 2022 22:34:54 +0000 Subject: [PATCH 217/564] 8267341: macos attempt_reserve_memory_at(arg1, arg2, true) failure Reviewed-by: dcubed, dholmes --- test/hotspot/gtest/runtime/test_os.cpp | 32 ++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/test/hotspot/gtest/runtime/test_os.cpp b/test/hotspot/gtest/runtime/test_os.cpp index 1c8ed269b54..a0859e7e296 100644 --- a/test/hotspot/gtest/runtime/test_os.cpp +++ b/test/hotspot/gtest/runtime/test_os.cpp @@ -351,6 +351,23 @@ TEST_VM(os, jio_snprintf) { test_snprintf(jio_snprintf, false); } +#ifdef __APPLE__ +// Not all macOS versions can use os::reserve_memory (i.e. anon_mmap) API +// to reserve executable memory, so before attempting to use it, +// we need to verify that we can do so by asking for a tiny executable +// memory chunk. +static inline bool can_reserve_executable_memory(void) { + bool executable = true; + size_t len = 128; + char* p = os::reserve_memory(len, executable); + bool exec_supported = (p != NULL); + if (exec_supported) { + os::release_memory(p, len); + } + return exec_supported; +} +#endif + // Test that os::release_memory() can deal with areas containing multiple mappings. #define PRINT_MAPPINGS(s) { tty->print_cr("%s", s); os::print_memory_mappings((char*)p, total_range_len, tty); } //#define PRINT_MAPPINGS @@ -360,6 +377,13 @@ TEST_VM(os, jio_snprintf) { // (from multiple calls to os::reserve_memory) static address reserve_multiple(int num_stripes, size_t stripe_len) { assert(is_aligned(stripe_len, os::vm_allocation_granularity()), "Sanity"); + +#ifdef __APPLE__ + // Workaround: try reserving executable memory to figure out + // if such operation is supported on this macOS version + const bool exec_supported = can_reserve_executable_memory(); +#endif + size_t total_range_len = num_stripes * stripe_len; // Reserve a large contiguous area to get the address space... address p = (address)os::reserve_memory(total_range_len); @@ -371,7 +395,11 @@ static address reserve_multiple(int num_stripes, size_t stripe_len) { address q = p + (stripe * stripe_len); // Commit, alternatingly with or without exec permission, // to prevent kernel from folding these mappings. +#ifdef __APPLE__ + const bool executable = exec_supported ? (stripe % 2 == 0) : false; +#else const bool executable = stripe % 2 == 0; +#endif q = (address)os::attempt_reserve_memory_at((char*)q, stripe_len, executable); EXPECT_NE(q, (address)NULL); EXPECT_TRUE(os::commit_memory((char*)q, stripe_len, executable)); @@ -413,11 +441,7 @@ struct NUMASwitcher { #endif #ifndef _AIX // JDK-8257041 -#if defined(__APPLE__) && !defined(AARCH64) // See JDK-8267341. - TEST_VM(os, DISABLED_release_multi_mappings) { -#else TEST_VM(os, release_multi_mappings) { -#endif // With NMT enabled, this will trigger JDK-8263464. For now disable the test if NMT=on. if (MemTracker::tracking_level() > NMT_off) { -- GitLab From 98d96a770756ffe3e7f5e4b82120e9fb484cad9a Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Wed, 19 Jan 2022 23:06:51 +0000 Subject: [PATCH 218/564] 8279796: Fix typo: Constucts -> Constructs Reviewed-by: iris --- .../classes/com/sun/security/sasl/digest/DigestMD5Base.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/java.security.sasl/share/classes/com/sun/security/sasl/digest/DigestMD5Base.java b/src/java.security.sasl/share/classes/com/sun/security/sasl/digest/DigestMD5Base.java index 5e26277136b..956a079ae99 100644 --- a/src/java.security.sasl/share/classes/com/sun/security/sasl/digest/DigestMD5Base.java +++ b/src/java.security.sasl/share/classes/com/sun/security/sasl/digest/DigestMD5Base.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2022, 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 @@ -158,7 +158,7 @@ abstract class DigestMD5Base extends AbstractSaslImpl { protected String authzid; // authzid or canonicalized authzid /** - * Constucts an instance of DigestMD5Base. Calls super constructor + * Constructs an instance of DigestMD5Base. Calls super constructor * to parse properties for mechanism. * * @param props A map of property/value pairs -- GitLab From c4a624d46332552e7baca8ee09bfdce0e53eef05 Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Thu, 20 Jan 2022 04:13:50 +0000 Subject: [PATCH 219/564] 8279894: javax/swing/JInternalFrame/8020708/bug8020708.java timeouts on Windows 11 Reviewed-by: serb, kizune --- .../javax/swing/JInternalFrame/8020708/bug8020708.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/test/jdk/javax/swing/JInternalFrame/8020708/bug8020708.java b/test/jdk/javax/swing/JInternalFrame/8020708/bug8020708.java index efd13ff7686..8f78178ada6 100644 --- a/test/jdk/javax/swing/JInternalFrame/8020708/bug8020708.java +++ b/test/jdk/javax/swing/JInternalFrame/8020708/bug8020708.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,7 +41,7 @@ import javax.swing.UIManager; * @summary NLS: mnemonics missing in SwingSet2/JInternalFrame demo * @library ../../regtesthelpers * @build Util - * @run main bug8020708 + * @run main/timeout=300 bug8020708 */ public class bug8020708 { @@ -68,6 +68,7 @@ public class bug8020708 { public static void main(String[] args) throws Exception { for (Locale locale : SUPPORTED_LOCALES) { + System.out.println("locale: " + locale); for (String laf : LOOK_AND_FEELS) { Locale.setDefault(locale); if (!installLookAndFeel(laf)) { @@ -80,7 +81,7 @@ public class bug8020708 { static void testInternalFrameMnemonic(Locale locale) throws Exception { Robot robot = new Robot(); - robot.setAutoDelay(250); + robot.setAutoDelay(100); robot.setAutoWaitForIdle(true); SwingUtilities.invokeAndWait(new Runnable() { @@ -142,6 +143,7 @@ public class bug8020708 { UIManager.LookAndFeelInfo[] infos = UIManager.getInstalledLookAndFeels(); for (UIManager.LookAndFeelInfo info : infos) { if (info.getClassName().contains(lafName)) { + System.out.println("LookAndFeel: " + info.getClassName()); UIManager.setLookAndFeel(info.getClassName()); return true; } -- GitLab From 1022cbdf987af846e79b92dfa20b763db7563320 Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Thu, 20 Jan 2022 04:16:11 +0000 Subject: [PATCH 220/564] 8280047: Broken link to Swing Connection document from javax.swing package docs Reviewed-by: kcr, aivanov --- .../share/classes/javax/swing/package-info.java | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/java.desktop/share/classes/javax/swing/package-info.java b/src/java.desktop/share/classes/javax/swing/package-info.java index 29509af1f4c..a75e62ebf4a 100644 --- a/src/java.desktop/share/classes/javax/swing/package-info.java +++ b/src/java.desktop/share/classes/javax/swing/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2022, 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 @@ -132,15 +132,12 @@ * For overviews, tutorials, examples, guides, and other documentation, * please see: *

    * * @serial exclude -- GitLab From e683d4ac8d9ee3b0078c5e87a2b3e7d36d7344fc Mon Sep 17 00:00:00 2001 From: Jaikiran Pai Date: Thu, 20 Jan 2022 04:49:52 +0000 Subject: [PATCH 221/564] 8279921: Dump the .class file in jlink debug mode for any failure during transform() of a plugin Reviewed-by: mchung --- .../internal/plugins/AbstractPlugin.java | 24 +++++++++++++++---- .../StripJavaDebugAttributesPlugin.java | 2 +- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/AbstractPlugin.java b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/AbstractPlugin.java index 758cb17e83e..cf46ac68407 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/AbstractPlugin.java +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/AbstractPlugin.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,6 +36,7 @@ import java.util.Locale; import java.util.MissingResourceException; import java.util.ResourceBundle; import jdk.internal.org.objectweb.asm.ClassReader; +import jdk.tools.jlink.plugin.ResourcePoolEntry; public abstract class AbstractPlugin implements Plugin { @@ -83,16 +84,31 @@ public abstract class AbstractPlugin implements Plugin { } } + ClassReader newClassReader(String path, ResourcePoolEntry resource) { + byte[] content = resource.contentBytes(); + try { + return new ClassReader(content); + } catch (Exception e) { + if (JlinkTask.DEBUG) { + System.err.printf("Failed to parse class file: %s from resource of type %s\n", path, + resource.getClass().getName()); + e.printStackTrace(); + dumpClassFile(path, content); + } + throw e; + } + } + protected ClassReader newClassReader(String path, byte[] buf) { try { return new ClassReader(buf); - } catch (IllegalArgumentException iae) { + } catch (Exception e) { if (JlinkTask.DEBUG) { System.err.printf("Failed to parse class file: %s\n", path); - iae.printStackTrace(); + e.printStackTrace(); dumpClassFile(path, buf); } - throw iae; + throw e; } } diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StripJavaDebugAttributesPlugin.java b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StripJavaDebugAttributesPlugin.java index 8e212f649c8..d56ffc729ad 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StripJavaDebugAttributesPlugin.java +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StripJavaDebugAttributesPlugin.java @@ -59,7 +59,7 @@ public final class StripJavaDebugAttributesPlugin extends AbstractPlugin { if (path.endsWith("module-info.class")) { // XXX. Do we have debug info? Is Asm ready for module-info? } else { - ClassReader reader = newClassReader(path, resource.contentBytes()); + ClassReader reader = newClassReader(path, resource); ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS); reader.accept(writer, ClassReader.SKIP_DEBUG); byte[] content = writer.toByteArray(); -- GitLab From 0bf95a1a7327cc4899863143e2dfdf3d87dbdf0c Mon Sep 17 00:00:00 2001 From: Zhiqiang Zang Date: Thu, 20 Jan 2022 07:38:04 +0000 Subject: [PATCH 222/564] 8279607: Existing optimization "~x+1" -> "-x" can be generalized to "~x+c" -> "(c-1)-x". Reviewed-by: thartmann, kvn --- src/hotspot/share/opto/addnode.cpp | 40 +- .../c2/irTests/TestIRAddIdealNotXPlusC.java | 366 ++++++++++++++++++ .../compiler/lib/ir_framework/IRNode.java | 2 + .../bench/vm/compiler/AddIdealNotXPlusC.java | 113 ++++++ 4 files changed, 503 insertions(+), 18 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/c2/irTests/TestIRAddIdealNotXPlusC.java create mode 100644 test/micro/org/openjdk/bench/vm/compiler/AddIdealNotXPlusC.java diff --git a/src/hotspot/share/opto/addnode.cpp b/src/hotspot/share/opto/addnode.cpp index e32c48b7041..9edb868b7bf 100644 --- a/src/hotspot/share/opto/addnode.cpp +++ b/src/hotspot/share/opto/addnode.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -367,12 +367,14 @@ Node* AddNode::IdealIL(PhaseGVN* phase, bool can_reshape, BasicType bt) { } } - // Convert (~x+1) into -x. Note there isn't a bitwise not bytecode, - // "~x" would typically represented as "x^(-1)", so (~x+1) will - // be (x^(-1))+1. - if (op1 == Op_Xor(bt) && phase->type(in2) == TypeInteger::one(bt) && + // Convert (~x+c) into (c-1)-x. Note there isn't a bitwise not + // bytecode, "~x" would typically represented as "x^(-1)", so (~x+c) + // will be (x^(-1))+c. + if (op1 == Op_Xor(bt) && + (in2->Opcode() == Op_ConI || in2->Opcode() == Op_ConL) && phase->type(in1->in(2)) == TypeInteger::minus_1(bt)) { - return SubNode::make(phase->makecon(TypeInteger::zero(bt)), in1->in(1), bt); + Node* c_minus_one = phase->makecon(add_ring(phase->type(in(2)), TypeInteger::minus_1(bt))); + return SubNode::make(c_minus_one, in1->in(1), bt); } return AddNode::Ideal(phase, can_reshape); } @@ -874,13 +876,14 @@ Node* XorINode::Ideal(PhaseGVN* phase, bool can_reshape) { Node* in1 = in(1); Node* in2 = in(2); int op1 = in1->Opcode(); - // Convert ~(x-1) into -x. Note there isn't a bitwise not bytecode, - // "~x" would typically represented as "x^(-1)", and "x-c0" would - // convert into "x+ -c0" in SubXNode::Ideal. So ~(x-1) will eventually - // be (x+(-1))^-1. + // Convert ~(x+c) into (-c-1)-x. Note there isn't a bitwise not + // bytecode, "~x" would typically represented as "x^(-1)", so ~(x+c) + // will eventually be (x+c)^-1. if (op1 == Op_AddI && phase->type(in2) == TypeInt::MINUS_1 && - phase->type(in1->in(2)) == TypeInt::MINUS_1) { - return new SubINode(phase->makecon(TypeInt::ZERO), in1->in(1)); + in1->in(2)->Opcode() == Op_ConI) { + jint c = phase->type(in1->in(2))->isa_int()->get_con(); + Node* neg_c_minus_one = phase->intcon(java_add(-c, -1)); + return new SubINode(neg_c_minus_one, in1->in(1)); } return AddNode::Ideal(phase, can_reshape); } @@ -953,13 +956,14 @@ Node* XorLNode::Ideal(PhaseGVN* phase, bool can_reshape) { Node* in1 = in(1); Node* in2 = in(2); int op1 = in1->Opcode(); - // Convert ~(x-1) into -x. Note there isn't a bitwise not bytecode, - // "~x" would typically represented as "x^(-1)", and "x-c0" would - // convert into "x+ -c0" in SubXNode::Ideal. So ~(x-1) will eventually - // be (x+(-1))^-1. + // Convert ~(x+c) into (-c-1)-x. Note there isn't a bitwise not + // bytecode, "~x" would typically represented as "x^(-1)", so ~(x+c) + // will eventually be (x+c)^-1. if (op1 == Op_AddL && phase->type(in2) == TypeLong::MINUS_1 && - phase->type(in1->in(2)) == TypeLong::MINUS_1) { - return new SubLNode(phase->makecon(TypeLong::ZERO), in1->in(1)); + in1->in(2)->Opcode() == Op_ConL) { + jlong c = phase->type(in1->in(2))->isa_long()->get_con(); + Node* neg_c_minus_one = phase->longcon(java_add(-c, (jlong)-1)); + return new SubLNode(neg_c_minus_one, in1->in(1)); } return AddNode::Ideal(phase, can_reshape); } diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestIRAddIdealNotXPlusC.java b/test/hotspot/jtreg/compiler/c2/irTests/TestIRAddIdealNotXPlusC.java new file mode 100644 index 00000000000..3d632b99856 --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/irTests/TestIRAddIdealNotXPlusC.java @@ -0,0 +1,366 @@ +/* + * Copyright (c) 2022, 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 compiler.c2.irTests; + +import jdk.test.lib.Asserts; +import compiler.lib.ir_framework.*; + +/* + * @test + * @bug 8279607 + * @summary Test that transformation from ~x + c to (c - 1) - x and + * from ~(x + c) to (-c - 1) - x works as intended. + * @library /test/lib / + * @run driver compiler.c2.irTests.TestIRAddIdealNotXPlusC + */ +public class TestIRAddIdealNotXPlusC { + + public static void main(String[] args) { + TestFramework.run(); + } + + @Test + @IR(failOn = {IRNode.ADD_I, IRNode.XOR_I}) + @IR(counts = {IRNode.SUB_I, "1"}) + public int testIntConIsNormal1(int x) { + return ~x + 1234; // transformed to 1233 - x + } + + @Run(test = "testIntConIsNormal1") + public void checkTestIntConIsNormal1(RunInfo info) { + assertC2Compiled(info); + Asserts.assertEquals(1223, testIntConIsNormal1(10)); + Asserts.assertEquals(1233, testIntConIsNormal1(0)); + } + + @Test + @IR(failOn = {IRNode.ADD_I, IRNode.XOR_I}) + @IR(counts = {IRNode.SUB_I, "1"}) + public int testIntConIsNormal2(int x) { + return ~(x + -1234); // transformed to 1233 - x + } + + @Run(test = "testIntConIsNormal2") + public void checkTestIntConIsNormal2(RunInfo info) { + assertC2Compiled(info); + Asserts.assertEquals(1223, testIntConIsNormal2(10)); + Asserts.assertEquals(1233, testIntConIsNormal2(0)); + } + + @Test + @IR(failOn = {IRNode.ADD_L, IRNode.XOR_L}) + @IR(counts = {IRNode.SUB_L, "1"}) + public long testLongConIsNormal1(long x) { + return ~x + 123_456_789_123L; // transformed to 123_456_789_122L - x + } + + @Run(test = "testLongConIsNormal1") + public void checkTestLongConIsNormal1(RunInfo info) { + assertC2Compiled(info); + Asserts.assertEquals(113_456_789_122L, testLongConIsNormal1(10_000_000_000L)); + Asserts.assertEquals(123_456_789_122L, testLongConIsNormal1(0L)); + } + + @Test + @IR(failOn = {IRNode.ADD_L, IRNode.XOR_L}) + @IR(counts = {IRNode.SUB_L, "1"}) + public long testLongConIsNormal2(long x) { + return ~(x + -123_456_789_123L); // transformed to 123_456_789_122L - x + } + + @Run(test = "testLongConIsNormal2") + public void checkTestLongConIsNormal2(RunInfo info) { + assertC2Compiled(info); + Asserts.assertEquals(113_456_789_122L, testLongConIsNormal2(10_000_000_000L)); + Asserts.assertEquals(123_456_789_122L, testLongConIsNormal2(0L)); + } + + @Test + @IR(failOn = {IRNode.ADD_I, IRNode.XOR_I}) + @IR(counts = {IRNode.SUB_I, "1"}) + public int testIntConIsZero1(int x) { + return ~x + 0; // transformed to -1 - x + } + + @Run(test = "testIntConIsZero1") + public void checkTestIntConIsZero1(RunInfo info) { + assertC2Compiled(info); + Asserts.assertEquals(-11, testIntConIsZero1(10)); + } + + @Test + @IR(failOn = {IRNode.ADD_I, IRNode.SUB_I}) + @IR(counts = {IRNode.XOR_I, "1"}) + public int testIntConIsZero2(int x) { + return ~(x + 0); // should not happen, transformed to ~x + } + + @Run(test = "testIntConIsZero2") + public void checkTestIntConIsZero2(RunInfo info) { + assertC2Compiled(info); + Asserts.assertEquals(-11, testIntConIsZero2(10)); + } + + @Test + @IR(failOn = {IRNode.ADD_L, IRNode.XOR_L}) + @IR(counts = {IRNode.SUB_L, "1"}) + public long testLongConIsZero1(long x) { + return ~x + 0L; // transformed to -1 - x + } + + @Run(test = "testLongConIsZero1") + public void checkTestLongConIsZero1(RunInfo info) { + assertC2Compiled(info); + Asserts.assertEquals(-10_000_000_001L, testLongConIsZero1(10_000_000_000L)); + } + + @Test + @IR(failOn = {IRNode.ADD_L, IRNode.SUB_L}) + @IR(counts = {IRNode.XOR_L, "1"}) + public long testLongConIsZero2(long x) { + return ~(x + 0L); // should not happen, transformed to ~x + } + + @Run(test = "testLongConIsZero2") + public void checkTestLongConIsZero2(RunInfo info) { + assertC2Compiled(info); + Asserts.assertEquals(-10_000_000_001L, testLongConIsZero2(10_000_000_000L)); + } + + @Test + @IR(failOn = {IRNode.ADD_I, IRNode.XOR_I}) + @IR(counts = {IRNode.SUB_I, "1"}) + public int testIntConIsOne1(int x) { + return ~x + 1; // transformed to 0 - x + } + + @Run(test = "testIntConIsOne1") + public void checkTestIntConIsOne1(RunInfo info) { + assertC2Compiled(info); + Asserts.assertEquals(-10, testIntConIsOne1(10)); + } + + @Test + @IR(failOn = {IRNode.ADD_I, IRNode.XOR_I}) + @IR(counts = {IRNode.SUB_I, "1"}) + public int testIntConIsNegOne2(int x) { + return ~(x + -1); // transformed to 0 - x + } + + @Run(test = "testIntConIsNegOne2") + public void checkTestIntConIsNegOne2(RunInfo info) { + assertC2Compiled(info); + Asserts.assertEquals(-10, testIntConIsNegOne2(10)); + } + + @Test + @IR(failOn = {IRNode.ADD_L, IRNode.XOR_L}) + @IR(counts = {IRNode.SUB_L, "1"}) + public long testLongConIsOne1(long x) { + return ~x + 1L; // transformed to 0 - x + } + + @Run(test = "testLongConIsOne1") + public void checkTestLongConIsOne1(RunInfo info) { + assertC2Compiled(info); + Asserts.assertEquals(-10_000_000_000L, testLongConIsOne1(10_000_000_000L)); + } + + @Test + @IR(failOn = {IRNode.ADD_L, IRNode.XOR_L}) + @IR(counts = {IRNode.SUB_L, "1"}) + public long testLongConIsNegOne2(long x) { + return ~(x + -1L); // transformed to 0 - x + } + + @Run(test = "testLongConIsNegOne2") + public void checkTestLongConIsNegOne2(RunInfo info) { + assertC2Compiled(info); + Asserts.assertEquals(-10_000_000_000L, testLongConIsNegOne2(10_000_000_000L)); + } + + @Test + @IR(failOn = {IRNode.ADD_I, IRNode.XOR_I}) + @IR(counts = {IRNode.SUB_I, "1"}) + public int testIntConMinusOneIsUnderflow1(int x) { + return ~x + Integer.MIN_VALUE; // transformed to Integer.MAX_VALUE - x + } + + @Run(test = "testIntConMinusOneIsUnderflow1") + public void checkTestIntConMinusOneIsUnderflow1(RunInfo info) { + assertC2Compiled(info); + Asserts.assertEquals(2147483637, testIntConMinusOneIsUnderflow1(10)); + } + + @Test + @IR(failOn = {IRNode.ADD_I, IRNode.XOR_I}) + @IR(counts = {IRNode.SUB_I, "1"}) + public int testIntNegConMinusOneIsUnderflow2(int x) { + return ~(x + Integer.MIN_VALUE); // transformed to Integer.MAX_VALUE - x + } + + @Run(test = "testIntNegConMinusOneIsUnderflow2") + public void checkTestIntNegConMinusOneIsUnderflow2(RunInfo info) { + assertC2Compiled(info); + Asserts.assertEquals(2147483637, testIntNegConMinusOneIsUnderflow2(10)); + } + + @Test + @IR(failOn = {IRNode.ADD_L, IRNode.XOR_L}) + @IR(counts = {IRNode.SUB_L, "1"}) + public long testLongConMinusOneIsUnderflow1(long x) { + return ~x + Long.MIN_VALUE; // transformed to Long.MAX_VALUE - x + } + + @Run(test = "testLongConMinusOneIsUnderflow1") + public void checkTestLongConMinusOneIsUnderflow1(RunInfo info) { + assertC2Compiled(info); + Asserts.assertEquals(9223372036854775797L, testLongConMinusOneIsUnderflow1(10)); + } + + @Test + @IR(failOn = {IRNode.ADD_L, IRNode.XOR_L}) + @IR(counts = {IRNode.SUB_L, "1"}) + public long testLongNegConMinusOneIsUnderflow2(long x) { + return ~(x + Long.MIN_VALUE); // transformed to Long.MAX_VALUE - x + } + + @Run(test = "testLongNegConMinusOneIsUnderflow2") + public void checkTestLongNegConMinusOneIsUnderflow2(RunInfo info) { + assertC2Compiled(info); + Asserts.assertEquals(9223372036854775797L, testLongNegConMinusOneIsUnderflow2(10)); + } + + @Test + @IR(failOn = {IRNode.ADD_I, IRNode.XOR_I}) + @IR(counts = {IRNode.SUB_I, "1"}) + public int testIntResultIsUnderflow1(int x) { + return ~x + -2147483638; // transformed to -2147483639 - x + } + + @Run(test = "testIntResultIsUnderflow1") + public void checkTestIntResultIsUnderflow1(RunInfo info) { + assertC2Compiled(info); + Asserts.assertEquals(Integer.MAX_VALUE, testIntResultIsUnderflow1(10)); + } + + @Test + @IR(failOn = {IRNode.ADD_I, IRNode.XOR_I}) + @IR(counts = {IRNode.SUB_I, "1"}) + public int testIntResultIsUnderflow2(int x) { + return ~(x + 2147483638); // transformed to -2147483639 - x + } + + @Run(test = "testIntResultIsUnderflow2") + public void checkTestIntResultIsUnderflow2(RunInfo info) { + assertC2Compiled(info); + Asserts.assertEquals(Integer.MAX_VALUE, testIntResultIsUnderflow2(10)); + } + + @Test + @IR(failOn = {IRNode.ADD_L, IRNode.XOR_L}) + @IR(counts = {IRNode.SUB_L, "1"}) + public long testLongResultIsUnderflow1(long x) { + return ~x + -9223372036854775798L; // transformed to -9223372036854775799L - x + } + + @Run(test = "testLongResultIsUnderflow1") + public void checkTestLongResultIsUnderflow1(RunInfo info) { + assertC2Compiled(info); + Asserts.assertEquals(Long.MAX_VALUE, testLongResultIsUnderflow1(10)); + } + + @Test + @IR(failOn = {IRNode.ADD_L, IRNode.XOR_L}) + @IR(counts = {IRNode.SUB_L, "1"}) + public long testLongResultIsUnderflow2(long x) { + return ~(x + 9223372036854775798L); // transformed to -9223372036854775799L - x + } + + @Run(test = "testLongResultIsUnderflow2") + public void checkTestLongResultIsUnderflow2(RunInfo info) { + assertC2Compiled(info); + Asserts.assertEquals(Long.MAX_VALUE, testLongResultIsUnderflow2(10)); + } + + @Test + @IR(failOn = {IRNode.ADD_I, IRNode.XOR_I}) + @IR(counts = {IRNode.SUB_I, "1"}) + public int testIntResultIsOverflow1(int x) { + return ~x + 2147483637; // transformed to 2147483646 - x + } + + @Run(test = "testIntResultIsOverflow1") + public void checkTestIntResultIsOverflow1(RunInfo info) { + assertC2Compiled(info); + Asserts.assertEquals(Integer.MIN_VALUE, testIntResultIsOverflow1(-12)); + } + @Test + @IR(failOn = {IRNode.ADD_I, IRNode.XOR_I}) + @IR(counts = {IRNode.SUB_I, "1"}) + public int testIntResultIsOverflow2(int x) { + return ~(x + -2147483637); // transformed to 2147483646 - x + } + + @Run(test = "testIntResultIsOverflow2") + public void checkTestIntResultIsOverflow2(RunInfo info) { + assertC2Compiled(info); + Asserts.assertEquals(Integer.MIN_VALUE, testIntResultIsOverflow2(-12)); + } + + @Test + @IR(failOn = {IRNode.ADD_L, IRNode.XOR_L}) + @IR(counts = {IRNode.SUB_L, "1"}) + public long testLongResultIsOverflow1(long x) { + return ~x + 9223372036854775797L; // transformed to 9223372036854775798L - x + } + + @Run(test = "testLongResultIsOverflow1") + public void checkTestLongResultIsOverflow1(RunInfo info) { + assertC2Compiled(info); + Asserts.assertEquals(Long.MIN_VALUE, testLongResultIsOverflow1(-12)); + } + + @Test + @IR(failOn = {IRNode.ADD_L, IRNode.XOR_L}) + @IR(counts = {IRNode.SUB_L, "1"}) + public long testLongResultIsOverflow2(long x) { + return ~(x + -9223372036854775797L); // transformed to 9223372036854775798L - x + } + + @Run(test = "testLongResultIsOverflow2") + public void checkTestLongResultIsOverflow2(RunInfo info) { + assertC2Compiled(info); + Asserts.assertEquals(Long.MIN_VALUE, testLongResultIsOverflow2(-12)); + } + + private void assertC2Compiled(RunInfo info) { + // Test VM allows C2 to work + Asserts.assertTrue(info.isC2CompilationEnabled()); + if (!info.isWarmUp()) { + // C2 compilation happens + Asserts.assertTrue(info.isTestC2Compiled()); + } + } +} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java index 315dfa350b7..c2e8a64f2b4 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java @@ -142,6 +142,8 @@ public class IRNode { public static final String ABS_D = START + "AbsD" + MID + END; public static final String AND_I = START + "AndI" + MID + END; public static final String AND_L = START + "AndL" + MID + END; + public static final String XOR_I = START + "XorI" + MID + END; + public static final String XOR_L = START + "XorL" + MID + END; public static final String LSHIFT_I = START + "LShiftI" + MID + END; public static final String LSHIFT_L = START + "LShiftL" + MID + END; public static final String ADD_I = START + "AddI" + MID + END; diff --git a/test/micro/org/openjdk/bench/vm/compiler/AddIdealNotXPlusC.java b/test/micro/org/openjdk/bench/vm/compiler/AddIdealNotXPlusC.java new file mode 100644 index 00000000000..057a1dc6104 --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/compiler/AddIdealNotXPlusC.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2022, 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.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; + +import java.util.concurrent.TimeUnit; + +/** + * Tests transformation that converts "~x + c" into "(c - 1) - x" in + * AddNode::IdealIL and "~(x+c)" into "(-c - 1) - x" in XorINode:Ideal + * and XorLNode::Ideal. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +@Warmup(iterations = 20, time = 1, timeUnit = TimeUnit.SECONDS) +@Measurement(iterations = 20, time = 1, timeUnit = TimeUnit.SECONDS) +@Fork(value = 3) +public class AddIdealNotXPlusC { + + private static final int I_C = 1234567; + + private static final long L_C = 123_456_789_123_456L; + + private int iFld = 4711; + + private long lFld = 4711 * 4711 * 4711; + + private final int SIZE = 10; + + @Benchmark + public void baselineInt(Blackhole bh) { + for (int i = 0; i < SIZE; i++) { + bh.consume(iFld); + } + } + + @Benchmark + public void baselineLong(Blackhole bh) { + for (int i = 0; i < SIZE; i++) { + bh.consume(lFld); + } + } + + // Convert "~x + c" into "(c - 1) - x" for int. + // (c - 1) -x + x is then converted into c - 1. + @Benchmark + public void testInt1(Blackhole bh) { + for (int i = 0; i < SIZE; i++) { + bh.consume(~iFld + I_C + iFld); + } + } + + // Convert "~(x + c)" into "(-c - 1) - x" for int. + // (-c - 1) -x + x is then converted into -c - 1. + @Benchmark + public void testInt2(Blackhole bh) { + for (int i = 0; i < SIZE; i++) { + bh.consume(~(iFld + I_C) + iFld); + } + } + + // Convert "~x + c" into "(c - 1) - x" for long. + // (c - 1) -x + x is then converted into c - 1. + @Benchmark + public void testLong1(Blackhole bh) { + for (int i = 0; i < SIZE; i++) { + bh.consume(~lFld + L_C + lFld); + } + } + + // Convert "~(x + c)" into "(-c - 1) - x" for long. + // (-c - 1) -x + x is then converted into -c - 1. + @Benchmark + public void testLong2(Blackhole bh) { + for (int i = 0; i < SIZE; i++) { + bh.consume(~(lFld + L_C) + lFld); + } + } +} -- GitLab From cf977e88ecc64b549f332efe01578fca9f435060 Mon Sep 17 00:00:00 2001 From: Sergey Tsypanov Date: Thu, 20 Jan 2022 09:14:49 +0000 Subject: [PATCH 223/564] 8276166: Remove dead code from MimeTable and MimeEntry Reviewed-by: dfuchs --- .../share/classes/sun/net/www/MimeEntry.java | 29 ------------------- .../share/classes/sun/net/www/MimeTable.java | 18 ++---------- 2 files changed, 3 insertions(+), 44 deletions(-) diff --git a/src/java.base/share/classes/sun/net/www/MimeEntry.java b/src/java.base/share/classes/sun/net/www/MimeEntry.java index 48b847cf558..3422b58e1bc 100644 --- a/src/java.base/share/classes/sun/net/www/MimeEntry.java +++ b/src/java.base/share/classes/sun/net/www/MimeEntry.java @@ -24,7 +24,6 @@ */ package sun.net.www; -import java.net.URL; import java.io.*; import java.util.StringJoiner; import java.util.StringTokenizer; @@ -63,34 +62,6 @@ public class MimeEntry implements Cloneable { this(type, UNKNOWN, null, null, null); } - // - // The next two constructors are used only by the deprecated - // PlatformMimeTable classes or, in last case, is called by the public - // constructor. They are kept here anticipating putting support for - // mailcap formatted config files back in (so BOTH the properties format - // and the mailcap formats are supported). - // - MimeEntry(String type, String imageFileName, String extensionString) { - typeName = type.toLowerCase(); - action = UNKNOWN; - command = null; - this.imageFileName = imageFileName; - setExtensions(extensionString); - starred = isStarred(typeName); - } - - // For use with MimeTable::parseMailCap - MimeEntry(String typeName, int action, String command, - String tempFileNameTemplate) { - this.typeName = typeName.toLowerCase(); - this.action = action; - this.command = command; - this.imageFileName = null; - this.fileExtensions = null; - - this.tempFileNameTemplate = tempFileNameTemplate; - } - // This is the one called by the public constructor. MimeEntry(String typeName, int action, String command, String imageFileName, String fileExtensions[]) { diff --git a/src/java.base/share/classes/sun/net/www/MimeTable.java b/src/java.base/share/classes/sun/net/www/MimeTable.java index 14149a637b3..accbe8b1c19 100644 --- a/src/java.base/share/classes/sun/net/www/MimeTable.java +++ b/src/java.base/share/classes/sun/net/www/MimeTable.java @@ -37,11 +37,11 @@ import java.util.StringTokenizer; public class MimeTable implements FileNameMap { /** Keyed by content type, returns MimeEntries */ private Hashtable entries - = new Hashtable(); + = new Hashtable<>(); /** Keyed by file extension (with the .), returns MimeEntries */ private Hashtable extensionMap - = new Hashtable(); + = new Hashtable<>(); // Will be reset if in the platform-specific data file @SuppressWarnings("removal") @@ -55,7 +55,6 @@ public class MimeTable implements FileNameMap { }); private static final String filePreamble = "sun.net.www MIME content-types table"; - private static final String fileMagic = "#" + filePreamble; MimeTable() { load(); @@ -67,7 +66,7 @@ public class MimeTable implements FileNameMap { @SuppressWarnings("removal") static MimeTable getDefaultInstance() { return java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { + new java.security.PrivilegedAction<>() { public MimeTable run() { MimeTable instance = new MimeTable(); URLConnection.setFileNameMap(instance); @@ -349,17 +348,6 @@ public class MimeTable implements FileNameMap { // else illegal name exception } - String[] getExtensions(String list) { - StringTokenizer tokenizer = new StringTokenizer(list, ","); - int n = tokenizer.countTokens(); - String[] extensions = new String[n]; - for (int i = 0; i < n; i++) { - extensions[i] = tokenizer.nextToken(); - } - - return extensions; - } - int getActionCode(String action) { for (int i = 0; i < MimeEntry.actionKeywords.length; i++) { if (action.equalsIgnoreCase(MimeEntry.actionKeywords[i])) { -- GitLab From 3f747368b9a5c321d2724ba57103f17edc166251 Mon Sep 17 00:00:00 2001 From: Vladimir Ivanov Date: Thu, 20 Jan 2022 11:23:17 +0000 Subject: [PATCH 224/564] 8280123: C2: Infinite loop in CMoveINode::Ideal during IGVN Reviewed-by: kvn, thartmann, chagedorn --- src/hotspot/share/opto/movenode.cpp | 42 ++++++------ .../compiler/c2/TestCMoveInfiniteGVN.java | 68 +++++++++++++++++++ 2 files changed, 89 insertions(+), 21 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/c2/TestCMoveInfiniteGVN.java diff --git a/src/hotspot/share/opto/movenode.cpp b/src/hotspot/share/opto/movenode.cpp index d7b445ea768..4e22a35aaec 100644 --- a/src/hotspot/share/opto/movenode.cpp +++ b/src/hotspot/share/opto/movenode.cpp @@ -75,21 +75,25 @@ // Return a node which is more "ideal" than the current node. // Move constants to the right. Node *CMoveNode::Ideal(PhaseGVN *phase, bool can_reshape) { - if( in(0) && remove_dead_region(phase, can_reshape) ) return this; + if (in(0) != NULL && remove_dead_region(phase, can_reshape)) { + return this; + } // Don't bother trying to transform a dead node - if( in(0) && in(0)->is_top() ) return NULL; + if (in(0) != NULL && in(0)->is_top()) { + return NULL; + } assert(in(Condition) != this && - in(IfFalse) != this && - in(IfTrue) != this, "dead loop in CMoveNode::Ideal" ); - if( phase->type(in(Condition)) == Type::TOP ) - return NULL; // return NULL when Condition is dead - - if( in(IfFalse)->is_Con() && !in(IfTrue)->is_Con() ) { - if( in(Condition)->is_Bool() ) { - BoolNode* b = in(Condition)->as_Bool(); - BoolNode* b2 = b->negate(phase); - return make(in(Control), phase->transform(b2), in(IfTrue), in(IfFalse), _type); - } + in(IfFalse) != this && + in(IfTrue) != this, "dead loop in CMoveNode::Ideal"); + if (phase->type(in(Condition)) == Type::TOP || + phase->type(in(IfFalse)) == Type::TOP || + phase->type(in(IfTrue)) == Type::TOP) { + return NULL; + } + // Canonicalize the node by moving constants to the right input. + if (in(Condition)->is_Bool() && phase->type(in(IfFalse))->singleton() && !phase->type(in(IfTrue))->singleton()) { + BoolNode* b = in(Condition)->as_Bool()->negate(phase); + return make(in(Control), phase->transform(b), in(IfTrue), in(IfFalse), _type); } return NULL; } @@ -191,14 +195,10 @@ Node *CMoveINode::Ideal(PhaseGVN *phase, bool can_reshape) { // If zero is on the left (false-case, no-move-case) it must mean another // constant is on the right (otherwise the shared CMove::Ideal code would - // have moved the constant to the right). This situation is bad for Intel - // and a don't-care for Sparc. It's bad for Intel because the zero has to - // be manifested in a register with a XOR which kills flags, which are live - // on input to the CMoveI, leading to a situation which causes excessive - // spilling on Intel. For Sparc, if the zero in on the left the Sparc will - // zero a register via G0 and conditionally-move the other constant. If the - // zero is on the right, the Sparc will load the first constant with a - // 13-bit set-lo and conditionally move G0. See bug 4677505. + // have moved the constant to the right). This situation is bad for x86 because + // the zero has to be manifested in a register with a XOR which kills flags, + // which are live on input to the CMoveI, leading to a situation which causes + // excessive spilling. See bug 4677505. if( phase->type(in(IfFalse)) == TypeInt::ZERO && !(phase->type(in(IfTrue)) == TypeInt::ZERO) ) { if( in(Condition)->is_Bool() ) { BoolNode* b = in(Condition)->as_Bool(); diff --git a/test/hotspot/jtreg/compiler/c2/TestCMoveInfiniteGVN.java b/test/hotspot/jtreg/compiler/c2/TestCMoveInfiniteGVN.java new file mode 100644 index 00000000000..50d9d02dea6 --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/TestCMoveInfiniteGVN.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2022, 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 + * @key stress randomness + * @bug 8280123 + * @run main/othervm -Xcomp -XX:-TieredCompilation + * -XX:CompileCommand=compileonly,compiler.c2.TestCMoveInfiniteGVN::test + * -XX:+UnlockDiagnosticVMOptions -XX:+StressIGVN -XX:StressSeed=43739875 + * compiler.c2.TestCMoveInfiniteGVN + * @run main/othervm -Xcomp -XX:-TieredCompilation + * -XX:CompileCommand=compileonly,compiler.c2.TestCMoveInfiniteGVN::test + * -XX:+UnlockDiagnosticVMOptions -XX:+StressIGVN + * compiler.c2.TestCMoveInfiniteGVN + */ + +package compiler.c2; + +public class TestCMoveInfiniteGVN { + + static int test(boolean b, int i) { + int iArr[] = new int[2]; + + double d = Math.max(i, i); + for (int i1 = 1; i1 < 2; i1++) { + if (i1 != 0) { + return (b ? 1 : 0); // CMoveI + } + for (int i2 = 1; i2 < 2; i2++) { + switch (i2) { + case 1: d -= Math.max(i1, i2); break; + } + d -= iArr[i1 - 1]; + } + } + return 0; + } + + static void test() { + test(true, 234); + } + + public static void main(String[] strArr) { + test(); // compilation, then nmethod invalidation during execution + test(); // trigger crashing recompilation + } +} -- GitLab From 20297deaeb64fb1e025ed1fcde19867c6875f9a0 Mon Sep 17 00:00:00 2001 From: Julia Boes Date: Thu, 20 Jan 2022 12:16:21 +0000 Subject: [PATCH 225/564] 8280161: com/sun/net/httpserver/simpleserver/jwebserver/MaxRequestTimeTest.java fails with SSLException Reviewed-by: dfuchs --- .../simpleserver/jwebserver/MaxRequestTimeTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/jdk/com/sun/net/httpserver/simpleserver/jwebserver/MaxRequestTimeTest.java b/test/jdk/com/sun/net/httpserver/simpleserver/jwebserver/MaxRequestTimeTest.java index 697e7381a37..e530c980565 100644 --- a/test/jdk/com/sun/net/httpserver/simpleserver/jwebserver/MaxRequestTimeTest.java +++ b/test/jdk/com/sun/net/httpserver/simpleserver/jwebserver/MaxRequestTimeTest.java @@ -41,7 +41,7 @@ import java.nio.file.Path; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLHandshakeException; +import javax.net.ssl.SSLException; import jdk.test.lib.Platform; import jdk.test.lib.net.SimpleSSLContext; import jdk.test.lib.process.OutputAnalyzer; @@ -140,8 +140,8 @@ public class MaxRequestTimeTest { var request = HttpRequest.newBuilder(URI.create("https://localhost:" + PORT.get() + "/")).build(); try { client.send(request, HttpResponse.BodyHandlers.ofString()); - throw new RuntimeException("Expected SSLHandshakeException not thrown"); - } catch (SSLHandshakeException expected) { // server closes connection when max request time is reached + throw new RuntimeException("Expected SSLException not thrown"); + } catch (SSLException expected) { // server closes connection when max request time is reached expected.printStackTrace(System.out); } } -- GitLab From 98b157a79af3e76f028bccd04a5e505642aae7a4 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Thu, 20 Jan 2022 12:33:16 +0000 Subject: [PATCH 226/564] 8280146: Parallel: Remove time log tag Reviewed-by: tschatzl, iwalulya --- .../share/gc/parallel/psParallelCompact.cpp | 12 ------------ src/hotspot/share/gc/parallel/psScavenge.cpp | 14 -------------- src/hotspot/share/logging/logPrefix.hpp | 1 - src/hotspot/share/logging/logTag.hpp | 1 - 4 files changed, 28 deletions(-) diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.cpp b/src/hotspot/share/gc/parallel/psParallelCompact.cpp index a28ebbf1510..9d30f4bf2e2 100644 --- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp +++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp @@ -1735,10 +1735,6 @@ bool PSParallelCompact::invoke_no_policy(bool maximum_heap_compaction) { _gc_timer.register_gc_start(); _gc_tracer.report_gc_start(heap->gc_cause(), _gc_timer.gc_start()); - TimeStamp marking_start; - TimeStamp compaction_start; - TimeStamp collection_exit; - GCCause::Cause gc_cause = heap->gc_cause(); PSYoungGen* young_gen = heap->young_gen(); PSOldGen* old_gen = heap->old_gen(); @@ -1791,7 +1787,6 @@ bool PSParallelCompact::invoke_no_policy(bool maximum_heap_compaction) { ref_processor()->start_discovery(maximum_heap_compaction); - marking_start.update(); marking_phase(vmthread_cm, &_gc_tracer); bool max_on_system_gc = UseMaximumCompactionOnSystemGC @@ -1807,7 +1802,6 @@ bool PSParallelCompact::invoke_no_policy(bool maximum_heap_compaction) { // needed by the compaction for filling holes in the dense prefix. adjust_roots(); - compaction_start.update(); compact(); ParCompactionManager::verify_all_region_stack_empty(); @@ -1922,15 +1916,9 @@ bool PSParallelCompact::invoke_no_policy(bool maximum_heap_compaction) { old_gen->object_space()->check_mangled_unused_area_complete(); } - collection_exit.update(); - heap->print_heap_after_gc(); heap->trace_heap_after_gc(&_gc_tracer); - log_debug(gc, task, time)("VM-Thread " JLONG_FORMAT " " JLONG_FORMAT " " JLONG_FORMAT, - marking_start.ticks(), compaction_start.ticks(), - collection_exit.ticks()); - AdaptiveSizePolicyOutput::print(size_policy, heap->total_collections()); _gc_timer.register_gc_end(); diff --git a/src/hotspot/share/gc/parallel/psScavenge.cpp b/src/hotspot/share/gc/parallel/psScavenge.cpp index 430e4ccf4ec..995c5157dfc 100644 --- a/src/hotspot/share/gc/parallel/psScavenge.cpp +++ b/src/hotspot/share/gc/parallel/psScavenge.cpp @@ -358,12 +358,6 @@ bool PSScavenge::invoke_no_policy() { _gc_timer.register_gc_start(); - TimeStamp scavenge_entry; - TimeStamp scavenge_midpoint; - TimeStamp scavenge_exit; - - scavenge_entry.update(); - if (GCLocker::check_active_before_gc()) { return false; } @@ -463,8 +457,6 @@ bool PSScavenge::invoke_no_policy() { ParallelScavengeHeap::heap()->workers().run_task(&task); } - scavenge_midpoint.update(); - // Process reference objects discovered during scavenge { GCTraceTime(Debug, gc, phases) tm("Reference Processing", &_gc_timer); @@ -669,12 +661,6 @@ bool PSScavenge::invoke_no_policy() { heap->print_heap_after_gc(); heap->trace_heap_after_gc(&_gc_tracer); - scavenge_exit.update(); - - log_debug(gc, task, time)("VM-Thread " JLONG_FORMAT " " JLONG_FORMAT " " JLONG_FORMAT, - scavenge_entry.ticks(), scavenge_midpoint.ticks(), - scavenge_exit.ticks()); - AdaptiveSizePolicyOutput::print(size_policy, heap->total_collections()); _gc_timer.register_gc_end(); diff --git a/src/hotspot/share/logging/logPrefix.hpp b/src/hotspot/share/logging/logPrefix.hpp index 3411bfb7c79..13650157303 100644 --- a/src/hotspot/share/logging/logPrefix.hpp +++ b/src/hotspot/share/logging/logPrefix.hpp @@ -90,7 +90,6 @@ DEBUG_ONLY(size_t Test_log_prefix_prefixer(char* buf, size_t len);) LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, task)) \ LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, task, start)) \ LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, task, stats)) \ - LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, task, time)) \ DEBUG_ONLY(LOG_PREFIX(Test_log_prefix_prefixer, LOG_TAGS(logging, test))) \ LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, tlab)) \ LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, verify)) \ diff --git a/src/hotspot/share/logging/logTag.hpp b/src/hotspot/share/logging/logTag.hpp index 2042cf2b4d7..78e0a88d112 100644 --- a/src/hotspot/share/logging/logTag.hpp +++ b/src/hotspot/share/logging/logTag.hpp @@ -183,7 +183,6 @@ DEBUG_ONLY(LOG_TAG(test)) \ LOG_TAG(thread) \ LOG_TAG(throttle) \ - LOG_TAG(time) \ LOG_TAG(timer) \ LOG_TAG(tlab) \ LOG_TAG(tracking) \ -- GitLab From a4d201909c8919b7465dee72594d718252c6344e Mon Sep 17 00:00:00 2001 From: Harold Seigel Date: Thu, 20 Jan 2022 13:10:33 +0000 Subject: [PATCH 227/564] 8280178: Remove os:: API's that just call system API's Reviewed-by: iklam, ccheung, dholmes --- src/hotspot/os/posix/os_posix.cpp | 8 -------- src/hotspot/os/posix/perfMemory_posix.cpp | 12 ++++++------ src/hotspot/os/windows/os_windows.cpp | 12 ++---------- .../linux_aarch64/vm_version_linux_aarch64.cpp | 4 ++-- src/hotspot/share/cds/filemap.cpp | 16 ++++++++-------- src/hotspot/share/classfile/classLoader.cpp | 6 +++--- src/hotspot/share/classfile/compactHashtable.cpp | 2 +- src/hotspot/share/compiler/compileLog.cpp | 6 +++--- src/hotspot/share/compiler/directivesParser.cpp | 6 +++--- src/hotspot/share/include/cds.h | 2 +- .../jfr/recorder/repository/jfrEmergencyDump.cpp | 8 ++++---- .../jfr/writers/jfrStreamWriterHost.inline.hpp | 2 +- src/hotspot/share/memory/virtualspace.cpp | 4 ++-- src/hotspot/share/runtime/arguments.cpp | 10 +++++----- src/hotspot/share/runtime/os.cpp | 6 +----- src/hotspot/share/runtime/os.hpp | 3 --- .../share/services/heapDumperCompression.cpp | 2 +- src/hotspot/share/utilities/ostream.cpp | 2 +- src/hotspot/share/utilities/vmError.cpp | 2 +- 19 files changed, 45 insertions(+), 68 deletions(-) diff --git a/src/hotspot/os/posix/os_posix.cpp b/src/hotspot/os/posix/os_posix.cpp index 3c32ec718a3..31c1cbc3d4f 100644 --- a/src/hotspot/os/posix/os_posix.cpp +++ b/src/hotspot/os/posix/os_posix.cpp @@ -689,10 +689,6 @@ ssize_t os::read_at(int fd, void *buf, unsigned int nBytes, jlong offset) { return ::pread(fd, buf, nBytes, offset); } -int os::close(int fd) { - return ::close(fd); -} - void os::flockfile(FILE* fp) { ::flockfile(fp); } @@ -720,10 +716,6 @@ int os::socket_close(int fd) { return ::close(fd); } -int os::socket(int domain, int type, int protocol) { - return ::socket(domain, type, protocol); -} - int os::recv(int fd, char* buf, size_t nBytes, uint flags) { RESTARTABLE_RETURN_INT(::recv(fd, buf, nBytes, flags)); } diff --git a/src/hotspot/os/posix/perfMemory_posix.cpp b/src/hotspot/os/posix/perfMemory_posix.cpp index 1a9a315042e..7fcf867b3f8 100644 --- a/src/hotspot/os/posix/perfMemory_posix.cpp +++ b/src/hotspot/os/posix/perfMemory_posix.cpp @@ -124,7 +124,7 @@ static void save_memory_to_file(char* addr, size_t size) { addr += result; } - result = os::close(fd); + result = ::close(fd); if (PrintMiscellaneous && Verbose) { if (result == OS_ERR) { warning("Could not close %s: %s\n", destfile, os::strerror(errno)); @@ -330,7 +330,7 @@ static DIR *open_directory_secure(const char* dirname) { // Determine if the open directory is secure. if (!is_dirfd_secure(fd)) { // The directory is not a secure directory. - os::close(fd); + ::close(fd); return dirp; } @@ -338,21 +338,21 @@ static DIR *open_directory_secure(const char* dirname) { dirp = ::opendir(dirname); if (dirp == NULL) { // The directory doesn't exist, close fd and return. - os::close(fd); + ::close(fd); return dirp; } // Check to make sure fd and dirp are referencing the same file system object. if (!is_same_fsobject(fd, AIX_ONLY(dirp->dd_fd) NOT_AIX(dirfd(dirp)))) { // The directory is not secure. - os::close(fd); + ::close(fd); os::closedir(dirp); dirp = NULL; return dirp; } // Close initial open now that we know directory is secure - os::close(fd); + ::close(fd); return dirp; } @@ -905,7 +905,7 @@ static int create_sharedmem_resources(const char* dirname, const char* filename, if (result != -1) { return fd; } else { - os::close(fd); + ::close(fd); return -1; } } diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index b31f08e5ec2..482c7615bc1 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -1553,7 +1553,7 @@ void * os::dll_load(const char *name, char *ebuf, int ebuflen) { || // Read location of signature (sizeof(signature_offset) != - (os::read(fd, (void*)&signature_offset, sizeof(signature_offset)))) + (::read(fd, (void*)&signature_offset, sizeof(signature_offset)))) || // Go to COFF File Header in dll // that is located after "signature" (4 bytes long) @@ -1562,7 +1562,7 @@ void * os::dll_load(const char *name, char *ebuf, int ebuflen) { || // Read field that contains code of architecture // that dll was built for - (sizeof(lib_arch) != (os::read(fd, (void*)&lib_arch, sizeof(lib_arch)))) + (sizeof(lib_arch) != (::read(fd, (void*)&lib_arch, sizeof(lib_arch)))) ); ::close(fd); @@ -4762,10 +4762,6 @@ ssize_t os::write(int fd, const void *buf, unsigned int nBytes) { return ::write(fd, buf, nBytes); } -int os::close(int fd) { - return ::close(fd); -} - void os::exit(int num) { win32::exit_process_or_thread(win32::EPT_PROCESS, num); } @@ -5725,10 +5721,6 @@ int os::socket_close(int fd) { return ::closesocket(fd); } -int os::socket(int domain, int type, int protocol) { - return ::socket(domain, type, protocol); -} - int os::connect(int fd, struct sockaddr* him, socklen_t len) { return ::connect(fd, him, len); } diff --git a/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp b/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp index a23c88518b0..b5f5a0787e9 100644 --- a/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp +++ b/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp @@ -174,8 +174,8 @@ static bool read_fully(const char *fname, char *buf, size_t buflen) { assert(buflen >= 1, "invalid argument"); int fd = os::open(fname, O_RDONLY, 0); if (fd != -1) { - ssize_t read_sz = os::read(fd, buf, buflen); - os::close(fd); + ssize_t read_sz = ::read(fd, buf, buflen); + ::close(fd); // Skip if the contents is just "\n" because some machine only sets // '\n' to the board name. diff --git a/src/hotspot/share/cds/filemap.cpp b/src/hotspot/share/cds/filemap.cpp index 5c684e960f1..3a121e3b4ee 100644 --- a/src/hotspot/share/cds/filemap.cpp +++ b/src/hotspot/share/cds/filemap.cpp @@ -190,7 +190,7 @@ FileMapInfo::~FileMapInfo() { _dynamic_archive_info = NULL; } if (_file_open) { - os::close(_fd); + ::close(_fd); } } @@ -1070,7 +1070,7 @@ public: ~FileHeaderHelper() { if (_fd != -1) { - os::close(_fd); + ::close(_fd); } } @@ -1092,7 +1092,7 @@ public: GenericCDSFileMapHeader gen_header; size_t size = sizeof(GenericCDSFileMapHeader); os::lseek(fd, 0, SEEK_SET); - size_t n = os::read(fd, (void*)&gen_header, (unsigned int)size); + size_t n = ::read(fd, (void*)&gen_header, (unsigned int)size); if (n != size) { FileMapInfo::fail_continue("Unable to read generic CDS file map header from shared archive"); return false; @@ -1125,7 +1125,7 @@ public: size = gen_header._header_size; _header = (GenericCDSFileMapHeader*)NEW_C_HEAP_ARRAY(char, size, mtInternal); os::lseek(fd, 0, SEEK_SET); - n = os::read(fd, (void*)_header, (unsigned int)size); + n = ::read(fd, (void*)_header, (unsigned int)size); if (n != size) { FileMapInfo::fail_continue("Unable to read actual CDS file map header from shared archive"); return false; @@ -1279,7 +1279,7 @@ bool FileMapInfo::init_from_file(int fd) { _header = (FileMapHeader*)os::malloc(gen_header->_header_size, mtInternal); os::lseek(fd, 0, SEEK_SET); // reset to begin of the archive size_t size = gen_header->_header_size; - size_t n = os::read(fd, (void*)_header, (unsigned int)size); + size_t n = ::read(fd, (void*)_header, (unsigned int)size); if (n != size) { fail_continue("Failed to read file header from the top archive file\n"); return false; @@ -1650,7 +1650,7 @@ void FileMapInfo::write_bytes_aligned(const void* buffer, size_t nbytes) { void FileMapInfo::close() { if (_file_open) { - if (os::close(_fd) < 0) { + if (::close(_fd) < 0) { fail_stop("Unable to close the shared archive file."); } _file_open = false; @@ -1778,7 +1778,7 @@ MapArchiveResult FileMapInfo::map_region(int i, intx addr_delta, char* mapped_ba if (MetaspaceShared::use_windows_memory_mapping() && rs.is_reserved()) { // This is the second time we try to map the archive(s). We have already created a ReservedSpace // that covers all the FileMapRegions to ensure all regions can be mapped. However, Windows - // can't mmap into a ReservedSpace, so we just os::read() the data. We're going to patch all the + // can't mmap into a ReservedSpace, so we just ::read() the data. We're going to patch all the // regions anyway, so there's no benefit for mmap anyway. if (!read_region(i, requested_addr, size, /* do_commit = */ true)) { log_info(cds)("Failed to read %s shared space into reserved space at " INTPTR_FORMAT, @@ -1884,7 +1884,7 @@ bool FileMapInfo::relocate_pointers_in_core_regions(intx addr_delta) { size_t FileMapInfo::read_bytes(void* buffer, size_t count) { assert(_file_open, "Archive file is not open"); - size_t n = os::read(_fd, buffer, (unsigned int)count); + size_t n = ::read(_fd, buffer, (unsigned int)count); if (n != count) { // Close the file if there's a problem reading it. close(); diff --git a/src/hotspot/share/classfile/classLoader.cpp b/src/hotspot/share/classfile/classLoader.cpp index f42b1fe4751..7fb8f71cbc8 100644 --- a/src/hotspot/share/classfile/classLoader.cpp +++ b/src/hotspot/share/classfile/classLoader.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -253,9 +253,9 @@ ClassFileStream* ClassPathDirEntry::open_stream(JavaThread* current, const char* if (file_handle != -1) { // read contents into resource array u1* buffer = NEW_RESOURCE_ARRAY(u1, st.st_size); - size_t num_read = os::read(file_handle, (char*) buffer, st.st_size); + size_t num_read = ::read(file_handle, (char*) buffer, st.st_size); // close file - os::close(file_handle); + ::close(file_handle); // construct ClassFileStream if (num_read == (size_t)st.st_size) { if (UsePerfData) { diff --git a/src/hotspot/share/classfile/compactHashtable.cpp b/src/hotspot/share/classfile/compactHashtable.cpp index b6fe339d4ce..4538af56e4b 100644 --- a/src/hotspot/share/classfile/compactHashtable.cpp +++ b/src/hotspot/share/classfile/compactHashtable.cpp @@ -252,7 +252,7 @@ HashtableTextDump::HashtableTextDump(const char* filename) : _fd(-1) { HashtableTextDump::~HashtableTextDump() { os::unmap_memory((char*)_base, _size); if (_fd >= 0) { - os::close(_fd); + ::close(_fd); } } diff --git a/src/hotspot/share/compiler/compileLog.cpp b/src/hotspot/share/compiler/compileLog.cpp index d5e9a52645a..3dbc71f6075 100644 --- a/src/hotspot/share/compiler/compileLog.cpp +++ b/src/hotspot/share/compiler/compileLog.cpp @@ -225,7 +225,7 @@ void CompileLog::finish_log_on_error(outputStream* file, char* buf, int buflen) if (to_read < (julong)buflen) nr = (size_t)to_read; else nr = buflen; - bytes_read = os::read(partial_fd, buf, (int)nr); + bytes_read = ::read(partial_fd, buf, (int)nr); if (bytes_read <= 0) break; nr = bytes_read; to_read -= (julong)nr; @@ -235,7 +235,7 @@ void CompileLog::finish_log_on_error(outputStream* file, char* buf, int buflen) // Copy any remaining data inside a quote: bool saw_slop = false; int end_cdata = 0; // state machine [0..2] watching for too many "]]" - while ((bytes_read = os::read(partial_fd, buf, buflen-1)) > 0) { + while ((bytes_read = ::read(partial_fd, buf, buflen-1)) > 0) { nr = bytes_read; buf[buflen-1] = '\0'; if (!saw_slop) { @@ -285,7 +285,7 @@ void CompileLog::finish_log_on_error(outputStream* file, char* buf, int buflen) file->print_raw_cr(""); } file->print_raw_cr(""); - os::close(partial_fd); + ::close(partial_fd); } CompileLog* next_log = log->_next; delete log; // Removes partial file diff --git a/src/hotspot/share/compiler/directivesParser.cpp b/src/hotspot/share/compiler/directivesParser.cpp index e88dda3768b..b4ce9a3877c 100644 --- a/src/hotspot/share/compiler/directivesParser.cpp +++ b/src/hotspot/share/compiler/directivesParser.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, 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 @@ -94,11 +94,11 @@ bool DirectivesParser::parse_from_file_inner(const char* filename, outputStream* if (file_handle != -1) { // read contents into resource array char* buffer = NEW_RESOURCE_ARRAY(char, st.st_size+1); - ssize_t num_read = os::read(file_handle, (char*) buffer, st.st_size); + ssize_t num_read = ::read(file_handle, (char*) buffer, st.st_size); if (num_read >= 0) { buffer[num_read] = '\0'; // close file - os::close(file_handle); + ::close(file_handle); return parse_string(buffer, stream) > 0; } } diff --git a/src/hotspot/share/include/cds.h b/src/hotspot/share/include/cds.h index 1c8640ec0b2..21a7a43b3af 100644 --- a/src/hotspot/share/include/cds.h +++ b/src/hotspot/share/include/cds.h @@ -48,7 +48,7 @@ typedef struct CDSFileMapRegion { int _is_heap_region; // Used by SA and debug build. int _is_bitmap_region; // Relocation bitmap for RO/RW regions (used by SA and debug build). int _mapped_from_file; // Is this region mapped from a file? - // If false, this region was initialized using os::read(). + // If false, this region was initialized using ::read(). size_t _file_offset; // Data for this region starts at this offset in the archive file. size_t _mapping_offset; // This region should be mapped at this offset from the base address // - for non-heap regions, the base address is SharedBaseAddress diff --git a/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp b/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp index 1dac9703459..8aeea6bdb44 100644 --- a/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp +++ b/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -105,7 +105,7 @@ static bool open_emergency_dump_fd(const char* path) { static void close_emergency_dump_file() { if (is_emergency_dump_file_open()) { - os::close(emergency_fd); + ::close(emergency_fd); } } @@ -298,7 +298,7 @@ const char* RepositoryIterator::filter(const char* file_name) const { return NULL; } const int64_t size = file_size(fd); - os::close(fd); + ::close(fd); if (size <= chunk_file_header_size) { return NULL; } @@ -389,7 +389,7 @@ static void write_repository_files(const RepositoryIterator& iterator, char* con bytes_written += (int64_t)os::write(emergency_fd, copy_block, bytes_read - bytes_written); assert(bytes_read == bytes_written, "invariant"); } - os::close(current_fd); + ::close(current_fd); } } } diff --git a/src/hotspot/share/jfr/writers/jfrStreamWriterHost.inline.hpp b/src/hotspot/share/jfr/writers/jfrStreamWriterHost.inline.hpp index ceb5e7fe027..3a7ec286381 100644 --- a/src/hotspot/share/jfr/writers/jfrStreamWriterHost.inline.hpp +++ b/src/hotspot/share/jfr/writers/jfrStreamWriterHost.inline.hpp @@ -135,7 +135,7 @@ inline bool StreamWriterHost::is_valid() const { template inline void StreamWriterHost::close_fd() { assert(this->has_valid_fd(), "closing invalid fd!"); - os::close(_fd); + ::close(_fd); _fd = invalid_fd; } diff --git a/src/hotspot/share/memory/virtualspace.cpp b/src/hotspot/share/memory/virtualspace.cpp index c5f682bb31f..ad918dea29b 100644 --- a/src/hotspot/share/memory/virtualspace.cpp +++ b/src/hotspot/share/memory/virtualspace.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -628,7 +628,7 @@ ReservedHeapSpace::ReservedHeapSpace(size_t size, size_t alignment, size_t page_ } if (_fd_for_heap != -1) { - os::close(_fd_for_heap); + ::close(_fd_for_heap); } } diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index b3855b4a0da..6d1e55f4c9a 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -3323,13 +3323,13 @@ jint Arguments::parse_vm_options_file(const char* file_name, ScopedVMInitArgs* v jio_fprintf(defaultStream::error_stream(), "Could not stat options file '%s'\n", file_name); - os::close(fd); + ::close(fd); return JNI_ERR; } if (stbuf.st_size == 0) { // tell caller there is no option data and that is ok - os::close(fd); + ::close(fd); return JNI_OK; } @@ -3340,15 +3340,15 @@ jint Arguments::parse_vm_options_file(const char* file_name, ScopedVMInitArgs* v if (NULL == buf) { jio_fprintf(defaultStream::error_stream(), "Could not allocate read buffer for options file parse\n"); - os::close(fd); + ::close(fd); return JNI_ENOMEM; } memset(buf, 0, bytes_alloc); // Fill buffer - ssize_t bytes_read = os::read(fd, (void *)buf, (unsigned)bytes_alloc); - os::close(fd); + ssize_t bytes_read = ::read(fd, (void *)buf, (unsigned)bytes_alloc); + ::close(fd); if (bytes_read < 0) { FREE_C_HEAP_ARRAY(char, buf); jio_fprintf(defaultStream::error_stream(), diff --git a/src/hotspot/share/runtime/os.cpp b/src/hotspot/share/runtime/os.cpp index bc78d28c43d..48a0f8398be 100644 --- a/src/hotspot/share/runtime/os.cpp +++ b/src/hotspot/share/runtime/os.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -1294,10 +1294,6 @@ FILE* os::fopen(const char* path, const char* mode) { return file; } -ssize_t os::read(int fd, void *buf, unsigned int nBytes) { - return ::read(fd, buf, nBytes); -} - bool os::set_boot_path(char fileSep, char pathSep) { const char* home = Arguments::get_java_home(); int home_len = (int)strlen(home); diff --git a/src/hotspot/share/runtime/os.hpp b/src/hotspot/share/runtime/os.hpp index d3e48cb54f4..b63637e3576 100644 --- a/src/hotspot/share/runtime/os.hpp +++ b/src/hotspot/share/runtime/os.hpp @@ -543,7 +543,6 @@ class os: AllStatic { static int open(const char *path, int oflag, int mode); static FILE* fdopen(int fd, const char* mode); static FILE* fopen(const char* path, const char* mode); - static int close(int fd); static jlong lseek(int fd, jlong offset, int whence); static bool file_exists(const char* file); // This function, on Windows, canonicalizes a given path (see os_windows.cpp for details). @@ -563,7 +562,6 @@ class os: AllStatic { //File i/o operations - static ssize_t read(int fd, void *buf, unsigned int nBytes); static ssize_t read_at(int fd, void *buf, unsigned int nBytes, jlong offset); static ssize_t write(int fd, const void *buf, unsigned int nBytes); @@ -785,7 +783,6 @@ class os: AllStatic { static char* strdup_check_oom(const char*, MEMFLAGS flags = mtInternal); // SocketInterface (ex HPI SocketInterface ) - static int socket(int domain, int type, int protocol); static int socket_close(int fd); static int recv(int fd, char* buf, size_t nBytes, uint flags); static int send(int fd, char* buf, size_t nBytes, uint flags); diff --git a/src/hotspot/share/services/heapDumperCompression.cpp b/src/hotspot/share/services/heapDumperCompression.cpp index b341a6366ef..0c9958077d2 100644 --- a/src/hotspot/share/services/heapDumperCompression.cpp +++ b/src/hotspot/share/services/heapDumperCompression.cpp @@ -46,7 +46,7 @@ char const* FileWriter::open_writer() { FileWriter::~FileWriter() { if (_fd >= 0) { - os::close(_fd); + ::close(_fd); _fd = -1; } } diff --git a/src/hotspot/share/utilities/ostream.cpp b/src/hotspot/share/utilities/ostream.cpp index 323691cf6d6..efb6a4ac7e6 100644 --- a/src/hotspot/share/utilities/ostream.cpp +++ b/src/hotspot/share/utilities/ostream.cpp @@ -1079,7 +1079,7 @@ networkStream::networkStream() : bufferedStream(1024*10, 1024*10) { _socket = -1; - int result = os::socket(AF_INET, SOCK_STREAM, 0); + int result = ::socket(AF_INET, SOCK_STREAM, 0); if (result <= 0) { assert(false, "Socket could not be created!"); } else { diff --git a/src/hotspot/share/utilities/vmError.cpp b/src/hotspot/share/utilities/vmError.cpp index e1d6581ca06..1d72092f8ae 100644 --- a/src/hotspot/share/utilities/vmError.cpp +++ b/src/hotspot/share/utilities/vmError.cpp @@ -1654,7 +1654,7 @@ void VMError::report_and_die(int id, const char* message, const char* detail_fmt _current_step_info = ""; if (fd_log > 3) { - os::close(fd_log); + ::close(fd_log); fd_log = -1; } -- GitLab From ec8b6acff39953ca60309c6f1db7ae4c93404da9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Walln=C3=B6fer?= Date: Thu, 20 Jan 2022 16:17:08 +0000 Subject: [PATCH 228/564] 8234682: The order of @param in the generated docs should match the method signature Reviewed-by: prappo --- .../doclets/toolkit/taglets/ParamTaglet.java | 117 ++++++++---------- .../testParamTaglet/TestParamTaglet.java | 53 ++++++-- .../javadoc/doclet/testParamTaglet/pkg/C.java | 38 +++++- .../doclet/testParamTaglet/pkg/Parent.java | 9 +- 4 files changed, 139 insertions(+), 78 deletions(-) diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/ParamTaglet.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/ParamTaglet.java index 2552eb137a7..2af114d322b 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/ParamTaglet.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/ParamTaglet.java @@ -165,54 +165,29 @@ public class ParamTaglet extends BaseTaglet implements InheritableTaglet { private Content getTagletOutput(ParamKind kind, Element holder, TagletWriter writer, List formalParameters, List paramTags) { Content result = writer.getOutputInstance(); - Set alreadyDocumented = new HashSet<>(); - if (!paramTags.isEmpty()) { - result.add( - processParamTags(holder, kind, paramTags, - getRankMap(writer.configuration().utils, formalParameters), writer, alreadyDocumented) - ); - } - if (alreadyDocumented.size() != formalParameters.size()) { - //Some parameters are missing corresponding @param tags. - //Try to inherit them. - result.add(getInheritedTagletOutput(kind, holder, - writer, formalParameters, alreadyDocumented)); - } + result.add(processParamTags(holder, kind, paramTags, formalParameters, writer)); return result; } /** - * Loop through each individual parameter, despite not having a - * corresponding param tag, try to inherit it. + * Try to get the inherited taglet documentation for a specific parameter. */ private Content getInheritedTagletOutput(ParamKind kind, Element holder, - TagletWriter writer, List formalParameters, - Set alreadyDocumented) { + TagletWriter writer, Element param, int rank, + boolean isFirst) { Utils utils = writer.configuration().utils; Content result = writer.getOutputInstance(); - if ((!alreadyDocumented.contains(null)) && utils.isExecutableElement(holder)) { - for (int i = 0; i < formalParameters.size(); i++) { - if (alreadyDocumented.contains(String.valueOf(i))) { - continue; - } - // This parameter does not have any @param documentation. - // Try to inherit it. - Input input = new DocFinder.Input(writer.configuration().utils, holder, this, - Integer.toString(i), kind == ParamKind.TYPE_PARAMETER); - DocFinder.Output inheritedDoc = DocFinder.search(writer.configuration(), input); - if (inheritedDoc.inlineTags != null && !inheritedDoc.inlineTags.isEmpty()) { - Element e = formalParameters.get(i); - String lname = kind != ParamKind.TYPE_PARAMETER - ? utils.getSimpleName(e) - : utils.getTypeName(e.asType(), false); - Content content = processParamTag(inheritedDoc.holder, kind, writer, - (ParamTree) inheritedDoc.holderTag, - lname, - alreadyDocumented.isEmpty()); - result.add(content); - } - alreadyDocumented.add(String.valueOf(i)); - } + Input input = new DocFinder.Input(writer.configuration().utils, holder, this, + Integer.toString(rank), kind == ParamKind.TYPE_PARAMETER); + DocFinder.Output inheritedDoc = DocFinder.search(writer.configuration(), input); + if (inheritedDoc.inlineTags != null && !inheritedDoc.inlineTags.isEmpty()) { + String lname = kind != ParamKind.TYPE_PARAMETER + ? utils.getSimpleName(param) + : utils.getTypeName(param.asType(), false); + Content content = processParamTag(inheritedDoc.holder, kind, writer, + (ParamTree) inheritedDoc.holderTag, + lname, isFirst); + result.add(content); } return result; } @@ -225,23 +200,15 @@ public class ParamTaglet extends BaseTaglet implements InheritableTaglet { * * @param paramTags the array of {@code @param DocTree} to convert. * @param writer the TagletWriter that will write this tag. - * @param alreadyDocumented the set of exceptions that have already - * been documented. - * @param rankMap a {@link java.util.Map} which holds ordering - * information about the parameters. - * @param rankMap a {@link java.util.Map} which holds a mapping - of a rank of a parameter to its name. This is - used to ensure that the right name is used - when parameter documentation is inherited. * @return the Content representation of this {@code @param DocTree}. */ - private Content processParamTags(Element e, ParamKind kind, - List paramTags, Map rankMap, TagletWriter writer, - Set alreadyDocumented) { + private Content processParamTags(Element e, ParamKind kind, List paramTags, + List formalParameters, TagletWriter writer) { + Map documented = new HashMap<>(); Messages messages = writer.configuration().getMessages(); - Content result = writer.getOutputInstance(); + CommentHelper ch = writer.configuration().utils.getCommentHelper(e); if (!paramTags.isEmpty()) { - CommentHelper ch = writer.configuration().utils.getCommentHelper(e); + Map rankMap = getRankMap(writer.configuration().utils, formalParameters); for (ParamTree dt : paramTags) { String name = ch.getParameterName(dt); String paramName = kind == ParamKind.TYPE_PARAMETER ? "<" + name + ">" : name; @@ -250,23 +217,45 @@ public class ParamTaglet extends BaseTaglet implements InheritableTaglet { case PARAMETER -> "doclet.Parameters_warn"; case TYPE_PARAMETER -> "doclet.TypeParameters_warn"; case RECORD_COMPONENT -> "doclet.RecordComponents_warn"; - default -> throw new IllegalArgumentException(kind.toString()); }; messages.warning(ch.getDocTreePath(dt), key, paramName); } String rank = rankMap.get(name); - if (rank != null && alreadyDocumented.contains(rank)) { - String key = switch (kind) { - case PARAMETER -> "doclet.Parameters_dup_warn"; - case TYPE_PARAMETER -> "doclet.TypeParameters_dup_warn"; - case RECORD_COMPONENT -> "doclet.RecordComponents_dup_warn"; - default -> throw new IllegalArgumentException(kind.toString()); - }; - messages.warning(ch.getDocTreePath(dt), key, paramName); + if (rank != null) { + if (documented.containsKey(rank)) { + String key = switch (kind) { + case PARAMETER -> "doclet.Parameters_dup_warn"; + case TYPE_PARAMETER -> "doclet.TypeParameters_dup_warn"; + case RECORD_COMPONENT -> "doclet.RecordComponents_dup_warn"; + }; + messages.warning(ch.getDocTreePath(dt), key, paramName); + } else { + documented.put(rank, dt); + } } + } + } + // Document declared parameters for which taglet documentation is available + // (either directly or inherited) in order of their declaration. + Content result = writer.getOutputInstance(); + for (int i = 0; i < formalParameters.size(); i++) { + ParamTree dt = documented.get(String.valueOf(i)); + if (dt != null) { result.add(processParamTag(e, kind, writer, dt, - name, alreadyDocumented.isEmpty())); - alreadyDocumented.add(rank); + ch.getParameterName(dt), result.isEmpty())); + } else if (writer.configuration().utils.isExecutableElement(e)) { + result.add(getInheritedTagletOutput(kind, e, writer, + formalParameters.get(i), i, result.isEmpty())); + } + } + if (paramTags.size() > documented.size()) { + // Generate documentation for remaining taglets that do not match a declared parameter. + // These are erroneous but we generate them anyway. + for (ParamTree dt : paramTags) { + if (!documented.containsValue(dt)) { + result.add(processParamTag(e, kind, writer, dt, + ch.getParameterName(dt), result.isEmpty())); + } } } return result; diff --git a/test/langtools/jdk/javadoc/doclet/testParamTaglet/TestParamTaglet.java b/test/langtools/jdk/javadoc/doclet/testParamTaglet/TestParamTaglet.java index b6b6a7a78d4..200af37a948 100644 --- a/test/langtools/jdk/javadoc/doclet/testParamTaglet/TestParamTaglet.java +++ b/test/langtools/jdk/javadoc/doclet/testParamTaglet/TestParamTaglet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, 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 4802275 4967243 8026567 8239804 + * @bug 4802275 4967243 8026567 8239804 8234682 * @summary Make sure param tags are still printed even though they do not * match up with a real parameters. * Make sure inheritDoc cannot be used in an invalid param tag. @@ -48,22 +48,51 @@ public class TestParamTaglet extends JavadocTester { "-sourcepath", testSrc, "pkg"); checkExit(Exit.ERROR); - + checkOutput(Output.OUT, true, + "warning: no @param for param1", + "error: @param name not found", + "warning: @param \"b\" has already been specified"); checkOutput("pkg/C.html", true, - //Regular param tags. + // Regular param tags. """
    Parameters:
    param1 - testing 1 2 3.
    -
    param2 - testing 1 2 3.""", - //Param tags that don't match with any real parameters. +
    param2 - testing 1 2 3.
    + """, + // Param tags that don't match with any real parameters. + // {@inheritDoc} misuse does not cause doclet to throw exception. + // Param is printed with nothing inherited. """
    Parameters:
    p1 - testing 1 2 3.
    -
    p2 - testing 1 2 3.""", - //{@inherit} doc misuse does not cause doclet to throw exception. - // Param is printed with nothing inherited. - //XXX: in the future when Configuration is available during doc inheritence, - //print a warning for this mistake. - "inheritBug -"); +
    p2 - testing 1 2 3.
    +
    inheritBug -
    + """, + """ +
    Parameters:
    +
    i - an int
    +
    d - a double
    +
    b - a boolean
    +
    x - does not exist
    +
    x - duplicate
    +
    b - another duplicate
    + """, + """ +
    Type Parameters:
    +
    T2 - type 2
    +
    Parameters:
    +
    t1 - param 1
    +
    t3 - param 3
    + """); + checkOutput("pkg/C.Point.html", true, + """ +
    Record Components:
    +
    y - the y coordinate
    + """); + checkOutput("pkg/C.Nested.html", true, + """ +
    Type Parameters:
    +
    T1 - type 1
    + """); } } diff --git a/test/langtools/jdk/javadoc/doclet/testParamTaglet/pkg/C.java b/test/langtools/jdk/javadoc/doclet/testParamTaglet/pkg/C.java index a50a8d7c6b9..ca5bda9eb60 100644 --- a/test/langtools/jdk/javadoc/doclet/testParamTaglet/pkg/C.java +++ b/test/langtools/jdk/javadoc/doclet/testParamTaglet/pkg/C.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,6 +36,42 @@ public class C extends Parent { * @param p2 testing 1 2 3. * @param inheritBug {@inheritDoc} */ + @Override public void nonMatchingParams(int param1, int param2) {} + /** + * Overriding method with missing/additional/duplicate param tags in non-declaration order. + * + * @param x does not exist + * @param b a boolean + * @param i an int + * @param x duplicate + * @param b another duplicate + */ + @Override + public void unorderedParams(int i, double d, boolean b) {} + + /** + * Generic method with mixed/missing param tags. + * + * @param t1 param 1 + * @param type 2 + * @param t3 param 3 + */ + public static void genericMethod(T1 t1, T2 t2, T3 t3) {} + + /** + * A partially documented point. + * + * @param y the y coordinate + */ + public static record Point(int x, int y) {} + + /** + * Generic class with missing param tags. + * + * @param type 1 + */ + public static class Nested {} + } diff --git a/test/langtools/jdk/javadoc/doclet/testParamTaglet/pkg/Parent.java b/test/langtools/jdk/javadoc/doclet/testParamTaglet/pkg/Parent.java index f0b380b19bd..133c7038cb5 100644 --- a/test/langtools/jdk/javadoc/doclet/testParamTaglet/pkg/Parent.java +++ b/test/langtools/jdk/javadoc/doclet/testParamTaglet/pkg/Parent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,4 +29,11 @@ public class Parent { * Just a dummy method that is here for inheritDoc testing purposes. */ public void nonMatchingParams(int param1, int param2) {} + + /** + * Base method with partially documented params. + * + * @param d a double + */ + public void unorderedParams(int i, double d, boolean b) {} } -- GitLab From 0ea2b39035f1b535a53770379c94ae43f0ddb8b6 Mon Sep 17 00:00:00 2001 From: Xue-Lei Andrew Fan Date: Thu, 20 Jan 2022 16:50:17 +0000 Subject: [PATCH 229/564] 8280363: Minor correction of ALPN specification in SSLParameters Reviewed-by: dfuchs, mullan --- src/java.base/share/classes/javax/net/ssl/SSLParameters.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java.base/share/classes/javax/net/ssl/SSLParameters.java b/src/java.base/share/classes/javax/net/ssl/SSLParameters.java index b156a8a5dac..ae1889198bf 100644 --- a/src/java.base/share/classes/javax/net/ssl/SSLParameters.java +++ b/src/java.base/share/classes/javax/net/ssl/SSLParameters.java @@ -617,7 +617,7 @@ public class SSLParameters { * * @return a non-null, possibly zero-length array of application protocol * {@code String}s. The array is ordered based on protocol - * preference, with {@code protocols[0]} being the most preferred. + * preference, with the first entry being the most preferred. * @see #setApplicationProtocols * @since 9 */ -- GitLab From 9636502658c0844c5790cf37af4b15163bf9fa61 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Thu, 20 Jan 2022 17:18:54 +0000 Subject: [PATCH 230/564] 8279008: G1: Calculate BOT threshold on-the-fly during Object Copy phase Reviewed-by: tschatzl, sjohanss --- src/hotspot/share/gc/g1/g1Allocator.cpp | 6 +-- src/hotspot/share/gc/g1/g1Allocator.hpp | 26 ----------- .../share/gc/g1/g1Allocator.inline.hpp | 45 ------------------- .../share/gc/g1/g1BlockOffsetTable.hpp | 3 +- .../share/gc/g1/g1BlockOffsetTable.inline.hpp | 13 +----- .../share/gc/g1/g1ParScanThreadState.cpp | 11 +++-- .../share/gc/g1/g1ParScanThreadState.hpp | 2 + src/hotspot/share/gc/g1/heapRegion.cpp | 2 +- src/hotspot/share/gc/g1/heapRegion.hpp | 9 +--- src/hotspot/share/gc/g1/heapRegion.inline.hpp | 37 +++++++-------- src/hotspot/share/gc/shared/plab.hpp | 2 +- 11 files changed, 33 insertions(+), 123 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1Allocator.cpp b/src/hotspot/share/gc/g1/g1Allocator.cpp index 7a6cb0a499d..f83ae9b52d3 100644 --- a/src/hotspot/share/gc/g1/g1Allocator.cpp +++ b/src/hotspot/share/gc/g1/g1Allocator.cpp @@ -301,10 +301,7 @@ G1PLABAllocator::G1PLABAllocator(G1Allocator* allocator) : _alloc_buffers[state] = NEW_C_HEAP_ARRAY(PLAB*, length, mtGC); size_t word_sz = _g1h->desired_plab_sz(state); for (uint node_index = 0; node_index < length; node_index++) { - // Specialized PLABs for old that handle BOT updates for object allocations. - _alloc_buffers[state][node_index] = (state == G1HeapRegionAttr::Old) - ? new G1BotUpdatingPLAB(word_sz) - : new PLAB(word_sz); + _alloc_buffers[state][node_index] = new PLAB(word_sz); } } } @@ -364,7 +361,6 @@ HeapWord* G1PLABAllocator::allocate_direct_or_new_plab(G1HeapRegionAttr dest, // Try direct allocation. HeapWord* result = _allocator->par_allocate_during_gc(dest, word_sz, node_index); if (result != NULL) { - update_bot_for_direct_allocation(dest, result, word_sz); _direct_allocated[dest.type()] += word_sz; } return result; diff --git a/src/hotspot/share/gc/g1/g1Allocator.hpp b/src/hotspot/share/gc/g1/g1Allocator.hpp index 8eea1e0f12b..5014442845a 100644 --- a/src/hotspot/share/gc/g1/g1Allocator.hpp +++ b/src/hotspot/share/gc/g1/g1Allocator.hpp @@ -145,22 +145,6 @@ public: uint node_index); }; -// Specialized PLAB for old generation promotions. For old regions the -// BOT needs to be updated and the relevant data to do this efficiently -// is stored in the PLAB. -class G1BotUpdatingPLAB : public PLAB { - // An object spanning this threshold will cause a BOT update. - HeapWord* _next_bot_threshold; - // The region in which the PLAB resides. - HeapRegion* _region; -public: - G1BotUpdatingPLAB(size_t word_sz) : PLAB(word_sz) { } - // Sets the new PLAB buffer as well as updates the threshold and region. - void set_buf(HeapWord* buf, size_t word_sz) override; - // Updates the BOT if the last allocation crossed the threshold. - inline void update_bot(size_t word_sz); -}; - // Manages the PLABs used during garbage collection. Interface for allocation from PLABs. // Needs to handle multiple contexts, extra alignment in any "survivor" area and some // statistics. @@ -181,18 +165,11 @@ private: inline PLAB* alloc_buffer(G1HeapRegionAttr dest, uint node_index) const; inline PLAB* alloc_buffer(region_type_t dest, uint node_index) const; - // Helpers to do explicit BOT updates for allocations in old generation regions. - void update_bot_for_direct_allocation(G1HeapRegionAttr attr, HeapWord* addr, size_t size); - // Returns the number of allocation buffers for the given dest. // There is only 1 buffer for Old while Young may have multiple buffers depending on // active NUMA nodes. inline uint alloc_buffers_length(region_type_t dest) const; - // Returns if BOT updates are needed for the given destinaion. Currently we only have - // two destinations and BOT updates are only needed for the old generation. - inline bool needs_bot_update(G1HeapRegionAttr dest) const; - bool may_throw_away_buffer(size_t const allocation_word_sz, size_t const buffer_size) const; public: G1PLABAllocator(G1Allocator* allocator); @@ -221,9 +198,6 @@ public: bool* refill_failed, uint node_index); - // Update the BOT for the last PLAB allocation. - inline void update_bot_for_plab_allocation(G1HeapRegionAttr dest, size_t word_sz, uint node_index); - void undo_allocation(G1HeapRegionAttr dest, HeapWord* obj, size_t word_sz, uint node_index); }; diff --git a/src/hotspot/share/gc/g1/g1Allocator.inline.hpp b/src/hotspot/share/gc/g1/g1Allocator.inline.hpp index 82223a75ad4..42d6a547257 100644 --- a/src/hotspot/share/gc/g1/g1Allocator.inline.hpp +++ b/src/hotspot/share/gc/g1/g1Allocator.inline.hpp @@ -133,49 +133,4 @@ inline HeapWord* G1PLABAllocator::allocate(G1HeapRegionAttr dest, return allocate_direct_or_new_plab(dest, word_sz, refill_failed, node_index); } -inline bool G1PLABAllocator::needs_bot_update(G1HeapRegionAttr dest) const { - return dest.is_old(); -} - -inline void G1PLABAllocator::update_bot_for_direct_allocation(G1HeapRegionAttr attr, HeapWord* addr, size_t size) { - if (!needs_bot_update(attr)) { - return; - } - - // Out of PLAB allocations in an old generation region. Update BOT. - HeapRegion* region = _g1h->heap_region_containing(addr); - region->update_bot_at(addr, size); -} - -inline void G1PLABAllocator::update_bot_for_plab_allocation(G1HeapRegionAttr dest, size_t word_sz, uint node_index) { - assert(needs_bot_update(dest), "Wrong destination: %s", dest.get_type_str()); - G1BotUpdatingPLAB* plab = static_cast(alloc_buffer(dest, node_index)); - plab->update_bot(word_sz); -} - -inline void G1BotUpdatingPLAB::set_buf(HeapWord* buf, size_t word_sz) { - PLAB::set_buf(buf, word_sz); - // Update the region and threshold to allow efficient BOT updates. - _region = G1CollectedHeap::heap()->heap_region_containing(buf); - _next_bot_threshold = _region->bot_threshold_for_addr(buf); -} - -inline void G1BotUpdatingPLAB::update_bot(size_t word_sz) { - // The last object end is at _top, if it did not cross the - // threshold, there is nothing to do. - if (_top <= _next_bot_threshold) { - return; - } - - HeapWord* obj_start = _top - word_sz; - assert(contains(obj_start), - "Object start outside PLAB. bottom: " PTR_FORMAT " object: " PTR_FORMAT, - p2i(_bottom), p2i(obj_start)); - assert(obj_start <= _next_bot_threshold, - "Object start not below or at threshold. threshold: " PTR_FORMAT " object: " PTR_FORMAT, - p2i(_next_bot_threshold), p2i(obj_start)); - - _region->update_bot_crossing_threshold(&_next_bot_threshold, obj_start, _top); -} - #endif // SHARE_GC_G1_G1ALLOCATOR_INLINE_HPP diff --git a/src/hotspot/share/gc/g1/g1BlockOffsetTable.hpp b/src/hotspot/share/gc/g1/g1BlockOffsetTable.hpp index 81317721330..505c528da9f 100644 --- a/src/hotspot/share/gc/g1/g1BlockOffsetTable.hpp +++ b/src/hotspot/share/gc/g1/g1BlockOffsetTable.hpp @@ -160,8 +160,7 @@ public: void verify() const; - // Given an address calculate where the next threshold needing an update is. - inline HeapWord* threshold_for_addr(const void* addr); + inline HeapWord* align_up_by_card_size(HeapWord* const addr) const; // Returns the address of the start of the block containing "addr", or // else "null" if it is covered by no block. (May have side effects, diff --git a/src/hotspot/share/gc/g1/g1BlockOffsetTable.inline.hpp b/src/hotspot/share/gc/g1/g1BlockOffsetTable.inline.hpp index 9652c600b8c..7ae313f2f70 100644 --- a/src/hotspot/share/gc/g1/g1BlockOffsetTable.inline.hpp +++ b/src/hotspot/share/gc/g1/g1BlockOffsetTable.inline.hpp @@ -31,18 +31,9 @@ #include "gc/shared/memset_with_concurrent_readers.hpp" #include "runtime/atomic.hpp" -inline HeapWord* G1BlockOffsetTablePart::threshold_for_addr(const void* addr) { +inline HeapWord* G1BlockOffsetTablePart::align_up_by_card_size(HeapWord* const addr) const { assert(addr >= _hr->bottom() && addr < _hr->top(), "invalid address"); - size_t index = _bot->index_for(addr); - HeapWord* card_boundary = _bot->address_for_index(index); - // Address at card boundary, use as threshold. - if (card_boundary == addr) { - return card_boundary; - } - - // Calculate next threshold. - HeapWord* threshold = card_boundary + BOTConstants::card_size_in_words(); - return threshold; + return align_up(addr, BOTConstants::card_size()); } inline HeapWord* G1BlockOffsetTablePart::block_start(const void* addr) { diff --git a/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp b/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp index 2bfb36b1511..f2889e78779 100644 --- a/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp +++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp @@ -434,6 +434,12 @@ void G1ParScanThreadState::undo_allocation(G1HeapRegionAttr dest_attr, _plab_allocator->undo_allocation(dest_attr, obj_ptr, word_sz, node_index); } +void G1ParScanThreadState::update_bot_after_copying(oop obj, size_t word_sz) { + HeapWord* obj_start = cast_from_oop(obj); + HeapRegion* region = _g1h->heap_region_containing(obj_start); + region->update_bot_if_crossing_boundary(obj_start, word_sz); +} + // Private inline function, for direct internal use and providing the // implementation of the public not-inline function. MAYBE_INLINE_EVACUATION @@ -503,10 +509,7 @@ oop G1ParScanThreadState::do_copy_to_survivor_space(G1HeapRegionAttr const regio } _age_table.add(age, word_sz); } else { - // Currently we only have two destinations and we only need BOT updates for - // old. If the current allocation was done outside the PLAB this call will - // have no effect since the _top of the PLAB has not changed. - _plab_allocator->update_bot_for_plab_allocation(dest_attr, word_sz, node_index); + update_bot_after_copying(obj, word_sz); } // Most objects are not arrays, so do one array check rather than diff --git a/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp b/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp index f40ca519268..dab2d718b7c 100644 --- a/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp +++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp @@ -169,6 +169,8 @@ private: size_t word_sz, uint node_index); + void update_bot_after_copying(oop obj, size_t word_sz); + oop do_copy_to_survivor_space(G1HeapRegionAttr region_attr, oop obj, markWord old_mark); diff --git a/src/hotspot/share/gc/g1/heapRegion.cpp b/src/hotspot/share/gc/g1/heapRegion.cpp index e2d48b0f852..4994070eaca 100644 --- a/src/hotspot/share/gc/g1/heapRegion.cpp +++ b/src/hotspot/share/gc/g1/heapRegion.cpp @@ -810,7 +810,7 @@ void HeapRegion::object_iterate(ObjectClosure* blk) { void HeapRegion::fill_with_dummy_object(HeapWord* address, size_t word_size, bool zap) { // Keep the BOT in sync for old generation regions. if (is_old()) { - update_bot_at(address, word_size); + update_bot_if_crossing_boundary(address, word_size); } // Fill in the object. CollectedHeap::fill_with_object(address, word_size, zap); diff --git a/src/hotspot/share/gc/g1/heapRegion.hpp b/src/hotspot/share/gc/g1/heapRegion.hpp index 96cd44a3317..782de66a1cb 100644 --- a/src/hotspot/share/gc/g1/heapRegion.hpp +++ b/src/hotspot/share/gc/g1/heapRegion.hpp @@ -162,13 +162,8 @@ public: inline HeapWord* allocate(size_t word_size); inline HeapWord* allocate(size_t min_word_size, size_t desired_word_size, size_t* actual_size); - // Update the BOT for the given address if it crosses the next - // BOT threshold at or after obj_start. - inline void update_bot_at(HeapWord* obj_start, size_t obj_size); - // Update BOT at the given threshold for the given object. The - // given object must cross the threshold. - inline void update_bot_crossing_threshold(HeapWord** threshold, HeapWord* obj_start, HeapWord* obj_end); - inline HeapWord* bot_threshold_for_addr(const void* addr); + // Update BOT if this obj is the first entering a new card (i.e. crossing the card boundary). + inline void update_bot_if_crossing_boundary(HeapWord* obj_start, size_t obj_size); // Full GC support methods. diff --git a/src/hotspot/share/gc/g1/heapRegion.inline.hpp b/src/hotspot/share/gc/g1/heapRegion.inline.hpp index 69da12e55bd..2a47d92a475 100644 --- a/src/hotspot/share/gc/g1/heapRegion.inline.hpp +++ b/src/hotspot/share/gc/g1/heapRegion.inline.hpp @@ -231,32 +231,27 @@ inline HeapWord* HeapRegion::allocate(size_t min_word_size, return allocate_impl(min_word_size, desired_word_size, actual_word_size); } -inline HeapWord* HeapRegion::bot_threshold_for_addr(const void* addr) { - HeapWord* threshold = _bot_part.threshold_for_addr(addr); - assert(threshold >= addr, - "threshold must be at or after given address. " PTR_FORMAT " >= " PTR_FORMAT, - p2i(threshold), p2i(addr)); - assert(is_old(), - "Should only calculate BOT threshold for old regions. addr: " PTR_FORMAT " region:" HR_FORMAT, - p2i(addr), HR_FORMAT_PARAMS(this)); - return threshold; -} - -inline void HeapRegion::update_bot_crossing_threshold(HeapWord** threshold, HeapWord* obj_start, HeapWord* obj_end) { +inline void HeapRegion::update_bot_if_crossing_boundary(HeapWord* obj_start, size_t obj_size) { assert(is_old(), "should only do BOT updates for old regions"); + + HeapWord* obj_end = obj_start + obj_size; + assert(is_in(obj_start), "obj_start must be in this region: " HR_FORMAT - " obj_start " PTR_FORMAT " obj_end " PTR_FORMAT " threshold " PTR_FORMAT, + " obj_start " PTR_FORMAT " obj_end " PTR_FORMAT, HR_FORMAT_PARAMS(this), - p2i(obj_start), p2i(obj_end), p2i(*threshold)); - _bot_part.alloc_block_work(threshold, obj_start, obj_end); -} + p2i(obj_start), p2i(obj_end)); + + HeapWord* cur_card_boundary = _bot_part.align_up_by_card_size(obj_start); -inline void HeapRegion::update_bot_at(HeapWord* obj_start, size_t obj_size) { - HeapWord* threshold = bot_threshold_for_addr(obj_start); - HeapWord* obj_end = obj_start + obj_size; + // strictly greater-than + bool cross_card_boundary = (obj_end > cur_card_boundary); - if (obj_end > threshold) { - update_bot_crossing_threshold(&threshold, obj_start, obj_end); + if (cross_card_boundary) { + // Creating a dummy variable inside this `if` as the arg of `&`; this + // avoids unnecessary loads in the assembly code on the fast path (the + // bot-not-updating case). + HeapWord* dummy = cur_card_boundary; + _bot_part.alloc_block_work(&dummy, obj_start, obj_end); } } diff --git a/src/hotspot/share/gc/shared/plab.hpp b/src/hotspot/share/gc/shared/plab.hpp index 5599ba9a8fd..ebe788122ba 100644 --- a/src/hotspot/share/gc/shared/plab.hpp +++ b/src/hotspot/share/gc/shared/plab.hpp @@ -116,7 +116,7 @@ public: } // Sets the space of the buffer to be [buf, space+word_sz()). - virtual void set_buf(HeapWord* buf, size_t new_word_sz) { + void set_buf(HeapWord* buf, size_t new_word_sz) { assert(new_word_sz > AlignmentReserve, "Too small"); _word_sz = new_word_sz; -- GitLab From d48279b0bf9ee9d18ac764776a655c44fa020509 Mon Sep 17 00:00:00 2001 From: Yumin Qi Date: Thu, 20 Jan 2022 17:52:49 +0000 Subject: [PATCH 231/564] 8279009: CDS crashes when the source of an InstanceKlass is NULL Reviewed-by: iklam, ccheung --- src/hotspot/share/cds/classListWriter.cpp | 30 ++- .../ClassListWithCustomClassNoSource.java | 85 +++++++ .../cds/appcds/ClassSpecializerTestApp.java | 63 +++++ .../cds/appcds/CommandLineFlagCombo.java | 49 +++- .../cds/appcds/TestDumpClassListSource.java | 233 ++++++++++++++++++ 5 files changed, 447 insertions(+), 13 deletions(-) create mode 100644 test/hotspot/jtreg/runtime/cds/appcds/ClassListWithCustomClassNoSource.java create mode 100644 test/hotspot/jtreg/runtime/cds/appcds/ClassSpecializerTestApp.java create mode 100644 test/hotspot/jtreg/runtime/cds/appcds/TestDumpClassListSource.java diff --git a/src/hotspot/share/cds/classListWriter.cpp b/src/hotspot/share/cds/classListWriter.cpp index 6750a5d4cac..2ff647559c3 100644 --- a/src/hotspot/share/cds/classListWriter.cpp +++ b/src/hotspot/share/cds/classListWriter.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022, 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 @@ -59,11 +59,6 @@ void ClassListWriter::write(const InstanceKlass* k, const ClassFileStream* cfs) return; } - // filter out java/lang/invoke/BoundMethodHandle$Species.... - if (cfs != NULL && strcmp(cfs->source(), "_ClassSpecializer_generateConcreteSpeciesCode") == 0) { - return; - } - ClassListWriter w; write_to_stream(k, w.stream(), cfs); } @@ -107,10 +102,21 @@ void ClassListWriter::handle_class_unloading(const InstanceKlass* klass) { void ClassListWriter::write_to_stream(const InstanceKlass* k, outputStream* stream, const ClassFileStream* cfs) { assert_locked(); - ClassLoaderData* loader_data = k->class_loader_data(); - if (!SystemDictionaryShared::is_builtin_loader(loader_data)) { - if (cfs == NULL || strncmp(cfs->source(), "file:", 5) != 0) { + ClassLoaderData* loader_data = k->class_loader_data(); + bool is_builtin_loader = SystemDictionaryShared::is_builtin_loader(loader_data); + if (!is_builtin_loader) { + // class may be loaded from shared archive + if (!k->is_shared()) { + if (cfs == nullptr || cfs->source() == nullptr) { + // CDS static dump only handles unregistered class with known source. + return; + } + if (strncmp(cfs->source(), "file:", 5) != 0) { + return; + } + } else { + // Shared unregistered classes are skipped since their real source are not recorded in shared space. return; } if (!SystemDictionaryShared::add_unregistered_class(Thread::current(), (InstanceKlass*)k)) { @@ -118,6 +124,10 @@ void ClassListWriter::write_to_stream(const InstanceKlass* k, outputStream* stre } } + // filter out java/lang/invoke/BoundMethodHandle$Species... + if (cfs != nullptr && cfs->source() != nullptr && strcmp(cfs->source(), "_ClassSpecializer_generateConcreteSpeciesCode") == 0) { + return; + } { InstanceKlass* super = k->java_super(); @@ -145,7 +155,7 @@ void ClassListWriter::write_to_stream(const InstanceKlass* k, outputStream* stre ResourceMark rm; stream->print("%s id: %d", k->name()->as_C_string(), get_id(k)); - if (!SystemDictionaryShared::is_builtin_loader(loader_data)) { + if (!is_builtin_loader) { InstanceKlass* super = k->java_super(); assert(super != NULL, "must be"); stream->print(" super: %d", get_id(super)); diff --git a/test/hotspot/jtreg/runtime/cds/appcds/ClassListWithCustomClassNoSource.java b/test/hotspot/jtreg/runtime/cds/appcds/ClassListWithCustomClassNoSource.java new file mode 100644 index 00000000000..4e5c52402a0 --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/ClassListWithCustomClassNoSource.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2022, 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.io.File; +import java.net.URL; +import java.net.URLClassLoader; +import java.security.ProtectionDomain; + + +public class ClassListWithCustomClassNoSource { + private static byte[] helloBytes; + private static final String HELLO = "Hello"; + static class CL extends ClassLoader { + private ProtectionDomain pd; + public CL(String name, ClassLoader parent, ProtectionDomain protD) { + super(name, parent); + pd = protD; + } + + @Override + protected Class findClass(String name) throws ClassNotFoundException { + if (pd == null) { + pd = new ProtectionDomain(null, null); + } + return defineClass(name, helloBytes, 0, helloBytes.length, pd); + } + } + + public static void main(String[] args) throws Exception { + if (args.length != 1) { + throw new RuntimeException("Invalid arg, Use 1, 2, or 3"); + } + + ClassLoader thisLoader = ClassListWithCustomClassNoSource.class.getClassLoader(); + helloBytes = thisLoader.getResourceAsStream(HELLO + ".class").readAllBytes(); + + switch(args[0]) { + case "1": + Class cls1 = (new CL("HelloLoader", null, null)).loadClass(HELLO); + System.out.println(HELLO + " was successfully loaded by " + cls1.getClassLoader().getName()); + break; + case "2": + ProtectionDomain p = ClassListWithCustomClassNoSource.class.getProtectionDomain(); + Class cls2 = (new CL("HelloLoader", null, p)).loadClass(HELLO); + System.out.println(HELLO + " was successfully loaded by " + cls2.getClassLoader().getName()); + break; + case "3": + URL url = ClassListWithCustomClassNoSource.class.getProtectionDomain().getCodeSource().getLocation(); + URLClassLoader urlLoader = new URLClassLoader("HelloClassLoader", new URL[] {url}, null); + Class cls = urlLoader.loadClass(HELLO); + if (cls != null) { + System.out.println(HELLO + " was loaded by " + cls.getClassLoader().getName()); + if (urlLoader != cls.getClassLoader()) { + System.out.println(HELLO + " was not loaded by " + urlLoader.getName()); + } + } else { + System.out.println(HELLO + " is not loaded"); + } + break; + default: + throw new RuntimeException("Should have one argument, 1, 2 or 3"); + } + } +} diff --git a/test/hotspot/jtreg/runtime/cds/appcds/ClassSpecializerTestApp.java b/test/hotspot/jtreg/runtime/cds/appcds/ClassSpecializerTestApp.java new file mode 100644 index 00000000000..7b9363e8c8f --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/ClassSpecializerTestApp.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2022, 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.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; + +// When this class is executed, the following classes will be generated by +// java.lang.invoke.ClassSpecializer with the code source +// "_ClassSpecializer_generateConcreteSpeciesCode". +// +// - java.lang.invoke.BoundMethodHandle$Species_LFDIIL +// - java.lang.invoke.BoundMethodHandle$Species_LFDIILJ +// - java.lang.invoke.BoundMethodHandle$Species_LFDIILJD +// - ... +// +// The TestDumpClassListSource test case checks that these classes are not +// written into the classlist, as they cannot be handled by -Xshare:dump +public class ClassSpecializerTestApp { + public static void main(String args[]) throws Throwable { + + MethodHandles.Lookup lookup = MethodHandles.lookup(); + MethodType mt = MethodType.methodType(void.class, float.class, double.class, int.class, + boolean.class, Object.class, long.class, double.class); + MethodHandle mh = lookup.findStatic(ClassSpecializerTestApp.class, "callme", mt); + invoke(mh, 4.0f, 5.0, 6, true, null, 7L, 8.0); + } + + private static Object invoke(MethodHandle mh, Object ... args) throws Throwable { + try { + for (Object o : args) { + mh = MethodHandles.insertArguments(mh, 0, o); + } + return mh.invoke(); + } catch (Throwable t) { + System.out.println("Failed to find, link and/or invoke " + mh.toString() + ": " + t.getMessage()); + throw t; + } + } + + private static void callme(float f, double d, int i, boolean b, Object o, long l, double d2) {} +} diff --git a/test/hotspot/jtreg/runtime/cds/appcds/CommandLineFlagCombo.java b/test/hotspot/jtreg/runtime/cds/appcds/CommandLineFlagCombo.java index 045d286115b..b0f18cd453e 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/CommandLineFlagCombo.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/CommandLineFlagCombo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,8 +38,11 @@ * @run main/othervm/timeout=240 -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. CommandLineFlagCombo */ +import java.io.File; + import jdk.test.lib.BuildHelper; import jdk.test.lib.Platform; +import jdk.test.lib.process.ProcessTools; import jdk.test.lib.process.OutputAnalyzer; import sun.hotspot.code.Compiler; @@ -47,6 +50,7 @@ import sun.hotspot.WhiteBox; public class CommandLineFlagCombo { + private static String HELLO_WORLD = "Hello World"; // shared base address test table private static final String[] testTable = { "-XX:+UseG1GC", "-XX:+UseSerialGC", "-XX:+UseParallelGC", @@ -83,7 +87,7 @@ public class CommandLineFlagCombo { if ((TestCommon.isDynamicArchive() && !testEntry.contains("ObjectAlignmentInBytes")) || !TestCommon.isDynamicArchive()) { OutputAnalyzer execOutput = TestCommon.exec(appJar, testEntry, "Hello"); - TestCommon.checkExec(execOutput, "Hello World"); + TestCommon.checkExec(execOutput, HELLO_WORLD); } } @@ -105,8 +109,10 @@ public class CommandLineFlagCombo { TestCommon.checkDump(dumpOutput, "Loading classes to share"); OutputAnalyzer execOutput = TestCommon.exec(appJar, run_g1Flag, run_serialFlag, "Hello"); - TestCommon.checkExec(execOutput, "Hello World"); + TestCommon.checkExec(execOutput, HELLO_WORLD); } + + testExtraCase(appJar, classList); } private static boolean skipTestCase(String testEntry) throws Exception { @@ -128,4 +134,41 @@ public class CommandLineFlagCombo { } return false; } + + // { -Xshare:dump, -XX:ArchiveClassesAtExit} x { -XX:DumpLoadedClassList } + private static void testExtraCase(String jarFile, String[] classList) throws Exception { + // 1. -Xshare:dump -XX:-XX:DumpLoadedClassFile + String dumpedListName = "tmpClassList.list"; + File listFile = new File(dumpedListName); + if (listFile.exists()) { + listFile.delete(); + } + OutputAnalyzer dumpOutput = TestCommon.dump(jarFile, classList, "-XX:DumpLoadedClassList=" + dumpedListName); + TestCommon.checkDump(dumpOutput, "Loading classes to share"); + if (!listFile.exists()) { + throw new RuntimeException("ClassList file " + dumpedListName + " should be created"); + } + + // 2. -XX:ArchiveClassesAtExit -XX:DumpLoadedClassFile + String dynName = "tmpDyn.jsa"; + File dynFile = new File(dynName); + if (dynFile.exists()) { + dynFile.delete(); + } + if (listFile.exists()) { + listFile.delete(); + } + String[] args = new String[] { + "-cp", jarFile, "-XX:ArchiveClassesAtExit=" + dynName, "-XX:DumpLoadedClassList=" + dumpedListName, "Hello"}; + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(args); + OutputAnalyzer output = TestCommon.executeAndLog(pb, "combo"); + output.shouldHaveExitValue(0) + .shouldContain(HELLO_WORLD); + if (!dynFile.exists()) { + throw new RuntimeException("Dynamic archive file " + dynName + " should be created"); + } + if (!listFile.exists()) { + throw new RuntimeException("ClassList file " + dumpedListName + " should be created"); + } + } } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/TestDumpClassListSource.java b/test/hotspot/jtreg/runtime/cds/appcds/TestDumpClassListSource.java new file mode 100644 index 00000000000..1b8d73a468d --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/TestDumpClassListSource.java @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2022, 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 + * @key randomness + * @summary test dynamic dump meanwhile output loaded class list + * @bug 8279009 8275084 + * @requires vm.cds + * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds + * @compile test-classes/Hello.java ClassSpecializerTestApp.java ClassListWithCustomClassNoSource.java + * @run main/othervm TestDumpClassListSource + */ + +/* Test two senarios: + * 1. ClassSpecializerTestApp.java: + * Test case for bug 8275084, make sure the filtering of source class to + * dumped class list. + * 2. ClassListWithCustomClassNoSource: test custom class loader + * 2.1 class loaded without source. + * 2.2 class loaded with ProtectionDomain set as same as main class. + * 2.3 class loaded by custom loader from shared space. + */ + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.File; + +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.cds.CDSTestUtils; + +public class TestDumpClassListSource { + private static final boolean EXPECT_MATCH = true; + private static final boolean EXPECT_NOMATCH = !EXPECT_MATCH; + + private static void checkMatch(String file, String regexp, boolean expectMatch, String exceptionMessage) throws Exception { + String listData = new String(Files.readAllBytes(Paths.get(file))); + Pattern pattern = Pattern.compile(regexp, Pattern.MULTILINE); + Matcher matcher = pattern.matcher(listData); + boolean found = matcher.find(); + if (expectMatch) { + if (!found) { + throw new RuntimeException(exceptionMessage); + } + } else { + if (found) { + throw new RuntimeException(exceptionMessage); + } + } + } + + static final String mainInvokeClass = "ClassSpecializerTestApp"; + static final String mainCutomClass = "ClassListWithCustomClassNoSource"; + static final String sourceTarget = "_ClassSpecializer_generateConcreteSpeciesCode"; + + private static void checkFileExistence(String type, File file) throws Exception { + if (!file.exists()) { + throw new RuntimeException(type + " file " + file.getName() + " should be created"); + } + } + + public static void main(String[] args) throws Exception { + String listFileName = "test-classlist.list"; + String archiveName = "test-dynamic.jsa"; + String jarFile = JarBuilder.build("test-hello", "ClassSpecializerTestApp", "ClassListWithCustomClassNoSource", + "ClassListWithCustomClassNoSource$CL", "Hello"); + // 1. Invoke lambda + File fileList = new File(listFileName); + if (fileList.exists()) { + fileList.delete(); + } + File fileArchive = new File(archiveName); + if (fileArchive.exists()) { + fileArchive.delete(); + } + String[] launchArgs = { + "-Xshare:auto", + "-XX:DumpLoadedClassList=" + listFileName, + "-XX:ArchiveClassesAtExit=" + archiveName, + "-Xlog:cds", + "-Xlog:cds+lambda", + "-cp", + jarFile, + mainInvokeClass}; + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(launchArgs); + OutputAnalyzer output = TestCommon.executeAndLog(pb, "invoke-class"); + + checkFileExistence("Archive", fileArchive); + checkFileExistence("ClassList", fileList); + + output.shouldHaveExitValue(0); + checkMatch(listFileName, sourceTarget, EXPECT_NOMATCH, "Failed to filter " + sourceTarget + " in class list file"); + + fileArchive.delete(); + fileList.delete(); + + // 2. Custom loaded class + // 2.1 test in memory class generation without source + launchArgs = new String[] { + "-Xshare:auto", + "-XX:DumpLoadedClassList=" + listFileName, + "-XX:ArchiveClassesAtExit=" + archiveName, + "-Xlog:cds", + "-Xlog:cds+lambda", + "-Xlog:class+path=info", + "-cp", + jarFile, + mainCutomClass, + "1"}; + pb = ProcessTools.createJavaProcessBuilder(launchArgs); + output = TestCommon.executeAndLog(pb, "custom-nosource"); + + checkFileExistence("Archive", fileArchive); + checkFileExistence("ClassList", fileList); + + output.shouldHaveExitValue(0); + checkMatch(listFileName, sourceTarget, EXPECT_NOMATCH, "Failed to filter " + sourceTarget + " in class list file"); + checkMatch(listFileName, "Hello", EXPECT_NOMATCH, "Hello should not be logged in class list file"); + + fileArchive.delete(); + fileList.delete(); + + // 2.2 test in memory class with ProtectionDomain as main class. + // "Hello" will be printed in list file and its source set as main class. + launchArgs = new String[] { + "-Xshare:auto", + "-XX:DumpLoadedClassList=" + listFileName, + "-XX:ArchiveClassesAtExit=" + archiveName, + "-Xlog:cds", + "-Xlog:cds+lambda", + "-Xlog:class+path=info", + "-cp", + jarFile, + mainCutomClass, + "2"}; + pb = ProcessTools.createJavaProcessBuilder(launchArgs); + output = TestCommon.executeAndLog(pb, "custom-nosource"); + + checkFileExistence("Archive", fileArchive); + checkFileExistence("ClassList", fileList); + + output.shouldHaveExitValue(0); + checkMatch(listFileName, sourceTarget, EXPECT_NOMATCH, "Failed to filter " + sourceTarget + " in class list file"); + checkMatch(listFileName, "Hello", EXPECT_MATCH, "Hello should be logged in class list file"); + + fileArchive.delete(); + fileList.delete(); + + // 2.3 class loaded by custom loader from shared space. + // 2.3.1 dump class list + launchArgs = new String[] { + "-XX:DumpLoadedClassList=" + listFileName, + "-cp", + jarFile, + mainCutomClass, + "3"}; + pb = ProcessTools.createJavaProcessBuilder(launchArgs); + output = TestCommon.executeAndLog(pb, "custom-dump-classlist"); + + checkFileExistence("ClassList", fileList); + + checkMatch(listFileName, "Hello id: [0-9]+ super: [0-9]+ source: .*/test-hello.jar", EXPECT_MATCH, + "Class Hello should be printed in classlist"); + // 2.3.2 dump shared archive based on listFileName + String archive = "test-hello.jsa"; + File archiveFile = new File(archive); + if (archiveFile.exists()) { + archiveFile.delete(); + } + launchArgs = new String[] { + "-Xshare:dump", + "-XX:SharedClassListFile=" + listFileName, + "-XX:SharedArchiveFile=" + archive, + "-cp", + jarFile, + mainCutomClass, + "3"}; + pb = ProcessTools.createJavaProcessBuilder(launchArgs); + output = TestCommon.executeAndLog(pb, "custom-dump"); + + checkFileExistence("Archive", archiveFile); + + // 2.3.3 run with the shared archive and -XX:DumpLoadedClassList + // Hello should not be printed out in class list file. + String classList = "new-test-list.list"; + File newFile = new File(classList); + if (newFile.exists()) { + newFile.delete(); + } + launchArgs = new String[] { + "-Xshare:on", + "-XX:SharedArchiveFile=" + archive, + "-XX:DumpLoadedClassList=" + classList, + "-cp", + jarFile, + mainCutomClass, + "3"}; + pb = ProcessTools.createJavaProcessBuilder(launchArgs); + output = TestCommon.executeAndLog(pb, "custom-share"); + + checkFileExistence("ClassList", newFile); + checkMatch(classList, "Hello id: ?", EXPECT_NOMATCH, "Failed to filter custom loaded class Hello from class list"); + } +} -- GitLab From 3419ff7ba70b778906249dd5ab3a91998ca5a864 Mon Sep 17 00:00:00 2001 From: Andrey Turbanov Date: Thu, 20 Jan 2022 18:11:55 +0000 Subject: [PATCH 232/564] 8277535: Remove redundant Stream.distinct()/sorted() steps Reviewed-by: prappo --- .../share/classes/jdk/internal/module/ModulePath.java | 3 +-- .../share/classes/com/sun/tools/jdeps/ModuleDotGraph.java | 3 +-- src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java | 2 -- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/java.base/share/classes/jdk/internal/module/ModulePath.java b/src/java.base/share/classes/jdk/internal/module/ModulePath.java index 47c21ed3b3d..876050ef839 100644 --- a/src/java.base/share/classes/jdk/internal/module/ModulePath.java +++ b/src/java.base/share/classes/jdk/internal/module/ModulePath.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2021, 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 @@ -527,7 +527,6 @@ public class ModulePath implements ModuleFinder { Set packages = classFiles.stream() .map(this::toPackageName) .flatMap(Optional::stream) - .distinct() .collect(Collectors.toSet()); // all packages are exported and open diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleDotGraph.java b/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleDotGraph.java index 21c4d67829c..a23f25be9d2 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleDotGraph.java +++ b/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleDotGraph.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -65,7 +65,6 @@ public class ModuleDotGraph { this(config, config.rootModules().stream() .map(Module::name) - .sorted() .collect(toMap(Function.identity(), mn -> config.resolve(Set.of(mn)))), apiOnly); } diff --git a/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java b/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java index b440e536235..52d6222d5a2 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java +++ b/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java @@ -690,7 +690,6 @@ public class JmodTask { .filter(path -> isResource(path.toString())) .map(path -> toPackageName(path)) .filter(pkg -> pkg.length() > 0) - .distinct() .collect(Collectors.toSet()); } catch (IOException ioe) { throw new UncheckedIOException(ioe); @@ -705,7 +704,6 @@ public class JmodTask { .filter(e -> !e.isDirectory() && isResource(e.getName())) .map(e -> toPackageName(e)) .filter(pkg -> pkg.length() > 0) - .distinct() .collect(Collectors.toSet()); } -- GitLab From 02390c79b1acff1a953d29c6f70623f3b7838698 Mon Sep 17 00:00:00 2001 From: Quan Anh Mai Date: Thu, 20 Jan 2022 18:24:53 +0000 Subject: [PATCH 233/564] 8279282: [vectorapi] Matcher::supports_vector_comparison_unsigned is not needed on x86 Reviewed-by: kvn, sviswanathan, vlivanov --- src/hotspot/cpu/x86/assembler_x86.cpp | 10 +++ src/hotspot/cpu/x86/assembler_x86.hpp | 1 + src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp | 78 ------------------- src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp | 6 -- src/hotspot/cpu/x86/macroAssembler_x86.cpp | 31 ++++++-- src/hotspot/cpu/x86/macroAssembler_x86.hpp | 8 +- src/hotspot/cpu/x86/matcher_x86.hpp | 17 +--- src/hotspot/cpu/x86/x86.ad | 75 ++++++++++++------ 8 files changed, 96 insertions(+), 130 deletions(-) diff --git a/src/hotspot/cpu/x86/assembler_x86.cpp b/src/hotspot/cpu/x86/assembler_x86.cpp index a15ce3119f6..3b1e42f3f95 100644 --- a/src/hotspot/cpu/x86/assembler_x86.cpp +++ b/src/hotspot/cpu/x86/assembler_x86.cpp @@ -2473,6 +2473,16 @@ void Assembler::movddup(XMMRegister dst, XMMRegister src) { emit_int16(0x12, 0xC0 | encode); } +void Assembler::vmovddup(XMMRegister dst, Address src, int vector_len) { + assert(VM_Version::supports_avx(), ""); + InstructionMark im(this); + InstructionAttr attributes(vector_len, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + attributes.set_rex_vex_w_reverted(); + simd_prefix(dst, xnoreg, src, VEX_SIMD_F2, VEX_OPCODE_0F, &attributes); + emit_int8(0x12); + emit_operand(dst, src); +} + void Assembler::kmovbl(KRegister dst, KRegister src) { assert(VM_Version::supports_avx512dq(), ""); InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false); diff --git a/src/hotspot/cpu/x86/assembler_x86.hpp b/src/hotspot/cpu/x86/assembler_x86.hpp index aa08e834853..5a7e595d029 100644 --- a/src/hotspot/cpu/x86/assembler_x86.hpp +++ b/src/hotspot/cpu/x86/assembler_x86.hpp @@ -1467,6 +1467,7 @@ private: void movb(Register dst, Address src); void movddup(XMMRegister dst, XMMRegister src); + void vmovddup(XMMRegister dst, Address src, int vector_len); void kandbl(KRegister dst, KRegister src1, KRegister src2); void kandwl(KRegister dst, KRegister src1, KRegister src2); diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp index 7405e73d4f7..65166197616 100644 --- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp @@ -2192,84 +2192,6 @@ void C2_MacroAssembler::evpcmp(BasicType typ, KRegister kdmask, KRegister ksmask } } -void C2_MacroAssembler::vpcmpu(BasicType typ, XMMRegister dst, XMMRegister src1, XMMRegister src2, ComparisonPredicate comparison, - int vlen_in_bytes, XMMRegister vtmp1, XMMRegister vtmp2, Register scratch) { - int vlen_enc = vector_length_encoding(vlen_in_bytes*2); - switch (typ) { - case T_BYTE: - vpmovzxbw(vtmp1, src1, vlen_enc); - vpmovzxbw(vtmp2, src2, vlen_enc); - vpcmpCCW(dst, vtmp1, vtmp2, comparison, Assembler::W, vlen_enc, scratch); - vpacksswb(dst, dst, dst, vlen_enc); - break; - case T_SHORT: - vpmovzxwd(vtmp1, src1, vlen_enc); - vpmovzxwd(vtmp2, src2, vlen_enc); - vpcmpCCW(dst, vtmp1, vtmp2, comparison, Assembler::D, vlen_enc, scratch); - vpackssdw(dst, dst, dst, vlen_enc); - break; - case T_INT: - vpmovzxdq(vtmp1, src1, vlen_enc); - vpmovzxdq(vtmp2, src2, vlen_enc); - vpcmpCCW(dst, vtmp1, vtmp2, comparison, Assembler::Q, vlen_enc, scratch); - vpermilps(dst, dst, 8, vlen_enc); - break; - default: - assert(false, "Should not reach here"); - } - if (vlen_in_bytes == 16) { - vpermpd(dst, dst, 0x8, vlen_enc); - } -} - -void C2_MacroAssembler::vpcmpu32(BasicType typ, XMMRegister dst, XMMRegister src1, XMMRegister src2, ComparisonPredicate comparison, int vlen_in_bytes, - XMMRegister vtmp1, XMMRegister vtmp2, XMMRegister vtmp3, Register scratch) { - int vlen_enc = vector_length_encoding(vlen_in_bytes); - switch (typ) { - case T_BYTE: - vpmovzxbw(vtmp1, src1, vlen_enc); - vpmovzxbw(vtmp2, src2, vlen_enc); - vpcmpCCW(dst, vtmp1, vtmp2, comparison, Assembler::W, vlen_enc, scratch); - vextracti128(vtmp1, src1, 1); - vextracti128(vtmp2, src2, 1); - vpmovzxbw(vtmp1, vtmp1, vlen_enc); - vpmovzxbw(vtmp2, vtmp2, vlen_enc); - vpcmpCCW(vtmp3, vtmp1, vtmp2, comparison, Assembler::W, vlen_enc, scratch); - vpacksswb(dst, dst, vtmp3, vlen_enc); - vpermpd(dst, dst, 0xd8, vlen_enc); - break; - case T_SHORT: - vpmovzxwd(vtmp1, src1, vlen_enc); - vpmovzxwd(vtmp2, src2, vlen_enc); - vpcmpCCW(dst, vtmp1, vtmp2, comparison, Assembler::D, vlen_enc, scratch); - vextracti128(vtmp1, src1, 1); - vextracti128(vtmp2, src2, 1); - vpmovzxwd(vtmp1, vtmp1, vlen_enc); - vpmovzxwd(vtmp2, vtmp2, vlen_enc); - vpcmpCCW(vtmp3, vtmp1, vtmp2, comparison, Assembler::D, vlen_enc, scratch); - vpackssdw(dst, dst, vtmp3, vlen_enc); - vpermpd(dst, dst, 0xd8, vlen_enc); - break; - case T_INT: - vpmovzxdq(vtmp1, src1, vlen_enc); - vpmovzxdq(vtmp2, src2, vlen_enc); - vpcmpCCW(dst, vtmp1, vtmp2, comparison, Assembler::Q, vlen_enc, scratch); - vpshufd(dst, dst, 8, vlen_enc); - vpermq(dst, dst, 8, vlen_enc); - vextracti128(vtmp1, src1, 1); - vextracti128(vtmp2, src2, 1); - vpmovzxdq(vtmp1, vtmp1, vlen_enc); - vpmovzxdq(vtmp2, vtmp2, vlen_enc); - vpcmpCCW(vtmp3, vtmp1, vtmp2, comparison, Assembler::Q, vlen_enc, scratch); - vpshufd(vtmp3, vtmp3, 8, vlen_enc); - vpermq(vtmp3, vtmp3, 0x80, vlen_enc); - vpblendd(dst, dst, vtmp3, 0xf0, vlen_enc); - break; - default: - assert(false, "Should not reach here"); - } -} - void C2_MacroAssembler::evpblend(BasicType typ, XMMRegister dst, KRegister kmask, XMMRegister src1, XMMRegister src2, bool merge, int vector_len) { switch(typ) { case T_BYTE: diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp index 3a1ad1d27e0..b97c1ed607d 100644 --- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp @@ -146,12 +146,6 @@ public: void load_iota_indices(XMMRegister dst, Register scratch, int vlen_in_bytes); - // vector compare - void vpcmpu(BasicType typ, XMMRegister dst, XMMRegister src1, XMMRegister src2, ComparisonPredicate comparison, int vlen_in_bytes, - XMMRegister vtmp1, XMMRegister vtmp2, Register scratch); - void vpcmpu32(BasicType typ, XMMRegister dst, XMMRegister src1, XMMRegister src2, ComparisonPredicate comparison, int vlen_in_bytes, - XMMRegister vtmp1, XMMRegister vtmp2, XMMRegister vtmp3, Register scratch); - // Reductions for vectors of bytes, shorts, ints, longs, floats, and doubles. // dst = src1 reduce(op, src2) using vtmp as temps diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.cpp b/src/hotspot/cpu/x86/macroAssembler_x86.cpp index 36f48006974..52fa1730586 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -2702,6 +2702,15 @@ void MacroAssembler::movss(XMMRegister dst, AddressLiteral src) { } } +void MacroAssembler::vmovddup(XMMRegister dst, AddressLiteral src, int vector_len, Register rscratch) { + if (reachable(src)) { + Assembler::vmovddup(dst, as_Address(src), vector_len); + } else { + lea(rscratch, src); + Assembler::vmovddup(dst, Address(rscratch, 0), vector_len); + } +} + void MacroAssembler::mulsd(XMMRegister dst, AddressLiteral src) { if (reachable(src)) { Assembler::mulsd(dst, as_Address(src)); @@ -3151,6 +3160,15 @@ void MacroAssembler::vpbroadcastw(XMMRegister dst, XMMRegister src, int vector_l Assembler::vpbroadcastw(dst, src, vector_len); } +void MacroAssembler::vbroadcastsd(XMMRegister dst, AddressLiteral src, int vector_len, Register rscratch) { + if (reachable(src)) { + Assembler::vbroadcastsd(dst, as_Address(src), vector_len); + } else { + lea(rscratch, src); + Assembler::vbroadcastsd(dst, Address(rscratch, 0), vector_len); + } +} + void MacroAssembler::vpcmpeqb(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { assert(((dst->encoding() < 16 && src->encoding() < 16 && nds->encoding() < 16) || VM_Version::supports_avx512vlbw()),"XMM register should be 0-15"); Assembler::vpcmpeqb(dst, nds, src, vector_len); @@ -3219,7 +3237,7 @@ void MacroAssembler::vpcmpCC(XMMRegister dst, XMMRegister nds, XMMRegister src, } } -void MacroAssembler::vpcmpCCW(XMMRegister dst, XMMRegister nds, XMMRegister src, ComparisonPredicate cond, Width width, int vector_len, Register scratch_reg) { +void MacroAssembler::vpcmpCCW(XMMRegister dst, XMMRegister nds, XMMRegister src, XMMRegister xtmp, ComparisonPredicate cond, Width width, int vector_len) { int eq_cond_enc = 0x29; int gt_cond_enc = 0x37; if (width != Assembler::Q) { @@ -3232,15 +3250,18 @@ void MacroAssembler::vpcmpCCW(XMMRegister dst, XMMRegister nds, XMMRegister src, break; case neq: vpcmpCC(dst, nds, src, eq_cond_enc, width, vector_len); - vpxor(dst, dst, ExternalAddress(StubRoutines::x86::vector_all_bits_set()), vector_len, scratch_reg); + vallones(xtmp, vector_len); + vpxor(dst, xtmp, dst, vector_len); break; case le: vpcmpCC(dst, nds, src, gt_cond_enc, width, vector_len); - vpxor(dst, dst, ExternalAddress(StubRoutines::x86::vector_all_bits_set()), vector_len, scratch_reg); + vallones(xtmp, vector_len); + vpxor(dst, xtmp, dst, vector_len); break; case nlt: vpcmpCC(dst, src, nds, gt_cond_enc, width, vector_len); - vpxor(dst, dst, ExternalAddress(StubRoutines::x86::vector_all_bits_set()), vector_len, scratch_reg); + vallones(xtmp, vector_len); + vpxor(dst, xtmp, dst, vector_len); break; case lt: vpcmpCC(dst, src, nds, gt_cond_enc, width, vector_len); diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.hpp b/src/hotspot/cpu/x86/macroAssembler_x86.hpp index 6a7e714be7f..3593874866c 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.hpp @@ -1176,6 +1176,9 @@ public: void movsd(XMMRegister dst, Address src) { Assembler::movsd(dst, src); } void movsd(XMMRegister dst, AddressLiteral src); + using Assembler::vmovddup; + void vmovddup(XMMRegister dst, AddressLiteral src, int vector_len, Register rscratch = rscratch1); + void mulpd(XMMRegister dst, XMMRegister src) { Assembler::mulpd(dst, src); } void mulpd(XMMRegister dst, Address src) { Assembler::mulpd(dst, src); } void mulpd(XMMRegister dst, AddressLiteral src); @@ -1284,6 +1287,9 @@ public: void vpbroadcastw(XMMRegister dst, XMMRegister src, int vector_len); void vpbroadcastw(XMMRegister dst, Address src, int vector_len) { Assembler::vpbroadcastw(dst, src, vector_len); } + using Assembler::vbroadcastsd; + void vbroadcastsd(XMMRegister dst, AddressLiteral src, int vector_len, Register rscratch = rscratch1); + void vpcmpeqb(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len); void vpcmpeqw(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len); @@ -1310,7 +1316,7 @@ public: void evpbroadcast(BasicType type, XMMRegister dst, Register src, int vector_len); // Emit comparison instruction for the specified comparison predicate. - void vpcmpCCW(XMMRegister dst, XMMRegister nds, XMMRegister src, ComparisonPredicate cond, Width width, int vector_len, Register scratch_reg); + void vpcmpCCW(XMMRegister dst, XMMRegister nds, XMMRegister src, XMMRegister xtmp, ComparisonPredicate cond, Width width, int vector_len); void vpcmpCC(XMMRegister dst, XMMRegister nds, XMMRegister src, int cond_encoding, Width width, int vector_len); void vpmovzxbw(XMMRegister dst, Address src, int vector_len); diff --git a/src/hotspot/cpu/x86/matcher_x86.hpp b/src/hotspot/cpu/x86/matcher_x86.hpp index 80ecf783434..61af24cf31c 100644 --- a/src/hotspot/cpu/x86/matcher_x86.hpp +++ b/src/hotspot/cpu/x86/matcher_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022, 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 @@ -166,20 +166,7 @@ // Does the CPU supports vector unsigned comparison instructions? static const bool supports_vector_comparison_unsigned(int vlen, BasicType bt) { - int vlen_in_bytes = vlen * type2aelembytes(bt); - if ((UseAVX > 2) && (VM_Version::supports_avx512vl() || vlen_in_bytes == 64)) - return true; - else { - // instruction set supports only signed comparison - // so need to zero extend to higher integral type and perform comparison - // cannot cast long to higher integral type - // and on avx1 cannot cast 128 bit integral vectors to higher size - - if ((bt != T_LONG) && - ((UseAVX >= 2) || (vlen_in_bytes <= 8))) - return true; - } - return false; + return true; } // Some microarchitectures have mask registers used on vectors diff --git a/src/hotspot/cpu/x86/x86.ad b/src/hotspot/cpu/x86/x86.ad index 6f38e05b90b..917a9ac84b7 100644 --- a/src/hotspot/cpu/x86/x86.ad +++ b/src/hotspot/cpu/x86/x86.ad @@ -2560,6 +2560,18 @@ static inline jlong replicate8_imm(int con, int width) { return val; } +static inline jlong high_bit_set(BasicType bt) { + switch (bt) { + case T_BYTE: return 0x8080808080808080; + case T_SHORT: return 0x8000800080008000; + case T_INT: return 0x8000000080000000; + case T_LONG: return 0x8000000000000000; + default: + ShouldNotReachHere(); + return 0; + } +} + #ifndef PRODUCT void MachNopNode::format(PhaseRegAlloc*, outputStream* st) const { st->print("nop \t# %d bytes pad for loops and calls", _count); @@ -7313,62 +7325,75 @@ instruct evcmpFD(kReg dst, vec src1, vec src2, immI8 cond) %{ ins_pipe( pipe_slow ); %} -instruct vcmp(legVec dst, legVec src1, legVec src2, immI8 cond, rRegP scratch) %{ +instruct vcmp_direct(legVec dst, legVec src1, legVec src2, immI8 cond) %{ predicate(n->bottom_type()->isa_vectmask() == NULL && !is_unsigned_booltest_pred(n->in(2)->get_int()) && Matcher::vector_length_in_bytes(n->in(1)->in(1)) >= 4 && // src1 Matcher::vector_length_in_bytes(n->in(1)->in(1)) <= 32 && // src1 - is_integral_type(Matcher::vector_element_basic_type(n->in(1)->in(1)))); // src1 + is_integral_type(Matcher::vector_element_basic_type(n->in(1)->in(1))) && + (n->in(2)->get_int() == BoolTest::eq || + n->in(2)->get_int() == BoolTest::lt || + n->in(2)->get_int() == BoolTest::gt)); // cond match(Set dst (VectorMaskCmp (Binary src1 src2) cond)); - effect(TEMP scratch); - format %{ "vector_compare $dst,$src1,$src2,$cond\t! using $scratch as TEMP" %} + format %{ "vector_compare $dst,$src1,$src2,$cond\t!" %} ins_encode %{ int vlen_enc = vector_length_encoding(this, $src1); Assembler::ComparisonPredicate cmp = booltest_pred_to_comparison_pred($cond$$constant); Assembler::Width ww = widthForType(Matcher::vector_element_basic_type(this, $src1)); - __ vpcmpCCW($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, cmp, ww, vlen_enc, $scratch$$Register); + __ vpcmpCCW($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, xnoreg, cmp, ww, vlen_enc); %} ins_pipe( pipe_slow ); %} -instruct vcmpu(legVec dst, legVec src1, legVec src2, immI8 cond, legVec vtmp1, legVec vtmp2, rRegP scratch) %{ +instruct vcmp_negate(legVec dst, legVec src1, legVec src2, immI8 cond, legVec xtmp) %{ predicate(n->bottom_type()->isa_vectmask() == NULL && - is_unsigned_booltest_pred(n->in(2)->get_int()) && - Matcher::vector_length_in_bytes(n->in(1)->in(1)) >= 8 && // src1 - Matcher::vector_length_in_bytes(n->in(1)->in(1)) <= 16 && // src1 - is_integral_type(Matcher::vector_element_basic_type(n->in(1)->in(1)))); // src1 + !is_unsigned_booltest_pred(n->in(2)->get_int()) && + Matcher::vector_length_in_bytes(n->in(1)->in(1)) >= 4 && // src1 + Matcher::vector_length_in_bytes(n->in(1)->in(1)) <= 32 && // src1 + is_integral_type(Matcher::vector_element_basic_type(n->in(1)->in(1))) && + (n->in(2)->get_int() == BoolTest::ne || + n->in(2)->get_int() == BoolTest::le || + n->in(2)->get_int() == BoolTest::ge)); // cond match(Set dst (VectorMaskCmp (Binary src1 src2) cond)); - effect(TEMP vtmp1, TEMP vtmp2, TEMP scratch); - format %{ "vector_compareu $dst,$src1,$src2,$cond\t! using $scratch as TEMP" %} + effect(TEMP dst, TEMP xtmp); + format %{ "vector_compare $dst,$src1,$src2,$cond\t! using $xtmp as TEMP" %} ins_encode %{ - int vlen = Matcher::vector_length_in_bytes(this, $src1); + int vlen_enc = vector_length_encoding(this, $src1); Assembler::ComparisonPredicate cmp = booltest_pred_to_comparison_pred($cond$$constant); - BasicType bt = Matcher::vector_element_basic_type(this, $src1); - __ vpcmpu(bt, $dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, cmp, vlen, $vtmp1$$XMMRegister, - $vtmp2$$XMMRegister, $scratch$$Register); + Assembler::Width ww = widthForType(Matcher::vector_element_basic_type(this, $src1)); + __ vpcmpCCW($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, $xtmp$$XMMRegister, cmp, ww, vlen_enc); %} ins_pipe( pipe_slow ); %} -instruct vcmpu32(legVec dst, legVec src1, legVec src2, immI8 cond, legVec vtmp1, legVec vtmp2, legVec vtmp3, rRegP scratch) %{ +instruct vcmpu(legVec dst, legVec src1, legVec src2, immI8 cond, legVec xtmp) %{ predicate(n->bottom_type()->isa_vectmask() == NULL && is_unsigned_booltest_pred(n->in(2)->get_int()) && - Matcher::vector_length_in_bytes(n->in(1)->in(1)) == 32 && // src1 + Matcher::vector_length_in_bytes(n->in(1)->in(1)) >= 4 && // src1 + Matcher::vector_length_in_bytes(n->in(1)->in(1)) <= 32 && // src1 is_integral_type(Matcher::vector_element_basic_type(n->in(1)->in(1)))); // src1 match(Set dst (VectorMaskCmp (Binary src1 src2) cond)); - effect(TEMP dst, TEMP vtmp1, TEMP vtmp2, TEMP vtmp3, TEMP scratch); - format %{ "vector_compareu $dst,$src1,$src2,$cond\t! using $scratch as TEMP" %} + effect(TEMP dst, TEMP xtmp); + format %{ "vector_compareu $dst,$src1,$src2,$cond\t! using $xtmp as TEMP" %} ins_encode %{ - int vlen = Matcher::vector_length_in_bytes(this, $src1); + InternalAddress flip_bit = $constantaddress(high_bit_set(Matcher::vector_element_basic_type(this, $src1))); + int vlen_enc = vector_length_encoding(this, $src1); Assembler::ComparisonPredicate cmp = booltest_pred_to_comparison_pred($cond$$constant); - BasicType bt = Matcher::vector_element_basic_type(this, $src1); - __ vpcmpu32(bt, $dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, cmp, vlen, $vtmp1$$XMMRegister, - $vtmp2$$XMMRegister, $vtmp3$$XMMRegister, $scratch$$Register); + Assembler::Width ww = widthForType(Matcher::vector_element_basic_type(this, $src1)); + + if (vlen_enc == Assembler::AVX_128bit) { + __ vmovddup($xtmp$$XMMRegister, flip_bit, vlen_enc, noreg); + } else { + __ vbroadcastsd($xtmp$$XMMRegister, flip_bit, vlen_enc, noreg); + } + __ vpxor($dst$$XMMRegister, $xtmp$$XMMRegister, $src1$$XMMRegister, vlen_enc); + __ vpxor($xtmp$$XMMRegister, $xtmp$$XMMRegister, $src2$$XMMRegister, vlen_enc); + __ vpcmpCCW($dst$$XMMRegister, $dst$$XMMRegister, $xtmp$$XMMRegister, $xtmp$$XMMRegister, cmp, ww, vlen_enc); %} ins_pipe( pipe_slow ); %} -instruct vcmpu64(vec dst, vec src1, vec src2, immI8 cond, rRegP scratch, kReg ktmp) %{ +instruct vcmp64(vec dst, vec src1, vec src2, immI8 cond, rRegP scratch, kReg ktmp) %{ predicate((n->bottom_type()->isa_vectmask() == NULL && Matcher::vector_length_in_bytes(n->in(1)->in(1)) == 64) && // src1 is_integral_type(Matcher::vector_element_basic_type(n->in(1)->in(1)))); // src1 -- GitLab From 2426d58e592c54de64ebe0f06448d239aeced082 Mon Sep 17 00:00:00 2001 From: Alexey Ivanov Date: Thu, 20 Jan 2022 20:12:11 +0000 Subject: [PATCH 234/564] 8278472: Invalid value set to CANDIDATEFORM structure Reviewed-by: prr, naoto, serb --- .../windows/native/libawt/windows/awt_Component.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp index 8db02f9aee4..2dadde05480 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2022, 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 @@ -3917,11 +3917,11 @@ void AwtComponent::SetCandidateWindow(int iCandType, int x, int y) HIMC hIMC = ImmGetContext(hwnd); if (hIMC) { CANDIDATEFORM cf; - cf.dwStyle = CFS_POINT; + cf.dwStyle = CFS_CANDIDATEPOS; ImmGetCandidateWindow(hIMC, 0, &cf); if (x != cf.ptCurrentPos.x || y != cf.ptCurrentPos.y) { cf.dwIndex = iCandType; - cf.dwStyle = CFS_POINT; + cf.dwStyle = CFS_CANDIDATEPOS; cf.ptCurrentPos = {x, y}; cf.rcArea = {0, 0, 0, 0}; ImmSetCandidateWindow(hIMC, &cf); -- GitLab From 293fb46f7cd28f2a08055e3eb8ec9459d64e9688 Mon Sep 17 00:00:00 2001 From: "Daniel D. Daugherty" Date: Thu, 20 Jan 2022 20:27:37 +0000 Subject: [PATCH 235/564] 8280413: ProblemList jdk/jfr/event/oldobject/TestLargeRootSet.java on all X64 platforms Reviewed-by: azvegint --- test/jdk/ProblemList.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index bf452e7a754..6b54c726277 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -825,7 +825,7 @@ jdk/jfr/event/compiler/TestCodeSweeper.java 8225209 generic- jdk/jfr/event/os/TestThreadContextSwitches.java 8247776 windows-all jdk/jfr/startupargs/TestStartName.java 8214685 windows-x64 jdk/jfr/startupargs/TestStartDuration.java 8214685 windows-x64 -jdk/jfr/event/oldobject/TestLargeRootSet.java 8276333 macosx-x64,windows-x64 +jdk/jfr/event/oldobject/TestLargeRootSet.java 8276333 generic-x64 jdk/jfr/api/consumer/recordingstream/TestOnEvent.java 8255404 linux-x64 ############################################################################ -- GitLab From 35ee0f38c6d5e35fb50a059a189e032df7f7e7c5 Mon Sep 17 00:00:00 2001 From: Yi-Fan Tsai Date: Thu, 20 Jan 2022 23:46:26 +0000 Subject: [PATCH 236/564] 8258814: Compilation logging crashes for thread suspension / debugging tests Reviewed-by: xliu, phh --- src/hotspot/share/compiler/compileBroker.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/hotspot/share/compiler/compileBroker.cpp b/src/hotspot/share/compiler/compileBroker.cpp index e3beed13662..1e2b5e395ba 100644 --- a/src/hotspot/share/compiler/compileBroker.cpp +++ b/src/hotspot/share/compiler/compileBroker.cpp @@ -1970,6 +1970,8 @@ void CompileBroker::compiler_thread_loop() { method->clear_queued_for_compilation(); task->set_failure_reason("compilation is disabled"); } + } else { + task->set_failure_reason("breakpoints are present"); } if (UseDynamicNumberOfCompilerThreads) { -- GitLab From 6352c020c25f2701afb4fabee0cc7fcef2d407fb Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Fri, 21 Jan 2022 03:16:08 +0000 Subject: [PATCH 237/564] 8280401: [sspi] gss_accept_sec_context leaves output_token uninitialized Reviewed-by: valeriep --- .../windows/native/libsspi_bridge/sspi.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/java.security.jgss/windows/native/libsspi_bridge/sspi.cpp b/src/java.security.jgss/windows/native/libsspi_bridge/sspi.cpp index 2f359a84e7b..aa673367607 100644 --- a/src/java.security.jgss/windows/native/libsspi_bridge/sspi.cpp +++ b/src/java.security.jgss/windows/native/libsspi_bridge/sspi.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, 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 @@ -1043,6 +1043,10 @@ gss_accept_sec_context(OM_uint32 *minor_status, { PP(">>>> Calling UNIMPLEMENTED gss_accept_sec_context..."); PP("gss_accept_sec_context is not supported in this initiator-only library"); + if (output_token) { + output_token->length = 0; + output_token->value = NULL; + } return GSS_S_FAILURE; } -- GitLab From 19f877981edf1db41b98c3b370d81c26d6617e49 Mon Sep 17 00:00:00 2001 From: Roland Westrelin Date: Fri, 21 Jan 2022 07:32:08 +0000 Subject: [PATCH 238/564] 8278784: C2: Refactor PhaseIdealLoop::remix_address_expressions() so it operates on longs Reviewed-by: chagedorn, thartmann --- src/hotspot/share/opto/loopnode.hpp | 3 +- src/hotspot/share/opto/loopopts.cpp | 219 ++++++++++-------- src/hotspot/share/opto/mulnode.cpp | 12 + src/hotspot/share/opto/mulnode.hpp | 2 + .../irTests/TestRemixAddressExpressions.java | 106 +++++++++ 5 files changed, 241 insertions(+), 101 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/c2/irTests/TestRemixAddressExpressions.java diff --git a/src/hotspot/share/opto/loopnode.hpp b/src/hotspot/share/opto/loopnode.hpp index 533c93d30d5..f3eaabebae1 100644 --- a/src/hotspot/share/opto/loopnode.hpp +++ b/src/hotspot/share/opto/loopnode.hpp @@ -1449,7 +1449,8 @@ public: // Rework addressing expressions to get the most loop-invariant stuff // moved out. We'd like to do all associative operators, but it's especially // important (common) to do address expressions. - Node *remix_address_expressions( Node *n ); + Node* remix_address_expressions(Node* n); + Node* remix_address_expressions_add_left_shift(Node* n, IdealLoopTree* n_loop, Node* n_ctrl, BasicType bt); // Convert add to muladd to generate MuladdS2I under certain criteria Node * convert_add_to_muladd(Node * n); diff --git a/src/hotspot/share/opto/loopopts.cpp b/src/hotspot/share/opto/loopopts.cpp index 7e4b7254e23..a7c82ad2ee1 100644 --- a/src/hotspot/share/opto/loopopts.cpp +++ b/src/hotspot/share/opto/loopopts.cpp @@ -352,139 +352,158 @@ Node *PhaseIdealLoop::has_local_phi_input( Node *n ) { return n_ctrl; } -//------------------------------remix_address_expressions---------------------- -// Rework addressing expressions to get the most loop-invariant stuff -// moved out. We'd like to do all associative operators, but it's especially -// important (common) to do address expressions. -Node *PhaseIdealLoop::remix_address_expressions( Node *n ) { - if (!has_ctrl(n)) return NULL; - Node *n_ctrl = get_ctrl(n); - IdealLoopTree *n_loop = get_loop(n_ctrl); - - // See if 'n' mixes loop-varying and loop-invariant inputs and - // itself is loop-varying. - - // Only interested in binary ops (and AddP) - if( n->req() < 3 || n->req() > 4 ) return NULL; - - Node *n1_ctrl = get_ctrl(n->in( 1)); - Node *n2_ctrl = get_ctrl(n->in( 2)); - Node *n3_ctrl = get_ctrl(n->in(n->req() == 3 ? 2 : 3)); - IdealLoopTree *n1_loop = get_loop( n1_ctrl ); - IdealLoopTree *n2_loop = get_loop( n2_ctrl ); - IdealLoopTree *n3_loop = get_loop( n3_ctrl ); - - // Does one of my inputs spin in a tighter loop than self? - if( (n_loop->is_member( n1_loop ) && n_loop != n1_loop) || - (n_loop->is_member( n2_loop ) && n_loop != n2_loop) || - (n_loop->is_member( n3_loop ) && n_loop != n3_loop) ) - return NULL; // Leave well enough alone - - // Is at least one of my inputs loop-invariant? - if( n1_loop == n_loop && - n2_loop == n_loop && - n3_loop == n_loop ) - return NULL; // No loop-invariant inputs - - +// Replace expressions like ((V+I) << 2) with (V<<2 + I<<2). +Node* PhaseIdealLoop::remix_address_expressions_add_left_shift(Node* n, IdealLoopTree* n_loop, Node* n_ctrl, BasicType bt) { + assert(bt == T_INT || bt == T_LONG, "only for integers"); int n_op = n->Opcode(); - // Replace expressions like ((V+I) << 2) with (V<<2 + I<<2). - if( n_op == Op_LShiftI ) { + if (n_op == Op_LShift(bt)) { // Scale is loop invariant - Node *scale = n->in(2); - Node *scale_ctrl = get_ctrl(scale); - IdealLoopTree *scale_loop = get_loop(scale_ctrl ); - if( n_loop == scale_loop || !scale_loop->is_member( n_loop ) ) + Node* scale = n->in(2); + Node* scale_ctrl = get_ctrl(scale); + IdealLoopTree* scale_loop = get_loop(scale_ctrl); + if (n_loop == scale_loop || !scale_loop->is_member(n_loop)) { return NULL; - const TypeInt *scale_t = scale->bottom_type()->isa_int(); - if( scale_t && scale_t->is_con() && scale_t->get_con() >= 16 ) + } + const TypeInt* scale_t = scale->bottom_type()->isa_int(); + if (scale_t != NULL && scale_t->is_con() && scale_t->get_con() >= 16) { return NULL; // Dont bother with byte/short masking + } // Add must vary with loop (else shift would be loop-invariant) - Node *add = n->in(1); - Node *add_ctrl = get_ctrl(add); - IdealLoopTree *add_loop = get_loop(add_ctrl); - //assert( n_loop == add_loop, "" ); - if( n_loop != add_loop ) return NULL; // happens w/ evil ZKM loops + Node* add = n->in(1); + Node* add_ctrl = get_ctrl(add); + IdealLoopTree* add_loop = get_loop(add_ctrl); + if (n_loop != add_loop) { + return NULL; // happens w/ evil ZKM loops + } // Convert I-V into I+ (0-V); same for V-I - if( add->Opcode() == Op_SubI && - _igvn.type( add->in(1) ) != TypeInt::ZERO ) { - Node *zero = _igvn.intcon(0); + if (add->Opcode() == Op_Sub(bt) && + _igvn.type(add->in(1)) != TypeInteger::zero(bt)) { + assert(add->Opcode() == Op_SubI || add->Opcode() == Op_SubL, ""); + Node* zero = _igvn.integercon(0, bt); set_ctrl(zero, C->root()); - Node *neg = new SubINode( _igvn.intcon(0), add->in(2) ); - register_new_node( neg, get_ctrl(add->in(2) ) ); - add = new AddINode( add->in(1), neg ); - register_new_node( add, add_ctrl ); + Node* neg = SubNode::make(zero, add->in(2), bt); + register_new_node(neg, get_ctrl(add->in(2))); + add = AddNode::make(add->in(1), neg, bt); + register_new_node(add, add_ctrl); } - if( add->Opcode() != Op_AddI ) return NULL; + if (add->Opcode() != Op_Add(bt)) return NULL; + assert(add->Opcode() == Op_AddI || add->Opcode() == Op_AddL, ""); // See if one add input is loop invariant - Node *add_var = add->in(1); - Node *add_var_ctrl = get_ctrl(add_var); - IdealLoopTree *add_var_loop = get_loop(add_var_ctrl ); - Node *add_invar = add->in(2); - Node *add_invar_ctrl = get_ctrl(add_invar); - IdealLoopTree *add_invar_loop = get_loop(add_invar_ctrl ); - if( add_var_loop == n_loop ) { - } else if( add_invar_loop == n_loop ) { + Node* add_var = add->in(1); + Node* add_var_ctrl = get_ctrl(add_var); + IdealLoopTree* add_var_loop = get_loop(add_var_ctrl); + Node* add_invar = add->in(2); + Node* add_invar_ctrl = get_ctrl(add_invar); + IdealLoopTree* add_invar_loop = get_loop(add_invar_ctrl); + if (add_invar_loop == n_loop) { // Swap to find the invariant part add_invar = add_var; add_invar_ctrl = add_var_ctrl; add_invar_loop = add_var_loop; add_var = add->in(2); - Node *add_var_ctrl = get_ctrl(add_var); - IdealLoopTree *add_var_loop = get_loop(add_var_ctrl ); - } else // Else neither input is loop invariant + } else if (add_var_loop != n_loop) { // Else neither input is loop invariant return NULL; - if( n_loop == add_invar_loop || !add_invar_loop->is_member( n_loop ) ) + } + if (n_loop == add_invar_loop || !add_invar_loop->is_member(n_loop)) { return NULL; // No invariant part of the add? + } // Yes! Reshape address expression! - Node *inv_scale = new LShiftINode( add_invar, scale ); - Node *inv_scale_ctrl = - dom_depth(add_invar_ctrl) > dom_depth(scale_ctrl) ? - add_invar_ctrl : scale_ctrl; - register_new_node( inv_scale, inv_scale_ctrl ); - Node *var_scale = new LShiftINode( add_var, scale ); - register_new_node( var_scale, n_ctrl ); - Node *var_add = new AddINode( var_scale, inv_scale ); - register_new_node( var_add, n_ctrl ); - _igvn.replace_node( n, var_add ); + Node* inv_scale = LShiftNode::make(add_invar, scale, bt); + Node* inv_scale_ctrl = + dom_depth(add_invar_ctrl) > dom_depth(scale_ctrl) ? + add_invar_ctrl : scale_ctrl; + register_new_node(inv_scale, inv_scale_ctrl); + Node* var_scale = LShiftNode::make(add_var, scale, bt); + register_new_node(var_scale, n_ctrl); + Node* var_add = AddNode::make(var_scale, inv_scale, bt); + register_new_node(var_add, n_ctrl); + _igvn.replace_node(n, var_add); return var_add; } + return NULL; +} +//------------------------------remix_address_expressions---------------------- +// Rework addressing expressions to get the most loop-invariant stuff +// moved out. We'd like to do all associative operators, but it's especially +// important (common) to do address expressions. +Node* PhaseIdealLoop::remix_address_expressions(Node* n) { + if (!has_ctrl(n)) return NULL; + Node* n_ctrl = get_ctrl(n); + IdealLoopTree* n_loop = get_loop(n_ctrl); + + // See if 'n' mixes loop-varying and loop-invariant inputs and + // itself is loop-varying. + + // Only interested in binary ops (and AddP) + if (n->req() < 3 || n->req() > 4) return NULL; + + Node* n1_ctrl = get_ctrl(n->in( 1)); + Node* n2_ctrl = get_ctrl(n->in( 2)); + Node* n3_ctrl = get_ctrl(n->in(n->req() == 3 ? 2 : 3)); + IdealLoopTree* n1_loop = get_loop(n1_ctrl); + IdealLoopTree* n2_loop = get_loop(n2_ctrl); + IdealLoopTree* n3_loop = get_loop(n3_ctrl); + + // Does one of my inputs spin in a tighter loop than self? + if ((n_loop->is_member(n1_loop) && n_loop != n1_loop) || + (n_loop->is_member(n2_loop) && n_loop != n2_loop) || + (n_loop->is_member(n3_loop) && n_loop != n3_loop)) { + return NULL; // Leave well enough alone + } + + // Is at least one of my inputs loop-invariant? + if (n1_loop == n_loop && + n2_loop == n_loop && + n3_loop == n_loop) { + return NULL; // No loop-invariant inputs + } + + Node* res = remix_address_expressions_add_left_shift(n, n_loop, n_ctrl, T_INT); + if (res != NULL) { + return res; + } + res = remix_address_expressions_add_left_shift(n, n_loop, n_ctrl, T_LONG); + if (res != NULL) { + return res; + } + + int n_op = n->Opcode(); // Replace (I+V) with (V+I) - if( n_op == Op_AddI || + if (n_op == Op_AddI || n_op == Op_AddL || n_op == Op_AddF || n_op == Op_AddD || n_op == Op_MulI || n_op == Op_MulL || n_op == Op_MulF || - n_op == Op_MulD ) { - if( n2_loop == n_loop ) { - assert( n1_loop != n_loop, "" ); + n_op == Op_MulD) { + if (n2_loop == n_loop) { + assert(n1_loop != n_loop, ""); n->swap_edges(1, 2); } } // Replace ((I1 +p V) +p I2) with ((I1 +p I2) +p V), // but not if I2 is a constant. - if( n_op == Op_AddP ) { - if( n2_loop == n_loop && n3_loop != n_loop ) { - if( n->in(2)->Opcode() == Op_AddP && !n->in(3)->is_Con() ) { - Node *n22_ctrl = get_ctrl(n->in(2)->in(2)); - Node *n23_ctrl = get_ctrl(n->in(2)->in(3)); - IdealLoopTree *n22loop = get_loop( n22_ctrl ); - IdealLoopTree *n23_loop = get_loop( n23_ctrl ); - if( n22loop != n_loop && n22loop->is_member(n_loop) && - n23_loop == n_loop ) { - Node *add1 = new AddPNode( n->in(1), n->in(2)->in(2), n->in(3) ); + if (n_op == Op_AddP) { + if (n2_loop == n_loop && n3_loop != n_loop) { + if (n->in(2)->Opcode() == Op_AddP && !n->in(3)->is_Con()) { + Node* n22_ctrl = get_ctrl(n->in(2)->in(2)); + Node* n23_ctrl = get_ctrl(n->in(2)->in(3)); + IdealLoopTree* n22loop = get_loop(n22_ctrl); + IdealLoopTree* n23_loop = get_loop(n23_ctrl); + if (n22loop != n_loop && n22loop->is_member(n_loop) && + n23_loop == n_loop) { + Node* add1 = new AddPNode(n->in(1), n->in(2)->in(2), n->in(3)); // Stuff new AddP in the loop preheader - register_new_node( add1, n_loop->_head->in(LoopNode::EntryControl) ); - Node *add2 = new AddPNode( n->in(1), add1, n->in(2)->in(3) ); - register_new_node( add2, n_ctrl ); - _igvn.replace_node( n, add2 ); + register_new_node(add1, n_loop->_head->in(LoopNode::EntryControl)); + Node* add2 = new AddPNode(n->in(1), add1, n->in(2)->in(3)); + register_new_node(add2, n_ctrl); + _igvn.replace_node(n, add2); return add2; } } @@ -493,17 +512,17 @@ Node *PhaseIdealLoop::remix_address_expressions( Node *n ) { // Replace (I1 +p (I2 + V)) with ((I1 +p I2) +p V) if (n2_loop != n_loop && n3_loop == n_loop) { if (n->in(3)->Opcode() == Op_AddX) { - Node *V = n->in(3)->in(1); - Node *I = n->in(3)->in(2); + Node* V = n->in(3)->in(1); + Node* I = n->in(3)->in(2); if (is_member(n_loop,get_ctrl(V))) { } else { Node *tmp = V; V = I; I = tmp; } if (!is_member(n_loop,get_ctrl(I))) { - Node *add1 = new AddPNode(n->in(1), n->in(2), I); + Node* add1 = new AddPNode(n->in(1), n->in(2), I); // Stuff new AddP in the loop preheader register_new_node(add1, n_loop->_head->in(LoopNode::EntryControl)); - Node *add2 = new AddPNode(n->in(1), add1, V); + Node* add2 = new AddPNode(n->in(1), add1, V); register_new_node(add2, n_ctrl); _igvn.replace_node(n, add2); return add2; diff --git a/src/hotspot/share/opto/mulnode.cpp b/src/hotspot/share/opto/mulnode.cpp index 1209cab44f4..11df86d19ff 100644 --- a/src/hotspot/share/opto/mulnode.cpp +++ b/src/hotspot/share/opto/mulnode.cpp @@ -738,6 +738,18 @@ Node *AndLNode::Ideal(PhaseGVN *phase, bool can_reshape) { return MulNode::Ideal(phase, can_reshape); } +LShiftNode* LShiftNode::make(Node* in1, Node* in2, BasicType bt) { + switch (bt) { + case T_INT: + return new LShiftINode(in1, in2); + case T_LONG: + return new LShiftLNode(in1, in2); + default: + fatal("Not implemented for %s", type2name(bt)); + } + return NULL; +} + //============================================================================= static bool const_shift_count(PhaseGVN* phase, Node* shiftNode, int* count) { diff --git a/src/hotspot/share/opto/mulnode.hpp b/src/hotspot/share/opto/mulnode.hpp index 29ce57db2eb..a28f700da7a 100644 --- a/src/hotspot/share/opto/mulnode.hpp +++ b/src/hotspot/share/opto/mulnode.hpp @@ -228,6 +228,8 @@ public: LShiftNode(Node *in1, Node *in2) : Node(NULL,in1,in2) { init_class_id(Class_LShift); } + + static LShiftNode* make(Node* in1, Node* in2, BasicType bt); }; //------------------------------LShiftINode------------------------------------ diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestRemixAddressExpressions.java b/test/hotspot/jtreg/compiler/c2/irTests/TestRemixAddressExpressions.java new file mode 100644 index 00000000000..f35b9273a56 --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/irTests/TestRemixAddressExpressions.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2022, Red Hat, Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package compiler.c2.irTests; + +import compiler.lib.ir_framework.*; + +/* + * @test + * @bug 8278784 + * @summary C2: Refactor PhaseIdealLoop::remix_address_expressions() so it operates on longs + * @library /test/lib / + * @run driver compiler.c2.irTests.TestRemixAddressExpressions + */ + +public class TestRemixAddressExpressions { + public static void main(String[] args) { + TestFramework.run(); + } + + @Test + @IR(counts = { IRNode.ADD_I, "1", IRNode.LSHIFT_I, "2" }) + @Arguments({Argument.RANDOM_EACH, Argument.RANDOM_EACH}) + public static float invPlusVarLshiftInt(int inv, int scale) { + float res = 0; + for (int i = 1; i < 100; i *= 11) { + res += (i + inv) << scale; + } + return res; + } + + @Test + @IR(counts = { IRNode.ADD_L, "1", IRNode.LSHIFT_L, "2" }) + @Arguments({Argument.RANDOM_EACH, Argument.RANDOM_EACH}) + public static float invPlusVarLshiftLong(long inv, int scale) { + float res = 0; + for (long i = 1; i < 100; i *= 11) { + res += (i + inv) << scale; + } + return res; + } + + @Test + @IR(counts = { IRNode.ADD_I, "1", IRNode.SUB_I, "1", IRNode.LSHIFT_I, "2" }) + @Arguments({Argument.RANDOM_EACH, Argument.RANDOM_EACH}) + public static float invMinusVarLshiftInt(int inv, int scale) { + float res = 0; + for (int i = 1; i < 100; i *= 11) { + res += (inv - i) << scale; + } + return res; + } + + @Test + @IR(counts = { IRNode.ADD_L, "1", IRNode.SUB_L, "1", IRNode.LSHIFT_L, "2" }) + @Arguments({Argument.RANDOM_EACH, Argument.RANDOM_EACH}) + public static float invMinusVarLshiftLong(long inv, int scale) { + float res = 0; + for (long i = 1; i < 100; i *= 11) { + res += (inv - i) << scale; + } + return res; + } + + @Test + @IR(counts = { IRNode.ADD_I, "1", IRNode.SUB_I, "1", IRNode.LSHIFT_I, "2" }) + @Arguments({Argument.RANDOM_EACH, Argument.RANDOM_EACH}) + public static float varMinusInvLshiftInt(int inv, int scale) { + float res = 0; + for (int i = 1; i < 100; i *= 11) { + res += (i - inv) << scale; + } + return res; + } + + @Test + @IR(counts = { IRNode.ADD_L, "1", IRNode.SUB_L, "1", IRNode.LSHIFT_L, "2" }) + @Arguments({Argument.RANDOM_EACH, Argument.RANDOM_EACH}) + public static float varMinusInvLshiftLong(long inv, int scale) { + float res = 0; + for (long i = 1; i < 100; i *= 11) { + res += (i - inv) << scale; + } + return res; + } +} -- GitLab From 47b1c51bbd28582d209db07052e553a76acced65 Mon Sep 17 00:00:00 2001 From: Andrey Turbanov Date: Fri, 21 Jan 2022 08:53:37 +0000 Subject: [PATCH 239/564] 8277120: Use Optional.isEmpty instead of !Optional.isPresent in java.net.http Reviewed-by: dfuchs --- .../classes/jdk/internal/net/http/AuthenticationFilter.java | 4 ++-- .../classes/jdk/internal/net/http/HttpRequestImpl.java | 4 ++-- .../share/classes/jdk/internal/net/http/common/Utils.java | 2 +- .../jdk/internal/net/http/websocket/BuilderImpl.java | 4 ++-- .../jdk/internal/net/http/websocket/OpeningHandshake.java | 6 ++---- 5 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/AuthenticationFilter.java b/src/java.net.http/share/classes/jdk/internal/net/http/AuthenticationFilter.java index 2561afd645d..6e6182a1fb2 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/AuthenticationFilter.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/AuthenticationFilter.java @@ -305,7 +305,7 @@ class AuthenticationFilter implements HeaderFilter { AuthInfo au = proxy ? exchange.proxyauth : exchange.serverauth; if (au == null) { // if no authenticator, let the user deal with 407/401 - if (!exchange.client().authenticator().isPresent()) return null; + if (exchange.client().authenticator().isEmpty()) return null; PasswordAuthentication pw = getCredentials(authval, proxy, req); if (pw == null) { @@ -331,7 +331,7 @@ class AuthenticationFilter implements HeaderFilter { } // if no authenticator, let the user deal with 407/401 - if (!exchange.client().authenticator().isPresent()) return null; + if (exchange.client().authenticator().isEmpty()) return null; // try again PasswordAuthentication pw = getCredentials(authval, proxy, req); diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/HttpRequestImpl.java b/src/java.net.http/share/classes/jdk/internal/net/http/HttpRequestImpl.java index a04ded70480..3e5da6d4c14 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/HttpRequestImpl.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/HttpRequestImpl.java @@ -124,7 +124,7 @@ public class HttpRequestImpl extends HttpRequest implements WebSocketRequest { checkTimeout(timeout); this.systemHeadersBuilder = new HttpHeadersBuilder(); } - if (!userHeaders.firstValue("User-Agent").isPresent()) { + if (userHeaders.firstValue("User-Agent").isEmpty()) { this.systemHeadersBuilder.setHeader("User-Agent", USER_AGENT); } this.uri = requestURI; @@ -182,7 +182,7 @@ public class HttpRequestImpl extends HttpRequest implements WebSocketRequest { this.userHeaders = other.userHeaders; this.isWebSocket = other.isWebSocket; this.systemHeadersBuilder = new HttpHeadersBuilder(); - if (!userHeaders.firstValue("User-Agent").isPresent()) { + if (userHeaders.firstValue("User-Agent").isEmpty()) { this.systemHeadersBuilder.setHeader("User-Agent", USER_AGENT); } this.uri = uri; diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java b/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java index c22c36a1eb3..09457b795b4 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java @@ -175,7 +175,7 @@ public final class Utils { // used by caller. public static final BiPredicate CONTEXT_RESTRICTED(HttpClient client) { - return (k, v) -> !client.authenticator().isPresent() || + return (k, v) -> client.authenticator().isEmpty() || (!k.equalsIgnoreCase("Authorization") && !k.equalsIgnoreCase("Proxy-Authorization")); } diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/websocket/BuilderImpl.java b/src/java.net.http/share/classes/jdk/internal/net/http/websocket/BuilderImpl.java index 7a8a540d2b3..452e83206f4 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/websocket/BuilderImpl.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/websocket/BuilderImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2021, 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 @@ -72,7 +72,7 @@ public final class BuilderImpl implements Builder { this.proxySelector = proxySelector; // If a proxy selector was supplied by the user, it should be present // on the client and should be the same that what we got as an argument - assert !client.proxy().isPresent() + assert client.proxy().isEmpty() || client.proxy().equals(proxySelector); this.headers = headers; this.subprotocols = subprotocols; diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/websocket/OpeningHandshake.java b/src/java.net.http/share/classes/jdk/internal/net/http/websocket/OpeningHandshake.java index b4d456b7646..dd60bd621b7 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/websocket/OpeningHandshake.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/websocket/OpeningHandshake.java @@ -28,7 +28,6 @@ package jdk.internal.net.http.websocket; import java.net.http.HttpClient; import java.net.http.HttpClient.Version; import java.net.http.HttpHeaders; -import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.http.HttpResponse.BodyHandlers; import java.net.http.WebSocketHandshakeException; @@ -62,7 +61,6 @@ import java.util.Optional; import java.util.Set; import java.util.TreeSet; import java.util.concurrent.CompletableFuture; -import java.util.stream.Collectors; import java.util.stream.Stream; import static java.lang.String.format; @@ -281,7 +279,7 @@ public class OpeningHandshake { throws CheckFailedException { Optional opt = responseHeaders.firstValue(HEADER_PROTOCOL); - if (!opt.isPresent()) { + if (opt.isEmpty()) { // If there is no such header in the response, then the server // doesn't want to use any subprotocol return ""; @@ -363,7 +361,7 @@ public class OpeningHandshake { * or {@code null} if none is required or applicable. */ private static Proxy proxyFor(Optional selector, URI uri) { - if (!selector.isPresent()) { + if (selector.isEmpty()) { return null; } URI requestURI = createRequestURI(uri); // Based on the HTTP scheme -- GitLab From ab2c8d3c9baf1080f436287785e4e02fd79953a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Walln=C3=B6fer?= Date: Fri, 21 Jan 2022 09:10:19 +0000 Subject: [PATCH 240/564] 8280393: Promote use of HtmlTree factory methods Reviewed-by: jjg --- .../doclets/formats/html/ClassUseWriter.java | 5 ++--- .../doclets/formats/html/ClassWriterImpl.java | 5 ++--- .../html/ConstantsSummaryWriterImpl.java | 6 ++---- .../doclets/formats/html/HelpWriter.java | 12 +++++------- .../doclets/formats/html/HtmlDocletWriter.java | 3 +-- .../formats/html/HtmlSerialFieldWriter.java | 8 ++------ .../formats/html/HtmlSerialMethodWriter.java | 10 +++------- .../doclets/formats/html/IndexWriter.java | 5 ++--- .../doclets/formats/html/ModuleWriterImpl.java | 13 +++++-------- .../doclets/formats/html/Navigation.java | 11 +++++------ .../doclets/formats/html/PackageTreeWriter.java | 5 ++--- .../doclets/formats/html/PackageUseWriter.java | 5 ++--- .../doclets/formats/html/PackageWriterImpl.java | 10 ++++------ .../formats/html/SerializedFormWriterImpl.java | 17 ++++++----------- .../formats/html/SubWriterHolderWriter.java | 17 ++++++----------- .../internal/doclets/formats/html/Table.java | 10 ++++------ .../doclets/formats/html/TagletWriterImpl.java | 5 ++--- .../doclets/formats/html/TreeWriter.java | 7 ++----- .../doclets/formats/html/markup/HtmlTree.java | 11 +++++++++++ 19 files changed, 68 insertions(+), 97 deletions(-) diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java index f91b06105a3..840676e875c 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -296,8 +296,7 @@ public class ClassUseWriter extends SubWriterHolderWriter { * @param contentTree the content tree to which the class elements will be added */ protected void addClassList(Content contentTree) { - HtmlTree ul = new HtmlTree(TagName.UL); - ul.setStyle(HtmlStyle.blockList); + HtmlTree ul = HtmlTree.UL(HtmlStyle.blockList); for (PackageElement pkg : pkgSet) { HtmlTree htmlTree = HtmlTree.SECTION(HtmlStyle.detail) .setId(htmlIds.forPackage(pkg)); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java index 40db035c8b9..3b1b8537bf0 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -105,8 +105,7 @@ public class ClassWriterImpl extends SubWriterHolderWriter implements ClassWrite @Override public Content getHeader(String header) { HtmlTree bodyTree = getBody(getWindowTitle(utils.getSimpleName(typeElement))); - HtmlTree div = new HtmlTree(TagName.DIV); - div.setStyle(HtmlStyle.header); + HtmlTree div = HtmlTree.DIV(HtmlStyle.header); if (configuration.showModules) { ModuleElement mdle = configuration.docEnv.getElementUtils().getModuleOf(typeElement); Content classModuleLabel = HtmlTree.SPAN(HtmlStyle.moduleLabelInType, contents.moduleLabel); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java index 2bd163b24de..1723bc6ecfd 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -165,9 +165,7 @@ public class ConstantsSummaryWriterImpl extends HtmlDocletWriter implements Cons @Override public Content getClassConstantHeader() { - HtmlTree ul = new HtmlTree(TagName.UL); - ul.setStyle(HtmlStyle.blockList); - return ul; + return HtmlTree.UL(HtmlStyle.blockList); } @Override diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HelpWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HelpWriter.java index 167b24b622b..11ed54c2d86 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HelpWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HelpWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2022, 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 @@ -128,9 +128,7 @@ public class HelpWriter extends HtmlDocletWriter { * */ protected void addHelpFileContents(Content contentTree) { - HtmlTree mainTOC = new HtmlTree(TagName.UL).setStyle(HtmlStyle.helpTOC); - - + HtmlTree mainTOC = HtmlTree.UL(HtmlStyle.helpTOC); contentTree.add(HtmlTree.HEADING(Headings.PAGE_TITLE_HEADING, HtmlStyle.title, getContent("doclet.help.main_heading"))) @@ -185,7 +183,7 @@ public class HelpWriter extends HtmlDocletWriter { } content.add(navSection); - HtmlTree subTOC = new HtmlTree(TagName.UL).setStyle(HtmlStyle.helpSubTOC); + HtmlTree subTOC = HtmlTree.UL(HtmlStyle.helpSubTOC); HtmlTree section; @@ -193,7 +191,7 @@ public class HelpWriter extends HtmlDocletWriter { if (options.createIndex()) { section = newHelpSection(getContent("doclet.help.search.head"), subTOC, HtmlIds.HELP_SEARCH); Content searchIntro = HtmlTree.P(getContent("doclet.help.search.intro")); - Content searchExamples = new HtmlTree(TagName.UL).setStyle(HtmlStyle.helpSectionList); + Content searchExamples = HtmlTree.UL(HtmlStyle.helpSectionList); for (String[] example : SEARCH_EXAMPLES) { searchExamples.add(HtmlTree.LI( getContent("doclet.help.search.example", @@ -240,7 +238,7 @@ public class HelpWriter extends HtmlDocletWriter { .add(HtmlTree.HEADING(Headings.CONTENT_HEADING, pageKindsHeading).setId(HtmlIds.HELP_PAGES)) .add(contents.getContent("doclet.help.page_kinds.intro")); - HtmlTree subTOC = new HtmlTree(TagName.UL).setStyle(HtmlStyle.helpSubTOC); + HtmlTree subTOC = HtmlTree.UL(HtmlStyle.helpSubTOC); HtmlTree section; diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java index 1a735412886..1c325db50e9 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java @@ -2380,8 +2380,7 @@ public class HtmlDocletWriter { Content leadingNote = contents.getContent("doclet.PreviewLeadingNote", nameCode); previewDiv.add(HtmlTree.SPAN(HtmlStyle.previewLabel, leadingNote)); - HtmlTree ul = new HtmlTree(TagName.UL); - ul.setStyle(HtmlStyle.previewComment); + HtmlTree ul = HtmlTree.UL(HtmlStyle.previewComment); for (Content note : previewNotes) { ul.add(HtmlTree.LI(note)); } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialFieldWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialFieldWriter.java index d57d82d9847..7278ac8e315 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialFieldWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialFieldWriter.java @@ -71,9 +71,7 @@ public class HtmlSerialFieldWriter extends FieldWriterImpl */ @Override public Content getSerializableFieldsHeader() { - HtmlTree ul = new HtmlTree(TagName.UL); - ul.setStyle(HtmlStyle.blockList); - return ul; + return HtmlTree.UL(HtmlStyle.blockList); } /** @@ -84,9 +82,7 @@ public class HtmlSerialFieldWriter extends FieldWriterImpl */ @Override public Content getFieldsContentHeader(boolean isLastContent) { - HtmlTree li = new HtmlTree(TagName.LI); - li.setStyle(HtmlStyle.blockList); - return li; + return new HtmlTree(TagName.LI).setStyle(HtmlStyle.blockList); } /** diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialMethodWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialMethodWriter.java index aa6e31e7c12..8b2bed47a00 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialMethodWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialMethodWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2022, 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 @@ -60,9 +60,7 @@ public class HtmlSerialMethodWriter extends MethodWriterImpl implements */ @Override public Content getSerializableMethodsHeader() { - HtmlTree ul = new HtmlTree(TagName.UL); - ul.setStyle(HtmlStyle.blockList); - return ul; + return HtmlTree.UL(HtmlStyle.blockList); } /** @@ -73,9 +71,7 @@ public class HtmlSerialMethodWriter extends MethodWriterImpl implements */ @Override public Content getMethodsContentHeader(boolean isLastContent) { - HtmlTree li = new HtmlTree(TagName.LI); - li.setStyle(HtmlStyle.blockList); - return li; + return new HtmlTree(TagName.LI); } /** diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/IndexWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/IndexWriter.java index 4fadb86baa7..9e486b74ab9 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/IndexWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/IndexWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2022, 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 @@ -292,8 +292,7 @@ public class IndexWriter extends HtmlDocletWriter { */ protected void addComment(Element element, Content contentTree) { Content span = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, getDeprecatedPhrase(element)); - HtmlTree div = new HtmlTree(TagName.DIV); - div.setStyle(HtmlStyle.deprecationBlock); + HtmlTree div = HtmlTree.DIV(HtmlStyle.deprecationBlock); if (utils.isDeprecated(element)) { div.add(span); List tags = utils.getDeprecatedTrees(element); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java index e4dd2efd10d..30803551b2f 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, 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 @@ -180,8 +180,7 @@ public class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryW @Override public Content getModuleHeader(String heading) { HtmlTree bodyTree = getBody(getWindowTitle(mdle.getQualifiedName().toString())); - HtmlTree div = new HtmlTree(TagName.DIV); - div.setStyle(HtmlStyle.header); + HtmlTree div = HtmlTree.DIV(HtmlStyle.header); Content moduleHead = new ContentBuilder(); moduleHead.add(mdle.isOpen() && (configuration.docEnv.getModuleMode() == ModuleMode.ALL) ? contents.openModuleLabel : contents.moduleLabel); @@ -222,7 +221,7 @@ public class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryW */ @Override public Content getSummariesList() { - return new HtmlTree(TagName.UL).setStyle(HtmlStyle.summaryList); + return HtmlTree.UL(HtmlStyle.summaryList); } /** @@ -799,8 +798,7 @@ public class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryW List deprs = utils.getDeprecatedTrees(mdle); if (utils.isDeprecated(mdle)) { CommentHelper ch = utils.getCommentHelper(mdle); - HtmlTree deprDiv = new HtmlTree(TagName.DIV); - deprDiv.setStyle(HtmlStyle.deprecationBlock); + HtmlTree deprDiv = HtmlTree.DIV(HtmlStyle.deprecationBlock); Content deprPhrase = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, getDeprecatedPhrase(mdle)); deprDiv.add(deprPhrase); if (!deprs.isEmpty()) { @@ -859,8 +857,7 @@ public class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryW public void addPackageDeprecationInfo(Content li, PackageElement pkg) { if (utils.isDeprecated(pkg)) { List deprs = utils.getDeprecatedTrees(pkg); - HtmlTree deprDiv = new HtmlTree(TagName.DIV); - deprDiv.setStyle(HtmlStyle.deprecationBlock); + HtmlTree deprDiv = HtmlTree.DIV(HtmlStyle.deprecationBlock); Content deprPhrase = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, getDeprecatedPhrase(pkg)); deprDiv.add(deprPhrase); if (!deprs.isEmpty()) { diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Navigation.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Navigation.java index 4ebd0c3f5c0..3e8e556974a 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Navigation.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Navigation.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,6 @@ import java.util.List; import java.util.Set; import javax.lang.model.element.Element; -import javax.lang.model.element.ElementKind; import javax.lang.model.element.ModuleElement; import javax.lang.model.element.PackageElement; import javax.lang.model.element.TypeElement; @@ -635,21 +634,21 @@ public class Navigation { .put(HtmlAttr.TITLE, rowListTitle); addMainNavLinks(navList); navDiv.add(navList); - HtmlTree ulNavSummaryRight = new HtmlTree(TagName.UL).setStyle(HtmlStyle.subNavListSmall); + HtmlTree ulNavSummaryRight = HtmlTree.UL(HtmlStyle.subNavListSmall); addSummaryLinks(ulNavSummaryRight, true); addDetailLinks(ulNavSummaryRight, true); navDiv.add(ulNavSummaryRight); tree.add(navDiv); - HtmlTree subDiv = new HtmlTree(TagName.DIV).setStyle(HtmlStyle.subNav); + HtmlTree subDiv = HtmlTree.DIV(HtmlStyle.subNav); HtmlTree div = new HtmlTree(TagName.DIV).setId(HtmlIds.NAVBAR_SUB_LIST); // Add the summary links if present. - HtmlTree ulNavSummary = new HtmlTree(TagName.UL).setStyle(HtmlStyle.subNavList); + HtmlTree ulNavSummary = HtmlTree.UL(HtmlStyle.subNavList); addSummaryLinks(ulNavSummary, false); div.add(ulNavSummary); // Add the detail links if present. - HtmlTree ulNavDetail = new HtmlTree(TagName.UL).setStyle(HtmlStyle.subNavList); + HtmlTree ulNavDetail = HtmlTree.UL(HtmlStyle.subNavList); addDetailLinks(ulNavDetail, false); div.add(ulNavDetail); subDiv.add(div); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageTreeWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageTreeWriter.java index ba54e2a26dc..9618be166f9 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageTreeWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageTreeWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2022, 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 @@ -147,8 +147,7 @@ public class PackageTreeWriter extends AbstractTreeWriter { Content span = HtmlTree.SPAN(HtmlStyle.packageHierarchyLabel, contents.packageHierarchies); div.add(span); - HtmlTree ul = new HtmlTree (TagName.UL); - ul.setStyle(HtmlStyle.horizontal); + HtmlTree ul = HtmlTree.UL(HtmlStyle.horizontal); ul.add(getNavLinkMainTree(resources.getText("doclet.All_Packages"))); div.add(ul); } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java index b6c40c39a57..1c44a130868 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2022, 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 @@ -181,8 +181,7 @@ public class PackageUseWriter extends SubWriterHolderWriter { protected void addClassList(Content contentTree) { TableHeader classTableHeader = new TableHeader( contents.classLabel, contents.descriptionLabel); - HtmlTree ul = new HtmlTree(TagName.UL); - ul.setStyle(HtmlStyle.blockList); + HtmlTree ul = HtmlTree.UL(HtmlStyle.blockList); for (String packageName : usingPackageToUsedClasses.keySet()) { PackageElement usingPackage = utils.elementUtils.getPackageElement(packageName); HtmlTree section = HtmlTree.SECTION(HtmlStyle.detail) diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java index 6bca82f17be..231ab6c50e2 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -111,8 +111,7 @@ public class PackageWriterImpl extends HtmlDocletWriter public Content getPackageHeader() { String packageName = getLocalizedPackageName(packageElement).toString(); HtmlTree bodyTree = getBody(getWindowTitle(packageName)); - HtmlTree div = new HtmlTree(TagName.DIV); - div.setStyle(HtmlStyle.header); + HtmlTree div = HtmlTree.DIV(HtmlStyle.header); if (configuration.showModules) { ModuleElement mdle = configuration.docEnv.getElementUtils().getModuleOf(packageElement); Content classModuleLabel = HtmlTree.SPAN(HtmlStyle.moduleLabelInPackage, contents.moduleLabel); @@ -212,8 +211,7 @@ public class PackageWriterImpl extends HtmlDocletWriter List deprs = utils.getDeprecatedTrees(packageElement); if (utils.isDeprecated(packageElement)) { CommentHelper ch = utils.getCommentHelper(packageElement); - HtmlTree deprDiv = new HtmlTree(TagName.DIV); - deprDiv.setStyle(HtmlStyle.deprecationBlock); + HtmlTree deprDiv = HtmlTree.DIV(HtmlStyle.deprecationBlock); Content deprPhrase = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, getDeprecatedPhrase(packageElement)); deprDiv.add(deprPhrase); if (!deprs.isEmpty()) { @@ -228,7 +226,7 @@ public class PackageWriterImpl extends HtmlDocletWriter @Override public Content getSummariesList() { - return new HtmlTree(TagName.UL).setStyle(HtmlStyle.summaryList); + return HtmlTree.UL(HtmlStyle.summaryList); } @Override diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SerializedFormWriterImpl.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SerializedFormWriterImpl.java index 8d97e0c5b4f..242ebf37199 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SerializedFormWriterImpl.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SerializedFormWriterImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2022, 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 @@ -33,7 +33,6 @@ import javax.lang.model.element.TypeElement; import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder; import jdk.javadoc.internal.doclets.formats.html.markup.Entity; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; -import jdk.javadoc.internal.doclets.formats.html.markup.TagName; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; import jdk.javadoc.internal.doclets.formats.html.Navigation.PageMode; import jdk.javadoc.internal.doclets.formats.html.markup.Text; @@ -90,9 +89,7 @@ public class SerializedFormWriterImpl extends SubWriterHolderWriter */ @Override public Content getSerializedSummariesHeader() { - HtmlTree ul = new HtmlTree(TagName.UL); - ul.setStyle(HtmlStyle.blockList); - return ul; + return HtmlTree.UL(HtmlStyle.blockList); } /** @@ -127,9 +124,8 @@ public class SerializedFormWriterImpl extends SubWriterHolderWriter */ @Override public Content getClassSerializedHeader() { - HtmlTree ul = new HtmlTree(TagName.UL); - ul.setStyle(HtmlStyle.blockList); - return ul; + return HtmlTree.UL(HtmlStyle.blockList); + } /** @@ -220,9 +216,8 @@ public class SerializedFormWriterImpl extends SubWriterHolderWriter */ @Override public Content getClassContentHeader() { - HtmlTree ul = new HtmlTree(TagName.UL); - ul.setStyle(HtmlStyle.blockList); - return ul; + return HtmlTree.UL(HtmlStyle.blockList); + } /** diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SubWriterHolderWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SubWriterHolderWriter.java index 5f09e20fd74..0a22ce4ae4a 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SubWriterHolderWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SubWriterHolderWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,7 +36,6 @@ import jdk.javadoc.internal.doclets.formats.html.markup.BodyContents; import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlId; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; -import jdk.javadoc.internal.doclets.formats.html.markup.TagName; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; import jdk.javadoc.internal.doclets.toolkit.Content; import jdk.javadoc.internal.doclets.toolkit.util.DocPath; @@ -207,9 +206,7 @@ public abstract class SubWriterHolderWriter extends HtmlDocletWriter { * @return a content tree for the member header */ public Content getMemberTreeHeader() { - HtmlTree ul = new HtmlTree(TagName.UL); - ul.setStyle(HtmlStyle.blockList); - return ul; + return HtmlTree.UL(HtmlStyle.blockList); } /** @@ -218,7 +215,7 @@ public abstract class SubWriterHolderWriter extends HtmlDocletWriter { * @return a list to be used for the list of summaries for members of a given kind */ public Content getSummariesList() { - return new HtmlTree(TagName.UL).setStyle(HtmlStyle.summaryList); + return HtmlTree.UL(HtmlStyle.summaryList); } /** @@ -238,7 +235,7 @@ public abstract class SubWriterHolderWriter extends HtmlDocletWriter { * @return a list to be used for the list of details for members of a given kind */ public Content getDetailsList() { - return new HtmlTree(TagName.UL).setStyle(HtmlStyle.detailsList); + return HtmlTree.UL(HtmlStyle.detailsList); } /** @@ -257,7 +254,7 @@ public abstract class SubWriterHolderWriter extends HtmlDocletWriter { * @return a list to be used for the list of members of a given kind */ public Content getMemberList() { - return new HtmlTree(TagName.UL).setStyle(HtmlStyle.memberList); + return HtmlTree.UL(HtmlStyle.memberList); } /** @@ -271,9 +268,7 @@ public abstract class SubWriterHolderWriter extends HtmlDocletWriter { } public Content getMemberInheritedTree() { - HtmlTree div = new HtmlTree(TagName.DIV); - div.setStyle(HtmlStyle.inheritedList); - return div; + return HtmlTree.DIV(HtmlStyle.inheritedList); } /** diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Table.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Table.java index 25f7e98f4f2..8cf2e3710f0 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Table.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Table.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, 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 @@ -386,7 +386,7 @@ public class Table extends Content { default -> throw new IllegalStateException(); }; - HtmlTree table = new HtmlTree(TagName.DIV).setStyle(tableStyle).addStyle(columnStyle); + HtmlTree table = HtmlTree.DIV(tableStyle).addStyle(columnStyle); if ((tabMap == null || tabs.size() == 1) && !alwaysShowDefaultTab) { if (tabMap == null) { main.add(caption); @@ -396,7 +396,7 @@ public class Table extends Content { table.add(getTableBody()); main.add(table); } else { - HtmlTree tablist = new HtmlTree(TagName.DIV).setStyle(tabListStyle) + HtmlTree tablist = HtmlTree.DIV(tabListStyle) .put(HtmlAttr.ROLE, "tablist") .put(HtmlAttr.ARIA_ORIENTATION, "horizontal"); @@ -481,8 +481,6 @@ public class Table extends Content { } private HtmlTree getCaption(Content title) { - return new HtmlTree(TagName.DIV) - .setStyle(HtmlStyle.caption) - .add(HtmlTree.SPAN(title)); + return HtmlTree.DIV(HtmlStyle.caption, HtmlTree.SPAN(title)); } } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TagletWriterImpl.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TagletWriterImpl.java index 576597ae86e..fdac4e55576 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TagletWriterImpl.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TagletWriterImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, 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 @@ -352,8 +352,7 @@ public class TagletWriterImpl extends TagletWriter { // Use a different style if any link label is longer than 30 chars or contains commas. boolean hasLongLabels = links.stream() .anyMatch(c -> c.charCount() > SEE_TAG_MAX_INLINE_LENGTH || c.toString().contains(",")); - HtmlTree seeList = new HtmlTree(TagName.UL) - .setStyle(hasLongLabels ? HtmlStyle.seeListLong : HtmlStyle.seeList); + HtmlTree seeList = HtmlTree.UL(hasLongLabels ? HtmlStyle.seeListLong : HtmlStyle.seeList); links.stream().filter(Content::isValid).forEach(item -> { seeList.add(HtmlTree.LI(item)); }); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TreeWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TreeWriter.java index 12971fc19dc..57b2b470dee 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TreeWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TreeWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,10 +32,8 @@ import javax.lang.model.element.PackageElement; import jdk.javadoc.internal.doclets.formats.html.markup.BodyContents; import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; -import jdk.javadoc.internal.doclets.formats.html.markup.TagName; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; import jdk.javadoc.internal.doclets.formats.html.Navigation.PageMode; -import jdk.javadoc.internal.doclets.formats.html.markup.Text; import jdk.javadoc.internal.doclets.toolkit.Content; import jdk.javadoc.internal.doclets.toolkit.util.ClassTree; import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException; @@ -135,8 +133,7 @@ public class TreeWriter extends AbstractTreeWriter { Content span = HtmlTree.SPAN(HtmlStyle.packageHierarchyLabel, contents.packageHierarchies); contentTree.add(span); - HtmlTree ul = new HtmlTree(TagName.UL); - ul.setStyle(HtmlStyle.horizontal); + HtmlTree ul = HtmlTree.UL(HtmlStyle.horizontal); int i = 0; for (PackageElement pkg : packages) { // If the package name length is 0 or if -nodeprecated option diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTree.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTree.java index 1d05cd8c4d4..9d1ad310767 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTree.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTree.java @@ -845,6 +845,17 @@ public class HtmlTree extends Content { .add(body); } + /** + * Creates an HTML {@code UL} element with the given style. + * + * @param style the style + * @return the element + */ + public static HtmlTree UL(HtmlStyle style) { + return new HtmlTree(TagName.UL) + .setStyle(style); + } + /** * Creates an HTML {@code UL} element with the given style and some content. * -- GitLab From 6287ae3707bac091b37cd5693ca77e2349a903ef Mon Sep 17 00:00:00 2001 From: KIRIYAMA Takuya Date: Fri, 21 Jan 2022 13:36:29 +0000 Subject: [PATCH 241/564] 8277531: Print actual default stacksize on Windows thread logging Reviewed-by: dholmes, stuefe --- src/hotspot/os/windows/os_windows.cpp | 2 +- .../jtreg/runtime/logging/ThreadLoggingTest.java | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index 482c7615bc1..ed4ba3e1fc2 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -529,7 +529,7 @@ static unsigned __stdcall thread_native_entry(Thread* thread) { res = 20115; // java thread } - log_info(os, thread)("Thread is alive (tid: " UINTX_FORMAT ").", os::current_thread_id()); + log_info(os, thread)("Thread is alive (tid: " UINTX_FORMAT ", stacksize: " SIZE_FORMAT "k).", os::current_thread_id(), thread->stack_size() / 1024); #ifdef USE_VECTORED_EXCEPTION_HANDLING // Any exception is caught by the Vectored Exception Handler, so VM can diff --git a/test/hotspot/jtreg/runtime/logging/ThreadLoggingTest.java b/test/hotspot/jtreg/runtime/logging/ThreadLoggingTest.java index 82a189a92cb..d98fc455319 100644 --- a/test/hotspot/jtreg/runtime/logging/ThreadLoggingTest.java +++ b/test/hotspot/jtreg/runtime/logging/ThreadLoggingTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016 SAP SE and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -24,7 +24,7 @@ /* * @test - * @bug 8149036 8150619 + * @bug 8149036 8150619 8277531 * @summary os+thread output should contain logging calls for thread start stop attaches detaches * @requires vm.flagless * @library /test/lib @@ -36,6 +36,7 @@ import java.io.File; import java.util.Map; +import jdk.test.lib.Platform; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; @@ -43,7 +44,11 @@ public class ThreadLoggingTest { static void analyzeOutputForInfoLevel(OutputAnalyzer output) throws Exception { output.shouldMatch("Thread .* started"); - output.shouldContain("Thread is alive"); + if (Platform.isWindows()) { + output.shouldMatch("Thread is alive \\(tid: [0-9]+, stacksize: [0-9]+k\\)"); + } else { + output.shouldContain("Thread is alive"); + } output.shouldContain("Thread finished"); output.shouldHaveExitValue(0); } -- GitLab From 2920ce54874c404126d9fd6bfbebee5f3da27dae Mon Sep 17 00:00:00 2001 From: Yi-Fan Tsai Date: Fri, 21 Jan 2022 18:09:17 +0000 Subject: [PATCH 242/564] 8278036: Saving rscratch1 is optional in MacroAssembler::verify_heapbase Reviewed-by: xliu, phh, coleenp --- src/hotspot/cpu/x86/assembler_x86.hpp | 2 +- src/hotspot/cpu/x86/macroAssembler_x86.cpp | 13 ++++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/hotspot/cpu/x86/assembler_x86.hpp b/src/hotspot/cpu/x86/assembler_x86.hpp index 5a7e595d029..2cfb1e29360 100644 --- a/src/hotspot/cpu/x86/assembler_x86.hpp +++ b/src/hotspot/cpu/x86/assembler_x86.hpp @@ -377,7 +377,7 @@ class AddressLiteral { private: address target() { return _target; } - bool is_lval() { return _is_lval; } + bool is_lval() const { return _is_lval; } relocInfo::relocType reloc() const { return _rspec.type(); } const RelocationHolder& rspec() const { return _rspec; } diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.cpp b/src/hotspot/cpu/x86/macroAssembler_x86.cpp index 52fa1730586..10a1cb4b6a1 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp @@ -4651,12 +4651,19 @@ void MacroAssembler::verify_heapbase(const char* msg) { assert (Universe::heap() != NULL, "java heap should be initialized"); if (CheckCompressedOops) { Label ok; - push(rscratch1); // cmpptr trashes rscratch1 - cmpptr(r12_heapbase, ExternalAddress((address)CompressedOops::ptrs_base_addr())); + const auto src2 = ExternalAddress((address)CompressedOops::ptrs_base_addr()); + assert(!src2.is_lval(), "should not be lval"); + const bool is_src2_reachable = reachable(src2); + if (!is_src2_reachable) { + push(rscratch1); // cmpptr trashes rscratch1 + } + cmpptr(r12_heapbase, src2); jcc(Assembler::equal, ok); STOP(msg); bind(ok); - pop(rscratch1); + if (!is_src2_reachable) { + pop(rscratch1); + } } } #endif -- GitLab From c1e4f3dd1b42474c9abc22c7b981a98f9c36e0d5 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Fri, 21 Jan 2022 18:55:25 +0000 Subject: [PATCH 243/564] 8279397: Update --release 18 symbol information for JDK 18 build 32 Reviewed-by: iris, jlahoda --- make/data/symbols/java.base-I.sym.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/make/data/symbols/java.base-I.sym.txt b/make/data/symbols/java.base-I.sym.txt index 35fe19bb6e5..bb60a7a3070 100644 --- a/make/data/symbols/java.base-I.sym.txt +++ b/make/data/symbols/java.base-I.sym.txt @@ -393,6 +393,16 @@ header extends java/util/AbstractSet implements java/util/Set,java/lang/Cloneabl innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 innerclass innerClass java/util/Map$Entry outerClass java/util/Map innerClassName Entry flags 609 +class name java/util/Hashtable +header extends java/util/Dictionary implements java/util/Map,java/lang/Cloneable,java/io/Serializable flags 21 signature Ljava/util/Dictionary;Ljava/util/Map;Ljava/lang/Cloneable;Ljava/io/Serializable; +innerclass innerClass java/util/Map$Entry outerClass java/util/Map innerClassName Entry flags 609 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 + +class name java/util/IdentityHashMap +header extends java/util/AbstractMap implements java/util/Map,java/io/Serializable,java/lang/Cloneable flags 21 signature Ljava/util/AbstractMap;Ljava/util/Map;Ljava/io/Serializable;Ljava/lang/Cloneable; +innerclass innerClass java/util/Map$Entry outerClass java/util/Map innerClassName Entry flags 609 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 + class name java/util/Locale$IsoCountryCode header extends java/lang/Enum nestHost java/util/Locale sealed true flags 4421 signature Ljava/lang/Enum; innerclass innerClass java/util/Locale$IsoCountryCode outerClass java/util/Locale innerClassName IsoCountryCode flags 4409 -- GitLab From 7d2ef9d984f96cd260dc233c4acf58669615227f Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Fri, 21 Jan 2022 23:18:37 +0000 Subject: [PATCH 244/564] 8279179: Update nroff pages in JDK 18 before RC Reviewed-by: iris, mchung --- src/java.base/share/man/java.1 | 9 +++++++++ src/java.base/share/man/keytool.1 | 12 +++++++++++- src/jdk.jartool/share/man/jarsigner.1 | 15 ++++++++++++++- 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/java.base/share/man/java.1 b/src/java.base/share/man/java.1 index 3e17a506fa9..246d0080577 100644 --- a/src/java.base/share/man/java.1 +++ b/src/java.base/share/man/java.1 @@ -512,6 +512,15 @@ of the release. .RS .RE .TP +.B \f[CB]\-\-finalization=\f[R]\f[I]value\f[R] +Controls whether the JVM performs finalization of objects. +Valid values are "enabled" and "disabled". +Finalization is enabled by default, so the value "enabled" does nothing. +The value "disabled" disables finalization, so that no finalizers are +invoked. +.RS +.RE +.TP .B \f[CB]\-\-module\-path\f[R] \f[I]modulepath\f[R]... or \f[CB]\-p\f[R] \f[I]modulepath\f[R] A semicolon (\f[CB];\f[R]) separated list of directories in which each directory is a directory of modules. diff --git a/src/java.base/share/man/keytool.1 b/src/java.base/share/man/keytool.1 index 8250cf555b9..5b70729917c 100644 --- a/src/java.base/share/man/keytool.1 +++ b/src/java.base/share/man/keytool.1 @@ -1,4 +1,4 @@ -.\" Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved. +.\" Copyright (c) 1998, 2022, 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 @@ -70,6 +70,8 @@ keystore \f[CB]\-storepasswd\f[R]: Changes the store password of a keystore .IP \[bu] 2 \f[CB]\-showinfo\f[R]: Displays security\-related information +.IP \[bu] 2 +\f[CB]\-version\f[R]: Prints the program version .PP See \f[B]Commands and Options\f[R] for a description of these commands with their options. @@ -219,6 +221,10 @@ they perform. \f[B]Commands for Displaying Security\-related Information\f[R]: .IP \[bu] 2 \f[CB]\-showinfo\f[R] +.PP +\f[B]Commands for Displaying Program Version\f[R]: +.IP \[bu] 2 +\f[CB]\-version\f[R] .SH COMMANDS FOR CREATING OR ADDING DATA TO THE KEYSTORE .TP .B \f[CB]\-gencert\f[R] @@ -1314,6 +1320,10 @@ information. The \f[CB]\-tls\f[R] option displays TLS configurations, such as the list of enabled protocols and cipher suites. .RE +.SH COMMANDS FOR DISPLAYING PROGRAM VERSION +.PP +You can use \f[CB]\-version\f[R] to print the program version of +\f[CB]keytool\f[R]. .SH COMMANDS FOR DISPLAYING HELP INFORMATION .PP You can use \f[CB]\-\-help\f[R] to display a list of \f[CB]keytool\f[R] diff --git a/src/jdk.jartool/share/man/jarsigner.1 b/src/jdk.jartool/share/man/jarsigner.1 index a29dc0e714e..290d8de5fcf 100644 --- a/src/jdk.jartool/share/man/jarsigner.1 +++ b/src/jdk.jartool/share/man/jarsigner.1 @@ -1,4 +1,4 @@ -.\" Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. +.\" Copyright (c) 1998, 2022, 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 @@ -33,6 +33,8 @@ jarsigner \- sign and verify Java Archive (JAR) files .PP \f[CB]jarsigner\f[R] \f[CB]\-verify\f[R] [\f[I]options\f[R]] \f[I]jar\-file\f[R] [\f[I]alias\f[R] ...] +.PP +\f[CB]jarsigner\f[R] \f[CB]\-version\f[R] .TP .B \f[I]options\f[R] The command\-line options. @@ -69,6 +71,12 @@ The aliases are defined in the keystore specified by \f[CB]\-keystore\f[R] or the default keystore. .RS .RE +.TP +.B \f[CB]\-version\f[R] +The \f[CB]\-version\f[R] option prints the program version of +\f[CB]jarsigner\f[R]. +.RS +.RE .SH DESCRIPTION .PP The \f[CB]jarsigner\f[R] tool has two purposes: @@ -1079,6 +1087,11 @@ The property keys supported are "jarsigner.all" for all actions, name(s) cannot be set in this file. .RS .RE +.TP +.B \f[CB]\-version\f[R] +Prints the program version. +.RS +.RE .SH DEPRECATED OPTIONS .PP The following \f[CB]jarsigner\f[R] options are deprecated as of JDK 9 and -- GitLab From b9ae77906e9c886ee239871b75c183c5ec7ae846 Mon Sep 17 00:00:00 2001 From: Calvin Cheung Date: Fri, 21 Jan 2022 23:47:09 +0000 Subject: [PATCH 245/564] 8279675: CDS cannot handle non-existent JAR file in bootclassapth Reviewed-by: iklam, minqi --- src/hotspot/share/cds/filemap.cpp | 22 ++++- src/hotspot/share/cds/filemap.hpp | 1 + .../runtime/cds/appcds/NonExistClasspath.java | 90 +++++++++++++++++-- .../cds/appcds/PrintSharedArchiveAndExit.java | 12 +-- .../OptimizeModuleHandlingTest.java | 12 ++- 5 files changed, 122 insertions(+), 15 deletions(-) diff --git a/src/hotspot/share/cds/filemap.cpp b/src/hotspot/share/cds/filemap.cpp index 3a121e3b4ee..5bf1887cfce 100644 --- a/src/hotspot/share/cds/filemap.cpp +++ b/src/hotspot/share/cds/filemap.cpp @@ -767,6 +767,21 @@ int FileMapInfo::num_paths(const char* path) { return npaths; } +// Returns true if a path within the paths exists and has non-zero size. +bool FileMapInfo::check_paths_existence(const char* paths) { + ClasspathStream cp_stream(paths); + bool exist = false; + struct stat st; + while (cp_stream.has_next()) { + const char* path = cp_stream.get_next(); + if (os::stat(path, &st) == 0 && st.st_size > 0) { + exist = true; + break; + } + } + return exist; +} + GrowableArray* FileMapInfo::create_path_array(const char* paths) { GrowableArray* path_array = new GrowableArray(10); JavaThread* current = JavaThread::current(); @@ -850,7 +865,12 @@ bool FileMapInfo::validate_boot_class_paths() { if (relaxed_check) { return true; // ok, relaxed check, runtime has extra boot append path entries } else { - mismatch = true; + ResourceMark rm; + if (check_paths_existence(rp)) { + // If a path exists in the runtime boot paths, it is considered a mismatch + // since there's no boot path specified during dump time. + mismatch = true; + } } } else if (dp_len > 0 && rp != NULL) { int num; diff --git a/src/hotspot/share/cds/filemap.hpp b/src/hotspot/share/cds/filemap.hpp index d29c240b192..ac2ad867f79 100644 --- a/src/hotspot/share/cds/filemap.hpp +++ b/src/hotspot/share/cds/filemap.hpp @@ -554,6 +554,7 @@ public: void seek_to_position(size_t pos); char* skip_first_path_entry(const char* path) NOT_CDS_RETURN_(NULL); int num_paths(const char* path) NOT_CDS_RETURN_(0); + bool check_paths_existence(const char* paths) NOT_CDS_RETURN_(false); GrowableArray* create_path_array(const char* path) NOT_CDS_RETURN_(NULL); bool classpath_failure(const char* msg, const char* name) NOT_CDS_RETURN_(false); bool check_paths(int shared_path_start_idx, int num_paths, diff --git a/test/hotspot/jtreg/runtime/cds/appcds/NonExistClasspath.java b/test/hotspot/jtreg/runtime/cds/appcds/NonExistClasspath.java index a08f1c5ff15..7f2af4bdcab 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/NonExistClasspath.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/NonExistClasspath.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, 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,13 @@ import jdk.test.lib.cds.CDSTestUtils; import jdk.test.lib.process.OutputAnalyzer; public class NonExistClasspath { + static final String outDir = CDSTestUtils.getOutputDir(); + static final String newFile = "non-exist.jar"; + static final String nonExistPath = outDir + File.separator + newFile; + static final String emptyJarPath = outDir + File.separator + "empty.jar"; + static final String errorMessage1 = "Unable to use shared archive"; + static final String errorMessage2 = "shared class paths mismatch"; + public static void main(String[] args) throws Exception { String appJar = JarBuilder.getOrCreateHelloJar(); doTest(appJar, false); @@ -47,13 +54,7 @@ public class NonExistClasspath { } static void doTest(String appJar, boolean bootcp) throws Exception { - String outDir = CDSTestUtils.getOutputDir(); - String newFile = "non-exist.jar"; - String nonExistPath = outDir + File.separator + newFile; - final String errorMessage1 = "Unable to use shared archive"; - final String errorMessage2 = "shared class paths mismatch"; final String errorMessage3 = (bootcp ? "BOOT" : "APP") + " classpath mismatch"; - (new File(nonExistPath)).delete(); String classPath = nonExistPath + File.pathSeparator + appJar; @@ -100,6 +101,81 @@ public class NonExistClasspath { "-Xlog:class+path=trace", "Hello")) .assertAbnormalExit(errorMessage1, errorMessage2, errorMessage3); + + if (bootcp) { + doMoreBCPTests(appJar, errorMessage3); + } + } + + static void doMoreBCPTests(String appJar, String errorMessage3) throws Exception { + + // Dump an archive with non-existent boot class path. + (new File(nonExistPath)).delete(); + TestCommon.testDump("foobar", TestCommon.list("Hello"), make_args(true, nonExistPath, "-cp", appJar)); + + // Run with non-existent boot class path, test should pass. + TestCommon.run(make_args(true, + nonExistPath, + "-cp", appJar, + "-Xlog:class+path=trace", + "Hello")) + .assertNormalExit(); + + // Run with existent boot class path, test should fail. + TestCommon.run(make_args(true, + appJar, + "-cp", appJar, + "-Xlog:class+path=trace", + "Hello")) + .assertAbnormalExit(errorMessage1, errorMessage2, errorMessage3); + + // Dump an archive with existent boot class path. + TestCommon.testDump("foobar", TestCommon.list("Hello"), make_args(true, appJar)); + + // Run with non-existent boot class path, test should fail. + TestCommon.run(make_args(true, + nonExistPath, + "-Xlog:class+path=trace", + "Hello")) + .assertAbnormalExit(errorMessage1, errorMessage2, errorMessage3); + + // Run with existent boot class path, test should pass. + TestCommon.run(make_args(true, + appJar, + "-Xlog:class+path=trace", + "Hello")) + .assertNormalExit(); + + // Test with empty jar file. + (new File(emptyJarPath)).delete(); + (new File(emptyJarPath)).createNewFile(); + + // Dump an archive with an empty jar in the boot class path. + TestCommon.testDump("foobar", TestCommon.list("Hello"), make_args(true, emptyJarPath, "-cp", appJar)); + + // Run with an empty jar in boot class path, test should pass. + TestCommon.run(make_args(true, + emptyJarPath, + "-cp", appJar, + "-Xlog:class+path=trace", + "Hello")) + .assertNormalExit(); + + // Run with non-existent boot class path, test should pass. + TestCommon.run(make_args(true, + nonExistPath, + "-cp", appJar, + "-Xlog:class+path=trace", + "Hello")) + .assertNormalExit(); + + // Run with existent boot class path, test should fail. + TestCommon.run(make_args(true, + appJar, + "-cp", appJar, + "-Xlog:class+path=trace", + "Hello")) + .assertAbnormalExit(errorMessage1, errorMessage2, errorMessage3); } static String[] make_args(boolean bootcp, String cp, String... suffix) { diff --git a/test/hotspot/jtreg/runtime/cds/appcds/PrintSharedArchiveAndExit.java b/test/hotspot/jtreg/runtime/cds/appcds/PrintSharedArchiveAndExit.java index fc34e932dc4..9a74dcb0d3b 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/PrintSharedArchiveAndExit.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/PrintSharedArchiveAndExit.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2022, 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 @@ -87,16 +87,16 @@ public class PrintSharedArchiveAndExit { TestCommon.run("-cp", cp, "-XX:+PrintSharedArchiveAndExit", "Hello") .ifNoMappingFailure(output -> check(output, 0, true, lastCheckMsg)); - log("Execution with simple errors -- with 'simple' errors like missing or modified\n" + - "JAR files, the VM should try to continue to print the remaining information.\n" + - "Use an invalid Boot CP -- all the JAR paths should be checked"); + log("Non-existent boot cp should be ignored, test should pass."); TestCommon.run( "-cp", cp, "-Xbootclasspath/a:foo.jar", "-XX:+PrintSharedArchiveAndExit") - .ifNoMappingFailure(output -> check(output, 1, true, lastCheckMsg, "[BOOT classpath mismatch, ")); + .ifNoMappingFailure(output -> check(output, 0, true, lastCheckMsg)); - log("Use an App CP shorter than the one at dump time -- all the JAR paths should be checked"); + log("Execution with simple errors -- with 'simple' errors like missing or modified\n" + + "JAR files, the VM should try to continue to print the remaining information.\n" + + "Use an App CP shorter than the one at dump time -- all the JAR paths should be checked"); TestCommon.run( "-cp", ".", "-XX:+PrintSharedArchiveAndExit") diff --git a/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/modulepath/OptimizeModuleHandlingTest.java b/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/modulepath/OptimizeModuleHandlingTest.java index 189559a4661..eecc218a71a 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/modulepath/OptimizeModuleHandlingTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/modulepath/OptimizeModuleHandlingTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, 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,16 @@ public class OptimizeModuleHandlingTest { "-Xbootclasspath/a:", ".", "--module-path", libsDir.toString(), MAIN_CLASS) + .assertAbnormalExit(out -> { + out.shouldNotContain(CLASS_FOUND_MESSAGE) + .shouldContain(OPTIMIZE_DISABLED) // mapping info + .shouldContain("Error: Could not find or load main class ."); + }); + tty("11. run with CDS on, --module-path, with -Xbootclasspath/a:."); + TestCommon.run("-Xlog:cds", + "-Xbootclasspath/a:.", + "--module-path", libsDir.toString(), + MAIN_CLASS) .assertAbnormalExit(out -> { out.shouldNotContain(CLASS_FOUND_MESSAGE) .shouldContain(OPTIMIZE_DISABLED) // mapping info -- GitLab From 54c9de26aba24ff5496f97dd6cb95075ab6b9777 Mon Sep 17 00:00:00 2001 From: Andrey Turbanov Date: Sat, 22 Jan 2022 13:56:51 +0000 Subject: [PATCH 246/564] 8275918: Remove unused local variables in java.base security code Reviewed-by: weijun --- .../macosx/classes/apple/security/KeychainStore.java | 2 -- .../classes/com/sun/crypto/provider/BlowfishCrypt.java | 4 ++-- .../classes/java/security/AccessControlContext.java | 1 - .../share/classes/sun/security/pkcs10/PKCS10.java | 3 +-- .../share/classes/sun/security/rsa/RSAPSSSignature.java | 1 - .../classes/sun/security/rsa/RSAPrivateCrtKeyImpl.java | 2 +- .../classes/sun/security/ssl/DHServerKeyExchange.java | 3 +-- .../classes/sun/security/ssl/SSLEngineInputRecord.java | 1 - .../classes/sun/security/x509/CRLNumberExtension.java | 3 +-- .../sun/security/x509/DeltaCRLIndicatorExtension.java | 8 ++------ .../share/classes/sun/security/x509/GeneralSubtrees.java | 5 ++--- .../share/classes/sun/security/x509/X509CertInfo.java | 3 +-- .../share/classes/sun/security/x509/X509Key.java | 9 +++------ 13 files changed, 14 insertions(+), 31 deletions(-) diff --git a/src/java.base/macosx/classes/apple/security/KeychainStore.java b/src/java.base/macosx/classes/apple/security/KeychainStore.java index cf97d4e04c0..688d280f838 100644 --- a/src/java.base/macosx/classes/apple/security/KeychainStore.java +++ b/src/java.base/macosx/classes/apple/security/KeychainStore.java @@ -945,7 +945,6 @@ public final class KeychainStore extends KeyStoreSpi { byte[] safeContentsData; ContentInfo safeContents; DerInputStream sci; - byte[] eAlgId = null; sci = new DerInputStream(safeContentsArray[i].toByteArray()); safeContents = new ContentInfo(sci); @@ -984,7 +983,6 @@ public final class KeychainStore extends KeyStoreSpi { ObjectIdentifier bagId; DerInputStream sbi; DerValue bagValue; - Object bagItem = null; sbi = safeBags[i].toDerInputStream(); bagId = sbi.getOID(); diff --git a/src/java.base/share/classes/com/sun/crypto/provider/BlowfishCrypt.java b/src/java.base/share/classes/com/sun/crypto/provider/BlowfishCrypt.java index f5483f7deff..5fde830e519 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/BlowfishCrypt.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/BlowfishCrypt.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2021, 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 @@ -64,7 +64,7 @@ final class BlowfishCrypt extends SymmetricCipher throw new InvalidKeyException("Key too long (> 448 bits)"); } // Step 1: Init P and then S arrays from pi bytes - int i, j, count; + int i, j; System.arraycopy(pi, 0, p, 0, 18); System.arraycopy(pi, 18, s0, 0, 256); diff --git a/src/java.base/share/classes/java/security/AccessControlContext.java b/src/java.base/share/classes/java/security/AccessControlContext.java index a7f3641beda..1cb35d9bdfc 100644 --- a/src/java.base/share/classes/java/security/AccessControlContext.java +++ b/src/java.base/share/classes/java/security/AccessControlContext.java @@ -916,7 +916,6 @@ public final class AccessControlContext { private boolean containsAllLimits(AccessControlContext that) { boolean match = false; - Permission thisPerm; if (this.permissions == null && that.permissions == null) return true; diff --git a/src/java.base/share/classes/sun/security/pkcs10/PKCS10.java b/src/java.base/share/classes/sun/security/pkcs10/PKCS10.java index 2a28f809888..05bb19fe1c1 100644 --- a/src/java.base/share/classes/sun/security/pkcs10/PKCS10.java +++ b/src/java.base/share/classes/sun/security/pkcs10/PKCS10.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2021, 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 @@ -141,7 +141,6 @@ public class PKCS10 { // Inner sequence: version, name, key, attributes // BigInteger serial; - DerValue val; serial = seq[0].data.getBigInteger(); if (!serial.equals(BigInteger.ZERO)) diff --git a/src/java.base/share/classes/sun/security/rsa/RSAPSSSignature.java b/src/java.base/share/classes/sun/security/rsa/RSAPSSSignature.java index d523e0b8be1..15c143127fb 100644 --- a/src/java.base/share/classes/sun/security/rsa/RSAPSSSignature.java +++ b/src/java.base/share/classes/sun/security/rsa/RSAPSSSignature.java @@ -255,7 +255,6 @@ public class RSAPSSSignature extends SignatureSpi { * internal signature parameters. */ private void isValid(RSAKey rsaKey) throws InvalidKeyException { - AlgorithmParameterSpec keyParams = rsaKey.getParams(); // validate key parameters if (!isCompatible(rsaKey.getParams(), this.sigParams)) { throw new InvalidKeyException diff --git a/src/java.base/share/classes/sun/security/rsa/RSAPrivateCrtKeyImpl.java b/src/java.base/share/classes/sun/security/rsa/RSAPrivateCrtKeyImpl.java index fbc9fda05fa..8ca5135fe85 100644 --- a/src/java.base/share/classes/sun/security/rsa/RSAPrivateCrtKeyImpl.java +++ b/src/java.base/share/classes/sun/security/rsa/RSAPrivateCrtKeyImpl.java @@ -141,7 +141,7 @@ public final class RSAPrivateCrtKeyImpl BigInteger n, BigInteger e, BigInteger d, BigInteger p, BigInteger q, BigInteger pe, BigInteger qe, BigInteger coeff) throws InvalidKeyException { - RSAPrivateKey key; + if ((e.signum() == 0) || (p.signum() == 0) || (q.signum() == 0) || (pe.signum() == 0) || (qe.signum() == 0) || (coeff.signum() == 0)) { diff --git a/src/java.base/share/classes/sun/security/ssl/DHServerKeyExchange.java b/src/java.base/share/classes/sun/security/ssl/DHServerKeyExchange.java index af64383457a..38e97073eb1 100644 --- a/src/java.base/share/classes/sun/security/ssl/DHServerKeyExchange.java +++ b/src/java.base/share/classes/sun/security/ssl/DHServerKeyExchange.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2021, 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 @@ -444,7 +444,6 @@ final class DHServerKeyExchange { */ private void updateSignature(Signature sig, byte[] clntNonce, byte[] svrNonce) throws SignatureException { - int tmp; sig.update(clntNonce); sig.update(svrNonce); diff --git a/src/java.base/share/classes/sun/security/ssl/SSLEngineInputRecord.java b/src/java.base/share/classes/sun/security/ssl/SSLEngineInputRecord.java index 31abe94e9a1..938768aaf76 100644 --- a/src/java.base/share/classes/sun/security/ssl/SSLEngineInputRecord.java +++ b/src/java.base/share/classes/sun/security/ssl/SSLEngineInputRecord.java @@ -358,7 +358,6 @@ final class SSLEngineInputRecord extends InputRecord implements SSLRecord { // The packet should be a complete record. // int srcPos = packet.position(); - int srcLim = packet.limit(); byte firstByte = packet.get(srcPos); byte thirdByte = packet.get(srcPos + 2); diff --git a/src/java.base/share/classes/sun/security/x509/CRLNumberExtension.java b/src/java.base/share/classes/sun/security/x509/CRLNumberExtension.java index 9434e613441..244e9d5df9b 100644 --- a/src/java.base/share/classes/sun/security/x509/CRLNumberExtension.java +++ b/src/java.base/share/classes/sun/security/x509/CRLNumberExtension.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2021, 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 @@ -199,7 +199,6 @@ implements CertAttrSet { * @exception IOException on encoding errors. */ public void encode(OutputStream out) throws IOException { - DerOutputStream tmp = new DerOutputStream(); encode(out, PKIXExtensions.CRLNumber_Id, true); } diff --git a/src/java.base/share/classes/sun/security/x509/DeltaCRLIndicatorExtension.java b/src/java.base/share/classes/sun/security/x509/DeltaCRLIndicatorExtension.java index 10b5a9dc09e..5933758874a 100644 --- a/src/java.base/share/classes/sun/security/x509/DeltaCRLIndicatorExtension.java +++ b/src/java.base/share/classes/sun/security/x509/DeltaCRLIndicatorExtension.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,9 +28,6 @@ package sun.security.x509; import java.io.IOException; import java.io.OutputStream; import java.math.BigInteger; -import java.util.Enumeration; - -import sun.security.util.*; /** * Represents the Delta CRL Indicator Extension. @@ -80,7 +77,7 @@ public class DeltaCRLIndicatorExtension extends CRLNumberExtension { } /** - * Creates a delta CRL indictor extension with the BigInteger value . + * Creates a delta CRL indicator extension with the BigInteger value . * The criticality is set to true. * * @param crlNum the value to be set for the extension. @@ -110,7 +107,6 @@ public class DeltaCRLIndicatorExtension extends CRLNumberExtension { * @exception IOException on encoding errors. */ public void encode(OutputStream out) throws IOException { - DerOutputStream tmp = new DerOutputStream(); super.encode(out, PKIXExtensions.DeltaCRLIndicator_Id, true); } } diff --git a/src/java.base/share/classes/sun/security/x509/GeneralSubtrees.java b/src/java.base/share/classes/sun/security/x509/GeneralSubtrees.java index 8adafe20344..c47fc0c8245 100644 --- a/src/java.base/share/classes/sun/security/x509/GeneralSubtrees.java +++ b/src/java.base/share/classes/sun/security/x509/GeneralSubtrees.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2021, 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 @@ -130,7 +130,7 @@ public class GeneralSubtrees implements Cloneable { /** * Encode the GeneralSubtrees. * - * @param out the DerOutputStrean to encode this object to. + * @param out the DerOutputStream to encode this object to. */ public void encode(DerOutputStream out) throws IOException { DerOutputStream seq = new DerOutputStream(); @@ -346,7 +346,6 @@ public class GeneralSubtrees implements Cloneable { // same type in this. for (int i = 0; i < size(); i++) { GeneralNameInterface thisEntry = getGeneralNameInterface(i); - boolean removeThisEntry = false; // Step 3a: If the widest name of this type in other narrows // thisEntry, remove thisEntry and add widest other to newThis. diff --git a/src/java.base/share/classes/sun/security/x509/X509CertInfo.java b/src/java.base/share/classes/sun/security/x509/X509CertInfo.java index 5fbc9a08f54..09a9ed29320 100644 --- a/src/java.base/share/classes/sun/security/x509/X509CertInfo.java +++ b/src/java.base/share/classes/sun/security/x509/X509CertInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2021, 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 @@ -729,7 +729,6 @@ public class X509CertInfo implements CertAttrSet { "has no extensions"); } SubjectAlternativeNameExtension subjectAltNameExt = null; - SubjectAlternativeNameExtension extValue = null; GeneralNames names = null; try { subjectAltNameExt = (SubjectAlternativeNameExtension) diff --git a/src/java.base/share/classes/sun/security/x509/X509Key.java b/src/java.base/share/classes/sun/security/x509/X509Key.java index faf7cfb927f..19979cb8e7e 100644 --- a/src/java.base/share/classes/sun/security/x509/X509Key.java +++ b/src/java.base/share/classes/sun/security/x509/X509Key.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,6 @@ package sun.security.x509; import java.io.*; import java.util.Arrays; -import java.util.Properties; import java.security.Key; import java.security.PublicKey; import java.security.KeyFactory; @@ -150,10 +149,10 @@ public class X509Key implements PublicKey { * this kind of key, a subclass is returned. Otherwise, a generic * X509Key object is returned. * - *

    This mechanism gurantees that keys (and algorithms) may be + *

    This mechanism guarantees that keys (and algorithms) may be * freely manipulated and transferred, without risk of losing * information. Also, when a key (or algorithm) needs some special - * handling, that specific need can be accomodated. + * handling, that specific need can be accommodated. * * @param in the DER-encoded SubjectPublicKeyInfo value * @exception IOException on data format errors @@ -233,8 +232,6 @@ public class X509Key implements PublicKey { */ String classname = ""; try { - Properties props; - String keytype; Provider sunProvider; sunProvider = Security.getProvider("SUN"); -- GitLab From 30cd47d42124540303e5f5dbbd509b58d8fb90a0 Mon Sep 17 00:00:00 2001 From: Jie Fu Date: Mon, 24 Jan 2022 04:37:51 +0000 Subject: [PATCH 247/564] 8280499: runtime/cds/appcds/TestDumpClassListSource.java fails on platforms without AppCDS custom class loaders support Reviewed-by: iklam --- .../jtreg/runtime/cds/appcds/TestDumpClassListSource.java | 1 + 1 file changed, 1 insertion(+) diff --git a/test/hotspot/jtreg/runtime/cds/appcds/TestDumpClassListSource.java b/test/hotspot/jtreg/runtime/cds/appcds/TestDumpClassListSource.java index 1b8d73a468d..647e44bc455 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/TestDumpClassListSource.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/TestDumpClassListSource.java @@ -28,6 +28,7 @@ * @summary test dynamic dump meanwhile output loaded class list * @bug 8279009 8275084 * @requires vm.cds + * @requires vm.cds.custom.loaders * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds * @compile test-classes/Hello.java ClassSpecializerTestApp.java ClassListWithCustomClassNoSource.java * @run main/othervm TestDumpClassListSource -- GitLab From 9bf6ffa19f1ea9efcadb3396d921305c9ec0b1d1 Mon Sep 17 00:00:00 2001 From: Xin Liu Date: Mon, 24 Jan 2022 05:05:07 +0000 Subject: [PATCH 248/564] 8279124: VM does not handle SIGQUIT during initialization Reviewed-by: dholmes, stuefe --- src/hotspot/os/posix/signals_posix.cpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/hotspot/os/posix/signals_posix.cpp b/src/hotspot/os/posix/signals_posix.cpp index 2c020a79408..895c3cc09ae 100644 --- a/src/hotspot/os/posix/signals_posix.cpp +++ b/src/hotspot/os/posix/signals_posix.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -562,6 +562,11 @@ int JVM_HANDLE_XXX_SIGNAL(int sig, siginfo_t* info, { assert(info != NULL && ucVoid != NULL, "sanity"); + if (sig == BREAK_SIGNAL) { + assert(!ReduceSignalUsage, "Should not happen with -Xrs/-XX:+ReduceSignalUsage"); + return true; // ignore it + } + // Note: it's not uncommon that JNI code uses signal/sigset to install, // then restore certain signal handler (e.g. to temporarily block SIGPIPE, // or have a SIGILL handler when detecting CPU type). When that happens, @@ -1197,7 +1202,7 @@ int os::get_signal_number(const char* signal_name) { return -1; } -void set_signal_handler(int sig) { +void set_signal_handler(int sig, bool do_check = true) { // Check for overwrite. struct sigaction oldAct; sigaction(sig, (struct sigaction*)NULL, &oldAct); @@ -1241,7 +1246,7 @@ void set_signal_handler(int sig) { // Save handler setup for later checking vm_handlers.set(sig, &sigAct); - do_check_signal_periodically[sig] = true; + do_check_signal_periodically[sig] = do_check; int ret = sigaction(sig, &sigAct, &oldAct); assert(ret == 0, "check"); @@ -1279,7 +1284,12 @@ void install_signal_handlers() { set_signal_handler(SIGFPE); PPC64_ONLY(set_signal_handler(SIGTRAP);) set_signal_handler(SIGXFSZ); - + if (!ReduceSignalUsage) { + // This is just for early initialization phase. Intercepting the signal here reduces the risk + // that an attach client accidentally forces HotSpot to quit prematurely. We skip the periodic + // check because late initialization will overwrite it to UserHandler. + set_signal_handler(BREAK_SIGNAL, false); + } #if defined(__APPLE__) // lldb (gdb) installs both standard BSD signal handlers, and mach exception // handlers. By replacing the existing task exception handler, we disable lldb's mach -- GitLab From d1569111d7077dd95b95aea6c42616f85d85e781 Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Mon, 24 Jan 2022 09:18:20 +0000 Subject: [PATCH 249/564] 8280459: Suspicious integer division in Hashtable.readHashtable Reviewed-by: rriggs, bpb --- src/java.base/share/classes/java/util/Hashtable.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java.base/share/classes/java/util/Hashtable.java b/src/java.base/share/classes/java/util/Hashtable.java index 2b6f6e72540..5d722879bc0 100644 --- a/src/java.base/share/classes/java/util/Hashtable.java +++ b/src/java.base/share/classes/java/util/Hashtable.java @@ -1290,7 +1290,7 @@ public class Hashtable // no larger than the clamped original length. Make the length // odd if it's large enough, this helps distribute the entries. // Guard against the length ending up zero, that's not valid. - int length = (int)((elements + elements / 20) / lf) + 3; + int length = (int)(elements * 1.05f / lf) + 3; if (length > elements && (length & 1) == 0) length--; length = Math.min(length, origlength); -- GitLab From ead9feccae75ab0491ce86a707f5056d88ac899a Mon Sep 17 00:00:00 2001 From: Julia Boes Date: Mon, 24 Jan 2022 10:03:40 +0000 Subject: [PATCH 250/564] 8280441: Missing "classpath exception" in several files from jdk.httpserver Reviewed-by: alanb, dfuchs --- .../classes/com/sun/net/httpserver/SimpleFileServer.java | 6 ++++-- .../sun/net/httpserver/simpleserver/FileServerHandler.java | 6 ++++-- .../classes/sun/net/httpserver/simpleserver/JWebServer.java | 6 ++++-- .../share/classes/sun/net/httpserver/simpleserver/Main.java | 6 ++++-- .../sun/net/httpserver/simpleserver/OutputFilter.java | 6 ++++-- .../net/httpserver/simpleserver/ResourceBundleHelper.java | 6 ++++-- .../net/httpserver/simpleserver/SimpleFileServerImpl.java | 6 ++++-- 7 files changed, 28 insertions(+), 14 deletions(-) diff --git a/src/jdk.httpserver/share/classes/com/sun/net/httpserver/SimpleFileServer.java b/src/jdk.httpserver/share/classes/com/sun/net/httpserver/SimpleFileServer.java index a08f48567c9..2952a40b142 100644 --- a/src/jdk.httpserver/share/classes/com/sun/net/httpserver/SimpleFileServer.java +++ b/src/jdk.httpserver/share/classes/com/sun/net/httpserver/SimpleFileServer.java @@ -1,10 +1,12 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022, 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. + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/FileServerHandler.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/FileServerHandler.java index b1b28446b4d..e0e9736cad4 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/FileServerHandler.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/FileServerHandler.java @@ -1,10 +1,12 @@ /* - * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2022, 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. + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/JWebServer.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/JWebServer.java index 59f77abbae8..015d1b95244 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/JWebServer.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/JWebServer.java @@ -1,10 +1,12 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022, 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. + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/Main.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/Main.java index 83441cdbc7f..30535c9296d 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/Main.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/Main.java @@ -1,10 +1,12 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022, 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. + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/OutputFilter.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/OutputFilter.java index bdbcf2361ee..0a4d901303e 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/OutputFilter.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/OutputFilter.java @@ -1,10 +1,12 @@ /* - * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2022, 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. + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/ResourceBundleHelper.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/ResourceBundleHelper.java index 99349fe3474..690722bddb9 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/ResourceBundleHelper.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/ResourceBundleHelper.java @@ -1,10 +1,12 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022, 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. + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/SimpleFileServerImpl.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/SimpleFileServerImpl.java index 852aae5a838..7e97d203b6c 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/SimpleFileServerImpl.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/SimpleFileServerImpl.java @@ -1,10 +1,12 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022, 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. + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -- GitLab From 0567a84d49fccda139388c22d1fc14e4aea6002b Mon Sep 17 00:00:00 2001 From: Jie Fu Date: Mon, 24 Jan 2022 10:52:15 +0000 Subject: [PATCH 251/564] 8280457: Duplicate implementation of dprecision_rounding and dstore_rounding Reviewed-by: vlivanov, shade --- .../share/gc/shared/c2/barrierSetC2.cpp | 4 ++-- src/hotspot/share/opto/graphKit.cpp | 20 +++---------------- src/hotspot/share/opto/graphKit.hpp | 5 +---- src/hotspot/share/opto/parse2.cpp | 10 +++++----- 4 files changed, 11 insertions(+), 28 deletions(-) diff --git a/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp b/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp index c89643a7881..a90565ef705 100644 --- a/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp +++ b/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2022, 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 @@ -96,7 +96,7 @@ Node* BarrierSetC2::store_at_resolved(C2Access& access, C2AccessValue& val) cons GraphKit* kit = parse_access.kit(); if (access.type() == T_DOUBLE) { - Node* new_val = kit->dstore_rounding(val.node()); + Node* new_val = kit->dprecision_rounding(val.node()); val.set_node(new_val); } diff --git a/src/hotspot/share/opto/graphKit.cpp b/src/hotspot/share/opto/graphKit.cpp index 8547f7fed90..da96ebd9169 100644 --- a/src/hotspot/share/opto/graphKit.cpp +++ b/src/hotspot/share/opto/graphKit.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2022, 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 @@ -2350,9 +2350,9 @@ void GraphKit::round_double_arguments(ciMethod* dest_method) { const Type *targ = tf->domain()->field_at(j + TypeFunc::Parms); if (targ->basic_type() == T_DOUBLE) { // If any parameters are doubles, they must be rounded before - // the call, dstore_rounding does gvn.transform + // the call, dprecision_rounding does gvn.transform Node *arg = argument(j); - arg = dstore_rounding(arg); + arg = dprecision_rounding(arg); set_argument(j, arg); } } @@ -2387,20 +2387,6 @@ Node* GraphKit::dprecision_rounding(Node *n) { return n; } -// rounding for non-strict double stores -Node* GraphKit::dstore_rounding(Node* n) { - if (Matcher::strict_fp_requires_explicit_rounding) { -#ifdef IA32 - if (UseSSE < 2) { - return _gvn.transform(new RoundDoubleNode(0, n)); - } -#else - Unimplemented(); -#endif // IA32 - } - return n; -} - //============================================================================= // Generate a fast path/slow path idiom. Graph looks like: // [foo] indicates that 'foo' is a parameter diff --git a/src/hotspot/share/opto/graphKit.hpp b/src/hotspot/share/opto/graphKit.hpp index d815e21956f..b2a85b84f03 100644 --- a/src/hotspot/share/opto/graphKit.hpp +++ b/src/hotspot/share/opto/graphKit.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2022, 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 @@ -790,9 +790,6 @@ class GraphKit : public Phase { // rounding for strict double precision conformance Node* dprecision_rounding(Node* n); - // rounding for non-strict double stores - Node* dstore_rounding(Node* n); - // Helper functions for fast/slow path codes Node* opt_iff(Node* region, Node* iff); Node* make_runtime_call(int flags, diff --git a/src/hotspot/share/opto/parse2.cpp b/src/hotspot/share/opto/parse2.cpp index 183994ecb0d..7ad08841476 100644 --- a/src/hotspot/share/opto/parse2.cpp +++ b/src/hotspot/share/opto/parse2.cpp @@ -2004,19 +2004,19 @@ void Parse::do_one_bytecode() { // double stores case Bytecodes::_dstore_0: - set_pair_local( 0, dstore_rounding(pop_pair()) ); + set_pair_local( 0, dprecision_rounding(pop_pair()) ); break; case Bytecodes::_dstore_1: - set_pair_local( 1, dstore_rounding(pop_pair()) ); + set_pair_local( 1, dprecision_rounding(pop_pair()) ); break; case Bytecodes::_dstore_2: - set_pair_local( 2, dstore_rounding(pop_pair()) ); + set_pair_local( 2, dprecision_rounding(pop_pair()) ); break; case Bytecodes::_dstore_3: - set_pair_local( 3, dstore_rounding(pop_pair()) ); + set_pair_local( 3, dprecision_rounding(pop_pair()) ); break; case Bytecodes::_dstore: - set_pair_local( iter().get_index(), dstore_rounding(pop_pair()) ); + set_pair_local( iter().get_index(), dprecision_rounding(pop_pair()) ); break; case Bytecodes::_pop: dec_sp(1); break; -- GitLab From 7a0a6c95a53c6cb3340328d6543a97807320b740 Mon Sep 17 00:00:00 2001 From: Dmitry Markov Date: Mon, 24 Jan 2022 10:55:13 +0000 Subject: [PATCH 252/564] 8274751: Drag And Drop hangs on Windows Reviewed-by: aivanov, prr, serb --- .../windows/native/libawt/windows/awt_DnDDS.cpp | 6 +++--- .../windows/native/libawt/windows/awt_DnDDT.cpp | 16 ++++++++-------- .../native/libawt/windows/awt_Toolkit.cpp | 9 +++++---- .../windows/native/libawt/windows/awt_Toolkit.h | 5 +++-- 4 files changed, 19 insertions(+), 17 deletions(-) diff --git a/src/java.desktop/windows/native/libawt/windows/awt_DnDDS.cpp b/src/java.desktop/windows/native/libawt/windows/awt_DnDDS.cpp index 0f9fb662bbf..8146d62c4a7 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_DnDDS.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_DnDDS.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -267,13 +267,13 @@ void AwtDragSource::_DoDragDrop(void* param) { dragSource->Signal(); AwtToolkit &toolkit = AwtToolkit::GetInstance(); - toolkit.isInDoDragDropLoop = TRUE; + toolkit.isDnDSourceActive = TRUE; res = ::DoDragDrop(dragSource, dragSource, convertActionsToDROPEFFECT(dragSource->m_actions), &effects ); - toolkit.isInDoDragDropLoop = FALSE; + toolkit.isDnDSourceActive = FALSE; if (effects == DROPEFFECT_NONE && dragSource->m_dwPerformedDropEffect != DROPEFFECT_NONE) { effects = dragSource->m_dwPerformedDropEffect; diff --git a/src/java.desktop/windows/native/libawt/windows/awt_DnDDT.cpp b/src/java.desktop/windows/native/libawt/windows/awt_DnDDT.cpp index 126e7194f86..ed41af9d6bf 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_DnDDT.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_DnDDT.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -141,7 +141,7 @@ static void ScaleDown(POINT &cp, HWND m_window) { HRESULT __stdcall AwtDropTarget::DragEnter(IDataObject __RPC_FAR *pDataObj, DWORD grfKeyState, POINTL pt, DWORD __RPC_FAR *pdwEffect) { TRY; - AwtToolkit::GetInstance().isInDoDragDropLoop = TRUE; + AwtToolkit::GetInstance().isDnDTargetActive = TRUE; if (NULL != m_pIDropTargetHelper) { m_pIDropTargetHelper->DragEnter( m_window, @@ -161,7 +161,7 @@ HRESULT __stdcall AwtDropTarget::DragEnter(IDataObject __RPC_FAR *pDataObj, DWOR (IsLocalDnD() && !IsLocalDataObject(pDataObj))) { *pdwEffect = retEffect; - AwtToolkit::GetInstance().isInDoDragDropLoop = FALSE; + AwtToolkit::GetInstance().isDnDTargetActive = FALSE; return ret; } @@ -173,7 +173,7 @@ HRESULT __stdcall AwtDropTarget::DragEnter(IDataObject __RPC_FAR *pDataObj, DWOR } if (JNU_IsNull(env, m_dtcp) || !JNU_IsNull(env, safe_ExceptionOccurred(env))) { - AwtToolkit::GetInstance().isInDoDragDropLoop = FALSE; + AwtToolkit::GetInstance().isDnDTargetActive = FALSE; return ret; } @@ -200,12 +200,12 @@ HRESULT __stdcall AwtDropTarget::DragEnter(IDataObject __RPC_FAR *pDataObj, DWOR env->ExceptionDescribe(); env->ExceptionClear(); actions = java_awt_dnd_DnDConstants_ACTION_NONE; - AwtToolkit::GetInstance().isInDoDragDropLoop = FALSE; + AwtToolkit::GetInstance().isDnDTargetActive = FALSE; } } catch (std::bad_alloc&) { retEffect = ::convertActionsToDROPEFFECT(actions); *pdwEffect = retEffect; - AwtToolkit::GetInstance().isInDoDragDropLoop = FALSE; + AwtToolkit::GetInstance().isDnDTargetActive = FALSE; throw; } @@ -421,7 +421,7 @@ void AwtDropTarget::DropDone(jboolean success, jint action) { m_dropSuccess = success; m_dropActions = action; AwtToolkit::GetInstance().QuitMessageLoop(AwtToolkit::EXIT_ENCLOSING_LOOP); - AwtToolkit::GetInstance().isInDoDragDropLoop = FALSE; + AwtToolkit::GetInstance().isDnDTargetActive = FALSE; } /** @@ -1136,7 +1136,7 @@ void AwtDropTarget::UnloadCache() { void AwtDropTarget::DragCleanup(void) { UnloadCache(); - AwtToolkit::GetInstance().isInDoDragDropLoop = FALSE; + AwtToolkit::GetInstance().isDnDTargetActive = FALSE; } BOOL AwtDropTarget::IsLocalDataObject(IDataObject __RPC_FAR *pDataObject) { diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp index 355d3207273..17e69d70b15 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2022, 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 @@ -344,7 +344,8 @@ AwtToolkit::AwtToolkit() { m_waitEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL); m_inputMethodWaitEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL); - isInDoDragDropLoop = FALSE; + isDnDSourceActive = FALSE; + isDnDTargetActive = FALSE; eventNumber = 0; } @@ -3012,7 +3013,7 @@ Java_sun_awt_windows_WToolkit_syncNativeQueue(JNIEnv *env, jobject self, jlong t tk.PostMessage(WM_SYNC_WAIT, 0, 0); for(long t = 2; t < timeout && WAIT_TIMEOUT == ::WaitForSingleObject(tk.m_waitEvent, 2); t+=2) { - if (tk.isInDoDragDropLoop) { + if (tk.isDnDSourceActive || tk.isDnDTargetActive) { break; } } @@ -3216,7 +3217,7 @@ LRESULT AwtToolkit::InvokeInputMethodFunction(UINT msg, WPARAM wParam, LPARAM lP * the IME completion. */ CriticalSection::Lock lock(m_inputMethodLock); - if (isInDoDragDropLoop) { + if (isDnDSourceActive || isDnDTargetActive) { SendMessage(msg, wParam, lParam); ::ResetEvent(m_inputMethodWaitEvent); return m_inputMethodData; diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.h b/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.h index a148001842d..ff9baf6464a 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.h +++ b/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2022, 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 @@ -441,7 +441,8 @@ public: HANDLE m_waitEvent; volatile DWORD eventNumber; - volatile BOOL isInDoDragDropLoop; + volatile BOOL isDnDSourceActive; + volatile BOOL isDnDTargetActive; private: HWND CreateToolkitWnd(LPCTSTR name); -- GitLab From f05ff996543d0239383d8b363fdbba15769c4aae Mon Sep 17 00:00:00 2001 From: Andrey Turbanov Date: Mon, 24 Jan 2022 11:10:16 +0000 Subject: [PATCH 253/564] 8280174: Possible NPE in Thread.dispatchUncaughtException Reviewed-by: alanb --- src/java.base/share/classes/java/lang/Thread.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/java.base/share/classes/java/lang/Thread.java b/src/java.base/share/classes/java/lang/Thread.java index 797a7f9f82e..77e0bbc6129 100644 --- a/src/java.base/share/classes/java/lang/Thread.java +++ b/src/java.base/share/classes/java/lang/Thread.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2022, 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 @@ -1976,8 +1976,8 @@ public class Thread implements Runnable { * @return the uncaught exception handler for this thread */ public UncaughtExceptionHandler getUncaughtExceptionHandler() { - return uncaughtExceptionHandler != null ? - uncaughtExceptionHandler : group; + UncaughtExceptionHandler handler = this.uncaughtExceptionHandler; + return handler != null ? handler : group; } /** -- GitLab From afd2805ef2fe72aee04b84956dba5bb5c012ff3c Mon Sep 17 00:00:00 2001 From: Roman Kennke Date: Mon, 24 Jan 2022 11:16:53 +0000 Subject: [PATCH 254/564] 8279534: Consolidate and remove oopDesc::klass_gap methods Reviewed-by: shade, dholmes --- .../share/interpreter/zero/bytecodeInterpreter.cpp | 10 +++++----- src/hotspot/share/oops/oop.hpp | 2 -- src/hotspot/share/oops/oop.inline.hpp | 8 -------- 3 files changed, 5 insertions(+), 15 deletions(-) diff --git a/src/hotspot/share/interpreter/zero/bytecodeInterpreter.cpp b/src/hotspot/share/interpreter/zero/bytecodeInterpreter.cpp index ee3648eaa61..4682c2b8129 100644 --- a/src/hotspot/share/interpreter/zero/bytecodeInterpreter.cpp +++ b/src/hotspot/share/interpreter/zero/bytecodeInterpreter.cpp @@ -1943,12 +1943,12 @@ run: Copy::fill_to_words(result + hdr_size, obj_size - hdr_size, 0); } - oop obj = cast_to_oop(result); + // Initialize header, mirrors MemAllocator. + oopDesc::set_mark(result, markWord::prototype()); + oopDesc::set_klass_gap(result, 0); + oopDesc::release_set_klass(result, ik); - // Initialize header - obj->set_mark(markWord::prototype()); - obj->set_klass_gap(0); - obj->set_klass(ik); + oop obj = cast_to_oop(result); // Must prevent reordering of stores for object initialization // with stores that publish the new object. diff --git a/src/hotspot/share/oops/oop.hpp b/src/hotspot/share/oops/oop.hpp index e7186b6a4ff..994bb677032 100644 --- a/src/hotspot/share/oops/oop.hpp +++ b/src/hotspot/share/oops/oop.hpp @@ -91,8 +91,6 @@ class oopDesc { static inline void release_set_klass(HeapWord* mem, Klass* k); // For klass field compression - inline int klass_gap() const; - inline void set_klass_gap(int z); static inline void set_klass_gap(HeapWord* mem, int z); // size of object header, aligned to platform wordSize diff --git a/src/hotspot/share/oops/oop.inline.hpp b/src/hotspot/share/oops/oop.inline.hpp index 371e97824f7..17ce5bed561 100644 --- a/src/hotspot/share/oops/oop.inline.hpp +++ b/src/hotspot/share/oops/oop.inline.hpp @@ -125,20 +125,12 @@ void oopDesc::release_set_klass(HeapWord* mem, Klass* k) { } } -int oopDesc::klass_gap() const { - return *(int*)(((intptr_t)this) + klass_gap_offset_in_bytes()); -} - void oopDesc::set_klass_gap(HeapWord* mem, int v) { if (UseCompressedClassPointers) { *(int*)(((char*)mem) + klass_gap_offset_in_bytes()) = v; } } -void oopDesc::set_klass_gap(int v) { - set_klass_gap((HeapWord*)this, v); -} - bool oopDesc::is_a(Klass* k) const { return klass()->is_subtype_of(k); } -- GitLab From 4501ddda7f8e0eb9352a937030a62902bfaac647 Mon Sep 17 00:00:00 2001 From: Harold Seigel Date: Mon, 24 Jan 2022 13:33:43 +0000 Subject: [PATCH 255/564] 8214733: runtime/8176717/TestInheritFD.java timed out Reviewed-by: lmesnik, coleenp, dcubed --- test/hotspot/jtreg/runtime/8176717/TestInheritFD.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/test/hotspot/jtreg/runtime/8176717/TestInheritFD.java b/test/hotspot/jtreg/runtime/8176717/TestInheritFD.java index 04a739079f9..37c5280d236 100644 --- a/test/hotspot/jtreg/runtime/8176717/TestInheritFD.java +++ b/test/hotspot/jtreg/runtime/8176717/TestInheritFD.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2022, 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 @@ -79,6 +79,7 @@ public class TestInheritFD { public static final String RETAINS_FD = "VM RESULT => RETAINS FD"; public static final String EXIT = "VM RESULT => VM EXIT"; public static final String LOG_SUFFIX = ".strangelogsuffixthatcanbecheckedfor"; + public static final String USER_DIR = System.getProperty("user.dir"); // first VM public static void main(String[] args) throws Exception { @@ -187,10 +188,10 @@ public class TestInheritFD { static Collection outputContainingFilenames() { long pid = ProcessHandle.current().pid(); - String[] command = lsofCommand().orElseThrow(() -> new RuntimeException("lsof like command not found")); - System.out.println("using command: " + command[0] + " " + command[1]); - return run(command[0], command[1], "" + pid).collect(toList()); + // Only search the directory in which the VM is running (user.dir property). + System.out.println("using command: " + command[0] + " -a +d " + USER_DIR + " " + command[1] + " " + pid); + return run(command[0], "-a", "+d", USER_DIR, command[1], "" + pid).collect(toList()); } static boolean findOpenLogFile(Collection fileNames) { -- GitLab From 44db4794d29c6e0755a6dc0ea1346f48f918155b Mon Sep 17 00:00:00 2001 From: Zhengyu Gu Date: Mon, 24 Jan 2022 13:34:37 +0000 Subject: [PATCH 256/564] 8280391: NMT: Correct NMT tag on CollectedHeap Reviewed-by: kbarrett, tschatzl, mli --- src/hotspot/share/gc/shared/collectedHeap.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hotspot/share/gc/shared/collectedHeap.hpp b/src/hotspot/share/gc/shared/collectedHeap.hpp index 84e545abd29..89cca6777d6 100644 --- a/src/hotspot/share/gc/shared/collectedHeap.hpp +++ b/src/hotspot/share/gc/shared/collectedHeap.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2022, 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 @@ -90,7 +90,7 @@ public: // ShenandoahHeap // ZCollectedHeap // -class CollectedHeap : public CHeapObj { +class CollectedHeap : public CHeapObj { friend class VMStructs; friend class JVMCIVMStructs; friend class IsGCActiveMark; // Block structured external access to _is_gc_active -- GitLab From 18c9cb07891cdd68c06385a28af16e3931b84317 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Mon, 24 Jan 2022 13:52:16 +0000 Subject: [PATCH 257/564] 8280067: Incorrect code generated for unary - on char operand Reviewed-by: jlaskey, vromero --- .../com/sun/tools/javac/jvm/Items.java | 4 +- .../tools/javac/code/CharImmediateValue.java | 185 ++++++++++++++++++ 2 files changed, 187 insertions(+), 2 deletions(-) create mode 100644 test/langtools/tools/javac/code/CharImmediateValue.java diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Items.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Items.java index 170cac2a111..c15287ad45e 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Items.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Items.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2022, 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 @@ -669,7 +669,7 @@ public class Items { } else { switch (targetcode) { case INTcode: - if (Code.truncate(typecode) == INTcode) + if (Code.truncate(typecode) == INTcode && typecode != CHARcode) return this; else return new ImmediateItem( diff --git a/test/langtools/tools/javac/code/CharImmediateValue.java b/test/langtools/tools/javac/code/CharImmediateValue.java new file mode 100644 index 00000000000..38745358be0 --- /dev/null +++ b/test/langtools/tools/javac/code/CharImmediateValue.java @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2022, 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 8280067 + * @summary Verify constant/immediate char values are correctly enhanced to ints when used in unary + * operators + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.code + * jdk.compiler/com.sun.tools.javac.comp + * jdk.compiler/com.sun.tools.javac.jvm + * jdk.compiler/com.sun.tools.javac.main + * jdk.compiler/com.sun.tools.javac.tree + * jdk.compiler/com.sun.tools.javac.util + * jdk.jdeps/com.sun.tools.classfile + * jdk.jdeps/com.sun.tools.javap + * @build toolbox.JarTask toolbox.JavacTask toolbox.JavapTask toolbox.ToolBox + * @compile CharImmediateValue.java + * @run main CharImmediateValue + */ + +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Objects; + +import com.sun.source.util.JavacTask; +import com.sun.source.util.Plugin; +import com.sun.source.util.TaskEvent; +import com.sun.source.util.TaskListener; + +import com.sun.tools.classfile.Attribute; +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.Code_attribute; +import com.sun.tools.classfile.Instruction; +import com.sun.tools.classfile.Opcode; + +import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; +import com.sun.tools.javac.tree.JCTree.JCIdent; +import com.sun.tools.javac.tree.TreeScanner; + +import toolbox.JarTask; +import toolbox.ToolBox; + + +public class CharImmediateValue implements Plugin { + public static void main(String... args) throws Exception { + new CharImmediateValue().runSourceTest(); + new CharImmediateValue().runReplacementTest(); + } + + void runSourceTest() throws Exception { + int param = 0; + Character var = (char) -(false ? (char) param : (char) 2); + } + + void runReplacementTest() throws Exception { + ToolBox tb = new ToolBox(); + Path pluginClasses = Path.of("plugin-classes"); + tb.writeFile(pluginClasses.resolve("META-INF").resolve("services").resolve(Plugin.class.getName()), + CharImmediateValue.class.getName() + System.lineSeparator()); + try (DirectoryStream ds = Files.newDirectoryStream(Path.of(ToolBox.testClasses))) { + for (Path p : ds) { + if (p.getFileName().toString().startsWith("CharImmediateValue") || + p.getFileName().toString().endsWith(".class")) { + Files.copy(p, pluginClasses.resolve(p.getFileName())); + } + } + } + + Path pluginJar = Path.of("plugin.jar"); + new JarTask(tb, pluginJar) + .baseDir(pluginClasses) + .files(".") + .run(); + + Path src = Path.of("src"); + tb.writeJavaFiles(src, + """ + public class Test{ + private static char replace; //this will be replace with a constant "1" after constant folding is done + public static String run() { + char c = (char) - replace; + if (c < 0) { + throw new AssertionError("Incorrect value!"); + } else { + return Integer.toString(c); + } + } + } + """); + Path classes = Files.createDirectories(Path.of("classes")); + + new toolbox.JavacTask(tb) + .classpath(pluginJar) + .options("-XDaccessInternalAPI") + .outdir(classes) + .files(tb.findJavaFiles(src)) + .run() + .writeAll(); + + URLClassLoader cl = new URLClassLoader(new URL[] {classes.toUri().toURL()}); + + String actual = (String) cl.loadClass("Test") + .getMethod("run") + .invoke(null); + String expected = "65535"; + if (!Objects.equals(actual, expected)) { + throw new AssertionError("expected: " + expected + "; but got: " + actual); + } + + Path testClass = classes.resolve("Test.class"); + ClassFile cf = ClassFile.read(testClass); + Code_attribute codeAttr = + (Code_attribute) cf.methods[1].attributes.get(Attribute.Code); + boolean seenCast = false; + for (Instruction i : codeAttr.getInstructions()) { + if (i.getOpcode() == Opcode.I2C) { + seenCast = true; + } + } + if (!seenCast) { + throw new AssertionError("Missing cast!"); + } + } + + // Plugin impl... + + @Override + public String getName() { return "CharImmediateValue"; } + + @Override + public void init(JavacTask task, String... args) { + task.addTaskListener(new TaskListener() { + @Override + public void started(TaskEvent e) { + if (e.getKind() == TaskEvent.Kind.GENERATE) { + convert((JCCompilationUnit) e.getCompilationUnit()); + } + } + }); + } + + @Override + public boolean autoStart() { + return true; + } + + private void convert(JCCompilationUnit toplevel) { + new TreeScanner() { + @Override + public void visitIdent(JCIdent tree) { + if (tree.name.contentEquals("replace")) { + tree.type = tree.type.constType(1); + } + super.visitIdent(tree); + } + }.scan(toplevel); + } + +} -- GitLab From d53d8bd7088c3dac0ca104aed919ad2dcb1cf6af Mon Sep 17 00:00:00 2001 From: Dmitry Kulikov Date: Mon, 24 Jan 2022 14:07:14 +0000 Subject: [PATCH 258/564] 8279315: Add Git support to update_copyright_year.sh script Reviewed-by: erikj --- make/scripts/update_copyright_year.sh | 94 +++++++++++++++++++++------ 1 file changed, 75 insertions(+), 19 deletions(-) diff --git a/make/scripts/update_copyright_year.sh b/make/scripts/update_copyright_year.sh index 0f9ba80fc5a..a825486a941 100644 --- a/make/scripts/update_copyright_year.sh +++ b/make/scripts/update_copyright_year.sh @@ -1,7 +1,7 @@ #!/bin/bash -f # -# Copyright (c) 2010, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2010, 2022, 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,27 +23,87 @@ # questions. # -# Script to update the Copyright YEAR range in Mercurial sources. +# Script to update the Copyright YEAR range in Mercurial & Git sources. # (Originally from xdono, Thanks!) -awk=awk +#------------------------------------------------------------ +copyright="Copyright (c)" +company="Oracle" +#------------------------------------------------------------ + +awk="awk" # Stop on any error set -e +# To allow total changes counting +shopt -s lastpipe + +# Get an absolute path to this script, since that determines the top-level directory. +this_script_dir=`dirname $0` +this_script_dir=`cd $this_script_dir > /dev/null && pwd` + # Temp area tmp=/tmp/`basename $0`.${USER}.$$ rm -f -r ${tmp} mkdir -p ${tmp} total=0 +# Default or supplied company name +if [ "$3" != "" ] ; then + company="$3" +fi + # This year or supplied year -if [ "$1" != "" ] ; then - year="$1" +if [ "$2" != "" ] ; then + year="$2" else year=`date +%Y` fi +# VCS select +vcs="$1" + +if [ -z "$vcs" ] ; then + git_found=false + hg_found=false + + [ -d "${this_script_dir}/../../.git" ] && git_found=true + [ -d "${this_script_dir}/../../.hg" ] && hg_found=true + + if [ "$git_found" == "true" ] && [ "$hg_found" == "false" ] ; then + vcs="git" + elif [ "$hg_found" == "true" ] && [ "$git_found" == "false" ] ; then + vcs="hg" + else + echo "Error: could not auto-detect version control system" + vcs="" + fi +fi + +case "$vcs" in + "git") + echo "Using Git version control system" + vcs_status=(git ls-files -m) + vcs_list_changesets=(git log --no-merges --since="${year}-01-01T00:00:00Z" --until="${year}-12-31T23:59:59Z" --pretty=tformat:"%H") + vcs_changeset_message=(git log -1 --pretty=tformat:"%B") # followed by ${changeset} + vcs_changeset_files=(git diff-tree --no-commit-id --name-only -r) # followed by ${changeset} + ;; + + "hg") + echo "Using Mercurial version control system" + vcs_status=(hg status) + vcs_list_changesets=(hg log --no-merges -v -d "${year}-01-01 to ${year}-12-31" --template '{node}\n') + vcs_changeset_message=(hg log -l1 --template '{desc}\n' --rev) # followed by ${changeset} + vcs_changeset_files=(hg log -l1 -v --template '{files}\n' --rev) # followed by ${changeset} + ;; + + *) + echo "Usage: `basename "$0"` [year [company]]" + exit 1 + ;; +esac + # Return true if it makes sense to edit this file saneFileToCheck() { @@ -68,8 +128,6 @@ updateFile() # file { changed="false" if [ `saneFileToCheck "$1"` = "true" ] ; then - copyright="Copyright (c)" - company="Oracle" rm -f $1.OLD mv $1 $1.OLD cat $1.OLD | \ @@ -94,12 +152,10 @@ updateChangesetFiles() # changeset count=0 files=${tmp}/files.$1 rm -f ${files} - hg log -l1 --rev $1 -v --template '{files}\n' | expand \ + "${vcs_changeset_files[@]}" "$1" | expand \ | ${awk} -F' ' '{for(i=1;i<=NF;i++)print $i}' \ > ${files} if [ -f "${files}" -a -s "${files}" ] ; then - copyright="Copyright (c)" - company="Oracle" fcount=`cat ${files}| wc -l` for i in `cat ${files}` ; do if [ `updateFile "${i}"` = "true" ] ; then @@ -116,8 +172,8 @@ updateChangesetFiles() # changeset printf " ERROR: No files changed in the changeset? Must be a mistake.\n" set -x ls -al ${files} - hg log -l1 --rev $1 -v --template '{files}\n' - hg log -l1 --rev $1 -v --template '{files}\n' | expand \ + "${vcs_changeset_files[@]}" "$1" + "${vcs_changeset_files[@]}" "$1" | expand \ | ${awk} -F' ' '{for(i=1;i<=NF;i++)print $i}' set +x exit 1 @@ -126,16 +182,16 @@ updateChangesetFiles() # changeset } # Check if repository is clean -previous=`hg status|wc -l` +previous=`"${vcs_status[@]}"|wc -l` if [ ${previous} -ne 0 ] ; then echo "WARNING: This repository contains previously edited working set files." - echo " hg status | wc -l = `hg status | wc -l`" + echo " ${vcs_status[*]} | wc -l = `"${vcs_status[@]}" | wc -l`" fi # Get all changesets this year all_changesets=${tmp}/all_changesets rm -f ${all_changesets} -hg log --no-merges -v -d "${year}-01-01 to ${year}-12-31" --template '{node}\n' > ${all_changesets} +"${vcs_list_changesets[@]}" > ${all_changesets} # Check changeset to see if it is Copyright only changes, filter changesets if [ -s ${all_changesets} ] ; then @@ -146,7 +202,7 @@ if [ -s ${all_changesets} ] ; then desc=${tmp}/desc.${changeset} rm -f ${desc} echo "------------------------------------------------" - hg log -l1 --rev ${changeset} --template '{desc}\n' > ${desc} + "${vcs_changeset_message[@]}" "${changeset}" > ${desc} printf "%d: %s\n%s\n" ${index} "${changeset}" "`cat ${desc}|head -1`" if [ "${year}" = "2010" ] ; then if cat ${desc} | fgrep -i "Added tag" > /dev/null ; then @@ -175,18 +231,18 @@ if [ ${total} -gt 0 ] ; then echo "---------------------------------------------" echo "Updated the copyright year on a total of ${total} files." if [ ${previous} -eq 0 ] ; then - echo "This count should match the count of modified files in the repository: hg status -m" + echo "This count should match the count of modified files in the repository: ${vcs_status[*]}" else echo "WARNING: This repository contained previously edited working set files." fi - echo " hg status -m | wc -l = `hg status -m | wc -l`" + echo " ${vcs_status[*]} | wc -l = `"${vcs_status[@]}" | wc -l`" else echo "---------------------------------------------" echo "No files were changed" if [ ${previous} -ne 0 ] ; then echo "WARNING: This repository contained previously edited working set files." fi - echo " hg status -m | wc -l = `hg status -m | wc -l`" + echo " ${vcs_status[*]} | wc -l = `"${vcs_status[@]}" | wc -l`" fi # Cleanup -- GitLab From 2b13341500cb9474f5fd6375b97d102ffb635b13 Mon Sep 17 00:00:00 2001 From: Angelos Bimpoudis Date: Mon, 24 Jan 2022 15:09:17 +0000 Subject: [PATCH 259/564] 8036019: Insufficient alternatives listed in some errors produced by the parser Reviewed-by: vromero --- .../sun/tools/javac/parser/JavacParser.java | 6 +-- .../tools/javac/resources/compiler.properties | 3 ++ test/langtools/tools/javac/T8036019.java | 46 +++++++++++++++++++ test/langtools/tools/javac/T8036019.out | 10 ++++ .../typeAnnotations/6967002/T6967002.out | 2 +- .../AnnotationMissingElementValue.java | 28 +++++++++++ .../tools/javac/enum/EnumMembersOrder.out | 2 +- .../tools/javac/parser/7157165/T7157165.out | 2 +- .../parser/SingleCommaAnnotationValueFail.out | 2 +- 9 files changed, 94 insertions(+), 7 deletions(-) create mode 100644 test/langtools/tools/javac/T8036019.java create mode 100644 test/langtools/tools/javac/T8036019.out create mode 100644 test/langtools/tools/javac/diags/examples/AnnotationMissingElementValue.java diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java index 4b508c4bdf0..b14673532bf 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java @@ -2035,7 +2035,7 @@ public class JavacParser implements Parser { args.append(parseExpression()); } } - accept(RPAREN); + accept(RPAREN, tk -> Errors.Expected2(RPAREN, COMMA)); } else { syntaxError(token.pos, Errors.Expected(LPAREN)); } @@ -2123,7 +2123,7 @@ public class JavacParser implements Parser { nextToken(); break; default: - args.append(syntaxError(token.pos, Errors.Expected(GT))); + args.append(syntaxError(token.pos, Errors.Expected2(GT, COMMA))); break; } return args.toList(); @@ -3379,7 +3379,7 @@ public class JavacParser implements Parser { buf.append(annotationValue()); } } - accept(RBRACE); + accept(RBRACE, tk -> Errors.AnnotationMissingElementValue); return toP(F.at(pos).NewArray(null, List.nil(), buf.toList())); default: selectExprMode(); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties index ae2f1f8c6fc..fddd3e935e1 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties @@ -118,6 +118,9 @@ compiler.err.already.defined.static.single.import=\ compiler.err.already.defined.this.unit=\ {0} is already defined in this compilation unit +compiler.err.annotation.missing.element.value=\ + annotation is missing element value + # 0: type, 1: list of name compiler.err.annotation.missing.default.value=\ annotation @{0} is missing a default value for the element ''{1}'' diff --git a/test/langtools/tools/javac/T8036019.java b/test/langtools/tools/javac/T8036019.java new file mode 100644 index 00000000000..709b8abba46 --- /dev/null +++ b/test/langtools/tools/javac/T8036019.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2021, 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 8036019 + * @summary Insufficient alternatives listed in some errors produced by the parser + * @compile/fail/ref=T8036019.out -XDrawDiagnostics T8036019.java + */ + + +public class T8036019 { + enum E { + E(String value) { } + } + + interface A {} + interface B {} + public class Foo { + Foo foo1 = null; + } + + @SuppressWarnings({,0}) + public class AV { + } +} diff --git a/test/langtools/tools/javac/T8036019.out b/test/langtools/tools/javac/T8036019.out new file mode 100644 index 00000000000..2c874175793 --- /dev/null +++ b/test/langtools/tools/javac/T8036019.out @@ -0,0 +1,10 @@ +T8036019.java:34:17: compiler.err.expected2: ')', ',' +T8036019.java:34:23: compiler.err.expected3: ',', '}', ';' +T8036019.java:34:25: compiler.err.enum.constant.expected +T8036019.java:40:24: compiler.err.expected2: >, ',' +T8036019.java:40:26: compiler.err.expected: token.identifier +T8036019.java:40:32: compiler.err.expected: token.identifier +T8036019.java:43:25: compiler.err.annotation.missing.element.value +T8036019.java:43:27: compiler.err.expected4: class, interface, enum, record +T8036019.java:46:1: compiler.err.expected4: class, interface, enum, record +9 errors \ No newline at end of file diff --git a/test/langtools/tools/javac/annotations/typeAnnotations/6967002/T6967002.out b/test/langtools/tools/javac/annotations/typeAnnotations/6967002/T6967002.out index 86480c2bfa8..d9a3545d31d 100644 --- a/test/langtools/tools/javac/annotations/typeAnnotations/6967002/T6967002.out +++ b/test/langtools/tools/javac/annotations/typeAnnotations/6967002/T6967002.out @@ -1,2 +1,2 @@ -T6967002.java:10:22: compiler.err.expected: ')' +T6967002.java:10:22: compiler.err.expected2: ')', ',' 1 error diff --git a/test/langtools/tools/javac/diags/examples/AnnotationMissingElementValue.java b/test/langtools/tools/javac/diags/examples/AnnotationMissingElementValue.java new file mode 100644 index 00000000000..65f24aad316 --- /dev/null +++ b/test/langtools/tools/javac/diags/examples/AnnotationMissingElementValue.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2010, 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. + */ + +// key: compiler.err.annotation.missing.element.value + +@SuppressWarnings({,0}) +public class AV { +} diff --git a/test/langtools/tools/javac/enum/EnumMembersOrder.out b/test/langtools/tools/javac/enum/EnumMembersOrder.out index b1e01860f34..94aff47aca8 100644 --- a/test/langtools/tools/javac/enum/EnumMembersOrder.out +++ b/test/langtools/tools/javac/enum/EnumMembersOrder.out @@ -1,4 +1,4 @@ -EnumMembersOrder.java:11:16: compiler.err.expected: ')' +EnumMembersOrder.java:11:16: compiler.err.expected2: ')', ',' EnumMembersOrder.java:11:18: compiler.err.expected3: ',', '}', ';' EnumMembersOrder.java:11:20: compiler.err.enum.constant.expected 3 errors diff --git a/test/langtools/tools/javac/parser/7157165/T7157165.out b/test/langtools/tools/javac/parser/7157165/T7157165.out index deb580df96c..7552381ba15 100644 --- a/test/langtools/tools/javac/parser/7157165/T7157165.out +++ b/test/langtools/tools/javac/parser/7157165/T7157165.out @@ -1,4 +1,4 @@ -T7157165.java:11:20: compiler.err.expected: > +T7157165.java:11:20: compiler.err.expected2: >, ',' T7157165.java:11:22: compiler.err.expected: token.identifier T7157165.java:11:28: compiler.err.expected: token.identifier 3 errors diff --git a/test/langtools/tools/javac/parser/SingleCommaAnnotationValueFail.out b/test/langtools/tools/javac/parser/SingleCommaAnnotationValueFail.out index 23d1082361b..05d27bc67df 100644 --- a/test/langtools/tools/javac/parser/SingleCommaAnnotationValueFail.out +++ b/test/langtools/tools/javac/parser/SingleCommaAnnotationValueFail.out @@ -1,3 +1,3 @@ -SingleCommaAnnotationValueFail.java:11:12: compiler.err.expected: '}' +SingleCommaAnnotationValueFail.java:11:12: compiler.err.annotation.missing.element.value SingleCommaAnnotationValueFail.java:11:14: compiler.err.expected4: class, interface, enum, record 2 errors -- GitLab From 4b329addf1aca4b5f67057b5c6852d283d0c8f49 Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Mon, 24 Jan 2022 17:08:50 +0000 Subject: [PATCH 260/564] 8280496: Remove unused G1PageBasedVirtualSpace::pretouch_internal Reviewed-by: tschatzl, sjohanss, mli --- src/hotspot/share/gc/g1/g1PageBasedVirtualSpace.cpp | 9 +-------- src/hotspot/share/gc/g1/g1PageBasedVirtualSpace.hpp | 5 +---- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1PageBasedVirtualSpace.cpp b/src/hotspot/share/gc/g1/g1PageBasedVirtualSpace.cpp index 7a164e6461f..94f51c8fdd1 100644 --- a/src/hotspot/share/gc/g1/g1PageBasedVirtualSpace.cpp +++ b/src/hotspot/share/gc/g1/g1PageBasedVirtualSpace.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2022, 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 @@ -178,13 +178,6 @@ char* G1PageBasedVirtualSpace::bounded_end_addr(size_t end_page) const { return MIN2(_high_boundary, page_start(end_page)); } -void G1PageBasedVirtualSpace::pretouch_internal(size_t start_page, size_t end_page) { - guarantee(start_page < end_page, - "Given start page " SIZE_FORMAT " is larger or equal to end page " SIZE_FORMAT, start_page, end_page); - - os::pretouch_memory(page_start(start_page), bounded_end_addr(end_page), _page_size); -} - bool G1PageBasedVirtualSpace::commit(size_t start_page, size_t size_in_pages) { // We need to make sure to commit all pages covered by the given area. guarantee(is_area_uncommitted(start_page, size_in_pages), diff --git a/src/hotspot/share/gc/g1/g1PageBasedVirtualSpace.hpp b/src/hotspot/share/gc/g1/g1PageBasedVirtualSpace.hpp index 8b68ad60e56..0b97656c883 100644 --- a/src/hotspot/share/gc/g1/g1PageBasedVirtualSpace.hpp +++ b/src/hotspot/share/gc/g1/g1PageBasedVirtualSpace.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2022, 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 @@ -87,9 +87,6 @@ class G1PageBasedVirtualSpace { // Uncommit the given memory range. void uncommit_internal(size_t start_page, size_t end_page); - // Pretouch the given memory range. - void pretouch_internal(size_t start_page, size_t end_page); - // Returns the index of the page which contains the given address. size_t addr_to_page_index(char* addr) const; -- GitLab From 1c7769d35b3a2aa4afe3125239dbfa1da5cfdeee Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Mon, 24 Jan 2022 17:23:14 +0000 Subject: [PATCH 261/564] 8280437: Move G1BufferNodeList to gc/shared Reviewed-by: sjohanss, iwalulya, mli --- src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp | 10 +++++----- src/hotspot/share/gc/g1/g1DirtyCardQueue.hpp | 8 ++++---- src/hotspot/share/gc/g1/g1RedirtyCardsQueue.cpp | 10 +++++----- src/hotspot/share/gc/g1/g1RedirtyCardsQueue.hpp | 10 +++++----- src/hotspot/share/gc/g1/g1RemSet.cpp | 5 +++-- .../bufferNodeList.cpp} | 12 ++++++------ .../bufferNodeList.hpp} | 15 +++++++-------- 7 files changed, 35 insertions(+), 35 deletions(-) rename src/hotspot/share/gc/{g1/g1BufferNodeList.cpp => shared/bufferNodeList.cpp} (80%) rename src/hotspot/share/gc/{g1/g1BufferNodeList.hpp => shared/bufferNodeList.hpp} (79%) diff --git a/src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp b/src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp index 8f704fce350..4ef40d29f16 100644 --- a/src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp +++ b/src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp @@ -24,7 +24,6 @@ #include "precompiled.hpp" #include "gc/g1/g1BarrierSet.inline.hpp" -#include "gc/g1/g1BufferNodeList.hpp" #include "gc/g1/g1CardTableEntryClosure.hpp" #include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1ConcurrentRefineStats.hpp" @@ -35,6 +34,7 @@ #include "gc/g1/g1RemSet.hpp" #include "gc/g1/g1ThreadLocalData.hpp" #include "gc/g1/heapRegionRemSet.inline.hpp" +#include "gc/shared/bufferNodeList.hpp" #include "gc/shared/suspendibleThreadSet.hpp" #include "memory/iterator.hpp" #include "runtime/atomic.hpp" @@ -313,7 +313,7 @@ void G1DirtyCardQueueSet::enqueue_all_paused_buffers() { } void G1DirtyCardQueueSet::abandon_completed_buffers() { - G1BufferNodeList list = take_all_completed_buffers(); + BufferNodeList list = take_all_completed_buffers(); BufferNode* buffers_to_delete = list._head; while (buffers_to_delete != NULL) { BufferNode* bn = buffers_to_delete; @@ -334,20 +334,20 @@ void G1DirtyCardQueueSet::notify_if_necessary() { // result. The queue sets must share the same allocator. void G1DirtyCardQueueSet::merge_bufferlists(G1RedirtyCardsQueueSet* src) { assert(allocator() == src->allocator(), "precondition"); - const G1BufferNodeList from = src->take_all_completed_buffers(); + const BufferNodeList from = src->take_all_completed_buffers(); if (from._head != NULL) { Atomic::add(&_num_cards, from._entry_count); _completed.append(*from._head, *from._tail); } } -G1BufferNodeList G1DirtyCardQueueSet::take_all_completed_buffers() { +BufferNodeList G1DirtyCardQueueSet::take_all_completed_buffers() { enqueue_all_paused_buffers(); verify_num_cards(); Pair pair = _completed.take_all(); size_t num_cards = Atomic::load(&_num_cards); Atomic::store(&_num_cards, size_t(0)); - return G1BufferNodeList(pair.first, pair.second, num_cards); + return BufferNodeList(pair.first, pair.second, num_cards); } class G1RefineBufferedCards : public StackObj { diff --git a/src/hotspot/share/gc/g1/g1DirtyCardQueue.hpp b/src/hotspot/share/gc/g1/g1DirtyCardQueue.hpp index 9e9ad0ee80c..051e29058eb 100644 --- a/src/hotspot/share/gc/g1/g1DirtyCardQueue.hpp +++ b/src/hotspot/share/gc/g1/g1DirtyCardQueue.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2022, 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,10 +25,10 @@ #ifndef SHARE_GC_G1_G1DIRTYCARDQUEUE_HPP #define SHARE_GC_G1_G1DIRTYCARDQUEUE_HPP -#include "gc/g1/g1BufferNodeList.hpp" #include "gc/g1/g1FreeIdSet.hpp" #include "gc/g1/g1CardTable.hpp" #include "gc/g1/g1ConcurrentRefineStats.hpp" +#include "gc/shared/bufferNodeList.hpp" #include "gc/shared/ptrQueue.hpp" #include "memory/allocation.hpp" #include "memory/padded.hpp" @@ -69,7 +69,7 @@ public: class G1DirtyCardQueueSet: public PtrQueueSet { // Head and tail of a list of BufferNodes, linked through their next() - // fields. Similar to G1BufferNodeList, but without the _entry_count. + // fields. Similar to BufferNodeList, but without the _entry_count. struct HeadTail { BufferNode* _head; BufferNode* _tail; @@ -275,7 +275,7 @@ public: void merge_bufferlists(G1RedirtyCardsQueueSet* src); - G1BufferNodeList take_all_completed_buffers(); + BufferNodeList take_all_completed_buffers(); void flush_queue(G1DirtyCardQueue& queue); diff --git a/src/hotspot/share/gc/g1/g1RedirtyCardsQueue.cpp b/src/hotspot/share/gc/g1/g1RedirtyCardsQueue.cpp index a1802e01821..d6c2ae148be 100644 --- a/src/hotspot/share/gc/g1/g1RedirtyCardsQueue.cpp +++ b/src/hotspot/share/gc/g1/g1RedirtyCardsQueue.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, 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 @@ -67,7 +67,7 @@ void G1RedirtyCardsLocalQueueSet::enqueue(void* value) { void G1RedirtyCardsLocalQueueSet::flush() { flush_queue(_queue); _shared_qset->add_bufferlist(_buffers); - _buffers = G1BufferNodeList(); + _buffers = BufferNodeList(); } // G1RedirtyCardsLocalQueueSet::Queue @@ -109,9 +109,9 @@ BufferNode* G1RedirtyCardsQueueSet::all_completed_buffers() const { return _list.top(); } -G1BufferNodeList G1RedirtyCardsQueueSet::take_all_completed_buffers() { +BufferNodeList G1RedirtyCardsQueueSet::take_all_completed_buffers() { DEBUG_ONLY(_collecting = false;) - G1BufferNodeList result(_list.pop_all(), _tail, _entry_count); + BufferNodeList result(_list.pop_all(), _tail, _entry_count); _tail = NULL; _entry_count = 0; DEBUG_ONLY(_collecting = true;) @@ -135,7 +135,7 @@ void G1RedirtyCardsQueueSet::enqueue_completed_buffer(BufferNode* node) { update_tail(node); } -void G1RedirtyCardsQueueSet::add_bufferlist(const G1BufferNodeList& buffers) { +void G1RedirtyCardsQueueSet::add_bufferlist(const BufferNodeList& buffers) { assert(_collecting, "precondition"); if (buffers._head != NULL) { assert(buffers._tail != NULL, "invariant"); diff --git a/src/hotspot/share/gc/g1/g1RedirtyCardsQueue.hpp b/src/hotspot/share/gc/g1/g1RedirtyCardsQueue.hpp index 26bb78c4096..b464d377298 100644 --- a/src/hotspot/share/gc/g1/g1RedirtyCardsQueue.hpp +++ b/src/hotspot/share/gc/g1/g1RedirtyCardsQueue.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, 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 @@ #ifndef SHARE_GC_G1_G1REDIRTYCARDSQUEUE_HPP #define SHARE_GC_G1_G1REDIRTYCARDSQUEUE_HPP -#include "gc/g1/g1BufferNodeList.hpp" +#include "gc/shared/bufferNodeList.hpp" #include "gc/shared/ptrQueue.hpp" #include "memory/padded.hpp" #include "utilities/macros.hpp" @@ -42,7 +42,7 @@ class G1RedirtyCardsLocalQueueSet : private PtrQueueSet { }; G1RedirtyCardsQueueSet* _shared_qset; - G1BufferNodeList _buffers; + BufferNodeList _buffers; Queue _queue; // Add the buffer to the local list. @@ -84,12 +84,12 @@ public: // Collect buffers. These functions are thread-safe. // precondition: Must not be concurrent with buffer processing. virtual void enqueue_completed_buffer(BufferNode* node); - void add_bufferlist(const G1BufferNodeList& buffers); + void add_bufferlist(const BufferNodeList& buffers); // Processing phase operations. // precondition: Must not be concurrent with buffer collection. BufferNode* all_completed_buffers() const; - G1BufferNodeList take_all_completed_buffers(); + BufferNodeList take_all_completed_buffers(); }; #endif // SHARE_GC_G1_G1REDIRTYCARDSQUEUE_HPP diff --git a/src/hotspot/share/gc/g1/g1RemSet.cpp b/src/hotspot/share/gc/g1/g1RemSet.cpp index c8f3b0d49b2..603ddbc1e26 100644 --- a/src/hotspot/share/gc/g1/g1RemSet.cpp +++ b/src/hotspot/share/gc/g1/g1RemSet.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2022, 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 @@ -45,6 +45,7 @@ #include "gc/g1/heapRegion.inline.hpp" #include "gc/g1/heapRegionManager.inline.hpp" #include "gc/g1/heapRegionRemSet.inline.hpp" +#include "gc/shared/bufferNodeList.hpp" #include "gc/shared/gcTraceTime.inline.hpp" #include "gc/shared/ptrQueue.hpp" #include "gc/shared/suspendibleThreadSet.hpp" @@ -1429,7 +1430,7 @@ public: { if (initial_evacuation) { G1DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set(); - G1BufferNodeList buffers = dcqs.take_all_completed_buffers(); + BufferNodeList buffers = dcqs.take_all_completed_buffers(); if (buffers._entry_count != 0) { _dirty_card_buffers.prepend(*buffers._head, *buffers._tail); } diff --git a/src/hotspot/share/gc/g1/g1BufferNodeList.cpp b/src/hotspot/share/gc/shared/bufferNodeList.cpp similarity index 80% rename from src/hotspot/share/gc/g1/g1BufferNodeList.cpp rename to src/hotspot/share/gc/shared/bufferNodeList.cpp index 3b89b0c7cd7..bcf4b42ec96 100644 --- a/src/hotspot/share/gc/g1/g1BufferNodeList.cpp +++ b/src/hotspot/share/gc/shared/bufferNodeList.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, 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,15 +23,15 @@ */ #include "precompiled.hpp" -#include "gc/g1/g1BufferNodeList.hpp" +#include "gc/shared/bufferNodeList.hpp" #include "utilities/debug.hpp" -G1BufferNodeList::G1BufferNodeList() : +BufferNodeList::BufferNodeList() : _head(NULL), _tail(NULL), _entry_count(0) {} -G1BufferNodeList::G1BufferNodeList(BufferNode* head, - BufferNode* tail, - size_t entry_count) : +BufferNodeList::BufferNodeList(BufferNode* head, + BufferNode* tail, + size_t entry_count) : _head(head), _tail(tail), _entry_count(entry_count) { assert((_head == NULL) == (_tail == NULL), "invariant"); diff --git a/src/hotspot/share/gc/g1/g1BufferNodeList.hpp b/src/hotspot/share/gc/shared/bufferNodeList.hpp similarity index 79% rename from src/hotspot/share/gc/g1/g1BufferNodeList.hpp rename to src/hotspot/share/gc/shared/bufferNodeList.hpp index 785c3118f9b..ae66a1fcc71 100644 --- a/src/hotspot/share/gc/g1/g1BufferNodeList.hpp +++ b/src/hotspot/share/gc/shared/bufferNodeList.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,21 +22,20 @@ * */ -#ifndef SHARE_GC_G1_G1BUFFERNODELIST_HPP -#define SHARE_GC_G1_G1BUFFERNODELIST_HPP +#ifndef SHARE_GC_SHARED_BUFFERNODELIST_HPP +#define SHARE_GC_SHARED_BUFFERNODELIST_HPP #include "utilities/globalDefinitions.hpp" class BufferNode; -struct G1BufferNodeList { +struct BufferNodeList { BufferNode* _head; // First node in list or NULL if empty. BufferNode* _tail; // Last node in list or NULL if empty. size_t _entry_count; // Sum of entries in nodes in list. - G1BufferNodeList(); - G1BufferNodeList(BufferNode* head, BufferNode* tail, size_t entry_count); + BufferNodeList(); + BufferNodeList(BufferNode* head, BufferNode* tail, size_t entry_count); }; -#endif // SHARE_GC_G1_G1BUFFERNODELIST_HPP - +#endif // SHARE_GC_SHARED_BUFFERNODELIST_HPP -- GitLab From dae2226a538f7156056d1f101fb5b4d1c6f72520 Mon Sep 17 00:00:00 2001 From: Alexey Ivanov Date: Mon, 24 Jan 2022 18:30:31 +0000 Subject: [PATCH 262/564] 8279795: Fix typo in BasicFileChooserUI: Constucts -> Constructs Reviewed-by: prr, serb --- .../swing/plaf/basic/BasicFileChooserUI.java | 72 ++++++++++++++----- 1 file changed, 55 insertions(+), 17 deletions(-) diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicFileChooserUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicFileChooserUI.java index 33f42da00f8..439101c0ef2 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicFileChooserUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicFileChooserUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2022, 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,21 +25,58 @@ package javax.swing.plaf.basic; -import javax.swing.*; -import javax.swing.filechooser.*; -import javax.swing.filechooser.FileFilter; -import javax.swing.event.*; -import javax.swing.plaf.*; -import java.awt.*; -import java.awt.event.*; -import java.awt.datatransfer.*; -import java.beans.*; -import java.io.*; -import java.util.*; +import java.awt.BorderLayout; +import java.awt.Toolkit; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.event.ActionEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.beans.PropertyChangeListener; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Hashtable; import java.util.List; -import java.util.regex.*; +import java.util.Locale; +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.ActionMap; +import javax.swing.Icon; +import javax.swing.InputMap; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JFileChooser; +import javax.swing.JList; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JTable; +import javax.swing.LookAndFeel; +import javax.swing.SwingUtilities; +import javax.swing.TransferHandler; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import javax.swing.filechooser.FileFilter; +import javax.swing.filechooser.FileSystemView; +import javax.swing.filechooser.FileView; +import javax.swing.plaf.ActionMapUIResource; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.FileChooserUI; +import javax.swing.plaf.UIResource; + import sun.awt.shell.ShellFolder; -import sun.swing.*; +import sun.swing.DefaultLookup; +import sun.swing.FilePane; +import sun.swing.SwingUtilities2; +import sun.swing.UIAction; /** * Basic L&F implementation of a FileChooser. @@ -723,11 +760,12 @@ public class BasicFileChooserUI extends FileChooserUI { // new functionality add it to the Handler, but make sure this // class calls into the Handler. Handler handler; + /** - * Constucts a {@code DoubleClickListener}. - * @param list the lsit + * Constructs a {@code DoubleClickListener}. + * @param list the list */ - public DoubleClickListener(JList list) { + public DoubleClickListener(JList list) { handler = new Handler(list); } -- GitLab From acd98294c628e8e03a036a8e3e08d775147b2fda Mon Sep 17 00:00:00 2001 From: Alexey Ivanov Date: Mon, 24 Jan 2022 18:31:43 +0000 Subject: [PATCH 263/564] 8279794: Fix typos in BasicScrollBarUI: Laysouts a vertical scroll bar Reviewed-by: prr, psadhukhan --- .../swing/plaf/basic/BasicScrollBarUI.java | 53 ++++++++++++++----- 1 file changed, 41 insertions(+), 12 deletions(-) diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicScrollBarUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicScrollBarUI.java index afb2d58b885..8c7f348097e 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicScrollBarUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicScrollBarUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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,18 +25,47 @@ package javax.swing.plaf.basic; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.LayoutManager; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseMotionListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javax.swing.BoundedRangeModel; +import javax.swing.InputMap; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JList; +import javax.swing.JScrollBar; +import javax.swing.JScrollPane; +import javax.swing.JViewport; +import javax.swing.LookAndFeel; +import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; +import javax.swing.Timer; +import javax.swing.UIManager; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.ScrollBarUI; +import javax.swing.plaf.UIResource; + import sun.swing.DefaultLookup; import sun.swing.UIAction; -import java.awt.*; -import java.awt.event.*; - -import java.beans.*; - -import javax.swing.*; -import javax.swing.event.*; -import javax.swing.plaf.*; - import static sun.swing.SwingUtilities2.drawHLine; import static sun.swing.SwingUtilities2.drawRect; import static sun.swing.SwingUtilities2.drawVLine; @@ -754,7 +783,7 @@ public class BasicScrollBarUI } /** - * Laysouts a vertical scroll bar. + * Lays out a vertical scroll bar. * @param sb the scroll bar */ protected void layoutVScrollbar(JScrollBar sb) @@ -856,7 +885,7 @@ public class BasicScrollBarUI } /** - * Laysouts a vertical scroll bar. + * Lays out a horizontal scroll bar. * @param sb the scroll bar */ protected void layoutHScrollbar(JScrollBar sb) -- GitLab From 0b5c54be675c63ecac17cd37f6d388fd42f09aa8 Mon Sep 17 00:00:00 2001 From: Alexey Ivanov Date: Mon, 24 Jan 2022 18:32:35 +0000 Subject: [PATCH 264/564] 8279798: Javadoc for BasicTabbedPaneUI is inconsistent Reviewed-by: prr, psadhukhan --- .../swing/plaf/basic/BasicTabbedPaneUI.java | 89 +++++++++++++------ 1 file changed, 64 insertions(+), 25 deletions(-) diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java index c9e5fd51f7f..3fc99dd2bc7 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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,21 +25,60 @@ package javax.swing.plaf.basic; -import sun.swing.SwingUtilities2; - -import javax.swing.*; -import javax.swing.event.*; -import javax.swing.plaf.*; -import javax.swing.text.View; - -import java.awt.*; -import java.awt.event.*; -import java.beans.PropertyChangeListener; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Insets; +import java.awt.LayoutManager; +import java.awt.Point; +import java.awt.Polygon; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ContainerEvent; +import java.awt.event.ContainerListener; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; import java.beans.PropertyChangeEvent; -import java.util.Vector; +import java.beans.PropertyChangeListener; import java.util.Hashtable; +import java.util.Vector; + +import javax.swing.Action; +import javax.swing.ActionMap; +import javax.swing.Icon; +import javax.swing.InputMap; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JPanel; +import javax.swing.JTabbedPane; +import javax.swing.JViewport; +import javax.swing.KeyStroke; +import javax.swing.LookAndFeel; +import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.plaf.ComponentInputMapUIResource; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.TabbedPaneUI; +import javax.swing.plaf.UIResource; +import javax.swing.text.View; import sun.swing.DefaultLookup; +import sun.swing.SwingUtilities2; import sun.swing.UIAction; /** @@ -216,7 +255,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants { public BasicTabbedPaneUI() {} /** - * Create a UI. + * Creates a UI. * @param c a component * @return a UI */ @@ -386,7 +425,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants { } /** - * Install the defaults. + * Installs the defaults. */ protected void installDefaults() { LookAndFeel.installColorsAndFont(tabPane, "TabbedPane.background", @@ -423,7 +462,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants { } /** - * Uninstall the defaults. + * Uninstalls the defaults. */ protected void uninstallDefaults() { highlight = null; @@ -438,7 +477,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants { } /** - * Install the listeners. + * Installs the listeners. */ protected void installListeners() { if ((propertyChangeListener = createPropertyChangeListener()) != null) { @@ -461,7 +500,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants { } /** - * Uninstall the listeners. + * Uninstalls the listeners. */ protected void uninstallListeners() { if (mouseListener != null) { @@ -1090,9 +1129,9 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants { } /** - * Laysout a label. + * Lays out a label. * @param tabPlacement the tab placement - * @param metrics the font metric + * @param metrics the font metrics * @param tabIndex the tab index * @param title the title * @param icon the icon @@ -2144,7 +2183,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants { // Tab Navigation methods /** - * Navigate the selected tab. + * Navigates the selected tab. * @param direction the direction */ protected void navigateSelectedTab(int direction) { @@ -2226,7 +2265,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants { } /** - * Select the next tab in the run. + * Selects the next tab in the run. * @param current the current tab */ protected void selectNextTabInRun(int current) { @@ -2240,7 +2279,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants { } /** - * Select the previous tab in the run. + * Selects the previous tab in the run. * @param current the current tab */ protected void selectPreviousTabInRun(int current) { @@ -2254,7 +2293,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants { } /** - * Select the next tab. + * Selects the next tab. * @param current the current tab */ protected void selectNextTab(int current) { @@ -2267,7 +2306,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants { } /** - * Select the previous tab. + * Selects the previous tab. * @param current the current tab */ protected void selectPreviousTab(int current) { @@ -2772,7 +2811,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants { * Returns the preferred tab area width. * @param tabPlacement the tab placement * @param height the height - * @return the preferred tab area widty + * @return the preferred tab area width */ protected int preferredTabAreaWidth(int tabPlacement, int height) { FontMetrics metrics = getFontMetrics(); -- GitLab From a825a4a1dba14317547b57bc0188b1e912baa251 Mon Sep 17 00:00:00 2001 From: Alexey Ivanov Date: Mon, 24 Jan 2022 18:35:53 +0000 Subject: [PATCH 265/564] 8279861: Clarify 'rect' parameters and description of paintTabBorder method in BasicTabbedPaneUI Reviewed-by: prr, psadhukhan --- .../javax/swing/plaf/basic/BasicTabbedPaneUI.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java index 3fc99dd2bc7..360e98eee7a 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java @@ -955,7 +955,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants { * Paints a tab. * @param g the graphics * @param tabPlacement the tab placement - * @param rects rectangles + * @param rects the tab rectangles * @param tabIndex the tab index * @param iconRect the icon rectangle * @param textRect the text rectangle @@ -1301,7 +1301,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants { * Paints the focus indicator. * @param g the graphics * @param tabPlacement the tab placement - * @param rects rectangles + * @param rects the tab rectangles * @param tabIndex the tab index * @param iconRect the icon rectangle * @param textRect the text rectangle @@ -1346,9 +1346,9 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants { } /** - * this function draws the border around each tab - * note that this function does now draw the background of the tab. - * that is done elsewhere + * Paints the border around a tab. + * Note that this function does not paint the background of the tab, + * that is done elsewhere. * * @param g the graphics context in which to paint * @param tabPlacement the placement (left, right, bottom, top) of the tab @@ -1878,7 +1878,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants { } /** - * Assure the rectangles are created. + * Assures the tab rectangles are created. * @param tabCount the tab count */ protected void assureRectsCreated(int tabCount) { -- GitLab From a5416669a57a7739af13efc32ec084560527862b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Jeli=C5=84ski?= Date: Mon, 24 Jan 2022 19:31:11 +0000 Subject: [PATCH 266/564] 8280474: Garbage value passed to getLocaleInfoWrapper in HostLocaleProviderAdapter_md Reviewed-by: naoto, alanb --- .../windows/native/libjava/HostLocaleProviderAdapter_md.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/java.base/windows/native/libjava/HostLocaleProviderAdapter_md.c b/src/java.base/windows/native/libjava/HostLocaleProviderAdapter_md.c index 879422f096f..b7c2bcc28db 100644 --- a/src/java.base/windows/native/libjava/HostLocaleProviderAdapter_md.c +++ b/src/java.base/windows/native/libjava/HostLocaleProviderAdapter_md.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022, 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 @@ -835,7 +835,7 @@ void replaceCalendarArrayElems(JNIEnv *env, jstring jlangtag, jint calid, jobjec WCHAR name[BUFLEN]; const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); jstring tmp_string; - CALTYPE isGenitive; + CALTYPE isGenitive = 0; CHECK_NULL(langtag); -- GitLab From 8e82d0021c119b7793870811fad37d7659c1174d Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Mon, 24 Jan 2022 20:16:38 +0000 Subject: [PATCH 267/564] 8280492: Use cross-module syntax for cross-module links Reviewed-by: iris, serb, lancea, dfuchs, aivanov --- .../share/classes/java/io/FilenameFilter.java | 4 +-- .../share/classes/java/lang/Character.java | 8 +++--- .../share/classes/java/lang/System.java | 24 ++++++++--------- .../java/lang/invoke/MethodHandleProxies.java | 4 +-- .../java/lang/invoke/MethodHandles.java | 4 +-- .../share/classes/java/net/package-info.java | 4 +-- .../text/AttributedCharacterIterator.java | 6 ++--- .../share/classes/java/text/Bidi.java | 8 +++--- .../share/classes/java/util/Observable.java | 4 +-- .../classes/java/util/ServiceLoader.java | 4 +-- .../java/awt/datatransfer/Clipboard.java | 14 +++++----- .../classes/java/util/logging/LogManager.java | 8 +++--- .../java/util/logging/LoggingMXBean.java | 14 +++++----- .../lang/management/ManagementFactory.java | 4 +-- .../management/PlatformLoggingMXBean.java | 26 +++++++++---------- .../management/remote/JMXAddressable.java | 4 +-- .../remote/JMXServerErrorException.java | 4 +-- 17 files changed, 72 insertions(+), 72 deletions(-) diff --git a/src/java.base/share/classes/java/io/FilenameFilter.java b/src/java.base/share/classes/java/io/FilenameFilter.java index fcd81479ee1..019ffb11771 100644 --- a/src/java.base/share/classes/java/io/FilenameFilter.java +++ b/src/java.base/share/classes/java/io/FilenameFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2022, 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,7 +34,7 @@ package java.io; * * @author Arthur van Hoff * @author Jonathan Payne - * @see java.awt.FileDialog#setFilenameFilter(java.io.FilenameFilter) + * @see java.desktop/java.awt.FileDialog#setFilenameFilter(java.io.FilenameFilter) * @see java.io.File * @see java.io.File#list(java.io.FilenameFilter) * @since 1.0 diff --git a/src/java.base/share/classes/java/lang/Character.java b/src/java.base/share/classes/java/lang/Character.java index 1cc12940ef1..0fdd23997cc 100644 --- a/src/java.base/share/classes/java/lang/Character.java +++ b/src/java.base/share/classes/java/lang/Character.java @@ -10302,7 +10302,7 @@ class Character implements java.io.Serializable, Comparable, Constabl * @see Character#isJavaIdentifierPart(char) * @see Character#isLetter(char) * @see Character#isUnicodeIdentifierStart(char) - * @see javax.lang.model.SourceVersion#isIdentifier(CharSequence) + * @see java.compiler/javax.lang.model.SourceVersion#isIdentifier(CharSequence) * @since 1.1 */ public static boolean isJavaIdentifierStart(char ch) { @@ -10331,7 +10331,7 @@ class Character implements java.io.Serializable, Comparable, Constabl * @see Character#isJavaIdentifierPart(int) * @see Character#isLetter(int) * @see Character#isUnicodeIdentifierStart(int) - * @see javax.lang.model.SourceVersion#isIdentifier(CharSequence) + * @see java.compiler/javax.lang.model.SourceVersion#isIdentifier(CharSequence) * @since 1.5 */ public static boolean isJavaIdentifierStart(int codePoint) { @@ -10368,7 +10368,7 @@ class Character implements java.io.Serializable, Comparable, Constabl * @see Character#isJavaIdentifierStart(char) * @see Character#isLetterOrDigit(char) * @see Character#isUnicodeIdentifierPart(char) - * @see javax.lang.model.SourceVersion#isIdentifier(CharSequence) + * @see java.compiler/javax.lang.model.SourceVersion#isIdentifier(CharSequence) * @since 1.1 */ public static boolean isJavaIdentifierPart(char ch) { @@ -10401,7 +10401,7 @@ class Character implements java.io.Serializable, Comparable, Constabl * @see Character#isJavaIdentifierStart(int) * @see Character#isLetterOrDigit(int) * @see Character#isUnicodeIdentifierPart(int) - * @see javax.lang.model.SourceVersion#isIdentifier(CharSequence) + * @see java.compiler/javax.lang.model.SourceVersion#isIdentifier(CharSequence) * @since 1.5 */ public static boolean isJavaIdentifierPart(int codePoint) { diff --git a/src/java.base/share/classes/java/lang/System.java b/src/java.base/share/classes/java/lang/System.java index 47b436847cb..2f9c205a327 100644 --- a/src/java.base/share/classes/java/lang/System.java +++ b/src/java.base/share/classes/java/lang/System.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2022, 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 @@ -1207,7 +1207,7 @@ public final class System { * Severity values and Mapping to {@code java.util.logging.Level}. *

    * {@linkplain System.Logger.Level System logger levels} are mapped to - * {@linkplain java.util.logging.Level java.util.logging levels} + * {@linkplain java.logging/java.util.logging.Level java.util.logging levels} * of corresponding severity. *
    The mapping is as follows: *

    @@ -1219,19 +1219,19 @@ public final class System { * * * {@link Logger.Level#ALL ALL} - * {@link java.util.logging.Level#ALL ALL} + * {@link java.logging/java.util.logging.Level#ALL ALL} * {@link Logger.Level#TRACE TRACE} - * {@link java.util.logging.Level#FINER FINER} + * {@link java.logging/java.util.logging.Level#FINER FINER} * {@link Logger.Level#DEBUG DEBUG} - * {@link java.util.logging.Level#FINE FINE} + * {@link java.logging/java.util.logging.Level#FINE FINE} * {@link Logger.Level#INFO INFO} - * {@link java.util.logging.Level#INFO INFO} + * {@link java.logging/java.util.logging.Level#INFO INFO} * {@link Logger.Level#WARNING WARNING} - * {@link java.util.logging.Level#WARNING WARNING} + * {@link java.logging/java.util.logging.Level#WARNING WARNING} * {@link Logger.Level#ERROR ERROR} - * {@link java.util.logging.Level#SEVERE SEVERE} + * {@link java.logging/java.util.logging.Level#SEVERE SEVERE} * {@link Logger.Level#OFF OFF} - * {@link java.util.logging.Level#OFF OFF} + * {@link java.logging/java.util.logging.Level#OFF OFF} * * * @@ -1542,7 +1542,7 @@ public final class System { * {@code java.util.logging} as the backend framework when the * {@code java.logging} module is present. * It returns a {@linkplain System.Logger logger} instance - * that will route log messages to a {@link java.util.logging.Logger + * that will route log messages to a {@link java.logging/java.util.logging.Logger * java.util.logging.Logger}. Otherwise, if {@code java.logging} is not * present, the default implementation will return a simple logger * instance that will route log messages of {@code INFO} level and above to @@ -1556,7 +1556,7 @@ public final class System { * logging backend, and usually requires using APIs specific to that backend. *

    For the default {@code LoggerFinder} implementation * using {@code java.util.logging} as its backend, refer to - * {@link java.util.logging java.util.logging} for logging configuration. + * {@link java.logging/java.util.logging java.util.logging} for logging configuration. * For the default {@code LoggerFinder} implementation returning simple loggers * when the {@code java.logging} module is absent, the configuration * is implementation dependent. @@ -1591,7 +1591,7 @@ public final class System { * System.Logger.Level} to a level supported by the logging backend it uses. *
    The default LoggerFinder using {@code java.util.logging} as the backend * maps {@code System.Logger} levels to - * {@linkplain java.util.logging.Level java.util.logging} levels + * {@linkplain java.logging/java.util.logging.Level java.util.logging} levels * of corresponding severity - as described in {@link Logger.Level * Logger.Level}. * diff --git a/src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java b/src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java index 4dd2b1fce7e..784d672ff8f 100644 --- a/src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2022, 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 @@ -88,7 +88,7 @@ public class MethodHandleProxies { * Therefore, each instance must implement a unique single-method interface. * Implementations may not bundle together * multiple single-method interfaces onto single implementation classes - * in the style of {@link java.awt.AWTEventMulticaster}. + * in the style of {@link java.desktop/java.awt.AWTEventMulticaster}. *

    * The method handle may throw an undeclared exception, * which means any checked exception (or other checked throwable) diff --git a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java index 743ebb66759..908c277fa86 100644 --- a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2022, 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 @@ -2002,7 +2002,7 @@ public class MethodHandles { * there is no internal form available to record in any class's constant pool. * A hidden class or interface is not discoverable by {@link Class#forName(String, boolean, ClassLoader)}, * {@link ClassLoader#loadClass(String, boolean)}, or {@link #findClass(String)}, and - * is not {@linkplain java.lang.instrument.Instrumentation#isModifiableClass(Class) + * is not {@linkplain java.instrument/java.lang.instrument.Instrumentation#isModifiableClass(Class) * modifiable} by Java agents or tool agents using the * JVM Tool Interface. * diff --git a/src/java.base/share/classes/java/net/package-info.java b/src/java.base/share/classes/java/net/package-info.java index b221c6bf2f7..e0325f6a0f1 100644 --- a/src/java.base/share/classes/java/net/package-info.java +++ b/src/java.base/share/classes/java/net/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2022, 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 @@ -122,7 +122,7 @@ *

  • {@link java.net.HttpURLConnection} is a subclass of URLConnection * and provides some additional functionalities specific to the * HTTP protocol. This API has been superseded by the newer - * {@linkplain java.net.http HTTP Client API}.
  • + * {@linkplain java.net.http/java.net.http HTTP Client API}. * *

    The recommended usage is to use {@link java.net.URI} to identify * resources, then convert it into a {@link java.net.URL} when it is time to diff --git a/src/java.base/share/classes/java/text/AttributedCharacterIterator.java b/src/java.base/share/classes/java/text/AttributedCharacterIterator.java index 31b5b7d8d3c..a77417462a7 100644 --- a/src/java.base/share/classes/java/text/AttributedCharacterIterator.java +++ b/src/java.base/share/classes/java/text/AttributedCharacterIterator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -67,10 +67,10 @@ import java.util.Set; * *

    * Attribute keys are instances of {@link AttributedCharacterIterator.Attribute} and its - * subclasses, such as {@link java.awt.font.TextAttribute}. + * subclasses, such as {@link java.desktop/java.awt.font.TextAttribute}. * * @see AttributedCharacterIterator.Attribute - * @see java.awt.font.TextAttribute + * @see java.desktop/java.awt.font.TextAttribute * @see AttributedString * @see Annotation * @since 1.2 diff --git a/src/java.base/share/classes/java/text/Bidi.java b/src/java.base/share/classes/java/text/Bidi.java index 00a878e1c64..41269afac9b 100644 --- a/src/java.base/share/classes/java/text/Bidi.java +++ b/src/java.base/share/classes/java/text/Bidi.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2022, 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 @@ -121,9 +121,9 @@ public final class Bidi { * * @param paragraph a paragraph of text with optional character and paragraph attribute information * - * @see java.awt.font.TextAttribute#BIDI_EMBEDDING - * @see java.awt.font.TextAttribute#NUMERIC_SHAPING - * @see java.awt.font.TextAttribute#RUN_DIRECTION + * @see java.desktop/java.awt.font.TextAttribute#BIDI_EMBEDDING + * @see java.desktop/java.awt.font.TextAttribute#NUMERIC_SHAPING + * @see java.desktop/java.awt.font.TextAttribute#RUN_DIRECTION */ public Bidi(AttributedCharacterIterator paragraph) { if (paragraph == null) { diff --git a/src/java.base/share/classes/java/util/Observable.java b/src/java.base/share/classes/java/util/Observable.java index d71bf5d5d4c..37a90f631ad 100644 --- a/src/java.base/share/classes/java/util/Observable.java +++ b/src/java.base/share/classes/java/util/Observable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2022, 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 @@ -66,7 +66,7 @@ package java.util; * {@code Observable} is unspecified, and state changes are not in * one-for-one correspondence with notifications. * For a richer event model, consider using the - * {@link java.beans} package. For reliable and ordered + * {@link java.desktop/java.beans} package. For reliable and ordered * messaging among threads, consider using one of the concurrent data * structures in the {@link java.util.concurrent} package. * For reactive streams style programming, see the diff --git a/src/java.base/share/classes/java/util/ServiceLoader.java b/src/java.base/share/classes/java/util/ServiceLoader.java index 64b01c3157e..c5d921896a0 100644 --- a/src/java.base/share/classes/java/util/ServiceLoader.java +++ b/src/java.base/share/classes/java/util/ServiceLoader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2022, 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 @@ -1585,7 +1585,7 @@ public final class ServiceLoader * are located in the order that its module descriptor {@linkplain * java.lang.module.ModuleDescriptor.Provides#providers() lists the * providers}. Providers added dynamically by instrumentation agents (see - * {@link java.lang.instrument.Instrumentation#redefineModule redefineModule}) + * {@link java.instrument/java.lang.instrument.Instrumentation#redefineModule redefineModule}) * are always located after providers declared by the module.

    * *
  • Step 2: Locate providers in unnamed modules.

    diff --git a/src/java.datatransfer/share/classes/java/awt/datatransfer/Clipboard.java b/src/java.datatransfer/share/classes/java/awt/datatransfer/Clipboard.java index ad3a56a701f..8aac4495547 100644 --- a/src/java.datatransfer/share/classes/java/awt/datatransfer/Clipboard.java +++ b/src/java.datatransfer/share/classes/java/awt/datatransfer/Clipboard.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2022, 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 @@ -43,8 +43,8 @@ import sun.datatransfer.DataFlavorUtil; * * @author Amy Fowler * @author Alexander Gerasimov - * @see java.awt.Toolkit#getSystemClipboard - * @see java.awt.Toolkit#getSystemSelection + * @see java.desktop/java.awt.Toolkit#getSystemClipboard + * @see java.desktop/java.awt.Toolkit#getSystemSelection * @since 1.1 */ public class Clipboard { @@ -81,7 +81,7 @@ public class Clipboard { * Creates a clipboard object. * * @param name for the clipboard - * @see java.awt.Toolkit#getSystemClipboard + * @see java.desktop/java.awt.Toolkit#getSystemClipboard */ public Clipboard(String name) { this.name = name; @@ -91,7 +91,7 @@ public class Clipboard { * Returns the name of this clipboard object. * * @return the name of this clipboard object - * @see java.awt.Toolkit#getSystemClipboard + * @see java.desktop/java.awt.Toolkit#getSystemClipboard */ public String getName() { return name; @@ -118,7 +118,7 @@ public class Clipboard { * content * @param owner the object which owns the clipboard content * @throws IllegalStateException if the clipboard is currently unavailable - * @see java.awt.Toolkit#getSystemClipboard + * @see java.desktop/java.awt.Toolkit#getSystemClipboard */ public synchronized void setContents(Transferable contents, ClipboardOwner owner) { final ClipboardOwner oldOwner = this.owner; @@ -145,7 +145,7 @@ public class Clipboard { * @param requestor the object requesting the clip data (not used) * @return the current transferable object on the clipboard * @throws IllegalStateException if the clipboard is currently unavailable - * @see java.awt.Toolkit#getSystemClipboard + * @see java.desktop/java.awt.Toolkit#getSystemClipboard */ public synchronized Transferable getContents(Object requestor) { return contents; diff --git a/src/java.logging/share/classes/java/util/logging/LogManager.java b/src/java.logging/share/classes/java/util/logging/LogManager.java index 59950865283..38e9ebafeb6 100644 --- a/src/java.logging/share/classes/java/util/logging/LogManager.java +++ b/src/java.logging/share/classes/java/util/logging/LogManager.java @@ -2556,10 +2556,10 @@ public class LogManager { /** * String representation of the - * {@link javax.management.ObjectName} for the management interface + * {@link java.management/javax.management.ObjectName} for the management interface * for the logging facility. * - * @see java.lang.management.PlatformLoggingMXBean + * @see java.management/java.lang.management.PlatformLoggingMXBean * * @since 1.5 */ @@ -2573,11 +2573,11 @@ public class LogManager { * * @deprecated {@code java.util.logging.LoggingMXBean} is deprecated and * replaced with {@code java.lang.management.PlatformLoggingMXBean}. Use - * {@link java.lang.management.ManagementFactory#getPlatformMXBean(Class) + * {@link java.management/java.lang.management.ManagementFactory#getPlatformMXBean(Class) * ManagementFactory.getPlatformMXBean}(PlatformLoggingMXBean.class) * instead. * - * @see java.lang.management.PlatformLoggingMXBean + * @see java.management/java.lang.management.PlatformLoggingMXBean * @since 1.5 */ @Deprecated(since="9") diff --git a/src/java.logging/share/classes/java/util/logging/LoggingMXBean.java b/src/java.logging/share/classes/java/util/logging/LoggingMXBean.java index 812eb36622d..b966421f9b0 100644 --- a/src/java.logging/share/classes/java/util/logging/LoggingMXBean.java +++ b/src/java.logging/share/classes/java/util/logging/LoggingMXBean.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,18 +29,18 @@ package java.util.logging; /** * The management interface for the logging facility. * - * {@link java.lang.management.PlatformLoggingMXBean + * {@link java.management/java.lang.management.PlatformLoggingMXBean * java.lang.management.PlatformLoggingMXBean} is the management interface * for logging facility registered in the {@link - * java.lang.management.ManagementFactory#getPlatformMBeanServer() + * java.management/java.lang.management.ManagementFactory#getPlatformMBeanServer() * platform MBeanServer}. * It is recommended to use the {@code PlatformLoggingMXBean} obtained via - * the {@link java.lang.management.ManagementFactory#getPlatformMXBean(Class) + * the {@link java.management/java.lang.management.ManagementFactory#getPlatformMXBean(Class) * ManagementFactory.getPlatformMXBean(PlatformLoggingMXBean.class)} method. * * @deprecated {@code LoggingMXBean} is no longer a {@link - * java.lang.management.PlatformManagedObject platform MXBean} and is replaced - * with {@link java.lang.management.PlatformLoggingMXBean}. + * java.management/java.lang.management.PlatformManagedObject platform MXBean} and is replaced + * with {@link java.management/java.lang.management.PlatformLoggingMXBean}. * It will not register in the platform {@code MBeanServer}. * Use {@code ManagementFactory.getPlatformMXBean(PlatformLoggingMXBean.class)} * instead. @@ -49,7 +49,7 @@ package java.util.logging; * @author Mandy Chung * @since 1.5 * - * @see java.lang.management.PlatformLoggingMXBean + * @see java.management/java.lang.management.PlatformLoggingMXBean */ @Deprecated(since="9") public interface LoggingMXBean { diff --git a/src/java.management/share/classes/java/lang/management/ManagementFactory.java b/src/java.management/share/classes/java/lang/management/ManagementFactory.java index cba413ccf63..76bc7417e68 100644 --- a/src/java.management/share/classes/java/lang/management/ManagementFactory.java +++ b/src/java.management/share/classes/java/lang/management/ManagementFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, 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 @@ import sun.management.spi.PlatformMBeanProvider.PlatformComponent; * * * {@link PlatformLoggingMXBean} - * {@link java.util.logging.LogManager#LOGGING_MXBEAN_NAME + * {@link java.logging/java.util.logging.LogManager#LOGGING_MXBEAN_NAME * java.util.logging:type=Logging} * * diff --git a/src/java.management/share/classes/java/lang/management/PlatformLoggingMXBean.java b/src/java.management/share/classes/java/lang/management/PlatformLoggingMXBean.java index 80595dd75d6..280d145be37 100644 --- a/src/java.management/share/classes/java/lang/management/PlatformLoggingMXBean.java +++ b/src/java.management/share/classes/java/lang/management/PlatformLoggingMXBean.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ package java.lang.management; /** - * The management interface for the {@linkplain java.util.logging logging} facility. + * The management interface for the {@linkplain java.logging/java.util.logging logging} facility. * *

    There is a single global instance of the {@code PlatformLoggingMXBean}. * The {@link java.lang.management.ManagementFactory#getPlatformMXBean(Class) @@ -41,7 +41,7 @@ package java.lang.management; * The {@link javax.management.ObjectName ObjectName} for uniquely * identifying the {@code PlatformLoggingMXBean} within an MBeanServer is: *

    - *      {@link java.util.logging.LogManager#LOGGING_MXBEAN_NAME java.util.logging:type=Logging}
    + *      {@link java.logging/java.util.logging.LogManager#LOGGING_MXBEAN_NAME java.util.logging:type=Logging}
      * 
    * * @since 1.7 @@ -50,8 +50,8 @@ public interface PlatformLoggingMXBean extends PlatformManagedObject { /** * Returns the list of the currently registered - * {@linkplain java.util.logging.Logger logger} names. This method - * calls {@link java.util.logging.LogManager#getLoggerNames} and + * {@linkplain java.logging/java.util.logging.Logger logger} names. This method + * calls {@link java.logging/java.util.logging.LogManager#getLoggerNames} and * returns a list of the logger names. * * @return A list of {@code String} each of which is a @@ -60,15 +60,15 @@ public interface PlatformLoggingMXBean extends PlatformManagedObject { java.util.List getLoggerNames(); /** - * Gets the name of the log {@linkplain java.util.logging.Logger#getLevel + * Gets the name of the log {@linkplain java.logging/java.util.logging.Logger#getLevel * level} associated with the specified logger. * If the specified logger does not exist, {@code null} * is returned. * This method first finds the logger of the given name and * then returns the name of the log level by calling: *
    - * {@link java.util.logging.Logger#getLevel - * Logger.getLevel()}.{@link java.util.logging.Level#getName getName()}; + * {@link java.logging/java.util.logging.Logger#getLevel + * Logger.getLevel()}.{@link java.logging/java.util.logging.Level#getName getName()}; *
    * *

    @@ -83,16 +83,16 @@ public interface PlatformLoggingMXBean extends PlatformManagedObject { * is {@code null}. If the specified logger does not * exist, {@code null} is returned. * - * @see java.util.logging.Logger#getLevel + * @see java.logging/java.util.logging.Logger#getLevel */ String getLoggerLevel(String loggerName); /** * Sets the specified logger to the specified new - * {@linkplain java.util.logging.Logger#setLevel level}. + * {@linkplain java.logging/java.util.logging.Logger#setLevel level}. * If the {@code levelName} is not {@code null}, the level * of the specified logger is set to the parsed - * {@link java.util.logging.Level Level} + * {@link java.logging/java.util.logging.Level Level} * matching the {@code levelName}. * If the {@code levelName} is {@code null}, the level * of the specified logger is set to {@code null} and @@ -111,13 +111,13 @@ public interface PlatformLoggingMXBean extends PlatformManagedObject { * @throws SecurityException if a security manager exists and if * the caller does not have LoggingPermission("control"). * - * @see java.util.logging.Logger#setLevel + * @see java.logging/java.util.logging.Logger#setLevel */ void setLoggerLevel(String loggerName, String levelName); /** * Returns the name of the - * {@linkplain java.util.logging.Logger#getParent parent} + * {@linkplain java.logging/java.util.logging.Logger#getParent parent} * for the specified logger. * If the specified logger does not exist, {@code null} is returned. * If the specified logger is the root {@code Logger} in the namespace, diff --git a/src/java.management/share/classes/javax/management/remote/JMXAddressable.java b/src/java.management/share/classes/javax/management/remote/JMXAddressable.java index cc770b75194..973626b99a1 100644 --- a/src/java.management/share/classes/javax/management/remote/JMXAddressable.java +++ b/src/java.management/share/classes/javax/management/remote/JMXAddressable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,7 @@ package javax.management.remote; * Depending on the connector implementation, a {@link JMXConnector} * object may implement this interface too. {@code JMXConnector} * objects for the RMI Connector are instances of - * {@link javax.management.remote.rmi.RMIConnector RMIConnector} which + * {@link java.management.rmi/javax.management.remote.rmi.RMIConnector RMIConnector} which * implements this interface.

    * *

    An object implementing this interface might not have an address diff --git a/src/java.management/share/classes/javax/management/remote/JMXServerErrorException.java b/src/java.management/share/classes/javax/management/remote/JMXServerErrorException.java index a8bf827fd3e..856234ad5dc 100644 --- a/src/java.management/share/classes/javax/management/remote/JMXServerErrorException.java +++ b/src/java.management/share/classes/javax/management/remote/JMXServerErrorException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,7 +38,7 @@ import javax.management.MBeanServer; * JMXServerErrorException instance contains the original * Error that occurred as its cause. * - * @see java.rmi.ServerError + * @see java.rmi/java.rmi.ServerError * @since 1.5 */ public class JMXServerErrorException extends IOException { -- GitLab From e3076552ec528864e61a6e0ec91e228006fddefc Mon Sep 17 00:00:00 2001 From: Ian Graves Date: Mon, 24 Jan 2022 22:21:22 +0000 Subject: [PATCH 268/564] 8280403: RegEx: String.split can fail with NPE in Pattern.CharPredicate::match Reviewed-by: lancea, iris, naoto, rriggs --- .../share/classes/java/util/regex/Pattern.java | 4 +++- test/jdk/java/util/regex/RegExTest.java | 11 ++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/java.base/share/classes/java/util/regex/Pattern.java b/src/java.base/share/classes/java/util/regex/Pattern.java index 84e1063621d..b1e3977d0b2 100644 --- a/src/java.base/share/classes/java/util/regex/Pattern.java +++ b/src/java.base/share/classes/java/util/regex/Pattern.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2022, 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 @@ -2689,6 +2689,8 @@ loop: for(int x=0, offset=0; x + Pattern.compile(pattern)); + assertTrue(e.getMessage().contains("Bad intersection syntax")); + } } -- GitLab From f35df5bfb5d23f439fb64e8511fd5ca34c773f30 Mon Sep 17 00:00:00 2001 From: David Holmes Date: Tue, 25 Jan 2022 01:22:48 +0000 Subject: [PATCH 269/564] 8280422: thread_from_jni_environment can never return NULL Reviewed-by: shade, kbarrett --- src/hotspot/share/runtime/globals.hpp | 4 ---- .../share/runtime/interfaceSupport.inline.hpp | 9 ++++++-- src/hotspot/share/runtime/thread.hpp | 23 +++++++++++-------- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index c963a69fa60..bc80a2eb45f 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -1191,10 +1191,6 @@ const intx ObjectAlignmentInBytes = 8; develop(bool, VerifyJNIFields, trueInDebug, \ "Verify jfieldIDs for instance fields") \ \ - notproduct(bool, VerifyJNIEnvThread, false, \ - "Verify JNIEnv.thread == Thread::current() when entering VM " \ - "from JNI") \ - \ develop(bool, VerifyFPU, false, \ "Verify FPU state (check for NaN's, etc.)") \ \ diff --git a/src/hotspot/share/runtime/interfaceSupport.inline.hpp b/src/hotspot/share/runtime/interfaceSupport.inline.hpp index 26a0cfe608e..13ecf2d80ce 100644 --- a/src/hotspot/share/runtime/interfaceSupport.inline.hpp +++ b/src/hotspot/share/runtime/interfaceSupport.inline.hpp @@ -340,6 +340,11 @@ class VMNativeEntryWrapper { #define JRT_END } // Definitions for JNI +// +// As the JNIEnv can be passed from external native code we validate +// it in debug builds, primarily for our own testing. In general JNI +// does not attempt to detect programming errors and a bad JNIEnv may +// not even be readable. #define JNI_ENTRY(result_type, header) \ JNI_ENTRY_NO_PRESERVE(result_type, header) \ @@ -349,7 +354,7 @@ class VMNativeEntryWrapper { extern "C" { \ result_type JNICALL header { \ JavaThread* thread=JavaThread::thread_from_jni_environment(env); \ - assert( !VerifyJNIEnvThread || (thread == Thread::current()), "JNIEnv is only valid in same thread"); \ + assert(thread == Thread::current(), "JNIEnv is only valid in same thread"); \ MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, thread)); \ ThreadInVMfromNative __tiv(thread); \ debug_only(VMNativeEntryWrapper __vew;) \ @@ -360,7 +365,7 @@ extern "C" { \ extern "C" { \ result_type JNICALL header { \ JavaThread* thread=JavaThread::thread_from_jni_environment(env); \ - assert( !VerifyJNIEnvThread || (thread == Thread::current()), "JNIEnv is only valid in same thread"); \ + assert(thread == Thread::current(), "JNIEnv is only valid in same thread"); \ VM_LEAF_BASE(result_type, header) diff --git a/src/hotspot/share/runtime/thread.hpp b/src/hotspot/share/runtime/thread.hpp index 74916b98275..71100dbe637 100644 --- a/src/hotspot/share/runtime/thread.hpp +++ b/src/hotspot/share/runtime/thread.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2021, Azul Systems, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -1312,16 +1312,21 @@ class JavaThread: public Thread { // Returns the jni environment for this thread JNIEnv* jni_environment() { return &_jni_environment; } + // Returns the current thread as indicated by the given JNIEnv. + // We don't assert it is Thread::current here as that is done at the + // external JNI entry points where the JNIEnv is passed into the VM. static JavaThread* thread_from_jni_environment(JNIEnv* env) { - JavaThread *thread_from_jni_env = (JavaThread*)((intptr_t)env - in_bytes(jni_environment_offset())); - // Only return NULL if thread is off the thread list; starting to - // exit should not return NULL. - if (thread_from_jni_env->is_terminated()) { - thread_from_jni_env->block_if_vm_exited(); - return NULL; - } else { - return thread_from_jni_env; + JavaThread* current = (JavaThread*)((intptr_t)env - in_bytes(jni_environment_offset())); + // We can't get here in a thread that has completed its execution and so + // "is_terminated", but a thread is also considered terminated if the VM + // has exited, so we have to check this and block in case this is a daemon + // thread returning to the VM (the JNI DirectBuffer entry points rely on + // this). + if (current->is_terminated()) { + current->block_if_vm_exited(); + ShouldNotReachHere(); } + return current; } // JNI critical regions. These can nest. -- GitLab From a59d717fd65d523bb6f4fc57949054e904a149f1 Mon Sep 17 00:00:00 2001 From: Zhengyu Gu Date: Tue, 25 Jan 2022 01:31:24 +0000 Subject: [PATCH 270/564] 8280289: Enhance debug pp() command with NMT info Reviewed-by: stuefe, iklam --- src/hotspot/share/services/mallocTracker.cpp | 55 ++++++++++++------- src/hotspot/share/services/mallocTracker.hpp | 14 +++-- .../share/services/virtualMemoryTracker.cpp | 28 +++++++++- .../share/services/virtualMemoryTracker.hpp | 6 +- src/hotspot/share/utilities/debug.cpp | 40 +++++++++++++- 5 files changed, 113 insertions(+), 30 deletions(-) diff --git a/src/hotspot/share/services/mallocTracker.cpp b/src/hotspot/share/services/mallocTracker.cpp index 285a60d853f..e27d312ad81 100644 --- a/src/hotspot/share/services/mallocTracker.cpp +++ b/src/hotspot/share/services/mallocTracker.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2022, 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,8 @@ #include "utilities/debug.hpp" #include "utilities/ostream.hpp" +#include "jvm_io.h" + size_t MallocMemorySummary::_snapshot[CALC_OBJ_SIZE_IN_TYPE(MallocMemorySnapshot, size_t)]; #ifdef ASSERT @@ -115,7 +117,7 @@ void MallocHeader::mark_block_as_dead() { void MallocHeader::release() { assert(MemTracker::enabled(), "Sanity"); - check_block_integrity(); + assert_block_integrity(); MallocMemorySummary::record_free(size(), flags()); MallocMemorySummary::record_free_malloc_header(sizeof(MallocHeader)); @@ -153,13 +155,18 @@ void MallocHeader::print_block_on_error(outputStream* st, address bad_address) c os::print_hex_dump(st, from1, to2, 1); } } +void MallocHeader::assert_block_integrity() const { + char msg[256]; + address corruption = NULL; + if (!check_block_integrity(msg, sizeof(msg), &corruption)) { + if (corruption != NULL) { + print_block_on_error(tty, (address)this); + } + fatal("NMT corruption: Block at " PTR_FORMAT ": %s", p2i(this), msg); + } +} -// Check block integrity. If block is broken, print out a report -// to tty (optionally with hex dump surrounding the broken block), -// then trigger a fatal error. -void MallocHeader::check_block_integrity() const { - -#define PREFIX "NMT corruption: " +bool MallocHeader::check_block_integrity(char* msg, size_t msglen, address* p_corruption) const { // Note: if you modify the error messages here, make sure you // adapt the associated gtests too. @@ -167,7 +174,8 @@ void MallocHeader::check_block_integrity() const { // values. Note that we should not call this for ::free(NULL), // which should be handled by os::free() above us. if (((size_t)p2i(this)) < K) { - fatal(PREFIX "Block at " PTR_FORMAT ": invalid block address", p2i(this)); + jio_snprintf(msg, msglen, "invalid block address"); + return false; } // From here on we assume the block pointer to be valid. We could @@ -186,37 +194,42 @@ void MallocHeader::check_block_integrity() const { // Should we ever start using std::max_align_t, this would be one place to // fix up. if (!is_aligned(this, sizeof(uint64_t))) { - print_block_on_error(tty, (address)this); - fatal(PREFIX "Block at " PTR_FORMAT ": block address is unaligned", p2i(this)); + *p_corruption = (address)this; + jio_snprintf(msg, msglen, "block address is unaligned"); + return false; } // Check header canary if (_canary != _header_canary_life_mark) { - print_block_on_error(tty, (address)this); - fatal(PREFIX "Block at " PTR_FORMAT ": header canary broken.", p2i(this)); + *p_corruption = (address)this; + jio_snprintf(msg, msglen, "header canary broken"); + return false; } #ifndef _LP64 // On 32-bit we have a second canary, check that one too. if (_alt_canary != _header_alt_canary_life_mark) { - print_block_on_error(tty, (address)this); - fatal(PREFIX "Block at " PTR_FORMAT ": header alternate canary broken.", p2i(this)); + *p_corruption = (address)this; + jio_snprintf(msg, msglen, "header canary broken"); + return false; } #endif // Does block size seems reasonable? if (_size >= max_reasonable_malloc_size) { - print_block_on_error(tty, (address)this); - fatal(PREFIX "Block at " PTR_FORMAT ": header looks invalid (weirdly large block size)", p2i(this)); + *p_corruption = (address)this; + jio_snprintf(msg, msglen, "header looks invalid (weirdly large block size)"); + return false; } // Check footer canary if (get_footer() != _footer_canary_life_mark) { - print_block_on_error(tty, footer_address()); - fatal(PREFIX "Block at " PTR_FORMAT ": footer canary broken at " PTR_FORMAT " (buffer overflow?)", - p2i(this), p2i(footer_address())); + *p_corruption = footer_address(); + jio_snprintf(msg, msglen, "footer canary broken at " PTR_FORMAT " (buffer overflow?)", + p2i(footer_address())); + return false; } -#undef PREFIX + return true; } bool MallocHeader::record_malloc_site(const NativeCallStack& stack, size_t size, diff --git a/src/hotspot/share/services/mallocTracker.hpp b/src/hotspot/share/services/mallocTracker.hpp index 6490b3d53ff..a0953c2b186 100644 --- a/src/hotspot/share/services/mallocTracker.hpp +++ b/src/hotspot/share/services/mallocTracker.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2022, 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 @@ -314,10 +314,9 @@ class MallocHeader { // We discount sizes larger than these static const size_t max_reasonable_malloc_size = LP64_ONLY(256 * G) NOT_LP64(3500 * M); - // Check block integrity. If block is broken, print out a report - // to tty (optionally with hex dump surrounding the broken block), - // then trigger a fatal error. - void check_block_integrity() const; + // If block is broken, print out a report to tty (optionally with + // hex dump surrounding the broken block), then trigger a fatal error + void assert_block_integrity() const; void print_block_on_error(outputStream* st, address bad_address) const; void mark_block_as_dead(); @@ -363,6 +362,11 @@ class MallocHeader { // Cleanup tracking information and mark block as dead before the memory is released. void release(); + // If block is broken, fill in a short descriptive text in out, + // an option pointer to the corruption in p_corruption, and return false. + // Return true if block is fine. + bool check_block_integrity(char* msg, size_t msglen, address* p_corruption) const; + private: inline void set_size(size_t size) { _size = size; diff --git a/src/hotspot/share/services/virtualMemoryTracker.cpp b/src/hotspot/share/services/virtualMemoryTracker.cpp index 77fb24927f5..53a2cf10642 100644 --- a/src/hotspot/share/services/virtualMemoryTracker.cpp +++ b/src/hotspot/share/services/virtualMemoryTracker.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2022, 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 @@ -671,3 +671,29 @@ bool VirtualMemoryTracker::walk_virtual_memory(VirtualMemoryWalker* walker) { } return true; } + +class FindAndSnapshotRegionWalker : public VirtualMemoryWalker { +private: + ReservedMemoryRegion& _region; + const address _p; + bool _found_region; +public: + FindAndSnapshotRegionWalker(void* p, ReservedMemoryRegion& region) : + _region(region), _p((address)p), _found_region(false) { } + + bool do_allocation_site(const ReservedMemoryRegion* rgn) { + if (rgn->contain_address(_p)) { + _region = *rgn; + _found_region = true; + return false; + } + return true; + } + bool found_region() const { return _found_region; } +}; + +const bool VirtualMemoryTracker::snapshot_region_contains(void* p, ReservedMemoryRegion& region) { + FindAndSnapshotRegionWalker walker(p, region); + walk_virtual_memory(&walker); + return walker.found_region(); +} diff --git a/src/hotspot/share/services/virtualMemoryTracker.hpp b/src/hotspot/share/services/virtualMemoryTracker.hpp index c96af6b8387..2f04503cf6e 100644 --- a/src/hotspot/share/services/virtualMemoryTracker.hpp +++ b/src/hotspot/share/services/virtualMemoryTracker.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2022, 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 @@ -341,7 +341,7 @@ class ReservedMemoryRegion : public VirtualMemoryRegion { return *this; } - const char* flag_name() { return NMTUtil::flag_to_name(_flag); } + const char* flag_name() const { return NMTUtil::flag_to_name(_flag); } private: // The committed region contains the uncommitted region, subtract the uncommitted @@ -387,6 +387,8 @@ class VirtualMemoryTracker : AllStatic { // Walk virtual memory data structure for creating baseline, etc. static bool walk_virtual_memory(VirtualMemoryWalker* walker); + static const bool snapshot_region_contains(void* p, ReservedMemoryRegion& region); + // Snapshot current thread stacks static void snapshot_thread_stacks(); diff --git a/src/hotspot/share/utilities/debug.cpp b/src/hotspot/share/utilities/debug.cpp index 1a0c3a84647..c3c98d3067f 100644 --- a/src/hotspot/share/utilities/debug.cpp +++ b/src/hotspot/share/utilities/debug.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,6 +44,7 @@ #include "runtime/handles.inline.hpp" #include "runtime/java.hpp" #include "runtime/os.hpp" +#include "runtime/safefetch.inline.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/stubCodeGenerator.hpp" #include "runtime/stubRoutines.hpp" @@ -51,7 +52,9 @@ #include "runtime/vframe.hpp" #include "runtime/vm_version.hpp" #include "services/heapDumper.hpp" +#include "services/mallocTracker.hpp" #include "services/memTracker.hpp" +#include "services/virtualMemoryTracker.hpp" #include "utilities/defaultStream.hpp" #include "utilities/events.hpp" #include "utilities/formatBuffer.hpp" @@ -480,6 +483,41 @@ extern "C" JNIEXPORT void pp(void* p) { oop obj = cast_to_oop(p); obj->print(); } else { +#if INCLUDE_NMT + // With NMT + if (MemTracker::enabled()) { + const NMT_TrackingLevel tracking_level = MemTracker::tracking_level(); + ReservedMemoryRegion region(0, 0); + // Check and snapshot a mmap'd region that contains the pointer + if (VirtualMemoryTracker::snapshot_region_contains(p, region)) { + tty->print_cr(PTR_FORMAT " in mmap'd memory region [" PTR_FORMAT " - " PTR_FORMAT "] by %s", + p2i(p), p2i(region.base()), p2i(region.base() + region.size()), region.flag_name()); + if (tracking_level == NMT_detail) { + region.call_stack()->print_on(tty); + tty->cr(); + } + return; + } + // Check if it is a malloc'd memory block + if (CanUseSafeFetchN() && SafeFetchN((intptr_t*)p, 0) != 0) { + const MallocHeader* mhdr = (const MallocHeader*)MallocTracker::get_base(p, tracking_level); + char msg[256]; + address p_corrupted; + if (SafeFetchN((intptr_t*)mhdr, 0) != 0 && mhdr->check_block_integrity(msg, sizeof(msg), &p_corrupted)) { + tty->print_cr(PTR_FORMAT " malloc'd " SIZE_FORMAT " bytes by %s", + p2i(p), mhdr->size(), NMTUtil::flag_to_name(mhdr->flags())); + if (tracking_level == NMT_detail) { + NativeCallStack ncs; + if (mhdr->get_stack(ncs)) { + ncs.print_on(tty); + tty->cr(); + } + } + return; + } + } + } +#endif // INCLUDE_NMT tty->print(PTR_FORMAT, p2i(p)); } } -- GitLab From 53804720a04b5b314701de82eddf1a55798eba00 Mon Sep 17 00:00:00 2001 From: Andrey Turbanov Date: Tue, 25 Jan 2022 08:08:17 +0000 Subject: [PATCH 271/564] 8280470: Confusing instanceof check in HijrahChronology.range Reviewed-by: rriggs, naoto, dfuchs, iris --- .../java/time/chrono/HijrahChronology.java | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/java.base/share/classes/java/time/chrono/HijrahChronology.java b/src/java.base/share/classes/java/time/chrono/HijrahChronology.java index 87f307e15d3..1ce99906708 100644 --- a/src/java.base/share/classes/java/time/chrono/HijrahChronology.java +++ b/src/java.base/share/classes/java/time/chrono/HijrahChronology.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022, 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 @@ -533,18 +533,14 @@ public final class HijrahChronology extends AbstractChronology implements Serial @Override public ValueRange range(ChronoField field) { checkCalendarInit(); - if (field instanceof ChronoField) { - ChronoField f = field; - return switch (f) { - case DAY_OF_MONTH -> ValueRange.of(1, 1, getMinimumMonthLength(), getMaximumMonthLength()); - case DAY_OF_YEAR -> ValueRange.of(1, getMaximumDayOfYear()); - case ALIGNED_WEEK_OF_MONTH -> ValueRange.of(1, 5); - case YEAR, YEAR_OF_ERA -> ValueRange.of(getMinimumYear(), getMaximumYear()); - case ERA -> ValueRange.of(1, 1); - default -> field.range(); - }; - } - return field.range(); + return switch (field) { + case DAY_OF_MONTH -> ValueRange.of(1, 1, getMinimumMonthLength(), getMaximumMonthLength()); + case DAY_OF_YEAR -> ValueRange.of(1, getMaximumDayOfYear()); + case ALIGNED_WEEK_OF_MONTH -> ValueRange.of(1, 5); + case YEAR, YEAR_OF_ERA -> ValueRange.of(getMinimumYear(), getMaximumYear()); + case ERA -> ValueRange.of(1, 1); + default -> field.range(); + }; } //----------------------------------------------------------------------- -- GitLab From b32774653f72f379655192874cb7076079d238e6 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Tue, 25 Jan 2022 09:12:18 +0000 Subject: [PATCH 272/564] 8280384: Parallel: Remove VMThread specific ParCompactionManager Reviewed-by: ayang, sjohanss --- .../share/gc/parallel/psCompactionManager.cpp | 13 ++++---- .../share/gc/parallel/psCompactionManager.hpp | 4 ++- .../share/gc/parallel/psParallelCompact.cpp | 30 ++++--------------- .../share/gc/parallel/psParallelCompact.hpp | 5 ++-- .../gc/parallel/psParallelCompact.inline.hpp | 6 +--- .../share/gc/parallel/psPromotionManager.cpp | 12 ++++---- .../gc/parallel/psPromotionManager.inline.hpp | 2 +- 7 files changed, 23 insertions(+), 49 deletions(-) diff --git a/src/hotspot/share/gc/parallel/psCompactionManager.cpp b/src/hotspot/share/gc/parallel/psCompactionManager.cpp index 0a71ec80e3b..3a7fc8ae758 100644 --- a/src/hotspot/share/gc/parallel/psCompactionManager.cpp +++ b/src/hotspot/share/gc/parallel/psCompactionManager.cpp @@ -70,7 +70,7 @@ void ParCompactionManager::initialize(ParMarkBitMap* mbm) { uint parallel_gc_threads = ParallelScavengeHeap::heap()->workers().max_workers(); assert(_manager_array == NULL, "Attempt to initialize twice"); - _manager_array = NEW_C_HEAP_ARRAY(ParCompactionManager*, parallel_gc_threads+1, mtGC); + _manager_array = NEW_C_HEAP_ARRAY(ParCompactionManager*, parallel_gc_threads, mtGC); _oop_task_queues = new OopTaskQueueSet(parallel_gc_threads); _objarray_task_queues = new ObjArrayTaskQueueSet(parallel_gc_threads); @@ -84,9 +84,6 @@ void ParCompactionManager::initialize(ParMarkBitMap* mbm) { region_task_queues()->register_queue(i, _manager_array[i]->region_stack()); } - // The VMThread gets its own ParCompactionManager, which is not available - // for work stealing. - _manager_array[parallel_gc_threads] = new ParCompactionManager(); assert(ParallelScavengeHeap::heap()->workers().max_workers() != 0, "Not initialized?"); @@ -97,14 +94,14 @@ void ParCompactionManager::initialize(ParMarkBitMap* mbm) { void ParCompactionManager::reset_all_bitmap_query_caches() { uint parallel_gc_threads = ParallelScavengeHeap::heap()->workers().max_workers(); - for (uint i=0; i<=parallel_gc_threads; i++) { + for (uint i=0; ireset_bitmap_query_cache(); } } void ParCompactionManager::flush_all_string_dedup_requests() { uint parallel_gc_threads = ParallelScavengeHeap::heap()->workers().max_workers(); - for (uint i=0; i<=parallel_gc_threads; i++) { + for (uint i=0; iflush_string_dedup_requests(); } } @@ -184,14 +181,14 @@ void ParCompactionManager::remove_all_shadow_regions() { #ifdef ASSERT void ParCompactionManager::verify_all_marking_stack_empty() { uint parallel_gc_threads = ParallelGCThreads; - for (uint i = 0; i <= parallel_gc_threads; i++) { + for (uint i = 0; i < parallel_gc_threads; i++) { assert(_manager_array[i]->marking_stacks_empty(), "Marking stack should be empty"); } } void ParCompactionManager::verify_all_region_stack_empty() { uint parallel_gc_threads = ParallelGCThreads; - for (uint i = 0; i <= parallel_gc_threads; i++) { + for (uint i = 0; i < parallel_gc_threads; i++) { assert(_manager_array[i]->region_stack()->is_empty(), "Region stack should be empty"); } } diff --git a/src/hotspot/share/gc/parallel/psCompactionManager.hpp b/src/hotspot/share/gc/parallel/psCompactionManager.hpp index 2e73da920b5..4299f7e4c02 100644 --- a/src/hotspot/share/gc/parallel/psCompactionManager.hpp +++ b/src/hotspot/share/gc/parallel/psCompactionManager.hpp @@ -147,7 +147,9 @@ class ParCompactionManager : public CHeapObj { RegionTaskQueue* region_stack() { return &_region_stack; } - static ParCompactionManager* get_vmthread_cm() { return _manager_array[ParallelGCThreads]; } + // Get the compaction manager when doing evacuation work from the VM thread. + // Simply use the first compaction manager here. + static ParCompactionManager* get_vmthread_cm() { return _manager_array[0]; } ParCompactionManager(); diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.cpp b/src/hotspot/share/gc/parallel/psParallelCompact.cpp index 9d30f4bf2e2..4657975b1bc 100644 --- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp +++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp @@ -1595,8 +1595,7 @@ void PSParallelCompact::summary_phase_msg(SpaceId dst_space_id, } #endif // #ifndef PRODUCT -void PSParallelCompact::summary_phase(ParCompactionManager* cm, - bool maximum_compaction) +void PSParallelCompact::summary_phase(bool maximum_compaction) { GCTraceTime(Info, gc, phases) tm("Summary Phase", &_gc_timer); @@ -1756,9 +1755,6 @@ bool PSParallelCompact::invoke_no_policy(bool maximum_heap_compaction) { const PreGenGCValues pre_gc_values = heap->get_pre_gc_values(); - // Get the compaction manager reserved for the VM thread. - ParCompactionManager* const vmthread_cm = ParCompactionManager::get_vmthread_cm(); - { const uint active_workers = WorkerPolicy::calc_active_workers(ParallelScavengeHeap::heap()->workers().max_workers(), @@ -1787,11 +1783,11 @@ bool PSParallelCompact::invoke_no_policy(bool maximum_heap_compaction) { ref_processor()->start_discovery(maximum_heap_compaction); - marking_phase(vmthread_cm, &_gc_tracer); + marking_phase(&_gc_tracer); bool max_on_system_gc = UseMaximumCompactionOnSystemGC && GCCause::is_user_requested_gc(gc_cause); - summary_phase(vmthread_cm, maximum_heap_compaction || max_on_system_gc); + summary_phase(maximum_heap_compaction || max_on_system_gc); #if COMPILER2_OR_JVMCI assert(DerivedPointerTable::is_active(), "Sanity"); @@ -2063,8 +2059,7 @@ public: } }; -void PSParallelCompact::marking_phase(ParCompactionManager* cm, - ParallelOldTracer *gc_tracer) { +void PSParallelCompact::marking_phase(ParallelOldTracer *gc_tracer) { // Recursively traverse all live objects and mark them GCTraceTime(Info, gc, phases) tm("Marking Phase", &_gc_timer); @@ -2125,19 +2120,6 @@ void PSParallelCompact::marking_phase(ParCompactionManager* cm, _gc_tracer.report_object_count_after_gc(is_alive_closure()); } -#ifdef ASSERT -void PCAdjustPointerClosure::verify_cm(ParCompactionManager* cm) { - assert(cm != NULL, "associate ParCompactionManage should not be NULL"); - auto vmthread_cm = ParCompactionManager::get_vmthread_cm(); - if (Thread::current()->is_VM_thread()) { - assert(cm == vmthread_cm, "VM threads should use ParCompactionManager from get_vmthread_cm()"); - } else { - assert(Thread::current()->is_Worker_thread(), "Must be a GC thread"); - assert(cm != vmthread_cm, "GC threads should use ParCompactionManager from gc_thread_compaction_manager()"); - } -} -#endif - class PSAdjustTask final : public WorkerTask { SubTasksDone _sub_tasks; WeakProcessor::Task _weak_proc_task; @@ -2528,9 +2510,7 @@ void PSParallelCompact::compact() { { GCTraceTime(Trace, gc, phases) tm("Deferred Updates", &_gc_timer); - // Update the deferred objects, if any. In principle, any compaction - // manager can be used. However, since the current thread is VM thread, we - // use the rightful one to keep the verification logic happy. + // Update the deferred objects, if any. ParCompactionManager* cm = ParCompactionManager::get_vmthread_cm(); for (unsigned int id = old_space_id; id < last_space_id; ++id) { update_deferred_objects(cm, SpaceId(id)); diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.hpp b/src/hotspot/share/gc/parallel/psParallelCompact.hpp index 0b8eb6b0116..77a9d44f9b6 100644 --- a/src/hotspot/share/gc/parallel/psParallelCompact.hpp +++ b/src/hotspot/share/gc/parallel/psParallelCompact.hpp @@ -1062,8 +1062,7 @@ class PSParallelCompact : AllStatic { static void post_compact(); // Mark live objects - static void marking_phase(ParCompactionManager* cm, - ParallelOldTracer *gc_tracer); + static void marking_phase(ParallelOldTracer *gc_tracer); // Compute the dense prefix for the designated space. This is an experimental // implementation currently not used in production. @@ -1123,7 +1122,7 @@ class PSParallelCompact : AllStatic { static void summarize_spaces_quick(); static void summarize_space(SpaceId id, bool maximum_compaction); - static void summary_phase(ParCompactionManager* cm, bool maximum_compaction); + static void summary_phase(bool maximum_compaction); // Adjust addresses in roots. Does not adjust addresses in heap. static void adjust_roots(); diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.inline.hpp b/src/hotspot/share/gc/parallel/psParallelCompact.inline.hpp index 001f55c076a..48c5a98fd1a 100644 --- a/src/hotspot/share/gc/parallel/psParallelCompact.inline.hpp +++ b/src/hotspot/share/gc/parallel/psParallelCompact.inline.hpp @@ -126,9 +126,7 @@ inline void PSParallelCompact::adjust_pointer(T* p, ParCompactionManager* cm) { class PCAdjustPointerClosure: public BasicOopIterateClosure { public: - PCAdjustPointerClosure(ParCompactionManager* cm) { - verify_cm(cm); - _cm = cm; + PCAdjustPointerClosure(ParCompactionManager* cm) : _cm(cm) { } template void do_oop_nv(T* p) { PSParallelCompact::adjust_pointer(p, _cm); } virtual void do_oop(oop* p) { do_oop_nv(p); } @@ -137,8 +135,6 @@ public: virtual ReferenceIterationMode reference_iteration_mode() { return DO_FIELDS; } private: ParCompactionManager* _cm; - - static void verify_cm(ParCompactionManager* cm) NOT_DEBUG_RETURN; }; #endif // SHARE_GC_PARALLEL_PSPARALLELCOMPACT_INLINE_HPP diff --git a/src/hotspot/share/gc/parallel/psPromotionManager.cpp b/src/hotspot/share/gc/parallel/psPromotionManager.cpp index 7ef706aba93..f7308366400 100644 --- a/src/hotspot/share/gc/parallel/psPromotionManager.cpp +++ b/src/hotspot/share/gc/parallel/psPromotionManager.cpp @@ -54,7 +54,7 @@ void PSPromotionManager::initialize() { _old_gen = heap->old_gen(); _young_space = heap->young_gen()->to_space(); - const uint promotion_manager_num = ParallelGCThreads + 1; + const uint promotion_manager_num = ParallelGCThreads; // To prevent false sharing, we pad the PSPromotionManagers // and make sure that the first instance starts at a cache line. @@ -95,7 +95,7 @@ PSPromotionManager* PSPromotionManager::gc_thread_promotion_manager(uint index) PSPromotionManager* PSPromotionManager::vm_thread_promotion_manager() { assert(_manager_array != NULL, "Sanity"); - return &_manager_array[ParallelGCThreads]; + return &_manager_array[0]; } void PSPromotionManager::pre_scavenge() { @@ -104,7 +104,7 @@ void PSPromotionManager::pre_scavenge() { _preserved_marks_set->assert_empty(); _young_space = heap->young_gen()->to_space(); - for(uint i=0; ireset(); } } @@ -113,7 +113,7 @@ bool PSPromotionManager::post_scavenge(YoungGCTracer& gc_tracer) { bool promotion_failure_occurred = false; TASKQUEUE_STATS_ONLY(print_taskqueue_stats()); - for (uint i = 0; i < ParallelGCThreads + 1; i++) { + for (uint i = 0; i < ParallelGCThreads; i++) { PSPromotionManager* manager = manager_array(i); assert(manager->claimed_stack_depth()->is_empty(), "should be empty"); if (manager->_promotion_failed_info.has_failed()) { @@ -162,7 +162,7 @@ PSPromotionManager::print_taskqueue_stats() { TaskQueueStats totals; out->print("thr "); TaskQueueStats::print_header(1, out); out->cr(); out->print("--- "); TaskQueueStats::print_header(2, out); out->cr(); - for (uint i = 0; i < ParallelGCThreads + 1; ++i) { + for (uint i = 0; i < ParallelGCThreads; ++i) { TaskQueueStats& next = manager_array(i)->_claimed_stack_depth.stats; out->print("%3d ", i); next.print(out); out->cr(); totals += next; @@ -171,7 +171,7 @@ PSPromotionManager::print_taskqueue_stats() { const uint hlines = sizeof(pm_stats_hdr) / sizeof(pm_stats_hdr[0]); for (uint i = 0; i < hlines; ++i) out->print_cr("%s", pm_stats_hdr[i]); - for (uint i = 0; i < ParallelGCThreads + 1; ++i) { + for (uint i = 0; i < ParallelGCThreads; ++i) { manager_array(i)->print_local_stats(out, i); } } diff --git a/src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp b/src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp index 733af9bee7f..b3f1c7297f4 100644 --- a/src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp +++ b/src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp @@ -44,7 +44,7 @@ inline PSPromotionManager* PSPromotionManager::manager_array(uint index) { assert(_manager_array != NULL, "access of NULL manager_array"); - assert(index <= ParallelGCThreads, "out of range manager_array access"); + assert(index < ParallelGCThreads, "out of range manager_array access"); return &_manager_array[index]; } -- GitLab From 295b263fa951b9d51bfa92c04e49b2a17a62bd6f Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Tue, 25 Jan 2022 09:13:50 +0000 Subject: [PATCH 273/564] 8279241: G1 Full GC does not always slide memory to bottom addresses Reviewed-by: iwalulya, ayang, sjohanss --- src/hotspot/share/gc/g1/g1FullCollector.cpp | 65 ++++- src/hotspot/share/gc/g1/g1FullCollector.hpp | 12 +- .../share/gc/g1/g1FullCollector.inline.hpp | 6 +- .../share/gc/g1/g1FullGCHeapRegionAttr.hpp | 6 +- .../share/gc/g1/g1FullGCPrepareTask.cpp | 239 ++++++------------ .../share/gc/g1/g1FullGCPrepareTask.hpp | 93 ++++--- .../gc/g1/g1FullGCPrepareTask.inline.hpp | 126 +++++++++ src/hotspot/share/gc/g1/g1FullGCScope.cpp | 4 +- src/hotspot/share/gc/g1/g1FullGCScope.hpp | 4 +- 9 files changed, 346 insertions(+), 209 deletions(-) create mode 100644 src/hotspot/share/gc/g1/g1FullGCPrepareTask.inline.hpp diff --git a/src/hotspot/share/gc/g1/g1FullCollector.cpp b/src/hotspot/share/gc/g1/g1FullCollector.cpp index 603b3818029..dd20a099919 100644 --- a/src/hotspot/share/gc/g1/g1FullCollector.cpp +++ b/src/hotspot/share/gc/g1/g1FullCollector.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,7 @@ #include "gc/g1/g1FullGCCompactTask.hpp" #include "gc/g1/g1FullGCMarker.inline.hpp" #include "gc/g1/g1FullGCMarkTask.hpp" -#include "gc/g1/g1FullGCPrepareTask.hpp" +#include "gc/g1/g1FullGCPrepareTask.inline.hpp" #include "gc/g1/g1FullGCScope.hpp" #include "gc/g1/g1OopClosures.hpp" #include "gc/g1/g1Policy.hpp" @@ -297,14 +297,67 @@ void G1FullCollector::phase1_mark_live_objects() { } void G1FullCollector::phase2_prepare_compaction() { - GCTraceTime(Info, gc, phases) info("Phase 2: Prepare for compaction", scope()->timer()); + GCTraceTime(Info, gc, phases) info("Phase 2: Prepare compaction", scope()->timer()); + + phase2a_determine_worklists(); + + bool has_free_compaction_targets = phase2b_forward_oops(); + + // Try to avoid OOM immediately after Full GC in case there are no free regions + // left after determining the result locations (i.e. this phase). Prepare to + // maximally compact the tail regions of the compaction queues serially. + if (!has_free_compaction_targets) { + phase2c_prepare_serial_compaction(); + } +} + +void G1FullCollector::phase2a_determine_worklists() { + GCTraceTime(Debug, gc, phases) debug("Phase 2: Determine work lists", scope()->timer()); + + G1DetermineCompactionQueueClosure cl(this); + _heap->heap_region_iterate(&cl); +} + +bool G1FullCollector::phase2b_forward_oops() { + GCTraceTime(Debug, gc, phases) debug("Phase 2: Prepare parallel compaction", scope()->timer()); + G1FullGCPrepareTask task(this); run_task(&task); - // To avoid OOM when there is memory left. - if (!task.has_freed_regions()) { - task.prepare_serial_compaction(); + return task.has_free_compaction_targets(); +} + +void G1FullCollector::phase2c_prepare_serial_compaction() { + GCTraceTime(Debug, gc, phases) debug("Phase 2: Prepare serial compaction", scope()->timer()); + // At this point we know that after parallel compaction there will be no + // completely free regions. That means that the last region of + // all compaction queues still have data in them. We try to compact + // these regions in serial to avoid a premature OOM when the mutator wants + // to allocate the first eden region after gc. + for (uint i = 0; i < workers(); i++) { + G1FullGCCompactionPoint* cp = compaction_point(i); + if (cp->has_regions()) { + serial_compaction_point()->add(cp->remove_last()); + } + } + + // Update the forwarding information for the regions in the serial + // compaction point. + G1FullGCCompactionPoint* cp = serial_compaction_point(); + for (GrowableArrayIterator it = cp->regions()->begin(); it != cp->regions()->end(); ++it) { + HeapRegion* current = *it; + if (!cp->is_initialized()) { + // Initialize the compaction point. Nothing more is needed for the first heap region + // since it is already prepared for compaction. + cp->initialize(current, false); + } else { + assert(!current->is_humongous(), "Should be no humongous regions in compaction queue"); + G1SerialRePrepareClosure re_prepare(cp, current); + current->set_compaction_top(current->bottom()); + current->apply_to_marked_objects(mark_bitmap(), &re_prepare); + } } + cp->update(); } void G1FullCollector::phase3_adjust_pointers() { diff --git a/src/hotspot/share/gc/g1/g1FullCollector.hpp b/src/hotspot/share/gc/g1/g1FullCollector.hpp index c4d019629dd..f9087298b86 100644 --- a/src/hotspot/share/gc/g1/g1FullCollector.hpp +++ b/src/hotspot/share/gc/g1/g1FullCollector.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022, 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 @@ public: G1FullGCCompactionPoint* serial_compaction_point() { return &_serial_compaction_point; } G1CMBitMap* mark_bitmap(); ReferenceProcessor* reference_processor(); - size_t live_words(uint region_index) { + size_t live_words(uint region_index) const { assert(region_index < _heap->max_regions(), "sanity"); return _live_stats[region_index]._live_words; } @@ -121,6 +121,9 @@ public: inline bool is_skip_compacting(uint region_index) const; inline bool is_skip_marking(oop obj) const; + // Are we (potentially) going to compact into this region? + inline bool is_compaction_target(uint region_index) const; + inline void set_free(uint region_idx); inline bool is_free(uint region_idx) const; inline void update_from_compacting_to_skip_compacting(uint region_idx); @@ -128,6 +131,11 @@ public: private: void phase1_mark_live_objects(); void phase2_prepare_compaction(); + + void phase2a_determine_worklists(); + bool phase2b_forward_oops(); + void phase2c_prepare_serial_compaction(); + void phase3_adjust_pointers(); void phase4_do_compaction(); diff --git a/src/hotspot/share/gc/g1/g1FullCollector.inline.hpp b/src/hotspot/share/gc/g1/g1FullCollector.inline.hpp index 5a0863b202a..37e16fc6f78 100644 --- a/src/hotspot/share/gc/g1/g1FullCollector.inline.hpp +++ b/src/hotspot/share/gc/g1/g1FullCollector.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, 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 @@ -43,6 +43,10 @@ bool G1FullCollector::is_skip_marking(oop obj) const { return _region_attr_table.is_skip_marking(cast_from_oop(obj)); } +bool G1FullCollector::is_compaction_target(uint region_index) const { + return _region_attr_table.is_compacting(region_index) || is_free(region_index); +} + void G1FullCollector::set_free(uint region_idx) { _region_attr_table.set_free(region_idx); } diff --git a/src/hotspot/share/gc/g1/g1FullGCHeapRegionAttr.hpp b/src/hotspot/share/gc/g1/g1FullGCHeapRegionAttr.hpp index ca2f970edde..017877785f4 100644 --- a/src/hotspot/share/gc/g1/g1FullGCHeapRegionAttr.hpp +++ b/src/hotspot/share/gc/g1/g1FullGCHeapRegionAttr.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, 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 @@ -70,6 +70,10 @@ public: return get_by_address(obj) == Compacting; } + bool is_compacting(uint idx) const { + return get_by_index(idx) == Compacting; + } + bool is_skip_compacting(uint idx) const { return get_by_index(idx) == SkipCompacting; } diff --git a/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp b/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp index 883e0a51f86..4ffe9329dc7 100644 --- a/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp +++ b/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022, 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,13 +23,13 @@ */ #include "precompiled.hpp" -#include "gc/g1/g1CollectedHeap.hpp" +#include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1ConcurrentMarkBitMap.inline.hpp" #include "gc/g1/g1FullCollector.inline.hpp" #include "gc/g1/g1FullGCCompactionPoint.hpp" #include "gc/g1/g1FullGCMarker.hpp" #include "gc/g1/g1FullGCOopClosures.inline.hpp" -#include "gc/g1/g1FullGCPrepareTask.hpp" +#include "gc/g1/g1FullGCPrepareTask.inline.hpp" #include "gc/g1/g1HotCardCache.hpp" #include "gc/g1/heapRegion.inline.hpp" #include "gc/shared/gcTraceTime.inline.hpp" @@ -39,113 +39,84 @@ #include "oops/oop.inline.hpp" #include "utilities/ticks.hpp" -template -void G1FullGCPrepareTask::G1CalculatePointersClosure::free_pinned_region(HeapRegion* hr) { - _regions_freed = true; - if (is_humongous) { - _g1h->free_humongous_region(hr, nullptr); - } else { - _g1h->free_region(hr, nullptr); - } - _collector->set_free(hr->hrm_index()); - prepare_for_compaction(hr); -} +G1DetermineCompactionQueueClosure::G1DetermineCompactionQueueClosure(G1FullCollector* collector) : + _g1h(G1CollectedHeap::heap()), + _collector(collector), + _cur_worker(0) { } bool G1FullGCPrepareTask::G1CalculatePointersClosure::do_heap_region(HeapRegion* hr) { - if (should_compact(hr)) { - assert(!hr->is_humongous(), "moving humongous objects not supported."); - prepare_for_compaction(hr); - } else { - // There is no need to iterate and forward objects in pinned regions ie. - // prepare them for compaction. The adjust pointers phase will skip - // work for them. - assert(hr->containing_set() == nullptr, "already cleared by PrepareRegionsClosure"); - if (hr->is_humongous()) { - oop obj = cast_to_oop(hr->humongous_start_region()->bottom()); - if (!_bitmap->is_marked(obj)) { - free_pinned_region(hr); - } - } else if (hr->is_open_archive()) { - bool is_empty = _collector->live_words(hr->hrm_index()) == 0; - if (is_empty) { - free_pinned_region(hr); - } - } else if (hr->is_closed_archive()) { - // nothing to do with closed archive region - } else { - assert(MarkSweepDeadRatio > 0, - "only skip compaction for other regions when MarkSweepDeadRatio > 0"); - - // Too many live objects; skip compacting it. - _collector->update_from_compacting_to_skip_compacting(hr->hrm_index()); - if (hr->is_young()) { - // G1 updates the BOT for old region contents incrementally, but young regions - // lack BOT information for performance reasons. - // Recreate BOT information of high live ratio young regions here to keep expected - // performance during scanning their card tables in the collection pauses later. - hr->update_bot(); - } - log_trace(gc, phases)("Phase 2: skip compaction region index: %u, live words: " SIZE_FORMAT, - hr->hrm_index(), _collector->live_words(hr->hrm_index())); - } - } + uint region_idx = hr->hrm_index(); + assert(_collector->is_compaction_target(region_idx), "must be"); - // Reset data structures not valid after Full GC. - reset_region_metadata(hr); + assert(!hr->is_pinned(), "must be"); + assert(!hr->is_closed_archive(), "must be"); + assert(!hr->is_open_archive(), "must be"); + + prepare_for_compaction(hr); return false; } G1FullGCPrepareTask::G1FullGCPrepareTask(G1FullCollector* collector) : G1FullGCTask("G1 Prepare Compact Task", collector), - _freed_regions(false), + _has_free_compaction_targets(false), _hrclaimer(collector->workers()) { } -void G1FullGCPrepareTask::set_freed_regions() { - if (!_freed_regions) { - _freed_regions = true; +void G1FullGCPrepareTask::set_has_free_compaction_targets() { + if (!_has_free_compaction_targets) { + _has_free_compaction_targets = true; } } -bool G1FullGCPrepareTask::has_freed_regions() { - return _freed_regions; +bool G1FullGCPrepareTask::has_free_compaction_targets() { + return _has_free_compaction_targets; } void G1FullGCPrepareTask::work(uint worker_id) { Ticks start = Ticks::now(); - G1FullGCCompactionPoint* compaction_point = collector()->compaction_point(worker_id); - G1CalculatePointersClosure closure(collector(), compaction_point); - G1CollectedHeap::heap()->heap_region_par_iterate_from_start(&closure, &_hrclaimer); - - compaction_point->update(); + // Calculate the target locations for the objects in the non-free regions of + // the compaction queues provided by the associate compaction point. + { + G1FullGCCompactionPoint* compaction_point = collector()->compaction_point(worker_id); + G1CalculatePointersClosure closure(collector(), compaction_point); + + for (GrowableArrayIterator it = compaction_point->regions()->begin(); + it != compaction_point->regions()->end(); + ++it) { + closure.do_heap_region(*it); + } + compaction_point->update(); + // Determine if there are any unused compaction targets. This is only the case if + // there are + // - any regions in queue, so no free ones either. + // - and the current region is not the last one in the list. + if (compaction_point->has_regions() && + compaction_point->current_region() != compaction_point->regions()->last()) { + set_has_free_compaction_targets(); + } + } - // Check if any regions was freed by this worker and store in task. - if (closure.freed_regions()) { - set_freed_regions(); + // Clear region metadata that is invalid after GC for all regions. + { + G1ResetMetadataClosure closure(collector()); + G1CollectedHeap::heap()->heap_region_par_iterate_from_start(&closure, &_hrclaimer); } log_task("Prepare compaction task", worker_id, start); } G1FullGCPrepareTask::G1CalculatePointersClosure::G1CalculatePointersClosure(G1FullCollector* collector, G1FullGCCompactionPoint* cp) : - _g1h(G1CollectedHeap::heap()), - _collector(collector), - _bitmap(collector->mark_bitmap()), - _cp(cp), - _regions_freed(false) { } - -bool G1FullGCPrepareTask::G1CalculatePointersClosure::should_compact(HeapRegion* hr) { - if (hr->is_pinned()) { - return false; - } - size_t live_words = _collector->live_words(hr->hrm_index()); - size_t live_words_threshold = _collector->scope()->region_compaction_threshold(); - // High live ratio region will not be compacted. - return live_words <= live_words_threshold; -} + _g1h(G1CollectedHeap::heap()), + _collector(collector), + _bitmap(collector->mark_bitmap()), + _cp(cp) { } -void G1FullGCPrepareTask::G1CalculatePointersClosure::reset_region_metadata(HeapRegion* hr) { +G1FullGCPrepareTask::G1ResetMetadataClosure::G1ResetMetadataClosure(G1FullCollector* collector) : + _g1h(G1CollectedHeap::heap()), + _collector(collector) { } + +void G1FullGCPrepareTask::G1ResetMetadataClosure::reset_region_metadata(HeapRegion* hr) { hr->rem_set()->clear(); hr->clear_cardtable(); @@ -155,6 +126,26 @@ void G1FullGCPrepareTask::G1CalculatePointersClosure::reset_region_metadata(Heap } } +bool G1FullGCPrepareTask::G1ResetMetadataClosure::do_heap_region(HeapRegion* hr) { + uint const region_idx = hr->hrm_index(); + if (!_collector->is_compaction_target(region_idx)) { + assert(!hr->is_free(), "all free regions should be compaction targets"); + assert(_collector->is_skip_compacting(region_idx) || hr->is_closed_archive(), "must be"); + if (hr->is_young()) { + // G1 updates the BOT for old region contents incrementally, but young regions + // lack BOT information for performance reasons. + // Recreate BOT information of high live ratio young regions here to keep expected + // performance during scanning their card tables in the collection pauses later. + hr->update_bot(); + } + } + + // Reset data structures not valid after Full GC. + reset_region_metadata(hr); + + return false; +} + G1FullGCPrepareTask::G1PrepareCompactLiveClosure::G1PrepareCompactLiveClosure(G1FullGCCompactionPoint* cp) : _cp(cp) { } @@ -164,87 +155,9 @@ size_t G1FullGCPrepareTask::G1PrepareCompactLiveClosure::apply(oop object) { return size; } -size_t G1FullGCPrepareTask::G1RePrepareClosure::apply(oop obj) { - // We only re-prepare objects forwarded within the current region, so - // skip objects that are already forwarded to another region. - if (obj->is_forwarded() && !_current->is_in(obj->forwardee())) { - return obj->size(); - } - - // Get size and forward. - size_t size = obj->size(); - _cp->forward(obj, size); - - return size; -} - -void G1FullGCPrepareTask::G1CalculatePointersClosure::prepare_for_compaction_work(G1FullGCCompactionPoint* cp, - HeapRegion* hr) { - hr->set_compaction_top(hr->bottom()); +void G1FullGCPrepareTask::G1CalculatePointersClosure::prepare_for_compaction(HeapRegion* hr) { if (!_collector->is_free(hr->hrm_index())) { - G1PrepareCompactLiveClosure prepare_compact(cp); + G1PrepareCompactLiveClosure prepare_compact(_cp); hr->apply_to_marked_objects(_bitmap, &prepare_compact); } } - -void G1FullGCPrepareTask::G1CalculatePointersClosure::prepare_for_compaction(HeapRegion* hr) { - if (!_cp->is_initialized()) { - hr->set_compaction_top(hr->bottom()); - _cp->initialize(hr, true); - } - // Add region to the compaction queue and prepare it. - _cp->add(hr); - prepare_for_compaction_work(_cp, hr); -} - -void G1FullGCPrepareTask::prepare_serial_compaction() { - GCTraceTime(Debug, gc, phases) debug("Phase 2: Prepare Serial Compaction", collector()->scope()->timer()); - // At this point we know that no regions were completely freed by - // the parallel compaction. That means that the last region of - // all compaction queues still have data in them. We try to compact - // these regions in serial to avoid a premature OOM. - for (uint i = 0; i < collector()->workers(); i++) { - G1FullGCCompactionPoint* cp = collector()->compaction_point(i); - if (cp->has_regions()) { - collector()->serial_compaction_point()->add(cp->remove_last()); - } - } - - // Update the forwarding information for the regions in the serial - // compaction point. - G1FullGCCompactionPoint* cp = collector()->serial_compaction_point(); - for (GrowableArrayIterator it = cp->regions()->begin(); it != cp->regions()->end(); ++it) { - HeapRegion* current = *it; - if (!cp->is_initialized()) { - // Initialize the compaction point. Nothing more is needed for the first heap region - // since it is already prepared for compaction. - cp->initialize(current, false); - } else { - assert(!current->is_humongous(), "Should be no humongous regions in compaction queue"); - G1RePrepareClosure re_prepare(cp, current); - current->set_compaction_top(current->bottom()); - current->apply_to_marked_objects(collector()->mark_bitmap(), &re_prepare); - } - } - cp->update(); -} - -bool G1FullGCPrepareTask::G1CalculatePointersClosure::freed_regions() { - if (_regions_freed) { - return true; - } - - if (!_cp->has_regions()) { - // No regions in queue, so no free ones either. - return false; - } - - if (_cp->current_region() != _cp->regions()->last()) { - // The current region used for compaction is not the last in the - // queue. That means there is at least one free region in the queue. - return true; - } - - // No free regions in the queue. - return false; -} diff --git a/src/hotspot/share/gc/g1/g1FullGCPrepareTask.hpp b/src/hotspot/share/gc/g1/g1FullGCPrepareTask.hpp index d694fc6ffca..41c0c67d87c 100644 --- a/src/hotspot/share/gc/g1/g1FullGCPrepareTask.hpp +++ b/src/hotspot/share/gc/g1/g1FullGCPrepareTask.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022, 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,53 +25,81 @@ #ifndef SHARE_GC_G1_G1FULLGCPREPARETASK_HPP #define SHARE_GC_G1_G1FULLGCPREPARETASK_HPP -#include "gc/g1/g1FullGCCompactionPoint.hpp" -#include "gc/g1/g1FullGCScope.hpp" #include "gc/g1/g1FullGCTask.hpp" -#include "gc/g1/g1RootProcessor.hpp" -#include "gc/g1/heapRegionManager.hpp" -#include "gc/shared/referenceProcessor.hpp" +#include "gc/g1/heapRegion.hpp" +#include "memory/allocation.hpp" +class G1CollectedHeap; class G1CMBitMap; class G1FullCollector; +class G1FullGCCompactionPoint; +class HeapRegion; + +// Determines the regions in the heap that should be part of the compaction and +// distributes them among the compaction queues in round-robin fashion. +class G1DetermineCompactionQueueClosure : public HeapRegionClosure { + G1CollectedHeap* _g1h; + G1FullCollector* _collector; + uint _cur_worker; + + template + inline void free_pinned_region(HeapRegion* hr); + + inline bool should_compact(HeapRegion* hr) const; + + // Returns the current worker id to assign a compaction point to, and selects + // the next one round-robin style. + inline uint next_worker(); + + inline G1FullGCCompactionPoint* next_compaction_point(); + + inline void add_to_compaction_queue(HeapRegion* hr); + +public: + G1DetermineCompactionQueueClosure(G1FullCollector* collector); + + inline bool do_heap_region(HeapRegion* hr) override; +}; class G1FullGCPrepareTask : public G1FullGCTask { -protected: - volatile bool _freed_regions; + volatile bool _has_free_compaction_targets; HeapRegionClaimer _hrclaimer; - void set_freed_regions(); + void set_has_free_compaction_targets(); public: G1FullGCPrepareTask(G1FullCollector* collector); void work(uint worker_id); - void prepare_serial_compaction(); - bool has_freed_regions(); + // After the Prepare phase, are there any unused (empty) regions (compaction + // targets) at the end of any compaction queues? + bool has_free_compaction_targets(); -protected: +private: class G1CalculatePointersClosure : public HeapRegionClosure { - private: - template - void free_pinned_region(HeapRegion* hr); - protected: G1CollectedHeap* _g1h; G1FullCollector* _collector; G1CMBitMap* _bitmap; G1FullGCCompactionPoint* _cp; - bool _regions_freed; - bool should_compact(HeapRegion* hr); void prepare_for_compaction(HeapRegion* hr); - void prepare_for_compaction_work(G1FullGCCompactionPoint* cp, HeapRegion* hr); - - void reset_region_metadata(HeapRegion* hr); public: G1CalculatePointersClosure(G1FullCollector* collector, G1FullGCCompactionPoint* cp); bool do_heap_region(HeapRegion* hr); - bool freed_regions(); + }; + + class G1ResetMetadataClosure : public HeapRegionClosure { + G1CollectedHeap* _g1h; + G1FullCollector* _collector; + + void reset_region_metadata(HeapRegion* hr); + + public: + G1ResetMetadataClosure(G1FullCollector* collector); + + bool do_heap_region(HeapRegion* hr); }; class G1PrepareCompactLiveClosure : public StackObj { @@ -81,19 +109,20 @@ protected: G1PrepareCompactLiveClosure(G1FullGCCompactionPoint* cp); size_t apply(oop object); }; +}; - class G1RePrepareClosure : public StackObj { - G1FullGCCompactionPoint* _cp; - HeapRegion* _current; +// Closure to re-prepare objects in the serial compaction point queue regions for +// serial compaction. +class G1SerialRePrepareClosure : public StackObj { + G1FullGCCompactionPoint* _cp; + HeapRegion* _current; - public: - G1RePrepareClosure(G1FullGCCompactionPoint* hrcp, - HeapRegion* hr) : - _cp(hrcp), - _current(hr) { } +public: + G1SerialRePrepareClosure(G1FullGCCompactionPoint* hrcp, HeapRegion* hr) : + _cp(hrcp), + _current(hr) { } - size_t apply(oop object); - }; + inline size_t apply(oop obj); }; #endif // SHARE_GC_G1_G1FULLGCPREPARETASK_HPP diff --git a/src/hotspot/share/gc/g1/g1FullGCPrepareTask.inline.hpp b/src/hotspot/share/gc/g1/g1FullGCPrepareTask.inline.hpp new file mode 100644 index 00000000000..75493b7de4f --- /dev/null +++ b/src/hotspot/share/gc/g1/g1FullGCPrepareTask.inline.hpp @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_GC_G1_G1FULLGCPREPARETASK_INLINE_HPP +#define SHARE_GC_G1_G1FULLGCPREPARETASK_INLINE_HPP + +#include "gc/g1/g1FullGCPrepareTask.hpp" + +#include "gc/g1/g1CollectedHeap.inline.hpp" +#include "gc/g1/g1FullCollector.hpp" +#include "gc/g1/g1FullGCCompactionPoint.hpp" +#include "gc/g1/g1FullGCScope.hpp" +#include "gc/g1/heapRegion.inline.hpp" + +template +void G1DetermineCompactionQueueClosure::free_pinned_region(HeapRegion* hr) { + if (is_humongous) { + _g1h->free_humongous_region(hr, nullptr); + } else { + _g1h->free_region(hr, nullptr); + } + _collector->set_free(hr->hrm_index()); + add_to_compaction_queue(hr); +} + +inline bool G1DetermineCompactionQueueClosure::should_compact(HeapRegion* hr) const { + // There is no need to iterate and forward objects in pinned regions ie. + // prepare them for compaction. + if (hr->is_pinned()) { + return false; + } + size_t live_words = _collector->live_words(hr->hrm_index()); + size_t live_words_threshold = _collector->scope()->region_compaction_threshold(); + // High live ratio region will not be compacted. + return live_words <= live_words_threshold; +} + +inline uint G1DetermineCompactionQueueClosure::next_worker() { + uint result = _cur_worker; + _cur_worker = (_cur_worker + 1) % _collector->workers(); + return result; +} + +inline G1FullGCCompactionPoint* G1DetermineCompactionQueueClosure::next_compaction_point() { + return _collector->compaction_point(next_worker()); +} + +inline void G1DetermineCompactionQueueClosure::add_to_compaction_queue(HeapRegion* hr) { + hr->set_compaction_top(hr->bottom()); + G1FullGCCompactionPoint* cp = next_compaction_point(); + if (!cp->is_initialized()) { + cp->initialize(hr, true); + } + // Add region to the compaction queue. + cp->add(hr); +} + +inline bool G1DetermineCompactionQueueClosure::do_heap_region(HeapRegion* hr) { + if (should_compact(hr)) { + assert(!hr->is_humongous(), "moving humongous objects not supported."); + add_to_compaction_queue(hr); + } else { + assert(hr->containing_set() == nullptr, "already cleared by PrepareRegionsClosure"); + if (hr->is_humongous()) { + oop obj = cast_to_oop(hr->humongous_start_region()->bottom()); + bool is_empty = !_collector->mark_bitmap()->is_marked(obj); + if (is_empty) { + free_pinned_region(hr); + } + } else if (hr->is_open_archive()) { + bool is_empty = _collector->live_words(hr->hrm_index()) == 0; + if (is_empty) { + free_pinned_region(hr); + } + } else if (hr->is_closed_archive()) { + // nothing to do with closed archive region + } else { + assert(MarkSweepDeadRatio > 0, + "only skip compaction for other regions when MarkSweepDeadRatio > 0"); + + // Too many live objects in the region; skip compacting it. + _collector->update_from_compacting_to_skip_compacting(hr->hrm_index()); + log_trace(gc, phases)("Phase 2: skip compaction region index: %u, live words: " SIZE_FORMAT, + hr->hrm_index(), _collector->live_words(hr->hrm_index())); + } + } + + return false; +} + +inline size_t G1SerialRePrepareClosure::apply(oop obj) { + // We only re-prepare objects forwarded within the current region, so + // skip objects that are already forwarded to another region. + if (obj->is_forwarded() && !_current->is_in(obj->forwardee())) { + return obj->size(); + } + + // Get size and forward. + size_t size = obj->size(); + _cp->forward(obj, size); + + return size; +} + +#endif // SHARE_GC_G1_G1FULLGCPREPARETASK_INLINE_HPP diff --git a/src/hotspot/share/gc/g1/g1FullGCScope.cpp b/src/hotspot/share/gc/g1/g1FullGCScope.cpp index b4d3b365603..0437d157eb0 100644 --- a/src/hotspot/share/gc/g1/g1FullGCScope.cpp +++ b/src/hotspot/share/gc/g1/g1FullGCScope.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022, 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 @@ -70,6 +70,6 @@ G1FullGCTracer* G1FullGCScope::tracer() { return &_tracer; } -size_t G1FullGCScope::region_compaction_threshold() { +size_t G1FullGCScope::region_compaction_threshold() const { return _region_compaction_threshold; } diff --git a/src/hotspot/share/gc/g1/g1FullGCScope.hpp b/src/hotspot/share/gc/g1/g1FullGCScope.hpp index c0035b9052a..a6e079f4d63 100644 --- a/src/hotspot/share/gc/g1/g1FullGCScope.hpp +++ b/src/hotspot/share/gc/g1/g1FullGCScope.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -71,7 +71,7 @@ public: STWGCTimer* timer(); G1FullGCTracer* tracer(); G1HeapTransition* heap_transition(); - size_t region_compaction_threshold(); + size_t region_compaction_threshold() const; }; #endif // SHARE_GC_G1_G1FULLGCSCOPE_HPP -- GitLab From 2155afe2a87d718757b009d712361d7a63946a7f Mon Sep 17 00:00:00 2001 From: Thomas Stuefe Date: Tue, 25 Jan 2022 09:15:11 +0000 Subject: [PATCH 274/564] 8280503: Use allStatic.hpp instead of allocation.hpp where possible Reviewed-by: dholmes, iklam --- src/hotspot/cpu/aarch64/bytes_aarch64.hpp | 4 ++-- src/hotspot/cpu/aarch64/jniTypes_aarch64.hpp | 4 ++-- src/hotspot/cpu/arm/bytes_arm.hpp | 4 ++-- src/hotspot/cpu/arm/jniTypes_arm.hpp | 4 ++-- src/hotspot/cpu/ppc/bytes_ppc.hpp | 6 +++--- src/hotspot/cpu/ppc/jniTypes_ppc.hpp | 6 +++--- src/hotspot/cpu/s390/bytes_s390.hpp | 6 +++--- src/hotspot/cpu/s390/jniTypes_s390.hpp | 4 ++-- src/hotspot/cpu/x86/bytes_x86.hpp | 4 ++-- src/hotspot/cpu/x86/c2_intelJccErratum_x86.hpp | 4 ++-- src/hotspot/cpu/x86/jniTypes_x86.hpp | 4 ++-- src/hotspot/cpu/x86/rdtsc_x86.hpp | 5 +++-- src/hotspot/cpu/zero/bytes_zero.hpp | 4 ++-- src/hotspot/cpu/zero/jniTypes_zero.hpp | 4 ++-- src/hotspot/os/bsd/gc/z/zNUMA_bsd.cpp | 1 + src/hotspot/os/linux/gc/z/zSyscall_linux.hpp | 5 +++-- src/hotspot/os/linux/osContainer_linux.hpp | 4 ++-- src/hotspot/os/posix/signals_posix.hpp | 4 ++-- src/hotspot/os/posix/threadLocalStorage_posix.cpp | 3 ++- src/hotspot/os/windows/gc/z/zMapper_windows.hpp | 2 +- src/hotspot/os/windows/iphlp_interface.hpp | 4 ++-- src/hotspot/os/windows/pdh_interface.hpp | 4 ++-- src/hotspot/os/windows/threadLocalStorage_windows.cpp | 1 + src/hotspot/share/c1/c1_Runtime1.hpp | 4 ++-- src/hotspot/share/cds/archiveUtils.cpp | 4 +++- src/hotspot/share/cds/dynamicArchive.hpp | 4 ++-- src/hotspot/share/classfile/altHashing.hpp | 5 +++-- src/hotspot/share/classfile/klassFactory.hpp | 4 ++-- src/hotspot/share/classfile/modules.hpp | 4 ++-- src/hotspot/share/code/vtableStubs.hpp | 4 ++-- src/hotspot/share/compiler/compilerDefinitions.hpp | 4 ++-- src/hotspot/share/compiler/compilerEvent.hpp | 4 ++-- src/hotspot/share/compiler/compilerOracle.hpp | 4 ++-- src/hotspot/share/gc/g1/g1CollectionSetChooser.hpp | 4 ++-- src/hotspot/share/gc/g1/g1FromCardCache.hpp | 4 ++-- src/hotspot/share/gc/g1/g1HeapRegionEventSender.hpp | 4 ++-- src/hotspot/share/gc/g1/g1HeapRegionTraceType.hpp | 4 ++-- src/hotspot/share/gc/g1/heapRegionBounds.hpp | 5 +++-- src/hotspot/share/gc/g1/heapRegionTracer.hpp | 5 +++-- src/hotspot/share/gc/g1/heapRegionType.hpp | 3 ++- src/hotspot/share/gc/parallel/psRootType.hpp | 4 ++-- src/hotspot/share/gc/parallel/psScavenge.hpp | 4 ++-- src/hotspot/share/gc/shared/accessBarrierSupport.hpp | 4 ++-- src/hotspot/share/gc/shared/ageTableTracer.hpp | 5 +++-- src/hotspot/share/gc/shared/allocTracer.hpp | 4 ++-- src/hotspot/share/gc/shared/blockOffsetTable.hpp | 4 ++-- src/hotspot/share/gc/shared/concurrentGCBreakpoints.hpp | 4 ++-- src/hotspot/share/gc/shared/gcCause.hpp | 5 +++-- src/hotspot/share/gc/shared/gcConfig.hpp | 2 +- src/hotspot/share/gc/shared/gcLocker.hpp | 4 ++-- src/hotspot/share/gc/shared/gcLogPrecious.hpp | 2 +- src/hotspot/share/gc/shared/gcWhen.hpp | 4 ++-- src/hotspot/share/gc/shared/locationPrinter.hpp | 2 +- src/hotspot/share/gc/shared/objectCountEventSender.hpp | 4 ++-- src/hotspot/share/gc/shared/scavengableNMethods.hpp | 4 ++-- src/hotspot/share/gc/shared/spaceDecorator.hpp | 4 ++-- src/hotspot/share/gc/shared/weakProcessor.hpp | 4 ++-- src/hotspot/share/gc/shared/workerPolicy.hpp | 4 ++-- src/hotspot/share/gc/shenandoah/shenandoahBreakpoint.hpp | 6 +++--- src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.hpp | 4 ++-- src/hotspot/share/gc/shenandoah/shenandoahRuntime.hpp | 4 ++-- src/hotspot/share/gc/shenandoah/shenandoahWorkerPolicy.hpp | 4 ++-- src/hotspot/share/gc/z/zAbort.hpp | 4 ++-- src/hotspot/share/gc/z/zAddress.hpp | 5 +++-- src/hotspot/share/gc/z/zAddressSpaceLimit.hpp | 5 +++-- src/hotspot/share/gc/z/zBarrier.hpp | 4 ++-- src/hotspot/share/gc/z/zBarrierSetRuntime.hpp | 2 +- src/hotspot/share/gc/z/zBitField.hpp | 5 +++-- src/hotspot/share/gc/z/zBreakpoint.hpp | 4 ++-- src/hotspot/share/gc/z/zCPU.hpp | 4 ++-- src/hotspot/share/gc/z/zHash.hpp | 4 ++-- src/hotspot/share/gc/z/zHeuristics.hpp | 4 ++-- src/hotspot/share/gc/z/zLargePages.hpp | 4 ++-- src/hotspot/share/gc/z/zNMethod.hpp | 4 ++-- src/hotspot/share/gc/z/zNMethodTable.hpp | 4 ++-- src/hotspot/share/gc/z/zNUMA.hpp | 5 +++-- src/hotspot/share/gc/z/zOop.hpp | 4 ++-- src/hotspot/share/gc/z/zResurrection.hpp | 4 ++-- src/hotspot/share/gc/z/zThread.hpp | 4 ++-- src/hotspot/share/gc/z/zThreadLocalAllocBuffer.hpp | 4 ++-- src/hotspot/share/gc/z/zUtils.hpp | 5 +++-- src/hotspot/share/gc/z/zValue.hpp | 4 ++-- src/hotspot/share/gc/z/zVerify.hpp | 4 ++-- src/hotspot/share/interpreter/bytecodeHistogram.hpp | 4 ++-- src/hotspot/share/interpreter/bytecodeTracer.hpp | 4 ++-- src/hotspot/share/interpreter/bytecodeUtils.hpp | 6 +++--- src/hotspot/share/interpreter/bytecodes.hpp | 5 +++-- src/hotspot/share/interpreter/templateTable.hpp | 4 ++-- .../share/jfr/instrumentation/jfrEventClassTransformer.hpp | 4 ++-- src/hotspot/share/jfr/jfr.hpp | 6 ++++-- src/hotspot/share/jfr/leakprofiler/chains/edgeUtils.hpp | 4 ++-- .../jfr/leakprofiler/checkpoint/objectSampleCheckpoint.hpp | 4 ++-- .../share/jfr/leakprofiler/checkpoint/rootResolver.hpp | 4 ++-- src/hotspot/share/jfr/leakprofiler/leakProfiler.hpp | 5 +++-- .../share/jfr/leakprofiler/utilities/granularTimer.hpp | 4 ++-- src/hotspot/share/jfr/leakprofiler/utilities/rootType.hpp | 4 ++-- .../share/jfr/periodic/jfrFinalizerStatisticsEvent.hpp | 4 ++-- src/hotspot/share/jfr/periodic/jfrModuleEvent.hpp | 4 ++-- src/hotspot/share/jfr/periodic/jfrNetworkUtilization.hpp | 4 ++-- src/hotspot/share/jfr/periodic/jfrThreadCPULoadEvent.hpp | 4 ++-- src/hotspot/share/jfr/periodic/jfrThreadDumpEvent.hpp | 4 ++-- .../share/jfr/recorder/checkpoint/jfrMetadataEvent.hpp | 4 ++-- .../share/jfr/recorder/checkpoint/types/jfrThreadState.hpp | 4 ++-- .../jfr/recorder/checkpoint/types/traceid/jfrTraceId.hpp | 4 ++-- .../recorder/checkpoint/types/traceid/jfrTraceIdBits.hpp | 2 +- .../recorder/checkpoint/types/traceid/jfrTraceIdEpoch.hpp | 4 ++-- .../checkpoint/types/traceid/jfrTraceIdLoadBarrier.hpp | 4 ++-- .../share/jfr/recorder/repository/jfrChunkRotation.hpp | 4 ++-- .../share/jfr/recorder/repository/jfrEmergencyDump.hpp | 4 ++-- src/hotspot/share/jfr/recorder/service/jfrMemorySizer.hpp | 4 ++-- src/hotspot/share/jfr/recorder/service/jfrOptionSet.hpp | 4 ++-- .../share/jfr/recorder/service/jfrRecorderThread.hpp | 4 ++-- src/hotspot/share/jfr/support/jfrJdkJfrEvent.hpp | 4 ++-- src/hotspot/share/jfr/support/jfrKlassUnloading.hpp | 4 ++-- src/hotspot/share/jfr/support/jfrMethodLookup.hpp | 2 +- src/hotspot/share/jfr/support/jfrObjectAllocationSample.hpp | 4 ++-- src/hotspot/share/jfr/utilities/jfrBigEndian.hpp | 4 ++-- src/hotspot/share/jfr/utilities/jfrJavaLog.hpp | 4 ++-- src/hotspot/share/jfr/utilities/jfrPredicate.hpp | 4 ++-- src/hotspot/share/jfr/utilities/jfrTimeConverter.hpp | 4 ++-- src/hotspot/share/jfr/writers/jfrEncoding.hpp | 4 ++-- src/hotspot/share/jfr/writers/jfrJavaEventWriter.hpp | 4 ++-- src/hotspot/share/logging/logConfiguration.hpp | 5 +++-- src/hotspot/share/logging/logLevel.hpp | 5 +++-- src/hotspot/share/logging/logTag.hpp | 6 ++++-- src/hotspot/share/memory/metaspace/internalStats.hpp | 6 +++--- src/hotspot/share/memory/metaspace/metaspaceReporter.hpp | 6 +++--- src/hotspot/share/memory/metaspace/metaspaceSettings.hpp | 6 +++--- src/hotspot/share/memory/metaspace/runningCounters.hpp | 6 +++--- src/hotspot/share/memory/metaspaceCounters.hpp | 4 ++-- src/hotspot/share/memory/metaspaceCriticalAllocation.hpp | 2 +- src/hotspot/share/metaprogramming/conditional.hpp | 4 ++-- src/hotspot/share/metaprogramming/decay.hpp | 4 ++-- src/hotspot/share/metaprogramming/removeCV.hpp | 4 ++-- src/hotspot/share/metaprogramming/removeExtent.hpp | 4 ++-- src/hotspot/share/metaprogramming/removePointer.hpp | 4 ++-- src/hotspot/share/metaprogramming/removeReference.hpp | 4 ++-- src/hotspot/share/oops/access.hpp | 4 ++-- src/hotspot/share/oops/accessDecorators.hpp | 4 ++-- src/hotspot/share/oops/compressedOops.hpp | 4 ++-- src/hotspot/share/prims/jniFastGetField.hpp | 4 ++-- src/hotspot/share/prims/jvmtiEventController.hpp | 4 ++-- src/hotspot/share/prims/jvmtiExtensions.hpp | 4 ++-- src/hotspot/share/prims/jvmtiManageCapabilities.hpp | 4 ++-- src/hotspot/share/prims/nativeLookup.hpp | 4 ++-- src/hotspot/share/prims/resolvedMethodTable.hpp | 4 ++-- src/hotspot/share/prims/vectorSupport.hpp | 4 ++-- src/hotspot/share/runtime/abstract_vm_version.hpp | 4 ++-- src/hotspot/share/runtime/arguments.hpp | 4 ++-- src/hotspot/share/runtime/handshake.hpp | 4 ++-- src/hotspot/share/runtime/icache.hpp | 4 ++-- src/hotspot/share/runtime/jniHandles.hpp | 4 ++-- src/hotspot/share/runtime/orderAccess.hpp | 4 ++-- src/hotspot/share/runtime/prefetch.hpp | 4 ++-- src/hotspot/share/runtime/reflectionUtils.hpp | 4 ++-- src/hotspot/share/runtime/safepoint.hpp | 2 +- src/hotspot/share/runtime/sharedRuntime.hpp | 4 ++-- src/hotspot/share/runtime/stackWatermark.hpp | 4 ++-- src/hotspot/share/runtime/threadLocalStorage.hpp | 4 ++-- src/hotspot/share/services/attachListener.hpp | 4 ++-- src/hotspot/share/services/gcNotifier.hpp | 4 ++-- src/hotspot/share/services/lowMemoryDetector.hpp | 4 ++-- src/hotspot/share/services/nmtCommon.hpp | 4 ++-- src/hotspot/share/services/threadIdTable.hpp | 2 +- src/hotspot/share/utilities/decoder.hpp | 4 ++-- src/hotspot/share/utilities/globalCounter.hpp | 4 ++-- src/hotspot/share/utilities/quickSort.hpp | 4 ++-- src/hotspot/share/utilities/stringUtils.cpp | 4 +++- src/hotspot/share/utilities/stringUtils.hpp | 4 ++-- src/hotspot/share/utilities/utf8.cpp | 6 +++++- src/hotspot/share/utilities/utf8.hpp | 6 ++++-- test/hotspot/gtest/classfile/test_AltHashing.cpp | 3 ++- 172 files changed, 368 insertions(+), 333 deletions(-) diff --git a/src/hotspot/cpu/aarch64/bytes_aarch64.hpp b/src/hotspot/cpu/aarch64/bytes_aarch64.hpp index acb2e493a9a..672f03b93a9 100644 --- a/src/hotspot/cpu/aarch64/bytes_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/bytes_aarch64.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -26,7 +26,7 @@ #ifndef CPU_AARCH64_BYTES_AARCH64_HPP #define CPU_AARCH64_BYTES_AARCH64_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" class Bytes: AllStatic { public: diff --git a/src/hotspot/cpu/aarch64/jniTypes_aarch64.hpp b/src/hotspot/cpu/aarch64/jniTypes_aarch64.hpp index 4254cdf4cfd..8d20a6a1701 100644 --- a/src/hotspot/cpu/aarch64/jniTypes_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/jniTypes_aarch64.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -27,7 +27,7 @@ #define CPU_AARCH64_JNITYPES_AARCH64_HPP #include "jni.h" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "oops/oop.hpp" // This file holds platform-dependent routines used to write primitive jni diff --git a/src/hotspot/cpu/arm/bytes_arm.hpp b/src/hotspot/cpu/arm/bytes_arm.hpp index b0d481f314d..34af43edcac 100644 --- a/src/hotspot/cpu/arm/bytes_arm.hpp +++ b/src/hotspot/cpu/arm/bytes_arm.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2022, 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 @@ #ifndef CPU_ARM_BYTES_ARM_HPP #define CPU_ARM_BYTES_ARM_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "utilities/macros.hpp" #ifndef VM_LITTLE_ENDIAN diff --git a/src/hotspot/cpu/arm/jniTypes_arm.hpp b/src/hotspot/cpu/arm/jniTypes_arm.hpp index 66596eac1a0..660e58110f8 100644 --- a/src/hotspot/cpu/arm/jniTypes_arm.hpp +++ b/src/hotspot/cpu/arm/jniTypes_arm.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ #define CPU_ARM_JNITYPES_ARM_HPP #include "jni.h" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "oops/oop.hpp" // This file holds platform-dependent routines used to write primitive jni diff --git a/src/hotspot/cpu/ppc/bytes_ppc.hpp b/src/hotspot/cpu/ppc/bytes_ppc.hpp index 8249068ecd6..a4d061e9b73 100644 --- a/src/hotspot/cpu/ppc/bytes_ppc.hpp +++ b/src/hotspot/cpu/ppc/bytes_ppc.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2016 SAP SE. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ #ifndef CPU_PPC_BYTES_PPC_HPP #define CPU_PPC_BYTES_PPC_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" class Bytes: AllStatic { public: diff --git a/src/hotspot/cpu/ppc/jniTypes_ppc.hpp b/src/hotspot/cpu/ppc/jniTypes_ppc.hpp index ef1fe4acfdf..13ccaf408e9 100644 --- a/src/hotspot/cpu/ppc/jniTypes_ppc.hpp +++ b/src/hotspot/cpu/ppc/jniTypes_ppc.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2013 SAP SE. All rights reserved. + * Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ #define CPU_PPC_JNITYPES_PPC_HPP #include "jni.h" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "oops/oop.hpp" // This file holds platform-dependent routines used to write primitive diff --git a/src/hotspot/cpu/s390/bytes_s390.hpp b/src/hotspot/cpu/s390/bytes_s390.hpp index f6882f980ab..9b4d7b04221 100644 --- a/src/hotspot/cpu/s390/bytes_s390.hpp +++ b/src/hotspot/cpu/s390/bytes_s390.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016, 2018 SAP SE. All rights reserved. + * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ #ifndef CPU_S390_BYTES_S390_HPP #define CPU_S390_BYTES_S390_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" class Bytes: AllStatic { public: diff --git a/src/hotspot/cpu/s390/jniTypes_s390.hpp b/src/hotspot/cpu/s390/jniTypes_s390.hpp index 56f4a05c6d4..951e7f5f6d2 100644 --- a/src/hotspot/cpu/s390/jniTypes_s390.hpp +++ b/src/hotspot/cpu/s390/jniTypes_s390.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -30,7 +30,7 @@ // jni types to the array of arguments passed into JavaCalls::call. #include "jni.h" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "oops/oop.hpp" class JNITypes : AllStatic { diff --git a/src/hotspot/cpu/x86/bytes_x86.hpp b/src/hotspot/cpu/x86/bytes_x86.hpp index 4ce19a473b4..cb5987d2c82 100644 --- a/src/hotspot/cpu/x86/bytes_x86.hpp +++ b/src/hotspot/cpu/x86/bytes_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ #ifndef CPU_X86_BYTES_X86_HPP #define CPU_X86_BYTES_X86_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "utilities/align.hpp" #include "utilities/macros.hpp" diff --git a/src/hotspot/cpu/x86/c2_intelJccErratum_x86.hpp b/src/hotspot/cpu/x86/c2_intelJccErratum_x86.hpp index f3f66f3d7bc..415d8a99933 100644 --- a/src/hotspot/cpu/x86/c2_intelJccErratum_x86.hpp +++ b/src/hotspot/cpu/x86/c2_intelJccErratum_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, 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 @@ #ifndef CPU_X86_INTELJCCERRATUM_X86_HPP #define CPU_X86_INTELJCCERRATUM_X86_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "utilities/globalDefinitions.hpp" class Block; diff --git a/src/hotspot/cpu/x86/jniTypes_x86.hpp b/src/hotspot/cpu/x86/jniTypes_x86.hpp index 403a0b63e2b..5c925474796 100644 --- a/src/hotspot/cpu/x86/jniTypes_x86.hpp +++ b/src/hotspot/cpu/x86/jniTypes_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ #define CPU_X86_JNITYPES_X86_HPP #include "jni.h" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "oops/oop.hpp" // This file holds platform-dependent routines used to write primitive jni diff --git a/src/hotspot/cpu/x86/rdtsc_x86.hpp b/src/hotspot/cpu/x86/rdtsc_x86.hpp index f66997c9cfe..d9e77a0ae6b 100644 --- a/src/hotspot/cpu/x86/rdtsc_x86.hpp +++ b/src/hotspot/cpu/x86/rdtsc_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022, 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,8 @@ #ifndef CPU_X86_RDTSC_X86_HPP #define CPU_X86_RDTSC_X86_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" +#include "utilities/globalDefinitions.hpp" #include "utilities/macros.hpp" // Interface to the x86 rdtsc() time counter, if available. diff --git a/src/hotspot/cpu/zero/bytes_zero.hpp b/src/hotspot/cpu/zero/bytes_zero.hpp index 9acd9dd2430..93d49b8a28d 100644 --- a/src/hotspot/cpu/zero/bytes_zero.hpp +++ b/src/hotspot/cpu/zero/bytes_zero.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright 2007, 2008, 2009 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -26,7 +26,7 @@ #ifndef CPU_ZERO_BYTES_ZERO_HPP #define CPU_ZERO_BYTES_ZERO_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" typedef union unaligned { u4 u; diff --git a/src/hotspot/cpu/zero/jniTypes_zero.hpp b/src/hotspot/cpu/zero/jniTypes_zero.hpp index 8d5a6bee7fa..9f6fe78005b 100644 --- a/src/hotspot/cpu/zero/jniTypes_zero.hpp +++ b/src/hotspot/cpu/zero/jniTypes_zero.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ #define CPU_ZERO_JNITYPES_ZERO_HPP #include "jni.h" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "oops/oop.hpp" // This file holds platform-dependent routines used to write primitive jni diff --git a/src/hotspot/os/bsd/gc/z/zNUMA_bsd.cpp b/src/hotspot/os/bsd/gc/z/zNUMA_bsd.cpp index a0fe34c6504..e5b3895c44e 100644 --- a/src/hotspot/os/bsd/gc/z/zNUMA_bsd.cpp +++ b/src/hotspot/os/bsd/gc/z/zNUMA_bsd.cpp @@ -23,6 +23,7 @@ #include "precompiled.hpp" #include "gc/z/zNUMA.hpp" +#include "utilities/globalDefinitions.hpp" void ZNUMA::pd_initialize() { _enabled = false; diff --git a/src/hotspot/os/linux/gc/z/zSyscall_linux.hpp b/src/hotspot/os/linux/gc/z/zSyscall_linux.hpp index 95b13841b2a..1e1becf5a14 100644 --- a/src/hotspot/os/linux/gc/z/zSyscall_linux.hpp +++ b/src/hotspot/os/linux/gc/z/zSyscall_linux.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,8 @@ #ifndef OS_LINUX_GC_Z_ZSYSCALL_LINUX_HPP #define OS_LINUX_GC_Z_ZSYSCALL_LINUX_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" +#include "utilities/globalDefinitions.hpp" // Flags for get_mempolicy() #ifndef MPOL_F_NODE diff --git a/src/hotspot/os/linux/osContainer_linux.hpp b/src/hotspot/os/linux/osContainer_linux.hpp index 940bc0e3874..1ba4a9dabdc 100644 --- a/src/hotspot/os/linux/osContainer_linux.hpp +++ b/src/hotspot/os/linux/osContainer_linux.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ #include "utilities/globalDefinitions.hpp" #include "utilities/macros.hpp" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #define OSCONTAINER_ERROR (-2) diff --git a/src/hotspot/os/posix/signals_posix.hpp b/src/hotspot/os/posix/signals_posix.hpp index 373a02ff3a3..2efdb374c4e 100644 --- a/src/hotspot/os/posix/signals_posix.hpp +++ b/src/hotspot/os/posix/signals_posix.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, 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 @@ #ifndef OS_POSIX_SIGNALS_POSIX_HPP #define OS_POSIX_SIGNALS_POSIX_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "utilities/globalDefinitions.hpp" class outputStream; diff --git a/src/hotspot/os/posix/threadLocalStorage_posix.cpp b/src/hotspot/os/posix/threadLocalStorage_posix.cpp index cc703ef811f..25bbbe2244f 100644 --- a/src/hotspot/os/posix/threadLocalStorage_posix.cpp +++ b/src/hotspot/os/posix/threadLocalStorage_posix.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, 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,6 +23,7 @@ */ #include "runtime/threadLocalStorage.hpp" +#include "utilities/debug.hpp" #include static pthread_key_t _thread_key; diff --git a/src/hotspot/os/windows/gc/z/zMapper_windows.hpp b/src/hotspot/os/windows/gc/z/zMapper_windows.hpp index 4db80c89956..3e47b470f5f 100644 --- a/src/hotspot/os/windows/gc/z/zMapper_windows.hpp +++ b/src/hotspot/os/windows/gc/z/zMapper_windows.hpp @@ -24,7 +24,7 @@ #ifndef OS_WINDOWS_GC_Z_ZMAPPER_WINDOWS_HPP #define OS_WINDOWS_GC_Z_ZMAPPER_WINDOWS_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "utilities/globalDefinitions.hpp" #include diff --git a/src/hotspot/os/windows/iphlp_interface.hpp b/src/hotspot/os/windows/iphlp_interface.hpp index 0ebe971a5f1..3e7e0adef65 100644 --- a/src/hotspot/os/windows/iphlp_interface.hpp +++ b/src/hotspot/os/windows/iphlp_interface.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2022, 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 @@ #ifndef OS_WINDOWS_IPHLP_INTERFACE_HPP #define OS_WINDOWS_IPHLP_INTERFACE_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "utilities/macros.hpp" #include #include diff --git a/src/hotspot/os/windows/pdh_interface.hpp b/src/hotspot/os/windows/pdh_interface.hpp index 743c737d998..151f9edd0e9 100644 --- a/src/hotspot/os/windows/pdh_interface.hpp +++ b/src/hotspot/os/windows/pdh_interface.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022, 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 @@ #ifndef OS_WINDOWS_PDH_INTERFACE_HPP #define OS_WINDOWS_PDH_INTERFACE_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include #include diff --git a/src/hotspot/os/windows/threadLocalStorage_windows.cpp b/src/hotspot/os/windows/threadLocalStorage_windows.cpp index 5648a672d71..7d809518aab 100644 --- a/src/hotspot/os/windows/threadLocalStorage_windows.cpp +++ b/src/hotspot/os/windows/threadLocalStorage_windows.cpp @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "runtime/threadLocalStorage.hpp" +#include "utilities/debug.hpp" #include static DWORD _thread_key; diff --git a/src/hotspot/share/c1/c1_Runtime1.hpp b/src/hotspot/share/c1/c1_Runtime1.hpp index 9212a4fb249..3dcb27476a6 100644 --- a/src/hotspot/share/c1/c1_Runtime1.hpp +++ b/src/hotspot/share/c1/c1_Runtime1.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,7 @@ #include "c1/c1_FrameMap.hpp" #include "code/stubs.hpp" #include "interpreter/interpreter.hpp" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "runtime/deoptimization.hpp" class StubAssembler; diff --git a/src/hotspot/share/cds/archiveUtils.cpp b/src/hotspot/share/cds/archiveUtils.cpp index 8c273c06a8d..27c94290c23 100644 --- a/src/hotspot/share/cds/archiveUtils.cpp +++ b/src/hotspot/share/cds/archiveUtils.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,7 +39,9 @@ #include "oops/compressedOops.inline.hpp" #include "runtime/arguments.hpp" #include "utilities/bitMap.inline.hpp" +#include "utilities/debug.hpp" #include "utilities/formatBuffer.hpp" +#include "utilities/globalDefinitions.hpp" CHeapBitMap* ArchivePtrMarker::_ptrmap = NULL; VirtualSpace* ArchivePtrMarker::_vs; diff --git a/src/hotspot/share/cds/dynamicArchive.hpp b/src/hotspot/share/cds/dynamicArchive.hpp index fbb831ae195..ec8a505978b 100644 --- a/src/hotspot/share/cds/dynamicArchive.hpp +++ b/src/hotspot/share/cds/dynamicArchive.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ #include "cds/filemap.hpp" #include "classfile/compactHashtable.hpp" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "memory/memRegion.hpp" #include "memory/virtualspace.hpp" #include "oops/oop.hpp" diff --git a/src/hotspot/share/classfile/altHashing.hpp b/src/hotspot/share/classfile/altHashing.hpp index f2fc52410d1..555720c0666 100644 --- a/src/hotspot/share/classfile/altHashing.hpp +++ b/src/hotspot/share/classfile/altHashing.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,8 @@ #define SHARE_CLASSFILE_ALTHASHING_HPP #include "jni.h" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" +#include "utilities/globalDefinitions.hpp" /** * Implementation of alternate more secure hashing. diff --git a/src/hotspot/share/classfile/klassFactory.hpp b/src/hotspot/share/classfile/klassFactory.hpp index 2b2ee36dfa3..b1584b3e2ca 100644 --- a/src/hotspot/share/classfile/klassFactory.hpp +++ b/src/hotspot/share/classfile/klassFactory.hpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. +* Copyright (c) 2015, 2022, 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 @@ #ifndef SHARE_CLASSFILE_KLASSFACTORY_HPP #define SHARE_CLASSFILE_KLASSFACTORY_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "runtime/handles.hpp" class ClassFileStream; diff --git a/src/hotspot/share/classfile/modules.hpp b/src/hotspot/share/classfile/modules.hpp index 31cab8209fa..5c52a323b0c 100644 --- a/src/hotspot/share/classfile/modules.hpp +++ b/src/hotspot/share/classfile/modules.hpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. +* Copyright (c) 2016, 2022, 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 @@ #ifndef SHARE_CLASSFILE_MODULES_HPP #define SHARE_CLASSFILE_MODULES_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "runtime/handles.hpp" class ModuleEntryTable; diff --git a/src/hotspot/share/code/vtableStubs.hpp b/src/hotspot/share/code/vtableStubs.hpp index 8fc2bdae94c..9498ad7d329 100644 --- a/src/hotspot/share/code/vtableStubs.hpp +++ b/src/hotspot/share/code/vtableStubs.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ #include "asm/macroAssembler.hpp" #include "code/vmreg.hpp" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" // A VtableStub holds an individual code stub for a pair (vtable index, #args) for either itables or vtables // There's a one-to-one relationship between a VtableStub and such a pair. diff --git a/src/hotspot/share/compiler/compilerDefinitions.hpp b/src/hotspot/share/compiler/compilerDefinitions.hpp index 1c8096918a6..153dfaad364 100644 --- a/src/hotspot/share/compiler/compilerDefinitions.hpp +++ b/src/hotspot/share/compiler/compilerDefinitions.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ #include "compiler/compiler_globals.hpp" #include "jvmci/jvmci_globals.hpp" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "runtime/globals.hpp" // The (closed set) of concrete compiler classes. diff --git a/src/hotspot/share/compiler/compilerEvent.hpp b/src/hotspot/share/compiler/compilerEvent.hpp index 65fc296b66b..cf04ce9a436 100644 --- a/src/hotspot/share/compiler/compilerEvent.hpp +++ b/src/hotspot/share/compiler/compilerEvent.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ #include "jni.h" #include "compiler/compilerDefinitions.hpp" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "utilities/macros.hpp" #include "utilities/ticks.hpp" diff --git a/src/hotspot/share/compiler/compilerOracle.hpp b/src/hotspot/share/compiler/compilerOracle.hpp index e5be64cbdd4..f2fc0e8251d 100644 --- a/src/hotspot/share/compiler/compilerOracle.hpp +++ b/src/hotspot/share/compiler/compilerOracle.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2022, 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 @@ #ifndef SHARE_COMPILER_COMPILERORACLE_HPP #define SHARE_COMPILER_COMPILERORACLE_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "oops/oopsHierarchy.hpp" class methodHandle; diff --git a/src/hotspot/share/gc/g1/g1CollectionSetChooser.hpp b/src/hotspot/share/gc/g1/g1CollectionSetChooser.hpp index 5692a0c407e..e8894323d65 100644 --- a/src/hotspot/share/gc/g1/g1CollectionSetChooser.hpp +++ b/src/hotspot/share/gc/g1/g1CollectionSetChooser.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ #define SHARE_GC_G1_G1COLLECTIONSETCHOOSER_HPP #include "gc/g1/heapRegion.hpp" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "runtime/globals.hpp" class G1CollectionSetCandidates; diff --git a/src/hotspot/share/gc/g1/g1FromCardCache.hpp b/src/hotspot/share/gc/g1/g1FromCardCache.hpp index b76d7b1b863..0a01e0102ae 100644 --- a/src/hotspot/share/gc/g1/g1FromCardCache.hpp +++ b/src/hotspot/share/gc/g1/g1FromCardCache.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2022, 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 @@ #ifndef SHARE_GC_G1_G1FROMCARDCACHE_HPP #define SHARE_GC_G1_G1FROMCARDCACHE_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "utilities/ostream.hpp" // G1FromCardCache remembers the most recently processed card on the heap on diff --git a/src/hotspot/share/gc/g1/g1HeapRegionEventSender.hpp b/src/hotspot/share/gc/g1/g1HeapRegionEventSender.hpp index c8518a5172e..eb3d60656d4 100644 --- a/src/hotspot/share/gc/g1/g1HeapRegionEventSender.hpp +++ b/src/hotspot/share/gc/g1/g1HeapRegionEventSender.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, 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 @@ #ifndef SHARE_GC_G1_G1HEAPREGIONEVENTSENDER_HPP #define SHARE_GC_G1_G1HEAPREGIONEVENTSENDER_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" class G1HeapRegionEventSender : public AllStatic { public: diff --git a/src/hotspot/share/gc/g1/g1HeapRegionTraceType.hpp b/src/hotspot/share/gc/g1/g1HeapRegionTraceType.hpp index ab3ee03137c..1c5690e566d 100644 --- a/src/hotspot/share/gc/g1/g1HeapRegionTraceType.hpp +++ b/src/hotspot/share/gc/g1/g1HeapRegionTraceType.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, 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 @@ #ifndef SHARE_GC_G1_G1HEAPREGIONTRACETYPE_HPP #define SHARE_GC_G1_G1HEAPREGIONTRACETYPE_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "utilities/debug.hpp" class G1HeapRegionTraceType : AllStatic { diff --git a/src/hotspot/share/gc/g1/heapRegionBounds.hpp b/src/hotspot/share/gc/g1/heapRegionBounds.hpp index 5e748de5928..5a6db9fac3b 100644 --- a/src/hotspot/share/gc/g1/heapRegionBounds.hpp +++ b/src/hotspot/share/gc/g1/heapRegionBounds.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2022, 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,8 @@ #ifndef SHARE_GC_G1_HEAPREGIONBOUNDS_HPP #define SHARE_GC_G1_HEAPREGIONBOUNDS_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" +#include "utilities/globalDefinitions.hpp" class HeapRegionBounds : public AllStatic { private: diff --git a/src/hotspot/share/gc/g1/heapRegionTracer.hpp b/src/hotspot/share/gc/g1/heapRegionTracer.hpp index bdfcd1cfd8e..647744d0d5e 100644 --- a/src/hotspot/share/gc/g1/heapRegionTracer.hpp +++ b/src/hotspot/share/gc/g1/heapRegionTracer.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,8 @@ #define SHARE_GC_G1_HEAPREGIONTRACER_HPP #include "gc/g1/g1HeapRegionTraceType.hpp" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" +#include "utilities/globalDefinitions.hpp" class HeapRegionTracer : AllStatic { public: diff --git a/src/hotspot/share/gc/g1/heapRegionType.hpp b/src/hotspot/share/gc/g1/heapRegionType.hpp index 74807c37746..9e1c79ea0d0 100644 --- a/src/hotspot/share/gc/g1/heapRegionType.hpp +++ b/src/hotspot/share/gc/g1/heapRegionType.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ #define SHARE_GC_G1_HEAPREGIONTYPE_HPP #include "gc/g1/g1HeapRegionTraceType.hpp" +#include "utilities/globalDefinitions.hpp" #define hrt_assert_is_valid(tag) \ assert(is_valid((tag)), "invalid HR type: %u", (uint) (tag)) diff --git a/src/hotspot/share/gc/parallel/psRootType.hpp b/src/hotspot/share/gc/parallel/psRootType.hpp index 921bbfdd2b0..cbdc94dc9ab 100644 --- a/src/hotspot/share/gc/parallel/psRootType.hpp +++ b/src/hotspot/share/gc/parallel/psRootType.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, 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 @@ #ifndef SHARE_GC_PARALLEL_PSROOTTYPE_HPP #define SHARE_GC_PARALLEL_PSROOTTYPE_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "utilities/macros.hpp" class ParallelRootType : public AllStatic { diff --git a/src/hotspot/share/gc/parallel/psScavenge.hpp b/src/hotspot/share/gc/parallel/psScavenge.hpp index 80f41a99934..c575e8a3f2c 100644 --- a/src/hotspot/share/gc/parallel/psScavenge.hpp +++ b/src/hotspot/share/gc/parallel/psScavenge.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,7 @@ #include "gc/parallel/psVirtualspace.hpp" #include "gc/shared/collectorCounters.hpp" #include "gc/shared/gcTrace.hpp" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "oops/oop.hpp" #include "utilities/stack.hpp" diff --git a/src/hotspot/share/gc/shared/accessBarrierSupport.hpp b/src/hotspot/share/gc/shared/accessBarrierSupport.hpp index 58bc562d988..ca3b4589224 100644 --- a/src/hotspot/share/gc/shared/accessBarrierSupport.hpp +++ b/src/hotspot/share/gc/shared/accessBarrierSupport.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022, 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 @@ #ifndef SHARE_GC_SHARED_ACCESSBARRIERSUPPORT_HPP #define SHARE_GC_SHARED_ACCESSBARRIERSUPPORT_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "oops/access.hpp" class AccessBarrierSupport: AllStatic { diff --git a/src/hotspot/share/gc/shared/ageTableTracer.hpp b/src/hotspot/share/gc/shared/ageTableTracer.hpp index cca3f125bfd..02e1fe3338d 100644 --- a/src/hotspot/share/gc/shared/ageTableTracer.hpp +++ b/src/hotspot/share/gc/shared/ageTableTracer.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, 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,8 @@ #ifndef SHARE_GC_SHARED_AGETABLETRACER_HPP #define SHARE_GC_SHARED_AGETABLETRACER_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" +#include "utilities/globalDefinitions.hpp" class AgeTableTracer : AllStatic { public: diff --git a/src/hotspot/share/gc/shared/allocTracer.hpp b/src/hotspot/share/gc/shared/allocTracer.hpp index c30628b2889..273f20d70ea 100644 --- a/src/hotspot/share/gc/shared/allocTracer.hpp +++ b/src/hotspot/share/gc/shared/allocTracer.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2022, 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 @@ #ifndef SHARE_GC_SHARED_ALLOCTRACER_HPP #define SHARE_GC_SHARED_ALLOCTRACER_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "runtime/handles.hpp" class AllocTracer : AllStatic { diff --git a/src/hotspot/share/gc/shared/blockOffsetTable.hpp b/src/hotspot/share/gc/shared/blockOffsetTable.hpp index 7d6ddfdf799..9a32594c123 100644 --- a/src/hotspot/share/gc/shared/blockOffsetTable.hpp +++ b/src/hotspot/share/gc/shared/blockOffsetTable.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,7 @@ #include "gc/shared/gc_globals.hpp" #include "gc/shared/memset_with_concurrent_readers.hpp" #include "gc/shared/cardTable.hpp" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "memory/memRegion.hpp" #include "memory/virtualspace.hpp" #include "runtime/globals.hpp" diff --git a/src/hotspot/share/gc/shared/concurrentGCBreakpoints.hpp b/src/hotspot/share/gc/shared/concurrentGCBreakpoints.hpp index c11c0e116c5..7af1b5746c3 100644 --- a/src/hotspot/share/gc/shared/concurrentGCBreakpoints.hpp +++ b/src/hotspot/share/gc/shared/concurrentGCBreakpoints.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ #define SHARE_GC_SHARED_CONCURRENTGCBREAKPOINTS_HPP #include "gc/shared/gcCause.hpp" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "utilities/globalDefinitions.hpp" class Monitor; diff --git a/src/hotspot/share/gc/shared/gcCause.hpp b/src/hotspot/share/gc/shared/gcCause.hpp index 75f7dc73a8c..a3746fa8745 100644 --- a/src/hotspot/share/gc/shared/gcCause.hpp +++ b/src/hotspot/share/gc/shared/gcCause.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2022, 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,8 @@ #ifndef SHARE_GC_SHARED_GCCAUSE_HPP #define SHARE_GC_SHARED_GCCAUSE_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" +#include "utilities/debug.hpp" // // This class exposes implementation details of the various diff --git a/src/hotspot/share/gc/shared/gcConfig.hpp b/src/hotspot/share/gc/shared/gcConfig.hpp index 2dfbf186b7f..9b0da3ad528 100644 --- a/src/hotspot/share/gc/shared/gcConfig.hpp +++ b/src/hotspot/share/gc/shared/gcConfig.hpp @@ -26,7 +26,7 @@ #define SHARE_GC_SHARED_GCCONFIG_HPP #include "gc/shared/collectedHeap.hpp" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" class GCArguments; diff --git a/src/hotspot/share/gc/shared/gcLocker.hpp b/src/hotspot/share/gc/shared/gcLocker.hpp index 91ed84c41a9..e567d0c1f16 100644 --- a/src/hotspot/share/gc/shared/gcLocker.hpp +++ b/src/hotspot/share/gc/shared/gcLocker.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ #define SHARE_GC_SHARED_GCLOCKER_HPP #include "gc/shared/gcCause.hpp" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/macros.hpp" diff --git a/src/hotspot/share/gc/shared/gcLogPrecious.hpp b/src/hotspot/share/gc/shared/gcLogPrecious.hpp index 5f1158caca7..ec8b1c670f3 100644 --- a/src/hotspot/share/gc/shared/gcLogPrecious.hpp +++ b/src/hotspot/share/gc/shared/gcLogPrecious.hpp @@ -26,7 +26,7 @@ #include "utilities/globalDefinitions.hpp" #include "logging/logHandle.hpp" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "utilities/debug.hpp" class Mutex; diff --git a/src/hotspot/share/gc/shared/gcWhen.hpp b/src/hotspot/share/gc/shared/gcWhen.hpp index ff489226f65..23e2ef6b229 100644 --- a/src/hotspot/share/gc/shared/gcWhen.hpp +++ b/src/hotspot/share/gc/shared/gcWhen.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022, 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 @@ #ifndef SHARE_GC_SHARED_GCWHEN_HPP #define SHARE_GC_SHARED_GCWHEN_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "utilities/debug.hpp" class GCWhen : AllStatic { diff --git a/src/hotspot/share/gc/shared/locationPrinter.hpp b/src/hotspot/share/gc/shared/locationPrinter.hpp index 2c99e452845..2d5d997376d 100644 --- a/src/hotspot/share/gc/shared/locationPrinter.hpp +++ b/src/hotspot/share/gc/shared/locationPrinter.hpp @@ -25,7 +25,7 @@ #ifndef SHARE_GC_SHARED_LOCATIONPRINTER_HPP #define SHARE_GC_SHARED_LOCATIONPRINTER_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "oops/oopsHierarchy.hpp" #include "utilities/globalDefinitions.hpp" diff --git a/src/hotspot/share/gc/shared/objectCountEventSender.hpp b/src/hotspot/share/gc/shared/objectCountEventSender.hpp index 58e6da016da..115fbfdaf7d 100644 --- a/src/hotspot/share/gc/shared/objectCountEventSender.hpp +++ b/src/hotspot/share/gc/shared/objectCountEventSender.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ #define SHARE_GC_SHARED_OBJECTCOUNTEVENTSENDER_HPP #include "gc/shared/gcTrace.hpp" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/macros.hpp" #include "utilities/ticks.hpp" diff --git a/src/hotspot/share/gc/shared/scavengableNMethods.hpp b/src/hotspot/share/gc/shared/scavengableNMethods.hpp index 276ea9843c0..4852e6d32fb 100644 --- a/src/hotspot/share/gc/shared/scavengableNMethods.hpp +++ b/src/hotspot/share/gc/shared/scavengableNMethods.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, 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 @@ #ifndef SHARE_GC_SHARED_SCAVENGABLENMETHODS_HPP #define SHARE_GC_SHARED_SCAVENGABLENMETHODS_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "utilities/macros.hpp" class BoolObjectClosure; diff --git a/src/hotspot/share/gc/shared/spaceDecorator.hpp b/src/hotspot/share/gc/shared/spaceDecorator.hpp index d421a2a40f5..778881f75a1 100644 --- a/src/hotspot/share/gc/shared/spaceDecorator.hpp +++ b/src/hotspot/share/gc/shared/spaceDecorator.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2022, 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 @@ #ifndef SHARE_GC_SHARED_SPACEDECORATOR_HPP #define SHARE_GC_SHARED_SPACEDECORATOR_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "memory/memRegion.hpp" #include "utilities/globalDefinitions.hpp" diff --git a/src/hotspot/share/gc/shared/weakProcessor.hpp b/src/hotspot/share/gc/shared/weakProcessor.hpp index 5eb2c59f3f2..b86129c9b93 100644 --- a/src/hotspot/share/gc/shared/weakProcessor.hpp +++ b/src/hotspot/share/gc/shared/weakProcessor.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,7 @@ #include "gc/shared/oopStorageParState.hpp" #include "gc/shared/oopStorageSetParState.hpp" #include "gc/shared/workerThread.hpp" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" class WeakProcessorTimes; class WorkerThreads; diff --git a/src/hotspot/share/gc/shared/workerPolicy.hpp b/src/hotspot/share/gc/shared/workerPolicy.hpp index 377c9135d29..769b0e0ed8b 100644 --- a/src/hotspot/share/gc/shared/workerPolicy.hpp +++ b/src/hotspot/share/gc/shared/workerPolicy.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2022, 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 @@ #ifndef SHARE_GC_SHARED_WORKERPOLICY_HPP #define SHARE_GC_SHARED_WORKERPOLICY_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "utilities/globalDefinitions.hpp" class WorkerPolicy : public AllStatic { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahBreakpoint.hpp b/src/hotspot/share/gc/shenandoah/shenandoahBreakpoint.hpp index f8b7489a3bb..acc497618c9 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahBreakpoint.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahBreakpoint.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2021, Red Hat, Inc. All rights reserved. - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022, Red Hat, Inc. All rights reserved. + * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ #ifndef SHARE_GC_SHENANDOAH_SHENANDOAHBREAKPOINT_HPP #define SHARE_GC_SHENANDOAH_SHENANDOAHBREAKPOINT_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" class ShenandoahBreakpoint : public AllStatic { private: diff --git a/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.hpp b/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.hpp index 17bc5b78934..377d7688333 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Red Hat, Inc. All rights reserved. + * Copyright (c) 2017, 2022, Red Hat, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,7 @@ #include "gc/shenandoah/shenandoahSharedVariables.hpp" #include "gc/shenandoah/shenandoahLock.hpp" #include "gc/shenandoah/shenandoahPadding.hpp" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "memory/iterator.hpp" #include "utilities/globalDefinitions.hpp" diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRuntime.hpp b/src/hotspot/share/gc/shenandoah/shenandoahRuntime.hpp index 788fe3fbeca..e187e4360b1 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahRuntime.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahRuntime.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2019, Red Hat, Inc. All rights reserved. + * Copyright (c) 2018, 2022, Red Hat, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ #ifndef SHARE_GC_SHENANDOAH_SHENANDOAHRUNTIME_HPP #define SHARE_GC_SHENANDOAH_SHENANDOAHRUNTIME_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "oops/oopsHierarchy.hpp" class JavaThread; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahWorkerPolicy.hpp b/src/hotspot/share/gc/shenandoah/shenandoahWorkerPolicy.hpp index 10a6fec6535..3f47822f220 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahWorkerPolicy.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahWorkerPolicy.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Red Hat, Inc. All rights reserved. + * Copyright (c) 2017, 2022, Red Hat, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ #ifndef SHARE_GC_SHENANDOAH_SHENANDOAHWORKERPOLICY_HPP #define SHARE_GC_SHENANDOAH_SHENANDOAHWORKERPOLICY_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" class ShenandoahWorkerPolicy : AllStatic { private: diff --git a/src/hotspot/share/gc/z/zAbort.hpp b/src/hotspot/share/gc/z/zAbort.hpp index 1a5bcc15f19..f87bca8c0a3 100644 --- a/src/hotspot/share/gc/z/zAbort.hpp +++ b/src/hotspot/share/gc/z/zAbort.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ #ifndef SHARE_GC_Z_ZABORT_HPP #define SHARE_GC_Z_ZABORT_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" class ZAbort : public AllStatic { private: diff --git a/src/hotspot/share/gc/z/zAddress.hpp b/src/hotspot/share/gc/z/zAddress.hpp index eddd104189e..2908c37bbe6 100644 --- a/src/hotspot/share/gc/z/zAddress.hpp +++ b/src/hotspot/share/gc/z/zAddress.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,8 @@ #ifndef SHARE_GC_Z_ZADDRESS_HPP #define SHARE_GC_Z_ZADDRESS_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" +#include "utilities/globalDefinitions.hpp" class ZAddress : public AllStatic { friend class ZAddressTest; diff --git a/src/hotspot/share/gc/z/zAddressSpaceLimit.hpp b/src/hotspot/share/gc/z/zAddressSpaceLimit.hpp index b6a03776f5c..ec0faf2c087 100644 --- a/src/hotspot/share/gc/z/zAddressSpaceLimit.hpp +++ b/src/hotspot/share/gc/z/zAddressSpaceLimit.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,8 @@ #ifndef SHARE_GC_Z_ZADDRESSSPACELIMIT_HPP #define SHARE_GC_Z_ZADDRESSSPACELIMIT_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" +#include "utilities/globalDefinitions.hpp" class ZAddressSpaceLimit : public AllStatic { public: diff --git a/src/hotspot/share/gc/z/zBarrier.hpp b/src/hotspot/share/gc/z/zBarrier.hpp index d57bef74f91..2dfc1591888 100644 --- a/src/hotspot/share/gc/z/zBarrier.hpp +++ b/src/hotspot/share/gc/z/zBarrier.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ #ifndef SHARE_GC_Z_ZBARRIER_HPP #define SHARE_GC_Z_ZBARRIER_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "memory/iterator.hpp" #include "oops/oop.hpp" diff --git a/src/hotspot/share/gc/z/zBarrierSetRuntime.hpp b/src/hotspot/share/gc/z/zBarrierSetRuntime.hpp index f3d4fb9c6bd..b3a143de3e9 100644 --- a/src/hotspot/share/gc/z/zBarrierSetRuntime.hpp +++ b/src/hotspot/share/gc/z/zBarrierSetRuntime.hpp @@ -24,7 +24,7 @@ #ifndef SHARE_GC_Z_ZBARRIERSETRUNTIME_HPP #define SHARE_GC_Z_ZBARRIERSETRUNTIME_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "oops/accessDecorators.hpp" #include "utilities/globalDefinitions.hpp" diff --git a/src/hotspot/share/gc/z/zBitField.hpp b/src/hotspot/share/gc/z/zBitField.hpp index 4d7171c41ac..9bec4e05594 100644 --- a/src/hotspot/share/gc/z/zBitField.hpp +++ b/src/hotspot/share/gc/z/zBitField.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,8 +24,9 @@ #ifndef SHARE_GC_Z_ZBITFIELD_HPP #define SHARE_GC_Z_ZBITFIELD_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "utilities/debug.hpp" +#include "utilities/globalDefinitions.hpp" // // Example diff --git a/src/hotspot/share/gc/z/zBreakpoint.hpp b/src/hotspot/share/gc/z/zBreakpoint.hpp index 14ba227e189..920169fb6a6 100644 --- a/src/hotspot/share/gc/z/zBreakpoint.hpp +++ b/src/hotspot/share/gc/z/zBreakpoint.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ #ifndef SHARE_GC_Z_ZBREAKPOINT_HPP #define SHARE_GC_Z_ZBREAKPOINT_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" class ZBreakpoint : public AllStatic { private: diff --git a/src/hotspot/share/gc/z/zCPU.hpp b/src/hotspot/share/gc/z/zCPU.hpp index 65e04cc75e3..0acc949e508 100644 --- a/src/hotspot/share/gc/z/zCPU.hpp +++ b/src/hotspot/share/gc/z/zCPU.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ #ifndef SHARE_GC_Z_ZCPU_HPP #define SHARE_GC_Z_ZCPU_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "memory/padded.hpp" #include "utilities/globalDefinitions.hpp" diff --git a/src/hotspot/share/gc/z/zHash.hpp b/src/hotspot/share/gc/z/zHash.hpp index 5752d2abee3..e6469698488 100644 --- a/src/hotspot/share/gc/z/zHash.hpp +++ b/src/hotspot/share/gc/z/zHash.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ #ifndef SHARE_GC_Z_ZHASH_HPP #define SHARE_GC_Z_ZHASH_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "utilities/globalDefinitions.hpp" class ZHash : public AllStatic { diff --git a/src/hotspot/share/gc/z/zHeuristics.hpp b/src/hotspot/share/gc/z/zHeuristics.hpp index 5b810a84851..362fd775f0f 100644 --- a/src/hotspot/share/gc/z/zHeuristics.hpp +++ b/src/hotspot/share/gc/z/zHeuristics.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ #ifndef SHARE_GC_Z_ZHEURISTICS_HPP #define SHARE_GC_Z_ZHEURISTICS_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" class ZHeuristics : public AllStatic { public: diff --git a/src/hotspot/share/gc/z/zLargePages.hpp b/src/hotspot/share/gc/z/zLargePages.hpp index 1201b496266..9f7c8310e50 100644 --- a/src/hotspot/share/gc/z/zLargePages.hpp +++ b/src/hotspot/share/gc/z/zLargePages.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ #ifndef SHARE_GC_Z_ZLARGEPAGES_HPP #define SHARE_GC_Z_ZLARGEPAGES_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" class ZLargePages : public AllStatic { private: diff --git a/src/hotspot/share/gc/z/zNMethod.hpp b/src/hotspot/share/gc/z/zNMethod.hpp index 40ac93adb8e..117c5e34f4e 100644 --- a/src/hotspot/share/gc/z/zNMethod.hpp +++ b/src/hotspot/share/gc/z/zNMethod.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ #ifndef SHARE_GC_Z_ZNMETHOD_HPP #define SHARE_GC_Z_ZNMETHOD_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" class nmethod; class NMethodClosure; diff --git a/src/hotspot/share/gc/z/zNMethodTable.hpp b/src/hotspot/share/gc/z/zNMethodTable.hpp index 26ae2d27933..a1af8512f69 100644 --- a/src/hotspot/share/gc/z/zNMethodTable.hpp +++ b/src/hotspot/share/gc/z/zNMethodTable.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ #include "gc/z/zNMethodTableIteration.hpp" #include "gc/z/zSafeDelete.hpp" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" class nmethod; class NMethodClosure; diff --git a/src/hotspot/share/gc/z/zNUMA.hpp b/src/hotspot/share/gc/z/zNUMA.hpp index 0dc4390e8b4..fb29e1faaa7 100644 --- a/src/hotspot/share/gc/z/zNUMA.hpp +++ b/src/hotspot/share/gc/z/zNUMA.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,8 @@ #ifndef SHARE_GC_Z_ZNUMA_HPP #define SHARE_GC_Z_ZNUMA_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" +#include "utilities/globalDefinitions.hpp" class ZNUMA : public AllStatic { private: diff --git a/src/hotspot/share/gc/z/zOop.hpp b/src/hotspot/share/gc/z/zOop.hpp index cf752ba61c3..4fb0e6499e1 100644 --- a/src/hotspot/share/gc/z/zOop.hpp +++ b/src/hotspot/share/gc/z/zOop.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ #ifndef SHARE_GC_Z_ZOOP_HPP #define SHARE_GC_Z_ZOOP_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "oops/oopsHierarchy.hpp" class ZOop : public AllStatic { diff --git a/src/hotspot/share/gc/z/zResurrection.hpp b/src/hotspot/share/gc/z/zResurrection.hpp index a88b9354469..3d6a8f95a1c 100644 --- a/src/hotspot/share/gc/z/zResurrection.hpp +++ b/src/hotspot/share/gc/z/zResurrection.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ #ifndef SHARE_GC_Z_ZRESURRECTION_HPP #define SHARE_GC_Z_ZRESURRECTION_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" class ZResurrection : public AllStatic { private: diff --git a/src/hotspot/share/gc/z/zThread.hpp b/src/hotspot/share/gc/z/zThread.hpp index f98b7a05fb6..c67807ff96e 100644 --- a/src/hotspot/share/gc/z/zThread.hpp +++ b/src/hotspot/share/gc/z/zThread.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ #ifndef SHARE_GC_Z_ZTHREAD_HPP #define SHARE_GC_Z_ZTHREAD_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "utilities/globalDefinitions.hpp" class ZThread : public AllStatic { diff --git a/src/hotspot/share/gc/z/zThreadLocalAllocBuffer.hpp b/src/hotspot/share/gc/z/zThreadLocalAllocBuffer.hpp index d6693fceb00..086c8a5c351 100644 --- a/src/hotspot/share/gc/z/zThreadLocalAllocBuffer.hpp +++ b/src/hotspot/share/gc/z/zThreadLocalAllocBuffer.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ #include "gc/shared/threadLocalAllocBuffer.hpp" #include "gc/z/zValue.hpp" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" class JavaThread; diff --git a/src/hotspot/share/gc/z/zUtils.hpp b/src/hotspot/share/gc/z/zUtils.hpp index f4abea9c6fe..470329daf0d 100644 --- a/src/hotspot/share/gc/z/zUtils.hpp +++ b/src/hotspot/share/gc/z/zUtils.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,8 @@ #ifndef SHARE_GC_Z_ZUTILS_HPP #define SHARE_GC_Z_ZUTILS_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" +#include "utilities/globalDefinitions.hpp" class ZUtils : public AllStatic { public: diff --git a/src/hotspot/share/gc/z/zValue.hpp b/src/hotspot/share/gc/z/zValue.hpp index 281a2e48b8c..e2c67e8c48d 100644 --- a/src/hotspot/share/gc/z/zValue.hpp +++ b/src/hotspot/share/gc/z/zValue.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ #ifndef SHARE_GC_Z_ZVALUE_HPP #define SHARE_GC_Z_ZVALUE_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "utilities/globalDefinitions.hpp" // diff --git a/src/hotspot/share/gc/z/zVerify.hpp b/src/hotspot/share/gc/z/zVerify.hpp index db2d56d0095..8d7abd4a8d5 100644 --- a/src/hotspot/share/gc/z/zVerify.hpp +++ b/src/hotspot/share/gc/z/zVerify.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ #ifndef SHARE_GC_Z_ZVERIFY_HPP #define SHARE_GC_Z_ZVERIFY_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" class frame; class ZPageAllocator; diff --git a/src/hotspot/share/interpreter/bytecodeHistogram.hpp b/src/hotspot/share/interpreter/bytecodeHistogram.hpp index b919227702f..44ddca074d0 100644 --- a/src/hotspot/share/interpreter/bytecodeHistogram.hpp +++ b/src/hotspot/share/interpreter/bytecodeHistogram.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ #define SHARE_INTERPRETER_BYTECODEHISTOGRAM_HPP #include "interpreter/bytecodes.hpp" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" // BytecodeCounter counts the number of bytecodes executed diff --git a/src/hotspot/share/interpreter/bytecodeTracer.hpp b/src/hotspot/share/interpreter/bytecodeTracer.hpp index 52e91a0e712..38c2b092ce3 100644 --- a/src/hotspot/share/interpreter/bytecodeTracer.hpp +++ b/src/hotspot/share/interpreter/bytecodeTracer.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ #ifndef SHARE_INTERPRETER_BYTECODETRACER_HPP #define SHARE_INTERPRETER_BYTECODETRACER_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "utilities/ostream.hpp" // The BytecodeTracer is a helper class used by the interpreter for run-time diff --git a/src/hotspot/share/interpreter/bytecodeUtils.hpp b/src/hotspot/share/interpreter/bytecodeUtils.hpp index ede99a995b7..ff23b9c000f 100644 --- a/src/hotspot/share/interpreter/bytecodeUtils.hpp +++ b/src/hotspot/share/interpreter/bytecodeUtils.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2019 SAP SE. All rights reserved. + * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ #ifndef SHARE_INTERPRETER_BYTECODEUTILS_HPP #define SHARE_INTERPRETER_BYTECODEUTILS_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "utilities/globalDefinitions.hpp" class Method; diff --git a/src/hotspot/share/interpreter/bytecodes.hpp b/src/hotspot/share/interpreter/bytecodes.hpp index 9a34a227c04..7c70518d2b1 100644 --- a/src/hotspot/share/interpreter/bytecodes.hpp +++ b/src/hotspot/share/interpreter/bytecodes.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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,8 @@ #ifndef SHARE_INTERPRETER_BYTECODES_HPP #define SHARE_INTERPRETER_BYTECODES_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" +#include "utilities/globalDefinitions.hpp" // Bytecodes specifies all bytecodes used in the VM and // provides utility functions to get bytecode attributes. diff --git a/src/hotspot/share/interpreter/templateTable.hpp b/src/hotspot/share/interpreter/templateTable.hpp index ff5d2c33880..e7575eeb40a 100644 --- a/src/hotspot/share/interpreter/templateTable.hpp +++ b/src/hotspot/share/interpreter/templateTable.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ #define SHARE_INTERPRETER_TEMPLATETABLE_HPP #include "interpreter/bytecodes.hpp" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "runtime/frame.hpp" #include "utilities/macros.hpp" diff --git a/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.hpp b/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.hpp index d34a4e57a78..939c02bfdf4 100644 --- a/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.hpp +++ b/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, 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 @@ #ifndef SHARE_JFR_INSTRUMENTATION_JFREVENTCLASSTRANSFORMER_HPP #define SHARE_JFR_INSTRUMENTATION_JFREVENTCLASSTRANSFORMER_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "utilities/exceptions.hpp" class ClassFileParser; diff --git a/src/hotspot/share/jfr/jfr.hpp b/src/hotspot/share/jfr/jfr.hpp index c97cc807c3b..b4b1ae78adc 100644 --- a/src/hotspot/share/jfr/jfr.hpp +++ b/src/hotspot/share/jfr/jfr.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,11 +26,13 @@ #define SHARE_JFR_JFR_HPP #include "jni.h" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" +#include "utilities/globalDefinitions.hpp" class JavaThread; class Thread; class Klass; +class outputStream; extern "C" void JNICALL jfr_register_natives(JNIEnv*, jclass); diff --git a/src/hotspot/share/jfr/leakprofiler/chains/edgeUtils.hpp b/src/hotspot/share/jfr/leakprofiler/chains/edgeUtils.hpp index c9a169e6edb..0f107e7c32e 100644 --- a/src/hotspot/share/jfr/leakprofiler/chains/edgeUtils.hpp +++ b/src/hotspot/share/jfr/leakprofiler/chains/edgeUtils.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2022, 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 @@ #ifndef SHARE_JFR_LEAKPROFILER_CHAINS_EDGEUTILS_HPP #define SHARE_JFR_LEAKPROFILER_CHAINS_EDGEUTILS_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" class Edge; class Symbol; diff --git a/src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleCheckpoint.hpp b/src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleCheckpoint.hpp index 0ed82fd55c8..f9f928699e2 100644 --- a/src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleCheckpoint.hpp +++ b/src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleCheckpoint.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2022, 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 @@ #ifndef SHARE_JFR_LEAKPROFILER_CHECKPOINT_OBJECTSAMPLECHECKPOINT_HPP #define SHARE_JFR_LEAKPROFILER_CHECKPOINT_OBJECTSAMPLECHECKPOINT_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "jfr/utilities/jfrTypes.hpp" class EdgeStore; diff --git a/src/hotspot/share/jfr/leakprofiler/checkpoint/rootResolver.hpp b/src/hotspot/share/jfr/leakprofiler/checkpoint/rootResolver.hpp index 63dca4afc72..279cb5032ff 100644 --- a/src/hotspot/share/jfr/leakprofiler/checkpoint/rootResolver.hpp +++ b/src/hotspot/share/jfr/leakprofiler/checkpoint/rootResolver.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ #include "jfr/leakprofiler/utilities/rootType.hpp" #include "jfr/leakprofiler/utilities/unifiedOopRef.hpp" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "oops/oopsHierarchy.hpp" struct RootCallbackInfo { diff --git a/src/hotspot/share/jfr/leakprofiler/leakProfiler.hpp b/src/hotspot/share/jfr/leakprofiler/leakProfiler.hpp index c541ff1086d..6290a10ff74 100644 --- a/src/hotspot/share/jfr/leakprofiler/leakProfiler.hpp +++ b/src/hotspot/share/jfr/leakprofiler/leakProfiler.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2022, 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,8 @@ #ifndef SHARE_JFR_LEAKPROFILER_LEAKPROFILER_HPP #define SHARE_JFR_LEAKPROFILER_LEAKPROFILER_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" +#include "utilities/globalDefinitions.hpp" class JavaThread; diff --git a/src/hotspot/share/jfr/leakprofiler/utilities/granularTimer.hpp b/src/hotspot/share/jfr/leakprofiler/utilities/granularTimer.hpp index 231c1b26df4..e42a815c10d 100644 --- a/src/hotspot/share/jfr/leakprofiler/utilities/granularTimer.hpp +++ b/src/hotspot/share/jfr/leakprofiler/utilities/granularTimer.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ #define SHARE_JFR_LEAKPROFILER_UTILITIES_GRANULARTIMER_HPP #include "jfr/utilities/jfrTime.hpp" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" class GranularTimer : public AllStatic { private: diff --git a/src/hotspot/share/jfr/leakprofiler/utilities/rootType.hpp b/src/hotspot/share/jfr/leakprofiler/utilities/rootType.hpp index ffc47c7b833..ce975e9b802 100644 --- a/src/hotspot/share/jfr/leakprofiler/utilities/rootType.hpp +++ b/src/hotspot/share/jfr/leakprofiler/utilities/rootType.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ #define SHARE_JFR_LEAKPROFILER_UTILITIES_ROOTTYPE_HPP #include "gc/shared/oopStorageSet.hpp" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "utilities/enumIterator.hpp" class OldObjectRoot : public AllStatic { diff --git a/src/hotspot/share/jfr/periodic/jfrFinalizerStatisticsEvent.hpp b/src/hotspot/share/jfr/periodic/jfrFinalizerStatisticsEvent.hpp index fe739495718..756b5318298 100644 --- a/src/hotspot/share/jfr/periodic/jfrFinalizerStatisticsEvent.hpp +++ b/src/hotspot/share/jfr/periodic/jfrFinalizerStatisticsEvent.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022, 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 @@ #ifndef SHARE_JFR_PERIODIC_JFRFINALIZERSTATISTICSEVENT_HPP #define SHARE_JFR_PERIODIC_JFRFINALIZERSTATISTICSEVENT_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" class InstanceKlass; diff --git a/src/hotspot/share/jfr/periodic/jfrModuleEvent.hpp b/src/hotspot/share/jfr/periodic/jfrModuleEvent.hpp index aec662be231..a417ab1bb48 100644 --- a/src/hotspot/share/jfr/periodic/jfrModuleEvent.hpp +++ b/src/hotspot/share/jfr/periodic/jfrModuleEvent.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, 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 @@ #ifndef SHARE_JFR_PERIODIC_JFRMODULEEVENT_HPP #define SHARE_JFR_PERIODIC_JFRMODULEEVENT_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" class JfrModuleEvent : AllStatic { public: diff --git a/src/hotspot/share/jfr/periodic/jfrNetworkUtilization.hpp b/src/hotspot/share/jfr/periodic/jfrNetworkUtilization.hpp index b7a78498a9f..0ec3de18dee 100644 --- a/src/hotspot/share/jfr/periodic/jfrNetworkUtilization.hpp +++ b/src/hotspot/share/jfr/periodic/jfrNetworkUtilization.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2022, 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 @@ #ifndef SHARE_JFR_PERIODIC_JFRNETWORKUTILIZATION_HPP #define SHARE_JFR_PERIODIC_JFRNETWORKUTILIZATION_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" class NetworkInterface; diff --git a/src/hotspot/share/jfr/periodic/jfrThreadCPULoadEvent.hpp b/src/hotspot/share/jfr/periodic/jfrThreadCPULoadEvent.hpp index 84d3099e825..d5bed0fd821 100644 --- a/src/hotspot/share/jfr/periodic/jfrThreadCPULoadEvent.hpp +++ b/src/hotspot/share/jfr/periodic/jfrThreadCPULoadEvent.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ #define SHARE_JFR_PERIODIC_JFRTHREADCPULOADEVENT_HPP #include "jni.h" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" class JavaThread; class EventThreadCPULoad; diff --git a/src/hotspot/share/jfr/periodic/jfrThreadDumpEvent.hpp b/src/hotspot/share/jfr/periodic/jfrThreadDumpEvent.hpp index 23af6a3060b..c00925903b1 100644 --- a/src/hotspot/share/jfr/periodic/jfrThreadDumpEvent.hpp +++ b/src/hotspot/share/jfr/periodic/jfrThreadDumpEvent.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, 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 @@ #ifndef SHARE_JFR_PERIODIC_JFRTHREADDUMPEVENT_HPP #define SHARE_JFR_PERIODIC_JFRTHREADDUMPEVENT_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" /* * Helper for generating jfr events using output data from Dcmd's. diff --git a/src/hotspot/share/jfr/recorder/checkpoint/jfrMetadataEvent.hpp b/src/hotspot/share/jfr/recorder/checkpoint/jfrMetadataEvent.hpp index 0111d3becbe..abadbfb0b13 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/jfrMetadataEvent.hpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/jfrMetadataEvent.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ #define SHARE_JFR_RECORDER_CHECKPOINT_JFRMETADATAEVENT_HPP #include "jni.h" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" class JfrChunkWriter; diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrThreadState.hpp b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrThreadState.hpp index 9421273dca7..4fd519b5064 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrThreadState.hpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrThreadState.hpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. +* Copyright (c) 2016, 2022, 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 @@ #ifndef SHARE_JFR_RECORDER_CHECKPOINT_TYPES_JFRTHREADSTATE_HPP #define SHARE_JFR_RECORDER_CHECKPOINT_TYPES_JFRTHREADSTATE_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" class JfrCheckpointWriter; class Thread; diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.hpp b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.hpp index 8136d125804..456599b45f3 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.hpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ #include "jni.h" #include "jfr/utilities/jfrTypes.hpp" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" class ClassLoaderData; class Klass; diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdBits.hpp b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdBits.hpp index 7fba5d8d1e8..d7f7effdc3e 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdBits.hpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdBits.hpp @@ -27,7 +27,7 @@ #include "jni.h" #include "jfr/utilities/jfrTypes.hpp" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" class JfrTraceIdBits : AllStatic { public: diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdEpoch.hpp b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdEpoch.hpp index ba14919c935..1216f6956ef 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdEpoch.hpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdEpoch.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ #include "jfr/utilities/jfrSignal.hpp" #include "jfr/utilities/jfrTypes.hpp" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "runtime/atomic.hpp" #define BIT 1 diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdLoadBarrier.hpp b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdLoadBarrier.hpp index 7113a65bd42..e7b7e1a8780 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdLoadBarrier.hpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdLoadBarrier.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ #define SHARE_JFR_RECORDER_CHECKPOINT_TYPES_TRACEID_JFRTRACEIDLOADBARRIER_HPP #include "jfr/utilities/jfrTypes.hpp" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" class ClassLoaderData; class JfrBuffer; diff --git a/src/hotspot/share/jfr/recorder/repository/jfrChunkRotation.hpp b/src/hotspot/share/jfr/recorder/repository/jfrChunkRotation.hpp index 973fa611718..76603b1cd5e 100644 --- a/src/hotspot/share/jfr/recorder/repository/jfrChunkRotation.hpp +++ b/src/hotspot/share/jfr/recorder/repository/jfrChunkRotation.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022, 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 @@ #ifndef SHARE_JFR_RECORDER_REPOSITORY_JFRCHUNKROTATION_HPP #define SHARE_JFR_RECORDER_REPOSITORY_JFRCHUNKROTATION_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" class JfrChunkWriter; diff --git a/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.hpp b/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.hpp index c96a7d802dc..7912daf35c9 100644 --- a/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.hpp +++ b/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2022, 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 @@ #ifndef SHARE_JFR_RECORDER_REPOSITORY_JFREMERGENCYDUMP_HPP #define SHARE_JFR_RECORDER_REPOSITORY_JFREMERGENCYDUMP_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "utilities/ostream.hpp" // diff --git a/src/hotspot/share/jfr/recorder/service/jfrMemorySizer.hpp b/src/hotspot/share/jfr/recorder/service/jfrMemorySizer.hpp index 8f056e95398..5e226437987 100644 --- a/src/hotspot/share/jfr/recorder/service/jfrMemorySizer.hpp +++ b/src/hotspot/share/jfr/recorder/service/jfrMemorySizer.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022, 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 @@ #ifndef SHARE_JFR_RECORDER_SERVICE_JFRMEMORYSIZER_HPP #define SHARE_JFR_RECORDER_SERVICE_JFRMEMORYSIZER_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "utilities/globalDefinitions.hpp" extern const julong MIN_BUFFER_COUNT; diff --git a/src/hotspot/share/jfr/recorder/service/jfrOptionSet.hpp b/src/hotspot/share/jfr/recorder/service/jfrOptionSet.hpp index 9e1dd6cef11..9ad810bc3cd 100644 --- a/src/hotspot/share/jfr/recorder/service/jfrOptionSet.hpp +++ b/src/hotspot/share/jfr/recorder/service/jfrOptionSet.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ #define SHARE_JFR_RECORDER_SERVICE_JFROPTIONSET_HPP #include "jni.h" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "utilities/exceptions.hpp" template diff --git a/src/hotspot/share/jfr/recorder/service/jfrRecorderThread.hpp b/src/hotspot/share/jfr/recorder/service/jfrRecorderThread.hpp index 736cc350833..ca8d3e87841 100644 --- a/src/hotspot/share/jfr/recorder/service/jfrRecorderThread.hpp +++ b/src/hotspot/share/jfr/recorder/service/jfrRecorderThread.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2022, 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 @@ #ifndef SHARE_JFR_RECORDER_SERVICE_JFRRECORDERTHREAD_HPP #define SHARE_JFR_RECORDER_SERVICE_JFRRECORDERTHREAD_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "utilities/debug.hpp" class JavaThread; diff --git a/src/hotspot/share/jfr/support/jfrJdkJfrEvent.hpp b/src/hotspot/share/jfr/support/jfrJdkJfrEvent.hpp index 06dddd6d39e..3c3a6d69377 100644 --- a/src/hotspot/share/jfr/support/jfrJdkJfrEvent.hpp +++ b/src/hotspot/share/jfr/support/jfrJdkJfrEvent.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ #define SHARE_JFR_SUPPORT_JFRJDKJFREVENT_HPP #include "jni.h" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "utilities/exceptions.hpp" class Klass; diff --git a/src/hotspot/share/jfr/support/jfrKlassUnloading.hpp b/src/hotspot/share/jfr/support/jfrKlassUnloading.hpp index dcbe11ab8f6..5d380df436c 100644 --- a/src/hotspot/share/jfr/support/jfrKlassUnloading.hpp +++ b/src/hotspot/share/jfr/support/jfrKlassUnloading.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ #define SHARE_JFR_SUPPORT_JFRKLASSUNLOADING_HPP #include "jfr/utilities/jfrTypes.hpp" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" class Klass; diff --git a/src/hotspot/share/jfr/support/jfrMethodLookup.hpp b/src/hotspot/share/jfr/support/jfrMethodLookup.hpp index 2f998a9def3..106648b25d7 100644 --- a/src/hotspot/share/jfr/support/jfrMethodLookup.hpp +++ b/src/hotspot/share/jfr/support/jfrMethodLookup.hpp @@ -26,7 +26,7 @@ #define SHARE_JFR_SUPPORT_JFRMETHODLOOKUP_HPP #include "jfr/utilities/jfrTypes.hpp" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" class InstanceKlass; class Method; diff --git a/src/hotspot/share/jfr/support/jfrObjectAllocationSample.hpp b/src/hotspot/share/jfr/support/jfrObjectAllocationSample.hpp index 0902db68f5b..f58caf3c2a6 100644 --- a/src/hotspot/share/jfr/support/jfrObjectAllocationSample.hpp +++ b/src/hotspot/share/jfr/support/jfrObjectAllocationSample.hpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. +* Copyright (c) 2020, 2022, 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 @@ #ifndef SHARE_JFR_SUPPORT_JFROBJECTALLOCATIONSAMPLE_HPP #define SHARE_JFR_SUPPORT_JFROBJECTALLOCATIONSAMPLE_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" class Klass; class Thread; diff --git a/src/hotspot/share/jfr/utilities/jfrBigEndian.hpp b/src/hotspot/share/jfr/utilities/jfrBigEndian.hpp index db2e7ebaad2..b2e641269e0 100644 --- a/src/hotspot/share/jfr/utilities/jfrBigEndian.hpp +++ b/src/hotspot/share/jfr/utilities/jfrBigEndian.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022, 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 @@ #ifndef SHARE_JFR_UTILITIES_JFRBIGENDIAN_HPP #define SHARE_JFR_UTILITIES_JFRBIGENDIAN_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "utilities/bytes.hpp" #include "utilities/macros.hpp" diff --git a/src/hotspot/share/jfr/utilities/jfrJavaLog.hpp b/src/hotspot/share/jfr/utilities/jfrJavaLog.hpp index daef51ac81e..3b5ccc661fe 100644 --- a/src/hotspot/share/jfr/utilities/jfrJavaLog.hpp +++ b/src/hotspot/share/jfr/utilities/jfrJavaLog.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, 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 @@ #ifndef SHARE_JFR_UTILITIES_JFRJAVALOG_HPP #define SHARE_JFR_UTILITIES_JFRJAVALOG_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "utilities/exceptions.hpp" /* diff --git a/src/hotspot/share/jfr/utilities/jfrPredicate.hpp b/src/hotspot/share/jfr/utilities/jfrPredicate.hpp index b5f87b4c1e0..51ad1fec0c9 100644 --- a/src/hotspot/share/jfr/utilities/jfrPredicate.hpp +++ b/src/hotspot/share/jfr/utilities/jfrPredicate.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, 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 @@ #ifndef SHARE_JFR_UTILITIES_JFRPREDICATE_HPP #define SHARE_JFR_UTILITIES_JFRPREDICATE_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "utilities/growableArray.hpp" /* diff --git a/src/hotspot/share/jfr/utilities/jfrTimeConverter.hpp b/src/hotspot/share/jfr/utilities/jfrTimeConverter.hpp index 9ce2308a551..6871fbb5461 100644 --- a/src/hotspot/share/jfr/utilities/jfrTimeConverter.hpp +++ b/src/hotspot/share/jfr/utilities/jfrTimeConverter.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2022, 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 @@ #ifndef SHARE_JFR_UTILITIES_JFRTIMECONVERTER_HPP #define SHARE_JFR_UTILITIES_JFRTIMECONVERTER_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "utilities/globalDefinitions.hpp" class JfrTimeConverter : AllStatic { diff --git a/src/hotspot/share/jfr/writers/jfrEncoding.hpp b/src/hotspot/share/jfr/writers/jfrEncoding.hpp index 4684cc4bc9d..3d4c7c55e0e 100644 --- a/src/hotspot/share/jfr/writers/jfrEncoding.hpp +++ b/src/hotspot/share/jfr/writers/jfrEncoding.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ #define SHARE_JFR_WRITERS_JFRENCODING_HPP #include "jfr/writers/jfrEncoders.hpp" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "utilities/globalDefinitions.hpp" enum JfrStringEncoding { diff --git a/src/hotspot/share/jfr/writers/jfrJavaEventWriter.hpp b/src/hotspot/share/jfr/writers/jfrJavaEventWriter.hpp index 844ce51a3d9..1159766428e 100644 --- a/src/hotspot/share/jfr/writers/jfrJavaEventWriter.hpp +++ b/src/hotspot/share/jfr/writers/jfrJavaEventWriter.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ #define SHARE_JFR_WRITERS_JFRJAVAEVENTWRITER_HPP #include "jni.h" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" class JavaThread; class Thread; diff --git a/src/hotspot/share/logging/logConfiguration.hpp b/src/hotspot/share/logging/logConfiguration.hpp index 542aaa2433b..35491d7459b 100644 --- a/src/hotspot/share/logging/logConfiguration.hpp +++ b/src/hotspot/share/logging/logConfiguration.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, 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,12 +25,13 @@ #define SHARE_LOGGING_LOGCONFIGURATION_HPP #include "logging/logLevel.hpp" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "utilities/globalDefinitions.hpp" class LogOutput; class LogDecorators; class LogSelectionList; +class outputStream; // Global configuration of logging. Handles parsing and configuration of the logging framework, // and manages the list of configured log outputs. The actual tag and level configuration is diff --git a/src/hotspot/share/logging/logLevel.hpp b/src/hotspot/share/logging/logLevel.hpp index 7fe2d31f999..56ea7f5958a 100644 --- a/src/hotspot/share/logging/logLevel.hpp +++ b/src/hotspot/share/logging/logLevel.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,8 @@ #ifndef SHARE_LOGGING_LOGLEVEL_HPP #define SHARE_LOGGING_LOGLEVEL_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" +#include "utilities/debug.hpp" #include "utilities/macros.hpp" // The list of log levels: diff --git a/src/hotspot/share/logging/logTag.hpp b/src/hotspot/share/logging/logTag.hpp index 78e0a88d112..9b216a9d35f 100644 --- a/src/hotspot/share/logging/logTag.hpp +++ b/src/hotspot/share/logging/logTag.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,9 +24,11 @@ #ifndef SHARE_LOGGING_LOGTAG_HPP #define SHARE_LOGGING_LOGTAG_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "utilities/globalDefinitions.hpp" +class outputStream; + // List of available logging tags. New tags should be added here, in // alphabetical order. // (The tags 'all', 'disable' and 'help' are special tags that can diff --git a/src/hotspot/share/memory/metaspace/internalStats.hpp b/src/hotspot/share/memory/metaspace/internalStats.hpp index dff2534e303..9c127568e57 100644 --- a/src/hotspot/share/memory/metaspace/internalStats.hpp +++ b/src/hotspot/share/memory/metaspace/internalStats.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2020 SAP SE. All rights reserved. + * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ #ifndef SHARE_MEMORY_METASPACE_INTERNALSTATS_HPP #define SHARE_MEMORY_METASPACE_INTERNALSTATS_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "runtime/atomic.hpp" #include "utilities/globalDefinitions.hpp" diff --git a/src/hotspot/share/memory/metaspace/metaspaceReporter.hpp b/src/hotspot/share/memory/metaspace/metaspaceReporter.hpp index 2aab2063379..acc5ca211e8 100644 --- a/src/hotspot/share/memory/metaspace/metaspaceReporter.hpp +++ b/src/hotspot/share/memory/metaspace/metaspaceReporter.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2018, 2020 SAP SE. All rights reserved. + * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2022 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ #ifndef SHARE_MEMORY_METASPACE_METASPACEREPORTER_HPP #define SHARE_MEMORY_METASPACE_METASPACEREPORTER_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" namespace metaspace { diff --git a/src/hotspot/share/memory/metaspace/metaspaceSettings.hpp b/src/hotspot/share/memory/metaspace/metaspaceSettings.hpp index e6d47fec3f4..d2dc3f97441 100644 --- a/src/hotspot/share/memory/metaspace/metaspaceSettings.hpp +++ b/src/hotspot/share/memory/metaspace/metaspaceSettings.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2020 SAP SE. All rights reserved. + * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ #ifndef SHARE_MEMORY_METASPACE_METASPACESETTINGS_HPP #define SHARE_MEMORY_METASPACE_METASPACESETTINGS_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "memory/metaspace/chunklevel.hpp" #include "utilities/globalDefinitions.hpp" diff --git a/src/hotspot/share/memory/metaspace/runningCounters.hpp b/src/hotspot/share/memory/metaspace/runningCounters.hpp index 8ef751896d3..ff24ead7ebd 100644 --- a/src/hotspot/share/memory/metaspace/runningCounters.hpp +++ b/src/hotspot/share/memory/metaspace/runningCounters.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2020 SAP SE. All rights reserved. + * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ #ifndef SHARE_MEMORY_METASPACE_RUNNINGCOUNTERS_HPP #define SHARE_MEMORY_METASPACE_RUNNINGCOUNTERS_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "memory/metaspace/counters.hpp" namespace metaspace { diff --git a/src/hotspot/share/memory/metaspaceCounters.hpp b/src/hotspot/share/memory/metaspaceCounters.hpp index 38d9c94ddb6..b83e1fdb1ba 100644 --- a/src/hotspot/share/memory/metaspaceCounters.hpp +++ b/src/hotspot/share/memory/metaspaceCounters.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2021 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -26,7 +26,7 @@ #ifndef SHARE_MEMORY_METASPACECOUNTERS_HPP #define SHARE_MEMORY_METASPACECOUNTERS_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" // Perf Counters for Metaspace diff --git a/src/hotspot/share/memory/metaspaceCriticalAllocation.hpp b/src/hotspot/share/memory/metaspaceCriticalAllocation.hpp index 71e8819aef3..bdc9ad8cf2c 100644 --- a/src/hotspot/share/memory/metaspaceCriticalAllocation.hpp +++ b/src/hotspot/share/memory/metaspaceCriticalAllocation.hpp @@ -25,7 +25,7 @@ #ifndef SHARE_MEMORY_METASPACECRITICALALLOCATION_HPP #define SHARE_MEMORY_METASPACECRITICALALLOCATION_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "memory/metaspace.hpp" class MetadataAllocationRequest; diff --git a/src/hotspot/share/metaprogramming/conditional.hpp b/src/hotspot/share/metaprogramming/conditional.hpp index 2d4fe1a86e8..3ba2fb7594e 100644 --- a/src/hotspot/share/metaprogramming/conditional.hpp +++ b/src/hotspot/share/metaprogramming/conditional.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022, 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 @@ #ifndef SHARE_METAPROGRAMMING_CONDITIONAL_HPP #define SHARE_METAPROGRAMMING_CONDITIONAL_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" // This trait evaluates its typedef called "type" to TrueType iff the condition // is true. Otherwise it evaluates to FalseType. diff --git a/src/hotspot/share/metaprogramming/decay.hpp b/src/hotspot/share/metaprogramming/decay.hpp index 4dff0500f13..f504c099e4d 100644 --- a/src/hotspot/share/metaprogramming/decay.hpp +++ b/src/hotspot/share/metaprogramming/decay.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022, 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 @@ #ifndef SHARE_METAPROGRAMMING_DECAY_HPP #define SHARE_METAPROGRAMMING_DECAY_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "metaprogramming/removeCV.hpp" #include "metaprogramming/removeReference.hpp" diff --git a/src/hotspot/share/metaprogramming/removeCV.hpp b/src/hotspot/share/metaprogramming/removeCV.hpp index 0c0b2f47fa7..5ddafc54746 100644 --- a/src/hotspot/share/metaprogramming/removeCV.hpp +++ b/src/hotspot/share/metaprogramming/removeCV.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022, 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 @@ #ifndef SHARE_METAPROGRAMMING_REMOVECV_HPP #define SHARE_METAPROGRAMMING_REMOVECV_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" template struct RemoveCV: AllStatic { diff --git a/src/hotspot/share/metaprogramming/removeExtent.hpp b/src/hotspot/share/metaprogramming/removeExtent.hpp index f188e0db264..3f93dd3eeb6 100644 --- a/src/hotspot/share/metaprogramming/removeExtent.hpp +++ b/src/hotspot/share/metaprogramming/removeExtent.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, 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 @@ #ifndef SHARE_METAPROGRAMMING_REMOVEEXTENT_HPP #define SHARE_METAPROGRAMMING_REMOVEEXTENT_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" template struct RemoveExtent: AllStatic { typedef T type; }; diff --git a/src/hotspot/share/metaprogramming/removePointer.hpp b/src/hotspot/share/metaprogramming/removePointer.hpp index be0f5b6e6fb..eb267c0702d 100644 --- a/src/hotspot/share/metaprogramming/removePointer.hpp +++ b/src/hotspot/share/metaprogramming/removePointer.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022, 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 @@ #ifndef SHARE_METAPROGRAMMING_REMOVEPOINTER_HPP #define SHARE_METAPROGRAMMING_REMOVEPOINTER_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" // This metafunction returns for a type T either the underlying type behind // the pointer iff T is a pointer type (irrespective of CV qualifiers), diff --git a/src/hotspot/share/metaprogramming/removeReference.hpp b/src/hotspot/share/metaprogramming/removeReference.hpp index 274c327a0ad..bd263d911a5 100644 --- a/src/hotspot/share/metaprogramming/removeReference.hpp +++ b/src/hotspot/share/metaprogramming/removeReference.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022, 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 @@ #ifndef SHARE_METAPROGRAMMING_REMOVEREFERENCE_HPP #define SHARE_METAPROGRAMMING_REMOVEREFERENCE_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" // This metafunction returns for a type T either the underlying type behind // the reference iff T is a reference type, or the same type T if T is not diff --git a/src/hotspot/share/oops/access.hpp b/src/hotspot/share/oops/access.hpp index c3f3d0ba45c..47e6bd27ea0 100644 --- a/src/hotspot/share/oops/access.hpp +++ b/src/hotspot/share/oops/access.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022, 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 @@ #ifndef SHARE_OOPS_ACCESS_HPP #define SHARE_OOPS_ACCESS_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "oops/accessBackend.hpp" #include "oops/accessDecorators.hpp" #include "oops/oopsHierarchy.hpp" diff --git a/src/hotspot/share/oops/accessDecorators.hpp b/src/hotspot/share/oops/accessDecorators.hpp index 21bcff9113d..976f2e355e1 100644 --- a/src/hotspot/share/oops/accessDecorators.hpp +++ b/src/hotspot/share/oops/accessDecorators.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ #define SHARE_OOPS_ACCESSDECORATORS_HPP #include "gc/shared/barrierSetConfig.hpp" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "metaprogramming/integralConstant.hpp" #include "utilities/globalDefinitions.hpp" diff --git a/src/hotspot/share/oops/compressedOops.hpp b/src/hotspot/share/oops/compressedOops.hpp index 83f18138b5a..2755b1eef92 100644 --- a/src/hotspot/share/oops/compressedOops.hpp +++ b/src/hotspot/share/oops/compressedOops.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, 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 @@ #ifndef SHARE_OOPS_COMPRESSEDOOPS_HPP #define SHARE_OOPS_COMPRESSEDOOPS_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "memory/memRegion.hpp" #include "oops/oopsHierarchy.hpp" #include "utilities/globalDefinitions.hpp" diff --git a/src/hotspot/share/prims/jniFastGetField.hpp b/src/hotspot/share/prims/jniFastGetField.hpp index 4673d2cb5c9..525ff0aba87 100644 --- a/src/hotspot/share/prims/jniFastGetField.hpp +++ b/src/hotspot/share/prims/jniFastGetField.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2022, 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 @@ #ifndef SHARE_PRIMS_JNIFASTGETFIELD_HPP #define SHARE_PRIMS_JNIFASTGETFIELD_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "prims/jvm_misc.hpp" // Basic logic of a fast version of jni_GetField: diff --git a/src/hotspot/share/prims/jvmtiEventController.hpp b/src/hotspot/share/prims/jvmtiEventController.hpp index 69156d27108..06a3e801876 100644 --- a/src/hotspot/share/prims/jvmtiEventController.hpp +++ b/src/hotspot/share/prims/jvmtiEventController.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ #define SHARE_PRIMS_JVMTIEVENTCONTROLLER_HPP #include "jvmtifiles/jvmti.h" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "utilities/globalDefinitions.hpp" // forward declaration diff --git a/src/hotspot/share/prims/jvmtiExtensions.hpp b/src/hotspot/share/prims/jvmtiExtensions.hpp index b1156b8be49..d44c6dd4f51 100644 --- a/src/hotspot/share/prims/jvmtiExtensions.hpp +++ b/src/hotspot/share/prims/jvmtiExtensions.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ #include "jvmtifiles/jvmti.h" #include "jvmtifiles/jvmtiEnv.hpp" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" // JvmtiExtensions // diff --git a/src/hotspot/share/prims/jvmtiManageCapabilities.hpp b/src/hotspot/share/prims/jvmtiManageCapabilities.hpp index fc6ef884f07..e588be4fa15 100644 --- a/src/hotspot/share/prims/jvmtiManageCapabilities.hpp +++ b/src/hotspot/share/prims/jvmtiManageCapabilities.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ #define SHARE_PRIMS_JVMTIMANAGECAPABILITIES_HPP #include "jvmtifiles/jvmti.h" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" class JvmtiManageCapabilities : public AllStatic { diff --git a/src/hotspot/share/prims/nativeLookup.hpp b/src/hotspot/share/prims/nativeLookup.hpp index a00b16c2fa4..9aafed6f272 100644 --- a/src/hotspot/share/prims/nativeLookup.hpp +++ b/src/hotspot/share/prims/nativeLookup.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ #ifndef SHARE_PRIMS_NATIVELOOKUP_HPP #define SHARE_PRIMS_NATIVELOOKUP_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "runtime/handles.hpp" // NativeLookup provides an interface for finding DLL entry points for diff --git a/src/hotspot/share/prims/resolvedMethodTable.hpp b/src/hotspot/share/prims/resolvedMethodTable.hpp index b89de0e419a..b437f012946 100644 --- a/src/hotspot/share/prims/resolvedMethodTable.hpp +++ b/src/hotspot/share/prims/resolvedMethodTable.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022, 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 @@ #ifndef SHARE_PRIMS_RESOLVEDMETHODTABLE_HPP #define SHARE_PRIMS_RESOLVEDMETHODTABLE_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "oops/symbol.hpp" #include "oops/weakHandle.hpp" diff --git a/src/hotspot/share/prims/vectorSupport.hpp b/src/hotspot/share/prims/vectorSupport.hpp index 324400c198d..ccae8bbcfc0 100644 --- a/src/hotspot/share/prims/vectorSupport.hpp +++ b/src/hotspot/share/prims/vectorSupport.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ #include "jni.h" #include "code/debugInfo.hpp" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "oops/typeArrayOop.hpp" #include "runtime/registerMap.hpp" #include "utilities/exceptions.hpp" diff --git a/src/hotspot/share/runtime/abstract_vm_version.hpp b/src/hotspot/share/runtime/abstract_vm_version.hpp index d2f210ca04d..a1dd51dad2c 100644 --- a/src/hotspot/share/runtime/abstract_vm_version.hpp +++ b/src/hotspot/share/runtime/abstract_vm_version.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ #ifndef SHARE_RUNTIME_ABSTRACT_VM_VERSION_HPP #define SHARE_RUNTIME_ABSTRACT_VM_VERSION_HPP -#include "memory/allocation.hpp" // For declaration of class AllStatic +#include "memory/allStatic.hpp" // For declaration of class AllStatic #include "utilities/globalDefinitions.hpp" typedef enum { diff --git a/src/hotspot/share/runtime/arguments.hpp b/src/hotspot/share/runtime/arguments.hpp index 7b03205cb08..19bb12196e3 100644 --- a/src/hotspot/share/runtime/arguments.hpp +++ b/src/hotspot/share/runtime/arguments.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ #include "logging/logLevel.hpp" #include "logging/logTag.hpp" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "runtime/globals.hpp" #include "runtime/java.hpp" #include "runtime/os.hpp" diff --git a/src/hotspot/share/runtime/handshake.hpp b/src/hotspot/share/runtime/handshake.hpp index f66c731cc2d..f6a8e28a037 100644 --- a/src/hotspot/share/runtime/handshake.hpp +++ b/src/hotspot/share/runtime/handshake.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022, 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 @@ #ifndef SHARE_RUNTIME_HANDSHAKE_HPP #define SHARE_RUNTIME_HANDSHAKE_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "memory/iterator.hpp" #include "runtime/flags/flagSetting.hpp" #include "runtime/mutex.hpp" diff --git a/src/hotspot/share/runtime/icache.hpp b/src/hotspot/share/runtime/icache.hpp index 522fc5ed1fe..d273372a877 100644 --- a/src/hotspot/share/runtime/icache.hpp +++ b/src/hotspot/share/runtime/icache.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ #ifndef SHARE_RUNTIME_ICACHE_HPP #define SHARE_RUNTIME_ICACHE_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "runtime/stubCodeGenerator.hpp" #include "utilities/macros.hpp" diff --git a/src/hotspot/share/runtime/jniHandles.hpp b/src/hotspot/share/runtime/jniHandles.hpp index 0ec73966f20..f1d9ee43529 100644 --- a/src/hotspot/share/runtime/jniHandles.hpp +++ b/src/hotspot/share/runtime/jniHandles.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2022, 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 @@ #ifndef SHARE_RUNTIME_JNIHANDLES_HPP #define SHARE_RUNTIME_JNIHANDLES_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "runtime/handles.hpp" class JavaThread; diff --git a/src/hotspot/share/runtime/orderAccess.hpp b/src/hotspot/share/runtime/orderAccess.hpp index 8e5944916f9..159fbd9038d 100644 --- a/src/hotspot/share/runtime/orderAccess.hpp +++ b/src/hotspot/share/runtime/orderAccess.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, 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 @@ #ifndef SHARE_RUNTIME_ORDERACCESS_HPP #define SHARE_RUNTIME_ORDERACCESS_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "runtime/vm_version.hpp" #include "utilities/macros.hpp" diff --git a/src/hotspot/share/runtime/prefetch.hpp b/src/hotspot/share/runtime/prefetch.hpp index dac34f6cd26..d949899813c 100644 --- a/src/hotspot/share/runtime/prefetch.hpp +++ b/src/hotspot/share/runtime/prefetch.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, 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 @@ #ifndef SHARE_RUNTIME_PREFETCH_HPP #define SHARE_RUNTIME_PREFETCH_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" // If calls to prefetch methods are in a loop, the loop should be cloned // such that if Prefetch{Scan,Copy}Interval and/or PrefetchFieldInterval diff --git a/src/hotspot/share/runtime/reflectionUtils.hpp b/src/hotspot/share/runtime/reflectionUtils.hpp index a928c50596e..ef9f8bbd62e 100644 --- a/src/hotspot/share/runtime/reflectionUtils.hpp +++ b/src/hotspot/share/runtime/reflectionUtils.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2022, 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 @@ #ifndef SHARE_RUNTIME_REFLECTIONUTILS_HPP #define SHARE_RUNTIME_REFLECTIONUTILS_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "oops/instanceKlass.hpp" #include "oops/objArrayOop.hpp" #include "oops/oopsHierarchy.hpp" diff --git a/src/hotspot/share/runtime/safepoint.hpp b/src/hotspot/share/runtime/safepoint.hpp index 8024ade2520..e67c960626b 100644 --- a/src/hotspot/share/runtime/safepoint.hpp +++ b/src/hotspot/share/runtime/safepoint.hpp @@ -25,7 +25,7 @@ #ifndef SHARE_RUNTIME_SAFEPOINT_HPP #define SHARE_RUNTIME_SAFEPOINT_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "runtime/os.hpp" #include "runtime/thread.hpp" #include "runtime/vmOperation.hpp" diff --git a/src/hotspot/share/runtime/sharedRuntime.hpp b/src/hotspot/share/runtime/sharedRuntime.hpp index 1adc9661985..10e4b0ec0af 100644 --- a/src/hotspot/share/runtime/sharedRuntime.hpp +++ b/src/hotspot/share/runtime/sharedRuntime.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,7 @@ #include "code/vmreg.hpp" #include "interpreter/bytecodeTracer.hpp" #include "interpreter/linkResolver.hpp" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "memory/resourceArea.hpp" #include "utilities/hashtable.hpp" #include "utilities/macros.hpp" diff --git a/src/hotspot/share/runtime/stackWatermark.hpp b/src/hotspot/share/runtime/stackWatermark.hpp index 3cf7ce59cd9..6210a0bc2bf 100644 --- a/src/hotspot/share/runtime/stackWatermark.hpp +++ b/src/hotspot/share/runtime/stackWatermark.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, 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 @@ #ifndef SHARE_RUNTIME_STACKWATERMARK_HPP #define SHARE_RUNTIME_STACKWATERMARK_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "runtime/mutex.hpp" #include "runtime/stackWatermarkKind.hpp" diff --git a/src/hotspot/share/runtime/threadLocalStorage.hpp b/src/hotspot/share/runtime/threadLocalStorage.hpp index 93607612a4d..604b624757e 100644 --- a/src/hotspot/share/runtime/threadLocalStorage.hpp +++ b/src/hotspot/share/runtime/threadLocalStorage.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ #ifndef SHARE_RUNTIME_THREADLOCALSTORAGE_HPP #define SHARE_RUNTIME_THREADLOCALSTORAGE_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" // forward-decl as we can't have an include cycle class Thread; diff --git a/src/hotspot/share/services/attachListener.hpp b/src/hotspot/share/services/attachListener.hpp index 25fad127d0f..5765240c16c 100644 --- a/src/hotspot/share/services/attachListener.hpp +++ b/src/hotspot/share/services/attachListener.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2022, 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 @@ #ifndef SHARE_SERVICES_ATTACHLISTENER_HPP #define SHARE_SERVICES_ATTACHLISTENER_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "runtime/atomic.hpp" #include "runtime/globals.hpp" #include "utilities/debug.hpp" diff --git a/src/hotspot/share/services/gcNotifier.hpp b/src/hotspot/share/services/gcNotifier.hpp index a13b85e0e69..1a4582025c4 100644 --- a/src/hotspot/share/services/gcNotifier.hpp +++ b/src/hotspot/share/services/gcNotifier.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2022, 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 @@ #ifndef SHARE_SERVICES_GCNOTIFIER_HPP #define SHARE_SERVICES_GCNOTIFIER_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "services/memoryPool.hpp" #include "services/memoryService.hpp" #include "services/memoryManager.hpp" diff --git a/src/hotspot/share/services/lowMemoryDetector.hpp b/src/hotspot/share/services/lowMemoryDetector.hpp index 09bb1ce6406..3070eb00ab7 100644 --- a/src/hotspot/share/services/lowMemoryDetector.hpp +++ b/src/hotspot/share/services/lowMemoryDetector.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, 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 @@ #ifndef SHARE_SERVICES_LOWMEMORYDETECTOR_HPP #define SHARE_SERVICES_LOWMEMORYDETECTOR_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "oops/oopHandle.hpp" #include "runtime/atomic.hpp" #include "services/memoryPool.hpp" diff --git a/src/hotspot/share/services/nmtCommon.hpp b/src/hotspot/share/services/nmtCommon.hpp index b573fb6b7df..dc85338c025 100644 --- a/src/hotspot/share/services/nmtCommon.hpp +++ b/src/hotspot/share/services/nmtCommon.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2022, 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 @@ #ifndef SHARE_SERVICES_NMTCOMMON_HPP #define SHARE_SERVICES_NMTCOMMON_HPP -#include "memory/allocation.hpp" +#include "memory/allocation.hpp" // for MEMFLAGS only #include "utilities/align.hpp" #include "utilities/globalDefinitions.hpp" diff --git a/src/hotspot/share/services/threadIdTable.hpp b/src/hotspot/share/services/threadIdTable.hpp index 223b57fcecb..12772aed88c 100644 --- a/src/hotspot/share/services/threadIdTable.hpp +++ b/src/hotspot/share/services/threadIdTable.hpp @@ -26,7 +26,7 @@ #ifndef SHARE_SERVICES_THREADIDTABLE_HPP #define SHARE_SERVICES_THREADIDTABLE_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" class JavaThread; class ThreadsList; diff --git a/src/hotspot/share/utilities/decoder.hpp b/src/hotspot/share/utilities/decoder.hpp index ccf3ac4ba3c..b0a368fd058 100644 --- a/src/hotspot/share/utilities/decoder.hpp +++ b/src/hotspot/share/utilities/decoder.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ #ifndef SHARE_UTILITIES_DECODER_HPP #define SHARE_UTILITIES_DECODER_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "runtime/mutex.hpp" #include "runtime/mutexLocker.hpp" #include "utilities/ostream.hpp" diff --git a/src/hotspot/share/utilities/globalCounter.hpp b/src/hotspot/share/utilities/globalCounter.hpp index beba72a954a..5f5eba263b9 100644 --- a/src/hotspot/share/utilities/globalCounter.hpp +++ b/src/hotspot/share/utilities/globalCounter.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2022, 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 @@ #ifndef SHARE_UTILITIES_GLOBALCOUNTER_HPP #define SHARE_UTILITIES_GLOBALCOUNTER_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "memory/padded.hpp" class Thread; diff --git a/src/hotspot/share/utilities/quickSort.hpp b/src/hotspot/share/utilities/quickSort.hpp index 000f1bf4f42..a94a7cd8b6c 100644 --- a/src/hotspot/share/utilities/quickSort.hpp +++ b/src/hotspot/share/utilities/quickSort.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2022, 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 @@ #ifndef SHARE_UTILITIES_QUICKSORT_HPP #define SHARE_UTILITIES_QUICKSORT_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "runtime/globals.hpp" #include "utilities/debug.hpp" diff --git a/src/hotspot/share/utilities/stringUtils.cpp b/src/hotspot/share/utilities/stringUtils.cpp index 21fb7a6e8d3..0ee73de809a 100644 --- a/src/hotspot/share/utilities/stringUtils.cpp +++ b/src/hotspot/share/utilities/stringUtils.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,8 @@ #include "utilities/debug.hpp" #include "utilities/stringUtils.hpp" +#include + int StringUtils::replace_no_expand(char* string, const char* from, const char* to) { int replace_count = 0; size_t from_len = strlen(from); diff --git a/src/hotspot/share/utilities/stringUtils.hpp b/src/hotspot/share/utilities/stringUtils.hpp index 372222d7c70..54d6847a4c4 100644 --- a/src/hotspot/share/utilities/stringUtils.hpp +++ b/src/hotspot/share/utilities/stringUtils.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2022, 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 @@ #ifndef SHARE_UTILITIES_STRINGUTILS_HPP #define SHARE_UTILITIES_STRINGUTILS_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" class StringUtils : AllStatic { public: diff --git a/src/hotspot/share/utilities/utf8.cpp b/src/hotspot/share/utilities/utf8.cpp index 6ebeb9a6c9b..81ad02a9ba6 100644 --- a/src/hotspot/share/utilities/utf8.cpp +++ b/src/hotspot/share/utilities/utf8.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,8 +23,12 @@ */ #include "precompiled.hpp" +#include "memory/allocation.hpp" +#include "utilities/debug.hpp" +#include "utilities/globalDefinitions.hpp" #include "utilities/utf8.hpp" + // Assume the utf8 string is in legal form and has been // checked in the class file parser/format checker. template char* UTF8::next(const char* str, T* value) { diff --git a/src/hotspot/share/utilities/utf8.hpp b/src/hotspot/share/utilities/utf8.hpp index 0ebd65b0658..e7b2905e046 100644 --- a/src/hotspot/share/utilities/utf8.hpp +++ b/src/hotspot/share/utilities/utf8.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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,9 @@ #ifndef SHARE_UTILITIES_UTF8_HPP #define SHARE_UTILITIES_UTF8_HPP -#include "memory/allocation.hpp" +#include "jni.h" +#include "memory/allStatic.hpp" +#include "utilities/debug.hpp" // Low-level interface for UTF8 strings diff --git a/test/hotspot/gtest/classfile/test_AltHashing.cpp b/test/hotspot/gtest/classfile/test_AltHashing.cpp index d11dc0fb4a2..0070c4fd2c1 100644 --- a/test/hotspot/gtest/classfile/test_AltHashing.cpp +++ b/test/hotspot/gtest/classfile/test_AltHashing.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,7 @@ #include "classfile/altHashing.hpp" #include "utilities/debug.hpp" #include "utilities/formatBuffer.hpp" +#include "utilities/globalDefinitions.hpp" #include "unittest.hpp" class AltHashingTest : public ::testing::Test { -- GitLab From 1b14157677b34891385f643a76a7aa19d7003acf Mon Sep 17 00:00:00 2001 From: Tobias Holenstein <71546117+tobiasholenstein@users.noreply.github.com> Date: Tue, 25 Jan 2022 09:59:55 +0000 Subject: [PATCH 275/564] 8280274: Guard printing code of Compile::print_method in PRODUCT Reviewed-by: thartmann, neliasso --- src/hotspot/share/opto/compile.cpp | 10 ++++++---- src/hotspot/share/opto/compile.hpp | 4 ++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index b0a2b3241e7..c730d1d9c98 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -2357,7 +2357,7 @@ void Compile::inline_vector_reboxing_calls() { CallGenerator* cg = _vector_reboxing_late_inlines.pop(); cg->do_late_inline(); if (failing()) return; - print_method(PHASE_INLINE_VECTOR_REBOX, cg->call_node()); + print_method(PHASE_INLINE_VECTOR_REBOX, cg->call_node(), 3); } _vector_reboxing_late_inlines.trunc_to(0); } @@ -4815,10 +4815,11 @@ void Compile::sort_macro_nodes() { } void Compile::print_method(CompilerPhaseType cpt, int level) { - print_method_impl(cpt, CompilerPhaseTypeHelper::to_string(cpt), level); + print_method_impl(cpt, NOT_PRODUCT(CompilerPhaseTypeHelper::to_string(cpt) COMMA) level); } void Compile::print_method(CompilerPhaseType cpt, Node* n, int level) { +#ifndef PRODUCT ResourceMark rm; stringStream ss; ss.print_raw(CompilerPhaseTypeHelper::to_string(cpt)); @@ -4827,10 +4828,11 @@ void Compile::print_method(CompilerPhaseType cpt, Node* n, int level) { } else { ss.print_raw(": NULL"); } - C->print_method_impl(cpt, ss.as_string(), level); +#endif + C->print_method_impl(cpt, NOT_PRODUCT(ss.as_string() COMMA) level); } -void Compile::print_method_impl(CompilerPhaseType cpt, const char *name, int level) { +void Compile::print_method_impl(CompilerPhaseType cpt, NOT_PRODUCT(const char* name COMMA) int level) { EventCompilerPhase event; if (event.should_commit()) { CompilerEvent::PhaseEvent::post(event, C->_latest_stage_start_counter, cpt, C->_compile_id, level); diff --git a/src/hotspot/share/opto/compile.hpp b/src/hotspot/share/opto/compile.hpp index 9b2fd80b589..0bf6b88eb17 100644 --- a/src/hotspot/share/opto/compile.hpp +++ b/src/hotspot/share/opto/compile.hpp @@ -656,8 +656,8 @@ class Compile : public Phase { bool should_print_igv(int level); void print_method(CompilerPhaseType cpt, int level); - void print_method(CompilerPhaseType cpt, Node* n, int level = 3); - void print_method_impl(CompilerPhaseType cpt, const char *name, int level); + void print_method(CompilerPhaseType cpt, Node* n, int level); + void print_method_impl(CompilerPhaseType cpt, NOT_PRODUCT(const char* name COMMA) int level); #ifndef PRODUCT void igv_print_method_to_file(const char* phase_name = "Debug", bool append = false); -- GitLab From c43ce85f01c96a4b80b971865306254c9417e549 Mon Sep 17 00:00:00 2001 From: Lutz Schmidt Date: Tue, 25 Jan 2022 10:07:07 +0000 Subject: [PATCH 276/564] 8278302: [s390] Implement fast-path for ASCII-compatible CharsetEncoders Reviewed-by: mdoerr --- .../cpu/s390/c2_MacroAssembler_s390.cpp | 83 +++++++++++++------ .../cpu/s390/c2_MacroAssembler_s390.hpp | 5 +- src/hotspot/cpu/s390/matcher_s390.hpp | 5 +- src/hotspot/cpu/s390/s390.ad | 24 ++++-- 4 files changed, 82 insertions(+), 35 deletions(-) diff --git a/src/hotspot/cpu/s390/c2_MacroAssembler_s390.cpp b/src/hotspot/cpu/s390/c2_MacroAssembler_s390.cpp index 83040fb6b7f..04a6b88052c 100644 --- a/src/hotspot/cpu/s390/c2_MacroAssembler_s390.cpp +++ b/src/hotspot/cpu/s390/c2_MacroAssembler_s390.cpp @@ -1,5 +1,6 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022 SAP SE. 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 @@ -46,22 +47,44 @@ // Note: // cnt is signed int. Do not rely on high word! // counts # characters, not bytes. -// The result is the number of characters copied before the first incompatible character was found. -// If precise is true, the processing stops exactly at this point. Otherwise, the result may be off -// by a few bytes. The result always indicates the number of copied characters. -// When used as a character index, the returned value points to the first incompatible character. // -// Note: Does not behave exactly like package private StringUTF16 compress java implementation in case of failure: -// - Different number of characters may have been written to dead array (if precise is false). -// - Returns a number --- - // Strings with 4 and 8 characters were fond to occur very frequently. + // Strings with 4 and 8 characters were found to occur very frequently. // Therefore, we handle them right away with minimal overhead. Label skipShortcut, skip4Shortcut, skip8Shortcut; Register Rout = Z_R0; @@ -133,7 +156,8 @@ unsigned int C2_MacroAssembler::string_compress(Register result, Register src, R if (VM_Version::has_VectorFacility()) { const int min_vcnt = 32; // Minimum #characters required to use vector instructions. // Otherwise just do nothing in vector mode. - // Must be multiple of 2*(vector register length in chars (8 HW = 128 bits)). + // Must correspond to # vector registers used by implementation, + // and must be a power of 2. const int log_min_vcnt = exact_log2(min_vcnt); Label VectorLoop, VectorDone, VectorBreak; @@ -150,7 +174,7 @@ unsigned int C2_MacroAssembler::string_compress(Register result, Register src, R z_brz(VectorDone); // not enough data for vector loop z_vzero(Vzero); // all zeroes - z_vgmh(Vmask, 0, 7); // generate 0xff00 mask for all 2-byte elements + z_vgmh(Vmask, mask_ix_l, mask_ix_r); // generate 0xff00/0xff80 mask for all 2-byte elements z_sllg(Z_R0, Rix, log_min_vcnt); // remember #chars that will be processed by vector loop bind(VectorLoop); @@ -162,7 +186,7 @@ unsigned int C2_MacroAssembler::string_compress(Register result, Register src, R z_vo(Vtmp2, Z_V22, Z_V23); z_vo(Vtmp1, Vtmp1, Vtmp2); z_vn(Vtmp1, Vtmp1, Vmask); - z_vceqhs(Vtmp1, Vtmp1, Vzero); // high half of all chars must be zero for successful compress. + z_vceqhs(Vtmp1, Vtmp1, Vzero); // all bits selected by mask must be zero for successful compress. z_bvnt(VectorBreak); // break vector loop if not all vector elements compare eq -> incompatible character found. // re-process data from current iteration in break handler. @@ -187,7 +211,8 @@ unsigned int C2_MacroAssembler::string_compress(Register result, Register src, R { const int min_cnt = 8; // Minimum #characters required to use unrolled loop. // Otherwise just do nothing in unrolled loop. - // Must be multiple of 8. + // Must correspond to # registers used by implementation, + // and must be a power of 2. const int log_min_cnt = exact_log2(min_cnt); Label UnrolledLoop, UnrolledDone, UnrolledBreak; @@ -197,7 +222,7 @@ unsigned int C2_MacroAssembler::string_compress(Register result, Register src, R z_lr(Rix, Rcnt); z_sr(Rix, Z_R0); } - z_sra(Rix, log_min_cnt); // unrolled loop count + z_sra(Rix, log_min_cnt); // unrolled loop count z_brz(UnrolledDone); bind(UnrolledLoop); @@ -244,6 +269,8 @@ unsigned int C2_MacroAssembler::string_compress(Register result, Register src, R z_sll(Rix, log_min_cnt); // # chars not yet processed in UnrolledLoop (due to break), broken iteration not included. z_sr(Z_R0, Rix); // fix # chars processed OK so far. if (!precise) { + // Because we don't need to be precise, we just return the # of characters which have been written. + // The first illegal character is in the index range [result-min_cnt/2, result+min_cnt/2). z_lgfr(result, Z_R0); z_sllg(Z_R1, Z_R0, 1); // # src bytes already processed. Only lower 32 bits are valid! // Z_R1 contents must be treated as unsigned operand! For huge strings, @@ -274,7 +301,7 @@ unsigned int C2_MacroAssembler::string_compress(Register result, Register src, R z_brh(ScalarDoit); z_llh(Z_R1, 0, Z_R0, Rsrc); z_bre(Scalar2Char); - z_tmll(Z_R1, 0xff00); + z_tmll(Z_R1, char_mask); z_lghi(result, 0); // cnt == 1, first char invalid, no chars successfully processed z_brnaz(AllDone); z_stc(Z_R1, 0, Z_R0, Rdst); @@ -283,11 +310,11 @@ unsigned int C2_MacroAssembler::string_compress(Register result, Register src, R bind(Scalar2Char); z_llh(Z_R0, 2, Z_R0, Rsrc); - z_tmll(Z_R1, 0xff00); + z_tmll(Z_R1, char_mask); z_lghi(result, 0); // cnt == 2, first char invalid, no chars successfully processed z_brnaz(AllDone); z_stc(Z_R1, 0, Z_R0, Rdst); - z_tmll(Z_R0, 0xff00); + z_tmll(Z_R0, char_mask); z_lghi(result, 1); // cnt == 2, second char invalid, one char successfully processed z_brnaz(AllDone); z_stc(Z_R0, 1, Z_R0, Rdst); @@ -299,17 +326,17 @@ unsigned int C2_MacroAssembler::string_compress(Register result, Register src, R #endif if (VM_Version::has_DistinctOpnds()) { - z_srk(Rix, Rcnt, Z_R0); // remaining # chars to compress in unrolled loop + z_srk(Rix, Rcnt, Z_R0); // remaining # chars to compress in scalar loop } else { z_lr(Rix, Rcnt); z_sr(Rix, Z_R0); } - z_lgfr(result, Rcnt); // # processed characters (if all runs ok). - z_brz(ScalarDone); // uses CC from Rix calculation + z_lgfr(result, Rcnt); // # processed characters (if all encodes ok). + z_brz(ScalarDone); // anything left to do? (uses CC from Rix calculation) bind(ScalarLoop); z_llh(Z_R1, 0, Z_R0, Rsrc); - z_tmll(Z_R1, 0xff00); + z_tmll(Z_R1, char_mask); z_brnaz(ScalarBreak); z_stc(Z_R1, 0, Z_R0, Rdst); add2reg(Rsrc, 2); @@ -329,7 +356,11 @@ unsigned int C2_MacroAssembler::string_compress(Register result, Register src, R bind(AllDone); if (precise) { - BLOCK_COMMENT("} encode_iso_array"); + if (toASCII) { + BLOCK_COMMENT("} encode_ascii_array"); + } else { + BLOCK_COMMENT("} encode_iso_array"); + } } else { BLOCK_COMMENT("} string_compress"); } diff --git a/src/hotspot/cpu/s390/c2_MacroAssembler_s390.hpp b/src/hotspot/cpu/s390/c2_MacroAssembler_s390.hpp index 08112a482d0..a6c98656495 100644 --- a/src/hotspot/cpu/s390/c2_MacroAssembler_s390.hpp +++ b/src/hotspot/cpu/s390/c2_MacroAssembler_s390.hpp @@ -1,5 +1,6 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,7 +39,7 @@ // Early clobber: result. // Boolean precise controls accuracy of result value. unsigned int string_compress(Register result, Register src, Register dst, Register cnt, - Register tmp, bool precise); + Register tmp, bool precise, bool toASCII); // Inflate byte[] to char[]. unsigned int string_inflate_trot(Register src, Register dst, Register cnt, Register tmp); diff --git a/src/hotspot/cpu/s390/matcher_s390.hpp b/src/hotspot/cpu/s390/matcher_s390.hpp index d95e3c17f43..ac55bd84dff 100644 --- a/src/hotspot/cpu/s390/matcher_s390.hpp +++ b/src/hotspot/cpu/s390/matcher_s390.hpp @@ -1,5 +1,6 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022 SAP SE. 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 @@ -150,6 +151,6 @@ } // Implements a variant of EncodeISOArrayNode that encode ASCII only - static const bool supports_encode_ascii_array = false; + static const bool supports_encode_ascii_array = true; #endif // CPU_S390_MATCHER_S390_HPP diff --git a/src/hotspot/cpu/s390/s390.ad b/src/hotspot/cpu/s390/s390.ad index 8a6e62a809b..74ad8ef40d3 100644 --- a/src/hotspot/cpu/s390/s390.ad +++ b/src/hotspot/cpu/s390/s390.ad @@ -1,6 +1,6 @@ // -// Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. -// Copyright (c) 2017, 2020 SAP SE. All rights reserved. +// Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2017, 2022 SAP SE. 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 @@ -10230,7 +10230,7 @@ instruct string_compress(iRegP src, iRegP dst, iRegI result, iRegI len, iRegI tm format %{ "String Compress $src->$dst($len) -> $result" %} ins_encode %{ __ string_compress($result$$Register, $src$$Register, $dst$$Register, $len$$Register, - $tmp$$Register, false); + $tmp$$Register, false, false); %} ins_pipe(pipe_class_dummy); %} @@ -10291,10 +10291,24 @@ instruct encode_iso_array(iRegP src, iRegP dst, iRegI result, iRegI len, iRegI t match(Set result (EncodeISOArray src (Binary dst len))); effect(TEMP_DEF result, TEMP tmp, KILL cr); // R0, R1 are killed, too. ins_cost(300); - format %{ "Encode array $src->$dst($len) -> $result" %} + format %{ "Encode iso array $src->$dst($len) -> $result" %} ins_encode %{ __ string_compress($result$$Register, $src$$Register, $dst$$Register, $len$$Register, - $tmp$$Register, true); + $tmp$$Register, true, false); + %} + ins_pipe(pipe_class_dummy); +%} + +// encode char[] to byte[] in ASCII +instruct encode_ascii_array(iRegP src, iRegP dst, iRegI result, iRegI len, iRegI tmp, flagsReg cr) %{ + predicate(((EncodeISOArrayNode*)n)->is_ascii()); + match(Set result (EncodeISOArray src (Binary dst len))); + effect(TEMP_DEF result, TEMP tmp, KILL cr); // R0, R1 are killed, too. + ins_cost(300); + format %{ "Encode ascii array $src->$dst($len) -> $result" %} + ins_encode %{ + __ string_compress($result$$Register, $src$$Register, $dst$$Register, $len$$Register, + $tmp$$Register, true, true); %} ins_pipe(pipe_class_dummy); %} -- GitLab From 28796cbd1d15de678b80295418f5d1f9f59176a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Jeli=C5=84ski?= Date: Tue, 25 Jan 2022 11:10:51 +0000 Subject: [PATCH 277/564] 8163921: HttpURLConnection default Accept header is malformed according to HTTP/1.1 RFC Reviewed-by: dfuchs, michaelm --- .../net/www/protocol/http/HttpURLConnection.java | 5 ++--- test/jdk/sun/net/www/B8185898.java | 16 ++++++++-------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java b/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java index cba385f04fa..c3d33014409 100644 --- a/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java +++ b/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2022, 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 @@ -288,8 +288,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection { } static final String httpVersion = "HTTP/1.1"; - static final String acceptString = - "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2"; + static final String acceptString = "*/*"; // the following http request headers should NOT have their values // returned for security reasons. diff --git a/test/jdk/sun/net/www/B8185898.java b/test/jdk/sun/net/www/B8185898.java index a50c6f93c7e..cfa54e15a52 100644 --- a/test/jdk/sun/net/www/B8185898.java +++ b/test/jdk/sun/net/www/B8185898.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, 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 8185898 + * @bug 8185898 8163921 * @modules java.base/sun.net.www * @library /test/lib * @run main/othervm B8185898 @@ -143,32 +143,32 @@ public class B8185898 { // {{inputString1, expectedToString1, expectedPrint1}, {...}} String[][] strings = { {"HTTP/1.1 200 OK\r\n" - + "Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2\r\n" + + "Accept: */*\r\n" + "Connection: keep-alive\r\n" + "Host: 127.0.0.1:12345\r\n" + "User-agent: Java/12\r\n\r\nfoooo", "pairs: {null: HTTP/1.1 200 OK}" - + "{Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2}" + + "{Accept: */*}" + "{Connection: keep-alive}" + "{Host: 127.0.0.1:12345}" + "{User-agent: Java/12}", - "Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2\r\n" + "Accept: */*\r\n" + "Connection: keep-alive\r\n" + "Host: 127.0.0.1:12345\r\n" + "User-agent: Java/12\r\n\r\n"}, {"HTTP/1.1 200 OK\r\n" - + "Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2\r\n" + + "Accept: */*\r\n" + "Connection: keep-alive\r\n" + "Host: 127.0.0.1:12345\r\n" + "User-agent: Java/12\r\n" + "X-Header:\r\n\r\n", "pairs: {null: HTTP/1.1 200 OK}" - + "{Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2}" + + "{Accept: */*}" + "{Connection: keep-alive}" + "{Host: 127.0.0.1:12345}" + "{User-agent: Java/12}" + "{X-Header: }", - "Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2\r\n" + "Accept: */*\r\n" + "Connection: keep-alive\r\n" + "Host: 127.0.0.1:12345\r\n" + "User-agent: Java/12\r\n" -- GitLab From 36fbec78be837fe1defb72f39c6e3f2b5135fddf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Jeli=C5=84ski?= Date: Tue, 25 Jan 2022 11:15:47 +0000 Subject: [PATCH 278/564] 8280241: (aio) AsynchronousSocketChannel init fails in IPv6 only Windows env Reviewed-by: dfuchs, alanb --- .../libnio/ch/WindowsAsynchronousServerSocketChannelImpl.c | 6 +++++- .../native/libnio/ch/WindowsAsynchronousSocketChannelImpl.c | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/java.base/windows/native/libnio/ch/WindowsAsynchronousServerSocketChannelImpl.c b/src/java.base/windows/native/libnio/ch/WindowsAsynchronousServerSocketChannelImpl.c index a08f3a3564f..340bbb9c8de 100644 --- a/src/java.base/windows/native/libnio/ch/WindowsAsynchronousServerSocketChannelImpl.c +++ b/src/java.base/windows/native/libnio/ch/WindowsAsynchronousServerSocketChannelImpl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2022, 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 @@ -69,6 +69,10 @@ Java_sun_nio_ch_WindowsAsynchronousServerSocketChannelImpl_initIDs(JNIEnv* env, DWORD dwBytes; s = socket(AF_INET, SOCK_STREAM, 0); + if (s == INVALID_SOCKET && WSAGetLastError() == WSAEAFNOSUPPORT) { + /* IPv4 unavailable... try IPv6 instead */ + s = socket(AF_INET6, SOCK_STREAM, 0); + } if (s == INVALID_SOCKET) { JNU_ThrowIOExceptionWithLastError(env, "socket failed"); return; diff --git a/src/java.base/windows/native/libnio/ch/WindowsAsynchronousSocketChannelImpl.c b/src/java.base/windows/native/libnio/ch/WindowsAsynchronousSocketChannelImpl.c index 40b8d8ba8dc..6b1fa64e708 100644 --- a/src/java.base/windows/native/libnio/ch/WindowsAsynchronousSocketChannelImpl.c +++ b/src/java.base/windows/native/libnio/ch/WindowsAsynchronousSocketChannelImpl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2022, 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 @@ -66,6 +66,10 @@ Java_sun_nio_ch_WindowsAsynchronousSocketChannelImpl_initIDs(JNIEnv* env, jclass DWORD dwBytes; s = socket(AF_INET, SOCK_STREAM, 0); + if (s == INVALID_SOCKET && WSAGetLastError() == WSAEAFNOSUPPORT) { + /* IPv4 unavailable... try IPv6 instead */ + s = socket(AF_INET6, SOCK_STREAM, 0); + } if (s == INVALID_SOCKET) { JNU_ThrowIOExceptionWithLastError(env, "socket failed"); return; -- GitLab From 4503d0431c0dd4d177cf5eb4df592f26b9d372bb Mon Sep 17 00:00:00 2001 From: Hamlin Li Date: Tue, 25 Jan 2022 12:11:21 +0000 Subject: [PATCH 279/564] 8280375: G1: Tighten mem region limit in G1RebuildRemSetHeapRegionClosure Reviewed-by: tschatzl, ayang --- src/hotspot/share/gc/g1/g1RemSet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/gc/g1/g1RemSet.cpp b/src/hotspot/share/gc/g1/g1RemSet.cpp index 603ddbc1e26..13977348825 100644 --- a/src/hotspot/share/gc/g1/g1RemSet.cpp +++ b/src/hotspot/share/gc/g1/g1RemSet.cpp @@ -1958,7 +1958,7 @@ public: HeapWord* const top_at_mark_start = hr->prev_top_at_mark_start(); HeapWord* cur = hr->bottom(); - while (cur < hr->end()) { + while (true) { // After every iteration (yield point) we need to check whether the region's // TARS changed due to e.g. eager reclaim. HeapWord* const top_at_rebuild_start = _cm->top_at_rebuild_start(region_idx); -- GitLab From 496baada1021eecae03e737afe838ad6d383cba9 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Tue, 25 Jan 2022 14:09:53 +0000 Subject: [PATCH 280/564] 8280030: [REDO] Parallel: More precise boundary in ObjectStartArray::object_starts_in_range Reviewed-by: sjohanss, tschatzl --- src/hotspot/share/gc/parallel/objectStartArray.cpp | 9 ++++++++- src/hotspot/share/gc/parallel/objectStartArray.hpp | 8 +++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/hotspot/share/gc/parallel/objectStartArray.cpp b/src/hotspot/share/gc/parallel/objectStartArray.cpp index 827ff73fb58..3e4820aa941 100644 --- a/src/hotspot/share/gc/parallel/objectStartArray.cpp +++ b/src/hotspot/share/gc/parallel/objectStartArray.cpp @@ -132,8 +132,15 @@ bool ObjectStartArray::object_starts_in_range(HeapWord* start_addr, "Range is wrong. start_addr (" PTR_FORMAT ") is after end_addr (" PTR_FORMAT ")", p2i(start_addr), p2i(end_addr)); + assert(is_aligned(start_addr, _card_size), "precondition"); + + if (start_addr == end_addr) { + // No objects in empty range. + return false; + } + jbyte* start_block = block_for_addr(start_addr); - jbyte* end_block = block_for_addr(end_addr); + jbyte* end_block = block_for_addr(end_addr - 1); for (jbyte* block = start_block; block <= end_block; block++) { if (*block != clean_block) { diff --git a/src/hotspot/share/gc/parallel/objectStartArray.hpp b/src/hotspot/share/gc/parallel/objectStartArray.hpp index be91b51cd94..06005fc0075 100644 --- a/src/hotspot/share/gc/parallel/objectStartArray.hpp +++ b/src/hotspot/share/gc/parallel/objectStartArray.hpp @@ -165,9 +165,11 @@ class ObjectStartArray : public CHeapObj { return *block != clean_block; } - // Return true if an object starts in the range of heap addresses. - // If an object starts at an address corresponding to - // "start", the method will return true. + // Return true iff an object starts in + // [start_addr, end_addr_aligned_up) + // where + // end_addr_aligned_up = align_up(end_addr, _card_size) + // Precondition: start_addr is card-size aligned bool object_starts_in_range(HeapWord* start_addr, HeapWord* end_addr) const; }; -- GitLab From fe77250fa450ec803d2818dc90c5bf156521d537 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Jeli=C5=84ski?= Date: Tue, 25 Jan 2022 14:41:41 +0000 Subject: [PATCH 281/564] 8280414: Memory leak in DefaultProxySelector Reviewed-by: dfuchs --- .../native/libnet/DefaultProxySelector.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/java.base/windows/native/libnet/DefaultProxySelector.c b/src/java.base/windows/native/libnet/DefaultProxySelector.c index d9107e738b3..6b91874eda1 100644 --- a/src/java.base/windows/native/libnet/DefaultProxySelector.c +++ b/src/java.base/windows/native/libnet/DefaultProxySelector.c @@ -104,7 +104,6 @@ static int createProxyList(LPWSTR win_proxy, const WCHAR *pproto, list_item **he int nr_elems = 0; wchar_t *context = NULL; wchar_t *current_proxy = NULL; - BOOL error = FALSE; /* * The proxy server list contains one or more of the following strings @@ -116,7 +115,6 @@ static int createProxyList(LPWSTR win_proxy, const WCHAR *pproto, list_item **he LPWSTR pport; LPWSTR phost; int portVal = 0; - wchar_t *next_proxy = NULL; list_item *proxy = NULL; wchar_t* pos = NULL; @@ -292,7 +290,6 @@ Java_sun_net_spi_DefaultProxySelector_getSystemProxies(JNIEnv *env, } if (win_proxy != NULL) { - wchar_t *context = NULL; int defport = 0; int nr_elems = 0; @@ -315,27 +312,28 @@ Java_sun_net_spi_DefaultProxySelector_getSystemProxies(JNIEnv *env, nr_elems = createProxyList(win_proxy, lpProto, &head); if (nr_elems != 0 && head != NULL) { int index = 0; + list_item *current = head; proxy_array = (*env)->NewObjectArray(env, nr_elems, proxy_class, NULL); if (proxy_array == NULL || (*env)->ExceptionCheck(env)) { goto noproxy; } - while (head != NULL && index < nr_elems) { + while (current != NULL && index < nr_elems) { jstring jhost; jobject isa; jobject proxy; - if (head->host != NULL && proxy_array != NULL) { + if (current->host != NULL && proxy_array != NULL) { /* Let's create the appropriate Proxy object then. */ - if (head->port == 0) { - head->port = defport; + if (current->port == 0) { + current->port = defport; } - jhost = (*env)->NewString(env, head->host, (jsize)wcslen(head->host)); + jhost = (*env)->NewString(env, current->host, (jsize)wcslen(current->host)); if (jhost == NULL || (*env)->ExceptionCheck(env)) { proxy_array = NULL; } isa = (*env)->CallStaticObjectMethod(env, isaddr_class, isaddr_createUnresolvedID, jhost, - head->port); + current->port); if (isa == NULL || (*env)->ExceptionCheck(env)) { proxy_array = NULL; } @@ -349,7 +347,7 @@ Java_sun_net_spi_DefaultProxySelector_getSystemProxies(JNIEnv *env, } index++; } - head = head->next; + current = current->next; } } } -- GitLab From 674a97b27ef621e7b54c13c121c625f91df5ee60 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Tue, 25 Jan 2022 16:27:30 +0000 Subject: [PATCH 282/564] 8280396: G1: Full gc mark stack draining should prefer to make work available to other threads Reviewed-by: sjohanss, ayang --- src/hotspot/share/gc/g1/g1FullGCMarker.hpp | 12 +++-- .../share/gc/g1/g1FullGCMarker.inline.hpp | 46 +++++++++++++------ 2 files changed, 40 insertions(+), 18 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1FullGCMarker.hpp b/src/hotspot/share/gc/g1/g1FullGCMarker.hpp index ec7f029b7ce..2d935d863c5 100644 --- a/src/hotspot/share/gc/g1/g1FullGCMarker.hpp +++ b/src/hotspot/share/gc/g1/g1FullGCMarker.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -71,8 +71,6 @@ class G1FullGCMarker : public CHeapObj { G1RegionMarkStatsCache _mark_stats_cache; inline bool is_empty(); - inline bool pop_object(oop& obj); - inline bool pop_objarray(ObjArrayTask& array); inline void push_objarray(oop obj, size_t index); inline bool mark_object(oop obj); @@ -80,6 +78,14 @@ class G1FullGCMarker : public CHeapObj { inline void follow_object(oop obj); inline void follow_array(objArrayOop array); inline void follow_array_chunk(objArrayOop array, int index); + + inline void drain_oop_stack(); + // Transfer contents from the objArray task queue overflow stack to the shared + // objArray stack. + // Returns true and a valid task if there has not been enough space in the shared + // objArray stack, otherwise the task is invalid. + inline bool transfer_objArray_overflow_stack(ObjArrayTask& task); + public: G1FullGCMarker(G1FullCollector* collector, uint worker_id, diff --git a/src/hotspot/share/gc/g1/g1FullGCMarker.inline.hpp b/src/hotspot/share/gc/g1/g1FullGCMarker.inline.hpp index c261c150e46..a68bae5ced6 100644 --- a/src/hotspot/share/gc/g1/g1FullGCMarker.inline.hpp +++ b/src/hotspot/share/gc/g1/g1FullGCMarker.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -91,20 +91,12 @@ inline bool G1FullGCMarker::is_empty() { return _oop_stack.is_empty() && _objarray_stack.is_empty(); } -inline bool G1FullGCMarker::pop_object(oop& oop) { - return _oop_stack.pop_overflow(oop) || _oop_stack.pop_local(oop); -} - inline void G1FullGCMarker::push_objarray(oop obj, size_t index) { ObjArrayTask task(obj, index); assert(task.is_valid(), "bad ObjArrayTask"); _objarray_stack.push(task); } -inline bool G1FullGCMarker::pop_objarray(ObjArrayTask& arr) { - return _objarray_stack.pop_overflow(arr) || _objarray_stack.pop_local(arr); -} - inline void G1FullGCMarker::follow_array(objArrayOop array) { follow_klass(array->klass()); // Don't push empty arrays to avoid unnecessary work. @@ -159,16 +151,40 @@ inline void G1FullGCMarker::follow_object(oop obj) { } } -void G1FullGCMarker::drain_stack() { - do { - oop obj; - while (pop_object(obj)) { +inline void G1FullGCMarker::drain_oop_stack() { + oop obj; + while (_oop_stack.pop_overflow(obj)) { + if (!_oop_stack.try_push_to_taskqueue(obj)) { assert(_bitmap->is_marked(obj), "must be marked"); follow_object(obj); } - // Process ObjArrays one at a time to avoid marking stack bloat. + } + while (_oop_stack.pop_local(obj)) { + assert(_bitmap->is_marked(obj), "must be marked"); + follow_object(obj); + } +} + +inline bool G1FullGCMarker::transfer_objArray_overflow_stack(ObjArrayTask& task) { + // It is desirable to move as much as possible work from the overflow queue to + // the shared queue as quickly as possible. + while (_objarray_stack.pop_overflow(task)) { + if (!_objarray_stack.try_push_to_taskqueue(task)) { + return true; + } + } + return false; +} + +void G1FullGCMarker::drain_stack() { + do { + // First, drain regular oop stack. + drain_oop_stack(); + + // Then process ObjArrays one at a time to avoid marking stack bloat. ObjArrayTask task; - if (pop_objarray(task)) { + if (transfer_objArray_overflow_stack(task) || + _objarray_stack.pop_local(task)) { follow_array_chunk(objArrayOop(task.obj()), task.index()); } } while (!is_empty()); -- GitLab From f4575e4052bf66f1259c626e01a74d3ac593e645 Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Tue, 25 Jan 2022 18:02:18 +0000 Subject: [PATCH 283/564] 8279946: (ch) java.nio.channels.FileChannel tryLock and write methods are missing @throws NonWritableChannelException Reviewed-by: alanb --- .../java/nio/channels/FileChannel.java | 33 ++++++++++++++++--- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/src/java.base/share/classes/java/nio/channels/FileChannel.java b/src/java.base/share/classes/java/nio/channels/FileChannel.java index 2ea213b3509..d8fee6ca995 100644 --- a/src/java.base/share/classes/java/nio/channels/FileChannel.java +++ b/src/java.base/share/classes/java/nio/channels/FileChannel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2022, 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,13 +25,16 @@ package java.nio.channels; -import java.io.*; +import java.io.IOException; import java.nio.ByteBuffer; import java.nio.MappedByteBuffer; import java.nio.channels.spi.AbstractInterruptibleChannel; -import java.nio.file.*; +import java.nio.file.FileAlreadyExistsException; +import java.nio.file.OpenOption; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; import java.nio.file.attribute.FileAttribute; -import java.nio.file.spi.*; +import java.nio.file.spi.FileSystemProvider; import java.util.Set; import java.util.HashSet; import java.util.Collections; @@ -403,6 +406,9 @@ public abstract class FileChannel * with the number of bytes actually written. Otherwise this method * behaves exactly as specified by the {@link WritableByteChannel} * interface.

    + * + * @throws NonWritableChannelException + * If this channel was not opened for writing */ public abstract int write(ByteBuffer src) throws IOException; @@ -417,6 +423,9 @@ public abstract class FileChannel * with the number of bytes actually written. Otherwise this method * behaves exactly as specified in the {@link GatheringByteChannel} * interface.

    + * + * @throws NonWritableChannelException + * If this channel was not opened for writing */ public abstract long write(ByteBuffer[] srcs, int offset, int length) throws IOException; @@ -431,6 +440,9 @@ public abstract class FileChannel * with the number of bytes actually written. Otherwise this method * behaves exactly as specified in the {@link GatheringByteChannel} * interface.

    + * + * @throws NonWritableChannelException + * If this channel was not opened for writing */ public final long write(ByteBuffer[] srcs) throws IOException { return write(srcs, 0, srcs.length); @@ -1030,7 +1042,7 @@ public abstract class FileChannel * region * * @throws NonReadableChannelException - * If {@code shared} is {@code true} this channel was not + * If {@code shared} is {@code true} but this channel was not * opened for reading * * @throws NonWritableChannelException @@ -1148,6 +1160,14 @@ public abstract class FileChannel * blocked in this method and is attempting to lock an overlapping * region of the same file * + * @throws NonReadableChannelException + * If {@code shared} is {@code true} but this channel was not + * opened for reading + * + * @throws NonWritableChannelException + * If {@code shared} is {@code false} but this channel was not + * opened for writing + * * @throws IOException * If some other I/O error occurs * @@ -1180,6 +1200,9 @@ public abstract class FileChannel * blocked in this method and is attempting to lock an overlapping * region * + * @throws NonWritableChannelException + * If this channel was not opened for writing + * * @throws IOException * If some other I/O error occurs * -- GitLab From cbe8395ace3230dc599c7f082e3524a861b2da8e Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Tue, 25 Jan 2022 18:15:37 +0000 Subject: [PATCH 284/564] 8280168: Add Objects.toIdentityString Reviewed-by: alanb, mchung, rriggs, smarks --- .../java/lang/invoke/MethodHandleProxies.java | 2 +- .../share/classes/java/util/Objects.java | 26 ++++++++++++- .../java/util/Objects/BasicObjectsTest.java | 37 +++++++++++++++++-- 3 files changed, 60 insertions(+), 5 deletions(-) diff --git a/src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java b/src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java index 784d672ff8f..c1c34185ffb 100644 --- a/src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java @@ -292,7 +292,7 @@ public class MethodHandleProxies { private static Object callObjectMethod(Object self, Method m, Object[] args) { assert(isObjectMethod(m)) : m; return switch (m.getName()) { - case "toString" -> self.getClass().getName() + "@" + Integer.toHexString(self.hashCode()); + case "toString" -> java.util.Objects.toIdentityString(self); case "hashCode" -> System.identityHashCode(self); case "equals" -> (self == args[0]); default -> null; diff --git a/src/java.base/share/classes/java/util/Objects.java b/src/java.base/share/classes/java/util/Objects.java index c32a67441da..0b727d6310b 100644 --- a/src/java.base/share/classes/java/util/Objects.java +++ b/src/java.base/share/classes/java/util/Objects.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2022, 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 @@ -164,6 +164,30 @@ public final class Objects { return (o != null) ? o.toString() : nullDefault; } + /** + * {@return a string equivalent to the string returned by {@code + * Object.toString} if that method and {@code hashCode} are not + * overridden} + * + * @implNote + * This method constructs a string for an object without calling + * any overridable methods of the object. + * + * @implSpec + * The method returns a string equivalent to:
    + * {@code o.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(o))} + * + * @param o an object + * @throws NullPointerException if the argument is null + * @see Object#toString + * @see System#identityHashCode(Object) + * @since 19 + */ + public static String toIdentityString(Object o) { + requireNonNull(o); + return o.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(o)); + } + /** * Returns 0 if the arguments are identical and {@code * c.compare(a, b)} otherwise. diff --git a/test/jdk/java/util/Objects/BasicObjectsTest.java b/test/jdk/java/util/Objects/BasicObjectsTest.java index a7636ef11d5..51268d4cbaf 100644 --- a/test/jdk/java/util/Objects/BasicObjectsTest.java +++ b/test/jdk/java/util/Objects/BasicObjectsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2022, 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,9 +23,8 @@ /* * @test - * @bug 6797535 6889858 6891113 8013712 8011800 8014365 + * @bug 6797535 6889858 6891113 8013712 8011800 8014365 8280168 * @summary Basic tests for methods in java.util.Objects - * @author Joseph D. Darcy */ import java.util.*; @@ -40,6 +39,7 @@ public class BasicObjectsTest { errors += testHash(); errors += testToString(); errors += testToString2(); + errors += testToIdentityString(); errors += testCompare(); errors += testRequireNonNull(); errors += testIsNull(); @@ -134,6 +134,37 @@ public class BasicObjectsTest { return errors; } + private static int testToIdentityString() { + int errors = 0; + // Test null behavior + try { + Objects.toIdentityString(null); + errors++; + } catch (NullPointerException npe) { + ; // Expected + } + // Behavior on typical objects + Object o = new Object(){}; + errors += (Objects.toIdentityString(o).equals(o.toString()))? 0 : 1; + // Verify object's toString *not* called + Object badToString = new Object() { + @Override + public String toString() { + throw new RuntimeException(); + } + }; + Objects.toIdentityString(badToString); + // Verify object's hashCode *not* called + Object badHashCode = new Object() { + @Override + public int hashCode() { + throw new RuntimeException("0xDEADBEFF"); + } + }; + Objects.toIdentityString(badHashCode); + return errors; + } + private static int testCompare() { int errors = 0; String[] values = {"e. e. cummings", "zzz"}; -- GitLab From cebaad1c94c301304fd146526cac95bfeaac66bf Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Tue, 25 Jan 2022 19:22:07 +0000 Subject: [PATCH 285/564] 8280041: Retry loop issues in java.io.ClassCache Co-authored-by: Peter Levart Reviewed-by: rkennke, rriggs, plevart --- .../share/classes/java/io/ClassCache.java | 53 ++++++++++++++----- .../java/io/ClassCache/ContinuousGCTest.java | 50 +++++++++++++++++ .../jdk/java/io/ClassCache/NullValueTest.java | 42 +++++++++++++++ .../java.base/java/io/NameClassCache.java | 35 ++++++++++++ .../java.base/java/io/NullClassCache.java | 34 ++++++++++++ 5 files changed, 202 insertions(+), 12 deletions(-) create mode 100644 test/jdk/java/io/ClassCache/ContinuousGCTest.java create mode 100644 test/jdk/java/io/ClassCache/NullValueTest.java create mode 100644 test/jdk/java/io/ClassCache/java.base/java/io/NameClassCache.java create mode 100644 test/jdk/java/io/ClassCache/java.base/java/io/NullClassCache.java diff --git a/src/java.base/share/classes/java/io/ClassCache.java b/src/java.base/share/classes/java/io/ClassCache.java index a3901d479ef..48e7a36c05a 100644 --- a/src/java.base/share/classes/java/io/ClassCache.java +++ b/src/java.base/share/classes/java/io/ClassCache.java @@ -28,6 +28,7 @@ package java.io; import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; import java.lang.ref.SoftReference; +import java.util.Objects; // Maps Class instances to values of type T. Under memory pressure, the // mapping is released (under soft references GC policy) and would be @@ -38,19 +39,29 @@ abstract class ClassCache { private static class CacheRef extends SoftReference { private final Class type; + private T strongReferent; CacheRef(T referent, ReferenceQueue queue, Class type) { super(referent, queue); this.type = type; + this.strongReferent = referent; } Class getType() { return type; } + + T getStrong() { + return strongReferent; + } + + void clearStrong() { + strongReferent = null; + } } private final ReferenceQueue queue; - private final ClassValue> map; + private final ClassValue> map; protected abstract T computeValue(Class cl); @@ -58,23 +69,41 @@ abstract class ClassCache { queue = new ReferenceQueue<>(); map = new ClassValue<>() { @Override - protected SoftReference computeValue(Class type) { - return new CacheRef<>(ClassCache.this.computeValue(type), queue, type); + protected CacheRef computeValue(Class type) { + T v = ClassCache.this.computeValue(type); + Objects.requireNonNull(v); + return new CacheRef<>(v, queue, type); } }; } T get(Class cl) { - processQueue(); - T val; - do { - SoftReference ref = map.get(cl); - val = ref.get(); - if (val == null) { - map.remove(cl); + while (true) { + processQueue(); + + CacheRef ref = map.get(cl); + + // Case 1: A recently created CacheRef. + // We might still have strong referent, and can return it. + // This guarantees progress for at least one thread on every CacheRef. + // Clear the strong referent before returning to make the cache soft. + T strongVal = ref.getStrong(); + if (strongVal != null) { + ref.clearStrong(); + return strongVal; + } + + // Case 2: Older or recently cleared CacheRef. + // Check if its soft referent is still available, and return it. + T val = ref.get(); + if (val != null) { + return val; } - } while (val == null); - return val; + + // Case 3: The reference was cleared. + // Clear the mapping and retry. + map.remove(cl); + } } private void processQueue() { diff --git a/test/jdk/java/io/ClassCache/ContinuousGCTest.java b/test/jdk/java/io/ClassCache/ContinuousGCTest.java new file mode 100644 index 00000000000..681663029e4 --- /dev/null +++ b/test/jdk/java/io/ClassCache/ContinuousGCTest.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2022, Red Hat, Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.NameClassCache; + +/** + * @test + * @bug 8280041 + * @summary Sanity test for ClassCache under continuous GC + * @compile/module=java.base java/io/NameClassCache.java + * @run main ContinuousGCTest + */ +public class ContinuousGCTest { + static final NameClassCache CACHE = new NameClassCache(); + static final String VALUE = "ClassCache-ContinuousGCTest"; + + public static void main(String... args) throws Throwable { + for (int c = 0; c < 1000; c++) { + test(); + System.gc(); + } + } + + public static void test() { + String cached = CACHE.get(ContinuousGCTest.class); + if (!cached.equals(VALUE)) { + throw new IllegalStateException("Cache failure, got: " + cached); + } + } +} diff --git a/test/jdk/java/io/ClassCache/NullValueTest.java b/test/jdk/java/io/ClassCache/NullValueTest.java new file mode 100644 index 00000000000..22b41fa071d --- /dev/null +++ b/test/jdk/java/io/ClassCache/NullValueTest.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2022, Red Hat, Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.NullClassCache; + +/** + * @test + * @bug 8280041 + * @summary Test that ClassCache throws on trying to pass null value + * @compile/module=java.base java/io/NullClassCache.java + * @run main NullValueTest + */ +public class NullValueTest { + public static void main(String... args) throws Throwable { + try { + new NullClassCache().get(Object.class); + throw new IllegalStateException("Should have failed"); + } catch (NullPointerException npe) { + // Expected + } + } +} diff --git a/test/jdk/java/io/ClassCache/java.base/java/io/NameClassCache.java b/test/jdk/java/io/ClassCache/java.base/java/io/NameClassCache.java new file mode 100644 index 00000000000..ff2149fc6a2 --- /dev/null +++ b/test/jdk/java/io/ClassCache/java.base/java/io/NameClassCache.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2022, Red Hat, Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.io; + +public class NameClassCache extends ClassCache { + protected String computeValue(Class cl) { + // Return string that is not interned and specific to class + return "ClassCache-" + cl.getName(); + } + + public String get(Class cl) { + return super.get(cl); + } +} diff --git a/test/jdk/java/io/ClassCache/java.base/java/io/NullClassCache.java b/test/jdk/java/io/ClassCache/java.base/java/io/NullClassCache.java new file mode 100644 index 00000000000..58c92ef1399 --- /dev/null +++ b/test/jdk/java/io/ClassCache/java.base/java/io/NullClassCache.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2022, Red Hat, Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.io; + +public class NullClassCache extends ClassCache { + protected Object computeValue(Class cl) { + return null; + } + + public Object get(Class cl) { + return super.get(cl); + } +} -- GitLab From 76fe03fe01a7c824e2e9263de95b8bcbb4b9d752 Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Tue, 25 Jan 2022 19:23:02 +0000 Subject: [PATCH 286/564] 8280166: Extend java/lang/instrument/GetObjectSizeIntrinsicsTest.java test cases Reviewed-by: sspitsyn, lmesnik --- .../GetObjectSizeIntrinsicsTest.java | 116 ++++++++++++++---- 1 file changed, 89 insertions(+), 27 deletions(-) diff --git a/test/jdk/java/lang/instrument/GetObjectSizeIntrinsicsTest.java b/test/jdk/java/lang/instrument/GetObjectSizeIntrinsicsTest.java index 1417eb427a0..975adb23cf5 100644 --- a/test/jdk/java/lang/instrument/GetObjectSizeIntrinsicsTest.java +++ b/test/jdk/java/lang/instrument/GetObjectSizeIntrinsicsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Red Hat, Inc. All rights reserved. + * Copyright (c) 2020, 2022, Red Hat, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -264,6 +264,39 @@ * -javaagent:basicAgent.jar GetObjectSizeIntrinsicsTest GetObjectSizeIntrinsicsTest */ +/* + * @test + * @summary Test for fInst.getObjectSize with large arrays + * @library /test/lib + * @requires vm.bits == 64 + * @requires vm.debug + * @requires os.maxMemory >= 10G + * + * @build sun.hotspot.WhiteBox + * @run build GetObjectSizeIntrinsicsTest + * @run shell MakeJAR.sh basicAgent + * + * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox + * + * @run main/othervm -Xmx8g + * -XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure -XX:+WhiteBoxAPI -Xbootclasspath/a:. + * -XX:ObjectAlignmentInBytes=32 + * -Xint + * -javaagent:basicAgent.jar GetObjectSizeIntrinsicsTest GetObjectSizeIntrinsicsTest large + * + * @run main/othervm -Xmx8g + * -XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure -XX:+WhiteBoxAPI -Xbootclasspath/a:. + * -XX:ObjectAlignmentInBytes=32 + * -Xbatch -XX:TieredStopAtLevel=1 + * -javaagent:basicAgent.jar GetObjectSizeIntrinsicsTest GetObjectSizeIntrinsicsTest large + * + * @run main/othervm -Xmx8g + * -XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure -XX:+WhiteBoxAPI -Xbootclasspath/a:. + * -XX:ObjectAlignmentInBytes=32 + * -Xbatch -XX:-TieredCompilation + * -javaagent:basicAgent.jar GetObjectSizeIntrinsicsTest GetObjectSizeIntrinsicsTest large + */ + import java.util.*; import jdk.test.lib.Platform; @@ -271,18 +304,26 @@ import sun.hotspot.WhiteBox; public class GetObjectSizeIntrinsicsTest extends ASimpleInstrumentationTestCase { - static final Boolean compressedOops = WhiteBox.getWhiteBox().getBooleanVMFlag("UseCompressedOops"); - static final int REF_SIZE = (compressedOops == null || compressedOops == true) ? 4 : 8; + static final Boolean COMPRESSED_OOPS = WhiteBox.getWhiteBox().getBooleanVMFlag("UseCompressedOops"); + static final long REF_SIZE = (COMPRESSED_OOPS == null || COMPRESSED_OOPS == true) ? 4 : 8; static final Long align = WhiteBox.getWhiteBox().getIntxVMFlag("ObjectAlignmentInBytes"); static final int OBJ_ALIGN = (align == null ? 8 : align.intValue()); - public GetObjectSizeIntrinsicsTest(String name) { + static final int SMALL_ARRAY_SIZE = 1024; + + // With int[] arrays, this overflows 4G boundary + static final int LARGE_ARRAY_SIZE = 1024*1024*1024 + 1024; + + final String mode; + + public GetObjectSizeIntrinsicsTest(String name, String mode) { super(name); + this.mode = mode; } public static void main(String[] args)throws Throwable { - new GetObjectSizeIntrinsicsTest(args[0]).runTest(); + new GetObjectSizeIntrinsicsTest(args[0], (args.length >= 2 ? args[1] : "")).runTest(); } public static final int ITERS = 200_000; @@ -312,30 +353,35 @@ public class GetObjectSizeIntrinsicsTest extends ASimpleInstrumentationTestCase testSize_localObject(); testSize_fieldObject(); - testSize_newSmallByteArray(); - testSize_localSmallByteArray(); - testSize_fieldSmallByteArray(); + testSize_newSmallIntArray(); + testSize_localSmallIntArray(); + testSize_fieldSmallIntArray(); testSize_newSmallObjArray(); testSize_localSmallObjArray(); testSize_fieldSmallObjArray(); + if (mode.equals("large")) { + testSize_localLargeIntArray(); + testSize_localLargeObjArray(); + } + testNulls(); } - private static int roundUp(int v, int a) { + private static long roundUp(long v, long a) { return (v + a - 1) / a * a; } private void testSize_newObject() { - int expected = roundUp(Platform.is64bit() ? 16 : 8, OBJ_ALIGN); + long expected = roundUp(Platform.is64bit() ? 16 : 8, OBJ_ALIGN); for (int c = 0; c < ITERS; c++) { assertEquals(expected, fInst.getObjectSize(new Object())); } } private void testSize_localObject() { - int expected = roundUp(Platform.is64bit() ? 16 : 8, OBJ_ALIGN); + long expected = roundUp(Platform.is64bit() ? 16 : 8, OBJ_ALIGN); Object o = new Object(); for (int c = 0; c < ITERS; c++) { assertEquals(expected, fInst.getObjectSize(o)); @@ -345,60 +391,76 @@ public class GetObjectSizeIntrinsicsTest extends ASimpleInstrumentationTestCase static Object staticO = new Object(); private void testSize_fieldObject() { - int expected = roundUp(Platform.is64bit() ? 16 : 8, OBJ_ALIGN); + long expected = roundUp(Platform.is64bit() ? 16 : 8, OBJ_ALIGN); for (int c = 0; c < ITERS; c++) { assertEquals(expected, fInst.getObjectSize(staticO)); } } - private void testSize_newSmallByteArray() { - int expected = roundUp(1024 + 16, OBJ_ALIGN); + private void testSize_newSmallIntArray() { + long expected = roundUp(4L*SMALL_ARRAY_SIZE + 16, OBJ_ALIGN); for (int c = 0; c < ITERS; c++) { - assertEquals(expected, fInst.getObjectSize(new byte[1024])); + assertEquals(expected, fInst.getObjectSize(new int[SMALL_ARRAY_SIZE])); } } - private void testSize_localSmallByteArray() { - byte[] arr = new byte[1024]; - int expected = roundUp(arr.length + 16, OBJ_ALIGN); + private void testSize_localSmallIntArray() { + int[] arr = new int[SMALL_ARRAY_SIZE]; + long expected = roundUp(4L*SMALL_ARRAY_SIZE + 16, OBJ_ALIGN); for (int c = 0; c < ITERS; c++) { assertEquals(expected, fInst.getObjectSize(arr)); } } - static byte[] smallArr = new byte[1024]; + static int[] smallArr = new int[SMALL_ARRAY_SIZE]; - private void testSize_fieldSmallByteArray() { - int expected = roundUp(smallArr.length + 16, OBJ_ALIGN); + private void testSize_fieldSmallIntArray() { + long expected = roundUp(4L*SMALL_ARRAY_SIZE + 16, OBJ_ALIGN); for (int c = 0; c < ITERS; c++) { assertEquals(expected, fInst.getObjectSize(smallArr)); } } private void testSize_newSmallObjArray() { - int expected = roundUp(1024*REF_SIZE + 16, OBJ_ALIGN); + long expected = roundUp(REF_SIZE*SMALL_ARRAY_SIZE + 16, OBJ_ALIGN); for (int c = 0; c < ITERS; c++) { - assertEquals(expected, fInst.getObjectSize(new Object[1024])); + assertEquals(expected, fInst.getObjectSize(new Object[SMALL_ARRAY_SIZE])); } } private void testSize_localSmallObjArray() { - Object[] arr = new Object[1024]; - int expected = roundUp(arr.length*REF_SIZE + 16, OBJ_ALIGN); + Object[] arr = new Object[SMALL_ARRAY_SIZE]; + long expected = roundUp(REF_SIZE*SMALL_ARRAY_SIZE + 16, OBJ_ALIGN); for (int c = 0; c < ITERS; c++) { assertEquals(expected, fInst.getObjectSize(arr)); } } - static Object[] smallObjArr = new Object[1024]; + static Object[] smallObjArr = new Object[SMALL_ARRAY_SIZE]; private void testSize_fieldSmallObjArray() { - int expected = roundUp(smallArr.length*REF_SIZE + 16, OBJ_ALIGN); + long expected = roundUp(REF_SIZE*SMALL_ARRAY_SIZE + 16, OBJ_ALIGN); for (int c = 0; c < ITERS; c++) { assertEquals(expected, fInst.getObjectSize(smallObjArr)); } } + private void testSize_localLargeIntArray() { + int[] arr = new int[LARGE_ARRAY_SIZE]; + long expected = roundUp(4L*LARGE_ARRAY_SIZE + 16, OBJ_ALIGN); + for (int c = 0; c < ITERS; c++) { + assertEquals(expected, fInst.getObjectSize(arr)); + } + } + + private void testSize_localLargeObjArray() { + Object[] arr = new Object[LARGE_ARRAY_SIZE]; + long expected = roundUp(REF_SIZE*LARGE_ARRAY_SIZE + 16, OBJ_ALIGN); + for (int c = 0; c < ITERS; c++) { + assertEquals(expected, fInst.getObjectSize(arr)); + } + } + private void testNulls() { for (int c = 0; c < ITERS; c++) { try { -- GitLab From 841eae6f527c00115e0455c4e04f042c28a014bb Mon Sep 17 00:00:00 2001 From: Chris Plummer Date: Tue, 25 Jan 2022 19:26:11 +0000 Subject: [PATCH 287/564] 8269542: JDWP: EnableCollection support is no longer spec compliant after JDK-8255987 8258071: Fix for JDK-8255987 can be subverted with ObjectReference.EnableCollection Reviewed-by: dholmes, pliden --- .../share/native/libjdwp/commonRef.c | 73 ++++++++++++------- .../share/native/libjdwp/util.h | 5 +- 2 files changed, 48 insertions(+), 30 deletions(-) diff --git a/src/jdk.jdwp.agent/share/native/libjdwp/commonRef.c b/src/jdk.jdwp.agent/share/native/libjdwp/commonRef.c index bc7ddb660bf..d55c517332b 100644 --- a/src/jdk.jdwp.agent/share/native/libjdwp/commonRef.c +++ b/src/jdk.jdwp.agent/share/native/libjdwp/commonRef.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2022, 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 @@ -82,6 +82,14 @@ newSeqNum(void) return gdata->nextSeqNum++; } +/* Returns true if this is a strong reference, meaning that either or both of + isPinAll and isCommonPin are true. */ +static jboolean +isStrong(RefNode* node) +{ + return node->isPinAll || node->isCommonPin; +} + /* Create a fresh RefNode structure, create a weak ref and tag the object */ static RefNode * createNode(JNIEnv *env, jobject ref) @@ -89,7 +97,7 @@ createNode(JNIEnv *env, jobject ref) RefNode *node; jobject strongOrWeakRef; jvmtiError error; - jboolean pin = gdata->pinAllCount != 0; + jboolean pinAll = gdata->pinAllCount != 0; /* Could allocate RefNode's in blocks, not sure it would help much */ node = (RefNode*)jvmtiAllocate((int)sizeof(RefNode)); @@ -97,7 +105,7 @@ createNode(JNIEnv *env, jobject ref) return NULL; } - if (pin) { + if (pinAll) { /* Create strong reference to make sure we have a reference */ strongOrWeakRef = JNI_FUNC_PTR(env,NewGlobalRef)(env, ref); } else { @@ -116,7 +124,7 @@ createNode(JNIEnv *env, jobject ref) error = JVMTI_FUNC_PTR(gdata->jvmti, SetTag) (gdata->jvmti, strongOrWeakRef, ptr_to_jlong(node)); if ( error != JVMTI_ERROR_NONE ) { - if (pin) { + if (pinAll) { JNI_FUNC_PTR(env,DeleteGlobalRef)(env, strongOrWeakRef); } else { JNI_FUNC_PTR(env,DeleteWeakGlobalRef)(env, strongOrWeakRef); @@ -128,7 +136,8 @@ createNode(JNIEnv *env, jobject ref) /* Fill in RefNode */ node->ref = strongOrWeakRef; node->count = 1; - node->strongCount = pin ? 1 : 0; + node->isPinAll = pinAll; + node->isCommonPin = JNI_FALSE; node->seqNum = newSeqNum(); /* Count RefNode's created */ @@ -146,7 +155,7 @@ deleteNode(JNIEnv *env, RefNode *node) /* Clear tag */ (void)JVMTI_FUNC_PTR(gdata->jvmti,SetTag) (gdata->jvmti, node->ref, NULL_OBJECT_ID); - if (node->strongCount != 0) { + if (isStrong(node)) { JNI_FUNC_PTR(env,DeleteGlobalRef)(env, node->ref); } else { JNI_FUNC_PTR(env,DeleteWeakGlobalRef)(env, node->ref); @@ -158,9 +167,9 @@ deleteNode(JNIEnv *env, RefNode *node) /* Change a RefNode to have a strong reference */ static jobject -strengthenNode(JNIEnv *env, RefNode *node) +strengthenNode(JNIEnv *env, RefNode *node, jboolean isPinAll) { - if (node->strongCount == 0) { + if (!isStrong(node)) { jobject strongRef; strongRef = JNI_FUNC_PTR(env,NewGlobalRef)(env, node->ref); @@ -176,20 +185,27 @@ strengthenNode(JNIEnv *env, RefNode *node) if (strongRef != NULL) { JNI_FUNC_PTR(env,DeleteWeakGlobalRef)(env, node->ref); node->ref = strongRef; - node->strongCount = 1; + } else { + return NULL; } - return strongRef; + } + if (isPinAll) { + node->isPinAll = JNI_TRUE; } else { - node->strongCount++; - return node->ref; + node->isCommonPin = JNI_TRUE; } + return node->ref; } /* Change a RefNode to have a weak reference */ static jweak -weakenNode(JNIEnv *env, RefNode *node) +weakenNode(JNIEnv *env, RefNode *node, jboolean isUnpinAll) { - if (node->strongCount == 1) { + jboolean willStillBeStrong = (node->isPinAll && !isUnpinAll) || (node->isCommonPin && isUnpinAll); + + // If the node is strong, but the reason(s) for it being strong + // will no longer exist, then weaken it. + if (isStrong(node) && !willStillBeStrong) { jweak weakRef; weakRef = JNI_FUNC_PTR(env,NewWeakGlobalRef)(env, node->ref); @@ -200,16 +216,18 @@ weakenNode(JNIEnv *env, RefNode *node) if (weakRef != NULL) { JNI_FUNC_PTR(env,DeleteGlobalRef)(env, node->ref); - node->ref = weakRef; - node->strongCount = 0; + node->ref = weakRef; + } else { + return NULL; } - return weakRef; + } + + if (isUnpinAll) { + node->isPinAll = JNI_FALSE; } else { - if (node->strongCount > 0) { - node->strongCount--; - } - return node->ref; + node->isCommonPin = JNI_FALSE; } + return node->ref; } /* @@ -470,7 +488,7 @@ commonRef_idToRef(JNIEnv *env, jlong id) node = findNodeByID(env, id); if (node != NULL) { - if (node->strongCount != 0) { + if (isStrong(node)) { saveGlobalRef(env, node->ref, &ref); } else { jobject lref; @@ -522,7 +540,7 @@ commonRef_pin(jlong id) } else { jobject strongRef; - strongRef = strengthenNode(env, node); + strongRef = strengthenNode(env, node, JNI_FALSE /* isPinAll */); if (strongRef == NULL) { /* * Referent has been collected, clean up now. @@ -551,7 +569,7 @@ commonRef_unpin(jlong id) if (node != NULL) { jweak weakRef; - weakRef = weakenNode(env, node); + weakRef = weakenNode(env, node, JNI_FALSE /* isUnpinAll */); if (weakRef == NULL) { error = AGENT_ERROR_OUT_OF_MEMORY; } @@ -585,7 +603,7 @@ commonRef_pinAll() while (node != NULL) { jobject strongRef; - strongRef = strengthenNode(env, node); + strongRef = strengthenNode(env, node, JNI_TRUE /* isPinAll */); /* Has the object been collected? */ if (strongRef == NULL) { @@ -628,7 +646,7 @@ commonRef_unpinAll() for (node = gdata->objectsByID[i]; node != NULL; node = node->next) { jweak weakRef; - weakRef = weakenNode(env, node); + weakRef = weakenNode(env, node, JNI_TRUE /* isUnpinAll */); if (weakRef == NULL) { EXIT_ERROR(AGENT_ERROR_NULL_POINTER,"NewWeakGlobalRef"); } @@ -676,8 +694,7 @@ commonRef_compact(void) prev = NULL; while (node != NULL) { /* Has the object been collected? */ - if ( (node->strongCount == 0) && - isSameObject(env, node->ref, NULL)) { + if (!isStrong(node) && isSameObject(env, node->ref, NULL)) { RefNode *freed; /* Detach from the ID list */ diff --git a/src/jdk.jdwp.agent/share/native/libjdwp/util.h b/src/jdk.jdwp.agent/share/native/libjdwp/util.h index 134bf03db7a..0619648d957 100644 --- a/src/jdk.jdwp.agent/share/native/libjdwp/util.h +++ b/src/jdk.jdwp.agent/share/native/libjdwp/util.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -65,7 +65,8 @@ typedef struct RefNode { jobject ref; /* could be strong or weak */ struct RefNode *next; /* next RefNode* in bucket chain */ jint count; /* count of references */ - unsigned strongCount; /* count of strong reference */ + jboolean isPinAll; /* true if this is a strong reference due to a commonRef_pinAll() */ + jboolean isCommonPin; /* true if this is a strong reference due to a commonRef_pin() */ } RefNode; /* Value of a NULL ID */ -- GitLab From 295c0474c43484e793b67a70af316aaae49fe361 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Tue, 25 Jan 2022 20:05:49 +0000 Subject: [PATCH 288/564] 8279242: Reflection newInstance() error message when constructor has no access modifiers could use improvement Reviewed-by: iris, dholmes, mchung --- .../jdk/internal/reflect/Reflection.java | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/java.base/share/classes/jdk/internal/reflect/Reflection.java b/src/java.base/share/classes/jdk/internal/reflect/Reflection.java index 76a4bf8fa4a..23b686041e6 100644 --- a/src/java.base/share/classes/jdk/internal/reflect/Reflection.java +++ b/src/java.base/share/classes/jdk/internal/reflect/Reflection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2022, 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 @@ -379,11 +379,8 @@ public class Reflection { String msg = currentClass + currentSuffix + " cannot access "; if (m2.isExported(memberPackageName, m1)) { - // module access okay so include the modifiers in the message - msg += "a member of " + memberClass + memberSuffix + - " with modifiers \"" + Modifier.toString(modifiers) + "\""; - + msg += "a member of " + memberClass + memberSuffix + msgSuffix(modifiers); } else { // module access failed msg += memberClass + memberSuffix+ " because " @@ -410,11 +407,8 @@ public class Reflection { String msg = "JNI attached native thread (null caller frame) cannot access "; if (m2.isExported(memberPackageName)) { - // module access okay so include the modifiers in the message - msg += "a member of " + memberClass + memberSuffix + - " with modifiers \"" + Modifier.toString(modifiers) + "\""; - + msg += "a member of " + memberClass + memberSuffix + msgSuffix(modifiers); } else { // module access failed msg += memberClass + memberSuffix+ " because " @@ -424,6 +418,16 @@ public class Reflection { return new IllegalAccessException(msg); } + private static String msgSuffix(int modifiers) { + boolean packageAccess = + ((Modifier.PRIVATE | + Modifier.PROTECTED | + Modifier.PUBLIC) & modifiers) == 0; + return packageAccess ? + " with package access" : + " with modifiers \"" + Modifier.toString(modifiers) + "\""; + } + /** * Returns true if {@code currentClass} and {@code memberClass} * are nestmates - that is, if they have the same nesthost as -- GitLab From 2eab86b513a9e4566b3f5989f899ae44280d3834 Mon Sep 17 00:00:00 2001 From: Vicente Romero Date: Wed, 26 Jan 2022 00:33:10 +0000 Subject: [PATCH 289/564] 8213905: reflection not working for type annotations applied to exception types in the inner class constructor Reviewed-by: jlahoda --- .../annotation/TypeAnnotationParser.java | 3 ++- .../annotation/TypeAnnotationReflection.java | 17 +++++++++++++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/java.base/share/classes/sun/reflect/annotation/TypeAnnotationParser.java b/src/java.base/share/classes/sun/reflect/annotation/TypeAnnotationParser.java index 5c7356fca81..fc51faad6fc 100644 --- a/src/java.base/share/classes/sun/reflect/annotation/TypeAnnotationParser.java +++ b/src/java.base/share/classes/sun/reflect/annotation/TypeAnnotationParser.java @@ -132,7 +132,8 @@ public final class TypeAnnotationParser { Class declaringClass = ctor.getDeclaringClass(); if (!declaringClass.isEnum() && (declaringClass.isMemberClass() && - (declaringClass.getModifiers() & Modifier.STATIC) == 0) ) { + (declaringClass.getModifiers() & Modifier.STATIC) == 0) && + filter == TypeAnnotation.TypeAnnotationTarget.METHOD_FORMAL_PARAMETER) { offset = true; } } diff --git a/test/jdk/java/lang/annotation/TypeAnnotationReflection.java b/test/jdk/java/lang/annotation/TypeAnnotationReflection.java index 64234ccc215..9c0a101c2b6 100644 --- a/test/jdk/java/lang/annotation/TypeAnnotationReflection.java +++ b/test/jdk/java/lang/annotation/TypeAnnotationReflection.java @@ -39,7 +39,8 @@ public class TypeAnnotationReflection { testReturnType(); testNested(); testArray(); - testRunException(); + testRunException(TestClassException.class.getDeclaredMethod("foo", (Class[])null)); + testRunException(Outer2.TestClassException2.class.getDeclaredConstructor(Outer2.class)); testClassTypeVarBounds(); testMethodTypeVarBounds(); testFields(); @@ -142,9 +143,8 @@ public class TypeAnnotationReflection { check(((TypeAnno)annos[0]).value().equals("return4")); } - private static void testRunException() throws Exception { - Method m = TestClassException.class.getDeclaredMethod("foo", (Class[])null); - AnnotatedType[] ts = m.getAnnotatedExceptionTypes(); + private static void testRunException(Executable e) throws Exception { + AnnotatedType[] ts = e.getAnnotatedExceptionTypes(); check(ts.length == 3); AnnotatedType t; @@ -624,6 +624,15 @@ abstract class TestClassException { } } +class Outer2 { + abstract class TestClassException2 { + public TestClassException2() throws + @TypeAnno("RE") @TypeAnno2("RE2") RuntimeException, + NullPointerException, + @TypeAnno("AIOOBE") ArrayIndexOutOfBoundsException {} + } +} + abstract class TestClassTypeVarAndField { -- GitLab From ef08e2c63b040cef6ca5f71dbce49f3d7647fdd8 Mon Sep 17 00:00:00 2001 From: Maurizio Cimadamore Date: Wed, 26 Jan 2022 01:12:37 +0000 Subject: [PATCH 290/564] 8280592: Small javadoc tweaks to foreign API Reviewed-by: psandoz --- .../jdk/incubator/foreign/Addressable.java | 3 +- .../incubator/foreign/FunctionDescriptor.java | 12 +++---- .../jdk/incubator/foreign/GroupLayout.java | 8 ++--- .../jdk/incubator/foreign/MemoryAddress.java | 6 ++-- .../jdk/incubator/foreign/MemoryLayout.java | 32 +++++------------- .../jdk/incubator/foreign/MemorySegment.java | 18 ++++------ .../jdk/incubator/foreign/NativeSymbol.java | 9 ++--- .../jdk/incubator/foreign/ResourceScope.java | 3 +- .../jdk/incubator/foreign/SequenceLayout.java | 8 ++--- .../classes/jdk/incubator/foreign/VaList.java | 6 ++-- .../jdk/incubator/foreign/ValueLayout.java | 33 +++++++++---------- .../jdk/incubator/foreign/package-info.java | 2 +- 12 files changed, 49 insertions(+), 91 deletions(-) diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/Addressable.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/Addressable.java index 39f61e76122..17d417bee51 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/Addressable.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/Addressable.java @@ -40,8 +40,7 @@ package jdk.incubator.foreign; public sealed interface Addressable permits MemorySegment, MemoryAddress, NativeSymbol, VaList { /** - * Returns the memory address associated with this addressable. - * @return The memory address associated with this addressable. + * {@return the {@linkplain MemoryAddress memory address} associated with this addressable} */ MemoryAddress address(); } diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/FunctionDescriptor.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/FunctionDescriptor.java index 9c557ec9e9e..6bedfc4c16a 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/FunctionDescriptor.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/FunctionDescriptor.java @@ -54,16 +54,14 @@ public sealed class FunctionDescriptor implements Constable permits FunctionDesc } /** - * Returns the return layout associated with this function. - * @return the return layout. + * {@return the return layout (if any) associated with this function descriptor} */ public Optional returnLayout() { return Optional.ofNullable(resLayout); } /** - * Returns the argument layouts associated with this function. - * @return the argument layouts. + * {@return the argument layouts associated with this function descriptor}. */ public List argumentLayouts() { return argLayouts; @@ -166,8 +164,7 @@ public sealed class FunctionDescriptor implements Constable permits FunctionDesc } /** - * Returns a string representation of this function descriptor. - * @return a string representation of this function descriptor. + * {@return the string representation of this function descriptor} */ @Override public String toString() { @@ -201,8 +198,7 @@ public sealed class FunctionDescriptor implements Constable permits FunctionDesc } /** - * Returns the hash code value for this function descriptor. - * @return the hash code value for this function descriptor. + * {@return the hash code value for this function descriptor} */ @Override public int hashCode() { diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/GroupLayout.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/GroupLayout.java index d08bb716ae8..6fc9baad7ff 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/GroupLayout.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/GroupLayout.java @@ -133,18 +133,14 @@ public final class GroupLayout extends AbstractLayout implements MemoryLayout { } /** - * Is this group layout a struct? - * - * @return true, if this group layout is a struct. + * {@return {@code true}, if this group layout is a struct} */ public boolean isStruct() { return kind == Kind.STRUCT; } /** - * Is this group layout a union? - * - * @return true, if this group layout is a union. + * {@return {@code true}, if this group layout is a union} */ public boolean isUnion() { return kind == Kind.UNION; diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryAddress.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryAddress.java index 47a17799700..007464d1691 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryAddress.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryAddress.java @@ -78,8 +78,7 @@ import java.nio.ByteOrder; public sealed interface MemoryAddress extends Addressable permits MemoryAddressImpl { /** - * Returns the raw long value associated with this memory address. - * @return The raw long value associated with this memory address. + * {@return the raw long value associated with this memory address} */ long toRawLongValue(); @@ -141,8 +140,7 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI boolean equals(Object that); /** - * Returns the hash code value for this address. - * @return the hash code value for this address. + * {@return the hash code value for this address} */ @Override int hashCode(); diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryLayout.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryLayout.java index fe0fb4e93f9..991897c367d 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryLayout.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryLayout.java @@ -195,18 +195,15 @@ import java.util.stream.Stream; public sealed interface MemoryLayout extends Constable permits AbstractLayout, SequenceLayout, GroupLayout, PaddingLayout, ValueLayout { /** - * Returns an {@link Optional} containing the nominal descriptor for this + * {@return an {@link Optional} containing the nominal descriptor for this * layout, if one can be constructed, or an empty {@link Optional} - * if one cannot be constructed. - * - * @return An {@link Optional} containing the resulting nominal descriptor, - * or an empty {@link Optional} if one cannot be constructed. + * if one cannot be constructed} */ @Override Optional> describeConstable(); /** - * Does this layout have a specified size? A layout does not have a specified size if it is (or contains) a sequence layout whose + * Returns {@code true} if this layout has a specified size. A layout does not have a specified size if it is (or contains) a sequence layout whose * size is unspecified (see {@link SequenceLayout#elementCount()}). * * Value layouts (see {@link ValueLayout}) and padding layouts (see {@link MemoryLayout#paddingLayout(long)}) @@ -217,26 +214,20 @@ public sealed interface MemoryLayout extends Constable permits AbstractLayout, S boolean hasSize(); /** - * Computes the layout size, in bits. - * - * @return the layout size, in bits. + * {@return the layout size, in bits} * @throws UnsupportedOperationException if the layout is, or contains, a sequence layout with unspecified size (see {@link SequenceLayout}). */ long bitSize(); /** - * Computes the layout size, in bytes. - * - * @return the layout size, in bytes. + * {@return the layout size, in bytes} * @throws UnsupportedOperationException if the layout is, or contains, a sequence layout with unspecified size (see {@link SequenceLayout}), * or if {@code bitSize()} is not a multiple of 8. */ long byteSize(); /** - * Return the name (if any) associated with this layout. - * - * @return the layout name (if any). + * {@return the name (if any) associated with this layout} * @see MemoryLayout#withName(String) */ Optional name(); @@ -534,8 +525,7 @@ public sealed interface MemoryLayout extends Constable permits AbstractLayout, S } /** - * Is this a {@linkplain #paddingLayout(long) padding layout} ? - * @return true, if this layout is a padding layout. + * {@return true, if this layout is a padding layout} */ boolean isPadding(); @@ -651,16 +641,12 @@ public sealed interface MemoryLayout extends Constable permits AbstractLayout, S boolean equals(Object that); /** - * Returns the hash code value for this layout. - * - * @return the hash code value for this layout. + * {@return the hash code value for this layout} */ int hashCode(); /** - * Returns a string representation of this layout. - * - * @return a string representation of this layout. + * {@return the string representation of this layout} */ @Override String toString(); diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemorySegment.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemorySegment.java index 3d3401ef05b..a4508530734 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemorySegment.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemorySegment.java @@ -250,11 +250,10 @@ boolean isAligned(MemorySegment segment, long offset, MemoryLayout layout) { public sealed interface MemorySegment extends Addressable permits AbstractMemorySegmentImpl { /** - * The base memory address associated with this native memory segment. + * {@return the base memory address associated with this native memory segment} * @throws UnsupportedOperationException if this segment is not a {@linkplain #isNative() native} segment. * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from * a thread other than the thread owning that scope. - * @return The base memory address. */ @Override MemoryAddress address(); @@ -299,14 +298,12 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory Stream elements(MemoryLayout elementLayout); /** - * Returns the resource scope associated with this memory segment. - * @return the resource scope associated with this memory segment. + * {@return the resource scope associated with this memory segment} */ ResourceScope scope(); /** - * The size (in bytes) of this memory segment. - * @return The size (in bytes) of this memory segment. + * {@return the size (in bytes) of this memory segment} */ long byteSize(); @@ -343,8 +340,7 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory } /** - * Is this segment read-only? - * @return {@code true}, if this segment is read-only. + * {@return {@code true}, if this segment is read-only} * @see #asReadOnly() */ boolean isReadOnly(); @@ -358,7 +354,7 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory MemorySegment asReadOnly(); /** - * Is this a native segment? Returns true if this segment is a native memory segment, + * Returns {@code true} if this segment is a native segment. A native memory segment is * created using the {@link #allocateNative(long, ResourceScope)} (and related) factory, or a buffer segment * derived from a direct {@link java.nio.ByteBuffer} using the {@link #ofByteBuffer(ByteBuffer)} factory, * or if this is a {@linkplain #isMapped() mapped} segment. @@ -367,7 +363,7 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory boolean isNative(); /** - * Is this a mapped segment? Returns true if this segment is a mapped memory segment, + * Returns {@code true} if this segment is a mapped segment. A mapped memory segment is * created using the {@link #mapFile(Path, long, long, FileChannel.MapMode, ResourceScope)} factory, or a buffer segment * derived from a {@link java.nio.MappedByteBuffer} using the {@link #ofByteBuffer(ByteBuffer)} factory. * @return {@code true} if this segment is a mapped segment. @@ -484,7 +480,7 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory long mismatch(MemorySegment other); /** - * Tells whether the contents of this mapped segment is resident in physical + * Determines whether the contents of this mapped segment is resident in physical * memory. * *

    A return value of {@code true} implies that it is highly likely diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/NativeSymbol.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/NativeSymbol.java index bf137e965d7..3dc583f98fc 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/NativeSymbol.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/NativeSymbol.java @@ -43,22 +43,19 @@ import java.util.Objects; sealed public interface NativeSymbol extends Addressable permits NativeSymbolImpl { /** - * Returns the name of this symbol. - * @return the name of this symbol. + * {@return the name of this symbol} */ String name(); /** - * Returns the resource scope associated with this symbol. - * @return the resource scope associated with this symbol. + * {@return the resource scope associated with this symbol} */ ResourceScope scope(); /** - * Returns the memory address associated with this symbol. + * {@return the memory address associated with this symbol} * @throws IllegalStateException if the scope associated with this symbol has been closed, or if access occurs from * a thread other than the thread owning that scope. - * @return The memory address associated with this symbol. */ @Override MemoryAddress address(); diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/ResourceScope.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/ResourceScope.java index 24665c7dfe9..6c5d6b2b66f 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/ResourceScope.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/ResourceScope.java @@ -147,8 +147,7 @@ import java.util.Spliterator; */ public sealed interface ResourceScope extends AutoCloseable permits ResourceScopeImpl { /** - * Is this resource scope alive? - * @return true, if this resource scope is alive. + * {@return {@code true}, if this resource scope is alive} * @see ResourceScope#close() */ boolean isAlive(); diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/SequenceLayout.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/SequenceLayout.java index 13ac7192728..8143d2929ce 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/SequenceLayout.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/SequenceLayout.java @@ -82,18 +82,14 @@ public final class SequenceLayout extends AbstractLayout implements MemoryLayout } /** - * Returns the element layout associated with this sequence layout. - * - * @return The element layout associated with this sequence layout. + * {@return the element layout associated with this sequence layout} */ public MemoryLayout elementLayout() { return elementLayout; } /** - * Returns the element count of this sequence layout (if any). - * - * @return the element count of this sequence layout (if any). + * {@return the element count of this sequence layout (if any)} */ public OptionalLong elementCount() { return elemCount; diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/VaList.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/VaList.java index 1bc449fa907..73ede4e4e9a 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/VaList.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/VaList.java @@ -132,8 +132,7 @@ sealed public interface VaList extends Addressable permits WinVaList, SysVVaList void skip(MemoryLayout... layouts); /** - * Returns the resource scope associated with this variable argument list. - * @return the resource scope associated with this variable argument list. + * {@return the resource scope associated with this variable argument list} */ ResourceScope scope(); @@ -153,10 +152,9 @@ sealed public interface VaList extends Addressable permits WinVaList, SysVVaList VaList copy(); /** - * Returns the memory address associated with this variable argument list. + * {@return the {@linkplain MemoryAddress memory address} associated with this variable argument list} * @throws IllegalStateException if the scope associated with this variable argument list has been closed, or if access occurs from * a thread other than the thread owning that scope. - * @return The memory address associated with this variable argument list. */ @Override MemoryAddress address(); diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/ValueLayout.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/ValueLayout.java index 3ce22d8743f..c2df9e1b25f 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/ValueLayout.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/ValueLayout.java @@ -41,9 +41,9 @@ import java.util.OptionalLong; /** * A value layout. A value layout is used to model the memory layout associated with values of basic data types, such as integral types - * (either signed or unsigned) and floating-point types. Each value layout has a size, an alignment, a {@linkplain ByteOrder byte order}) - * and a carrier, that is, the Java type that should be used when {@linkplain MemorySegment#get(OfInt, long) accessing} - * a memory region using the value layout. + * (either signed or unsigned) and floating-point types. Each value layout has a size, an alignment (in bits), + * a {@linkplain ByteOrder byte order}, and a carrier, that is, the Java type that should be used when + * {@linkplain MemorySegment#get(OfInt, long) accessing} a memory region using the value layout. *

    * This class defines useful value layout constants for Java primitive types and addresses. * The layout constants in this class make implicit alignment and byte-ordering assumption: all layout @@ -82,9 +82,7 @@ public sealed class ValueLayout extends AbstractLayout implements MemoryLayout { } /** - * Returns the value's byte order. - * - * @return the value's byte order. + * {@return the value's byte order} */ public ByteOrder order() { return order; @@ -125,8 +123,7 @@ public sealed class ValueLayout extends AbstractLayout implements MemoryLayout { } /** - * Returns the carrier associated with this value layout. - * @return the carrier associated with this value layout. + * {@return the carrier associated with this value layout} */ public Class carrier() { return carrier; @@ -513,8 +510,8 @@ public sealed class ValueLayout extends AbstractLayout implements MemoryLayout { } /** - * A value layout constant whose size is the same as that of a machine address (e.g. {@code size_t}), - * bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}. + * A value layout constant whose size is the same as that of a machine address ({@code size_t}), + * bit alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}. * Equivalent to the following code: * {@snippet lang=java : * MemoryLayout.valueLayout(MemoryAddress.class, ByteOrder.nativeOrder()).withBitAlignment(8); @@ -524,7 +521,7 @@ public sealed class ValueLayout extends AbstractLayout implements MemoryLayout { /** * A value layout constant whose size is the same as that of a Java {@code byte}, - * bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}. + * bit alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}. * Equivalent to the following code: * {@snippet lang=java : * MemoryLayout.valueLayout(byte.class, ByteOrder.nativeOrder()).withBitAlignment(8); @@ -534,7 +531,7 @@ public sealed class ValueLayout extends AbstractLayout implements MemoryLayout { /** * A value layout constant whose size is the same as that of a Java {@code boolean}, - * bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}. + * bit alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}. * Equivalent to the following code: * {@snippet lang=java : * MemoryLayout.valueLayout(boolean.class, ByteOrder.nativeOrder()).withBitAlignment(8); @@ -544,7 +541,7 @@ public sealed class ValueLayout extends AbstractLayout implements MemoryLayout { /** * A value layout constant whose size is the same as that of a Java {@code char}, - * bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}. + * bit alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}. * Equivalent to the following code: * {@snippet lang=java : * MemoryLayout.valueLayout(char.class, ByteOrder.nativeOrder()).withBitAlignment(8); @@ -554,7 +551,7 @@ public sealed class ValueLayout extends AbstractLayout implements MemoryLayout { /** * A value layout constant whose size is the same as that of a Java {@code short}, - * bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}. + * bit alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}. * Equivalent to the following code: * {@snippet lang=java : * MemoryLayout.valueLayout(short.class, ByteOrder.nativeOrder()).withBitAlignment(8); @@ -564,7 +561,7 @@ public sealed class ValueLayout extends AbstractLayout implements MemoryLayout { /** * A value layout constant whose size is the same as that of a Java {@code int}, - * bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}. + * bit alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}. * Equivalent to the following code: * {@snippet lang=java : * MemoryLayout.valueLayout(int.class, ByteOrder.nativeOrder()).withBitAlignment(8); @@ -574,7 +571,7 @@ public sealed class ValueLayout extends AbstractLayout implements MemoryLayout { /** * A value layout constant whose size is the same as that of a Java {@code long}, - * bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}. + * bit alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}. * Equivalent to the following code: * {@snippet lang=java : * MemoryLayout.valueLayout(long.class, ByteOrder.nativeOrder()).withBitAlignment(8); @@ -585,7 +582,7 @@ public sealed class ValueLayout extends AbstractLayout implements MemoryLayout { /** * A value layout constant whose size is the same as that of a Java {@code float}, - * bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}. + * bit alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}. * Equivalent to the following code: * {@snippet lang=java : * MemoryLayout.valueLayout(float.class, ByteOrder.nativeOrder()).withBitAlignment(8); @@ -595,7 +592,7 @@ public sealed class ValueLayout extends AbstractLayout implements MemoryLayout { /** * A value layout constant whose size is the same as that of a Java {@code double}, - * bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}. + * bit alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}. * Equivalent to the following code: * {@snippet lang=java : * MemoryLayout.valueLayout(double.class, ByteOrder.nativeOrder()).withBitAlignment(8); diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/package-info.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/package-info.java index 3621495d064..a74c6d3a55d 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/package-info.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/package-info.java @@ -30,7 +30,7 @@ *

    Foreign memory access

    * *

    - * The main abstractions introduced to support foreign memory access is {@link jdk.incubator.foreign.MemorySegment}, which + * The main abstraction introduced to support foreign memory access is {@link jdk.incubator.foreign.MemorySegment}, which * models a contiguous memory region, which can reside either inside or outside the Java heap. * A memory segment represents the main access coordinate of a memory access var handle, which can be obtained * using the combinator methods defined in the {@link jdk.incubator.foreign.MemoryHandles} class; a set of -- GitLab From a183bfb436a7dd998e602c2d16486e88c390fca1 Mon Sep 17 00:00:00 2001 From: Mandy Chung Date: Wed, 26 Jan 2022 01:24:15 +0000 Subject: [PATCH 291/564] 8280377: MethodHandleProxies does not correctly invoke default methods with varags Reviewed-by: alanb --- .../java/lang/invoke/MethodHandleProxies.java | 43 ++-------- .../java/lang/reflect/InvocationHandler.java | 30 +------ .../classes/java/lang/reflect/Proxy.java | 40 ++++++++++ .../java/lang/reflect/ReflectAccess.java | 5 ++ .../access/JavaLangReflectAccess.java | 7 ++ .../invoke/MethodHandleProxies/Driver.java | 32 ++++++++ .../MethodHandlesProxiesTest.java | 0 .../invoke/MethodHandleProxies/Unnamed.java | 45 +++++++++++ .../MethodHandleProxies/m1/module-info.java | 27 +++++++ .../MethodHandleProxies/m1/p1/Main.java | 80 +++++++++++++++++++ .../MethodHandleProxies/m2/module-info.java | 25 ++++++ .../MethodHandleProxies/m2/p2/TestIntf.java | 27 +++++++ 12 files changed, 295 insertions(+), 66 deletions(-) create mode 100644 test/jdk/java/lang/invoke/MethodHandleProxies/Driver.java rename test/jdk/java/lang/invoke/{ => MethodHandleProxies}/MethodHandlesProxiesTest.java (100%) create mode 100644 test/jdk/java/lang/invoke/MethodHandleProxies/Unnamed.java create mode 100644 test/jdk/java/lang/invoke/MethodHandleProxies/m1/module-info.java create mode 100644 test/jdk/java/lang/invoke/MethodHandleProxies/m1/p1/Main.java create mode 100644 test/jdk/java/lang/invoke/MethodHandleProxies/m2/module-info.java create mode 100644 test/jdk/java/lang/invoke/MethodHandleProxies/m2/p2/TestIntf.java diff --git a/src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java b/src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java index c1c34185ffb..b2e93afea12 100644 --- a/src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java @@ -28,9 +28,11 @@ package java.lang.invoke; import java.lang.reflect.*; import java.security.AccessController; import java.security.PrivilegedAction; + +import jdk.internal.access.JavaLangReflectAccess; +import jdk.internal.access.SharedSecrets; import sun.invoke.WrapperInstance; import java.util.ArrayList; -import java.util.concurrent.ConcurrentHashMap; import jdk.internal.reflect.CallerSensitive; import jdk.internal.reflect.Reflection; @@ -184,8 +186,6 @@ public class MethodHandleProxies { checkTarget = checkTarget.asType(checkTarget.type().changeReturnType(Object.class)); vaTargets[i] = checkTarget.asSpreader(Object[].class, smMT.parameterCount()); } - final ConcurrentHashMap defaultMethodMap = - hasDefaultMethods(intfc) ? new ConcurrentHashMap<>() : null; final InvocationHandler ih = new InvocationHandler() { private Object getArg(String name) { if ((Object)name == "getWrapperInstanceTarget") return target; @@ -202,7 +202,8 @@ public class MethodHandleProxies { if (isObjectMethod(method)) return callObjectMethod(proxy, method, args); if (isDefaultMethod(method)) { - return callDefaultMethod(defaultMethodMap, proxy, intfc, method, args); + // no additional access check is performed + return JLRA.invokeDefault(proxy, method, args, null); } throw newInternalError("bad proxy method: "+method); } @@ -320,37 +321,5 @@ public class MethodHandleProxies { return !Modifier.isAbstract(m.getModifiers()); } - private static boolean hasDefaultMethods(Class intfc) { - for (Method m : intfc.getMethods()) { - if (!isObjectMethod(m) && - !Modifier.isAbstract(m.getModifiers())) { - return true; - } - } - return false; - } - - private static Object callDefaultMethod(ConcurrentHashMap defaultMethodMap, - Object self, Class intfc, Method m, Object[] args) throws Throwable { - assert(isDefaultMethod(m) && !isObjectMethod(m)) : m; - - // Lazily compute the associated method handle from the method - MethodHandle dmh = defaultMethodMap.computeIfAbsent(m, mk -> { - try { - // Look up the default method for special invocation thereby - // avoiding recursive invocation back to the proxy - MethodHandle mh = MethodHandles.Lookup.IMPL_LOOKUP.findSpecial( - intfc, mk.getName(), - MethodType.methodType(mk.getReturnType(), mk.getParameterTypes()), - self.getClass()); - return mh.asSpreader(Object[].class, mk.getParameterCount()); - } catch (NoSuchMethodException | IllegalAccessException e) { - // The method is known to exist and should be accessible, this - // method would not be called unless the invokeinterface to the - // default (public) method passed access control checks - throw new InternalError(e); - } - }); - return dmh.invoke(self, args); - } + private static final JavaLangReflectAccess JLRA = SharedSecrets.getJavaLangReflectAccess(); } diff --git a/src/java.base/share/classes/java/lang/reflect/InvocationHandler.java b/src/java.base/share/classes/java/lang/reflect/InvocationHandler.java index 4ca59906367..d5d00f34c86 100644 --- a/src/java.base/share/classes/java/lang/reflect/InvocationHandler.java +++ b/src/java.base/share/classes/java/lang/reflect/InvocationHandler.java @@ -28,7 +28,6 @@ package java.lang.reflect; import jdk.internal.reflect.CallerSensitive; import jdk.internal.reflect.Reflection; -import java.lang.invoke.MethodHandle; import java.util.Objects; /** @@ -262,33 +261,6 @@ public interface InvocationHandler { throws Throwable { Objects.requireNonNull(proxy); Objects.requireNonNull(method); - - // verify that the object is actually a proxy instance - if (!Proxy.isProxyClass(proxy.getClass())) { - throw new IllegalArgumentException("'proxy' is not a proxy instance"); - } - if (!method.isDefault()) { - throw new IllegalArgumentException("\"" + method + "\" is not a default method"); - } - @SuppressWarnings("unchecked") - Class proxyClass = (Class)proxy.getClass(); - - Class intf = method.getDeclaringClass(); - // access check on the default method - method.checkAccess(Reflection.getCallerClass(), intf, proxyClass, method.getModifiers()); - - MethodHandle mh = Proxy.defaultMethodHandle(proxyClass, method); - // invoke the super method - try { - // the args array can be null if the number of formal parameters required by - // the method is zero (consistent with Method::invoke) - Object[] params = args != null ? args : Proxy.EMPTY_ARGS; - return mh.invokeExact(proxy, params); - } catch (ClassCastException | NullPointerException e) { - throw new IllegalArgumentException(e.getMessage(), e); - } catch (Proxy.InvocationException e) { - // unwrap and throw the exception thrown by the default method - throw e.getCause(); - } + return Proxy.invokeDefault(proxy, method, args, Reflection.getCallerClass()); } } diff --git a/src/java.base/share/classes/java/lang/reflect/Proxy.java b/src/java.base/share/classes/java/lang/reflect/Proxy.java index c9e3bb259ae..6dd5b3ef1db 100644 --- a/src/java.base/share/classes/java/lang/reflect/Proxy.java +++ b/src/java.base/share/classes/java/lang/reflect/Proxy.java @@ -1314,6 +1314,46 @@ public class Proxy implements java.io.Serializable { }); } + /* + * Invoke the default method of the given proxy with an explicit caller class. + * + * @throws IllegalAccessException if the proxy interface is inaccessible to the caller + * if caller is non-null + */ + static Object invokeDefault(Object proxy, Method method, Object[] args, Class caller) + throws Throwable { + // verify that the object is actually a proxy instance + if (!Proxy.isProxyClass(proxy.getClass())) { + throw new IllegalArgumentException("'proxy' is not a proxy instance"); + } + if (!method.isDefault()) { + throw new IllegalArgumentException("\"" + method + "\" is not a default method"); + } + @SuppressWarnings("unchecked") + Class proxyClass = (Class)proxy.getClass(); + + // skip access check if caller is null + if (caller != null) { + Class intf = method.getDeclaringClass(); + // access check on the default method + method.checkAccess(caller, intf, proxyClass, method.getModifiers()); + } + + MethodHandle mh = Proxy.defaultMethodHandle(proxyClass, method); + // invoke the super method + try { + // the args array can be null if the number of formal parameters required by + // the method is zero (consistent with Method::invoke) + Object[] params = args != null ? args : Proxy.EMPTY_ARGS; + return mh.invokeExact(proxy, params); + } catch (ClassCastException | NullPointerException e) { + throw new IllegalArgumentException(e.getMessage(), e); + } catch (Proxy.InvocationException e) { + // unwrap and throw the exception thrown by the default method + throw e.getCause(); + } + } + /** * Internal exception type to wrap the exception thrown by the default method * so that it can distinguish CCE and NPE thrown due to the arguments diff --git a/src/java.base/share/classes/java/lang/reflect/ReflectAccess.java b/src/java.base/share/classes/java/lang/reflect/ReflectAccess.java index 6ac890156b0..fa5a5d453ec 100644 --- a/src/java.base/share/classes/java/lang/reflect/ReflectAccess.java +++ b/src/java.base/share/classes/java/lang/reflect/ReflectAccess.java @@ -127,4 +127,9 @@ class ReflectAccess implements jdk.internal.access.JavaLangReflectAccess { { return ctor.newInstanceWithCaller(args, true, caller); } + + public Object invokeDefault(Object proxy, Method method, Object[] args, Class caller) + throws Throwable { + return Proxy.invokeDefault(proxy, method, args, caller); + } } diff --git a/src/java.base/share/classes/jdk/internal/access/JavaLangReflectAccess.java b/src/java.base/share/classes/jdk/internal/access/JavaLangReflectAccess.java index 4082fae336f..9e3ce846f02 100644 --- a/src/java.base/share/classes/jdk/internal/access/JavaLangReflectAccess.java +++ b/src/java.base/share/classes/jdk/internal/access/JavaLangReflectAccess.java @@ -102,4 +102,11 @@ public interface JavaLangReflectAccess { /** Returns a new instance created by the given constructor with access check */ public T newInstance(Constructor ctor, Object[] args, Class caller) throws IllegalAccessException, InstantiationException, InvocationTargetException; + + /** Invokes the given default method if the method's declaring interface is + * accessible to the given caller. Otherwise, IllegalAccessException will + * be thrown. If the caller is null, no access check is performed. + */ + public Object invokeDefault(Object proxy, Method method, Object[] args, Class caller) + throws Throwable; } diff --git a/test/jdk/java/lang/invoke/MethodHandleProxies/Driver.java b/test/jdk/java/lang/invoke/MethodHandleProxies/Driver.java new file mode 100644 index 00000000000..6acd4fb30e1 --- /dev/null +++ b/test/jdk/java/lang/invoke/MethodHandleProxies/Driver.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2022, 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 8280377 + * @build m1/* m2/* Unnamed + * @run testng/othervm m1/p1.Main + * @run testng/othervm Unnamed + * @summary Test MethodHandleProxies::asInterfaceInstance with a default + * method with varargs + */ diff --git a/test/jdk/java/lang/invoke/MethodHandlesProxiesTest.java b/test/jdk/java/lang/invoke/MethodHandleProxies/MethodHandlesProxiesTest.java similarity index 100% rename from test/jdk/java/lang/invoke/MethodHandlesProxiesTest.java rename to test/jdk/java/lang/invoke/MethodHandleProxies/MethodHandlesProxiesTest.java diff --git a/test/jdk/java/lang/invoke/MethodHandleProxies/Unnamed.java b/test/jdk/java/lang/invoke/MethodHandleProxies/Unnamed.java new file mode 100644 index 00000000000..f42071f0427 --- /dev/null +++ b/test/jdk/java/lang/invoke/MethodHandleProxies/Unnamed.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2022, 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.invoke.MethodHandle; +import java.lang.invoke.MethodHandleProxies; +import java.lang.invoke.MethodHandles; +import java.lang.reflect.Method; + +import static org.testng.Assert.*; + +/* + * Test MethodHandleProxies::asInterfaceInstance with an inaccessible interface + */ +public class Unnamed { + public static void main(String... args) throws Throwable { + MethodHandle target = MethodHandles.constant(String.class, "test"); + Class intf = Class.forName("p2.TestIntf"); + Object t = MethodHandleProxies.asInterfaceInstance(intf, target); + + // verify that the caller has no access to the proxy created on an + // inaccessible interface + Method m = intf.getMethod("test", Object[].class); + assertFalse(m.canAccess(null)); + } +} diff --git a/test/jdk/java/lang/invoke/MethodHandleProxies/m1/module-info.java b/test/jdk/java/lang/invoke/MethodHandleProxies/m1/module-info.java new file mode 100644 index 00000000000..1bdeddce28f --- /dev/null +++ b/test/jdk/java/lang/invoke/MethodHandleProxies/m1/module-info.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2022, 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. + */ +module m1 { + requires m2; + requires org.testng; + exports p1; +} diff --git a/test/jdk/java/lang/invoke/MethodHandleProxies/m1/p1/Main.java b/test/jdk/java/lang/invoke/MethodHandleProxies/m1/p1/Main.java new file mode 100644 index 00000000000..df71809996b --- /dev/null +++ b/test/jdk/java/lang/invoke/MethodHandleProxies/m1/p1/Main.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2022, 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 p1; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandleProxies; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.Arrays; +import java.util.stream.Collectors; + +import p2.TestIntf; + +import org.testng.annotations.Test; + +import static org.testng.Assert.*; + +public class Main { + public interface A { + default String aConcat(Object... objs) { return Arrays.deepToString(objs); } + } + + public interface B { + default String bConcat(Object[] objs) { return Arrays.deepToString(objs); } + } + + public interface C extends A, B { + String c(Object... objs); + } + + private static String concat(Object... objs) { + return Arrays.stream(objs).map(Object::toString).collect(Collectors.joining()); + } + + /* + * Test the invocation of default methods with varargs + */ + @Test + public static void testVarargsMethods() throws Throwable { + MethodHandle target = MethodHandles.lookup().findStatic(Main.class, + "concat", MethodType.methodType(String.class, Object[].class)); + C proxy = MethodHandleProxies.asInterfaceInstance(C.class, target); + + assertEquals(proxy.c("a", "b", "c"), "abc"); + assertEquals(proxy.aConcat("a", "b", "c"), "[a, b, c]"); + assertEquals(proxy.aConcat(new Object[] { "a", "b", "c" }), "[a, b, c]"); + assertEquals(proxy.bConcat(new Object[] { "a", "b", "c" }), "[a, b, c]"); + } + + /* + * Test the invocation of a default method of an accessible interface + */ + @Test + public static void modulePrivateInterface() { + MethodHandle target = MethodHandles.constant(String.class, "test"); + TestIntf t = MethodHandleProxies.asInterfaceInstance(TestIntf.class, target); + assertEquals(t.test(), "test"); + } +} diff --git a/test/jdk/java/lang/invoke/MethodHandleProxies/m2/module-info.java b/test/jdk/java/lang/invoke/MethodHandleProxies/m2/module-info.java new file mode 100644 index 00000000000..1015757fc9c --- /dev/null +++ b/test/jdk/java/lang/invoke/MethodHandleProxies/m2/module-info.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2022, 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. + */ +module m2 { + exports p2 to m1; +} diff --git a/test/jdk/java/lang/invoke/MethodHandleProxies/m2/p2/TestIntf.java b/test/jdk/java/lang/invoke/MethodHandleProxies/m2/p2/TestIntf.java new file mode 100644 index 00000000000..a87d248e0c8 --- /dev/null +++ b/test/jdk/java/lang/invoke/MethodHandleProxies/m2/p2/TestIntf.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2022, 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 p2; + +public interface TestIntf { + String test(); +} -- GitLab From 2c64a7f2e30dc83701456595814a831e41e5f628 Mon Sep 17 00:00:00 2001 From: Hamlin Li Date: Wed, 26 Jan 2022 06:11:04 +0000 Subject: [PATCH 292/564] 8280374: G1: Remove unnecessary prev bitmap mark Reviewed-by: tschatzl, ayang --- src/hotspot/share/gc/g1/g1EvacFailure.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1EvacFailure.cpp b/src/hotspot/share/gc/g1/g1EvacFailure.cpp index 75fa7aee9db..8c6a68ad5ab 100644 --- a/src/hotspot/share/gc/g1/g1EvacFailure.cpp +++ b/src/hotspot/share/gc/g1/g1EvacFailure.cpp @@ -104,7 +104,8 @@ public: } // Fill the memory area from start to end with filler objects, and update the BOT - // and the mark bitmap accordingly. + // accordingly. Since we clear and use the prev bitmap for marking objects that + // failed evacuation, there is no work to be done there. void zap_dead_objects(HeapWord* start, HeapWord* end) { if (start == end) { return; @@ -133,7 +134,7 @@ public: #endif } } - _cm->clear_range_in_prev_bitmap(mr); + assert(!_cm->is_marked_in_prev_bitmap(cast_to_oop(start)), "should not be marked in prev bitmap"); } void zap_remainder() { -- GitLab From e72eefd9f66e63a1e11d582e4916374840111928 Mon Sep 17 00:00:00 2001 From: Andrey Turbanov Date: Wed, 26 Jan 2022 06:52:12 +0000 Subject: [PATCH 293/564] 8280531: Remove unused DeferredCloseInputStream Reviewed-by: bpb, rriggs, iris --- .../unix/classes/java/lang/ProcessImpl.java | 108 +----------------- 1 file changed, 2 insertions(+), 106 deletions(-) diff --git a/src/java.base/unix/classes/java/lang/ProcessImpl.java b/src/java.base/unix/classes/java/lang/ProcessImpl.java index 2bf36f8f136..0a3f4e34783 100644 --- a/src/java.base/unix/classes/java/lang/ProcessImpl.java +++ b/src/java.base/unix/classes/java/lang/ProcessImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, 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 @@ -45,7 +45,6 @@ import java.security.AccessController; import java.security.PrivilegedAction; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; -import java.util.Properties; import jdk.internal.access.JavaIOFileDescriptorAccess; import jdk.internal.access.SharedSecrets; import jdk.internal.util.StaticProperty; @@ -641,109 +640,6 @@ final class ProcessImpl extends Process { } } - // A FileInputStream that supports the deferment of the actual close - // operation until the last pending I/O operation on the stream has - // finished. This is required on Solaris because we must close the stdin - // and stdout streams in the destroy method in order to reclaim the - // underlying file descriptors. Doing so, however, causes any thread - // currently blocked in a read on one of those streams to receive an - // IOException("Bad file number"), which is incompatible with historical - // behavior. By deferring the close we allow any pending reads to see -1 - // (EOF) as they did before. - // - private static class DeferredCloseInputStream extends PipeInputStream { - DeferredCloseInputStream(FileDescriptor fd) { - super(fd); - } - - private Object lock = new Object(); // For the following fields - private boolean closePending = false; - private int useCount = 0; - private InputStream streamToClose; - - private void raise() { - synchronized (lock) { - useCount++; - } - } - - private void lower() throws IOException { - synchronized (lock) { - useCount--; - if (useCount == 0 && closePending) { - streamToClose.close(); - } - } - } - - // stc is the actual stream to be closed; it might be this object, or - // it might be an upstream object for which this object is downstream. - // - private void closeDeferred(InputStream stc) throws IOException { - synchronized (lock) { - if (useCount == 0) { - stc.close(); - } else { - closePending = true; - streamToClose = stc; - } - } - } - - public void close() throws IOException { - synchronized (lock) { - useCount = 0; - closePending = false; - } - super.close(); - } - - public int read() throws IOException { - raise(); - try { - return super.read(); - } finally { - lower(); - } - } - - public int read(byte[] b) throws IOException { - raise(); - try { - return super.read(b); - } finally { - lower(); - } - } - - public int read(byte[] b, int off, int len) throws IOException { - raise(); - try { - return super.read(b, off, len); - } finally { - lower(); - } - } - - public long skip(long n) throws IOException { - raise(); - try { - return super.skip(n); - } finally { - lower(); - } - } - - public int available() throws IOException { - raise(); - try { - return super.available(); - } finally { - lower(); - } - } - } - /** * A buffered input stream for a subprocess pipe file descriptor * that allows the underlying file descriptor to be reclaimed when @@ -757,7 +653,7 @@ final class ProcessImpl extends Process { * will block if another thread is at the same time blocked in a file * operation (e.g. 'read()') on the same file descriptor. We therefore * combine 'ProcessPipeInputStream' approach used on Linux and Bsd - * with the DeferredCloseInputStream approach used on Solaris. This means + * with the deferring 'close' of InputStream. This means * that every potentially blocking operation on the file descriptor * increments a counter before it is executed and decrements it once it * finishes. The 'close()' operation will only be executed if there are -- GitLab From a24f44d17de586c72c8343f8891e72ad8a514597 Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Wed, 26 Jan 2022 08:31:49 +0000 Subject: [PATCH 294/564] 8280526: x86_32 Math.sqrt performance regression with -XX:UseSSE={0,1} Reviewed-by: kvn, neliasso --- src/hotspot/cpu/x86/x86.ad | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/hotspot/cpu/x86/x86.ad b/src/hotspot/cpu/x86/x86.ad index 917a9ac84b7..a9dc2997e21 100644 --- a/src/hotspot/cpu/x86/x86.ad +++ b/src/hotspot/cpu/x86/x86.ad @@ -1608,9 +1608,14 @@ const bool Matcher::match_rule_supported(int opcode) { } break; case Op_SqrtD: +#ifdef _LP64 if (UseSSE < 2) { return false; } +#else + // x86_32.ad has a special match rule for SqrtD. + // Together with common x86 rules, this handles all UseSSE cases. +#endif break; } return true; // Match rules are supported by default. -- GitLab From c180070cb59b8e075376ae913c5db9a4ed868303 Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Wed, 26 Jan 2022 08:41:37 +0000 Subject: [PATCH 295/564] 8280373: Update Xalan serializer / SystemIDResolver to align with JDK-8270492 Reviewed-by: yan, joehw --- .../xml/internal/serializer/utils/SystemIDResolver.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/utils/SystemIDResolver.java b/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/utils/SystemIDResolver.java index f2c198c9f09..fa4e0c90126 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/utils/SystemIDResolver.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/utils/SystemIDResolver.java @@ -1,6 +1,5 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -42,6 +41,8 @@ import com.sun.org.apache.xml.internal.serializer.utils.URI.MalformedURIExceptio * used in com.sun.org.apache.xml.internal.serializer. * * @xsl.usage internal + * + * @LastModified: Jan 2022 */ public final class SystemIDResolver { @@ -282,7 +283,7 @@ public final class SystemIDResolver public static String getAbsoluteURI(String urlString, String base) throws TransformerException { - if (base == null) + if (base == null || base.length() == 0) return getAbsoluteURI(urlString); String absoluteBase = getAbsoluteURI(base); -- GitLab From ed0df2fa1f1cb019eadd0083a5006b3142ac0eb5 Mon Sep 17 00:00:00 2001 From: Emanuel Peter Date: Wed, 26 Jan 2022 10:12:22 +0000 Subject: [PATCH 296/564] 8268033: compiler/intrinsics/bmi/verifycode/BzhiTestI2L.java fails with "fatal error: Not compilable at tier 3: CodeBuffer overflow" Reviewed-by: kvn, neliasso, chagedorn --- test/hotspot/jtreg/ProblemList-Xcomp.txt | 2 -- .../jtreg/compiler/intrinsics/bmi/verifycode/BzhiTestI2L.java | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/test/hotspot/jtreg/ProblemList-Xcomp.txt b/test/hotspot/jtreg/ProblemList-Xcomp.txt index b56e43c4e92..23f25da41d0 100644 --- a/test/hotspot/jtreg/ProblemList-Xcomp.txt +++ b/test/hotspot/jtreg/ProblemList-Xcomp.txt @@ -27,8 +27,6 @@ # ############################################################################# -compiler/intrinsics/bmi/verifycode/BzhiTestI2L.java 8268033 generic-x64 - vmTestbase/nsk/jvmti/SetFieldAccessWatch/setfldw001/TestDescription.java 8205957 generic-all vmTestbase/vm/mlvm/mixed/stress/regression/b6969574/INDIFY_Test.java 8265295 linux-x64,windows-x64 diff --git a/test/hotspot/jtreg/compiler/intrinsics/bmi/verifycode/BzhiTestI2L.java b/test/hotspot/jtreg/compiler/intrinsics/bmi/verifycode/BzhiTestI2L.java index 93f54bdef73..08f83e1b8f0 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/bmi/verifycode/BzhiTestI2L.java +++ b/test/hotspot/jtreg/compiler/intrinsics/bmi/verifycode/BzhiTestI2L.java @@ -31,6 +31,7 @@ * @build sun.hotspot.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox * @run main/bootclasspath/othervm -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+AbortVMOnCompilationFailure + * -XX:CompileCommand=compileonly,compiler.intrinsics.bmi.*::* * -XX:+IgnoreUnrecognizedVMOptions -XX:+UseBMI2Instructions * compiler.intrinsics.bmi.verifycode.BzhiTestI2L */ -- GitLab From a07e19d8336f8fbea8736ba169787aec6d812817 Mon Sep 17 00:00:00 2001 From: Roman Kennke Date: Wed, 26 Jan 2022 11:05:30 +0000 Subject: [PATCH 297/564] 8278410: Improve argument processing around UseHeavyMonitors Reviewed-by: rehn, dholmes --- src/hotspot/share/runtime/arguments.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index 6d1e55f4c9a..fd551f1ec22 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -2015,16 +2015,23 @@ bool Arguments::check_vm_args_consistency() { #if !defined(X86) && !defined(AARCH64) && !defined(PPC64) if (UseHeavyMonitors) { - warning("UseHeavyMonitors is not fully implemented on this architecture"); + jio_fprintf(defaultStream::error_stream(), + "UseHeavyMonitors is not fully implemented on this architecture"); + return false; } #endif #if (defined(X86) || defined(PPC64)) && !defined(ZERO) if (UseHeavyMonitors && UseRTMForStackLocks) { - fatal("-XX:+UseHeavyMonitors and -XX:+UseRTMForStackLocks are mutually exclusive"); + jio_fprintf(defaultStream::error_stream(), + "-XX:+UseHeavyMonitors and -XX:+UseRTMForStackLocks are mutually exclusive"); + + return false; } #endif if (VerifyHeavyMonitors && !UseHeavyMonitors) { - fatal("-XX:+VerifyHeavyMonitors requires -XX:+UseHeavyMonitors"); + jio_fprintf(defaultStream::error_stream(), + "-XX:+VerifyHeavyMonitors requires -XX:+UseHeavyMonitors"); + return false; } return status; -- GitLab From f34f8d4d6a9b3e24a93a322b985c1413c27311cc Mon Sep 17 00:00:00 2001 From: stsypanov Date: Wed, 26 Jan 2022 14:12:51 +0000 Subject: [PATCH 298/564] 8277983: Remove unused fields from sun.net.www.protocol.jar.JarURLConnection Reviewed-by: dfuchs --- .../www/protocol/jar/JarURLConnection.java | 42 +++++-------------- 1 file changed, 11 insertions(+), 31 deletions(-) diff --git a/src/java.base/share/classes/sun/net/www/protocol/jar/JarURLConnection.java b/src/java.base/share/classes/sun/net/www/protocol/jar/JarURLConnection.java index 4ccf7819914..234827fb76f 100644 --- a/src/java.base/share/classes/sun/net/www/protocol/jar/JarURLConnection.java +++ b/src/java.base/share/classes/sun/net/www/protocol/jar/JarURLConnection.java @@ -25,21 +25,17 @@ package sun.net.www.protocol.jar; -import java.io.InputStream; -import java.io.IOException; -import java.io.FileNotFoundException; import java.io.BufferedInputStream; -import java.net.URL; -import java.net.URLConnection; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; import java.net.MalformedURLException; -import java.net.UnknownServiceException; -import java.util.Enumeration; -import java.util.Map; +import java.net.URL; +import java.security.Permission; import java.util.List; +import java.util.Map; import java.util.jar.JarEntry; import java.util.jar.JarFile; -import java.util.jar.Manifest; -import java.security.Permission; /** * @author Benjamin Renaud @@ -47,26 +43,10 @@ import java.security.Permission; */ public class JarURLConnection extends java.net.JarURLConnection { - private static final boolean debug = false; - /* the Jar file factory. It handles both retrieval and caching. */ private static final JarFileFactory factory = JarFileFactory.getInstance(); - /* the url for the Jar file */ - private URL jarFileURL; - - /* the permission to get this JAR file. This is the actual, ultimate, - * permission, returned by the jar file factory. - */ - private Permission permission; - - /* the url connection for the JAR file */ - private URLConnection jarFileURLConnection; - - /* the entry name, if any */ - private String entryName; - /* the JarEntry */ private JarEntry jarEntry; @@ -80,12 +60,10 @@ public class JarURLConnection extends java.net.JarURLConnection { throws MalformedURLException, IOException { super(url); - jarFileURL = getJarFileURL(); - jarFileURLConnection = jarFileURL.openConnection(); + jarFileURLConnection = getJarFileURL().openConnection(); // whether, or not, the embedded URL should use the cache will depend // on this instance's cache value jarFileURLConnection.setUseCaches(useCaches); - entryName = getEntryName(); } public JarFile getJarFile() throws IOException { @@ -120,7 +98,7 @@ public class JarURLConnection extends java.net.JarURLConnection { public void connect() throws IOException { if (!connected) { boolean useCaches = getUseCaches(); - String entryName = this.entryName; + String entryName = getEntryName(); /* the factory call will do the security checks */ URL url = getJarFileURL(); @@ -176,6 +154,7 @@ public class JarURLConnection extends java.net.JarURLConnection { InputStream result = null; + String entryName = getEntryName(); if (entryName == null) { throw new IOException("no entry name specified"); } else { @@ -216,7 +195,7 @@ public class JarURLConnection extends java.net.JarURLConnection { Object result = null; connect(); - if (entryName == null) { + if (getEntryName() == null) { result = jarFile; } else { result = super.getContent(); @@ -226,6 +205,7 @@ public class JarURLConnection extends java.net.JarURLConnection { public String getContentType() { if (contentType == null) { + String entryName = getEntryName(); if (entryName == null) { contentType = "x-java/jar"; } else { -- GitLab From e1d8f555644e7766811bda1468af3f7f3d3f4239 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Wed, 26 Jan 2022 17:06:50 +0000 Subject: [PATCH 299/564] 8280402: Add new convenience forms to HtmlTree Reviewed-by: hannesw --- .../formats/html/HtmlDocletWriter.java | 46 ++--- .../doclets/formats/html/markup/HtmlTree.java | 161 +++++++++++++----- .../internal/doclets/toolkit/Content.java | 21 +++ 3 files changed, 154 insertions(+), 74 deletions(-) diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java index 1c325db50e9..7efa7b85992 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java @@ -27,6 +27,7 @@ package jdk.javadoc.internal.doclets.formats.html; import java.util.ArrayList; import java.util.Collections; +import java.util.Comparator; import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; @@ -263,7 +264,7 @@ public class HtmlDocletWriter { do { int match = docrootMatcher.start(); // append htmlstr up to start of next {@docroot} - buf.append(htmlstr.substring(prevEnd, match)); + buf.append(htmlstr, prevEnd, match); prevEnd = docrootMatcher.end(); if (options.docrootParent().length() > 0 && htmlstr.startsWith("/..", prevEnd)) { // Insert the absolute link if {@docRoot} is followed by "/..". @@ -549,8 +550,7 @@ public class HtmlDocletWriter { protected Content getNavLinkMainTree(String label) { Content mainTreeContent = links.createLink(pathToRoot.resolve(DocPaths.OVERVIEW_TREE), Text.of(label)); - Content li = HtmlTree.LI(mainTreeContent); - return li; + return HtmlTree.LI(mainTreeContent); } /** @@ -623,7 +623,7 @@ public class HtmlDocletWriter { } else { flags = EnumSet.noneOf(ElementFlag.class); } - DocLink targetLink = null; + DocLink targetLink; if (included || packageElement == null) { targetLink = new DocLink(pathString(packageElement, DocPaths.PACKAGE_SUMMARY)); } else { @@ -1531,18 +1531,11 @@ public class HtmlDocletWriter { return false; } sb.append("="); - String quote; - switch (node.getValueKind()) { - case DOUBLE: - quote = "\""; - break; - case SINGLE: - quote = "'"; - break; - default: - quote = ""; - break; - } + String quote = switch (node.getValueKind()) { + case DOUBLE -> "\""; + case SINGLE -> "'"; + default -> ""; + }; sb.append(quote); result.add(sb); Content docRootContent = new ContentBuilder(); @@ -1794,9 +1787,9 @@ public class HtmlDocletWriter { if (detail.isEmpty() || detail.get().isEmpty()) { return HtmlTree.SPAN(HtmlStyle.invalidTag, Text.of(summary)); } - return new HtmlTree(TagName.DETAILS).addStyle(HtmlStyle.invalidTag) - .add(new HtmlTree(TagName.SUMMARY).add(Text.of(summary))) - .add(new HtmlTree(TagName.PRE).add(detail.get())); + return HtmlTree.DETAILS(HtmlStyle.invalidTag) + .add(HtmlTree.SUMMARY(Text.of(summary))) + .add(HtmlTree.PRE(detail.get())); } /** @@ -2226,17 +2219,13 @@ public class HtmlDocletWriter { for (Element e: chain) { String name; switch (e.getKind()) { - case MODULE: - case PACKAGE: + case MODULE, PACKAGE -> { name = ((QualifiedNameable) e).getQualifiedName().toString(); if (name.length() == 0) { name = ""; } - break; - - default: - name = e.getSimpleName().toString(); - break; + } + default -> name = e.getSimpleName().toString(); } if (sb.length() == 0) { @@ -2444,8 +2433,7 @@ public class HtmlDocletWriter { private Content withPreviewFeatures(String key, String className, String featureName, List features) { String[] sep = new String[] {""}; ContentBuilder featureCodes = new ContentBuilder(); - features.stream() - .forEach(c -> { + features.forEach(c -> { featureCodes.add(sep[0]); featureCodes.add(HtmlTree.CODE(new ContentBuilder().add(c))); sep[0] = ", "; @@ -2460,7 +2448,7 @@ public class HtmlDocletWriter { String[] sep = new String[] {""}; ContentBuilder links = new ContentBuilder(); elements.stream() - .sorted((te1, te2) -> te1.getSimpleName().toString().compareTo(te2.getSimpleName().toString())) + .sorted(Comparator.comparing(te -> te.getSimpleName().toString())) .distinct() .map(te -> getLink(new HtmlLinkInfo(configuration, HtmlLinkInfo.Kind.CLASS, te) .label(HtmlTree.CODE(Text.of(te.getSimpleName()))).skipPreview(true))) diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTree.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTree.java index 9d1ad310767..4b954ef1a31 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTree.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTree.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,14 +27,17 @@ package jdk.javadoc.internal.doclets.formats.html.markup; import java.io.IOException; import java.io.Writer; +import java.net.URI; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.BitSet; +import java.util.Collection; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.function.Function; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlAttr.Role; import jdk.javadoc.internal.doclets.toolkit.Content; @@ -222,6 +225,20 @@ public class HtmlTree extends Content { return this; } + /** + * Adds each of a collection of items, using a map function to create the content for each item. + * + * @param items the items + * @param mapper the map function to generate the content for each item + * + * @return this object + */ + @Override + public HtmlTree addAll(Collection items, Function mapper) { + items.forEach(item -> add(mapper.apply(item))); + return this; + } + @Override public int charCount() { int n = 0; @@ -301,6 +318,7 @@ public class HtmlTree extends Content { /** * Creates an HTML {@code A} element. + * The {@code ref} argument will be URL-encoded for use as the attribute value. * * @param ref the value for the {@code href} attribute} * @param body the content for element @@ -312,6 +330,22 @@ public class HtmlTree extends Content { .add(body); } + /** + * Creates an HTML {@code A} element. + * The {@code ref} argument is assumed to be already suitably encoded, + * and will not be additionally URL-encoded, but will be + * {@link URI#toASCIIString() converted} to ASCII for use as the attribute value. + * + * @param ref the value for the {@code href} attribute} + * @param body the content for element + * @return the element + */ + public static HtmlTree A(URI ref, Content body) { + return new HtmlTree(TagName.A) + .put(HtmlAttr.HREF, ref.toASCIIString()) + .add(body); + } + /** * Creates an HTML {@code CAPTION} element with the given content. * @@ -345,6 +379,16 @@ public class HtmlTree extends Content { .add(body); } + /** + * Creates an HTML {@code DETAILS} element. + * + * @return the element + */ + public static HtmlTree DETAILS(HtmlStyle style) { + return new HtmlTree(TagName.DETAILS) + .setStyle(style); + } + /** * Creates an HTML {@code DL} element with the given style. * @@ -495,12 +539,10 @@ public class HtmlTree extends Content { } private static TagName checkHeading(TagName headingTag) { - switch (headingTag) { - case H1: case H2: case H3: case H4: case H5: case H6: - return headingTag; - default: - throw new IllegalArgumentException(headingTag.toString()); - } + return switch (headingTag) { + case H1, H2, H3, H4, H5, H6 -> headingTag; + default -> throw new IllegalArgumentException(headingTag.toString()); + }; } /** @@ -682,6 +724,16 @@ public class HtmlTree extends Content { .setStyle(style); } + /** + * Creates an HTML {@code PRE} element with some content. + * + * @param body the content + * @return the element + */ + public static HtmlTree PRE(Content body) { + return new HtmlTree(TagName.PRE).add(body); + } + /** * Creates an HTML {@code SCRIPT} element with some script content. * The type of the script is set to {@code text/javascript}. @@ -782,6 +834,17 @@ public class HtmlTree extends Content { .add(body); } + /** + * Creates an HTML {@code SUMMARY} element with the given content. + * + * @param body the content + * @return the element + */ + public static HtmlTree SUMMARY(Content body) { + return new HtmlTree(TagName.SUMMARY) + .add(body); + } + /** * Creates an HTML {@code SUP} element with the given content. * @@ -874,6 +937,21 @@ public class HtmlTree extends Content { return htmlTree; } + /** + * Creates an HTML {@code UL} element with the given style and content generated + * from a collection of items.. + * + * @param style the style + * @param items the items to be added to the list + * @param mapper a mapper to create the content for each item + * @return the element + */ + public static HtmlTree UL(HtmlStyle style, Collection items, Function mapper) { + return new HtmlTree(TagName.UL) + .setStyle(style) + .addAll(items, mapper); + } + @Override public boolean isEmpty() { return (!hasContent() && !hasAttrs()); @@ -916,30 +994,29 @@ public class HtmlTree extends Content { */ @Override public boolean isValid() { - switch (tagName) { - case A: - return (hasAttr(HtmlAttr.ID) || (hasAttr(HtmlAttr.HREF) && hasContent())); - case BR: - return (!hasContent() && (!hasAttrs() || hasAttr(HtmlAttr.CLEAR))); - case HR: - case INPUT: - return (!hasContent()); - case IMG: - return (hasAttr(HtmlAttr.SRC) && hasAttr(HtmlAttr.ALT) && !hasContent()); - case LINK: - return (hasAttr(HtmlAttr.HREF) && !hasContent()); - case META: - return (hasAttr(HtmlAttr.CONTENT) && !hasContent()); - case SCRIPT: - return ((hasAttr(HtmlAttr.TYPE) && hasAttr(HtmlAttr.SRC) && !hasContent()) || - (hasAttr(HtmlAttr.TYPE) && hasContent())); - case SPAN: - return (hasAttr(HtmlAttr.ID) || hasContent()); - case WBR: - return (!hasContent()); - default : - return hasContent(); - } + return switch (tagName) { + case A -> + hasAttr(HtmlAttr.ID) || (hasAttr(HtmlAttr.HREF) && hasContent()); + case BR -> + !hasContent() && (!hasAttrs() || hasAttr(HtmlAttr.CLEAR)); + case HR, INPUT -> + !hasContent(); + case IMG -> + hasAttr(HtmlAttr.SRC) && hasAttr(HtmlAttr.ALT) && !hasContent(); + case LINK -> + hasAttr(HtmlAttr.HREF) && !hasContent(); + case META -> + hasAttr(HtmlAttr.CONTENT) && !hasContent(); + case SCRIPT -> + (hasAttr(HtmlAttr.TYPE) && hasAttr(HtmlAttr.SRC) && !hasContent()) + || (hasAttr(HtmlAttr.TYPE) && hasContent()); + case SPAN -> + hasAttr(HtmlAttr.ID) || hasContent(); + case WBR -> + !hasContent(); + default -> + hasContent(); + }; } /** @@ -950,14 +1027,10 @@ public class HtmlTree extends Content { * @see Phrasing Content */ public boolean isInline() { - switch (tagName) { - case A: case BUTTON: case BR: case CODE: case EM: case I: case IMG: - case LABEL: case SMALL: case SPAN: case STRONG: case SUB: case SUP: - case WBR: - return true; - default: - return false; - } + return switch (tagName) { + case A, BUTTON, BR, CODE, EM, I, IMG, LABEL, SMALL, SPAN, STRONG, SUB, SUP, WBR -> true; + default -> false; + }; } /** @@ -968,12 +1041,10 @@ public class HtmlTree extends Content { * @see Void Elements */ public boolean isVoid() { - switch (tagName) { - case BR: case HR: case IMG: case INPUT: case LINK: case META: case WBR: - return true; - default: - return false; - } + return switch (tagName) { + case BR, HR, IMG, INPUT, LINK, META, WBR -> true; + default -> false; + }; } @Override diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Content.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Content.java index 84cc66912b4..80dd9c48587 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Content.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Content.java @@ -28,6 +28,8 @@ package jdk.javadoc.internal.doclets.toolkit; import java.io.IOException; import java.io.StringWriter; import java.io.Writer; +import java.util.Collection; +import java.util.function.Function; /** * A class to create content for javadoc output pages. @@ -89,6 +91,25 @@ public abstract class Content { throw new UnsupportedOperationException(); } + /** + * Adds content to the existing content, generated from a collection of items + * This is an optional operation. + * + * @implSpec This implementation delegates to {@link #add(Content)}. + * + * @param items the items to be added + * @param mapper the function to create content for each item + * + * @return this object + * @throws UnsupportedOperationException if this operation is not supported by + * a particular implementation + * @throws IllegalArgumentException if the content is not suitable to be added + */ + public Content addAll(Collection items, Function mapper) { + items.forEach(item -> add(mapper.apply(item))); + return this; + } + /** * Writes content to a writer. * -- GitLab From 4b2370e57698e7413fef053afe9d22bb0bc86041 Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Wed, 26 Jan 2022 17:07:53 +0000 Subject: [PATCH 300/564] 8279294: NonblockingQueue::try_pop may improperly indicate queue is empty Reviewed-by: iwalulya, tschatzl --- .../utilities/nonblockingQueue.inline.hpp | 62 ++++++++++++------- 1 file changed, 41 insertions(+), 21 deletions(-) diff --git a/src/hotspot/share/utilities/nonblockingQueue.inline.hpp b/src/hotspot/share/utilities/nonblockingQueue.inline.hpp index 355b2120902..2fbd26f2dca 100644 --- a/src/hotspot/share/utilities/nonblockingQueue.inline.hpp +++ b/src/hotspot/share/utilities/nonblockingQueue.inline.hpp @@ -135,28 +135,46 @@ bool NonblockingQueue::try_pop(T** node_ptr) { } T* next_node = Atomic::load_acquire(next_ptr(*result)); - if (next_node == NULL) { - // A concurrent try_pop already claimed what was the last entry. That - // operation may not have cleared queue head yet, but we should still - // treat the queue as empty until a push/append operation changes head - // to an entry with a non-NULL next value. - *node_ptr = NULL; - return true; - - } else if (!is_end(next_node)) { - // The next_node is not at the end of the queue's list. Use the "usual" - // lock-free pop from the head of a singly linked list to try to take it. - if (result == Atomic::cmpxchg(&_head, result, next_node)) { - // Former head successfully taken. + if (!is_end(next_node)) { + // [Clause 1] + // There are several cases for next_node. + // (1) next_node is the extension of the queue's list. + // (2) next_node is NULL, because a competing try_pop took result. + // (3) next_node is the extension of some unrelated list, because a + // competing try_pop took result and put it in some other list. + // + // Attempt to advance the list, replacing result with next_node in + // _head. The success or failure of that attempt, along with the value + // of next_node, are used to partially determine which case we're in and + // how to proceed. In particular, advancement will fail for case (3). + if (result != Atomic::cmpxchg(&_head, result, next_node)) { + // [Clause 1a] + // The cmpxchg to advance the list failed; a concurrent try_pop won + // the race and claimed result. This can happen for any of the + // next_node cases. + return false; + } else if (next_node == NULL) { + // [Clause 1b] + // The cmpxchg to advance the list succeeded, but a concurrent try_pop + // has already claimed result (see [Clause 2] - result was the last + // entry in the list) by nulling result's next field. The advance set + // _head to NULL, "helping" the competing try_pop. _head will remain + // NULL until a subsequent push/append. This is a lost race, and we + // report it as such for consistency, though we could report the queue + // was empty. + return false; + } else { + // [Clause 1c] + // Successfully advanced the list and claimed result. next_node was + // in the extension of the queue's list. Return result after + // unlinking it from next_node. set_next(*result, NULL); *node_ptr = result; return true; - } else { - // Lost race to take result from the head of the list. - return false; } - } else if (is_end(Atomic::cmpxchg(next_ptr(*result), end_marker(), (T*)NULL))) { + } else if (is_end(Atomic::cmpxchg(next_ptr(*result), next_node, (T*)NULL))) { + // [Clause 2] // Result was the last entry and we've claimed it by setting its next // value to NULL. However, this leaves the queue in disarray. Fix up // the queue, possibly in conjunction with other concurrent operations. @@ -170,7 +188,8 @@ bool NonblockingQueue::try_pop(T** node_ptr) { Atomic::cmpxchg(&_tail, result, (T*)NULL); // Attempt to change the queue head from result to NULL. Failure of the - // cmpxchg indicates a concurrent push/append updated the head first. + // cmpxchg indicates a concurrent operation updated _head first. That + // could be either a push/extend or a try_pop in [Clause 1b]. Atomic::cmpxchg(&_head, result, (T*)NULL); // The queue has been restored to order, and we can return the result. @@ -178,9 +197,10 @@ bool NonblockingQueue::try_pop(T** node_ptr) { return true; } else { - // Result was the last entry in the list, but either a concurrent pop - // claimed it first or a concurrent push/append extended the list from - // it. Either way, we lost the race. + // [Clause 3] + // Result was the last entry in the list, but either a concurrent + // try_pop claimed it first or a concurrent push/append extended the + // list from it. Either way, we lost the race to claim it. return false; } } -- GitLab From b8365aa48599a318c426c2ec4ffb3f296ffdbd73 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Wed, 26 Jan 2022 17:10:45 +0000 Subject: [PATCH 301/564] 8268978: Document the javadoc software stack Reviewed-by: hannesw --- .../jdk/javadoc/internal/package-info.java | 139 +++++++++++++++++- 1 file changed, 132 insertions(+), 7 deletions(-) diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/package-info.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/package-info.java index 473e44ff421..4d7da0ba7cd 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/package-info.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,21 +24,146 @@ */ /** - * The implementation of the javadoc tool, and associated doclets. + * The implementation of the javadoc tool and associated doclets. * - *

    Internally, javadoc is composed of two primary parts: + *

    Internally, javadoc is composed of two primary parts: * the {@link jdk.javadoc.internal.tool tool}, and a series of * {@link jdk.javadoc.internal.doclets doclets}. * - * The tool provides a common infrastructure for command-line processing, - * and for reading the documentation comments in Java source files, + *

    The tool provides a common infrastructure for command-line processing, + * and for reading the declarations and documentation comments in Java source files, * while doclets provide a user-selectable backend for determining - * how to process the documentation comments. + * how to process the declarations and their documentation comments. + * + *

    The following provides a top-down description of the overall javadoc + * software stack. + * + *

    + *
    Doclets + *
    + *
    + *
    The Standard Doclet + *

    + * The {@link jdk.javadoc.doclet.StandardDoclet} is a thin public wrapper + * around the internal HTML doclet. + * + *

    The HTML Doclet + *

    + * The {@link jdk.javadoc.internal.doclets.formats.html.HtmlDoclet} class + * and other classes in the + * {@link jdk.javadoc.internal.doclets.formats.html formats.html} package + * customize the abstract pages generated by the toolkit layer to generate + * HTML pages. Some pages are specific to the HTML output format, + * and do not have an abstract builder in the toolkit layer. + * + *

    Individual pages of output are generated by page-specific subtypes of + * {@link jdk.javadoc.internal.doclets.formats.html.HtmlDocletWriter}. + * + *

    The {@link jdk.javadoc.internal.doclets.formats.html.HtmlConfiguration} class + * provides configuration information that is relevant to all the generated pages. + * The class extends the {@link jdk.javadoc.internal.doclets.toolkit.BaseConfiguration} + * class provided by the toolkit layer. + * + *

    The classes in the {@code formats.html} package use an internal + * library in the + * {@link jdk.javadoc.internal.doclets.formats.html.markup formats.html.markup} package, + * to create trees (or acyclic graphs) of + * {@linkplain jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree HTML tree nodes}. + * Apart from using a common format-neutral supertype, + * {@link jdk.javadoc.internal.doclets.toolkit.Content}, the {@code markup} library + * is mostly independent of the rest of the javadoc software stack. + * + *

    Toolkit + *

    + * The {@link jdk.javadoc.internal.doclets.toolkit toolkit} package provides + * support for a format-neutral + * {@linkplain jdk.javadoc.internal.doclets.toolkit.AbstractDoclet abstract doclet}, + * which uses + * {@linkplain jdk.javadoc.internal.doclets.toolkit.builders.AbstractBuilder builders} + * to generate pages of abstract + * {@linkplain jdk.javadoc.internal.doclets.toolkit.Content content}. + * + *

    The format-specific content for each page is provided by implementations + * of various writer interfaces, created by a format-specific + * {@linkplain jdk.javadoc.internal.doclets.toolkit.WriterFactory writer factory}. + * + *

    The {@link jdk.javadoc.internal.doclets.toolkit.BaseConfiguration} provides + * configuration information that is relevant to all the generated pages. + * Some of the information is provided by abstract methods which are implemented + * in format-specific subtypes of the class. + * + *

    The toolkit layer also provides + * {@linkplain jdk.javadoc.internal.doclets.toolkit.util utility classes} + * used by this layer and by format-specific layers. + * + *

    Generally, it is intended that doclets should use the + * {@link javax.lang.model Language Model API} to navigate the structure of a Java program, + * without needing to access any internal details of the underlying javac implementation. + * However, there are still some shortcomings of the Language Model API, + * and so it is still necessary to provide limited access to some of those internal details. + * Although not enforceable by the module system, by design the access to javac + * internal details by doclets based on {@code AbstractDoclet} is restricted to the aptly-named + * {@link jdk.javadoc.internal.doclets.toolkit.WorkArounds} class. + * + *

    Other Doclets + *

    + * Doclets are obviously not required to use + * {@link jdk.javadoc.internal.doclets.toolkit.AbstractDoclet} and other classes in + * the toolkit layer. In times past, it was common to write doclets to analyze + * code using the then-current API as an early version of a Java language model. + * That old API has been replaced by the {@link javax.lang.model Language Model API}, + * and tools that wish to use that API to analyze Java programs have a choice of + * how to invoke it, using the javac support for + * {@linkplain javax.annotation.processing annotation processing}, + * or {@linkplain com.sun.source.util.Plugin plugins}, as well as doclets. + * Which is best for any application will depend of the circumstances, but + * if a tool does not need access to the documentation comments in a program, + * it is possible that one of the other invocation mechanisms will be more convenient. + * + *

    + * + *
    The Doclet Interface + *

    + * The {@linkplain jdk.javadoc.doclet Doclet API} is the interface layer between + * the javadoc tool and the code to process the elements specified to the tool. + * + *

    Above this layer, in any doclet, the code is expected to use the + * {@linkplain javax.lang.model Language Model API} to navigate around the specified + * elements, and/or the {@linkplain com.sun.source.doctree DocTree API} to examine + * the corresponding documentation comments. + * + *

    The javadoc Tool + *

    + * After reading the command-line options, the tool uses a modified javac + * front end to read the necessary files and thus instantiate the + * {@linkplain javax.lang.model.element.Element elements} to be made available to + * the doclet that will be used to process them. + * + * The tool uses an internal feature of the javac architecture, which + * allows various components to be replaced by subtypes with modified behavior. + * This is done by pre-registering the desired components in the javac + * {@code Context}. + * The tool uses this mechanism to do the following: + *

      + *
    • although source files are parsed in their entirety, the + * content of method bodies is quickly discarded as unnecessary; + *
    • the class reader is updated to handle {@code package.html} + * files in any package directories that are read; and + *
    • the compilation pipeline for each source file is terminated + * after the parse and enter phases, meaning that + * the files are processed enough to instantiate the elements to + * be made available to the doclet, but no more. + *
    + *
    * * *

    This is NOT part of any supported API. * If you write code that depends on this, you do so at your own risk. * This code and its internal interfaces are subject to change or * deletion without notice. + * + * @see JavaDoc Architecture + * @see Using the new Doclet API + * @see Processing Code */ -package jdk.javadoc.internal; +package jdk.javadoc.internal; \ No newline at end of file -- GitLab From 0c42e43f77b91a50fedc3fddb74e17f910d8df2a Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Wed, 26 Jan 2022 17:25:30 +0000 Subject: [PATCH 302/564] 8280550: SplittableRandom#nextDouble(double,double) can return result >= bound Reviewed-by: jlaskey, psandoz --- .../internal/util/random/RandomSupport.java | 4 +- .../util/Random/RandomNextDoubleBoundary.java | 52 +++++++++++++++++++ 2 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 test/jdk/java/util/Random/RandomNextDoubleBoundary.java diff --git a/src/java.base/share/classes/jdk/internal/util/random/RandomSupport.java b/src/java.base/share/classes/jdk/internal/util/random/RandomSupport.java index d47043b89aa..99ca3da322d 100644 --- a/src/java.base/share/classes/jdk/internal/util/random/RandomSupport.java +++ b/src/java.base/share/classes/jdk/internal/util/random/RandomSupport.java @@ -645,7 +645,7 @@ public class RandomSupport { if (origin < bound) { r = r * (bound - origin) + origin; if (r >= bound) // may need to correct a rounding problem - r = Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1); + r = Math.nextAfter(r, origin); } return r; } @@ -677,7 +677,7 @@ public class RandomSupport { double r = rng.nextDouble(); r = r * bound; if (r >= bound) // may need to correct a rounding problem - r = Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1); + r = Math.nextDown(r); return r; } diff --git a/test/jdk/java/util/Random/RandomNextDoubleBoundary.java b/test/jdk/java/util/Random/RandomNextDoubleBoundary.java new file mode 100644 index 00000000000..511f251aed6 --- /dev/null +++ b/test/jdk/java/util/Random/RandomNextDoubleBoundary.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2022, 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 + * @summary Verify nextDouble stays within range + * @bug 8280550 + */ + +import java.util.SplittableRandom; + +public class RandomNextDoubleBoundary { + public static void main(String... args) { + // Both bounds are negative + double lowerBound = -1.0000000000000002; + double upperBound = -1.0; + var sr = new SplittableRandom(42L); + var r = sr.nextDouble(lowerBound, upperBound); + + if (r >= upperBound) { + System.err.println("r = " + r + "\t" + Double.toHexString(r)); + System.err.println("ub = " + upperBound + "\t" + Double.toHexString(upperBound)); + throw new RuntimeException("Greater than upper bound"); + } + + if (r < lowerBound) { + System.err.println("r = " + r + "\t" + Double.toHexString(r)); + System.err.println("lb = " + lowerBound + "\t" + Double.toHexString(lowerBound)); + throw new RuntimeException("Less than lower bound"); + } + } +} -- GitLab From b5de2cc9d36e1fad7d0bf70f7c83ff829e16b7f3 Mon Sep 17 00:00:00 2001 From: Liam Miller-Cushon Date: Wed, 26 Jan 2022 17:40:17 +0000 Subject: [PATCH 303/564] 8280546: Remove hard-coded 127.0.0.1 loopback address Reviewed-by: mullan --- test/jdk/javax/net/ssl/TLS/TestJSSE.java | 3 ++- test/jdk/javax/net/ssl/sanity/interop/JSSEClient.java | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/test/jdk/javax/net/ssl/TLS/TestJSSE.java b/test/jdk/javax/net/ssl/TLS/TestJSSE.java index 2c5a2c6274d..29631064011 100644 --- a/test/jdk/javax/net/ssl/TLS/TestJSSE.java +++ b/test/jdk/javax/net/ssl/TLS/TestJSSE.java @@ -21,12 +21,13 @@ * questions. */ +import java.net.InetAddress; import java.security.Provider; import java.security.Security; public class TestJSSE { - private static final String LOCAL_IP = "127.0.0.1"; + private static final String LOCAL_IP = InetAddress.getLoopbackAddress().getHostAddress(); public static void main(String... args) throws Exception { // reset the security property to make sure that the algorithms diff --git a/test/jdk/javax/net/ssl/sanity/interop/JSSEClient.java b/test/jdk/javax/net/ssl/sanity/interop/JSSEClient.java index 2207749302d..21416f0aaef 100644 --- a/test/jdk/javax/net/ssl/sanity/interop/JSSEClient.java +++ b/test/jdk/javax/net/ssl/sanity/interop/JSSEClient.java @@ -23,6 +23,7 @@ import java.io.InputStream; import java.io.OutputStream; +import java.net.InetAddress; import java.security.cert.Certificate; import javax.net.ssl.KeyManager; @@ -52,7 +53,8 @@ class JSSEClient extends CipherTest.Client { new TrustManager[] { CipherTest.trustManager }, CipherTest.secureRandom); SSLSocketFactory factory = (SSLSocketFactory)sslContext.getSocketFactory(); - socket = (SSLSocket)factory.createSocket("127.0.0.1", CipherTest.serverPort); + socket = (SSLSocket)factory.createSocket( + InetAddress.getLoopbackAddress().getHostAddress(), CipherTest.serverPort); socket.setSoTimeout(CipherTest.TIMEOUT); socket.setEnabledCipherSuites(new String[] { params.cipherSuite.name() }); socket.setEnabledProtocols(new String[] { params.protocol.name }); -- GitLab From d2a50a64920d22bbbd19ac7fa8681ff177799faf Mon Sep 17 00:00:00 2001 From: Alexandre Iline Date: Wed, 26 Jan 2022 18:05:15 +0000 Subject: [PATCH 304/564] 8279636: Update JCov version to 3.0.12 Reviewed-by: alanb, erikj --- make/conf/jib-profiles.js | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/make/conf/jib-profiles.js b/make/conf/jib-profiles.js index 5603678d4b8..e0041e91851 100644 --- a/make/conf/jib-profiles.js +++ b/make/conf/jib-profiles.js @@ -1169,15 +1169,8 @@ var getJibProfilesDependencies = function (input, common) { }, jcov: { - // Use custom build of JCov - // See CODETOOLS-7902734 for more info. - // server: "jpg", - // product: "jcov", - // version: "3.0", - // build_number: "b07", - // file: "bundles/jcov-3_0.zip", organization: common.organization, - revision: "3.0-9-jdk-asm+1.0", + revision: "3.0-12-jdk-asm+1.0", ext: "zip", environment_name: "JCOV_HOME", }, -- GitLab From 16e0ad0ad088af3ba1c9903ed8df60799a1ba651 Mon Sep 17 00:00:00 2001 From: Chris Plummer Date: Wed, 26 Jan 2022 18:06:05 +0000 Subject: [PATCH 305/564] 8270199: Most SA tests are skipped on macosx-aarch64 because all executables are signed Reviewed-by: dholmes, kevinw --- test/hotspot/jtreg/ProblemList.txt | 8 +-- ...stMutuallyExclusivePlatformPredicates.java | 4 +- test/lib/jdk/test/lib/Platform.java | 65 +++++++++++-------- test/lib/jdk/test/lib/SA/SATestUtils.java | 6 +- test/lib/jdk/test/lib/util/CoreUtils.java | 8 +-- 5 files changed, 50 insertions(+), 41 deletions(-) diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index b05f3317527..e08217cd776 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -1,5 +1,5 @@ # -# Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2016, 2022, 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 @@ -121,10 +121,10 @@ serviceability/dcmd/gc/RunFinalizationTest.java 8227120 linux-all,windows-x64 serviceability/sa/ClhsdbCDSCore.java 8269982,8267433 macosx-aarch64,macosx-x64 serviceability/sa/ClhsdbFindPC.java#xcomp-core 8269982,8267433 macosx-aarch64,macosx-x64 serviceability/sa/ClhsdbFindPC.java#no-xcomp-core 8269982,8267433 macosx-aarch64,macosx-x64 -serviceability/sa/ClhsdbPmap.java#core 8267433 macosx-x64 +serviceability/sa/ClhsdbPmap.java#core 8269982,8267433 macosx-aarch64,macosx-x64 serviceability/sa/ClhsdbPstack.java#core 8269982,8267433 macosx-aarch64,macosx-x64 -serviceability/sa/TestJmapCore.java 8267433 macosx-x64 -serviceability/sa/TestJmapCoreMetaspace.java 8267433 macosx-x64 +serviceability/sa/TestJmapCore.java 8269982,8267433 macosx-aarch64,macosx-x64 +serviceability/sa/TestJmapCoreMetaspace.java 8269982,8267433 macosx-aarch64,macosx-x64 ############################################################################# diff --git a/test/lib-test/jdk/test/lib/TestMutuallyExclusivePlatformPredicates.java b/test/lib-test/jdk/test/lib/TestMutuallyExclusivePlatformPredicates.java index 4be69a6566c..3ca1de653a4 100644 --- a/test/lib-test/jdk/test/lib/TestMutuallyExclusivePlatformPredicates.java +++ b/test/lib-test/jdk/test/lib/TestMutuallyExclusivePlatformPredicates.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -53,7 +53,7 @@ public class TestMutuallyExclusivePlatformPredicates { IGNORED("isEmulatedClient", "isDebugBuild", "isFastDebugBuild", "isSlowDebugBuild", "hasSA", "isRoot", "isTieredSupported", "areCustomLoadersSupportedForCDS", "isDefaultCDSArchiveSupported", - "isSignedOSX"); + "isHardenedOSX"); public final List methodNames; diff --git a/test/lib/jdk/test/lib/Platform.java b/test/lib/jdk/test/lib/Platform.java index 7666fdcc459..a8405c93722 100644 --- a/test/lib/jdk/test/lib/Platform.java +++ b/test/lib/jdk/test/lib/Platform.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,8 +23,10 @@ package jdk.test.lib; +import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.IOException; +import java.io.InputStreamReader; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -242,13 +244,13 @@ public class Platform { } /** - * Return true if the test JDK is signed, otherwise false. Only valid on OSX. + * Return true if the test JDK is hardened, otherwise false. Only valid on OSX. */ - public static boolean isSignedOSX() throws IOException { - // We only care about signed binaries for 10.14 and later (actually 10.14.5, but + public static boolean isHardenedOSX() throws IOException { + // We only care about hardened binaries for 10.14 and later (actually 10.14.5, but // for simplicity we'll also include earlier 10.14 versions). if (getOsVersionMajor() == 10 && getOsVersionMinor() < 14) { - return false; // assume not signed + return false; // assume not hardened } // Find the path to the java binary. @@ -260,38 +262,45 @@ public class Platform { } // Run codesign on the java binary. - ProcessBuilder pb = new ProcessBuilder("codesign", "-d", "-v", javaFileName); - pb.redirectError(ProcessBuilder.Redirect.DISCARD); - pb.redirectOutput(ProcessBuilder.Redirect.DISCARD); + ProcessBuilder pb = new ProcessBuilder("codesign", "--display", "--verbose", javaFileName); + pb.redirectErrorStream(true); // redirect stderr to stdout Process codesignProcess = pb.start(); + BufferedReader is = new BufferedReader(new InputStreamReader(codesignProcess.getInputStream())); + String line; + boolean isHardened = false; + boolean hardenedStatusConfirmed = false; // set true when we confirm whether or not hardened + while ((line = is.readLine()) != null) { + System.out.println("STDOUT: " + line); + if (line.indexOf("flags=0x10000(runtime)") != -1 ) { + hardenedStatusConfirmed = true; + isHardened = true; + System.out.println("Target JDK is hardened. Some tests may be skipped."); + } else if (line.indexOf("flags=0x20002(adhoc,linker-signed)") != -1 ) { + hardenedStatusConfirmed = true; + isHardened = false; + System.out.println("Target JDK is adhoc signed, but not hardened."); + } else if (line.indexOf("code object is not signed at all") != -1) { + hardenedStatusConfirmed = true; + isHardened = false; + System.out.println("Target JDK is not signed, therefore not hardened."); + } + } + if (!hardenedStatusConfirmed) { + System.out.println("Could not confirm if TargetJDK is hardened. Assuming not hardened."); + isHardened = false; + } + try { if (codesignProcess.waitFor(10, TimeUnit.SECONDS) == false) { - System.err.println("Timed out waiting for the codesign process to complete. Assuming not signed."); + System.err.println("Timed out waiting for the codesign process to complete. Assuming not hardened."); codesignProcess.destroyForcibly(); - return false; // assume not signed + return false; // assume not hardened } } catch (InterruptedException e) { throw new RuntimeException(e); } - // Check codesign result to see if java binary is signed. Here are the - // exit code meanings: - // 0: signed - // 1: not signed - // 2: invalid arguments - // 3: only has meaning with the -R argument. - // So we should always get 0 or 1 as an exit value. - if (codesignProcess.exitValue() == 0) { - System.out.println("Target JDK is signed. Some tests may be skipped."); - return true; // signed - } else if (codesignProcess.exitValue() == 1) { - System.out.println("Target JDK is not signed."); - return false; // not signed - } else { - System.err.println("Executing codesign failed. Assuming unsigned: " + - codesignProcess.exitValue()); - return false; // not signed - } + return isHardened; } private static boolean isArch(String archnameRE) { diff --git a/test/lib/jdk/test/lib/SA/SATestUtils.java b/test/lib/jdk/test/lib/SA/SATestUtils.java index 0ba91f2a994..d4daf5ef145 100644 --- a/test/lib/jdk/test/lib/SA/SATestUtils.java +++ b/test/lib/jdk/test/lib/SA/SATestUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -63,8 +63,8 @@ public class SATestUtils { throw new SkippedException("SA Attach not expected to work. Ptrace attach not supported."); } } else if (Platform.isOSX()) { - if (Platform.isSignedOSX()) { - throw new SkippedException("SA Attach not expected to work. JDK is signed."); + if (Platform.isHardenedOSX()) { + throw new SkippedException("SA Attach not expected to work. JDK is hardened."); } if (!Platform.isRoot() && !canAddPrivileges()) { throw new SkippedException("SA Attach not expected to work. Insufficient privileges (not root and can't use sudo)."); diff --git a/test/lib/jdk/test/lib/util/CoreUtils.java b/test/lib/jdk/test/lib/util/CoreUtils.java index 15de012534b..c9335792593 100644 --- a/test/lib/jdk/test/lib/util/CoreUtils.java +++ b/test/lib/jdk/test/lib/util/CoreUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -138,12 +138,12 @@ public class CoreUtils { if (!coresDir.canWrite()) { throw new SkippedException("Directory \"" + coresDir + "\" is not writable"); } - if (Platform.isSignedOSX()) { + if (Platform.isHardenedOSX()) { if (Platform.getOsVersionMajor() > 10 || (Platform.getOsVersionMajor() == 10 && Platform.getOsVersionMinor() >= 15)) { - // We can't generate cores files with signed binaries on OSX 10.15 and later. - throw new SkippedException("Cannot produce core file with signed binary on OSX 10.15 and later"); + // We can't generate cores files with hardened binaries on OSX 10.15 and later. + throw new SkippedException("Cannot produce core file with hardened binary on OSX 10.15 and later"); } } } else if (Platform.isLinux()) { -- GitLab From c2ee1b33c37e6f2848dc8b3e5417b93b1dac1112 Mon Sep 17 00:00:00 2001 From: Hai-May Chao Date: Wed, 26 Jan 2022 20:31:04 +0000 Subject: [PATCH 306/564] 8273236: keytool does not accurately warn about algorithms that are disabled but have additional constraints Reviewed-by: mullan --- .../sun/security/tools/keytool/Main.java | 423 +++++++++++++++--- .../sun/security/tools/keytool/Resources.java | 4 +- .../security/tools/keytool/TestSha1Usage.java | 60 +++ 3 files changed, 432 insertions(+), 55 deletions(-) create mode 100644 test/jdk/sun/security/tools/keytool/TestSha1Usage.java diff --git a/src/java.base/share/classes/sun/security/tools/keytool/Main.java b/src/java.base/share/classes/sun/security/tools/keytool/Main.java index 8cf77c96e69..de13f75aea9 100644 --- a/src/java.base/share/classes/sun/security/tools/keytool/Main.java +++ b/src/java.base/share/classes/sun/security/tools/keytool/Main.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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,10 +31,14 @@ import java.nio.file.Path; import java.security.*; import java.security.cert.Certificate; import java.security.cert.CertificateFactory; +import java.security.cert.CertPathValidatorException; +import java.security.cert.CertPathValidatorException.BasicReason; import java.security.cert.CertStoreException; import java.security.cert.CRL; import java.security.cert.X509Certificate; import java.security.cert.CertificateException; +import java.security.cert.CertificateParsingException; +import java.security.cert.TrustAnchor; import java.security.cert.URICertStoreParameters; @@ -43,6 +47,8 @@ import java.security.interfaces.EdECKey; import java.security.spec.ECParameterSpec; import java.text.Collator; import java.text.MessageFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; import java.util.*; import java.util.function.BiFunction; import java.util.jar.JarEntry; @@ -60,6 +66,7 @@ import javax.security.auth.x500.X500Principal; import java.util.Base64; import sun.security.pkcs12.PKCS12KeyStore; +import sun.security.provider.certpath.CertPathConstraintsParameters; import sun.security.util.ECKeySizeParameterSpec; import sun.security.util.KeyUtil; import sun.security.util.NamedCurve; @@ -83,6 +90,7 @@ import sun.security.tools.KeyStoreUtil; import sun.security.tools.PathList; import sun.security.util.DerValue; import sun.security.util.Pem; +import sun.security.validator.Validator; import sun.security.x509.*; import static java.security.KeyStore.*; @@ -178,6 +186,8 @@ public final class Main { // Warnings on weak algorithms etc private List weakWarnings = new ArrayList<>(); + private Set trustedCerts = new HashSet<>(); + private static final DisabledAlgorithmConstraints DISABLED_CHECK = new DisabledAlgorithmConstraints( DisabledAlgorithmConstraints.PROPERTY_CERTPATH_DISABLED_ALGS); @@ -1118,6 +1128,7 @@ public final class Main { } } + KeyStore cakstore = buildTrustedCerts(); // -trustcacerts can be specified on -importcert, -printcert or -printcrl. // Reset it so that warnings on CA cert will remain for other command. if (command != IMPORTCERT && command != PRINTCERT @@ -1126,7 +1137,13 @@ public final class Main { } if (trustcacerts) { - caks = KeyStoreUtil.getCacertsKeyStore(); + if (cakstore != null) { + caks = cakstore; + } else { + // try to load cacerts again, and let exception propagate + // if it cannot be loaded + caks = KeyStoreUtil.getCacertsKeyStore(); + } } // Perform the specified command @@ -1485,7 +1502,9 @@ public final class Main { byte[] rawReq = Pem.decode(new String(sb)); PKCS10 req = new PKCS10(rawReq); - checkWeak(rb.getString("the.certificate.request"), req); + CertPathConstraintsParameters cpcp = new CertPathConstraintsParameters( + req.getSubjectPublicKeyInfo(), null, null, null); + checkWeakConstraint(rb.getString("the.certificate.request"), req, cpcp); info.set(X509CertInfo.KEY, new CertificateX509Key(req.getSubjectPublicKeyInfo())); info.set(X509CertInfo.SUBJECT, @@ -1542,8 +1561,11 @@ public final class Main { } } - checkWeak(rb.getString("the.issuer"), keyStore.getCertificateChain(alias)); - checkWeak(rb.getString("the.generated.certificate"), cert); + checkWeakConstraint(rb.getString("the.issuer"), + keyStore.getCertificateChain(alias)); + cpcp = buildCertPathConstraint(cert, null); + checkWeakConstraint(rb.getString("the.generated.certificate"), + cert, cpcp); } private void doGenCRL(PrintStream out) @@ -1592,7 +1614,10 @@ public final class Main { } else { out.write(crl.getEncodedInternal()); } - checkWeak(rb.getString("the.generated.crl"), crl, privateKey); + CertPathConstraintsParameters cpcp = new CertPathConstraintsParameters( + privateKey, null, null, null); + checkWeakConstraint(rb.getString("the.generated.crl"), crl, privateKey, + cpcp); } /** @@ -1638,7 +1663,10 @@ public final class Main { request.encodeAndSign(subject, privKey, sigAlgName); request.print(out); - checkWeak(rb.getString("the.generated.certificate.request"), request); + CertPathConstraintsParameters cpcp = new CertPathConstraintsParameters( + request.getSubjectPublicKeyInfo(), null, null, null); + checkWeakConstraint(rb.getString("the.generated.certificate.request"), + request, cpcp); } /** @@ -1683,7 +1711,9 @@ public final class Main { throw new Exception(form.format(source)); } dumpCert(cert, out); - checkWeak(rb.getString("the.certificate"), cert); + CertPathConstraintsParameters cpcp = + buildCertPathConstraint(cert, null); + checkWeakConstraint(rb.getString("the.certificate"), cert, cpcp); } /** @@ -2021,7 +2051,8 @@ public final class Main { } else { finalChain = new Certificate[] { newCert }; } - checkWeak(rb.getString("the.generated.certificate"), finalChain); + checkWeakConstraint(rb.getString("the.generated.certificate"), + finalChain); keyStore.setKeyEntry(alias, privKey, keyPass, finalChain); } @@ -2114,6 +2145,7 @@ public final class Main { private void doPrintEntry(String label, String alias, PrintStream out) throws Exception { + CertPathConstraintsParameters cpcp; if (keyStore.containsAlias(alias) == false) { MessageFormat form = new MessageFormat (rb.getString("Alias.alias.does.not.exist")); @@ -2170,6 +2202,10 @@ public final class Main { if (verbose || rfc || debug) { out.println(rb.getString ("Certificate.chain.length.") + chain.length); + + X509Certificate[] xcerts = convertCerts(chain); + List certs = Arrays.asList(xcerts); + TrustAnchor anchor = findTrustAnchor(certs); for (int i = 0; i < chain.length; i ++) { MessageFormat form = new MessageFormat (rb.getString("Certificate.i.1.")); @@ -2182,14 +2218,26 @@ public final class Main { } else { dumpCert(chain[i], out); } - checkWeak(label, chain[i]); + + if (i == 0 && + ((X509Certificate)chain[0]). + getBasicConstraints() == -1) { + // this is an EE + cpcp = buildCertPathConstraint((X509Certificate) chain[i], anchor); + } else { + cpcp = new CertPathConstraintsParameters( + (X509Certificate)chain[i], null, anchor, + null); + } + + checkWeakConstraint(label, chain[i], cpcp); } } else { // Print the digest of the user cert only out.println (rb.getString("Certificate.fingerprint.SHA.256.") + getCertFingerPrint("SHA-256", chain[0])); - checkWeak(label, chain); + checkWeakConstraint(label, chain); } } else { out.println(rb.getString @@ -2215,7 +2263,8 @@ public final class Main { out.println(rb.getString("Certificate.fingerprint.SHA.256.") + getCertFingerPrint("SHA-256", cert)); } - checkWeak(label, cert); + cpcp = buildCertPathConstraint((X509Certificate)cert, null); + checkWeakConstraint(label, cert, cpcp); } else { out.println(rb.getString("Unknown.Entry.Type")); } @@ -2442,7 +2491,9 @@ public final class Main { try { Certificate c = srckeystore.getCertificate(alias); if (c != null) { - checkWeak("<" + newAlias + ">", c); + CertPathConstraintsParameters cpcp = + buildCertPathConstraint((X509Certificate)c, null); + checkWeakConstraint("<" + newAlias + ">", c, cpcp); } keyStore.setEntry(newAlias, entry, pp); // Place the check so that only successful imports are blocked. @@ -2639,11 +2690,14 @@ public final class Main { issuer = verifyCRL(caks, crl); if (issuer != null) { signer = caks.getCertificate(issuer); + CertPathConstraintsParameters cpcp = + buildCertPathConstraint((X509Certificate)signer, + null); out.printf(rb.getString( "verified.by.s.in.s.weak"), issuer, "cacerts", - withWeak(signer.getPublicKey())); + withWeakConstraint(signer.getPublicKey(), cpcp)); out.println(); } } @@ -2651,11 +2705,14 @@ public final class Main { issuer = verifyCRL(keyStore, crl); if (issuer != null) { signer = keyStore.getCertificate(issuer); + CertPathConstraintsParameters cpcp = + buildCertPathConstraint((X509Certificate)signer, + null); out.printf(rb.getString( "verified.by.s.in.s.weak"), issuer, "keystore", - withWeak(signer.getPublicKey())); + withWeakConstraint(signer.getPublicKey(), cpcp)); out.println(); } } @@ -2672,7 +2729,15 @@ public final class Main { out.println(rb.getString ("STARNN")); } - checkWeak(rb.getString("the.crl"), crl, signer == null ? null : signer.getPublicKey()); + + if (signer != null) { + CertPathConstraintsParameters cpcp = + buildCertPathConstraint((X509Certificate)signer, null); + checkWeakConstraint(rb.getString("the.crl"), crl, + signer.getPublicKey(), cpcp); + } else { + checkWeak(rb.getString("the.crl"), crl, null); + } } } @@ -2718,10 +2783,12 @@ public final class Main { PKCS10 req = new PKCS10(Pem.decode(new String(sb))); PublicKey pkey = req.getSubjectPublicKeyInfo(); + CertPathConstraintsParameters cpcp = + new CertPathConstraintsParameters(pkey, null, null, null); out.printf(rb.getString("PKCS.10.with.weak"), req.getSubjectName(), pkey.getFormat(), - withWeak(pkey), + withWeakConstraint(pkey, cpcp), withWeak(req.getSigAlg())); for (PKCS10Attribute attr: req.getAttributes().getAttributes()) { ObjectIdentifier oid = attr.getAttributeId(); @@ -2745,7 +2812,12 @@ public final class Main { if (debug) { out.println(req); // Just to see more, say, public key length... } - checkWeak(rb.getString("the.certificate.request"), req); + + CertPathConstraintsParameters cpcp1 = + new CertPathConstraintsParameters( + req.getSubjectPublicKeyInfo(), null, null, null); + checkWeakConstraint(rb.getString("the.certificate.request"), req, + cpcp1); } /** @@ -2765,6 +2837,9 @@ public final class Main { throw new Exception(rb.getString("Empty.input")); } Certificate[] certs = c.toArray(new Certificate[c.size()]); + X509Certificate[] xcerts = convertCerts(certs); + List chain = Arrays.asList(xcerts); + TrustAnchor anchor = findTrustAnchor(chain); for (int i=0; i certs = signer.getSignerCertPath().getCertificates(); + @SuppressWarnings("unchecked") + List chain = + (List)certs; + TrustAnchor anchor = findTrustAnchor(chain); + CertPathConstraintsParameters cpcp; int cc = 0; for (Certificate cert: certs) { out.printf(rb.getString("Certificate.d."), ++cc); @@ -2913,16 +3003,27 @@ public final class Main { printX509Cert(x, out); } out.println(); - checkWeak(oneInManys(rb.getString( + if (cc == 0 && x.getBasicConstraints() == -1) { + // this is an EE + cpcp = buildCertPathConstraint(x, anchor); + } else { + cpcp = new CertPathConstraintsParameters( + x, null, anchor, null); + } + checkWeakConstraint(oneInManys(rb.getString( "the.certificate"), cc, certs.size(), pos, - ss.size()), x); + ss.size()), x, cpcp); } Timestamp ts = signer.getTimestamp(); if (ts != null) { out.println(rb.getString("Timestamp.")); out.println(); certs = ts.getSignerCertPath().getCertificates(); + @SuppressWarnings("unchecked") + List tschain = + (List)certs; + anchor = findTrustAnchor(tschain); cc = 0; for (Certificate cert: certs) { out.printf(rb.getString("Certificate.d."), ++cc); @@ -2935,10 +3036,18 @@ public final class Main { printX509Cert(x, out); } out.println(); - checkWeak(oneInManys(rb.getString( + if (cc == 0 && + x.getBasicConstraints() == -1) { + // this is an EE + cpcp = buildCertPathConstraint(x, anchor); + } else { + cpcp = new CertPathConstraintsParameters( + x, null, anchor, null); + } + checkWeakConstraint(oneInManys(rb.getString( "the.tsa.certificate"), cc, certs.size(), pos, - ss.size()), x); + ss.size()), x, cpcp); } } } @@ -2968,6 +3077,9 @@ public final class Main { } int i = 0; + @SuppressWarnings("unchecked") + List xcerts = (List)chain; + TrustAnchor anchor = findTrustAnchor(xcerts); for (Certificate cert : chain) { try { if (rfc) { @@ -2978,7 +3090,17 @@ public final class Main { printX509Cert((X509Certificate)cert, out); out.println(); } - checkWeak(oneInMany(rb.getString("the.certificate"), i++, chain.size()), cert); + X509Certificate x = (X509Certificate)cert; + CertPathConstraintsParameters cpcp; + if (i == 0 && x.getBasicConstraints() == -1) { + // this is an EE + cpcp = buildCertPathConstraint(x, anchor); + } else { + cpcp = new CertPathConstraintsParameters( + x, null, anchor, null); + } + checkWeakConstraint(oneInMany(rb.getString( + "the.certificate"), i++, chain.size()), x, cpcp); } catch (Exception e) { if (debug) { e.printStackTrace(); @@ -3202,8 +3324,11 @@ public final class Main { throw new Exception(rb.getString("Input.not.an.X.509.certificate")); } + CertPathConstraintsParameters cpcp = + buildCertPathConstraint(cert, null); + if (noprompt) { - checkWeak(rb.getString("the.input"), cert); + checkWeakConstraint(rb.getString("the.input"), cert, cpcp); keyStore.setCertificateEntry(alias, cert); return true; } @@ -3223,7 +3348,7 @@ public final class Main { ("Certificate.already.exists.in.keystore.under.alias.trustalias.")); Object[] source = {trustalias}; System.err.println(form.format(source)); - checkWeak(rb.getString("the.input"), cert); + checkWeakConstraint(rb.getString("the.input"), cert, cpcp); printWeakWarnings(true); reply = getYesNoReply (rb.getString("Do.you.still.want.to.add.it.no.")); @@ -3234,7 +3359,7 @@ public final class Main { ("Certificate.already.exists.in.system.wide.CA.keystore.under.alias.trustalias.")); Object[] source = {trustalias}; System.err.println(form.format(source)); - checkWeak(rb.getString("the.input"), cert); + checkWeakConstraint(rb.getString("the.input"), cert, cpcp); printWeakWarnings(true); reply = getYesNoReply (rb.getString("Do.you.still.want.to.add.it.to.your.own.keystore.no.")); @@ -3243,7 +3368,7 @@ public final class Main { // Print the cert and ask user if they really want to add // it to their keystore printX509Cert(cert, System.out); - checkWeak(rb.getString("the.input"), cert); + checkWeakConstraint(rb.getString("the.input"), cert, cpcp); printWeakWarnings(true); reply = getYesNoReply (rb.getString("Trust.this.certificate.no.")); @@ -3270,7 +3395,7 @@ public final class Main { // Print the cert and ask user if they really want to add it to // their keystore printX509Cert(cert, System.out); - checkWeak(rb.getString("the.input"), cert); + checkWeakConstraint(rb.getString("the.input"), cert, cpcp); printWeakWarnings(true); reply = getYesNoReply (rb.getString("Trust.this.certificate.no.")); @@ -3410,6 +3535,21 @@ public final class Main { return keyPass; } + private String withWeakConstraint(String alg, + CertPathConstraintsParameters cpcp) { + try { + DISABLED_CHECK.permits(alg, cpcp, false); + } catch (CertPathValidatorException e) { + return String.format(rb.getString("with.disabled"), alg); + } + try { + LEGACY_CHECK.permits(alg, cpcp, false); + return alg; + } catch (CertPathValidatorException e) { + return String.format(rb.getString("with.weak"), alg); + } + } + private String withWeak(String alg) { if (DISABLED_CHECK.permits(SIG_PRIMITIVE_SET, alg, null)) { if (LEGACY_CHECK.permits(SIG_PRIMITIVE_SET, alg, null)) { @@ -3436,21 +3576,24 @@ public final class Main { return result; } - private String withWeak(Key key) { + private String withWeakConstraint(Key key, + CertPathConstraintsParameters cpcp) { int kLen = KeyUtil.getKeySize(key); String displayAlg = fullDisplayAlgName(key); - if (DISABLED_CHECK.permits(SIG_PRIMITIVE_SET, key)) { - if (LEGACY_CHECK.permits(SIG_PRIMITIVE_SET, key)) { - if (kLen >= 0) { - return String.format(rb.getString("key.bit"), kLen, displayAlg); - } else { - return String.format(rb.getString("unknown.size.1"), displayAlg); - } + try { + DISABLED_CHECK.permits(key.getAlgorithm(), cpcp, true); + } catch (CertPathValidatorException e) { + return String.format(rb.getString("key.bit.disabled"), kLen, displayAlg); + } + try { + LEGACY_CHECK.permits(key.getAlgorithm(), cpcp, true); + if (kLen >= 0) { + return String.format(rb.getString("key.bit"), kLen, displayAlg); } else { - return String.format(rb.getString("key.bit.weak"), kLen, displayAlg); + return String.format(rb.getString("unknown.size.1"), displayAlg); } - } else { - return String.format(rb.getString("key.bit.disabled"), kLen, displayAlg); + } catch (CertPathValidatorException e) { + return String.format(rb.getString("key.bit.weak"), kLen, displayAlg); } } @@ -3465,9 +3608,11 @@ public final class Main { (rb.getString(".PATTERN.printX509Cert.with.weak")); PublicKey pkey = cert.getPublicKey(); String sigName = cert.getSigAlgName(); + CertPathConstraintsParameters cpcp = + buildCertPathConstraint(cert, null); // No need to warn about sigalg of a trust anchor if (!isTrustedCert(cert)) { - sigName = withWeak(sigName); + sigName = withWeakConstraint(sigName, cpcp); } Object[] source = {cert.getSubjectX500Principal().toString(), cert.getIssuerX500Principal().toString(), @@ -3477,7 +3622,7 @@ public final class Main { getCertFingerPrint("SHA-1", cert), getCertFingerPrint("SHA-256", cert), sigName, - withWeak(pkey), + withWeakConstraint(pkey, cpcp), cert.getVersion() }; out.println(form.format(source)); @@ -3801,7 +3946,7 @@ public final class Main { throws Exception { - checkWeak(rb.getString("reply"), replyCerts); + checkWeakConstraint(rb.getString("reply"), replyCerts); // order the certs in the reply (bottom-up). // we know that all certs in the reply are of type X.509, because @@ -3883,11 +4028,14 @@ public final class Main { replyCerts.length); tmpCerts[tmpCerts.length-1] = root.snd; replyCerts = tmpCerts; - checkWeak(String.format(fromKeyStore + CertPathConstraintsParameters cpcp = + buildCertPathConstraint((X509Certificate)root.snd, + null); + checkWeakConstraint(String.format(fromKeyStore ? rb.getString("alias.in.keystore") : rb.getString("alias.in.cacerts"), root.fst), - root.snd); + root.snd, cpcp); } } return replyCerts; @@ -3952,7 +4100,9 @@ public final class Main { (X509Certificate) certToVerify), chain, certs)) { for (Pair p : chain) { - checkWeak(p.fst, p.snd); + CertPathConstraintsParameters cpcp = + buildCertPathConstraint(p.snd, null); + checkWeakConstraint(p.fst, p.snd, cpcp); } Certificate[] newChain = new Certificate[chain.size()]; @@ -4748,6 +4898,78 @@ public final class Main { } } + private void checkWeakConstraint(String label, String sigAlg, Key key, + CertPathConstraintsParameters cpcp) throws Exception { + if (sigAlg != null) { + try { + DISABLED_CHECK.permits(sigAlg, cpcp, false); + try { + LEGACY_CHECK.permits(sigAlg, cpcp, false); + } catch (CertPathValidatorException e) { + weakWarnings.add(String.format( + rb.getString("whose.sigalg.weak"), label, sigAlg)); + } + } catch (CertPathValidatorException e) { + String eMessage = e.getMessage(); + if (eMessage.contains("denyAfter constraint check failed") && + e.getReason() == BasicReason.ALGORITHM_CONSTRAINED) { + String startSeparator = "Constraint date: "; + int startSepPos = eMessage.indexOf(startSeparator); + String endSeparator = "; params date"; + int endSepPos = eMessage.indexOf(endSeparator); + String denyAfterDate = null; + try { + denyAfterDate = eMessage.substring(startSepPos + startSeparator.length(), + endSepPos); + } catch (IndexOutOfBoundsException e1) { + throw new Exception(rb.getString( + "Unable.to.parse.denyAfter.string.in.exception.message")); + } + + SimpleDateFormat formatter = new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy"); + Date dateObj = null; + try { + dateObj = formatter.parse(denyAfterDate); + } catch (ParseException e2) { + throw new Exception(rb.getString( + "Unable.to.parse.denyAfter.string.in.exception.message")); + } + formatter = new SimpleDateFormat("yyyy-MM-dd"); + denyAfterDate = formatter.format(dateObj); + + weakWarnings.add(String.format( + rb.getString("whose.sigalg.usagesignedjar"), label, sigAlg, + denyAfterDate)); + } else { + weakWarnings.add(String.format( + rb.getString("whose.sigalg.disabled"), label, sigAlg)); + } + if (debug) { + e.printStackTrace(); + } + } + } + + if (key != null) { + try { + DISABLED_CHECK.permits(key.getAlgorithm(), cpcp, true); + try { + LEGACY_CHECK.permits(key.getAlgorithm(), cpcp, true); + } catch (CertPathValidatorException e) { + weakWarnings.add(String.format( + rb.getString("whose.key.weak"), label, + String.format(rb.getString("key.bit"), + KeyUtil.getKeySize(key), fullDisplayAlgName(key)))); + } + } catch (CertPathValidatorException e) { + weakWarnings.add(String.format( + rb.getString("whose.key.disabled"), label, + String.format(rb.getString("key.bit"), + KeyUtil.getKeySize(key), fullDisplayAlgName(key)))); + } + } + } + private void checkWeak(String label, String sigAlg, Key key) { if (sigAlg != null) { if (!DISABLED_CHECK.permits(SIG_PRIMITIVE_SET, sigAlg, null)) { @@ -4774,8 +4996,11 @@ public final class Main { } } - private void checkWeak(String label, Certificate[] certs) - throws KeyStoreException { + private void checkWeakConstraint(String label, Certificate[] certs) + throws KeyStoreException, Exception { + X509Certificate[] xcerts = convertCerts(certs); + List chain = Arrays.asList(xcerts); + TrustAnchor anchor = findTrustAnchor(chain); for (int i = 0; i < certs.length; i++) { Certificate cert = certs[i]; if (cert instanceof X509Certificate) { @@ -4784,23 +5009,43 @@ public final class Main { if (certs.length > 1) { fullLabel = oneInMany(label, i, certs.length); } - checkWeak(fullLabel, xc); + + CertPathConstraintsParameters cpcp = null; + if (i == 0 && xc.getBasicConstraints() == -1) { + // this is an EE + cpcp = buildCertPathConstraint(xc, anchor); + } else { + cpcp = new CertPathConstraintsParameters( + xc, null, anchor, null); + } + checkWeakConstraint(fullLabel, xc, cpcp); } } } - private void checkWeak(String label, Certificate cert) - throws KeyStoreException { + private void checkWeakConstraint(String label, Certificate cert, + CertPathConstraintsParameters cpcp) + throws KeyStoreException, Exception { if (cert instanceof X509Certificate) { X509Certificate xc = (X509Certificate)cert; // No need to check the sigalg of a trust anchor String sigAlg = isTrustedCert(cert) ? null : xc.getSigAlgName(); - checkWeak(label, sigAlg, xc.getPublicKey()); + checkWeakConstraint(label, sigAlg, xc.getPublicKey(), cpcp); } } - private void checkWeak(String label, PKCS10 p10) { - checkWeak(label, p10.getSigAlg(), p10.getSubjectPublicKeyInfo()); + private void checkWeakConstraint(String label, PKCS10 p10, + CertPathConstraintsParameters cpcp) throws Exception { + checkWeakConstraint(label, p10.getSigAlg(), + p10.getSubjectPublicKeyInfo(), cpcp); + } + + private void checkWeakConstraint(String label, CRL crl, Key key, + CertPathConstraintsParameters cpcp) throws Exception { + if (crl instanceof X509CRLImpl) { + X509CRLImpl impl = (X509CRLImpl)crl; + checkWeakConstraint(label, impl.getSigAlgName(), key, cpcp); + } } private void checkWeak(String label, CRL crl, Key key) { @@ -4810,6 +5055,76 @@ public final class Main { } } + private KeyStore buildTrustedCerts() { + KeyStore caks = null; + try { + caks = KeyStoreUtil.getCacertsKeyStore(); + if (caks != null) { + Enumeration aliases = caks.aliases(); + while (aliases.hasMoreElements()) { + String a = aliases.nextElement(); + try { + trustedCerts.add((X509Certificate)caks.getCertificate(a)); + } catch (Exception e2) { + // ignore, if the keystore has not been loaded/initialized properly + } + } + } + } catch (Exception e) { + // Ignore, if cacerts cannot be loaded + } + return caks; + } + + private TrustAnchor findTrustAnchor(List chain) { + if (chain.isEmpty()) { + return null; + } + + X509Certificate last = chain.get(chain.size() - 1); + Optional trusted = + trustedCerts.stream() + .filter(c -> c.getSubjectX500Principal().equals(last.getIssuerX500Principal())) + .findFirst(); + return trusted.isPresent() ? new TrustAnchor(trusted.get(), null) : null; + } + + private X509Certificate[] convertCerts(Certificate[] certs) { + X509Certificate[] xcerts = new X509Certificate[certs.length]; + + for (int i = 0; i < certs.length; i++) { + if (certs[i] instanceof X509Certificate) { + xcerts[i] = (X509Certificate) certs[i]; + } + } + return xcerts; + } + + private CertPathConstraintsParameters buildCertPathConstraint( + X509Certificate xcert, TrustAnchor anchor) throws Exception{ + List eku = xcert.getExtendedKeyUsage(); + if (eku == null) { + return new CertPathConstraintsParameters(xcert, null, + anchor, null); + } + + if (eku.contains(KnownOIDs.codeSigning.value())) { + return new CertPathConstraintsParameters(xcert, + Validator.VAR_CODE_SIGNING, anchor, null); + } else if (eku.contains(KnownOIDs.clientAuth.value())) { + return new CertPathConstraintsParameters(xcert, + Validator.VAR_TLS_CLIENT, anchor, null); + } else if (eku.contains(KnownOIDs.serverAuth.value())) { + return new CertPathConstraintsParameters(xcert, + Validator.VAR_TLS_SERVER, anchor, null); + } else if (eku.contains(KnownOIDs.KP_TimeStamping.value())) { + return new CertPathConstraintsParameters(xcert, + Validator.VAR_TSA_SERVER, anchor, null); + } + return new CertPathConstraintsParameters(xcert, Validator.VAR_GENERIC, + anchor, null); + } + private void printWeakWarnings(boolean newLine) { if (!weakWarnings.isEmpty() && !nowarn) { System.err.println("\nWarning:"); diff --git a/src/java.base/share/classes/sun/security/tools/keytool/Resources.java b/src/java.base/share/classes/sun/security/tools/keytool/Resources.java index df0147e529d..f26b2a13bd8 100644 --- a/src/java.base/share/classes/sun/security/tools/keytool/Resources.java +++ b/src/java.base/share/classes/sun/security/tools/keytool/Resources.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2022, 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 @@ -483,6 +483,8 @@ public class Resources extends java.util.ListResourceBundle { "Subject: %1$s\nFormat: %2$s\nPublic Key: %3$s\nSignature algorithm: %4$s\n"}, {"verified.by.s.in.s.weak", "Verified by %1$s in %2$s with a %3$s"}, {"whose.sigalg.disabled", "%1$s uses the %2$s signature algorithm which is considered a security risk and is disabled."}, + {"whose.sigalg.usagesignedjar", "%1$s uses the %2$s signature algorithm which is considered a security risk and cannot be used to sign JARs after %3$s."}, + {"Unable.to.parse.denyAfter.string.in.exception.message", "Unable to parse denyAfter date string in exception message"}, {"whose.sigalg.weak", "%1$s uses the %2$s signature algorithm which is considered a security risk. This algorithm will be disabled in a future update."}, {"whose.key.disabled", "%1$s uses a %2$s which is considered a security risk and is disabled."}, {"whose.key.weak", "%1$s uses a %2$s which is considered a security risk. This key size will be disabled in a future update."}, diff --git a/test/jdk/sun/security/tools/keytool/TestSha1Usage.java b/test/jdk/sun/security/tools/keytool/TestSha1Usage.java new file mode 100644 index 00000000000..0cbece46e14 --- /dev/null +++ b/test/jdk/sun/security/tools/keytool/TestSha1Usage.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2022, 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 8273236 + * @summary Test SHA1 usage SignedJAR + * @library /test/lib + */ + +import jdk.test.lib.SecurityTools; +import jdk.test.lib.process.OutputAnalyzer; + +public class TestSha1Usage { + + static OutputAnalyzer kt(String cmd, String ks) throws Exception { + return SecurityTools.keytool("-storepass changeit " + cmd + + " -keystore " + ks); + } + + public static void main(String[] args) throws Exception { + + SecurityTools.keytool("-keystore ks -storepass changeit " + + "-genkeypair -keyalg rsa -alias ca -dname CN=CA " + + "-ext eku=codeSigning -sigalg SHA1withRSA") + .shouldContain("Warning:") + .shouldMatch("The generated certificate.*SHA1withRSA.*considered a security risk") + .shouldMatch("cannot be used to sign JARs") + .shouldHaveExitValue(0); + + kt("-genkeypair -keyalg rsa -alias e1 -dname CN=E1", "ks"); + kt("-certreq -alias e1 -file tmp.req", "ks"); + SecurityTools.keytool("-keystore ks -storepass changeit " + + "-gencert -alias ca -infile tmp.req -outfile tmp.cert") + .shouldContain("Warning:") + .shouldMatch("The issuer.*SHA1withRSA.*considered a security risk") + .shouldMatch("cannot be used to sign JARs") + .shouldHaveExitValue(0); + } +} -- GitLab From 890830196dea3dfacef231b458fa4a459791c2bb Mon Sep 17 00:00:00 2001 From: Jaikiran Pai Date: Thu, 27 Jan 2022 03:57:28 +0000 Subject: [PATCH 307/564] 8076089: Cleanup: Inline & remove sun.management.Util.newException Reviewed-by: kevinw, amenkov, dfuchs, sspitsyn --- .../share/classes/sun/management/LockInfoCompositeData.java | 6 +++--- .../classes/sun/management/ManagementFactoryHelper.java | 6 +++--- src/java.management/share/classes/sun/management/Util.java | 6 +----- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/src/java.management/share/classes/sun/management/LockInfoCompositeData.java b/src/java.management/share/classes/sun/management/LockInfoCompositeData.java index 087ce3d780e..bafdff2dbfb 100644 --- a/src/java.management/share/classes/sun/management/LockInfoCompositeData.java +++ b/src/java.management/share/classes/sun/management/LockInfoCompositeData.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022, 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 @@ -68,7 +68,7 @@ public class LockInfoCompositeData extends LazyCompositeData { return new CompositeDataSupport(LOCK_INFO_COMPOSITE_TYPE, items); } catch (OpenDataException e) { // Should never reach here - throw Util.newException(e); + throw new RuntimeException(e); } } @@ -79,7 +79,7 @@ public class LockInfoCompositeData extends LazyCompositeData { MappedMXBeanType.toOpenType(LockInfo.class); } catch (OpenDataException e) { // Should never reach here - throw Util.newException(e); + throw new RuntimeException(e); } } diff --git a/src/java.management/share/classes/sun/management/ManagementFactoryHelper.java b/src/java.management/share/classes/sun/management/ManagementFactoryHelper.java index 7e5c1d87640..3746cd311b2 100644 --- a/src/java.management/share/classes/sun/management/ManagementFactoryHelper.java +++ b/src/java.management/share/classes/sun/management/ManagementFactoryHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, 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 @@ -482,7 +482,7 @@ public class ManagementFactoryHelper { } }); } catch (PrivilegedActionException e) { - throw Util.newException(e.getException()); + throw new RuntimeException(e.getException()); } } @@ -540,7 +540,7 @@ public class ManagementFactoryHelper { } }); } catch (PrivilegedActionException e) { - throw Util.newException(e.getException()); + throw new RuntimeException(e.getException()); } } diff --git a/src/java.management/share/classes/sun/management/Util.java b/src/java.management/share/classes/sun/management/Util.java index 9ce1a5d31ee..94bab86140c 100644 --- a/src/java.management/share/classes/sun/management/Util.java +++ b/src/java.management/share/classes/sun/management/Util.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, 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,10 +34,6 @@ import javax.management.MalformedObjectNameException; public class Util { private Util() {} // there are no instances of this class - static RuntimeException newException(Exception e) { - throw new RuntimeException(e); - } - private static final String[] EMPTY_STRING_ARRAY = new String[0]; static String[] toStringArray(List list) { return list.toArray(EMPTY_STRING_ARRAY); -- GitLab From 2ea0edf2c40edde4c191864a40e7a4d741ac0b8e Mon Sep 17 00:00:00 2001 From: Andrey Turbanov Date: Thu, 27 Jan 2022 07:00:56 +0000 Subject: [PATCH 308/564] 8279673: AudioClip.play doesn't work due to NullPointerException when creating DataPusher Reviewed-by: prr, serb --- .../com/sun/media/sound/DataPusher.java | 4 +- .../sun/media/sound/JSSecurityManager.java | 3 +- .../sampled/Clip/DataPusherThreadCheck.java | 89 +++++++++++++++++++ 3 files changed, 92 insertions(+), 4 deletions(-) create mode 100644 test/jdk/javax/sound/sampled/Clip/DataPusherThreadCheck.java diff --git a/src/java.desktop/share/classes/com/sun/media/sound/DataPusher.java b/src/java.desktop/share/classes/com/sun/media/sound/DataPusher.java index 8944df836ae..d40c2cd8c31 100644 --- a/src/java.desktop/share/classes/com/sun/media/sound/DataPusher.java +++ b/src/java.desktop/share/classes/com/sun/media/sound/DataPusher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2022, 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 @@ -108,7 +108,7 @@ public final class DataPusher implements Runnable { source.start(); if (pushThread == null) { pushThread = JSSecurityManager.createThread(this, - null, // name + "DataPusher", // name false, // daemon -1, // priority true); // doStart diff --git a/src/java.desktop/share/classes/com/sun/media/sound/JSSecurityManager.java b/src/java.desktop/share/classes/com/sun/media/sound/JSSecurityManager.java index f593ed8b897..51482b24aea 100644 --- a/src/java.desktop/share/classes/com/sun/media/sound/JSSecurityManager.java +++ b/src/java.desktop/share/classes/com/sun/media/sound/JSSecurityManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -112,7 +112,6 @@ final class JSSecurityManager { final boolean isDaemon, final int priority, final boolean doStart) { - String name = (threadName != null) ? threadName : "JSSM Thread"; Thread thread = new Thread(null, runnable, threadName, 0, false); thread.setDaemon(isDaemon); diff --git a/test/jdk/javax/sound/sampled/Clip/DataPusherThreadCheck.java b/test/jdk/javax/sound/sampled/Clip/DataPusherThreadCheck.java new file mode 100644 index 00000000000..733a317ab37 --- /dev/null +++ b/test/jdk/javax/sound/sampled/Clip/DataPusherThreadCheck.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import static javax.sound.sampled.AudioFormat.Encoding.PCM_SIGNED; +import static javax.sound.sampled.AudioSystem.NOT_SPECIFIED; + +import javax.sound.sampled.AudioFileFormat; +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import java.applet.AudioClip; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.InputStream; +import java.nio.file.Files; + +/* + * @test + * @key headful + * @bug 8279673 + * @summary Verify no NPE creating threads + * @run main/othervm DataPusherThreadCheck + */ +public class DataPusherThreadCheck { + + public static void main(String[] args) throws Exception { + // Prepare the audio file + File file = new File("audio.wav"); + try { + AudioFormat format = + new AudioFormat(PCM_SIGNED, 44100, 8, 1, 1, 44100, false); + int dataSize = 6000*1000 * format.getFrameSize(); + InputStream in = new ByteArrayInputStream(new byte[dataSize]); + AudioInputStream audioStream = new AudioInputStream(in, format, NOT_SPECIFIED); + AudioSystem.write(audioStream, AudioFileFormat.Type.WAVE, file); + } catch (Exception ignored) { + return; // the test is not applicable + } + try { + checkThread(file); + } finally { + Files.delete(file.toPath()); + } + } + + private static void checkThread(File file) throws Exception { + AudioClip clip = (AudioClip) file.toURL().getContent(); + clip.loop(); + try { + Thread.sleep(2000); + } catch (InterruptedException ignored) { + } + boolean found = isDataPushedThreadExist(); + clip.stop(); + if (!found) { + throw new RuntimeException("Thread 'DataPusher' isn't found"); + } + } + + private static boolean isDataPushedThreadExist() { + for (Thread t : Thread.getAllStackTraces().keySet()) { + if (t.getName().equals("DataPusher")) { + return true; + } + } + return false; + } + +} -- GitLab From 0dba1707910734d03c318424764b8682b028a8e0 Mon Sep 17 00:00:00 2001 From: Roland Westrelin Date: Thu, 27 Jan 2022 08:44:58 +0000 Subject: [PATCH 309/564] 8278518: String(byte[], int, int, Charset) constructor and String.translateEscapes() miss bounds check elimination Co-authored-by: Sergey Tsypanov Reviewed-by: kvn, jrose --- src/hotspot/share/ci/ciTypeFlow.cpp | 111 ++++++++++++++++-- src/hotspot/share/ci/ciTypeFlow.hpp | 7 +- .../bench/vm/compiler/SharedLoopHeader.java | 65 ++++++++++ .../compiler/StringConstructorBenchmark.java | 58 +++++++++ 4 files changed, 232 insertions(+), 9 deletions(-) create mode 100644 test/micro/org/openjdk/bench/vm/compiler/SharedLoopHeader.java create mode 100644 test/micro/org/openjdk/bench/vm/compiler/StringConstructorBenchmark.java diff --git a/src/hotspot/share/ci/ciTypeFlow.cpp b/src/hotspot/share/ci/ciTypeFlow.cpp index 802ba97db2e..240cb654380 100644 --- a/src/hotspot/share/ci/ciTypeFlow.cpp +++ b/src/hotspot/share/ci/ciTypeFlow.cpp @@ -2202,10 +2202,10 @@ bool ciTypeFlow::can_trap(ciBytecodeStream& str) { // ciTypeFlow::clone_loop_heads // // Clone the loop heads -bool ciTypeFlow::clone_loop_heads(Loop* lp, StateVector* temp_vector, JsrSet* temp_set) { +bool ciTypeFlow::clone_loop_heads(StateVector* temp_vector, JsrSet* temp_set) { bool rslt = false; for (PreorderLoops iter(loop_tree_root()); !iter.done(); iter.next()) { - lp = iter.current(); + Loop* lp = iter.current(); Block* head = lp->head(); if (lp == loop_tree_root() || lp->is_irreducible() || @@ -2450,6 +2450,103 @@ void ciTypeFlow::PreorderLoops::next() { } } +// If the tail is a branch to the head, retrieve how many times that path was taken from profiling +int ciTypeFlow::profiled_count(ciTypeFlow::Loop* loop) { + ciMethodData* methodData = method()->method_data(); + if (!methodData->is_mature()) { + return 0; + } + ciTypeFlow::Block* tail = loop->tail(); + if (tail->control() == -1) { + return 0; + } + + ciProfileData* data = methodData->bci_to_data(tail->control()); + assert(data != NULL, "some profile data expected at branch"); + + if (!data->is_JumpData()) { + return 0; + } + + ciBytecodeStream iter(method()); + iter.reset_to_bci(tail->control()); + + bool is_an_if = false; + bool wide = false; + Bytecodes::Code bc = iter.next(); + switch (bc) { + case Bytecodes::_ifeq: + case Bytecodes::_ifne: + case Bytecodes::_iflt: + case Bytecodes::_ifge: + case Bytecodes::_ifgt: + case Bytecodes::_ifle: + case Bytecodes::_if_icmpeq: + case Bytecodes::_if_icmpne: + case Bytecodes::_if_icmplt: + case Bytecodes::_if_icmpge: + case Bytecodes::_if_icmpgt: + case Bytecodes::_if_icmple: + case Bytecodes::_if_acmpeq: + case Bytecodes::_if_acmpne: + case Bytecodes::_ifnull: + case Bytecodes::_ifnonnull: + is_an_if = true; + break; + case Bytecodes::_goto_w: + case Bytecodes::_jsr_w: + wide = true; + break; + case Bytecodes::_goto: + case Bytecodes::_jsr: + break; + default: + fatal(" invalid bytecode: %s", Bytecodes::name(iter.cur_bc())); + } + + GrowableArray* succs = tail->successors(); + + if (!is_an_if) { + assert(((wide ? iter.get_far_dest() : iter.get_dest()) == loop->head()->start()) == (succs->at(ciTypeFlow::GOTO_TARGET) == loop->head()), "branch should lead to loop head"); + if (succs->at(ciTypeFlow::GOTO_TARGET) == loop->head()) { + return method()->scale_count(data->as_JumpData()->taken()); + } + } else { + assert((iter.get_dest() == loop->head()->start()) == (succs->at(ciTypeFlow::IF_TAKEN) == loop->head()), "bytecode and CFG not consistent"); + assert((tail->limit() == loop->head()->start()) == (succs->at(ciTypeFlow::IF_NOT_TAKEN) == loop->head()), "bytecode and CFG not consistent"); + if (succs->at(ciTypeFlow::IF_TAKEN) == loop->head()) { + return method()->scale_count(data->as_JumpData()->taken()); + } else if (succs->at(ciTypeFlow::IF_NOT_TAKEN) == loop->head()) { + return method()->scale_count(data->as_BranchData()->not_taken()); + } + } + + return 0; +} + +bool ciTypeFlow::Loop::at_insertion_point(Loop* lp, Loop* current) { + int lp_pre_order = lp->head()->pre_order(); + if (current->head()->pre_order() < lp_pre_order) { + return true; + } else if (current->head()->pre_order() > lp_pre_order) { + return false; + } + // In the case of a shared head, make the most frequent head/tail (as reported by profiling) the inner loop + if (current->head() == lp->head()) { + int lp_count = outer()->profiled_count(lp); + int current_count = outer()->profiled_count(current); + if (current_count < lp_count) { + return true; + } else if (current_count > lp_count) { + return false; + } + } + if (current->tail()->pre_order() > lp->tail()->pre_order()) { + return true; + } + return false; +} + // ------------------------------------------------------------------ // ciTypeFlow::Loop::sorted_merge // @@ -2467,12 +2564,10 @@ ciTypeFlow::Loop* ciTypeFlow::Loop::sorted_merge(Loop* lp) { int lp_pre_order = lp->head()->pre_order(); // Find insertion point for "lp" while (current != NULL) { - if (current == lp) + if (current == lp) { return leaf; // Already in list - if (current->head()->pre_order() < lp_pre_order) - break; - if (current->head()->pre_order() == lp_pre_order && - current->tail()->pre_order() > lp->tail()->pre_order()) { + } + if (at_insertion_point(lp, current)) { break; } prev = current; @@ -2732,7 +2827,7 @@ void ciTypeFlow::flow_types() { env()->comp_level() >= CompLevel_full_optimization) { // Loop optimizations are not performed on Tier1 compiles. - bool changed = clone_loop_heads(loop_tree_root(), temp_vector, temp_set); + bool changed = clone_loop_heads(temp_vector, temp_set); // If some loop heads were cloned, recompute postorder and loop tree if (changed) { diff --git a/src/hotspot/share/ci/ciTypeFlow.hpp b/src/hotspot/share/ci/ciTypeFlow.hpp index 907897fe310..b733a694f38 100644 --- a/src/hotspot/share/ci/ciTypeFlow.hpp +++ b/src/hotspot/share/ci/ciTypeFlow.hpp @@ -717,6 +717,9 @@ public: bool _irreducible; LocalSet _def_locals; + ciTypeFlow* outer() const { return head()->outer(); } + bool at_insertion_point(Loop* lp, Loop* current); + public: Loop(Block* head, Block* tail) : _parent(NULL), _sibling(NULL), _child(NULL), @@ -795,7 +798,7 @@ private: bool can_trap(ciBytecodeStream& str); // Clone the loop heads. Returns true if any cloning occurred. - bool clone_loop_heads(Loop* lp, StateVector* temp_vector, JsrSet* temp_set); + bool clone_loop_heads(StateVector* temp_vector, JsrSet* temp_set); // Clone lp's head and replace tail's successors with clone. Block* clone_loop_head(Loop* lp, StateVector* temp_vector, JsrSet* temp_set); @@ -913,6 +916,8 @@ private: // Create the block map, which indexes blocks in pre_order. void map_blocks(); + int profiled_count(ciTypeFlow::Loop* loop); + public: // Perform type inference flow analysis. void do_flow(); diff --git a/test/micro/org/openjdk/bench/vm/compiler/SharedLoopHeader.java b/test/micro/org/openjdk/bench/vm/compiler/SharedLoopHeader.java new file mode 100644 index 00000000000..e84ca35ab27 --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/compiler/SharedLoopHeader.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2022, Red Hat, Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package org.openjdk.bench.vm.compiler; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Mode; +import java.util.concurrent.TimeUnit; + +@State(Scope.Thread) +public class SharedLoopHeader { + + private static final int size = 1000; + private static final boolean branch[] = new boolean[size]; + private static final int count[] = new int[size]; + + @Setup + public void setup() { + for (int i = 0; i < branch.length; i++) { + branch[i] = ((i % 10) != 0); + } + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public void sharedHeader() { + int i = 0; + while (i < branch.length) { + if (branch[i]) { + // common branch + count[i]++; + i++; + continue; + } + i += 2; + } + } + +} diff --git a/test/micro/org/openjdk/bench/vm/compiler/StringConstructorBenchmark.java b/test/micro/org/openjdk/bench/vm/compiler/StringConstructorBenchmark.java new file mode 100644 index 00000000000..4763c59629c --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/compiler/StringConstructorBenchmark.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2022, Red Hat, Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package org.openjdk.bench.vm.compiler; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.Setup; +import java.util.concurrent.TimeUnit; +import java.nio.charset.StandardCharsets; + +@State(Scope.Thread) +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +public class StringConstructorBenchmark { + private byte[] array; + private String str; + + @Setup + public void setup() { + str = "Quizdeltagerne spiste jordb\u00e6r med fl\u00f8de, mens cirkusklovnen. \u042f";//Latin1 ending with Russian + array = str.getBytes(StandardCharsets.UTF_8); + } + + @Benchmark + public String newString() { + return new String(array, 0, array.length, StandardCharsets.UTF_8); + } + + @Benchmark + public String translateEscapes() { + return str.translateEscapes(); + } +} -- GitLab From 94380d0e464a491977ed2b5f1998a55cfe73c3c6 Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Thu, 27 Jan 2022 08:59:34 +0000 Subject: [PATCH 310/564] 8278232: [macos] Wrong chars emitted when entering certain char-sequence of Indic language Reviewed-by: prr --- .../macosx/native/libawt_lwawt/awt/AWTView.m | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m index 8e44052333c..15be2ae90f2 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m @@ -546,12 +546,13 @@ static BOOL shouldUsePressAndHold() { -(BOOL) isCodePointInUnicodeBlockNeedingIMEvent: (unichar) codePoint { if ((codePoint == 0x0024) || (codePoint == 0x00A3) || (codePoint == 0x00A5) || + ((codePoint >= 0x900) && (codePoint <= 0x97F)) || ((codePoint >= 0x20A3) && (codePoint <= 0x20BF)) || ((codePoint >= 0x3000) && (codePoint <= 0x303F)) || ((codePoint >= 0xFF00) && (codePoint <= 0xFFEF))) { // Code point is in 'CJK Symbols and Punctuation' or // 'Halfwidth and Fullwidth Forms' Unicode block or - // currency symbols unicode + // currency symbols unicode or Devanagari script return YES; } return NO; @@ -957,11 +958,17 @@ static jclass jc_CInputMethod = NULL; #ifdef IM_DEBUG NSLog(@"insertText kbdlayout %@ ",(NSString *)kbdLayout); + + NSLog(@"utf8Length %lu utf16Length %lu", (unsigned long)utf8Length, (unsigned long)utf16Length); + NSLog(@"codePoint %x", codePoint); #endif // IM_DEBUG if ((utf16Length > 2) || ((utf8Length > 1) && [self isCodePointInUnicodeBlockNeedingIMEvent:codePoint]) || ((codePoint == 0x5c) && ([(NSString *)kbdLayout containsString:@"Kotoeri"]))) { +#ifdef IM_DEBUG + NSLog(@"string complex "); +#endif aStringIsComplex = YES; } -- GitLab From 7f68759c60d026eba3ad0a7f775497886c727384 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Thu, 27 Jan 2022 09:06:13 +0000 Subject: [PATCH 311/564] 8280719: G1: Remove outdated comment in RemoveSelfForwardPtrObjClosure::apply Reviewed-by: ayang, mli --- src/hotspot/share/gc/g1/g1EvacFailure.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/hotspot/share/gc/g1/g1EvacFailure.cpp b/src/hotspot/share/gc/g1/g1EvacFailure.cpp index 8c6a68ad5ab..dbad25955ae 100644 --- a/src/hotspot/share/gc/g1/g1EvacFailure.cpp +++ b/src/hotspot/share/gc/g1/g1EvacFailure.cpp @@ -77,7 +77,6 @@ public: zap_dead_objects(_last_forwarded_object_end, obj_addr); - // Zapping clears the bitmap, make sure it didn't clear too much. assert(_cm->is_marked_in_prev_bitmap(obj), "should be correctly marked"); if (_during_concurrent_start) { // For the next marking info we'll only mark the -- GitLab From cab590517bf705418c7376edd5d7066b13b6dde8 Mon Sep 17 00:00:00 2001 From: Thomas Stuefe Date: Thu, 27 Jan 2022 09:18:17 +0000 Subject: [PATCH 312/564] 8280583: Always build NMT Reviewed-by: shade, ihse, zgu --- make/autoconf/jvm-features.m4 | 11 +--- make/hotspot/lib/JvmFeatures.gmk | 9 +-- src/hotspot/share/memory/allocation.hpp | 10 +-- .../share/memory/metaspace/metaspaceDCmd.cpp | 6 +- src/hotspot/share/prims/whitebox.cpp | 14 ++--- src/hotspot/share/runtime/arguments.cpp | 8 --- src/hotspot/share/runtime/mutexLocker.cpp | 7 +-- src/hotspot/share/runtime/mutexLocker.hpp | 4 +- src/hotspot/share/runtime/os.cpp | 25 +++----- src/hotspot/share/runtime/thread.cpp | 4 -- src/hotspot/share/runtime/thread.hpp | 4 +- .../share/services/mallocSiteTable.hpp | 8 +-- src/hotspot/share/services/mallocTracker.hpp | 5 -- src/hotspot/share/services/memBaseline.hpp | 6 +- src/hotspot/share/services/memReporter.hpp | 6 +- src/hotspot/share/services/memTracker.hpp | 62 +------------------ src/hotspot/share/services/nmtDCmd.hpp | 6 +- src/hotspot/share/services/nmtPreInit.cpp | 8 +-- src/hotspot/share/services/nmtPreInit.hpp | 8 +-- .../share/services/threadStackTracker.hpp | 4 +- .../share/services/virtualMemoryTracker.hpp | 5 +- src/hotspot/share/utilities/debug.cpp | 3 - src/hotspot/share/utilities/macros.hpp | 18 +----- .../test_nmt_buffer_overflow_detection.cpp | 10 +-- test/hotspot/gtest/nmt/test_nmtpreinit.cpp | 8 +-- test/hotspot/gtest/nmt/test_nmtpreinitmap.cpp | 8 +-- .../runtime/test_committed_virtualmemory.cpp | 6 +- .../runtime/test_virtualMemoryTracker.cpp | 11 +--- 28 files changed, 51 insertions(+), 233 deletions(-) diff --git a/make/autoconf/jvm-features.m4 b/make/autoconf/jvm-features.m4 index 906a2857877..70457149edc 100644 --- a/make/autoconf/jvm-features.m4 +++ b/make/autoconf/jvm-features.m4 @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2022, 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 @@ -45,7 +45,7 @@ m4_define(jvm_features_valid, m4_normalize( \ ifdef([custom_jvm_features_valid], custom_jvm_features_valid) \ \ cds compiler1 compiler2 dtrace epsilongc g1gc jfr jni-check \ - jvmci jvmti link-time-opt management minimal nmt opt-size parallelgc \ + jvmci jvmti link-time-opt management minimal opt-size parallelgc \ serialgc services shenandoahgc static-build vm-structs zero zgc \ )) @@ -68,7 +68,6 @@ m4_define(jvm_feature_desc_jvmti, [enable Java Virtual Machine Tool Interface (J m4_define(jvm_feature_desc_link_time_opt, [enable link time optimization]) m4_define(jvm_feature_desc_management, [enable java.lang.management API support]) m4_define(jvm_feature_desc_minimal, [support building variant 'minimal']) -m4_define(jvm_feature_desc_nmt, [include native memory tracking (NMT)]) m4_define(jvm_feature_desc_opt_size, [optimize the JVM library for size]) m4_define(jvm_feature_desc_parallelgc, [include the parallel garbage collector]) m4_define(jvm_feature_desc_serialgc, [include the serial garbage collector]) @@ -443,7 +442,7 @@ AC_DEFUN([JVM_FEATURES_PREPARE_VARIANT], JVM_FEATURES_VARIANT_FILTER="compiler2 jvmci link-time-opt opt-size" elif test "x$variant" = "xminimal"; then JVM_FEATURES_VARIANT_FILTER="cds compiler2 dtrace epsilongc g1gc \ - jfr jni-check jvmci jvmti management nmt parallelgc services \ + jfr jni-check jvmci jvmti management parallelgc services \ shenandoahgc vm-structs zgc" if test "x$OPENJDK_TARGET_CPU" = xarm ; then JVM_FEATURES_VARIANT_FILTER="$JVM_FEATURES_VARIANT_FILTER opt-size" @@ -538,10 +537,6 @@ AC_DEFUN([JVM_FEATURES_VERIFY], AC_MSG_ERROR([Specified JVM feature 'jvmti' requires feature 'services' for variant '$variant']) fi - if JVM_FEATURES_IS_ACTIVE(management) && ! JVM_FEATURES_IS_ACTIVE(nmt); then - AC_MSG_ERROR([Specified JVM feature 'management' requires feature 'nmt' for variant '$variant']) - fi - # For backwards compatibility, disable a feature "globally" if one variant # is missing the feature. if ! JVM_FEATURES_IS_ACTIVE(cds); then diff --git a/make/hotspot/lib/JvmFeatures.gmk b/make/hotspot/lib/JvmFeatures.gmk index ab555f9d82d..07ce6feaf6f 100644 --- a/make/hotspot/lib/JvmFeatures.gmk +++ b/make/hotspot/lib/JvmFeatures.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2013, 2022, 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 @@ -130,13 +130,6 @@ ifneq ($(call check-jvm-feature, cds), true) JVM_EXCLUDE_PATTERNS += cds/ endif -ifneq ($(call check-jvm-feature, nmt), true) - JVM_CFLAGS_FEATURES += -DINCLUDE_NMT=0 - JVM_EXCLUDE_FILES += \ - memBaseline.cpp memReporter.cpp mallocTracker.cpp virtualMemoryTracker.cpp nmtCommon.cpp \ - memTracker.cpp nmtDCmd.cpp mallocSiteTable.cpp threadStackTracker.cpp -endif - ifneq ($(call check-jvm-feature, g1gc), true) JVM_CFLAGS_FEATURES += -DINCLUDE_G1GC=0 JVM_EXCLUDE_PATTERNS += gc/g1 diff --git a/src/hotspot/share/memory/allocation.hpp b/src/hotspot/share/memory/allocation.hpp index 0562a44063d..8503942f21f 100644 --- a/src/hotspot/share/memory/allocation.hpp +++ b/src/hotspot/share/memory/allocation.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -170,16 +170,8 @@ MEMORY_TYPES_DO(MEMORY_TYPE_SHORTNAME) // Make an int version of the sentinel end value. constexpr int mt_number_of_types = static_cast(MEMFLAGS::mt_number_of_types); -#if INCLUDE_NMT - extern bool NMT_track_callsite; -#else - -const bool NMT_track_callsite = false; - -#endif // INCLUDE_NMT - class NativeCallStack; diff --git a/src/hotspot/share/memory/metaspace/metaspaceDCmd.cpp b/src/hotspot/share/memory/metaspace/metaspaceDCmd.cpp index 96814781377..c4eea087b37 100644 --- a/src/hotspot/share/memory/metaspace/metaspaceDCmd.cpp +++ b/src/hotspot/share/memory/metaspace/metaspaceDCmd.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2018, 2020 SAP SE. All rights reserved. + * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2022 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -77,7 +77,7 @@ void MetaspaceDCmd::execute(DCmdSource source, TRAPS) { if (strcasecmp("dynamic", scale_value) == 0) { scale = 0; } else { - scale = NMT_ONLY(NMTUtil::scale_from_name(scale_value)) NOT_NMT(0); + scale = NMTUtil::scale_from_name(scale_value); if (scale == 0) { output()->print_cr("Invalid scale: \"%s\". Will use dynamic scaling.", scale_value); } diff --git a/src/hotspot/share/prims/whitebox.cpp b/src/hotspot/share/prims/whitebox.cpp index 3e569f8b8cd..b990ea55640 100644 --- a/src/hotspot/share/prims/whitebox.cpp +++ b/src/hotspot/share/prims/whitebox.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022, 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 @@ -87,12 +87,15 @@ #include "runtime/threadSMR.hpp" #include "runtime/vframe.hpp" #include "runtime/vm_version.hpp" +#include "services/mallocSiteTable.hpp" #include "services/memoryService.hpp" +#include "services/memTracker.hpp" #include "utilities/align.hpp" #include "utilities/debug.hpp" #include "utilities/elfFile.hpp" #include "utilities/exceptions.hpp" #include "utilities/macros.hpp" +#include "utilities/nativeCallStack.hpp" #include "utilities/ostream.hpp" #if INCLUDE_G1GC #include "gc/g1/g1Arguments.hpp" @@ -105,11 +108,6 @@ #if INCLUDE_PARALLELGC #include "gc/parallel/parallelScavengeHeap.inline.hpp" #endif // INCLUDE_PARALLELGC -#if INCLUDE_NMT -#include "services/mallocSiteTable.hpp" -#include "services/memTracker.hpp" -#include "utilities/nativeCallStack.hpp" -#endif // INCLUDE_NMT #if INCLUDE_JVMCI #include "jvmci/jvmciEnv.hpp" #include "jvmci/jvmciRuntime.hpp" @@ -646,7 +644,6 @@ WB_END #endif // INCLUDE_G1GC -#if INCLUDE_NMT // Alloc memory using the test memory type so that we can use that to see if // NMT picks it up correctly WB_ENTRY(jlong, WB_NMTMalloc(JNIEnv* env, jobject o, jlong size)) @@ -724,7 +721,6 @@ WB_ENTRY(void, WB_NMTArenaMalloc(JNIEnv* env, jobject o, jlong arena, jlong size Arena* a = (Arena*)arena; a->Amalloc(size_t(size)); WB_END -#endif // INCLUDE_NMT static jmethodID reflected_method_to_jmid(JavaThread* thread, JNIEnv* env, jobject method) { assert(method != NULL, "method should not be null"); @@ -2545,7 +2541,6 @@ static JNINativeMethod methods[] = { {CC"psVirtualSpaceAlignment",CC"()J", (void*)&WB_PSVirtualSpaceAlignment}, {CC"psHeapGenerationAlignment",CC"()J", (void*)&WB_PSHeapGenerationAlignment}, #endif -#if INCLUDE_NMT {CC"NMTMalloc", CC"(J)J", (void*)&WB_NMTMalloc }, {CC"NMTMallocWithPseudoStack", CC"(JI)J", (void*)&WB_NMTMallocWithPseudoStack}, {CC"NMTMallocWithPseudoStackAndType", CC"(JII)J", (void*)&WB_NMTMallocWithPseudoStackAndType}, @@ -2559,7 +2554,6 @@ static JNINativeMethod methods[] = { {CC"NMTNewArena", CC"(J)J", (void*)&WB_NMTNewArena }, {CC"NMTFreeArena", CC"(J)V", (void*)&WB_NMTFreeArena }, {CC"NMTArenaMalloc", CC"(JJ)V", (void*)&WB_NMTArenaMalloc }, -#endif // INCLUDE_NMT {CC"deoptimizeFrames", CC"(Z)I", (void*)&WB_DeoptimizeFrames }, {CC"isFrameDeoptimized", CC"(I)Z", (void*)&WB_IsFrameDeoptimized}, {CC"deoptimizeAll", CC"()V", (void*)&WB_DeoptimizeAll }, diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index fd551f1ec22..c0f78eaaccf 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -4019,7 +4019,6 @@ jint Arguments::parse(const JavaVMInitArgs* initial_cmd_args) { no_shared_spaces("CDS Disabled"); #endif // INCLUDE_CDS -#if INCLUDE_NMT // Verify NMT arguments const NMT_TrackingLevel lvl = NMTUtil::parse_tracking_level(NativeMemoryTracking); if (lvl == NMT_unknown) { @@ -4031,13 +4030,6 @@ jint Arguments::parse(const JavaVMInitArgs* initial_cmd_args) { warning("PrintNMTStatistics is disabled, because native memory tracking is not enabled"); FLAG_SET_DEFAULT(PrintNMTStatistics, false); } -#else - if (!FLAG_IS_DEFAULT(NativeMemoryTracking) || PrintNMTStatistics) { - warning("Native Memory Tracking is not supported in this VM"); - FLAG_SET_DEFAULT(NativeMemoryTracking, "off"); - FLAG_SET_DEFAULT(PrintNMTStatistics, false); - } -#endif // INCLUDE_NMT if (TraceDependencies && VerifyDependencies) { if (!FLAG_IS_DEFAULT(TraceDependencies)) { diff --git a/src/hotspot/share/runtime/mutexLocker.cpp b/src/hotspot/share/runtime/mutexLocker.cpp index 257f853fb92..2d5c34cd215 100644 --- a/src/hotspot/share/runtime/mutexLocker.cpp +++ b/src/hotspot/share/runtime/mutexLocker.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -137,9 +137,8 @@ Monitor* ThreadsSMRDelete_lock = NULL; Mutex* ThreadIdTableCreate_lock = NULL; Mutex* SharedDecoder_lock = NULL; Mutex* DCmdFactory_lock = NULL; -#if INCLUDE_NMT Mutex* NMTQuery_lock = NULL; -#endif + #if INCLUDE_CDS #if INCLUDE_JVMTI Mutex* CDSClassFileStream_lock = NULL; @@ -320,9 +319,7 @@ void mutex_init() { def(ThreadIdTableCreate_lock , PaddedMutex , safepoint); def(SharedDecoder_lock , PaddedMutex , tty-1); def(DCmdFactory_lock , PaddedMutex , nosafepoint); -#if INCLUDE_NMT def(NMTQuery_lock , PaddedMutex , safepoint); -#endif #if INCLUDE_CDS #if INCLUDE_JVMTI def(CDSClassFileStream_lock , PaddedMutex , safepoint); diff --git a/src/hotspot/share/runtime/mutexLocker.hpp b/src/hotspot/share/runtime/mutexLocker.hpp index a40b0592cc4..cd415e945a5 100644 --- a/src/hotspot/share/runtime/mutexLocker.hpp +++ b/src/hotspot/share/runtime/mutexLocker.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -114,9 +114,7 @@ extern Monitor* ThreadsSMRDelete_lock; // Used by ThreadsSMRSupport to extern Mutex* ThreadIdTableCreate_lock; // Used by ThreadIdTable to lazily create the thread id table extern Mutex* SharedDecoder_lock; // serializes access to the decoder during normal (not error reporting) use extern Mutex* DCmdFactory_lock; // serialize access to DCmdFactory information -#if INCLUDE_NMT extern Mutex* NMTQuery_lock; // serialize NMT Dcmd queries -#endif #if INCLUDE_CDS #if INCLUDE_JVMTI extern Mutex* CDSClassFileStream_lock; // FileMapInfo::open_stream_for_jvmti diff --git a/src/hotspot/share/runtime/os.cpp b/src/hotspot/share/runtime/os.cpp index 48a0f8398be..29a3d7622f6 100644 --- a/src/hotspot/share/runtime/os.cpp +++ b/src/hotspot/share/runtime/os.cpp @@ -631,14 +631,11 @@ void* os::malloc(size_t size, MEMFLAGS flags) { void* os::malloc(size_t size, MEMFLAGS memflags, const NativeCallStack& stack) { -#if INCLUDE_NMT - { - void* rc = NULL; - if (NMTPreInit::handle_malloc(&rc, size)) { - return rc; - } + // Special handling for NMT preinit phase before arguments are parsed + void* rc = NULL; + if (NMTPreInit::handle_malloc(&rc, size)) { + return rc; } -#endif DEBUG_ONLY(check_crash_protection()); @@ -677,14 +674,11 @@ void* os::realloc(void *memblock, size_t size, MEMFLAGS flags) { void* os::realloc(void *memblock, size_t size, MEMFLAGS memflags, const NativeCallStack& stack) { -#if INCLUDE_NMT - { - void* rc = NULL; - if (NMTPreInit::handle_realloc(&rc, memblock, size)) { - return rc; - } + // Special handling for NMT preinit phase before arguments are parsed + void* rc = NULL; + if (NMTPreInit::handle_realloc(&rc, memblock, size)) { + return rc; } -#endif if (memblock == NULL) { return os::malloc(size, memflags, stack); @@ -723,11 +717,10 @@ void* os::realloc(void *memblock, size_t size, MEMFLAGS memflags, const NativeCa void os::free(void *memblock) { -#if INCLUDE_NMT + // Special handling for NMT preinit phase before arguments are parsed if (NMTPreInit::handle_free(memblock)) { return; } -#endif if (memblock == NULL) { return; diff --git a/src/hotspot/share/runtime/thread.cpp b/src/hotspot/share/runtime/thread.cpp index e25d44f4f06..0ec50849f5a 100644 --- a/src/hotspot/share/runtime/thread.cpp +++ b/src/hotspot/share/runtime/thread.cpp @@ -317,7 +317,6 @@ void Thread::record_stack_base_and_size() { } } -#if INCLUDE_NMT void Thread::register_thread_stack_with_NMT() { MemTracker::record_thread_stack(stack_end(), stack_size()); } @@ -325,7 +324,6 @@ void Thread::register_thread_stack_with_NMT() { void Thread::unregister_thread_stack_with_NMT() { MemTracker::release_thread_stack(stack_end(), stack_size()); } -#endif // INCLUDE_NMT void Thread::call_run() { DEBUG_ONLY(_run_state = CALL_RUN;) @@ -2704,10 +2702,8 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { jint parse_result = Arguments::parse(args); if (parse_result != JNI_OK) return parse_result; -#if INCLUDE_NMT // Initialize NMT right after argument parsing to keep the pre-NMT-init window small. MemTracker::initialize(); -#endif // INCLUDE_NMT os::init_before_ergo(); diff --git a/src/hotspot/share/runtime/thread.hpp b/src/hotspot/share/runtime/thread.hpp index 71100dbe637..9ceb17f7af1 100644 --- a/src/hotspot/share/runtime/thread.hpp +++ b/src/hotspot/share/runtime/thread.hpp @@ -550,8 +550,8 @@ protected: void set_stack_size(size_t size) { _stack_size = size; } address stack_end() const { return stack_base() - stack_size(); } void record_stack_base_and_size(); - void register_thread_stack_with_NMT() NOT_NMT_RETURN; - void unregister_thread_stack_with_NMT() NOT_NMT_RETURN; + void register_thread_stack_with_NMT(); + void unregister_thread_stack_with_NMT(); int lgrp_id() const { return _lgrp_id; } void set_lgrp_id(int value) { _lgrp_id = value; } diff --git a/src/hotspot/share/services/mallocSiteTable.hpp b/src/hotspot/share/services/mallocSiteTable.hpp index 6e026f9704c..814b70c6473 100644 --- a/src/hotspot/share/services/mallocSiteTable.hpp +++ b/src/hotspot/share/services/mallocSiteTable.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2022, 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,15 +25,12 @@ #ifndef SHARE_SERVICES_MALLOCSITETABLE_HPP #define SHARE_SERVICES_MALLOCSITETABLE_HPP -#include "utilities/macros.hpp" - -#if INCLUDE_NMT - #include "memory/allocation.hpp" #include "runtime/atomic.hpp" #include "services/allocationSite.hpp" #include "services/mallocTracker.hpp" #include "services/nmtCommon.hpp" +#include "utilities/macros.hpp" #include "utilities/nativeCallStack.hpp" // MallocSite represents a code path that eventually calls @@ -199,5 +196,4 @@ class MallocSiteTable : AllStatic { static const MallocSiteHashtableEntry* _hash_entry_allocation_site; }; -#endif // INCLUDE_NMT #endif // SHARE_SERVICES_MALLOCSITETABLE_HPP diff --git a/src/hotspot/share/services/mallocTracker.hpp b/src/hotspot/share/services/mallocTracker.hpp index a0953c2b186..ac8eaf17c5c 100644 --- a/src/hotspot/share/services/mallocTracker.hpp +++ b/src/hotspot/share/services/mallocTracker.hpp @@ -25,8 +25,6 @@ #ifndef SHARE_SERVICES_MALLOCTRACKER_HPP #define SHARE_SERVICES_MALLOCTRACKER_HPP -#if INCLUDE_NMT - #include "memory/allocation.hpp" #include "runtime/atomic.hpp" #include "runtime/threadCritical.hpp" @@ -448,7 +446,4 @@ class MallocTracker : AllStatic { } }; -#endif // INCLUDE_NMT - - #endif // SHARE_SERVICES_MALLOCTRACKER_HPP diff --git a/src/hotspot/share/services/memBaseline.hpp b/src/hotspot/share/services/memBaseline.hpp index c43c937abb1..ef801373464 100644 --- a/src/hotspot/share/services/memBaseline.hpp +++ b/src/hotspot/share/services/memBaseline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,8 +25,6 @@ #ifndef SHARE_SERVICES_MEMBASELINE_HPP #define SHARE_SERVICES_MEMBASELINE_HPP -#if INCLUDE_NMT - #include "memory/metaspaceStats.hpp" #include "runtime/mutex.hpp" #include "services/mallocSiteTable.hpp" @@ -212,6 +210,4 @@ class MemBaseline { void virtual_memory_sites_to_reservation_site_order(); }; -#endif // INCLUDE_NMT - #endif // SHARE_SERVICES_MEMBASELINE_HPP diff --git a/src/hotspot/share/services/memReporter.hpp b/src/hotspot/share/services/memReporter.hpp index 77fb1d70a00..2051ab88e3c 100644 --- a/src/hotspot/share/services/memReporter.hpp +++ b/src/hotspot/share/services/memReporter.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,8 +25,6 @@ #ifndef SHARE_SERVICES_MEMREPORTER_HPP #define SHARE_SERVICES_MEMREPORTER_HPP -#if INCLUDE_NMT - #include "memory/metaspace.hpp" #include "oops/instanceKlass.hpp" #include "services/memBaseline.hpp" @@ -239,6 +237,4 @@ class MemDetailDiffReporter : public MemSummaryDiffReporter { size_t current_committed, size_t early_reserved, size_t early_committed, MEMFLAGS flag) const; }; -#endif // INCLUDE_NMT - #endif // SHARE_SERVICES_MEMREPORTER_HPP diff --git a/src/hotspot/share/services/memTracker.hpp b/src/hotspot/share/services/memTracker.hpp index 1c81c3f7928..06d5c0c94a8 100644 --- a/src/hotspot/share/services/memTracker.hpp +++ b/src/hotspot/share/services/memTracker.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2022, 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,67 +25,13 @@ #ifndef SHARE_SERVICES_MEMTRACKER_HPP #define SHARE_SERVICES_MEMTRACKER_HPP -#include "services/nmtCommon.hpp" -#include "utilities/nativeCallStack.hpp" - - -#if !INCLUDE_NMT - -#define CURRENT_PC NativeCallStack::empty_stack() -#define CALLER_PC NativeCallStack::empty_stack() - -class Tracker : public StackObj { - public: - enum TrackerType { - uncommit, - release - }; - Tracker(enum TrackerType type) : _type(type) { } - void record(address addr, size_t size) { } - private: - enum TrackerType _type; -}; - -class MemTracker : AllStatic { - public: - static inline NMT_TrackingLevel tracking_level() { return NMT_off; } - static inline bool enabled() { return false; } - static inline void init() { } - static bool check_launcher_nmt_support(const char* value) { return true; } - static bool verify_nmt_option() { return true; } - - static inline void* record_malloc(void* mem_base, size_t size, MEMFLAGS flag, - const NativeCallStack& stack, NMT_TrackingLevel level) { return mem_base; } - static inline size_t malloc_header_size(NMT_TrackingLevel level) { return 0; } - static inline size_t malloc_header_size(void* memblock) { return 0; } - static inline size_t malloc_footer_size(NMT_TrackingLevel level) { return 0; } - static inline void* malloc_base(void* memblock) { return memblock; } - static inline void* record_free(void* memblock, NMT_TrackingLevel level) { return memblock; } - - static inline void record_new_arena(MEMFLAGS flag) { } - static inline void record_arena_free(MEMFLAGS flag) { } - static inline void record_arena_size_change(ssize_t diff, MEMFLAGS flag) { } - static inline void record_virtual_memory_reserve(void* addr, size_t size, const NativeCallStack& stack, - MEMFLAGS flag = mtNone) { } - static inline void record_virtual_memory_reserve_and_commit(void* addr, size_t size, - const NativeCallStack& stack, MEMFLAGS flag = mtNone) { } - static inline void record_virtual_memory_split_reserved(void* addr, size_t size, size_t split) { } - static inline void record_virtual_memory_commit(void* addr, size_t size, const NativeCallStack& stack) { } - static inline void record_virtual_memory_type(void* addr, MEMFLAGS flag) { } - static inline void record_thread_stack(void* addr, size_t size) { } - static inline void release_thread_stack(void* addr, size_t size) { } - - static void final_report(outputStream*) { } - static void error_report(outputStream*) { } -}; - -#else - #include "runtime/mutexLocker.hpp" #include "runtime/threadCritical.hpp" #include "services/mallocTracker.hpp" +#include "services/nmtCommon.hpp" #include "services/threadStackTracker.hpp" #include "services/virtualMemoryTracker.hpp" +#include "utilities/nativeCallStack.hpp" #define CURRENT_PC ((MemTracker::tracking_level() == NMT_detail) ? \ NativeCallStack(0) : NativeCallStack::empty_stack()) @@ -309,6 +255,4 @@ class MemTracker : AllStatic { static Mutex* _query_lock; }; -#endif // INCLUDE_NMT - #endif // SHARE_SERVICES_MEMTRACKER_HPP diff --git a/src/hotspot/share/services/nmtDCmd.hpp b/src/hotspot/share/services/nmtDCmd.hpp index 52c61d34c0c..23302b790a6 100644 --- a/src/hotspot/share/services/nmtDCmd.hpp +++ b/src/hotspot/share/services/nmtDCmd.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,8 +25,6 @@ #ifndef SHARE_SERVICES_NMTDCMD_HPP #define SHARE_SERVICES_NMTDCMD_HPP -#if INCLUDE_NMT - #include "services/diagnosticArgument.hpp" #include "services/diagnosticFramework.hpp" #include "services/memBaseline.hpp" @@ -71,6 +69,4 @@ class NMTDCmd: public DCmdWithParser { bool check_detail_tracking_level(outputStream* out); }; -#endif // INCLUDE_NMT - #endif // SHARE_SERVICES_NMTDCMD_HPP diff --git a/src/hotspot/share/services/nmtPreInit.cpp b/src/hotspot/share/services/nmtPreInit.cpp index 1fdf4ba9d9f..67eb3eef41f 100644 --- a/src/hotspot/share/services/nmtPreInit.cpp +++ b/src/hotspot/share/services/nmtPreInit.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2021 SAP SE. All rights reserved. - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022 SAP SE. All rights reserved. + * Copyright (c) 2022, 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,8 +31,6 @@ #include "utilities/ostream.hpp" #include "utilities/globalDefinitions.hpp" -#if INCLUDE_NMT - // Obviously we cannot use os::malloc for any dynamic allocation during pre-NMT-init, so we must use // raw malloc; to make this very clear, wrap them. static void* raw_malloc(size_t s) { return ::malloc(s); } @@ -190,5 +188,3 @@ void NMTPreInit::print_state(outputStream* st) { st->print_cr("pre-init mallocs: %u, pre-init reallocs: %u, pre-init frees: %u", _num_mallocs_pre, _num_reallocs_pre, _num_frees_pre); } - -#endif // INCLUDE_NMT diff --git a/src/hotspot/share/services/nmtPreInit.hpp b/src/hotspot/share/services/nmtPreInit.hpp index eed25191135..d65ebaf5dc3 100644 --- a/src/hotspot/share/services/nmtPreInit.hpp +++ b/src/hotspot/share/services/nmtPreInit.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2021 SAP SE. All rights reserved. - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022 SAP SE. All rights reserved. + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,8 +34,6 @@ #include "utilities/globalDefinitions.hpp" #include "utilities/macros.hpp" -#if INCLUDE_NMT - class outputStream; // NMTPreInit is the solution to a specific problem: @@ -353,7 +351,5 @@ public: DEBUG_ONLY(static void verify();) }; -#endif // INCLUDE_NMT - #endif // SHARE_SERVICES_NMT_PREINIT_HPP diff --git a/src/hotspot/share/services/threadStackTracker.hpp b/src/hotspot/share/services/threadStackTracker.hpp index 74e2311b763..db7fc0e8569 100644 --- a/src/hotspot/share/services/threadStackTracker.hpp +++ b/src/hotspot/share/services/threadStackTracker.hpp @@ -25,8 +25,6 @@ #ifndef SHARE_SERVICES_THREADSTACKTRACKER_HPP #define SHARE_SERVICES_THREADSTACKTRACKER_HPP -#if INCLUDE_NMT - #include "services/allocationSite.hpp" #include "services/mallocSiteTable.hpp" #include "services/nmtCommon.hpp" @@ -84,5 +82,5 @@ public: static bool walk_simple_thread_stack_site(MallocSiteWalker* walker); }; -#endif // INCLUDE_NMT #endif // SHARE_SERVICES_THREADSTACKTRACKER_HPP + diff --git a/src/hotspot/share/services/virtualMemoryTracker.hpp b/src/hotspot/share/services/virtualMemoryTracker.hpp index 2f04503cf6e..15627470f78 100644 --- a/src/hotspot/share/services/virtualMemoryTracker.hpp +++ b/src/hotspot/share/services/virtualMemoryTracker.hpp @@ -25,8 +25,6 @@ #ifndef SHARE_SERVICES_VIRTUALMEMORYTRACKER_HPP #define SHARE_SERVICES_VIRTUALMEMORYTRACKER_HPP -#if INCLUDE_NMT - #include "memory/allocation.hpp" #include "memory/metaspace.hpp" // For MetadataType #include "memory/metaspaceStats.hpp" @@ -396,6 +394,5 @@ class VirtualMemoryTracker : AllStatic { static SortedLinkedList* _reserved_regions; }; -#endif // INCLUDE_NMT - #endif // SHARE_SERVICES_VIRTUALMEMORYTRACKER_HPP + diff --git a/src/hotspot/share/utilities/debug.cpp b/src/hotspot/share/utilities/debug.cpp index c3c98d3067f..bb2a0446aee 100644 --- a/src/hotspot/share/utilities/debug.cpp +++ b/src/hotspot/share/utilities/debug.cpp @@ -483,8 +483,6 @@ extern "C" JNIEXPORT void pp(void* p) { oop obj = cast_to_oop(p); obj->print(); } else { -#if INCLUDE_NMT - // With NMT if (MemTracker::enabled()) { const NMT_TrackingLevel tracking_level = MemTracker::tracking_level(); ReservedMemoryRegion region(0, 0); @@ -517,7 +515,6 @@ extern "C" JNIEXPORT void pp(void* p) { } } } -#endif // INCLUDE_NMT tty->print(PTR_FORMAT, p2i(p)); } } diff --git a/src/hotspot/share/utilities/macros.hpp b/src/hotspot/share/utilities/macros.hpp index 9b362b88c11..9207e8a1739 100644 --- a/src/hotspot/share/utilities/macros.hpp +++ b/src/hotspot/share/utilities/macros.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -241,22 +241,6 @@ #define NOT_ZGC_RETURN_(code) { return code; } #endif // INCLUDE_ZGC -#ifndef INCLUDE_NMT -#define INCLUDE_NMT 1 -#endif // INCLUDE_NMT - -#if INCLUDE_NMT -#define NOT_NMT_RETURN /* next token must be ; */ -#define NOT_NMT_RETURN_(code) /* next token must be ; */ -#define NMT_ONLY(x) x -#define NOT_NMT(x) -#else -#define NOT_NMT_RETURN {} -#define NOT_NMT_RETURN_(code) { return code; } -#define NMT_ONLY(x) -#define NOT_NMT(x) x -#endif // INCLUDE_NMT - #ifndef INCLUDE_JFR #define INCLUDE_JFR 1 #endif diff --git a/test/hotspot/gtest/nmt/test_nmt_buffer_overflow_detection.cpp b/test/hotspot/gtest/nmt/test_nmt_buffer_overflow_detection.cpp index c1aeb3e845c..ce30fb8d61d 100644 --- a/test/hotspot/gtest/nmt/test_nmt_buffer_overflow_detection.cpp +++ b/test/hotspot/gtest/nmt/test_nmt_buffer_overflow_detection.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2021 SAP SE. All rights reserved. - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022 SAP SE. All rights reserved. + * Copyright (c) 2022, 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,14 +31,10 @@ #include "unittest.hpp" #include "testutils.hpp" -#if INCLUDE_NMT - // This prefix shows up on any c heap corruption NMT detects. If unsure which assert will // come, just use this one. #define COMMON_NMT_HEAP_CORRUPTION_MESSAGE_PREFIX "NMT corruption" - - #define DEFINE_TEST(test_function, expected_assertion_message) \ TEST_VM_FATAL_ERROR_MSG(NMT, test_function, ".*" expected_assertion_message ".*") { \ if (MemTracker::tracking_level() > NMT_off) { \ @@ -165,5 +161,3 @@ TEST_VM(NMT, test_realloc) { } } } - -#endif // INCLUDE_NMT diff --git a/test/hotspot/gtest/nmt/test_nmtpreinit.cpp b/test/hotspot/gtest/nmt/test_nmtpreinit.cpp index 310cbb187b2..6475e865708 100644 --- a/test/hotspot/gtest/nmt/test_nmtpreinit.cpp +++ b/test/hotspot/gtest/nmt/test_nmtpreinit.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2021 SAP SE. All rights reserved. - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022 SAP SE. All rights reserved. + * Copyright (c) 2021, 2022, 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 @@ -54,8 +54,6 @@ // us. So inside that scope VM initialization ran and with it the NMT initialization. // To be sure, we assert those assumptions. -#if INCLUDE_NMT - // Some shorts to save writing out the flags every time static void* os_malloc(size_t s) { return os::malloc(s, mtTest); } static void* os_realloc(void* old, size_t s) { return os::realloc(old, s, mtTest); } @@ -127,5 +125,3 @@ TEST_VM(NMTPreInit, pre_to_post_allocs) { g_test_allocations.test_post(); g_test_allocations.free_all(); } - -#endif // INCLUDE_NMT diff --git a/test/hotspot/gtest/nmt/test_nmtpreinitmap.cpp b/test/hotspot/gtest/nmt/test_nmtpreinitmap.cpp index 356c79a8d4a..e68d5ca069a 100644 --- a/test/hotspot/gtest/nmt/test_nmtpreinitmap.cpp +++ b/test/hotspot/gtest/nmt/test_nmtpreinitmap.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2021 SAP SE. All rights reserved. - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022 SAP SE. All rights reserved. + * Copyright (c) 2021, 2022, 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,8 +31,6 @@ #include "utilities/ostream.hpp" #include "unittest.hpp" -#if INCLUDE_NMT - // This tests the NMTPreInitAllocationTable hash table used to store C-heap allocations before NMT initialization ran. static size_t small_random_nonzero_size() { @@ -132,5 +130,3 @@ TEST_VM_ASSERT_MSG(NMTPreInit, assert_on_lu_table_overflow, ".*NMT preinit looku table.verify(); } #endif // ASSERT - -#endif // INCLUDE_NMT diff --git a/test/hotspot/gtest/runtime/test_committed_virtualmemory.cpp b/test/hotspot/gtest/runtime/test_committed_virtualmemory.cpp index 0abc004a935..b95b86c1247 100644 --- a/test/hotspot/gtest/runtime/test_committed_virtualmemory.cpp +++ b/test/hotspot/gtest/runtime/test_committed_virtualmemory.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,8 +26,6 @@ // Included early because the NMT flags don't include it. #include "utilities/macros.hpp" -#if INCLUDE_NMT - #include "runtime/thread.hpp" #include "services/memTracker.hpp" #include "services/virtualMemoryTracker.hpp" @@ -223,5 +221,3 @@ TEST_VM(CommittedVirtualMemoryTracker, test_committed_virtualmemory_region) { } } - -#endif // INCLUDE_NMT diff --git a/test/hotspot/gtest/runtime/test_virtualMemoryTracker.cpp b/test/hotspot/gtest/runtime/test_virtualMemoryTracker.cpp index ae4457f3e93..4aa058dc160 100644 --- a/test/hotspot/gtest/runtime/test_virtualMemoryTracker.cpp +++ b/test/hotspot/gtest/runtime/test_virtualMemoryTracker.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,16 +32,13 @@ #include "precompiled.hpp" -// Included early because the NMT flags don't include it. -#include "utilities/macros.hpp" - -#if INCLUDE_NMT - #include "memory/virtualspace.hpp" #include "services/memTracker.hpp" #include "services/virtualMemoryTracker.hpp" #include "utilities/globalDefinitions.hpp" +#include "utilities/macros.hpp" #include "unittest.hpp" + #include // #define LOG(...) printf(__VA_ARGS__); printf("\n"); fflush(stdout); @@ -566,5 +563,3 @@ TEST_VM(NMT_VirtualMemoryTracker, remove_uncommitted_region) { tty->print_cr("skipped."); } } - -#endif // INCLUDE_NMT -- GitLab From a3a0dcd9215beb6baf43c6e94f8e16fb6a2ccf68 Mon Sep 17 00:00:00 2001 From: Yumin Qi Date: Thu, 27 Jan 2022 18:58:49 +0000 Subject: [PATCH 313/564] 8280353: -XX:ArchiveClassesAtExit should print warning if base archive failed to load Reviewed-by: iklam, ccheung --- src/hotspot/share/cds/metaspaceShared.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/hotspot/share/cds/metaspaceShared.cpp b/src/hotspot/share/cds/metaspaceShared.cpp index c79e8df4200..5070f7bf39a 100644 --- a/src/hotspot/share/cds/metaspaceShared.cpp +++ b/src/hotspot/share/cds/metaspaceShared.cpp @@ -955,6 +955,9 @@ void MetaspaceShared::initialize_runtime_shared_and_meta_spaces() { } } else { set_shared_metaspace_range(NULL, NULL, NULL); + if (DynamicDumpSharedSpaces) { + warning("-XX:ArchiveClassesAtExit is unsupported when base CDS archive is not loaded. Run with -Xlog:cds for more info."); + } UseSharedSpaces = false; // The base archive cannot be mapped. We cannot dump the dynamic shared archive. AutoCreateSharedArchive = false; -- GitLab From b94ebaa09c9ff788a37edcdbd043f9bb3998cede Mon Sep 17 00:00:00 2001 From: Xin Liu Date: Thu, 27 Jan 2022 19:31:19 +0000 Subject: [PATCH 314/564] 8280686: Remove Compile::print_method_impl Reviewed-by: neliasso, chagedorn, thartmann --- src/hotspot/share/opto/compile.cpp | 28 +++++++++------------------- src/hotspot/share/opto/compile.hpp | 6 ++---- src/hotspot/share/opto/vector.cpp | 10 +++++----- 3 files changed, 16 insertions(+), 28 deletions(-) diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index c730d1d9c98..9adda4961e5 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -1892,7 +1892,7 @@ bool Compile::inline_incrementally_one() { return false; } else if (inlining_progress()) { _late_inlines_pos = i+1; // restore the position in case new elements were inserted - print_method(PHASE_INCREMENTAL_INLINE_STEP, cg->call_node(), 3); + print_method(PHASE_INCREMENTAL_INLINE_STEP, 3, cg->call_node()); break; // process one call site at a time } } else { @@ -2357,7 +2357,7 @@ void Compile::inline_vector_reboxing_calls() { CallGenerator* cg = _vector_reboxing_late_inlines.pop(); cg->do_late_inline(); if (failing()) return; - print_method(PHASE_INLINE_VECTOR_REBOX, cg->call_node(), 3); + print_method(PHASE_INLINE_VECTOR_REBOX, 3, cg->call_node()); } _vector_reboxing_late_inlines.trunc_to(0); } @@ -4814,30 +4814,20 @@ void Compile::sort_macro_nodes() { } } -void Compile::print_method(CompilerPhaseType cpt, int level) { - print_method_impl(cpt, NOT_PRODUCT(CompilerPhaseTypeHelper::to_string(cpt) COMMA) level); -} - -void Compile::print_method(CompilerPhaseType cpt, Node* n, int level) { +void Compile::print_method(CompilerPhaseType cpt, int level, Node* n) { + EventCompilerPhase event; + if (event.should_commit()) { + CompilerEvent::PhaseEvent::post(event, C->_latest_stage_start_counter, cpt, C->_compile_id, level); + } #ifndef PRODUCT ResourceMark rm; stringStream ss; ss.print_raw(CompilerPhaseTypeHelper::to_string(cpt)); - if (n != NULL) { + if (n != nullptr) { ss.print(": %d %s ", n->_idx, NodeClassNames[n->Opcode()]); - } else { - ss.print_raw(": NULL"); } -#endif - C->print_method_impl(cpt, NOT_PRODUCT(ss.as_string() COMMA) level); -} -void Compile::print_method_impl(CompilerPhaseType cpt, NOT_PRODUCT(const char* name COMMA) int level) { - EventCompilerPhase event; - if (event.should_commit()) { - CompilerEvent::PhaseEvent::post(event, C->_latest_stage_start_counter, cpt, C->_compile_id, level); - } -#ifndef PRODUCT + const char* name = ss.as_string(); if (should_print_igv(level)) { _igv_printer->print_method(name, level); } diff --git a/src/hotspot/share/opto/compile.hpp b/src/hotspot/share/opto/compile.hpp index 0bf6b88eb17..70480b0d06e 100644 --- a/src/hotspot/share/opto/compile.hpp +++ b/src/hotspot/share/opto/compile.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -655,9 +655,7 @@ class Compile : public Phase { void end_method(); bool should_print_igv(int level); - void print_method(CompilerPhaseType cpt, int level); - void print_method(CompilerPhaseType cpt, Node* n, int level); - void print_method_impl(CompilerPhaseType cpt, NOT_PRODUCT(const char* name COMMA) int level); + void print_method(CompilerPhaseType cpt, int level, Node* n = nullptr); #ifndef PRODUCT void igv_print_method_to_file(const char* phase_name = "Debug", bool append = false); diff --git a/src/hotspot/share/opto/vector.cpp b/src/hotspot/share/opto/vector.cpp index a1e324363db..137990ddc77 100644 --- a/src/hotspot/share/opto/vector.cpp +++ b/src/hotspot/share/opto/vector.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, 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 @@ -96,7 +96,7 @@ void PhaseVector::scalarize_vbox_nodes() { VectorBoxNode* vbox = static_cast(n); scalarize_vbox_node(vbox); if (C->failing()) return; - C->print_method(PHASE_SCALARIZE_VBOX, vbox, 3); + C->print_method(PHASE_SCALARIZE_VBOX, 3, vbox); } if (C->failing()) return; macro_idx = MIN2(macro_idx - 1, C->macro_count() - 1); @@ -131,7 +131,7 @@ void PhaseVector::expand_vunbox_nodes() { VectorUnboxNode* vec_unbox = static_cast(n); expand_vunbox_node(vec_unbox); if (C->failing()) return; - C->print_method(PHASE_EXPAND_VUNBOX, vec_unbox, 3); + C->print_method(PHASE_EXPAND_VUNBOX, 3, vec_unbox); } if (C->failing()) return; macro_idx = MIN2(macro_idx - 1, C->macro_count() - 1); @@ -149,7 +149,7 @@ void PhaseVector::eliminate_vbox_alloc_nodes() { VectorBoxAllocateNode* vbox_alloc = static_cast(n); eliminate_vbox_alloc_node(vbox_alloc); if (C->failing()) return; - C->print_method(PHASE_ELIMINATE_VBOX_ALLOC, vbox_alloc, 3); + C->print_method(PHASE_ELIMINATE_VBOX_ALLOC, 3, vbox_alloc); } if (C->failing()) return; macro_idx = MIN2(macro_idx - 1, C->macro_count() - 1); @@ -297,7 +297,7 @@ void PhaseVector::expand_vbox_node(VectorBoxNode* vec_box) { Node* vect = vec_box->in(VectorBoxNode::Value); Node* result = expand_vbox_node_helper(vbox, vect, vec_box->box_type(), vec_box->vec_type()); C->gvn_replace_by(vec_box, result); - C->print_method(PHASE_EXPAND_VBOX, vec_box, 3); + C->print_method(PHASE_EXPAND_VBOX, 3, vec_box); } C->remove_macro_node(vec_box); } -- GitLab From ece89c6df167e9a7f99b00e3f89c2c41c10ab31b Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Thu, 27 Jan 2022 21:00:45 +0000 Subject: [PATCH 315/564] 8280366: (fs) Restore Files.createTempFile javadoc Reviewed-by: alanb, lancea --- src/java.base/share/classes/java/nio/file/Files.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/java.base/share/classes/java/nio/file/Files.java b/src/java.base/share/classes/java/nio/file/Files.java index b0184395af0..0d9bba9cbca 100644 --- a/src/java.base/share/classes/java/nio/file/Files.java +++ b/src/java.base/share/classes/java/nio/file/Files.java @@ -823,11 +823,12 @@ public final class Files { * names in the same manner as the {@link * java.io.File#createTempFile(String,String,File)} method. * - *

    The file may be opened using the {@link + *

    As with the {@code File.createTempFile} methods, this method is only + * part of a temporary-file facility. Where used as a work file, + * the resulting file may be opened using the {@link * StandardOpenOption#DELETE_ON_CLOSE DELETE_ON_CLOSE} option so that the - * file is deleted when the appropriate {@code close} method is invoked - * either explicitly or via a try-with-resources statement. Alternatively, - * a {@link Runtime#addShutdownHook shutdown-hook}, or the + * file is deleted when the appropriate {@code close} method is invoked. + * Alternatively, a {@link Runtime#addShutdownHook shutdown-hook}, or the * {@link java.io.File#deleteOnExit} mechanism may be used to delete the * file automatically. * -- GitLab From 6d242e406539e97bdd4da82c478db901942b770f Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Thu, 27 Jan 2022 21:58:44 +0000 Subject: [PATCH 316/564] 8280835: jdk/javadoc/tool/CheckManPageOptions.java depends on source hierarchy Reviewed-by: hannesw --- .../jdk/javadoc/tool/CheckManPageOptions.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/test/langtools/jdk/javadoc/tool/CheckManPageOptions.java b/test/langtools/jdk/javadoc/tool/CheckManPageOptions.java index 5a0d83926c8..a5b853c7aa4 100644 --- a/test/langtools/jdk/javadoc/tool/CheckManPageOptions.java +++ b/test/langtools/jdk/javadoc/tool/CheckManPageOptions.java @@ -54,8 +54,14 @@ import java.util.stream.Collectors; * of the javadoc man page against the set of options declared in the source code. */ public class CheckManPageOptions { + static class SourceDirNotFound extends Error { } + public static void main(String... args) throws Exception { - new CheckManPageOptions().run(args); + try { + new CheckManPageOptions().run(args); + } catch (SourceDirNotFound e) { + System.err.println("NOTE: Cannot find src directory; test skipped"); + } } static final PrintStream out = System.err; @@ -143,7 +149,7 @@ public class CheckManPageOptions { } dir = dir.getParent(); } - throw new IllegalStateException("cannot find root dir"); + throw new SourceDirNotFound(); } List getToolOptions() throws Error { -- GitLab From 40a2ce20334207b542d18f52e26bf418bf29c9ca Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Thu, 27 Jan 2022 22:57:09 +0000 Subject: [PATCH 317/564] 8270476: Make floating-point test infrastructure more lambda and method reference friendly Reviewed-by: bpb --- test/jdk/java/lang/Math/Atan2Tests.java | 11 +- .../jdk/java/lang/Math/CeilAndFloorTests.java | 10 +- test/jdk/java/lang/Math/CubeRootTests.java | 20 +-- .../java/lang/Math/ExpCornerCaseTests.java | 6 +- test/jdk/java/lang/Math/Expm1Tests.java | 5 +- .../java/lang/Math/FusedMultiplyAddTests.java | 14 +- test/jdk/java/lang/Math/HyperbolicTests.java | 123 ++++++----------- test/jdk/java/lang/Math/HypotTests.java | 27 ++-- .../lang/Math/Ieee754SpecialCaseTests.java | 18 +-- .../java/lang/Math/IeeeRecommendedTests.java | 39 +++--- test/jdk/java/lang/Math/Log10Tests.java | 15 +- test/jdk/java/lang/Math/Log1pTests.java | 15 +- test/jdk/java/lang/Math/PowTests.java | 25 ++-- test/jdk/java/lang/Math/Rint.java | 16 +-- test/jdk/java/lang/Math/RoundTests.java | 28 ++-- .../lang/Math/SinCosCornerCasesTests.java | 7 +- test/jdk/java/lang/Math/TanTests.java | 11 +- test/jdk/java/lang/Math/Tests.java | 129 ++++++++++++++---- test/jdk/java/lang/Math/WorstCaseTests.java | 47 ++++--- .../java/lang/StrictMath/CubeRootTests.java | 7 +- test/jdk/java/lang/StrictMath/Expm1Tests.java | 7 +- .../java/lang/StrictMath/HyperbolicTests.java | 9 +- test/jdk/java/lang/StrictMath/HypotTests.java | 19 ++- test/jdk/java/lang/StrictMath/Log10Tests.java | 5 +- test/jdk/java/lang/StrictMath/Log1pTests.java | 5 +- test/jdk/java/lang/StrictMath/PowTests.java | 5 +- test/jdk/java/lang/StrictMath/Tests.java | 43 ++++-- 27 files changed, 320 insertions(+), 346 deletions(-) diff --git a/test/jdk/java/lang/Math/Atan2Tests.java b/test/jdk/java/lang/Math/Atan2Tests.java index d6ff8605ddd..7e5dca17f1b 100644 --- a/test/jdk/java/lang/Math/Atan2Tests.java +++ b/test/jdk/java/lang/Math/Atan2Tests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 4984407 * @summary Tests for {Math, StrictMath}.atan2 - * @author Joseph D. Darcy */ public class Atan2Tests { @@ -33,10 +32,8 @@ public class Atan2Tests { static int testAtan2Case(double input1, double input2, double expected) { int failures = 0; - failures += Tests.test("StrictMath.atan2(double, double)", input1, input2, - StrictMath.atan2(input1, input2), expected); - failures += Tests.test("Math.atan2(double, double)", input1, input2, - Math.atan2(input1, input2), expected); + failures += Tests.test("StrictMath.atan2", input1, input2, StrictMath::atan2, expected); + failures += Tests.test("Math.atan2", input1, input2, Math::atan2, expected); return failures; } @@ -55,7 +52,7 @@ public class Atan2Tests { return failures; } - public static void main(String [] argv) { + public static void main(String... argv) { int failures = 0; failures += testAtan2(); diff --git a/test/jdk/java/lang/Math/CeilAndFloorTests.java b/test/jdk/java/lang/Math/CeilAndFloorTests.java index d4508f839c8..6b75b2a8dcb 100644 --- a/test/jdk/java/lang/Math/CeilAndFloorTests.java +++ b/test/jdk/java/lang/Math/CeilAndFloorTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,15 +30,15 @@ public class CeilAndFloorTests { private static int testCeilCase(double input, double expected) { int failures = 0; - failures += Tests.test("Math.ceil", input, Math.ceil(input), expected); - failures += Tests.test("StrictMath.ceil", input, StrictMath.ceil(input), expected); + failures += Tests.test("Math.ceil", input, Math::ceil, expected); + failures += Tests.test("StrictMath.ceil", input, StrictMath::ceil, expected); return failures; } private static int testFloorCase(double input, double expected) { int failures = 0; - failures += Tests.test("Math.floor", input, Math.floor(input), expected); - failures += Tests.test("StrictMath.floor", input, StrictMath.floor(input), expected); + failures += Tests.test("Math.floor", input, Math::floor, expected); + failures += Tests.test("StrictMath.floor", input, StrictMath::floor, expected); return failures; } diff --git a/test/jdk/java/lang/Math/CubeRootTests.java b/test/jdk/java/lang/Math/CubeRootTests.java index 53ef270377f..a6350702d90 100644 --- a/test/jdk/java/lang/Math/CubeRootTests.java +++ b/test/jdk/java/lang/Math/CubeRootTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,6 @@ * @run main CubeRootTests * @bug 4347132 4939441 8078672 * @summary Tests for {Math, StrictMath}.cbrt (use -Dseed=X to set PRNG seed) - * @author Joseph D. Darcy * @key randomness */ @@ -46,17 +45,10 @@ public class CubeRootTests { static int testCubeRootCase(double input, double expected) { int failures=0; - double minus_input = -input; - double minus_expected = -expected; - - failures+=Tests.test("Math.cbrt(double)", input, - Math.cbrt(input), expected); - failures+=Tests.test("Math.cbrt(double)", minus_input, - Math.cbrt(minus_input), minus_expected); - failures+=Tests.test("StrictMath.cbrt(double)", input, - StrictMath.cbrt(input), expected); - failures+=Tests.test("StrictMath.cbrt(double)", minus_input, - StrictMath.cbrt(minus_input), minus_expected); + failures+=Tests.test("Math.cbrt", input, Math::cbrt, expected); + failures+=Tests.test("Math.cbrt", -input, Math::cbrt, -expected); + failures+=Tests.test("StrictMath.cbrt", input, StrictMath::cbrt, expected); + failures+=Tests.test("StrictMath.cbrt", -input, StrictMath::cbrt, -expected); return failures; } @@ -324,7 +316,7 @@ public class CubeRootTests { return failures; } - public static void main(String argv[]) { + public static void main(String... argv) { int failures = 0; failures += testCubeRoot(); diff --git a/test/jdk/java/lang/Math/ExpCornerCaseTests.java b/test/jdk/java/lang/Math/ExpCornerCaseTests.java index 16168254378..e48f31beb91 100644 --- a/test/jdk/java/lang/Math/ExpCornerCaseTests.java +++ b/test/jdk/java/lang/Math/ExpCornerCaseTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2022, 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 @@ -61,8 +61,8 @@ public class ExpCornerCaseTests { private static int testExp(double input, double expected) { int failures = 0; - failures += Tests.test("StrictMath.exp", input, StrictMath.exp(input), expected); - failures += Tests.test("Math.exp", input, Math.exp(input), expected); + failures += Tests.test("StrictMath.exp", input, StrictMath::exp, expected); + failures += Tests.test("Math.exp", input, Math::exp, expected); return failures; } } diff --git a/test/jdk/java/lang/Math/Expm1Tests.java b/test/jdk/java/lang/Math/Expm1Tests.java index 5bf267d15fd..204fe44ef15 100644 --- a/test/jdk/java/lang/Math/Expm1Tests.java +++ b/test/jdk/java/lang/Math/Expm1Tests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 4851638 4900189 4939441 * @summary Tests for {Math, StrictMath}.expm1 - * @author Joseph D. Darcy */ /* @@ -214,7 +213,7 @@ public class Expm1Tests { return failures; } - public static void main(String argv[]) { + public static void main(String... argv) { int failures = 0; failures += testExpm1(); diff --git a/test/jdk/java/lang/Math/FusedMultiplyAddTests.java b/test/jdk/java/lang/Math/FusedMultiplyAddTests.java index 03e164c2198..61a3bfb0de1 100644 --- a/test/jdk/java/lang/Math/FusedMultiplyAddTests.java +++ b/test/jdk/java/lang/Math/FusedMultiplyAddTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, 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,16 +365,12 @@ public class FusedMultiplyAddTests { private static int testFusedMacCase(double input1, double input2, double input3, double expected) { int failures = 0; - failures += Tests.test("Math.fma(double)", input1, input2, input3, - Math.fma(input1, input2, input3), expected); - failures += Tests.test("StrictMath.fma(double)", input1, input2, input3, - StrictMath.fma(input1, input2, input3), expected); + failures += Tests.test("Math.fma", input1, input2, input3, Math::fma, expected); + failures += Tests.test("StrictMath.fma", input1, input2, input3, StrictMath::fma, expected); // Permute first two inputs - failures += Tests.test("Math.fma(double)", input2, input1, input3, - Math.fma(input2, input1, input3), expected); - failures += Tests.test("StrictMath.fma(double)", input2, input1, input3, - StrictMath.fma(input2, input1, input3), expected); + failures += Tests.test("Math.fma", input2, input1, input3, Math::fma, expected); + failures += Tests.test("StrictMath.fma", input2, input1, input3, StrictMath::fma, expected); return failures; } diff --git a/test/jdk/java/lang/Math/HyperbolicTests.java b/test/jdk/java/lang/Math/HyperbolicTests.java index 0df493698fe..8309606f63d 100644 --- a/test/jdk/java/lang/Math/HyperbolicTests.java +++ b/test/jdk/java/lang/Math/HyperbolicTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 4851625 4900189 4939441 * @summary Tests for {Math, StrictMath}.{sinh, cosh, tanh} - * @author Joseph D. Darcy */ public class HyperbolicTests { @@ -33,6 +32,20 @@ public class HyperbolicTests { static final double NaNd = Double.NaN; + public static void main(String... argv) { + int failures = 0; + + failures += testSinh(); + failures += testCosh(); + failures += testTanh(); + + if (failures > 0) { + System.err.println("Testing the hyperbolic functions incurred " + + failures + " failures."); + throw new RuntimeException(); + } + } + /** * Test accuracy of {Math, StrictMath}.sinh. The specified * accuracy is 2.5 ulps. @@ -355,19 +368,11 @@ public class HyperbolicTests { double expected, double tolerance) { int failures = 0; - failures += Tests.testTolerance("Math.sinh(double)", - input, Math.sinh(input), - expected, tolerance); - failures += Tests.testTolerance("Math.sinh(double)", - -input, Math.sinh(-input), - -expected, tolerance); + failures += Tests.testTolerance("Math.sinh", input, Math::sinh, expected, tolerance); + failures += Tests.testTolerance("Math.sinh", -input, Math::sinh, -expected, tolerance); - failures += Tests.testTolerance("StrictMath.sinh(double)", - input, StrictMath.sinh(input), - expected, tolerance); - failures += Tests.testTolerance("StrictMath.sinh(double)", - -input, StrictMath.sinh(-input), - -expected, tolerance); + failures += Tests.testTolerance("StrictMath.sinh", input, StrictMath::sinh, expected, tolerance); + failures += Tests.testTolerance("StrictMath.sinh", -input, StrictMath::sinh, -expected, tolerance); return failures; } @@ -375,23 +380,14 @@ public class HyperbolicTests { double expected, double ulps) { int failures = 0; - failures += Tests.testUlpDiff("Math.sinh(double)", - input, Math.sinh(input), - expected, ulps); - failures += Tests.testUlpDiff("Math.sinh(double)", - -input, Math.sinh(-input), - -expected, ulps); - - failures += Tests.testUlpDiff("StrictMath.sinh(double)", - input, StrictMath.sinh(input), - expected, ulps); - failures += Tests.testUlpDiff("StrictMath.sinh(double)", - -input, StrictMath.sinh(-input), - -expected, ulps); + failures += Tests.testUlpDiff("Math.sinh", input, Math::sinh, expected, ulps); + failures += Tests.testUlpDiff("Math.sinh", -input, Math::sinh, -expected, ulps); + + failures += Tests.testUlpDiff("StrictMath.sinh", input, StrictMath::sinh, expected, ulps); + failures += Tests.testUlpDiff("StrictMath.sinh", -input, StrictMath::sinh, -expected, ulps); return failures; } - /** * Test accuracy of {Math, StrictMath}.cosh. The specified * accuracy is 2.5 ulps. @@ -594,7 +590,6 @@ public class HyperbolicTests { 3.0); } - double [][] specialTestCases = { {0.0, 1.0}, {NaNd, NaNd}, @@ -733,23 +728,14 @@ public class HyperbolicTests { double expected, double ulps) { int failures = 0; - failures += Tests.testUlpDiff("Math.cosh(double)", - input, Math.cosh(input), - expected, ulps); - failures += Tests.testUlpDiff("Math.cosh(double)", - -input, Math.cosh(-input), - expected, ulps); - - failures += Tests.testUlpDiff("StrictMath.cosh(double)", - input, StrictMath.cosh(input), - expected, ulps); - failures += Tests.testUlpDiff("StrictMath.cosh(double)", - -input, StrictMath.cosh(-input), - expected, ulps); + failures += Tests.testUlpDiff("Math.cosh", input, Math::cosh, expected, ulps); + failures += Tests.testUlpDiff("Math.cosh", -input, Math::cosh, expected, ulps); + + failures += Tests.testUlpDiff("StrictMath.cosh", input, StrictMath::cosh, expected, ulps); + failures += Tests.testUlpDiff("StrictMath.cosh", -input, StrictMath::cosh, expected, ulps); return failures; } - /** * Test accuracy of {Math, StrictMath}.tanh. The specified * accuracy is 2.5 ulps. @@ -952,7 +938,6 @@ public class HyperbolicTests { 3.0); } - double [][] specialTestCases = { {0.0, 0.0}, {NaNd, NaNd}, @@ -1007,19 +992,11 @@ public class HyperbolicTests { double expected, double tolerance) { int failures = 0; - failures += Tests.testTolerance("Math.tanh(double", - input, Math.tanh(input), - expected, tolerance); - failures += Tests.testTolerance("Math.tanh(double", - -input, Math.tanh(-input), - -expected, tolerance); + failures += Tests.testTolerance("Math.tanh", input, Math::tanh, expected, tolerance); + failures += Tests.testTolerance("Math.tanh", -input, Math::tanh, -expected, tolerance); - failures += Tests.testTolerance("StrictMath.tanh(double", - input, StrictMath.tanh(input), - expected, tolerance); - failures += Tests.testTolerance("StrictMath.tanh(double", - -input, StrictMath.tanh(-input), - -expected, tolerance); + failures += Tests.testTolerance("StrictMath.tanh", input, StrictMath::tanh, expected, tolerance); + failures += Tests.testTolerance("StrictMath.tanh", -input, StrictMath::tanh, -expected, tolerance); return failures; } @@ -1028,35 +1005,11 @@ public class HyperbolicTests { double ulps) { int failures = 0; - failures += Tests.testUlpDiffWithAbsBound("Math.tanh(double)", - input, Math.tanh(input), - expected, ulps, 1.0); - failures += Tests.testUlpDiffWithAbsBound("Math.tanh(double)", - -input, Math.tanh(-input), - -expected, ulps, 1.0); - - failures += Tests.testUlpDiffWithAbsBound("StrictMath.tanh(double)", - input, StrictMath.tanh(input), - expected, ulps, 1.0); - failures += Tests.testUlpDiffWithAbsBound("StrictMath.tanh(double)", - -input, StrictMath.tanh(-input), - -expected, ulps, 1.0); - return failures; - } - - - public static void main(String argv[]) { - int failures = 0; + failures += Tests.testUlpDiffWithAbsBound("Math.tanh", input, Math::tanh, expected, ulps, 1.0); + failures += Tests.testUlpDiffWithAbsBound("Math.tanh", -input, Math::tanh, -expected, ulps, 1.0); - failures += testSinh(); - failures += testCosh(); - failures += testTanh(); - - if (failures > 0) { - System.err.println("Testing the hyperbolic functions incurred " - + failures + " failures."); - throw new RuntimeException(); - } + failures += Tests.testUlpDiffWithAbsBound("StrictMath.tanh", input, StrictMath::tanh, expected, ulps, 1.0); + failures += Tests.testUlpDiffWithAbsBound("StrictMath.tanh", -input, StrictMath::tanh, -expected, ulps, 1.0); + return failures; } - } diff --git a/test/jdk/java/lang/Math/HypotTests.java b/test/jdk/java/lang/Math/HypotTests.java index d7e562ca5fd..e09799e34a4 100644 --- a/test/jdk/java/lang/Math/HypotTests.java +++ b/test/jdk/java/lang/Math/HypotTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,6 @@ * @run main HypotTests * @bug 4851638 4939441 8078672 8240632 * @summary Tests for {Math, StrictMath}.hypot (use -Dseed=X to set PRNG seed) - * @author Joseph D. Darcy * @key randomness */ @@ -51,7 +50,6 @@ public class HypotTests { long N = n; long result[] = new long[3]; - result[0] = Math.abs(M*M - N*N); result[1] = Math.abs(2*M*N); result[2] = Math.abs(M*M + N*N); @@ -188,13 +186,11 @@ public class HypotTests { pcNeighborsStrictHypot[j+1] ); } - } } } - return failures; } @@ -221,26 +217,22 @@ public class HypotTests { // each input negated singly, and both inputs negated. Also // test inputs in reversed order. - for(int i = -1; i <= 1; i+=2) { - for(int j = -1; j <= 1; j+=2) { + for(int i = -1; i <= 1; i += 2) { + for(int j = -1; j <= 1; j += 2) { double x = i * input1; double y = j * input2; - failures += Tests.testUlpDiff("Math.hypot", x, y, - Math.hypot(x, y), expected, ulps); - failures += Tests.testUlpDiff("Math.hypot", y, x, - Math.hypot(y, x ), expected, ulps); - - failures += Tests.testUlpDiff("StrictMath.hypot", x, y, - StrictMath.hypot(x, y), expected, ulps); - failures += Tests.testUlpDiff("StrictMath.hypot", y, x, - StrictMath.hypot(y, x), expected, ulps); + failures += Tests.testUlpDiff("Math.hypot", x, y, Math::hypot, expected, ulps); + failures += Tests.testUlpDiff("Math.hypot", y, x, Math::hypot, expected, ulps); + + failures += Tests.testUlpDiff("StrictMath.hypot", x, y, StrictMath::hypot, expected, ulps); + failures += Tests.testUlpDiff("StrictMath.hypot", y, x, StrictMath::hypot, expected, ulps); } } return failures; } - public static void main(String argv[]) { + public static void main(String... argv) { int failures = 0; failures += testHypot(); @@ -252,5 +244,4 @@ public class HypotTests { throw new RuntimeException(); } } - } diff --git a/test/jdk/java/lang/Math/Ieee754SpecialCaseTests.java b/test/jdk/java/lang/Math/Ieee754SpecialCaseTests.java index d8192f2fee3..f53f2314647 100644 --- a/test/jdk/java/lang/Math/Ieee754SpecialCaseTests.java +++ b/test/jdk/java/lang/Math/Ieee754SpecialCaseTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2022, 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 @@ -62,8 +62,8 @@ public class Ieee754SpecialCaseTests { private static int testCosCase(double input, double expected) { int failures = 0; - failures += Tests.test("Math.cos", input, Math.cos(input), expected); - failures += Tests.test("StrictMath.cos", input, StrictMath.cos(input), expected); + failures += Tests.test("Math.cos", input, Math::cos, expected); + failures += Tests.test("StrictMath.cos", input, StrictMath::cos, expected); return failures; } @@ -82,8 +82,8 @@ public class Ieee754SpecialCaseTests { private static int testAcosCase(double input, double expected) { int failures = 0; - failures += Tests.test("Math.acos", input, Math.acos(input), expected); - failures += Tests.test("StrictMath.acos", input, StrictMath.acos(input), expected); + failures += Tests.test("Math.acos", input, Math::acos, expected); + failures += Tests.test("StrictMath.acos", input, StrictMath::acos, expected); return failures; } @@ -103,8 +103,8 @@ public class Ieee754SpecialCaseTests { private static int testAtanCase(double input, double expected) { int failures = 0; - failures += Tests.test("Math.atan", input, Math.atan(input), expected); - failures += Tests.test("StrictMath.atan", input, StrictMath.atan(input), expected); + failures += Tests.test("Math.atan", input, Math::atan, expected); + failures += Tests.test("StrictMath.atan", input, StrictMath::atan, expected); return failures; } @@ -123,8 +123,8 @@ public class Ieee754SpecialCaseTests { private static int testLogCase(double input, double expected) { int failures = 0; - failures += Tests.test("Math.log", input, Math.log(input), expected); - failures += Tests.test("StrictMath.log", input, StrictMath.log(input), expected); + failures += Tests.test("Math.log", input, Math::log, expected); + failures += Tests.test("StrictMath.log", input, StrictMath::log, expected); return failures; } } diff --git a/test/jdk/java/lang/Math/IeeeRecommendedTests.java b/test/jdk/java/lang/Math/IeeeRecommendedTests.java index 830b16d765a..8570508ff44 100644 --- a/test/jdk/java/lang/Math/IeeeRecommendedTests.java +++ b/test/jdk/java/lang/Math/IeeeRecommendedTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,6 @@ * @run main IeeeRecommendedTests * @bug 4860891 4826732 4780454 4939441 4826652 8078672 * @summary Tests for IEEE 754[R] recommended functions and similar methods (use -Dseed=X to set PRNG seed) - * @author Joseph D. Darcy * @key randomness */ @@ -364,14 +363,14 @@ public class IeeeRecommendedTests { double minus_expected = -expected; failures+=Tests.test("Math.nextAfter(double,double)", start, direction, - Math.nextAfter(start, direction), expected); + Math::nextAfter, expected); failures+=Tests.test("Math.nextAfter(double,double)", minus_start, minus_direction, - Math.nextAfter(minus_start, minus_direction), minus_expected); + Math::nextAfter, minus_expected); failures+=Tests.test("StrictMath.nextAfter(double,double)", start, direction, - StrictMath.nextAfter(start, direction), expected); + StrictMath::nextAfter, expected); failures+=Tests.test("StrictMath.nextAfter(double,double)", minus_start, minus_direction, - StrictMath.nextAfter(minus_start, minus_direction), minus_expected); + StrictMath::nextAfter, minus_expected); return failures; } @@ -586,10 +585,10 @@ public class IeeeRecommendedTests { for(int i = 0; i < testCases.length; i++) { failures+=Tests.test("Math.nextUp(double)", - testCases[i][0], Math.nextUp(testCases[i][0]), testCases[i][1]); + testCases[i][0], Math::nextUp, testCases[i][1]); failures+=Tests.test("StrictMath.nextUp(double)", - testCases[i][0], StrictMath.nextUp(testCases[i][0]), testCases[i][1]); + testCases[i][0], StrictMath::nextUp, testCases[i][1]); } return failures; @@ -665,10 +664,10 @@ public class IeeeRecommendedTests { for(int i = 0; i < testCases.length; i++) { failures+=Tests.test("Math.nextDown(double)", - testCases[i][0], Math.nextDown(testCases[i][0]), testCases[i][1]); + testCases[i][0], Math::nextDown, testCases[i][1]); failures+=Tests.test("StrictMath.nextDown(double)", - testCases[i][0], StrictMath.nextDown(testCases[i][0]), testCases[i][1]); + testCases[i][0], StrictMath::nextDown, testCases[i][1]); } return failures; @@ -906,12 +905,12 @@ public class IeeeRecommendedTests { // copySign(magnitude, sign) failures+=Tests.test("MathcopySign(double,double)", testCases[i][m],testCases[j][n], - Math.copySign(testCases[i][m], testCases[j][n]), + Math::copySign, (j==0?1.0f:-1.0f)*Math.abs(testCases[i][m]) ); failures+=Tests.test("StrictMath.copySign(double,double)", testCases[i][m],testCases[j][n], - StrictMath.copySign(testCases[i][m], testCases[j][n]), + StrictMath::copySign, (j==0?1.0f:-1.0f)*Math.abs(testCases[i][m]) ); } } @@ -932,7 +931,7 @@ public class IeeeRecommendedTests { failures+=Tests.test("StrictMath.copySign(double,double)", testCases[i][m], NaNs[j], - StrictMath.copySign(testCases[i][m], NaNs[j]), + StrictMath::copySign, Math.abs(testCases[i][m]) ); } } @@ -1384,13 +1383,13 @@ public class IeeeRecommendedTests { int failures=0; failures+=Tests.test("Math.ulp(double)", d, - Math.ulp(d), expected); + Math::ulp, expected); failures+=Tests.test("Math.ulp(double)", minus_d, - Math.ulp(minus_d), expected); + Math::ulp, expected); failures+=Tests.test("StrictMath.ulp(double)", d, - StrictMath.ulp(d), expected); + StrictMath::ulp, expected); failures+=Tests.test("StrictMath.ulp(double)", minus_d, - StrictMath.ulp(minus_d), expected); + StrictMath::ulp, expected); return failures; } @@ -1664,16 +1663,16 @@ public class IeeeRecommendedTests { for(int i = 0; i < testCases.length; i++) { failures+=Tests.test("Math.signum(double)", - testCases[i][0], Math.signum(testCases[i][0]), testCases[i][1]); + testCases[i][0], Math::signum, testCases[i][1]); failures+=Tests.test("StrictMath.signum(double)", - testCases[i][0], StrictMath.signum(testCases[i][0]), testCases[i][1]); + testCases[i][0], StrictMath::signum, testCases[i][1]); } return failures; } - public static void main(String argv[]) { + public static void main(String... argv) { int failures = 0; failures += testFloatGetExponent(); diff --git a/test/jdk/java/lang/Math/Log10Tests.java b/test/jdk/java/lang/Math/Log10Tests.java index 7bc75644f2b..dbdd7c14179 100644 --- a/test/jdk/java/lang/Math/Log10Tests.java +++ b/test/jdk/java/lang/Math/Log10Tests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 4074599 4939441 * @summary Tests for {Math, StrictMath}.log10 - * @author Joseph D. Darcy */ public class Log10Tests { @@ -41,11 +40,8 @@ public class Log10Tests { static int testLog10Case(double input, double expected) { int failures=0; - failures+=Tests.test("Math.log10(double)", input, - Math.log10(input), expected); - - failures+=Tests.test("StrictMath.log10(double)", input, - StrictMath.log10(input), expected); + failures+=Tests.test("Math.log10", input, Math::log10, expected); + failures+=Tests.test("StrictMath.log10", input, StrictMath::log10, expected); return failures; } @@ -121,8 +117,6 @@ public class Log10Tests { "log(input)/log(10): log10(input) = " + result + "\tlog(input)/log(10) = " + expected); } - - } } } @@ -205,7 +199,7 @@ public class Log10Tests { return failures; } - public static void main(String argv[]) { + public static void main(String... argv) { int failures = 0; failures += testLog10(); @@ -216,5 +210,4 @@ public class Log10Tests { throw new RuntimeException(); } } - } diff --git a/test/jdk/java/lang/Math/Log1pTests.java b/test/jdk/java/lang/Math/Log1pTests.java index 021a651ed18..2fa7ddec442 100644 --- a/test/jdk/java/lang/Math/Log1pTests.java +++ b/test/jdk/java/lang/Math/Log1pTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,6 @@ * @run main Log1pTests * @bug 4851638 4939441 8078672 * @summary Tests for {Math, StrictMath}.log1p (use -Dseed=X to set PRNG seed) - * @author Joseph D. Darcy * @key randomness */ @@ -167,9 +166,7 @@ public class Log1pTests { pcNeighborsStrictLog1p[j+1] ); } - } - } } @@ -185,16 +182,12 @@ public class Log1pTests { double expected, double ulps) { int failures = 0; - failures += Tests.testUlpDiff("Math.lop1p(double", - input, Math.log1p(input), - expected, ulps); - failures += Tests.testUlpDiff("StrictMath.log1p(double", - input, StrictMath.log1p(input), - expected, ulps); + failures += Tests.testUlpDiff("Math.lop1p", input, Math::log1p, expected, ulps); + failures += Tests.testUlpDiff("StrictMath.log1p", input, StrictMath::log1p, expected, ulps); return failures; } - public static void main(String argv[]) { + public static void main(String... argv) { int failures = 0; failures += testLog1p(); diff --git a/test/jdk/java/lang/Math/PowTests.java b/test/jdk/java/lang/Math/PowTests.java index 88221c5415a..8f8ea098bda 100644 --- a/test/jdk/java/lang/Math/PowTests.java +++ b/test/jdk/java/lang/Math/PowTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 4984407 5033578 8134795 * @summary Tests for {Math, StrictMath}.pow - * @author Joseph D. Darcy */ public class PowTests { @@ -35,35 +34,29 @@ public class PowTests { static int testPowCase(double input1, double input2, double expected) { int failures = 0; - failures += Tests.test("StrictMath.pow(double, double)", input1, input2, - StrictMath.pow(input1, input2), expected); - failures += Tests.test("Math.pow(double, double)", input1, input2, - Math.pow(input1, input2), expected); + failures += Tests.test("StrictMath.pow", input1, input2, StrictMath::pow, expected); + failures += Tests.test("Math.pow", input1, input2, Math::pow, expected); return failures; } - static int testStrictPowCase(double input1, double input2, double expected) { int failures = 0; - failures += Tests.test("StrictMath.pow(double, double)", input1, input2, - StrictMath.pow(input1, input2), expected); + failures += Tests.test("StrictMath.pow", input1, input2, + StrictMath::pow, expected); return failures; } static int testNonstrictPowCase(double input1, double input2, double expected) { int failures = 0; - failures += Tests.test("Math.pow(double, double)", input1, input2, - Math.pow(input1, input2), expected); + failures += Tests.test("Math.pow", input1, input2, + Math::pow, expected); return failures; } static int testStrictVsNonstrictPowCase(double input1, double input2) { - double smResult = StrictMath.pow(input1, input2); - double mResult = Math.pow(input1, input2); return Tests.testUlpDiff( "StrictMath.pow(double, double) vs Math.pow(double, double)", - input1, input2, mResult, smResult, 2.0 - ); + input1, input2, Math::pow, StrictMath.pow(input1, input2), 2.0); } /* @@ -313,7 +306,7 @@ public class PowTests { } } - public static void main(String [] argv) { + public static void main(String... argv) { int failures = 0; failures += testPow(); diff --git a/test/jdk/java/lang/Math/Rint.java b/test/jdk/java/lang/Math/Rint.java index 53e4d26b131..a9c6952b90b 100644 --- a/test/jdk/java/lang/Math/Rint.java +++ b/test/jdk/java/lang/Math/Rint.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,17 +32,14 @@ public class Rint { static int testRintCase(double input, double expected) { int failures = 0; double result; - failures += Tests.test("Math.rint", input, Math.rint(input), expected); - failures += Tests.test("Math.rint", -input, Math.rint(-input), -expected); - failures += Tests.test("StrictMath.rint", - input, StrictMath.rint(input), expected); - failures += Tests.test("StrictMath.rint", -input, - StrictMath.rint(-input), -expected); + failures += Tests.test("Math.rint", input, Math::rint, expected); + failures += Tests.test("Math.rint", -input, Math::rint, -expected); + failures += Tests.test("StrictMath.rint", input, StrictMath::rint, expected); + failures += Tests.test("StrictMath.rint", -input, StrictMath::rint, -expected); return failures; } - - public static void main(String args[]) { + public static void main(String... args) { int failures = 0; double twoToThe52 = Math.scalb(1.0, 52); // 2^52 @@ -97,7 +94,6 @@ public class Rint { }; - for(int i = 0; i < testCases.length; i++) { failures += testRintCase(testCases[i][0], testCases[i][1]); } diff --git a/test/jdk/java/lang/Math/RoundTests.java b/test/jdk/java/lang/Math/RoundTests.java index cae190f9770..0a51b426386 100644 --- a/test/jdk/java/lang/Math/RoundTests.java +++ b/test/jdk/java/lang/Math/RoundTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2022, 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 @@ -64,8 +64,8 @@ public class RoundTests { private static int testNearHalfCases(double input, double expected) { int failures = 0; - failures += Tests.test("Math.round", input, Math.round(input), expected); - failures += Tests.test("StrictMath.round", input, StrictMath.round(input), expected); + failures += Tests.test("Math.round", input, Math::round, expected); + failures += Tests.test("StrictMath.round", input, StrictMath::round, expected); return failures; } @@ -145,20 +145,14 @@ public class RoundTests { failures += Tests.test("Math.round", -Float.MIN_VALUE, Math.round(-Float.MIN_VALUE), 0.0F); - failures += Tests.test("Math.round", Double.NaN, Math.round(Double.NaN), 0.0); - failures += Tests.test("Math.round", Double.POSITIVE_INFINITY, - Math.round(Double.POSITIVE_INFINITY), Long.MAX_VALUE); - failures += Tests.test("Math.round", Double.NEGATIVE_INFINITY, - Math.round(Double.NEGATIVE_INFINITY), Long.MIN_VALUE); - failures += Tests.test("Math.round", -(double)Long.MIN_VALUE, - Math.round(-(double)Long.MIN_VALUE), Long.MAX_VALUE); - failures += Tests.test("Math.round", (double) Long.MIN_VALUE, - Math.round((double) Long.MIN_VALUE), Long.MIN_VALUE); - failures += Tests.test("Math.round", 0, Math.round(0), 0.0); - failures += Tests.test("Math.round", Double.MIN_VALUE, - Math.round(Double.MIN_VALUE), 0.0); - failures += Tests.test("Math.round", -Double.MIN_VALUE, - Math.round(-Double.MIN_VALUE), 0.0); + failures += Tests.test("Math.round", Double.NaN, Math::round, 0.0); + failures += Tests.test("Math.round", Double.POSITIVE_INFINITY, Math::round, Long.MAX_VALUE); + failures += Tests.test("Math.round", Double.NEGATIVE_INFINITY, Math::round, Long.MIN_VALUE); + failures += Tests.test("Math.round", -(double)Long.MIN_VALUE, Math::round, Long.MAX_VALUE); + failures += Tests.test("Math.round", (double) Long.MIN_VALUE, Math::round, Long.MIN_VALUE); + failures += Tests.test("Math.round", 0, Math::round, 0.0); + failures += Tests.test("Math.round", Double.MIN_VALUE, Math::round, 0.0); + failures += Tests.test("Math.round", -Double.MIN_VALUE, Math::round, 0.0); return failures; } diff --git a/test/jdk/java/lang/Math/SinCosCornerCasesTests.java b/test/jdk/java/lang/Math/SinCosCornerCasesTests.java index e144857443f..225cdaebf0e 100644 --- a/test/jdk/java/lang/Math/SinCosCornerCasesTests.java +++ b/test/jdk/java/lang/Math/SinCosCornerCasesTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,6 @@ * @build Tests * @build SinCosCornerCasesTests * @run main SinCosCornerCasesTests - * @author Vivek Deshpande */ public class SinCosCornerCasesTests { @@ -1502,7 +1501,7 @@ public class SinCosCornerCasesTests { private static int testSinCase(double input, double bound1, double bound2) { int failures = 0; - failures += Tests.testBounds("Math.sin", input, Math.sin(input), bound1, bound2); + failures += Tests.testBounds("Math.sin", input, Math::sin, bound1, bound2); return failures; } @@ -2921,7 +2920,7 @@ public class SinCosCornerCasesTests { private static int testCosCase(double input, double bound1, double bound2) { int failures = 0; - failures += Tests.testBounds("Math.cos", input, Math.cos(input), bound1, bound2); + failures += Tests.testBounds("Math.cos", input, Math::cos, bound1, bound2); return failures; } } diff --git a/test/jdk/java/lang/Math/TanTests.java b/test/jdk/java/lang/Math/TanTests.java index f4ad1872238..04ed7d47ed1 100644 --- a/test/jdk/java/lang/Math/TanTests.java +++ b/test/jdk/java/lang/Math/TanTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 5033578 * @summary Tests for {Math, StrictMath}.tan - * @author Joseph D. Darcy */ public class TanTests { @@ -33,10 +32,8 @@ public class TanTests { static int testTanCase(double input, double expected, double ulps) { int failures = 0; - failures += Tests.testUlpDiff("StrictMath.tan(double, double)", input, - StrictMath.tan(input), expected, ulps); - failures += Tests.testUlpDiff("Math.tan(double, double)", input, - Math.tan(input), expected, ulps); + failures += Tests.testUlpDiff("StrictMath.tan", input, StrictMath::tan, expected, ulps); + failures += Tests.testUlpDiff("Math.tan", input, Math::tan, expected, ulps); return failures; } @@ -173,7 +170,7 @@ public class TanTests { return failures; } - public static void main(String [] argv) { + public static void main(String... argv) { int failures = 0; failures += testTan(); diff --git a/test/jdk/java/lang/Math/Tests.java b/test/jdk/java/lang/Math/Tests.java index 98821142fc9..f1de6319a9e 100644 --- a/test/jdk/java/lang/Math/Tests.java +++ b/test/jdk/java/lang/Math/Tests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,6 +21,10 @@ * questions. */ +import java.util.function.DoubleBinaryOperator; +import java.util.function.DoubleUnaryOperator; +import java.util.function.DoubleToIntFunction; + /* * Shared static test methods for numerical tests. Sharing these * helper test methods avoids repeated functions in the various test @@ -235,9 +239,9 @@ public class Tests { "\texpected " + expected + "\n" + "\tgot " + result + ")."); return 1; - } - else + } else { return 0; + } } public static int test(String testName, double input, @@ -248,9 +252,9 @@ public class Tests { "\texpected " + expected + "\n" + "\tgot " + result + ")."); return 1; - } - else + } else { return 0; + } } public static int test(String testName, float input1, float input2, @@ -291,6 +295,13 @@ public class Tests { return 0; } + public static int test(String testName, + double input, + DoubleToIntFunction func, + int expected) { + return test(testName, input, func.applyAsInt(input), expected); + } + public static int test(String testName, double input, int result, int expected) { if (expected != result) { @@ -299,9 +310,9 @@ public class Tests { "\texpected " + expected + "\n" + "\tgot " + result + ")."); return 1; - } - else + } else { return 0; + } } public static int test(String testName, float input, @@ -312,11 +323,17 @@ public class Tests { "\texpected " + expected + "\t(" + toHexString(expected) + ")\n" + "\tgot " + result + "\t(" + toHexString(result) + ")."); return 1; - } - else + } else { return 0; + } } + public static int test(String testName, + double input, + DoubleUnaryOperator func, + double expected) { + return test(testName, input, func.applyAsDouble(input), expected); + } public static int test(String testName, double input, double result, double expected) { @@ -326,9 +343,9 @@ public class Tests { "\texpected " + expected + "\t(" + toHexString(expected) + ")\n" + "\tgot " + result + "\t(" + toHexString(result) + ")."); return 1; - } - else + } else { return 0; + } } public static int test(String testName, @@ -341,9 +358,16 @@ public class Tests { "\texpected " + expected + "\t(" + toHexString(expected) + ")\n" + "\tgot " + result + "\t(" + toHexString(result) + ")."); return 1; - } - else + } else { return 0; + } + } + + public static int test(String testName, + double input1, double input2, + DoubleBinaryOperator func, + double expected) { + return test(testName, input1, input2, func.applyAsDouble(input1, input2), expected); } public static int test(String testName, @@ -356,9 +380,9 @@ public class Tests { "\texpected " + expected + "\t(" + toHexString(expected) + ")\n" + "\tgot " + result + "\t(" + toHexString(result) + ")."); return 1; - } - else + } else { return 0; + } } public static int test(String testName, @@ -371,9 +395,9 @@ public class Tests { "\texpected " + expected + "\t(" + toHexString(expected) + ")\n" + "\tgot " + result + "\t(" + toHexString(result) + ")."); return 1; - } - else + } else { return 0; + } } public static int test(String testName, @@ -386,9 +410,9 @@ public class Tests { "\texpected " + expected + "\t(" + toHexString(expected) + ")\n" + "\tgot " + result + "\t(" + toHexString(result) + ")."); return 1; - } - else + } else { return 0; + } } public static int test(String testName, @@ -402,9 +426,21 @@ public class Tests { "\texpected " + expected + "\t(" + toHexString(expected) + ")\n" + "\tgot " + result + "\t(" + toHexString(result) + ")."); return 1; - } - else + } else { return 0; + } + } + + @FunctionalInterface + public interface DoubleTernaryOperator { + double applyAsDouble(double input1, double input2, double input3); + } + + public static int test(String testName, + double input1, double input2, double input3, + DoubleTernaryOperator func, double expected) { + return test(testName, input1, input2, input3, func.applyAsDouble(input1, input2, input3), expected); + } public static int test(String testName, @@ -418,9 +454,9 @@ public class Tests { "\texpected " + expected + "\t(" + toHexString(expected) + ")\n" + "\tgot " + result + "\t(" + toHexString(result) + ")."); return 1; - } - else + } else { return 0; + } } static int testUlpCore(double result, double expected, double ulps) { @@ -442,14 +478,19 @@ public class Tests { // fail if greater than or unordered !(Math.abs( difference/Math.ulp(expected) ) <= Math.abs(ulps)) ) { return 1; - } - else + } else { return 0; + } } } } // One input argument. + public static int testUlpDiff(String testName, double input, + DoubleUnaryOperator func, double expected, double ulps) { + return testUlpDiff(testName, input, func.applyAsDouble(input), expected, ulps); + } + public static int testUlpDiff(String testName, double input, double result, double expected, double ulps) { int code = testUlpCore(result, expected, ulps); @@ -464,6 +505,11 @@ public class Tests { } // Two input arguments. + public static int testUlpDiff(String testName, double input1, double input2, + DoubleBinaryOperator func, double expected, double ulps) { + return testUlpDiff(testName, input1, input2, func.applyAsDouble(input1, input2), expected, ulps); + } + public static int testUlpDiff(String testName, double input1, double input2, double result, double expected, double ulps) { int code = testUlpCore(result, expected, ulps); @@ -481,6 +527,14 @@ public class Tests { // For a successful test, the result must be within the ulp bound of // expected AND the result must have absolute value less than or // equal to absBound. + public static int testUlpDiffWithAbsBound(String testName, double input, + DoubleUnaryOperator func, double expected, + double ulps, double absBound) { + return testUlpDiffWithAbsBound(testName, input, + func.applyAsDouble(input), expected, + ulps, absBound); + } + public static int testUlpDiffWithAbsBound(String testName, double input, double result, double expected, double ulps, double absBound) { @@ -506,6 +560,14 @@ public class Tests { // For a successful test, the result must be within the ulp bound of // expected AND the result must have absolute value greater than // or equal to the lowerBound. + public static int testUlpDiffWithLowerBound(String testName, double input, + DoubleUnaryOperator func, double expected, + double ulps, double lowerBound) { + return testUlpDiffWithLowerBound(testName, input, + func.applyAsDouble(input), expected, + ulps, lowerBound); + } + public static int testUlpDiffWithLowerBound(String testName, double input, double result, double expected, double ulps, double lowerBound) { @@ -513,8 +575,9 @@ public class Tests { if (!(result >= lowerBound) && !Double.isNaN(expected)) { code = 1; - } else + } else { code = testUlpCore(result, expected, ulps); + } if (code == 1) { System.err.println("Failure for " + testName + @@ -528,6 +591,11 @@ public class Tests { return code; } + public static int testTolerance(String testName, double input, + DoubleUnaryOperator func, double expected, double tolerance) { + return testTolerance(testName, input, func.applyAsDouble(input), expected, tolerance); + + } public static int testTolerance(String testName, double input, double result, double expected, double tolerance) { if (Double.compare(expected, result ) != 0) { @@ -544,13 +612,18 @@ public class Tests { return 1; } return 0; - } - else + } else { return 0; + } } // For a successful test, the result must be within the upper and // lower bounds. + public static int testBounds(String testName, double input, DoubleUnaryOperator func, + double bound1, double bound2) { + return testBounds(testName, input, func.applyAsDouble(input), bound1, bound2); + } + public static int testBounds(String testName, double input, double result, double bound1, double bound2) { if ((result >= bound1 && result <= bound2) || diff --git a/test/jdk/java/lang/Math/WorstCaseTests.java b/test/jdk/java/lang/Math/WorstCaseTests.java index be98d977aab..2cffa8fabfc 100644 --- a/test/jdk/java/lang/Math/WorstCaseTests.java +++ b/test/jdk/java/lang/Math/WorstCaseTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,6 @@ * @build WorstCaseTests * @run main WorstCaseTests * @run main/othervm -Xcomp WorstCaseTests - * @author Joseph D. Darcy */ /** @@ -126,8 +125,8 @@ public class WorstCaseTests { private static int testExpCase(double input, double expected) { int failures = 0; double out = Tests.nextOut(expected); - failures += Tests.testBounds("Math.exp", input, Math.exp(input), expected, out); - failures += Tests.testBounds("StrictMath.exp", input, StrictMath.exp(input), expected, out); + failures += Tests.testBounds("Math.exp", input, Math::exp, expected, out); + failures += Tests.testBounds("StrictMath.exp", input, StrictMath::exp, expected, out); return failures; } @@ -158,8 +157,8 @@ public class WorstCaseTests { private static int testLogCase(double input, double expected) { int failures = 0; double out = Tests.nextOut(expected); - failures += Tests.testBounds("Math.log", input, Math.log(input), expected, out); - failures += Tests.testBounds("StrictMath.log", input, StrictMath.log(input), expected, out); + failures += Tests.testBounds("Math.log", input, Math::log, expected, out); + failures += Tests.testBounds("StrictMath.log", input, StrictMath::log, expected, out); return failures; } @@ -191,8 +190,8 @@ public class WorstCaseTests { private static int testSinCase(double input, double expected) { int failures = 0; double out = Tests.nextOut(expected); - failures += Tests.testBounds("Math.sin", input, Math.sin(input), expected, out); - failures += Tests.testBounds("StrictMath.sin", input, StrictMath.sin(input), expected, out); + failures += Tests.testBounds("Math.sin", input, Math::sin, expected, out); + failures += Tests.testBounds("StrictMath.sin", input, StrictMath::sin, expected, out); return failures; } @@ -223,8 +222,8 @@ public class WorstCaseTests { private static int testAsinCase(double input, double expected) { int failures = 0; double out = Tests.nextOut(expected); - failures += Tests.testBounds("Math.asin", input, Math.asin(input), expected, out); - failures += Tests.testBounds("StrictMath.asin", input, StrictMath.asin(input), expected, out); + failures += Tests.testBounds("Math.asin", input, Math::asin, expected, out); + failures += Tests.testBounds("StrictMath.asin", input, StrictMath::asin, expected, out); return failures; } @@ -256,8 +255,8 @@ public class WorstCaseTests { private static int testCosCase(double input, double expected) { int failures = 0; double out = Tests.nextOut(expected); - failures += Tests.testBounds("Math.cos", input, Math.cos(input), expected, out); - failures += Tests.testBounds("StrictMath.cos", input, StrictMath.cos(input), expected, out); + failures += Tests.testBounds("Math.cos", input, Math::cos, expected, out); + failures += Tests.testBounds("StrictMath.cos", input, StrictMath::cos, expected, out); return failures; } @@ -280,8 +279,8 @@ public class WorstCaseTests { private static int testAcosCase(double input, double expected) { int failures = 0; double out = Tests.nextOut(expected); - failures += Tests.testBounds("Math.acos", input, Math.acos(input), expected, out); - failures += Tests.testBounds("StrictMath.acos", input, StrictMath.acos(input), expected, out); + failures += Tests.testBounds("Math.acos", input, Math::acos, expected, out); + failures += Tests.testBounds("StrictMath.acos", input, StrictMath::acos, expected, out); return failures; } @@ -309,8 +308,8 @@ public class WorstCaseTests { private static int testTanCase(double input, double expected) { int failures = 0; double out = Tests.nextOut(expected); - failures += Tests.testBounds("Math.tan", input, Math.tan(input), expected, out); - failures += Tests.testBounds("StrictMath.tan", input, StrictMath.tan(input), expected, out); + failures += Tests.testBounds("Math.tan", input, Math::tan, expected, out); + failures += Tests.testBounds("StrictMath.tan", input, StrictMath::tan, expected, out); return failures; } @@ -341,8 +340,8 @@ public class WorstCaseTests { private static int testAtanCase(double input, double expected) { int failures = 0; double out = Tests.nextOut(expected); - failures += Tests.testBounds("Math.atan", input, Math.atan(input), expected, out); - failures += Tests.testBounds("StrictMath.atan", input, StrictMath.atan(input), expected, out); + failures += Tests.testBounds("Math.atan", input, Math::atan, expected, out); + failures += Tests.testBounds("StrictMath.atan", input, StrictMath::atan, expected, out); return failures; } @@ -367,8 +366,8 @@ public class WorstCaseTests { private static int testPow2Case(double input, double expected) { int failures = 0; double out = Tests.nextOut(expected); - failures += Tests.testBounds("Math.pow2", input, Math.pow(2, input), expected, out); - failures += Tests.testBounds("StrictMath.pow2", input, StrictMath.pow(2, input), expected, out); + failures += Tests.testBounds("Math.pow2", input, d -> Math.pow(2, d), expected, out); + failures += Tests.testBounds("StrictMath.pow2", input, d -> StrictMath.pow(2, d), expected, out); return failures; } @@ -400,8 +399,8 @@ public class WorstCaseTests { private static int testSinhCase(double input, double expected) { int failures = 0; double out = Tests.nextOut(expected); - failures += Tests.testBounds("Math.sinh", input, Math.sinh(input), expected, out); - failures += Tests.testBounds("StrictMath.sinh", input, StrictMath.sinh(input), expected, out); + failures += Tests.testBounds("Math.sinh", input, Math::sinh, expected, out); + failures += Tests.testBounds("StrictMath.sinh", input, StrictMath::sinh, expected, out); return failures; } @@ -428,8 +427,8 @@ public class WorstCaseTests { private static int testCoshCase(double input, double expected) { int failures = 0; double out = Tests.nextOut(expected); - failures += Tests.testBounds("Math.cosh", input, Math.cosh(input), expected, out); - failures += Tests.testBounds("StrictMath.cosh", input, StrictMath.cosh(input), expected, out); + failures += Tests.testBounds("Math.cosh", input, Math::cosh, expected, out); + failures += Tests.testBounds("StrictMath.cosh", input, StrictMath::cosh, expected, out); return failures; } } diff --git a/test/jdk/java/lang/StrictMath/CubeRootTests.java b/test/jdk/java/lang/StrictMath/CubeRootTests.java index f4a3978075d..0423f1ff087 100644 --- a/test/jdk/java/lang/StrictMath/CubeRootTests.java +++ b/test/jdk/java/lang/StrictMath/CubeRootTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,6 @@ * @build CubeRootTests * @run main CubeRootTests * @summary Tests specifically for StrictMath.cbrt - * @author Joseph D. Darcy */ import jdk.test.lib.RandomFactory; @@ -71,9 +70,9 @@ public class CubeRootTests { double minus_expected = -expected; failures+=Tests.test("StrictMath.cbrt(double)", input, - StrictMath.cbrt(input), expected); + StrictMath::cbrt, expected); failures+=Tests.test("StrictMath.cbrt(double)", minus_input, - StrictMath.cbrt(minus_input), minus_expected); + StrictMath::cbrt, minus_expected); return failures; } diff --git a/test/jdk/java/lang/StrictMath/Expm1Tests.java b/test/jdk/java/lang/StrictMath/Expm1Tests.java index 368d1025993..e7d9696535d 100644 --- a/test/jdk/java/lang/StrictMath/Expm1Tests.java +++ b/test/jdk/java/lang/StrictMath/Expm1Tests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, 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,8 @@ * @test * @bug 4851638 * @summary Tests for StrictMath.expm1 - * @author Joseph D. Darcy + * @compile -Xdiags:verbose Expm1Tests.java + * @run main Expm1Tests */ /** @@ -44,7 +45,7 @@ public class Expm1Tests { static int testExpm1Case(double input, double expected) { return Tests.test("StrictMath.expm1(double)", input, - StrictMath.expm1(input), expected); + StrictMath::expm1, expected); } static int testExpm1() { diff --git a/test/jdk/java/lang/StrictMath/HyperbolicTests.java b/test/jdk/java/lang/StrictMath/HyperbolicTests.java index 37b851dd795..4dfc7596d38 100644 --- a/test/jdk/java/lang/StrictMath/HyperbolicTests.java +++ b/test/jdk/java/lang/StrictMath/HyperbolicTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 4851625 * @summary Tests for StrictMath.{sinh, cosh, tanh} - * @author Joseph D. Darcy */ /** @@ -45,17 +44,17 @@ public class HyperbolicTests { static int testSinhCase(double input, double expected) { return Tests.test("StrictMath.sinh(double)", input, - StrictMath.sinh(input), expected); + StrictMath::sinh, expected); } static int testCoshCase(double input, double expected) { return Tests.test("StrictMath.cosh(double)", input, - StrictMath.cosh(input), expected); + StrictMath::cosh, expected); } static int testTanhCase(double input, double expected) { return Tests.test("StrictMath.tanh(double)", input, - StrictMath.tanh(input), expected); + StrictMath::tanh, expected); } static int testSinh() { diff --git a/test/jdk/java/lang/StrictMath/HypotTests.java b/test/jdk/java/lang/StrictMath/HypotTests.java index 0b1dd41691f..c714dcf1499 100644 --- a/test/jdk/java/lang/StrictMath/HypotTests.java +++ b/test/jdk/java/lang/StrictMath/HypotTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,6 @@ * @build FdlibmTranslit * @build HypotTests * @run main HypotTests - * @author Joseph D. Darcy */ import jdk.test.lib.RandomFactory; @@ -72,28 +71,28 @@ public class HypotTests { static int testHypotCase(double input1, double input2, double expected) { int failures = 0; failures += Tests.test("StrictMath.hypot(double)", input1, input2, - StrictMath.hypot(input1, input2), expected); + StrictMath::hypot, expected); failures += Tests.test("StrictMath.hypot(double)", input2, input1, - StrictMath.hypot(input2, input1), expected); + StrictMath::hypot, expected); failures += Tests.test("StrictMath.hypot(double)", -input1, input2, - StrictMath.hypot(-input1, input2), expected); + StrictMath::hypot, expected); failures += Tests.test("StrictMath.hypot(double)", input2, -input1, - StrictMath.hypot(input2, -input1), expected); + StrictMath::hypot, expected); failures += Tests.test("StrictMath.hypot(double)", input1, -input2, - StrictMath.hypot(input1, -input2), expected); + StrictMath::hypot, expected); failures += Tests.test("StrictMath.hypot(double)", -input2, input1, - StrictMath.hypot(-input2, input1), expected); + StrictMath::hypot, expected); failures += Tests.test("StrictMath.hypot(double)", -input1, -input2, - StrictMath.hypot(-input1, -input2), expected); + StrictMath::hypot, expected); failures += Tests.test("StrictMath.hypot(double)", -input2, -input1, - StrictMath.hypot(-input2, -input1), expected); + StrictMath::hypot, expected); return failures; } diff --git a/test/jdk/java/lang/StrictMath/Log10Tests.java b/test/jdk/java/lang/StrictMath/Log10Tests.java index af07eac7e66..eed6e8a5106 100644 --- a/test/jdk/java/lang/StrictMath/Log10Tests.java +++ b/test/jdk/java/lang/StrictMath/Log10Tests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 4074599 * @summary Tests for StrictMath.log10 - * @author Joseph D. Darcy */ @@ -45,7 +44,7 @@ public class Log10Tests { static int testLog10Case(double input, double expected) { return Tests.test("StrictMath.log10(double)", input, - StrictMath.log10(input), expected); + StrictMath::log10, expected); } static int testLog10() { diff --git a/test/jdk/java/lang/StrictMath/Log1pTests.java b/test/jdk/java/lang/StrictMath/Log1pTests.java index 91b0835222c..9cd03d3306a 100644 --- a/test/jdk/java/lang/StrictMath/Log1pTests.java +++ b/test/jdk/java/lang/StrictMath/Log1pTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 4851638 * @summary Tests for StrictMath.log1p - * @author Joseph D. Darcy */ /** @@ -44,7 +43,7 @@ public class Log1pTests { static int testLog1pCase(double input, double expected) { return Tests.test("StrictMath.log1p(double)", input, - StrictMath.log1p(input), expected); + StrictMath::log1p, expected); } static int testLog1p() { diff --git a/test/jdk/java/lang/StrictMath/PowTests.java b/test/jdk/java/lang/StrictMath/PowTests.java index 338cf42d54c..2936dfdf247 100644 --- a/test/jdk/java/lang/StrictMath/PowTests.java +++ b/test/jdk/java/lang/StrictMath/PowTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 8136874 * @summary Tests for StrictMath.pow - * @author Joseph D. Darcy */ /** @@ -295,7 +294,7 @@ public class PowTests { private static int testPowCase(double input1, double input2, double expected) { int failures = 0; failures += Tests.test("StrictMath.pow(double)", input1, input2, - StrictMath.pow(input1, input2), expected); + StrictMath::pow, expected); return failures; } } diff --git a/test/jdk/java/lang/StrictMath/Tests.java b/test/jdk/java/lang/StrictMath/Tests.java index 0513cb70d1e..a675b2e9617 100644 --- a/test/jdk/java/lang/StrictMath/Tests.java +++ b/test/jdk/java/lang/StrictMath/Tests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,33 +21,48 @@ * questions. */ +import java.util.function.DoubleBinaryOperator; +import java.util.function.DoubleUnaryOperator; + /* - * - * * Shared static test method for StrictMath tests. */ - public class Tests { private Tests(){} - static int test(String testName, - double input, - double result, - double expected) { + public static int test(String testName, + double input, + DoubleUnaryOperator func, + double expected) { + return test(testName, input, func.applyAsDouble(input), expected); + } + + public static int test(String testName, + double input, + double result, + double expected) { if (Double.compare(expected, result ) != 0) { System.err.println("Failure for " + testName + ":\n" + "\tFor input " + input + "\t(" + Double.toHexString(input) + ")\n" + "\texpected " + expected + "\t(" + Double.toHexString(expected) + ")\n" + "\tgot " + result + "\t(" + Double.toHexString(result) + ")."); return 1; - } - else + } else { return 0; + } + } + + public static int test(String testName, + double input1, + double input2, + DoubleBinaryOperator func, + double expected) { + return test(testName, input1, input2, func.applyAsDouble(input1, input2), expected); } - static int test(String testName, double input1, double input2, - double result, double expected) { + public static int test(String testName, double input1, double input2, + double result, double expected) { if (Double.compare(expected, result ) != 0) { System.err.println("Failure for " + testName + ":\n" + "\tFor input " + input1 + "\t(" + Double.toHexString(input1) + "), " + @@ -55,9 +70,9 @@ public class Tests { "\texpected " + expected + "\t(" + Double.toHexString(expected) + ")\n" + "\tgot " + result + "\t(" + Double.toHexString(result) + ")."); return 1; - } - else + } else { return 0; + } } /** -- GitLab From 78574057a4758fc3da5f39af77df09dc2232a9a1 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Fri, 28 Jan 2022 00:44:13 +0000 Subject: [PATCH 318/564] 8280744: Allow SuppressWarnings to be used in all declaration contexts Reviewed-by: iris --- .../classes/java/lang/SuppressWarnings.java | 63 +++++++++++++------ 1 file changed, 44 insertions(+), 19 deletions(-) diff --git a/src/java.base/share/classes/java/lang/SuppressWarnings.java b/src/java.base/share/classes/java/lang/SuppressWarnings.java index 09ab6c4724b..fd115fb8bef 100644 --- a/src/java.base/share/classes/java/lang/SuppressWarnings.java +++ b/src/java.base/share/classes/java/lang/SuppressWarnings.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,21 +29,52 @@ import java.lang.annotation.*; import static java.lang.annotation.ElementType.*; /** - * Indicates that the named compiler warnings should be suppressed in the - * annotated element (and in all program elements contained in the annotated - * element). Note that the set of warnings suppressed in a given element is - * a superset of the warnings suppressed in all containing elements. For - * example, if you annotate a class to suppress one warning and annotate a - * method to suppress another, both warnings will be suppressed in the method. - * However, note that if a warning is suppressed in a {@code - * module-info} file, the suppression applies to elements within the - * file and not to types contained within the module. + * Indicates the warnings to be suppressed at compile time in the + * annotated element, and in all elements contained in the annotated + * element. * - *

    As a matter of style, programmers should always use this annotation - * on the most deeply nested element where it is effective. If you want to + *

    The {@code SuppressWarnings} annotation interface is applicable + * in all declaration contexts, so an {@code @SuppressWarnings} + * annotation can be used on any element. As a matter of style, + * programmers should always use this annotation on the most deeply + * nested element where it is effective. For example, if you want to * suppress a warning in a particular method, you should annotate that * method rather than its class. * + *

    The set of warnings suppressed in a given element is a union of + * the warnings suppressed in all containing elements. For example, + * if you annotate a class to suppress one warning and annotate a + * method in the class to suppress another, both warnings will be + * suppressed in the method. However, note that if a warning is + * suppressed in a {@code module-info} file, the suppression applies + * to elements within the file and not to types contained + * within the module. Likewise, if a warning is suppressed in a + * {@code package-info} file, the suppression applies to elements + * within the file and not to types contained within the + * package. + * + *

    Java compilers must recognize all the kinds of warnings defined + * in the Java Language Specification (JLS section {@jls + * 9.6.4.5}) which include: + * + *

      + *
    • Unchecked warnings, specified by the string {@code "unchecked"}. + *
    • Deprecation warnings, specified by the string {@code "deprecation"}. + *
    • Removal warnings, specified by the string {@code "removal"}. + *
    • Preview warnings, specified by the string {@code "preview"}. + *
    + * + * Whether or not a Java compiler recognizes other strings is a + * quality of implementation concern. Compiler vendors should + * document the additional warning names they support. Vendors are + * encouraged to cooperate to ensure that the same names work across + * multiple compilers. + * + * @implNote + * In addition to the mandated suppression strings, the {@code javac} + * reference implementation recognizes compilation-related warning + * names documented in its {@code --help-lint} output. + * * @author Josh Bloch * @since 1.5 * @jls 4.8 Raw Types @@ -52,7 +83,7 @@ import static java.lang.annotation.ElementType.*; * @jls 5.5 Casting Contexts * @jls 9.6.4.5 @SuppressWarnings */ -@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, MODULE}) +// Implicitly target all declaration contexts by omitting a @Target annotation @Retention(RetentionPolicy.SOURCE) public @interface SuppressWarnings { /** @@ -63,12 +94,6 @@ public @interface SuppressWarnings { * ignore any warning names they do not recognize. They are, however, * free to emit a warning if an annotation contains an unrecognized * warning name. - * - *

    The string {@code "unchecked"} is used to suppress - * unchecked warnings. Compiler vendors should document the - * additional warning names they support in conjunction with this - * annotation type. They are encouraged to cooperate to ensure - * that the same names work across multiple compilers. * @return the set of warnings to be suppressed */ String[] value(); -- GitLab From 094db1a3eeb3709c8218d8d26f13699024ec2943 Mon Sep 17 00:00:00 2001 From: Denghui Dong Date: Fri, 28 Jan 2022 00:49:17 +0000 Subject: [PATCH 319/564] 8277948: AArch64: Print the correct native stack if -XX:+PreserveFramePointer when crash Reviewed-by: aph, adinn --- src/hotspot/cpu/aarch64/frame_aarch64.cpp | 20 ++++++++++++++----- src/hotspot/cpu/aarch64/frame_aarch64.hpp | 9 ++++++++- .../cpu/aarch64/frame_aarch64.inline.hpp | 6 +++++- .../linux_aarch64/thread_linux_aarch64.cpp | 6 ++++-- 4 files changed, 32 insertions(+), 9 deletions(-) diff --git a/src/hotspot/cpu/aarch64/frame_aarch64.cpp b/src/hotspot/cpu/aarch64/frame_aarch64.cpp index 35cc1ee1f84..cb59e8b12af 100644 --- a/src/hotspot/cpu/aarch64/frame_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/frame_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -358,6 +358,7 @@ frame frame::sender_for_entry_frame(RegisterMap* map) const { assert(map->include_argument_oops(), "should be set by clear"); vmassert(jfa->last_Java_pc() != NULL, "not walkable"); frame fr(jfa->last_Java_sp(), jfa->last_Java_fp(), jfa->last_Java_pc()); + fr.set_sp_is_trusted(); return fr; } @@ -463,12 +464,21 @@ frame frame::sender_for_interpreter_frame(RegisterMap* map) const { //------------------------------------------------------------------------------ // frame::sender_for_compiled_frame frame frame::sender_for_compiled_frame(RegisterMap* map) const { - // we cannot rely upon the last fp having been saved to the thread - // in C2 code but it will have been pushed onto the stack. so we - // have to find it relative to the unextended sp + // When the sp of a compiled frame is correct, we can get the correct sender sp + // by unextended sp + frame size. + // For the following two scenarios, the sp of a compiled frame is correct: + // a) This compiled frame is built from the anchor. + // b) This compiled frame is built from a callee frame, and the callee frame can + // calculate its sp correctly. + // + // For b), if the callee frame is a native code frame (such as leaf call), the sp of + // the compiled frame cannot be calculated correctly. There is currently no suitable + // solution to solve this problem perfectly. But when PreserveFramePointer is enabled, + // we can get the correct sender sp by fp + 2 (that is sender_sp()). assert(_cb->frame_size() >= 0, "must have non-zero frame size"); - intptr_t* l_sender_sp = unextended_sp() + _cb->frame_size(); + intptr_t* l_sender_sp = (!PreserveFramePointer || _sp_is_trusted) ? unextended_sp() + _cb->frame_size() + : sender_sp(); intptr_t* unextended_sp = l_sender_sp; // the return_address is always the word on the stack diff --git a/src/hotspot/cpu/aarch64/frame_aarch64.hpp b/src/hotspot/cpu/aarch64/frame_aarch64.hpp index 716c0ff9f1a..95f470befa0 100644 --- a/src/hotspot/cpu/aarch64/frame_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/frame_aarch64.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -124,6 +124,11 @@ intptr_t* _unextended_sp; void adjust_unextended_sp(); + // true means _sp value is correct and we can use it to get the sender's sp + // of the compiled frame, otherwise, _sp value may be invalid and we can use + // _fp to get the sender's sp if PreserveFramePointer is enabled. + bool _sp_is_trusted; + intptr_t* ptr_at_addr(int offset) const { return (intptr_t*) addr_at(offset); } @@ -165,4 +170,6 @@ // returns the sending frame, without applying any barriers frame sender_raw(RegisterMap* map) const; + void set_sp_is_trusted() { _sp_is_trusted = true; } + #endif // CPU_AARCH64_FRAME_AARCH64_HPP diff --git a/src/hotspot/cpu/aarch64/frame_aarch64.inline.hpp b/src/hotspot/cpu/aarch64/frame_aarch64.inline.hpp index 5be02aa57e7..b0fe436ca59 100644 --- a/src/hotspot/cpu/aarch64/frame_aarch64.inline.hpp +++ b/src/hotspot/cpu/aarch64/frame_aarch64.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -41,6 +41,7 @@ inline frame::frame() { _fp = NULL; _cb = NULL; _deopt_state = unknown; + _sp_is_trusted = false; } static int spin; @@ -64,6 +65,7 @@ inline void frame::init(intptr_t* sp, intptr_t* fp, address pc) { } else { _deopt_state = not_deoptimized; } + _sp_is_trusted = false; } inline frame::frame(intptr_t* sp, intptr_t* fp, address pc) { @@ -91,6 +93,7 @@ inline frame::frame(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, address } else { _deopt_state = not_deoptimized; } + _sp_is_trusted = false; } inline frame::frame(intptr_t* sp, intptr_t* fp) { @@ -122,6 +125,7 @@ inline frame::frame(intptr_t* sp, intptr_t* fp) { } else { _deopt_state = not_deoptimized; } + _sp_is_trusted = false; } // Accessors diff --git a/src/hotspot/os_cpu/linux_aarch64/thread_linux_aarch64.cpp b/src/hotspot/os_cpu/linux_aarch64/thread_linux_aarch64.cpp index fca22629bc5..f584da5814a 100644 --- a/src/hotspot/os_cpu/linux_aarch64/thread_linux_aarch64.cpp +++ b/src/hotspot/os_cpu/linux_aarch64/thread_linux_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -29,7 +29,9 @@ frame JavaThread::pd_last_frame() { assert(has_last_Java_frame(), "must have last_Java_sp() when suspended"); - return frame(_anchor.last_Java_sp(), _anchor.last_Java_fp(), _anchor.last_Java_pc()); + frame f = frame(_anchor.last_Java_sp(), _anchor.last_Java_fp(), _anchor.last_Java_pc()); + f.set_sp_is_trusted(); + return f; } // For Forte Analyzer AsyncGetCallTrace profiling support - thread is -- GitLab From a1d1e4753b87dfc6ce179c389480dcf2c5a0dc2e Mon Sep 17 00:00:00 2001 From: Ioi Lam Date: Fri, 28 Jan 2022 01:55:16 +0000 Subject: [PATCH 320/564] 8280823: Remove NULL check in DumpTimeClassInfo::is_excluded Reviewed-by: minqi, ccheung --- src/hotspot/share/cds/dumpTimeClassInfo.hpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/hotspot/share/cds/dumpTimeClassInfo.hpp b/src/hotspot/share/cds/dumpTimeClassInfo.hpp index 04b0af221cf..28fe986ff7a 100644 --- a/src/hotspot/share/cds/dumpTimeClassInfo.hpp +++ b/src/hotspot/share/cds/dumpTimeClassInfo.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022, 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 @@ -135,8 +135,7 @@ public: } bool is_excluded() { - // _klass may become NULL due to DynamicArchiveBuilder::set_to_null - return _excluded || _failed_verification || _klass == NULL; + return _excluded || _failed_verification; } // Was this class loaded while JvmtiExport::is_early_phase()==true -- GitLab From 178ac7465360729628521a0d555253b9fb2ad7bf Mon Sep 17 00:00:00 2001 From: Andrey Turbanov Date: Fri, 28 Jan 2022 07:01:21 +0000 Subject: [PATCH 321/564] 8251466: test/java/io/File/GetXSpace.java fails on Windows with mapped network drives. Reviewed-by: bpb --- test/jdk/java/io/File/GetXSpace.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/test/jdk/java/io/File/GetXSpace.java b/test/jdk/java/io/File/GetXSpace.java index eacc7565227..ac80bdf68fd 100644 --- a/test/jdk/java/io/File/GetXSpace.java +++ b/test/jdk/java/io/File/GetXSpace.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2022, 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,7 +34,6 @@ import java.io.BufferedReader; import java.io.File; -import java.io.FilePermission; import java.io.InputStreamReader; import java.io.IOException; import java.nio.file.Files; @@ -108,8 +107,8 @@ public class GetXSpace { Space(String total, String free, String name) { try { - this.total = Long.valueOf(total) * KSIZE; - this.free = Long.valueOf(free) * KSIZE; + this.total = Long.parseLong(total) * KSIZE; + this.free = Long.parseLong(free) * KSIZE; } catch (NumberFormatException x) { throw new RuntimeException("the regex should have caught this", x); } @@ -157,7 +156,7 @@ public class GetXSpace { } al.add(new Space(m.group(2), m.group(3), name));; } - j = m.end() + 1; + j = m.end(); } else { throw new RuntimeException("unrecognized df output format: " + "charAt(" + j + ") = '" @@ -227,7 +226,7 @@ public class GetXSpace { // On Linux, ignore the NSFE if the path is one of the // /run/user/$UID mounts created by pam_systemd(8) as it // might be deleted during the test - if (!Platform.isLinux() || s.name().indexOf("/run/user") == -1) + if (!Platform.isLinux() || !s.name().contains("/run/user")) throw new RuntimeException(nsfe); } catch (IOException e) { throw new RuntimeException(e); -- GitLab From 55f180fb7dfecc859e59c7852d48aeab6c936a5d Mon Sep 17 00:00:00 2001 From: Thomas Stuefe Date: Fri, 28 Jan 2022 08:10:12 +0000 Subject: [PATCH 322/564] 8280004: DCmdArgument::parse_value() should handle NULL input Reviewed-by: dholmes, mbaesken --- src/hotspot/share/services/diagnosticArgument.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/hotspot/share/services/diagnosticArgument.cpp b/src/hotspot/share/services/diagnosticArgument.cpp index f10fe6c4641..3dd75009175 100644 --- a/src/hotspot/share/services/diagnosticArgument.cpp +++ b/src/hotspot/share/services/diagnosticArgument.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ #include "memory/resourceArea.hpp" #include "runtime/thread.hpp" #include "services/diagnosticArgument.hpp" +#include "utilities/globalDefinitions.hpp" StringArrayArgument::StringArrayArgument() { _array = new (ResourceObj::C_HEAP, mtServiceability) GrowableArray(32, mtServiceability); @@ -114,13 +115,12 @@ template <> void DCmdArgument::parse_value(const char* str, || sscanf(str, JLONG_FORMAT "%n", &_value, &scanned) != 1 || (size_t)scanned != len) { - ResourceMark rm; - - char* buf = NEW_RESOURCE_ARRAY(char, len + 1); - strncpy(buf, str, len); - buf[len] = '\0'; + const int maxprint = 64; Exceptions::fthrow(THREAD_AND_LOCATION, vmSymbols::java_lang_IllegalArgumentException(), - "Integer parsing error in command argument '%s'. Could not parse: %s.\n", _name, buf); + "Integer parsing error in command argument '%s'. Could not parse: %.*s%s.\n", _name, + MIN2((int)len, maxprint), + (str == NULL ? "" : str), + (len > maxprint ? "..." : "")); } } -- GitLab From 973dda5ce0747a8ea67ec3a34c2ef2a0b2b6b140 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Fri, 28 Jan 2022 08:11:44 +0000 Subject: [PATCH 323/564] 8280804: Parallel: Remove unused variables in PSPromotionManager::drain_stacks_depth Reviewed-by: tschatzl, mli --- src/hotspot/share/gc/parallel/psPromotionManager.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/hotspot/share/gc/parallel/psPromotionManager.cpp b/src/hotspot/share/gc/parallel/psPromotionManager.cpp index f7308366400..ad63244a299 100644 --- a/src/hotspot/share/gc/parallel/psPromotionManager.cpp +++ b/src/hotspot/share/gc/parallel/psPromotionManager.cpp @@ -244,12 +244,6 @@ void PSPromotionManager::restore_preserved_marks() { void PSPromotionManager::drain_stacks_depth(bool totally_drain) { totally_drain = totally_drain || _totally_drain; -#ifdef ASSERT - ParallelScavengeHeap* heap = ParallelScavengeHeap::heap(); - MutableSpace* to_space = heap->young_gen()->to_space(); - MutableSpace* old_space = heap->old_gen()->object_space(); -#endif /* ASSERT */ - PSScannerTasksQueue* const tq = claimed_stack_depth(); do { ScannerTask task; -- GitLab From 8a3cca09ba427282f2712bec7298b85bbacf076b Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Fri, 28 Jan 2022 09:06:06 +0000 Subject: [PATCH 324/564] 8280784: VM_Cleanup unnecessarily processes all thread oops Reviewed-by: eosterlund, shade --- src/hotspot/share/runtime/vmOperations.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/hotspot/share/runtime/vmOperations.hpp b/src/hotspot/share/runtime/vmOperations.hpp index 3394d53fa98..b68b6fd728b 100644 --- a/src/hotspot/share/runtime/vmOperations.hpp +++ b/src/hotspot/share/runtime/vmOperations.hpp @@ -45,6 +45,10 @@ class VM_Cleanup: public VM_Operation { public: VMOp_Type type() const { return VMOp_Cleanup; } void doit() {}; + virtual bool skip_thread_oop_barriers() const { + // None of the safepoint cleanup tasks read oops in the Java threads. + return true; + } }; class VM_ClearICs: public VM_Operation { -- GitLab From ed826f2927457f73f058732c6d073acf54ee86f7 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Fri, 28 Jan 2022 09:16:43 +0000 Subject: [PATCH 325/564] 8280397: Factor out task queue statistics printing Reviewed-by: pliden, kbarrett, mli --- src/hotspot/share/gc/g1/g1YoungCollector.cpp | 46 +---------------- src/hotspot/share/gc/g1/g1YoungCollector.hpp | 9 +--- .../share/gc/parallel/psPromotionManager.cpp | 27 +++------- src/hotspot/share/gc/shared/taskqueue.hpp | 14 ++++- .../share/gc/shared/taskqueue.inline.hpp | 51 ++++++++++++++++++- 5 files changed, 72 insertions(+), 75 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1YoungCollector.cpp b/src/hotspot/share/gc/g1/g1YoungCollector.cpp index d476c981d71..1a73ed30e26 100644 --- a/src/hotspot/share/gc/g1/g1YoungCollector.cpp +++ b/src/hotspot/share/gc/g1/g1YoungCollector.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022, 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 @@ -59,47 +59,6 @@ #include "memory/resourceArea.hpp" #include "utilities/ticks.hpp" -#if TASKQUEUE_STATS -uint G1YoungCollector::num_task_queues() const { - return task_queues()->size(); -} - -void G1YoungCollector::print_taskqueue_stats_hdr(outputStream* const st) { - st->print_raw_cr("GC Task Stats"); - st->print_raw("thr "); TaskQueueStats::print_header(1, st); st->cr(); - st->print_raw("--- "); TaskQueueStats::print_header(2, st); st->cr(); -} - -void G1YoungCollector::print_taskqueue_stats() const { - if (!log_is_enabled(Trace, gc, task, stats)) { - return; - } - Log(gc, task, stats) log; - ResourceMark rm; - LogStream ls(log.trace()); - outputStream* st = &ls; - - print_taskqueue_stats_hdr(st); - - TaskQueueStats totals; - const uint n = num_task_queues(); - for (uint i = 0; i < n; ++i) { - st->print("%3u ", i); _g1h->task_queue(i)->stats.print(st); st->cr(); - totals += _g1h->task_queue(i)->stats; - } - st->print_raw("tot "); totals.print(st); st->cr(); - - DEBUG_ONLY(totals.verify()); -} - -void G1YoungCollector::reset_taskqueue_stats() { - const uint n = num_task_queues(); - for (uint i = 0; i < n; ++i) { - _g1h->task_queue(i)->stats.reset(); - } -} -#endif // TASKQUEUE_STATS - // GCTraceTime wrapper that constructs the message according to GC pause type and // GC cause. // The code relies on the fact that GCTraceTimeWrapper stores the string passed @@ -1147,6 +1106,5 @@ void G1YoungCollector::collect() { policy()->record_young_collection_end(_concurrent_operation_is_full_mark, evacuation_failed()); } - TASKQUEUE_STATS_ONLY(print_taskqueue_stats()); - TASKQUEUE_STATS_ONLY(reset_taskqueue_stats()); + TASKQUEUE_STATS_ONLY(_g1h->task_queues()->print_and_reset_taskqueue_stats("Oop Queue");) } diff --git a/src/hotspot/share/gc/g1/g1YoungCollector.hpp b/src/hotspot/share/gc/g1/g1YoungCollector.hpp index 055803a3352..c5ad5c45235 100644 --- a/src/hotspot/share/gc/g1/g1YoungCollector.hpp +++ b/src/hotspot/share/gc/g1/g1YoungCollector.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022, 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 @@ -134,13 +134,6 @@ class G1YoungCollector { // True iff an evacuation has failed in the most-recent collection. bool evacuation_failed() const; -#if TASKQUEUE_STATS - uint num_task_queues() const; - static void print_taskqueue_stats_hdr(outputStream* const st); - void print_taskqueue_stats() const; - void reset_taskqueue_stats(); -#endif // TASKQUEUE_STATS - public: G1YoungCollector(GCCause::Cause gc_cause, double target_pause_time_ms); diff --git a/src/hotspot/share/gc/parallel/psPromotionManager.cpp b/src/hotspot/share/gc/parallel/psPromotionManager.cpp index ad63244a299..0eef7667810 100644 --- a/src/hotspot/share/gc/parallel/psPromotionManager.cpp +++ b/src/hotspot/share/gc/parallel/psPromotionManager.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2022, 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 @@ -147,37 +147,24 @@ static const char* const pm_stats_hdr[] = { "--- ---------- ---------- ---------- ----------" }; -void -PSPromotionManager::print_taskqueue_stats() { +void PSPromotionManager::print_taskqueue_stats() { if (!log_is_enabled(Trace, gc, task, stats)) { return; } Log(gc, task, stats) log; ResourceMark rm; LogStream ls(log.trace()); - outputStream* out = &ls; - out->print_cr("== GC Tasks Stats, GC %3d", - ParallelScavengeHeap::heap()->total_collections()); - TaskQueueStats totals; - out->print("thr "); TaskQueueStats::print_header(1, out); out->cr(); - out->print("--- "); TaskQueueStats::print_header(2, out); out->cr(); - for (uint i = 0; i < ParallelGCThreads; ++i) { - TaskQueueStats& next = manager_array(i)->_claimed_stack_depth.stats; - out->print("%3d ", i); next.print(out); out->cr(); - totals += next; - } - out->print("tot "); totals.print(out); out->cr(); + stack_array_depth()->print_taskqueue_stats(&ls, "Oop Queue"); const uint hlines = sizeof(pm_stats_hdr) / sizeof(pm_stats_hdr[0]); - for (uint i = 0; i < hlines; ++i) out->print_cr("%s", pm_stats_hdr[i]); + for (uint i = 0; i < hlines; ++i) ls.print_cr("%s", pm_stats_hdr[i]); for (uint i = 0; i < ParallelGCThreads; ++i) { - manager_array(i)->print_local_stats(out, i); + manager_array(i)->print_local_stats(&ls, i); } } -void -PSPromotionManager::reset_stats() { +void PSPromotionManager::reset_stats() { claimed_stack_depth()->stats.reset(); _array_chunk_pushes = _array_chunk_steals = 0; _arrays_chunked = _array_chunks_processed = 0; @@ -216,8 +203,6 @@ void PSPromotionManager::reset() { // We need to get an assert in here to make sure the labs are always flushed. - ParallelScavengeHeap* heap = ParallelScavengeHeap::heap(); - // Do not prefill the LAB's, save heap wastage! HeapWord* lab_base = young_space()->top(); _young_lab.initialize(MemRegion(lab_base, (size_t)0)); diff --git a/src/hotspot/share/gc/shared/taskqueue.hpp b/src/hotspot/share/gc/shared/taskqueue.hpp index e2c21f1dc6d..dd2039ddf2a 100644 --- a/src/hotspot/share/gc/shared/taskqueue.hpp +++ b/src/hotspot/share/gc/shared/taskqueue.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2022, 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 @@ -473,6 +473,18 @@ public: virtual uint tasks() const; uint size() const { return _n; } + +#if TASKQUEUE_STATS +private: + static void print_taskqueue_stats_hdr(outputStream* const st, const char* label); +public: + void print_taskqueue_stats(outputStream* const st, const char* label); + void reset_taskqueue_stats(); + + // Prints taskqueue set statistics into gc+task+stats=trace and resets + // its statistics. + void print_and_reset_taskqueue_stats(const char* label); +#endif // TASKQUEUE_STATS }; template void diff --git a/src/hotspot/share/gc/shared/taskqueue.inline.hpp b/src/hotspot/share/gc/shared/taskqueue.inline.hpp index c0ea64ba165..1b47c4193d9 100644 --- a/src/hotspot/share/gc/shared/taskqueue.inline.hpp +++ b/src/hotspot/share/gc/shared/taskqueue.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,11 +27,15 @@ #include "gc/shared/taskqueue.hpp" +#include "logging/log.hpp" +#include "logging/logStream.hpp" #include "memory/allocation.inline.hpp" +#include "memory/resourceArea.hpp" #include "oops/oop.inline.hpp" #include "runtime/atomic.hpp" #include "runtime/orderAccess.hpp" #include "utilities/debug.hpp" +#include "utilities/ostream.hpp" #include "utilities/stack.inline.hpp" template @@ -48,6 +52,51 @@ inline GenericTaskQueueSet::~GenericTaskQueueSet() { FREE_C_HEAP_ARRAY(T*, _queues); } +#if TASKQUEUE_STATS +template +void GenericTaskQueueSet::print_taskqueue_stats_hdr(outputStream* const st, const char* label) { + st->print_cr("GC Task Stats %s", label); + st->print("thr "); TaskQueueStats::print_header(1, st); st->cr(); + st->print("--- "); TaskQueueStats::print_header(2, st); st->cr(); +} + +template +void GenericTaskQueueSet::print_taskqueue_stats(outputStream* const st, const char* label) { + print_taskqueue_stats_hdr(st, label); + + TaskQueueStats totals; + const uint n = size(); + for (uint i = 0; i < n; ++i) { + st->print("%3u ", i); queue(i)->stats.print(st); st->cr(); + totals += queue(i)->stats; + } + st->print_raw("tot "); totals.print(st); st->cr(); + + DEBUG_ONLY(totals.verify()); +} + +template +void GenericTaskQueueSet::reset_taskqueue_stats() { + const uint n = size(); + for (uint i = 0; i < n; ++i) { + queue(i)->stats.reset(); + } +} + +template +inline void GenericTaskQueueSet::print_and_reset_taskqueue_stats(const char* label) { + if (!log_is_enabled(Trace, gc, task, stats)) { + return; + } + Log(gc, task, stats) log; + ResourceMark rm; + LogStream ls(log.trace()); + + print_taskqueue_stats(&ls, label); + reset_taskqueue_stats(); +} +#endif // TASKQUEUE_STATS + template inline GenericTaskQueue::GenericTaskQueue() : _elems(ArrayAllocator::allocate(N, F)), -- GitLab From 6de90ad9800b83c4a5f364c3645603fcb6828d6c Mon Sep 17 00:00:00 2001 From: Magnus Ihse Bursie Date: Fri, 28 Jan 2022 12:45:43 +0000 Subject: [PATCH 326/564] 8280863: Update build README to reflect that MSYS2 is supported Reviewed-by: ihse --- doc/building.html | 4 ++-- doc/building.md | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/building.html b/doc/building.html index 6b99cf03ef2..9cb1807345c 100644 --- a/doc/building.html +++ b/doc/building.html @@ -196,7 +196,7 @@

    Windows

    Windows XP is not a supported platform, but all newer Windows should be able to build the JDK.

    On Windows, it is important that you pay attention to the instructions in the Special Considerations.

    -

    Windows is the only non-POSIX OS supported by the JDK, and as such, requires some extra care. A POSIX support layer is required to build on Windows. Currently, the only supported such layers are Cygwin and Windows Subsystem for Linux (WSL). (Msys is no longer supported due to a too old bash; msys2 would likely be possible to support in a future version but that would require effort to implement.)

    +

    Windows is the only non-POSIX OS supported by the JDK, and as such, requires some extra care. A POSIX support layer is required to build on Windows. Currently, the only supported such layers are Cygwin, Windows Subsystem for Linux (WSL), and MSYS2. (MSYS is no longer supported due to an outdated bash; While OpenJDK can be built with MSYS2, support for it is still experimental, so build failures and unusual errors are not uncommon.)

    Internally in the build system, all paths are represented as Unix-style paths, e.g. /cygdrive/c/git/jdk/Makefile rather than C:\git\jdk\Makefile. This rule also applies to input to the build system, e.g. in arguments to configure. So, use --with-msvcr-dll=/cygdrive/c/msvcr100.dll rather than --with-msvcr-dll=c:\msvcr100.dll. For details on this conversion, see the section on Fixpath.

    Cygwin

    A functioning Cygwin environment is required for building the JDK on Windows. If you have a 64-bit OS, we strongly recommend using the 64-bit version of Cygwin.

    @@ -298,7 +298,7 @@

    It is advisable to keep an older version of Xcode for building the JDK when updating Xcode. This blog page has good suggestions on managing multiple Xcode versions. To use a specific version of Xcode, use xcode-select -s before running configure, or use --with-toolchain-path to point to the version of Xcode to use, e.g. configure --with-toolchain-path=/Applications/Xcode8.app/Contents/Developer/usr/bin

    If you have recently (inadvertently) updated your OS and/or Xcode version, and the JDK can no longer be built, please see the section on Problems with the Build Environment, and Getting Help to find out if there are any recent, non-merged patches available for this update.

    Microsoft Visual Studio

    -

    For aarch64 machines running Windows the minimum accepted version is Visual Studio 2019 (16.8 or higher). For all other platforms the minimum accepted version of Visual Studio is 2017. Older versions will not be accepted by configure and will not work. For all platforms the maximum accepted version of Visual Studio is 2022.

    +

    For aarch64 machines running Windows the minimum accepted version is Visual Studio 2019 (16.8 or higher). For all other platforms the minimum accepted version of Visual Studio is 2017. Older versions will not be accepted by configure and will not work. For all platforms the maximum accepted version of Visual Studio is 2022.

    If you have multiple versions of Visual Studio installed, configure will by default pick the latest. You can request a specific version to be used by setting --with-toolchain-version, e.g. --with-toolchain-version=2017.

    If you have Visual Studio installed but configure fails to detect it, it may be because of spaces in path.

    IBM XL C/C++

    diff --git a/doc/building.md b/doc/building.md index 3ae4a28ac1f..459dbaa4c41 100644 --- a/doc/building.md +++ b/doc/building.md @@ -179,10 +179,10 @@ On Windows, it is important that you pay attention to the instructions in the Windows is the only non-POSIX OS supported by the JDK, and as such, requires some extra care. A POSIX support layer is required to build on Windows. -Currently, the only supported such layers are Cygwin and Windows Subsystem for -Linux (WSL). (Msys is no longer supported due to a too old bash; msys2 would -likely be possible to support in a future version but that would require effort -to implement.) +Currently, the only supported such layers are Cygwin, Windows Subsystem for +Linux (WSL), and MSYS2. (MSYS is no longer supported due to an outdated bash; +While OpenJDK can be built with MSYS2, support for it is still experimental, so +build failures and unusual errors are not uncommon.) Internally in the build system, all paths are represented as Unix-style paths, e.g. `/cygdrive/c/git/jdk/Makefile` rather than `C:\git\jdk\Makefile`. This -- GitLab From cb8a82ee24881113af4eea04d7ce5963d18e9b83 Mon Sep 17 00:00:00 2001 From: Kevin Walls Date: Fri, 28 Jan 2022 12:54:19 +0000 Subject: [PATCH 327/564] 8272317: jstatd has dependency on Security Manager which needs to be removed Reviewed-by: cjplummer, rriggs --- make/modules/jdk.jstatd/Launcher.gmk | 3 +-- .../share/classes/sun/tools/jstatd/Jstatd.java | 15 ++++++--------- test/jdk/sun/tools/jstatd/JstatdTest.java | 18 +++++++----------- test/jdk/sun/tools/jstatd/all.policy | 3 --- 4 files changed, 14 insertions(+), 25 deletions(-) delete mode 100644 test/jdk/sun/tools/jstatd/all.policy diff --git a/make/modules/jdk.jstatd/Launcher.gmk b/make/modules/jdk.jstatd/Launcher.gmk index 26813fa06e7..2137fddd9a0 100644 --- a/make/modules/jdk.jstatd/Launcher.gmk +++ b/make/modules/jdk.jstatd/Launcher.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -27,5 +27,4 @@ include LauncherCommon.gmk $(eval $(call SetupBuildLauncher, jstatd, \ MAIN_CLASS := sun.tools.jstatd.Jstatd, \ - JAVA_ARGS := -Djava.security.manager=allow, \ )) diff --git a/src/jdk.jstatd/share/classes/sun/tools/jstatd/Jstatd.java b/src/jdk.jstatd/share/classes/sun/tools/jstatd/Jstatd.java index 30fe303fa61..5dc7f1fa2fb 100644 --- a/src/jdk.jstatd/share/classes/sun/tools/jstatd/Jstatd.java +++ b/src/jdk.jstatd/share/classes/sun/tools/jstatd/Jstatd.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ package sun.tools.jstatd; +import java.io.ObjectInputFilter; import java.rmi.*; import java.rmi.server.*; import java.rmi.registry.Registry; @@ -47,6 +48,8 @@ public class Jstatd { private static boolean startRegistry = true; private static RemoteHost remoteHost; + private static final String rmiFilterPattern = "sun.jvmstat.monitor.remote.RemoteVm;com.sun.proxy.jdk.proxy*;java.lang.reflect.Proxy;java.rmi.server.RemoteObjectInvocationHandler;java.rmi.server.RemoteObject;!*"; + private static void printUsage() { System.err.println("usage: jstatd [-nr] [-p port] [-r rmiport] [-n rminame]\n" + " jstatd -?|-h|--help"); @@ -72,7 +75,6 @@ public class Jstatd { } } - @SuppressWarnings({"removal","deprecation"}) // Use of RMISecurityManager public static void main(String[] args) { String rminame = null; int rmiPort = 0; @@ -132,10 +134,6 @@ public class Jstatd { System.exit(1); } - if (System.getSecurityManager() == null) { - System.setSecurityManager(new RMISecurityManager()); - } - StringBuilder name = new StringBuilder(); if (port >= 0) { @@ -149,11 +147,10 @@ public class Jstatd { name.append("/").append(rminame); try { - // use 1.5.0 dynamically generated subs. - System.setProperty("java.rmi.server.ignoreSubClasses", "true"); remoteHost = new RemoteHostImpl(rmiPort); + ObjectInputFilter filter = ObjectInputFilter.Config.createFilter(rmiFilterPattern); RemoteHost stub = (RemoteHost) UnicastRemoteObject.exportObject( - remoteHost, rmiPort); + remoteHost, rmiPort, filter); bind(name.toString(), stub); System.out.println("jstatd started (bound to " + name.toString() + ")"); System.out.flush(); diff --git a/test/jdk/sun/tools/jstatd/JstatdTest.java b/test/jdk/sun/tools/jstatd/JstatdTest.java index 56c86cbfa07..9eb1ccb3748 100644 --- a/test/jdk/sun/tools/jstatd/JstatdTest.java +++ b/test/jdk/sun/tools/jstatd/JstatdTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2022, 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 @@ -43,7 +43,7 @@ import jdk.test.lib.thread.ProcessThread; *
      * {@code
      * // start jstatd process
    - * jstatd -J-XX:+UsePerfData -J-Djava.security.policy=all.policy
    + * jstatd -J-XX:+UsePerfData
      *
      * // run jps and verify its output
      * jps -J-XX:+UsePerfData hostname
    @@ -244,20 +244,16 @@ public final class JstatdTest {
         /**
          * Depending on test settings command line can look like:
          *
    -     * jstatd -J-XX:+UsePerfData -J-Djava.security.policy=all.policy
    -     * jstatd -J-XX:+UsePerfData -J-Djava.security.policy=all.policy -p port
    -     * jstatd -J-XX:+UsePerfData -J-Djava.security.policy=all.policy -p port -r rmiport
    -     * jstatd -J-XX:+UsePerfData -J-Djava.security.policy=all.policy -n serverName
    -     * jstatd -J-XX:+UsePerfData -J-Djava.security.policy=all.policy -p port -n serverName
    +     * jstatd -J-XX:+UsePerfData
    +     * jstatd -J-XX:+UsePerfData -p port
    +     * jstatd -J-XX:+UsePerfData -p port -r rmiport
    +     * jstatd -J-XX:+UsePerfData -n serverName
    +     * jstatd -J-XX:+UsePerfData -p port -n serverName
          */
         private String[] getJstatdCmd() throws Exception {
             JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jstatd");
             launcher.addVMArg("-XX:+UsePerfData");
             String testSrc = System.getProperty("test.src");
    -        File policy = new File(testSrc, "all.policy");
    -        assertTrue(policy.exists() && policy.isFile(),
    -                "Security policy " + policy.getAbsolutePath() + " does not exist or not a file");
    -        launcher.addVMArg("-Djava.security.policy=" + policy.getAbsolutePath());
             if (port != null) {
                 addToolArg(launcher,"-p", port);
             }
    diff --git a/test/jdk/sun/tools/jstatd/all.policy b/test/jdk/sun/tools/jstatd/all.policy
    deleted file mode 100644
    index e202e4e91b6..00000000000
    --- a/test/jdk/sun/tools/jstatd/all.policy
    +++ /dev/null
    @@ -1,3 +0,0 @@
    -grant {
    -   permission java.security.AllPermission;
    -};
    -- 
    GitLab
    
    
    From 409382ba4b43bf48ed0086020dd20641effd35b6 Mon Sep 17 00:00:00 2001
    From: Sebastian Stenzel 
    Date: Fri, 28 Jan 2022 16:42:42 +0000
    Subject: [PATCH 328/564] 8280703: CipherCore.doFinal(...) causes potentially
     massive byte[] allocations during decryption
    
    Reviewed-by: ascarpino
    ---
     .../classes/com/sun/crypto/provider/CipherCore.java | 13 ++++++++-----
     1 file changed, 8 insertions(+), 5 deletions(-)
    
    diff --git a/src/java.base/share/classes/com/sun/crypto/provider/CipherCore.java b/src/java.base/share/classes/com/sun/crypto/provider/CipherCore.java
    index 93eede032f1..64ce01c53ab 100644
    --- a/src/java.base/share/classes/com/sun/crypto/provider/CipherCore.java
    +++ b/src/java.base/share/classes/com/sun/crypto/provider/CipherCore.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2002, 2022, 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
    @@ -812,10 +812,13 @@ final class CipherCore {
                 if (outputCapacity < estOutSize) {
                     cipher.save();
                 }
    -            // create temporary output buffer if the estimated size is larger
    -            // than the user-provided buffer.
    -            internalOutput = new byte[estOutSize];
    -            offset = 0;
    +            if (outputCapacity < estOutSize || padding != null) {
    +                // create temporary output buffer if the estimated size is larger
    +                // than the user-provided buffer or a padding needs to be removed
    +                // before copying the unpadded result to the output buffer
    +                internalOutput = new byte[estOutSize];
    +                offset = 0;
    +            }
             }
     
             byte[] outBuffer = (internalOutput != null) ? internalOutput : output;
    -- 
    GitLab
    
    
    From 95ee9bf7be40572e768cf6213c03ca183b8ad886 Mon Sep 17 00:00:00 2001
    From: Brian Burkhalter 
    Date: Fri, 28 Jan 2022 17:12:42 +0000
    Subject: [PATCH 329/564] 4774868: (fc spec) Unclear spec for FileChannel.force
    
    Reviewed-by: alanb
    ---
     .../share/classes/java/nio/channels/FileChannel.java          | 4 +++-
     1 file changed, 3 insertions(+), 1 deletion(-)
    
    diff --git a/src/java.base/share/classes/java/nio/channels/FileChannel.java b/src/java.base/share/classes/java/nio/channels/FileChannel.java
    index d8fee6ca995..fb9639a2d5d 100644
    --- a/src/java.base/share/classes/java/nio/channels/FileChannel.java
    +++ b/src/java.base/share/classes/java/nio/channels/FileChannel.java
    @@ -566,7 +566,9 @@ public abstract class FileChannel
          * actually done is system-dependent and is therefore unspecified.
          *
          * 

    This method is only guaranteed to force changes that were made to - * this channel's file via the methods defined in this class. It may or + * this channel's file via the methods defined in this class, or the methods + * defined by {@link FileOutputStream} or {@link RandomAccessFile} when the + * channel was obtained with the {@code getChannel} method. It may or * may not force changes that were made by modifying the content of a * {@link MappedByteBuffer mapped byte buffer} obtained by * invoking the {@link #map map} method. Invoking the {@link -- GitLab From ff34d624ba81698db0aacc1d5e2332c4345010ce Mon Sep 17 00:00:00 2001 From: "Daniel D. Daugherty" Date: Fri, 28 Jan 2022 18:09:35 +0000 Subject: [PATCH 330/564] 8280898: ProblemList compiler/regalloc/TestC2IntPressure.java on macosx-aarch64 Reviewed-by: ctornqvi --- test/hotspot/jtreg/ProblemList.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index e08217cd776..b5fe9a5bb83 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -73,6 +73,7 @@ compiler/whitebox/MakeMethodNotCompilableTest.java 8265360 macosx-aarch64 compiler/codecache/jmx/PoolsIndependenceTest.java 8264632 macosx-generic compiler/codecache/TestStressCodeBuffers.java 8272094 generic-aarch64 +compiler/regalloc/TestC2IntPressure.java 8280843 macosx-aarch64 ############################################################################# -- GitLab From 0740ac474cbda439684223e660827e38964e6b1f Mon Sep 17 00:00:00 2001 From: Chris Plummer Date: Fri, 28 Jan 2022 18:51:21 +0000 Subject: [PATCH 331/564] 8280555: serviceability/sa/TestObjectMonitorIterate.java is failing due to ObjectMonitor referencing a null Object Reviewed-by: sspitsyn, lmesnik --- .../serviceability/sa/TestObjectMonitorIterate.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/test/hotspot/jtreg/serviceability/sa/TestObjectMonitorIterate.java b/test/hotspot/jtreg/serviceability/sa/TestObjectMonitorIterate.java index 5f1e6c48f5f..e2d79b1ce9d 100644 --- a/test/hotspot/jtreg/serviceability/sa/TestObjectMonitorIterate.java +++ b/test/hotspot/jtreg/serviceability/sa/TestObjectMonitorIterate.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2021, NTT DATA. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -59,8 +59,12 @@ public class TestObjectMonitorIterate { while (itr.hasNext()) { ObjectMonitor mon = (ObjectMonitor)itr.next(); - Oop oop = heap.newOop(mon.object()); - System.out.println("Monitor found: " + oop.getKlass().getName().asString()); + if (mon.object() == null) { + System.out.println("Monitor found: object is null"); + } else { + Oop oop = heap.newOop(mon.object()); + System.out.println("Monitor found: " + oop.getKlass().getName().asString()); + } } } finally { agent.detach(); -- GitLab From 91391598989c70c98b9400997df4f9177d3e576f Mon Sep 17 00:00:00 2001 From: Denghui Dong Date: Fri, 28 Jan 2022 22:52:32 +0000 Subject: [PATCH 332/564] 8280843: macos-Aarch64 SEGV in frame::sender_for_compiled_frame after JDK-8277948 Reviewed-by: aph, dholmes --- src/hotspot/os_cpu/bsd_aarch64/thread_bsd_aarch64.cpp | 6 ++++-- .../os_cpu/windows_aarch64/thread_windows_aarch64.cpp | 5 ++++- test/hotspot/jtreg/ProblemList.txt | 1 - 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/hotspot/os_cpu/bsd_aarch64/thread_bsd_aarch64.cpp b/src/hotspot/os_cpu/bsd_aarch64/thread_bsd_aarch64.cpp index d8b1a0b20ef..f07f22bc0cd 100644 --- a/src/hotspot/os_cpu/bsd_aarch64/thread_bsd_aarch64.cpp +++ b/src/hotspot/os_cpu/bsd_aarch64/thread_bsd_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * Copyright (c) 2021, Azul Systems, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -32,7 +32,9 @@ frame JavaThread::pd_last_frame() { assert(has_last_Java_frame(), "must have last_Java_sp() when suspended"); vmassert(_anchor.last_Java_pc() != NULL, "not walkable"); - return frame(_anchor.last_Java_sp(), _anchor.last_Java_fp(), _anchor.last_Java_pc()); + frame f = frame(_anchor.last_Java_sp(), _anchor.last_Java_fp(), _anchor.last_Java_pc()); + f.set_sp_is_trusted(); + return f; } // For Forte Analyzer AsyncGetCallTrace profiling support - thread is diff --git a/src/hotspot/os_cpu/windows_aarch64/thread_windows_aarch64.cpp b/src/hotspot/os_cpu/windows_aarch64/thread_windows_aarch64.cpp index 6512df3e7b9..c5267d85d37 100644 --- a/src/hotspot/os_cpu/windows_aarch64/thread_windows_aarch64.cpp +++ b/src/hotspot/os_cpu/windows_aarch64/thread_windows_aarch64.cpp @@ -1,5 +1,6 @@ /* * Copyright (c) 2020, Microsoft Corporation. All rights reserved. + * Copyright (c) 2022, Alibaba Group Holding Limited. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +30,9 @@ frame JavaThread::pd_last_frame() { assert(has_last_Java_frame(), "must have last_Java_sp() when suspended"); vmassert(_anchor.last_Java_pc() != NULL, "not walkable"); - return frame(_anchor.last_Java_sp(), _anchor.last_Java_fp(), _anchor.last_Java_pc()); + frame f = frame(_anchor.last_Java_sp(), _anchor.last_Java_fp(), _anchor.last_Java_pc()); + f.set_sp_is_trusted(); + return f; } // For Forte Analyzer AsyncGetCallTrace profiling support - thread is diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index b5fe9a5bb83..e08217cd776 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -73,7 +73,6 @@ compiler/whitebox/MakeMethodNotCompilableTest.java 8265360 macosx-aarch64 compiler/codecache/jmx/PoolsIndependenceTest.java 8264632 macosx-generic compiler/codecache/TestStressCodeBuffers.java 8272094 generic-aarch64 -compiler/regalloc/TestC2IntPressure.java 8280843 macosx-aarch64 ############################################################################# -- GitLab From d366d15d67a08833d93a5806edef8145cb7803e5 Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Fri, 28 Jan 2022 23:18:20 +0000 Subject: [PATCH 333/564] 8280903: javadoc build fails after JDK-4774868 Reviewed-by: lancea --- .../share/classes/java/nio/channels/FileChannel.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/java.base/share/classes/java/nio/channels/FileChannel.java b/src/java.base/share/classes/java/nio/channels/FileChannel.java index fb9639a2d5d..9d9c35fbc1f 100644 --- a/src/java.base/share/classes/java/nio/channels/FileChannel.java +++ b/src/java.base/share/classes/java/nio/channels/FileChannel.java @@ -567,9 +567,10 @@ public abstract class FileChannel * *

    This method is only guaranteed to force changes that were made to * this channel's file via the methods defined in this class, or the methods - * defined by {@link FileOutputStream} or {@link RandomAccessFile} when the - * channel was obtained with the {@code getChannel} method. It may or - * may not force changes that were made by modifying the content of a + * defined by {@link java.io.FileOutputStream} or + * {@link java.io.RandomAccessFile} when the channel was obtained with the + * {@code getChannel} method. It may or may not force changes that were made + * by modifying the content of a * {@link MappedByteBuffer mapped byte buffer} obtained by * invoking the {@link #map map} method. Invoking the {@link * MappedByteBuffer#force force} method of the mapped byte buffer will -- GitLab From 268880b471eed54535927fba953347160f447fcd Mon Sep 17 00:00:00 2001 From: Andrey Turbanov Date: Sat, 29 Jan 2022 11:36:11 +0000 Subject: [PATCH 334/564] 8277412: Use String.isBlank to simplify code in sun.net.www.protocol.mailto.Handler Reviewed-by: dfuchs --- .../sun/net/www/protocol/mailto/Handler.java | 31 +++---------------- 1 file changed, 5 insertions(+), 26 deletions(-) diff --git a/src/java.base/share/classes/sun/net/www/protocol/mailto/Handler.java b/src/java.base/share/classes/sun/net/www/protocol/mailto/Handler.java index e9052397483..0c420fa1400 100644 --- a/src/java.base/share/classes/sun/net/www/protocol/mailto/Handler.java +++ b/src/java.base/share/classes/sun/net/www/protocol/mailto/Handler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,10 +32,6 @@ package sun.net.www.protocol.mailto; import java.net.URL; import java.net.URLConnection; import java.net.URLStreamHandler; -import java.io.*; -import sun.net.www.*; -//import sun.net.www.protocol.news.ArticlePoster; -import sun.net.smtp.SmtpClient; /** open an nntp input stream given a URL */ public class Handler extends URLStreamHandler { @@ -126,33 +122,16 @@ public class Handler extends URLStreamHandler { /* * Let's just make sure we DO have an Email address in the URL. */ - boolean nogood = false; - if (file == null || file.isEmpty()) - nogood = true; - else { - boolean allwhites = true; - for (int i = 0; i < file.length(); i++) - if (!Character.isWhitespace(file.charAt(i))) - allwhites = false; - if (allwhites) - nogood = true; - } - if (nogood) + if (file.isBlank()) throw new RuntimeException("No email address"); - setURLHandler(u, protocol, host, port, file, null); + setURLHandler(u, protocol, host, port, file); } /** * This method is used to suppress the deprecated warning - * - * @param u the URL to receive the result of parsing the spec - * @param spec the URL string to parse - * @param start the character position to start parsing at. This is - * just past the ':'. - * @param limit the character position to stop parsing at. */ @SuppressWarnings("deprecation") - private void setURLHandler(URL u, String protocol, String host, int port, String file, String ref) { - setURL(u,protocol,host,port,file,null); + private void setURLHandler(URL u, String protocol, String host, int port, String file) { + setURL(u, protocol, host, port, file, null); } } -- GitLab From be9f984caec32c3fe1deef30efe40fa115409ca0 Mon Sep 17 00:00:00 2001 From: Chris Plummer Date: Sat, 29 Jan 2022 21:35:06 +0000 Subject: [PATCH 335/564] 8280553: resourcehogs/serviceability/sa/TestHeapDumpForLargeArray.java can fail if GC occurs Reviewed-by: alanb, amenkov --- .../serviceability/sa/LingeredAppWithLargeArray.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/hotspot/jtreg/resourcehogs/serviceability/sa/LingeredAppWithLargeArray.java b/test/hotspot/jtreg/resourcehogs/serviceability/sa/LingeredAppWithLargeArray.java index 44929f05b15..244f4187334 100644 --- a/test/hotspot/jtreg/resourcehogs/serviceability/sa/LingeredAppWithLargeArray.java +++ b/test/hotspot/jtreg/resourcehogs/serviceability/sa/LingeredAppWithLargeArray.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022, 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,9 +23,12 @@ import jdk.test.lib.apps.LingeredApp; +import java.lang.ref.Reference; + public class LingeredAppWithLargeArray extends LingeredApp { public static void main(String args[]) { int[] hugeArray = new int[Integer.MAX_VALUE/2]; LingeredApp.main(args); + Reference.reachabilityFence(hugeArray); } } -- GitLab From 251351f49498ea39150b38860b8f73232fbaf05d Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Mon, 31 Jan 2022 08:49:02 +0000 Subject: [PATCH 336/564] 8280889: java/lang/instrument/GetObjectSizeIntrinsicsTest.java fails with -XX:-UseCompressedOops Reviewed-by: sspitsyn, dcubed --- .../instrument/GetObjectSizeIntrinsicsTest.java | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/test/jdk/java/lang/instrument/GetObjectSizeIntrinsicsTest.java b/test/jdk/java/lang/instrument/GetObjectSizeIntrinsicsTest.java index 975adb23cf5..a4fdab2ec47 100644 --- a/test/jdk/java/lang/instrument/GetObjectSizeIntrinsicsTest.java +++ b/test/jdk/java/lang/instrument/GetObjectSizeIntrinsicsTest.java @@ -280,19 +280,16 @@ * * @run main/othervm -Xmx8g * -XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure -XX:+WhiteBoxAPI -Xbootclasspath/a:. - * -XX:ObjectAlignmentInBytes=32 * -Xint * -javaagent:basicAgent.jar GetObjectSizeIntrinsicsTest GetObjectSizeIntrinsicsTest large * * @run main/othervm -Xmx8g * -XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure -XX:+WhiteBoxAPI -Xbootclasspath/a:. - * -XX:ObjectAlignmentInBytes=32 * -Xbatch -XX:TieredStopAtLevel=1 * -javaagent:basicAgent.jar GetObjectSizeIntrinsicsTest GetObjectSizeIntrinsicsTest large * * @run main/othervm -Xmx8g * -XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure -XX:+WhiteBoxAPI -Xbootclasspath/a:. - * -XX:ObjectAlignmentInBytes=32 * -Xbatch -XX:-TieredCompilation * -javaagent:basicAgent.jar GetObjectSizeIntrinsicsTest GetObjectSizeIntrinsicsTest large */ @@ -312,8 +309,9 @@ public class GetObjectSizeIntrinsicsTest extends ASimpleInstrumentationTestCase static final int SMALL_ARRAY_SIZE = 1024; - // With int[] arrays, this overflows 4G boundary - static final int LARGE_ARRAY_SIZE = 1024*1024*1024 + 1024; + // These should overflow 4G size boundary + static final int LARGE_INT_ARRAY_SIZE = 1024*1024*1024 + 1024; + static final int LARGE_OBJ_ARRAY_SIZE = (4096/(int)REF_SIZE)*1024*1024 + 1024; final String mode; @@ -446,16 +444,16 @@ public class GetObjectSizeIntrinsicsTest extends ASimpleInstrumentationTestCase } private void testSize_localLargeIntArray() { - int[] arr = new int[LARGE_ARRAY_SIZE]; - long expected = roundUp(4L*LARGE_ARRAY_SIZE + 16, OBJ_ALIGN); + int[] arr = new int[LARGE_INT_ARRAY_SIZE]; + long expected = roundUp(4L*LARGE_INT_ARRAY_SIZE + 16, OBJ_ALIGN); for (int c = 0; c < ITERS; c++) { assertEquals(expected, fInst.getObjectSize(arr)); } } private void testSize_localLargeObjArray() { - Object[] arr = new Object[LARGE_ARRAY_SIZE]; - long expected = roundUp(REF_SIZE*LARGE_ARRAY_SIZE + 16, OBJ_ALIGN); + Object[] arr = new Object[LARGE_OBJ_ARRAY_SIZE]; + long expected = roundUp(REF_SIZE*LARGE_OBJ_ARRAY_SIZE + 16, OBJ_ALIGN); for (int c = 0; c < ITERS; c++) { assertEquals(expected, fInst.getObjectSize(arr)); } -- GitLab From c6ed2046b4ba8eafb6b7e934b134829760d56ecd Mon Sep 17 00:00:00 2001 From: Andrey Turbanov Date: Mon, 31 Jan 2022 12:11:03 +0000 Subject: [PATCH 337/564] 8278263: Remove redundant synchronized from URLStreamHandler.openConnection methods Reviewed-by: dfuchs --- .../sun/net/www/protocol/mailto/Handler.java | 2 +- .../sun/net/www/protocol/file/Handler.java | 19 ++++--------------- .../sun/net/www/protocol/file/Handler.java | 19 ++++--------------- 3 files changed, 9 insertions(+), 31 deletions(-) diff --git a/src/java.base/share/classes/sun/net/www/protocol/mailto/Handler.java b/src/java.base/share/classes/sun/net/www/protocol/mailto/Handler.java index 0c420fa1400..cb8e490995e 100644 --- a/src/java.base/share/classes/sun/net/www/protocol/mailto/Handler.java +++ b/src/java.base/share/classes/sun/net/www/protocol/mailto/Handler.java @@ -95,7 +95,7 @@ public class Handler extends URLStreamHandler { // } */ - public synchronized URLConnection openConnection(URL u) { + public URLConnection openConnection(URL u) { return new MailToURLConnection(u); } diff --git a/src/java.base/unix/classes/sun/net/www/protocol/file/Handler.java b/src/java.base/unix/classes/sun/net/www/protocol/file/Handler.java index 5892517e938..207e95d27f8 100644 --- a/src/java.base/unix/classes/sun/net/www/protocol/file/Handler.java +++ b/src/java.base/unix/classes/sun/net/www/protocol/file/Handler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2021, 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,13 +25,10 @@ package sun.net.www.protocol.file; -import java.net.InetAddress; import java.net.URLConnection; import java.net.URL; import java.net.Proxy; -import java.net.MalformedURLException; import java.net.URLStreamHandler; -import java.io.InputStream; import java.io.IOException; import sun.net.www.ParseUtil; import java.io.File; @@ -42,14 +39,6 @@ import java.io.File; */ public class Handler extends URLStreamHandler { - private String getHost(URL url) { - String host = url.getHost(); - if (host == null) - host = ""; - return host; - } - - protected void parseURL(URL u, String spec, int start, int limit) { /* * Ugly backwards compatibility. Flip any file separator @@ -61,18 +50,18 @@ public class Handler extends URLStreamHandler { * rather than forcing this to be fixed in the caller of the URL * class where it belongs. Since backslash is an "unwise" * character that would normally be encoded if literally intended - * as a non-seperator character the damage of veering away from the + * as a non-separator character the damage of veering away from the * specification is presumably limited. */ super.parseURL(u, spec.replace(File.separatorChar, '/'), start, limit); } - public synchronized URLConnection openConnection(URL u) + public URLConnection openConnection(URL u) throws IOException { return openConnection(u, null); } - public synchronized URLConnection openConnection(URL u, Proxy p) + public URLConnection openConnection(URL u, Proxy p) throws IOException { String host = u.getHost(); if (host == null || host.isEmpty() || host.equals("~") || diff --git a/src/java.base/windows/classes/sun/net/www/protocol/file/Handler.java b/src/java.base/windows/classes/sun/net/www/protocol/file/Handler.java index 5475eca7c2e..18ccda6e7c1 100644 --- a/src/java.base/windows/classes/sun/net/www/protocol/file/Handler.java +++ b/src/java.base/windows/classes/sun/net/www/protocol/file/Handler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2021, 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,13 +25,10 @@ package sun.net.www.protocol.file; -import java.net.InetAddress; import java.net.URLConnection; import java.net.URL; import java.net.Proxy; -import java.net.MalformedURLException; import java.net.URLStreamHandler; -import java.io.InputStream; import java.io.IOException; import sun.net.www.ParseUtil; import java.io.File; @@ -42,14 +39,6 @@ import java.io.File; */ public class Handler extends URLStreamHandler { - private String getHost(URL url) { - String host = url.getHost(); - if (host == null) - host = ""; - return host; - } - - protected void parseURL(URL u, String spec, int start, int limit) { /* * Ugly backwards compatibility. Flip any file separator @@ -61,18 +50,18 @@ public class Handler extends URLStreamHandler { * rather than forcing this to be fixed in the caller of the URL * class where it belongs. Since backslash is an "unwise" * character that would normally be encoded if literally intended - * as a non-seperator character the damage of veering away from the + * as a non-separator character the damage of veering away from the * specification is presumably limited. */ super.parseURL(u, spec.replace(File.separatorChar, '/'), start, limit); } - public synchronized URLConnection openConnection(URL url) + public URLConnection openConnection(URL url) throws IOException { return openConnection(url, null); } - public synchronized URLConnection openConnection(URL url, Proxy p) + public URLConnection openConnection(URL url, Proxy p) throws IOException { String path; -- GitLab From 61794c503973a330278f0595e36be0bd686fe2b5 Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Mon, 31 Jan 2022 12:30:09 +0000 Subject: [PATCH 338/564] 8280817: Clean up and unify empty VM operations Reviewed-by: shade, coleenp --- src/hotspot/share/runtime/vmOperation.hpp | 12 ++--- src/hotspot/share/runtime/vmOperations.hpp | 58 ++++++++++------------ src/hotspot/share/runtime/vmThread.cpp | 6 +-- test/hotspot/gtest/threadHelper.inline.hpp | 8 +-- 4 files changed, 35 insertions(+), 49 deletions(-) diff --git a/src/hotspot/share/runtime/vmOperation.hpp b/src/hotspot/share/runtime/vmOperation.hpp index bd453df5979..5489770f386 100644 --- a/src/hotspot/share/runtime/vmOperation.hpp +++ b/src/hotspot/share/runtime/vmOperation.hpp @@ -35,20 +35,19 @@ // Note: When new VM_XXX comes up, add 'XXX' to the template table. #define VM_OPS_DO(template) \ - template(None) \ + template(Halt) \ + template(SafepointALot) \ template(Cleanup) \ template(ThreadDump) \ template(PrintThreads) \ template(FindDeadlocks) \ template(ClearICs) \ template(ForceSafepoint) \ - template(ForceAsyncSafepoint) \ template(DeoptimizeFrame) \ template(DeoptimizeAll) \ template(ZombieAll) \ template(Verify) \ template(HeapDumper) \ - template(DeoptimizeTheWorld) \ template(CollectForMetadataAllocation) \ template(GC_HeapInspection) \ template(GenCollectFull) \ @@ -64,9 +63,7 @@ template(ZMarkEnd) \ template(ZRelocateStart) \ template(ZVerify) \ - template(HandshakeOneThread) \ template(HandshakeAllThreads) \ - template(HandshakeFallback) \ template(PopulateDumpSharedSpace) \ template(JNIFunctionTableCopier) \ template(RedefineClasses) \ @@ -89,7 +86,6 @@ template(ShenandoahDegeneratedGC) \ template(Exit) \ template(LinuxDllLoad) \ - template(RotateGCLog) \ template(WhiteBoxOperation) \ template(JVMCIResizeCounters) \ template(ClassLoaderStatsOperation) \ @@ -99,12 +95,10 @@ template(CleanClassLoaderDataMetaspaces) \ template(PrintCompileQueue) \ template(PrintClassHierarchy) \ - template(ThreadSuspend) \ - template(ThreadsSuspendJVMTI) \ template(ICBufferFull) \ - template(ScavengeMonitors) \ template(PrintMetadata) \ template(GTestExecuteAtSafepoint) \ + template(GTestStopSafepoint) \ template(JFROldObject) \ template(JvmtiPostObjectFree) diff --git a/src/hotspot/share/runtime/vmOperations.hpp b/src/hotspot/share/runtime/vmOperations.hpp index b68b6fd728b..262ac740c1c 100644 --- a/src/hotspot/share/runtime/vmOperations.hpp +++ b/src/hotspot/share/runtime/vmOperations.hpp @@ -32,58 +32,50 @@ // A hodge podge of commonly used VM Operations -class VM_None: public VM_Operation { - const char* _reason; - public: - VM_None(const char* reason) : _reason(reason) {} - const char* name() const { return _reason; } - VMOp_Type type() const { return VMOp_None; } - void doit() {}; -}; - -class VM_Cleanup: public VM_Operation { - public: - VMOp_Type type() const { return VMOp_Cleanup; } - void doit() {}; - virtual bool skip_thread_oop_barriers() const { - // None of the safepoint cleanup tasks read oops in the Java threads. +class VM_EmptyOperation : public VM_Operation { +public: + virtual void doit() final {} + virtual bool skip_thread_oop_barriers() const final { + // Neither the doit function nor the the safepoint + // cleanup tasks read oops in the Java threads. return true; } }; -class VM_ClearICs: public VM_Operation { - private: - bool _preserve_static_stubs; +class VM_Halt: public VM_EmptyOperation { public: - VM_ClearICs(bool preserve_static_stubs) { _preserve_static_stubs = preserve_static_stubs; } - void doit(); - VMOp_Type type() const { return VMOp_ClearICs; } + VMOp_Type type() const { return VMOp_Halt; } }; -// empty vm op, evaluated just to force a safepoint -class VM_ForceSafepoint: public VM_Operation { +class VM_SafepointALot: public VM_EmptyOperation { public: - void doit() {} - VMOp_Type type() const { return VMOp_ForceSafepoint; } + VMOp_Type type() const { return VMOp_SafepointALot; } }; -// empty vm op, when forcing a safepoint to suspend a thread -class VM_ThreadSuspend: public VM_ForceSafepoint { +class VM_Cleanup: public VM_EmptyOperation { public: - VMOp_Type type() const { return VMOp_ThreadSuspend; } + VMOp_Type type() const { return VMOp_Cleanup; } }; -// empty vm op, when forcing a safepoint to suspend threads from jvmti -class VM_ThreadsSuspendJVMTI: public VM_ForceSafepoint { +// empty vm op, evaluated just to force a safepoint +class VM_ForceSafepoint: public VM_EmptyOperation { public: - VMOp_Type type() const { return VMOp_ThreadsSuspendJVMTI; } + VMOp_Type type() const { return VMOp_ForceSafepoint; } }; // empty vm op, when forcing a safepoint due to inline cache buffers being full -class VM_ICBufferFull: public VM_ForceSafepoint { +class VM_ICBufferFull: public VM_EmptyOperation { public: VMOp_Type type() const { return VMOp_ICBufferFull; } - virtual bool skip_thread_oop_barriers() const { return true; } +}; + +class VM_ClearICs: public VM_Operation { + private: + bool _preserve_static_stubs; + public: + VM_ClearICs(bool preserve_static_stubs) { _preserve_static_stubs = preserve_static_stubs; } + void doit(); + VMOp_Type type() const { return VMOp_ClearICs; } }; // Base class for invoking parts of a gtest in a safepoint. diff --git a/src/hotspot/share/runtime/vmThread.cpp b/src/hotspot/share/runtime/vmThread.cpp index 2e601a11f60..e22c3398486 100644 --- a/src/hotspot/share/runtime/vmThread.cpp +++ b/src/hotspot/share/runtime/vmThread.cpp @@ -96,8 +96,8 @@ void VMOperationTimeoutTask::disarm() { //------------------------------------------------------------------------------------------------------------------ // Implementation of VMThread stuff -static VM_None safepointALot_op("SafepointALot"); -static VM_Cleanup cleanup_op; +static VM_SafepointALot safepointALot_op; +static VM_Cleanup cleanup_op; bool VMThread::_should_terminate = false; bool VMThread::_terminated = false; @@ -147,7 +147,7 @@ void VMThread::destroy() { _vm_thread = NULL; // VM thread is gone } -static VM_None halt_op("Halt"); +static VM_Halt halt_op; void VMThread::run() { assert(this == vm_thread(), "check"); diff --git a/test/hotspot/gtest/threadHelper.inline.hpp b/test/hotspot/gtest/threadHelper.inline.hpp index 52c044850e8..3c6b951df0a 100644 --- a/test/hotspot/gtest/threadHelper.inline.hpp +++ b/test/hotspot/gtest/threadHelper.inline.hpp @@ -49,13 +49,13 @@ static void startTestThread(JavaThread* thread, const char* name) { } } -class VM_StopSafepoint : public VM_Operation { +class VM_GTestStopSafepoint : public VM_Operation { public: Semaphore* _running; Semaphore* _test_complete; - VM_StopSafepoint(Semaphore* running, Semaphore* wait_for) : + VM_GTestStopSafepoint(Semaphore* running, Semaphore* wait_for) : _running(running), _test_complete(wait_for) {} - VMOp_Type type() const { return VMOp_None; } + VMOp_Type type() const { return VMOp_GTestStopSafepoint; } bool evaluate_at_safepoint() const { return false; } void doit() { _running->signal(); _test_complete->wait(); } }; @@ -67,7 +67,7 @@ class VMThreadBlocker : public JavaThread { static void blocker_thread_entry(JavaThread* thread, TRAPS) { VMThreadBlocker* t = static_cast(thread); - VM_StopSafepoint ss(&t->_ready, &t->_unblock); + VM_GTestStopSafepoint ss(&t->_ready, &t->_unblock); VMThread::execute(&ss); } -- GitLab From 091aff92e2213bfe0de79b3561a7613ab77e24b6 Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Mon, 31 Jan 2022 13:43:35 +0000 Subject: [PATCH 339/564] 8278908: [macOS] Unexpected text normalization on pasting from clipboard Reviewed-by: serb, aivanov --- .../macosx/classes/sun/lwawt/macosx/CDataTransferer.java | 5 ----- .../UnicodeTransferTest/UnicodeTransferTest.java | 8 ++------ 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDataTransferer.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDataTransferer.java index 0ea70549d43..e6a16ed670f 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDataTransferer.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDataTransferer.java @@ -33,8 +33,6 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.net.URL; import java.nio.charset.Charset; -import java.text.Normalizer; -import java.text.Normalizer.Form; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -165,9 +163,6 @@ public class CDataTransferer extends DataTransferer { // regular string that allows to translate data to target represantation // class by base method format = CF_STRING; - } else if (format == CF_STRING) { - String src = new String(bytes, UTF_8); - bytes = Normalizer.normalize(src, Form.NFC).getBytes(UTF_8); } return super.translateBytes(bytes, flavor, format, transferable); diff --git a/test/jdk/java/awt/datatransfer/UnicodeTransferTest/UnicodeTransferTest.java b/test/jdk/java/awt/datatransfer/UnicodeTransferTest/UnicodeTransferTest.java index 3a7ea0c5995..7dba15b5a1f 100644 --- a/test/jdk/java/awt/datatransfer/UnicodeTransferTest/UnicodeTransferTest.java +++ b/test/jdk/java/awt/datatransfer/UnicodeTransferTest/UnicodeTransferTest.java @@ -25,7 +25,7 @@ /* @test @key headful - @bug 4718897 + @bug 4718897 8278908 @summary tests that a Unicode string can be transferred between JVMs. @author das@sparc.spb.su area=datatransfer @library ../../regtesthelpers/process @@ -35,7 +35,6 @@ import java.awt.datatransfer.*; import java.awt.*; -import java.text.Normalizer; import test.java.awt.regtesthelpers.process.ProcessResults; import test.java.awt.regtesthelpers.process.ProcessCommunicator; @@ -77,10 +76,7 @@ class Util { buf.append(0x20); } } - // On OS X the unicode string is normalized but the clipboard, - // so we need to use normalized strings as well to be able to - // check the result - testString = Normalizer.normalize(buf.toString(), Normalizer.Form.NFC); + testString = buf.toString(); } public static String getTestString() { -- GitLab From bdda43e066b8da0ebf9a8ef2f843eabb230f0800 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Mon, 31 Jan 2022 16:01:18 +0000 Subject: [PATCH 340/564] 8280705: Parallel: Full gc mark stack draining should prefer to make work available to other threads Reviewed-by: ayang, mli --- .../share/gc/parallel/psCompactionManager.cpp | 18 +++++++++++++++--- .../share/gc/parallel/psCompactionManager.hpp | 1 + .../share/gc/parallel/psParallelCompact.cpp | 12 +++++------- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/src/hotspot/share/gc/parallel/psCompactionManager.cpp b/src/hotspot/share/gc/parallel/psCompactionManager.cpp index 3a7fc8ae758..c6bb7bf1e99 100644 --- a/src/hotspot/share/gc/parallel/psCompactionManager.cpp +++ b/src/hotspot/share/gc/parallel/psCompactionManager.cpp @@ -113,12 +113,24 @@ ParCompactionManager::gc_thread_compaction_manager(uint index) { return _manager_array[index]; } +bool ParCompactionManager::transfer_from_overflow_stack(ObjArrayTask& task) { + while (_objarray_stack.pop_overflow(task)) { + if (!_objarray_stack.try_push_to_taskqueue(task)) { + return true; + } + } + return false; +} + void ParCompactionManager::follow_marking_stacks() { do { - // Drain the overflow stack first, to allow stealing from the marking stack. + // First, try to move tasks from the overflow stack into the shared buffer, so + // that other threads can steal. Otherwise process the overflow stack first. oop obj; while (marking_stack()->pop_overflow(obj)) { - follow_contents(obj); + if (!marking_stack()->try_push_to_taskqueue(obj)) { + follow_contents(obj); + } } while (marking_stack()->pop_local(obj)) { follow_contents(obj); @@ -126,7 +138,7 @@ void ParCompactionManager::follow_marking_stacks() { // Process ObjArrays one at a time to avoid marking stack bloat. ObjArrayTask task; - if (_objarray_stack.pop_overflow(task) || _objarray_stack.pop_local(task)) { + if (transfer_from_overflow_stack(task) || _objarray_stack.pop_local(task)) { follow_array((objArrayOop)task.obj(), task.index()); } } while (!marking_stacks_empty()); diff --git a/src/hotspot/share/gc/parallel/psCompactionManager.hpp b/src/hotspot/share/gc/parallel/psCompactionManager.hpp index 4299f7e4c02..0cb5d33e0f5 100644 --- a/src/hotspot/share/gc/parallel/psCompactionManager.hpp +++ b/src/hotspot/share/gc/parallel/psCompactionManager.hpp @@ -97,6 +97,7 @@ class ParCompactionManager : public CHeapObj { static void initialize(ParMarkBitMap* mbm); + bool transfer_from_overflow_stack(ObjArrayTask& task); protected: // Array of task queues. Needed by the task terminator. static RegionTaskQueueSet* region_task_queues() { return _region_task_queues; } diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.cpp b/src/hotspot/share/gc/parallel/psParallelCompact.cpp index 4657975b1bc..bc080814122 100644 --- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp +++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp @@ -1984,17 +1984,15 @@ void steal_marking_work(TaskTerminator& terminator, uint worker_id) { ParCompactionManager* cm = ParCompactionManager::gc_thread_compaction_manager(worker_id); - oop obj = NULL; - ObjArrayTask task; do { - while (ParCompactionManager::steal_objarray(worker_id, task)) { + oop obj = NULL; + ObjArrayTask task; + if (ParCompactionManager::steal_objarray(worker_id, task)) { cm->follow_array((objArrayOop)task.obj(), task.index()); - cm->follow_marking_stacks(); - } - while (ParCompactionManager::steal(worker_id, obj)) { + } else if (ParCompactionManager::steal(worker_id, obj)) { cm->follow_contents(obj); - cm->follow_marking_stacks(); } + cm->follow_marking_stacks(); } while (!terminator.offer_termination()); } -- GitLab From dcc666d53d66e87c11c0c39858b36d40299b7de6 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Mon, 31 Jan 2022 16:51:10 +0000 Subject: [PATCH 341/564] 8280139: Report more detailed statistics about task stealing in task queue stats Reviewed-by: kbarrett, iwalulya --- src/hotspot/share/gc/shared/taskqueue.cpp | 31 ++++++---- src/hotspot/share/gc/shared/taskqueue.hpp | 47 +++++++++++++--- .../share/gc/shared/taskqueue.inline.hpp | 56 ++++++++++++------- 3 files changed, 95 insertions(+), 39 deletions(-) diff --git a/src/hotspot/share/gc/shared/taskqueue.cpp b/src/hotspot/share/gc/shared/taskqueue.cpp index 2ed1c613bc8..1a11a536683 100644 --- a/src/hotspot/share/gc/shared/taskqueue.cpp +++ b/src/hotspot/share/gc/shared/taskqueue.cpp @@ -34,7 +34,9 @@ #if TASKQUEUE_STATS const char * const TaskQueueStats::_names[last_stat_id] = { - "qpush", "qpop", "qpop-s", "qattempt", "qsteal", "opush", "omax" + "push", "pop", "pop-slow", + "st-attempt", "st-empty", "st-ctdd", "st-success", "st-ctdd-max", "st-biasdrop", + "ovflw-push", "ovflw-max" }; TaskQueueStats & TaskQueueStats::operator +=(const TaskQueueStats & addend) @@ -86,20 +88,29 @@ void TaskQueueStats::print(outputStream* stream, unsigned int width) const // quiescent; they do not hold at arbitrary times. void TaskQueueStats::verify() const { - assert(get(push) == get(pop) + get(steal), - "push=" SIZE_FORMAT " pop=" SIZE_FORMAT " steal=" SIZE_FORMAT, - get(push), get(pop), get(steal)); + assert(get(push) == get(pop) + get(steal_success), + "push=%zu pop=%zu steal=%zu", + get(push), get(pop), get(steal_success)); assert(get(pop_slow) <= get(pop), - "pop_slow=" SIZE_FORMAT " pop=" SIZE_FORMAT, + "pop_slow=%zu pop=%zu", get(pop_slow), get(pop)); - assert(get(steal) <= get(steal_attempt), - "steal=" SIZE_FORMAT " steal_attempt=" SIZE_FORMAT, - get(steal), get(steal_attempt)); + assert(get(steal_empty) <= get(steal_attempt), + "steal_empty=%zu steal_attempt=%zu", + get(steal_empty), get(steal_attempt)); + assert(get(steal_contended) <= get(steal_attempt), + "steal_contended=%zu steal_attempt=%zu", + get(steal_contended), get(steal_attempt)); + assert(get(steal_success) <= get(steal_attempt), + "steal_success=%zu steal_attempt=%zu", + get(steal_success), get(steal_attempt)); + assert(get(steal_empty) + get(steal_contended) + get(steal_success) == get(steal_attempt), + "steal_empty=%zu steal_contended=%zu steal_success=%zu steal_attempt=%zu", + get(steal_empty), get(steal_contended), get(steal_success), get(steal_attempt)); assert(get(overflow) == 0 || get(push) != 0, - "overflow=" SIZE_FORMAT " push=" SIZE_FORMAT, + "overflow=%zu push=%zu", get(overflow), get(push)); assert(get(overflow_max_len) == 0 || get(overflow) != 0, - "overflow_max_len=" SIZE_FORMAT " overflow=" SIZE_FORMAT, + "overflow_max_len=%zu overflow=%zu", get(overflow_max_len), get(overflow)); } #endif // ASSERT diff --git a/src/hotspot/share/gc/shared/taskqueue.hpp b/src/hotspot/share/gc/shared/taskqueue.hpp index dd2039ddf2a..d61326bd2fd 100644 --- a/src/hotspot/share/gc/shared/taskqueue.hpp +++ b/src/hotspot/share/gc/shared/taskqueue.hpp @@ -56,7 +56,11 @@ public: pop, // number of taskqueue pops pop_slow, // subset of taskqueue pops that were done slow-path steal_attempt, // number of taskqueue steal attempts - steal, // number of taskqueue steals + steal_empty, // number of empty taskqueues + steal_contended, // number of contended steals + steal_success, // number of successful steals + steal_max_contended_in_a_row, // maximum number of contended steals in a row + steal_bias_drop, // number of times the bias has been dropped overflow, // number of overflow pushes overflow_max_len, // max length of overflow stack last_stat_id @@ -68,8 +72,16 @@ public: inline void record_push() { ++_stats[push]; } inline void record_pop() { ++_stats[pop]; } inline void record_pop_slow() { record_pop(); ++_stats[pop_slow]; } - inline void record_steal_attempt() { ++_stats[steal_attempt]; } - inline void record_steal() { ++_stats[steal]; } + inline void record_steal_attempt(uint kind) { + ++_stats[steal_attempt]; + ++_stats[steal_empty + kind]; + } + inline void record_contended_in_a_row(uint in_a_row) { + if (_stats[steal_max_contended_in_a_row] < in_a_row) { + _stats[steal_max_contended_in_a_row] = in_a_row; + } + } + inline void record_bias_drop() { ++_stats[steal_bias_drop]; } inline void record_overflow(size_t new_length); TaskQueueStats & operator +=(const TaskQueueStats & addend); @@ -81,9 +93,9 @@ public: // Print the specified line of the header (does not include a line separator). static void print_header(unsigned int line, outputStream* const stream = tty, - unsigned int width = 10); + unsigned int width = 11); // Print the statistics (does not include a line separator). - void print(outputStream* const stream = tty, unsigned int width = 10) const; + void print(outputStream* const stream = tty, unsigned int width = 11) const; DEBUG_ONLY(void verify() const;) @@ -268,6 +280,16 @@ public: // in GenericTaskQueue. uint max_elems() const { return N - 2; } + // The result of a pop_global operation. The value order of this must correspond + // to the order in the corresponding TaskQueueStats StatId. + enum class PopResult : uint { + Empty = 0, // Queue has been empty. t is undefined. + Contended = 1, // Contention prevented successful retrieval, queue most likely contains elements. t is undefined. + Success = 2 // Successfully retrieved an element, t contains it. + }; + + TASKQUEUE_STATS_ONLY(void record_steal_attempt(PopResult kind) { stats.record_steal_attempt((uint)kind); }) + TASKQUEUE_STATS_ONLY(TaskQueueStats stats;) }; @@ -328,6 +350,8 @@ protected: using TaskQueueSuper::assert_not_underflow; public: + typedef typename TaskQueueSuper::PopResult PopResult; + using TaskQueueSuper::max_elems; using TaskQueueSuper::size; @@ -357,7 +381,7 @@ public: // Like pop_local(), but uses the "global" end of the queue (the least // recently pushed). - bool pop_global(E& t); + PopResult pop_global(E& t); // Delete any resource associated with the queue. ~GenericTaskQueue(); @@ -387,7 +411,10 @@ public: void set_last_stolen_queue_id(uint id) { _last_stolen_queue_id = id; } uint last_stolen_queue_id() const { return _last_stolen_queue_id; } bool is_last_stolen_queue_id_valid() const { return _last_stolen_queue_id != InvalidQueueId; } - void invalidate_last_stolen_queue_id() { _last_stolen_queue_id = InvalidQueueId; } + void invalidate_last_stolen_queue_id() { + TASKQUEUE_STATS_ONLY(stats.record_bias_drop();) + _last_stolen_queue_id = InvalidQueueId; + } }; // OverflowTaskQueue is a TaskQueue that also includes an overflow stack for @@ -447,12 +474,16 @@ template class GenericTaskQueueSet: public TaskQueueSetSuperImpl { public: typedef typename T::element_type E; + typedef typename T::PopResult PopResult; private: uint _n; T** _queues; - bool steal_best_of_2(uint queue_num, E& t); + // Attempts to steal an element from a foreign queue (!= queue_num), setting + // the result in t. Validity of this value and the return value is the same + // as for the last pop_global() operation. + PopResult steal_best_of_2(uint queue_num, E& t); public: GenericTaskQueueSet(uint n); diff --git a/src/hotspot/share/gc/shared/taskqueue.inline.hpp b/src/hotspot/share/gc/shared/taskqueue.inline.hpp index 1b47c4193d9..f544a24d536 100644 --- a/src/hotspot/share/gc/shared/taskqueue.inline.hpp +++ b/src/hotspot/share/gc/shared/taskqueue.inline.hpp @@ -254,7 +254,7 @@ bool OverflowTaskQueue::pop_overflow(E& t) // reads elems[oldAge.top]. The owner's bottom == the thief's oldAge.top. // (4) Thief will discard the read value, because its cmpxchg of age will fail. template -bool GenericTaskQueue::pop_global(E& t) { +typename GenericTaskQueue::PopResult GenericTaskQueue::pop_global(E& t) { Age oldAge = age_relaxed(); // Architectures with non-multi-copy-atomic memory model require a @@ -275,7 +275,7 @@ bool GenericTaskQueue::pop_global(E& t) { uint localBot = bottom_acquire(); uint n_elems = clean_size(localBot, oldAge.top()); if (n_elems == 0) { - return false; + return PopResult::Empty; } t = _elems[oldAge.top()]; @@ -289,7 +289,7 @@ bool GenericTaskQueue::pop_global(E& t) { // Note that using "bottom" here might fail, since a pop_local might // have decremented it. assert_not_underflow(localBot, newAge.top()); - return resAge == oldAge; + return resAge == oldAge ? PopResult::Success : PopResult::Contended; } inline int randomParkAndMiller(int *seed0) { @@ -316,10 +316,10 @@ int GenericTaskQueue::next_random_queue_id() { return randomParkAndMiller(&_seed); } -template bool -GenericTaskQueueSet::steal_best_of_2(uint queue_num, E& t) { +template +typename GenericTaskQueueSet::PopResult GenericTaskQueueSet::steal_best_of_2(uint queue_num, E& t) { + T* const local_queue = queue(queue_num); if (_n > 2) { - T* const local_queue = _queues[queue_num]; uint k1 = queue_num; if (local_queue->is_last_stolen_queue_id_valid()) { @@ -336,21 +336,23 @@ GenericTaskQueueSet::steal_best_of_2(uint queue_num, E& t) { k2 = local_queue->next_random_queue_id() % _n; } // Sample both and try the larger. - uint sz1 = _queues[k1]->size(); - uint sz2 = _queues[k2]->size(); + uint sz1 = queue(k1)->size(); + uint sz2 = queue(k2)->size(); uint sel_k = 0; - bool suc = false; + PopResult suc = PopResult::Empty; if (sz2 > sz1) { sel_k = k2; - suc = _queues[k2]->pop_global(t); + suc = queue(k2)->pop_global(t); + TASKQUEUE_STATS_ONLY(local_queue->record_steal_attempt(suc);) } else if (sz1 > 0) { sel_k = k1; - suc = _queues[k1]->pop_global(t); + suc = queue(k1)->pop_global(t); + TASKQUEUE_STATS_ONLY(local_queue->record_steal_attempt(suc);) } - if (suc) { + if (suc == PopResult::Success) { local_queue->set_last_stolen_queue_id(sel_k); } else { local_queue->invalidate_last_stolen_queue_id(); @@ -360,21 +362,33 @@ GenericTaskQueueSet::steal_best_of_2(uint queue_num, E& t) { } else if (_n == 2) { // Just try the other one. uint k = (queue_num + 1) % 2; - return _queues[k]->pop_global(t); + PopResult res = queue(k)->pop_global(t); + TASKQUEUE_STATS_ONLY(local_queue->record_steal_attempt(res);) + return res; } else { assert(_n == 1, "can't be zero."); - return false; + TASKQUEUE_STATS_ONLY(local_queue->record_steal_attempt(PopResult::Empty);) + return PopResult::Empty; } } -template bool -GenericTaskQueueSet::steal(uint queue_num, E& t) { - assert(queue_num < _n, "index out of range."); - for (uint i = 0; i < 2 * _n; i++) { - TASKQUEUE_STATS_ONLY(queue(queue_num)->stats.record_steal_attempt()); - if (steal_best_of_2(queue_num, t)) { - TASKQUEUE_STATS_ONLY(queue(queue_num)->stats.record_steal()); +template +bool GenericTaskQueueSet::steal(uint queue_num, E& t) { + uint const num_retries = 2 * _n; + + TASKQUEUE_STATS_ONLY(uint contended_in_a_row = 0;) + for (uint i = 0; i < num_retries; i++) { + PopResult sr = steal_best_of_2(queue_num, t); + if (sr == PopResult::Success) { return true; + } else if (sr == PopResult::Contended) { + TASKQUEUE_STATS_ONLY( + contended_in_a_row++; + queue(queue_num)->stats.record_contended_in_a_row(contended_in_a_row); + ) + } else { + assert(sr == PopResult::Empty, "must be"); + TASKQUEUE_STATS_ONLY(contended_in_a_row = 0;) } } return false; -- GitLab From 993a2488ef42b4c63a7e342c12bba8af8e3fab40 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Mon, 31 Jan 2022 16:52:28 +0000 Subject: [PATCH 342/564] 8280450: Add task queue printing to STW Full GCs Reviewed-by: ayang, sjohanss --- src/hotspot/share/gc/g1/g1FullCollector.cpp | 4 ++++ src/hotspot/share/gc/parallel/psParallelCompact.cpp | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/hotspot/share/gc/g1/g1FullCollector.cpp b/src/hotspot/share/gc/g1/g1FullCollector.cpp index dd20a099919..37c1e1476eb 100644 --- a/src/hotspot/share/gc/g1/g1FullCollector.cpp +++ b/src/hotspot/share/gc/g1/g1FullCollector.cpp @@ -294,6 +294,10 @@ void G1FullCollector::phase1_mark_live_objects() { } scope()->tracer()->report_object_count_after_gc(&_is_alive); +#if TASKQUEUE_STATS + oop_queue_set()->print_and_reset_taskqueue_stats("Oop Queue"); + array_queue_set()->print_and_reset_taskqueue_stats("ObjArrayOop Queue"); +#endif } void G1FullCollector::phase2_prepare_compaction() { diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.cpp b/src/hotspot/share/gc/parallel/psParallelCompact.cpp index bc080814122..d415de47ca5 100644 --- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp +++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp @@ -2116,6 +2116,10 @@ void PSParallelCompact::marking_phase(ParallelOldTracer *gc_tracer) { } _gc_tracer.report_object_count_after_gc(is_alive_closure()); +#if TASKQUEUE_STATS + ParCompactionManager::oop_task_queues()->print_and_reset_taskqueue_stats("Oop Queue"); + ParCompactionManager::_objarray_task_queues->print_and_reset_taskqueue_stats("ObjArrayOop Queue"); +#endif } class PSAdjustTask final : public WorkerTask { -- GitLab From 319b77492f78a08b7b9488c73876b027c3076c76 Mon Sep 17 00:00:00 2001 From: Yumin Qi Date: Mon, 31 Jan 2022 19:27:59 +0000 Subject: [PATCH 343/564] 8277101: jcmd VM.cds dynamic_dump should not regenerate holder classes Reviewed-by: iklam, ccheung --- src/hotspot/share/cds/dynamicArchive.cpp | 6 +++--- src/hotspot/share/cds/metaspaceShared.cpp | 8 +++++--- src/hotspot/share/cds/metaspaceShared.hpp | 4 ++-- .../cds/appcds/jcmd/JCmdTestDynamicDump.java | 13 ++++++++++++- 4 files changed, 22 insertions(+), 9 deletions(-) diff --git a/src/hotspot/share/cds/dynamicArchive.cpp b/src/hotspot/share/cds/dynamicArchive.cpp index eb99176405f..0ff6a017fed 100644 --- a/src/hotspot/share/cds/dynamicArchive.cpp +++ b/src/hotspot/share/cds/dynamicArchive.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, 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 @@ -384,7 +384,7 @@ void DynamicArchive::check_for_dynamic_dump() { void DynamicArchive::prepare_for_dump_at_exit() { EXCEPTION_MARK; ResourceMark rm(THREAD); - MetaspaceShared::link_shared_classes(THREAD); + MetaspaceShared::link_shared_classes(false/*not from jcmd*/, THREAD); if (HAS_PENDING_EXCEPTION) { log_error(cds)("Dynamic dump has failed"); log_error(cds)("%s: %s", PENDING_EXCEPTION->klass()->external_name(), @@ -400,7 +400,7 @@ void DynamicArchive::dump_for_jcmd(const char* archive_name, TRAPS) { assert(UseSharedSpaces && RecordDynamicDumpInfo, "already checked in arguments.cpp"); assert(ArchiveClassesAtExit == nullptr, "already checked in arguments.cpp"); assert(DynamicDumpSharedSpaces, "already checked by check_for_dynamic_dump() during VM startup"); - MetaspaceShared::link_shared_classes(CHECK); + MetaspaceShared::link_shared_classes(true/*from jcmd*/, CHECK); dump(archive_name, THREAD); } diff --git a/src/hotspot/share/cds/metaspaceShared.cpp b/src/hotspot/share/cds/metaspaceShared.cpp index 5070f7bf39a..ca2e4ecacde 100644 --- a/src/hotspot/share/cds/metaspaceShared.cpp +++ b/src/hotspot/share/cds/metaspaceShared.cpp @@ -642,8 +642,10 @@ bool MetaspaceShared::link_class_for_cds(InstanceKlass* ik, TRAPS) { return res; } -void MetaspaceShared::link_shared_classes(TRAPS) { - LambdaFormInvokers::regenerate_holder_classes(CHECK); +void MetaspaceShared::link_shared_classes(bool jcmd_request, TRAPS) { + if (!jcmd_request) { + LambdaFormInvokers::regenerate_holder_classes(CHECK); + } // Collect all loaded ClassLoaderData. CollectCLDClosure collect_cld(THREAD); @@ -775,7 +777,7 @@ void MetaspaceShared::preload_and_dump_impl(TRAPS) { // were not explicitly specified in the classlist. E.g., if an interface implemented by class K // fails verification, all other interfaces that were not specified in the classlist but // are implemented by K are not verified. - link_shared_classes(CHECK); + link_shared_classes(false/*not from jcmd*/, CHECK); log_info(cds)("Rewriting and linking classes: done"); #if INCLUDE_CDS_JAVA_HEAP diff --git a/src/hotspot/share/cds/metaspaceShared.hpp b/src/hotspot/share/cds/metaspaceShared.hpp index 74077d0fff0..c7d64d7de0c 100644 --- a/src/hotspot/share/cds/metaspaceShared.hpp +++ b/src/hotspot/share/cds/metaspaceShared.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022, 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 @@ -133,7 +133,7 @@ public: } static bool try_link_class(JavaThread* current, InstanceKlass* ik); - static void link_shared_classes(TRAPS) NOT_CDS_RETURN; + static void link_shared_classes(bool jcmd_request, TRAPS) NOT_CDS_RETURN; static bool link_class_for_cds(InstanceKlass* ik, TRAPS) NOT_CDS_RETURN_(false); static bool may_be_eagerly_linked(InstanceKlass* ik) NOT_CDS_RETURN_(false); diff --git a/test/hotspot/jtreg/runtime/cds/appcds/jcmd/JCmdTestDynamicDump.java b/test/hotspot/jtreg/runtime/cds/appcds/jcmd/JCmdTestDynamicDump.java index 72cb5c24d9a..61ec6325854 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/jcmd/JCmdTestDynamicDump.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/jcmd/JCmdTestDynamicDump.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022, 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,6 +117,17 @@ public class JCmdTestDynamicDump extends JCmdTestDumpBase { throw new RuntimeException("The JCmdTestLingeredApp should not start up!"); } } + // Test dynamic dump with -Xlog:cds to check lambda invoker class regeneration + print2ln(test_count++ + " Test dynamic dump with -Xlog:cds to check lambda invoker class regeneration"); + app = createLingeredApp("-cp", allJars, "-XX:+RecordDynamicDumpInfo", "-Xlog:cds", + "-XX:SharedArchiveFile=" + archiveFile); + pid = app.getPid(); + test(null, pid, noBoot, EXPECT_PASS, DYNAMIC_MESSAGES); + String stdout = app.getProcessStdout(); + if (stdout.contains("Regenerate MethodHandle Holder classes...")) { + throw new RuntimeException("jcmd VM.cds dynamic_dump should not regenerate MethodHandle Holder classes"); + } + app.stopApp(); } // Dump a static archive, not using TestCommon.dump(...), we do not take jtreg args. -- GitLab From f991891b0ba7a3767d2abd85ab9b2d284dc3d013 Mon Sep 17 00:00:00 2001 From: Xue-Lei Andrew Fan Date: Mon, 31 Jan 2022 20:25:50 +0000 Subject: [PATCH 344/564] 8280949: Correct the references for the Java Security Standard Algorithm Names specification Reviewed-by: mullan --- .../classes/javax/net/ssl/SSLEngine.java | 22 +++++++-------- .../classes/javax/net/ssl/SSLParameters.java | 28 +++++++++---------- .../javax/net/ssl/SSLServerSocket.java | 22 +++++++-------- .../javax/net/ssl/SSLServerSocketFactory.java | 14 +++++----- .../classes/javax/net/ssl/SSLSocket.java | 22 +++++++-------- .../javax/net/ssl/SSLSocketFactory.java | 14 +++++----- 6 files changed, 61 insertions(+), 61 deletions(-) diff --git a/src/java.base/share/classes/javax/net/ssl/SSLEngine.java b/src/java.base/share/classes/javax/net/ssl/SSLEngine.java index b3007b2a9a1..f60ab53f34e 100644 --- a/src/java.base/share/classes/javax/net/ssl/SSLEngine.java +++ b/src/java.base/share/classes/javax/net/ssl/SSLEngine.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, 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 @@ -920,9 +920,9 @@ public abstract class SSLEngine { * The returned array includes cipher suites from the list of standard * cipher suite names in the - * JSSE Cipher Suite Names section of the Java Cryptography - * Architecture Standard Algorithm Name Documentation, and may also - * include other cipher suites that the provider supports. + * JSSE Cipher Suite Names section of the Java Security Standard + * Algorithm Names Specification, and may also include other cipher + * suites that the provider supports. * * @return an array of cipher suite names * @see #getEnabledCipherSuites() @@ -946,9 +946,9 @@ public abstract class SSLEngine { * The returned array includes cipher suites from the list of standard * cipher suite names in the - * JSSE Cipher Suite Names section of the Java Cryptography - * Architecture Standard Algorithm Name Documentation, and may also - * include other cipher suites that the provider supports. + * JSSE Cipher Suite Names section of the Java Security Standard + * Algorithm Names Specification, and may also include other cipher + * suites that the provider supports. * * @return an array of cipher suite names * @see #getSupportedCipherSuites() @@ -968,10 +968,10 @@ public abstract class SSLEngine { * Note that the standard list of cipher suite names may be found in the * - * JSSE Cipher Suite Names section of the Java Cryptography - * Architecture Standard Algorithm Name Documentation. Providers - * may support cipher suite names not found in this list or might not - * use the recommended name for a certain cipher suite. + * JSSE Cipher Suite Names section of the Java Security Standard + * Algorithm Names Specification. Providers may support cipher suite + * names not found in this list or might not use the recommended name + * for a certain cipher suite. *

    * See {@link #getEnabledCipherSuites()} for more information * on why a specific cipher suite may never be used on a engine. diff --git a/src/java.base/share/classes/javax/net/ssl/SSLParameters.java b/src/java.base/share/classes/javax/net/ssl/SSLParameters.java index ae1889198bf..83b83c84270 100644 --- a/src/java.base/share/classes/javax/net/ssl/SSLParameters.java +++ b/src/java.base/share/classes/javax/net/ssl/SSLParameters.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2022, 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 @@ -111,9 +111,9 @@ public class SSLParameters { * {@code setCipherSuites(cipherSuites);}. Note that the * standard list of cipher suite names may be found in the - * JSSE Cipher Suite Names section of the Java Cryptography - * Architecture Standard Algorithm Name Documentation. Providers - * may support cipher suite names not found in this list. + * JSSE Cipher Suite Names section of the Java Security Standard + * Algorithm Names Specification. Providers may support cipher suite + * names not found in this list. * * @param cipherSuites the array of ciphersuites (or null) */ @@ -131,9 +131,9 @@ public class SSLParameters { * Note that the standard list of cipher suite names may be found in the * - * JSSE Cipher Suite Names section of the Java Cryptography - * Architecture Standard Algorithm Name Documentation. Providers - * may support cipher suite names not found in this list. + * JSSE Cipher Suite Names section of the Java Security Standard + * Algorithm Names Specification. Providers may support cipher suite + * names not found in this list. * * @param cipherSuites the array of ciphersuites (or null) * @param protocols the array of protocols (or null) @@ -154,9 +154,9 @@ public class SSLParameters { * The returned array includes cipher suites from the list of standard * cipher suite names in the - * JSSE Cipher Suite Names section of the Java Cryptography - * Architecture Standard Algorithm Name Documentation, and may also - * include other cipher suites that the provider supports. + * JSSE Cipher Suite Names section of the Java Security Standard + * Algorithm Names Specification, and may also include other cipher suites + * that the provider supports. * * @return a copy of the array of ciphersuites or null if none * have been set. @@ -171,10 +171,10 @@ public class SSLParameters { * @param cipherSuites the array of ciphersuites (or null). Note that the * standard list of cipher suite names may be found in the - * JSSE Cipher Suite Names section of the Java Cryptography - * Architecture Standard Algorithm Name Documentation. Providers - * may support cipher suite names not found in this list or might not - * use the recommended name for a certain cipher suite. + * JSSE Cipher Suite Names section of the Java Security Standard + * Algorithm Names Specification. Providers may support cipher suite + * names not found in this list or might not use the recommended name + * for a certain cipher suite. */ public void setCipherSuites(String[] cipherSuites) { this.cipherSuites = clone(cipherSuites); diff --git a/src/java.base/share/classes/javax/net/ssl/SSLServerSocket.java b/src/java.base/share/classes/javax/net/ssl/SSLServerSocket.java index 00a8bed19f0..20d7e7af676 100644 --- a/src/java.base/share/classes/javax/net/ssl/SSLServerSocket.java +++ b/src/java.base/share/classes/javax/net/ssl/SSLServerSocket.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -197,9 +197,9 @@ public abstract class SSLServerSocket extends ServerSocket { * The returned array includes cipher suites from the list of standard * cipher suite names in the - * JSSE Cipher Suite Names section of the Java Cryptography - * Architecture Standard Algorithm Name Documentation, and may also - * include other cipher suites that the provider supports. + * JSSE Cipher Suite Names section of the Java Security Standard + * Algorithm Names Specification, and may also include other cipher + * suites that the provider supports. * * @return an array of cipher suites enabled * @see #getSupportedCipherSuites() @@ -223,10 +223,10 @@ public abstract class SSLServerSocket extends ServerSocket { * Note that the standard list of cipher suite names may be found in the * - * JSSE Cipher Suite Names section of the Java Cryptography - * Architecture Standard Algorithm Name Documentation. Providers - * may support cipher suite names not found in this list or might not - * use the recommended name for a certain cipher suite. + * JSSE Cipher Suite Names section of the Java Security Standard + * Algorithm Names Specification. Providers may support cipher suite + * names not found in this list or might not use the recommended name + * for a certain cipher suite. *

    * SSLSockets returned from accept() * inherit this setting. @@ -253,9 +253,9 @@ public abstract class SSLServerSocket extends ServerSocket { * The returned array includes cipher suites from the list of standard * cipher suite names in the - * JSSE Cipher Suite Names section of the Java Cryptography - * Architecture Standard Algorithm Name Documentation, and may also - * include other cipher suites that the provider supports. + * JSSE Cipher Suite Names section of the Java Security Standard + * Algorithm Names Specification, and may also include other cipher + * suites that the provider supports. * * @return an array of cipher suite names * @see #getEnabledCipherSuites() diff --git a/src/java.base/share/classes/javax/net/ssl/SSLServerSocketFactory.java b/src/java.base/share/classes/javax/net/ssl/SSLServerSocketFactory.java index e66bd11239d..68c09c02a6f 100644 --- a/src/java.base/share/classes/javax/net/ssl/SSLServerSocketFactory.java +++ b/src/java.base/share/classes/javax/net/ssl/SSLServerSocketFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -87,9 +87,9 @@ public abstract class SSLServerSocketFactory extends ServerSocketFactory { * The returned array includes cipher suites from the list of standard * cipher suite names in the - * JSSE Cipher Suite Names section of the Java Cryptography - * Architecture Standard Algorithm Name Documentation, and may also - * include other cipher suites that the provider supports. + * JSSE Cipher Suite Names section of the Java Security Standard + * Algorithm Names Specification, and may also include other cipher + * suites that the provider supports. * * @see #getSupportedCipherSuites() * @return array of the cipher suites enabled by default @@ -108,9 +108,9 @@ public abstract class SSLServerSocketFactory extends ServerSocketFactory { * The returned array includes cipher suites from the list of standard * cipher suite names in the - * JSSE Cipher Suite Names section of the Java Cryptography - * Architecture Standard Algorithm Name Documentation, and may also - * include other cipher suites that the provider supports. + * JSSE Cipher Suite Names section of the Java Security Standard + * Algorithm Names Specification, and may also include other cipher + * suites that the provider supports. * * @return an array of cipher suite names * @see #getDefaultCipherSuites() diff --git a/src/java.base/share/classes/javax/net/ssl/SSLSocket.java b/src/java.base/share/classes/javax/net/ssl/SSLSocket.java index 84e5be716fe..b2c912c3b65 100644 --- a/src/java.base/share/classes/javax/net/ssl/SSLSocket.java +++ b/src/java.base/share/classes/javax/net/ssl/SSLSocket.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -327,9 +327,9 @@ public abstract class SSLSocket extends Socket * The returned array includes cipher suites from the list of standard * cipher suite names in the - * JSSE Cipher Suite Names section of the Java Cryptography - * Architecture Standard Algorithm Name Documentation, and may also - * include other cipher suites that the provider supports. + * JSSE Cipher Suite Names section of the Java Security Standard + * Algorithm Names Specification, and may also include other cipher + * suites that the provider supports. * * @return an array of cipher suite names * @see #getEnabledCipherSuites() @@ -353,9 +353,9 @@ public abstract class SSLSocket extends Socket * The returned array includes cipher suites from the list of standard * cipher suite names in the - * JSSE Cipher Suite Names section of the Java Cryptography - * Architecture Standard Algorithm Name Documentation, and may also - * include other cipher suites that the provider supports. + * JSSE Cipher Suite Names section of the Java Security Standard + * Algorithm Names Specification, and may also include other cipher + * suites that the provider supports. * * @return an array of cipher suite names * @see #getSupportedCipherSuites() @@ -375,10 +375,10 @@ public abstract class SSLSocket extends Socket * Note that the standard list of cipher suite names may be found in the * - * JSSE Cipher Suite Names section of the Java Cryptography - * Architecture Standard Algorithm Name Documentation. Providers - * may support cipher suite names not found in this list or might not - * use the recommended name for a certain cipher suite. + * JSSE Cipher Suite Names section of the Java Security Standard + * Algorithm Names Specification. Providers may support cipher suite + * names not found in this list or might not use the recommended name + * for a certain cipher suite. *

    * See {@link #getEnabledCipherSuites()} for more information * on why a specific ciphersuite may never be used on a connection. diff --git a/src/java.base/share/classes/javax/net/ssl/SSLSocketFactory.java b/src/java.base/share/classes/javax/net/ssl/SSLSocketFactory.java index 6db6d740750..dd10f422f3e 100644 --- a/src/java.base/share/classes/javax/net/ssl/SSLSocketFactory.java +++ b/src/java.base/share/classes/javax/net/ssl/SSLSocketFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -113,9 +113,9 @@ public abstract class SSLSocketFactory extends SocketFactory { * The returned array includes cipher suites from the list of standard * cipher suite names in the - * JSSE Cipher Suite Names section of the Java Cryptography - * Architecture Standard Algorithm Name Documentation, and may also - * include other cipher suites that the provider supports. + * JSSE Cipher Suite Names section of the Java Security Standard + * Algorithm Names Specification, and may also include other cipher suites + * that the provider supports. * * @see #getSupportedCipherSuites() * @return array of the cipher suites enabled by default @@ -132,9 +132,9 @@ public abstract class SSLSocketFactory extends SocketFactory { * The returned array includes cipher suites from the list of standard * cipher suite names in the - * JSSE Cipher Suite Names section of the Java Cryptography - * Architecture Standard Algorithm Name Documentation, and may also - * include other cipher suites that the provider supports. + * JSSE Cipher Suite Names section of the Java Security Standard + * Algorithm Names Specification, and may also include other cipher suites + * that the provider supports. * * @see #getDefaultCipherSuites() * @return an array of cipher suite names -- GitLab From 39165613aa0430861e361a33a4925b85ea24fff1 Mon Sep 17 00:00:00 2001 From: Ioi Lam Date: Mon, 31 Jan 2022 21:48:32 +0000 Subject: [PATCH 345/564] 8280543: Update the "java" and "jcmd" tool specification for CDS Reviewed-by: hseigel, sspitsyn, ccheung --- src/java.base/share/man/java.1 | 599 +++++++-------------------------- src/jdk.jcmd/share/man/jcmd.1 | 20 +- 2 files changed, 145 insertions(+), 474 deletions(-) diff --git a/src/java.base/share/man/java.1 b/src/java.base/share/man/java.1 index 9ef865ec657..6a1532a8981 100644 --- a/src/java.base/share/man/java.1 +++ b/src/java.base/share/man/java.1 @@ -1,4 +1,4 @@ -.\" Copyright (c) 1994, 2021, Oracle and/or its affiliates. All rights reserved. +.\" Copyright (c) 1994, 2022, 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 @@ -1090,8 +1090,10 @@ Require using shared class data, otherwise fail. .RS .PP \f[B]Note:\f[R] The \f[CB]\-Xshare:on\f[R] option is used for testing -purposes only and may cause intermittent failures due to the use of -address space layout randomization by the operation system. +purposes only. +It may cause the VM to unexpectedly exit during start\-up when the CDS +archive cannot be used (for example, when certain VM parameters are +changed, or when a different JDK is used). This option should not be used in production environments. .RE .TP @@ -5256,293 +5258,83 @@ who\[aq]s running the application, because administrators by default don\[aq]t have the privilege to lock pages in memory. .SH APPLICATION CLASS DATA SHARING .PP -Application Class Data Sharing (AppCDS) extends class data sharing (CDS) -to enable application classes to be placed in a shared archive. +Application Class Data Sharing (AppCDS) stores classes used by your +applications in an archive file. +Since these classes are stored in a format that can be loaded very +quickly (compared to classes stored in a JAR file), AppCDS can improve +the start\-up time of your applications. +In addition, AppCDS can reduce the runtime memory footprint by sharing +parts of these classes across multiple processes. .PP -In addition to the core library classes, AppCDS supports \f[B]Class Data -Sharing\f[R] -[https://docs.oracle.com/en/java/javase/12/vm/class\-data\-sharing.html#GUID\-7EAA3411\-8CF0\-4D19\-BD05\-DF5E1780AA91] -from the following locations: -.IP \[bu] 2 -Platform classes from the runtime image -.IP \[bu] 2 -Application classes from the runtime image -.IP \[bu] 2 -Application classes from the class path -.IP \[bu] 2 -Application classes from the module path +Classes in the CDS archive are stored in an optimized format that\[aq]s +about 2 to 5 times larger than classes stored in JAR files or the JDK +runtime image. +Therefore, it\[aq]s a good idea to archive only those classes that are +actually used by your application. +These usually are just a small portion of all available classes. +For example, your application may use only a few APIs provided by a +large library. +.SS Using CDS Archives .PP -Archiving application classes provides better start up time at runtime. -When running multiple JVM processes, AppCDS also reduces the runtime -footprint with memory sharing for read\-only metadata. +By default, in most JDK distributions, unless \f[CB]\-Xshare:off\f[R] is +specified, the JVM starts up with a default CDS archive, which is +usually located in \f[CB]JAVA_HOME/lib/server/classes.jsa\f[R] (or +\f[CB]JAVA_HOME\\bin\\server\\classes.jsa\f[R] on Windows). +This archive contains about 1300 core library classes that are used by +most applications. .PP -CDS/AppCDS supports archiving classes from JAR files only. +To use CDS for the exact set of classes used by your application, you +can use the \f[CB]\-XX:SharedArchiveFile\f[R] option, which has the +general form: +.RS .PP -Prior to JDK 11, a non\-empty directory was reported as a fatal error in -the following conditions: -.IP \[bu] 2 -For base CDS, a non\-empty directory cannot exist in the -\f[CB]\-Xbootclasspath/a\f[R] path +\f[CB]\-XX:SharedArchiveFile=:\f[R] +.RE .IP \[bu] 2 -With \f[CB]\-XX:+UseAppCDS\f[R], a non\-empty directory could not exist in -the \f[CB]\-Xbootclasspath/a\f[R] path, class path, and module path. -.PP -In JDK 11 and later, \f[CB]\-XX:+UseAppCDS\f[R] is obsolete and the -behavior for a non\-empty directory is based on the class types in the -classlist. -A non\-empty directory is reported as a fatal error in the following -conditions: +The \f[CB]\f[R] overrides the default CDS archive. .IP \[bu] 2 -If application classes or platform classes are not loaded, dump time -only reports an error if a non\-empty directory exists in -\f[CB]\-Xbootclasspath/a\f[R] path +The \f[CB]\f[R] provides additional classes that can be +loaded on top of those in the \f[CB]\f[R]. .IP \[bu] 2 -If application classes or platform classes are loaded, dump time reports -an error for a non\-empty directory that exists in -\f[CB]\-Xbootclasspath/a\f[R] path, class path, or module path -.PP -In JDK 11 and later, using -\f[CB]\-XX:DumpLoadedClassList=\f[R]\f[I]class_list_file\f[R] results a -generated classlist with all classes (both system library classes and -application classes) included. -You no longer have to specify \f[CB]\-XX:+UseAppCDS\f[R] with -\f[CB]\-XX:DumpLoadedClassList\f[R] to produce a complete class list. +On Windows, the above path delimiter \f[CB]:\f[R] should be replaced with +\f[CB];\f[R] .PP -In JDK 11 and later, because \f[CB]UseAppCDS\f[R] is obsolete, -\f[CB]SharedArchiveFile\f[R] becomes a product flag by default. -Specifying \f[CB]+UnlockDiagnosticVMOptions\f[R] for -\f[CB]SharedArchiveFile\f[R] is no longer needed in any configuration. +(The names "static" and "dyanmic" are used for historical reasons. +The only significance is that the "static" archive is loaded first and +the "dynamic" archive is loaded second). .PP -Class Data Sharing (CDS)/AppCDS does not support archiving array classes -in a class list. -When an array in the class list is encountered, CDS dump time gives the -explicit error message: +The JVM can use up to two archives. +To use only a single \f[CB]\f[R], you can omit the +\f[CB]\f[R] portion: .RS .PP -\f[CB]Preload\ Warning:\ Cannot\ find\f[R] \f[I]array_name\f[R] +\f[CB]\-XX:SharedArchiveFile=\f[R] .RE .PP -Although an array in the class list is not allowed, some array classes -can still be created at CDS/AppCDS dump time. -Those arrays are created during the execution of the Java code used by -the Java class loaders (\f[CB]PlatformClassLoader\f[R] and the system -class loader) to load classes at dump time. -The created arrays are archived with the rest of the loaded classes. -.SS Extending Class Data Sharing to Support the Module Path -.PP -In JDK 11, Class Data Sharing (CDS) has been improved to support -archiving classes from the module path. -.IP \[bu] 2 -To create a CDS archive using the \f[CB]\-\-module\-path\f[R] VM option, -use the following command line syntax: -.RS 2 -.RS -.PP -\f[CB]java\ \-Xshare:dump\ \-XX:SharedClassListFile=\f[R]\f[I]class_list_file\f[R] -\f[CB]\-XX:SharedArchiveFile=\f[R]\f[I]shared_archive_file\f[R] -\f[CB]\-\-module\-path=\f[R]\f[I]path_to_modular_jar\f[R] \f[CB]\-m\f[R] -\f[I]module_name\f[R] -.RE -.RE -.IP \[bu] 2 -To run with a CDS archive using the \f[CB]\-\-module\-path\f[R] VM option, -use the following the command line syntax: -.RS 2 +For convenience, the \f[CB]\f[R] records the location of +the \f[CB]\f[R]. +Therefore, you can omit the \f[CB]\f[R] by saying only: .RS .PP -\f[CB]java\ \-XX:SharedArchiveFile=\f[R]\f[I]shared_archive_file\f[R] -\f[CB]\-\-module\-path=\f[R]\f[I]path_to_modular_jar\f[R] \f[CB]\-m\f[R] -\f[I]module_name\f[R] -.RE +\f[CB]\-XX:SharedArchiveFile=\f[R] .RE +.SS Creating CDS Archives .PP -The following table describes how the VM options related to module paths -can be used along with the \f[CB]\-Xshare\f[R] option. -.PP -.TS -tab(@); -l l l. -T{ -Option -T}@T{ -\-Xshare:dump -T}@T{ -\-Xshare:{on,auto} -T} -_ -T{ -\f[CB]\-\-module\-path\f[R][1] \f[I]mp\f[R] -T}@T{ -Allowed -T}@T{ -Allowed[2] -T} -T{ -\f[CB]\-\-module\f[R] -T}@T{ -Allowed -T}@T{ -Allowed -T} -T{ -\f[CB]\-\-add\-module\f[R] -T}@T{ -Allowed -T}@T{ -Allowed -T} -T{ -\f[CB]\-\-upgrade\-module\-path\f[R][3] -T}@T{ -Disallowed (exits if specified) -T}@T{ -Allowed (disables CDS) -T} -T{ -\f[CB]\-\-patch\-module\f[R][4] -T}@T{ -Disallowed (exits if specified) -T}@T{ -Allowed (disables CDS) -T} -T{ -\f[CB]\-\-limit\-modules\f[R][5] -T}@T{ -Disallowed (exits if specified) -T}@T{ -Allowed (disables CDS) -T} -.TE -.PP -[1] Although there are two ways of specifying a module in a -\f[CB]\-\-module\-path\f[R], that is, modular JAR or exploded module, only -modular JARs are supported. -.PP -[2] Different \f[I]mp\f[R] can be specified during dump time versus run -time. -If an archived class K was loaded from \f[CB]mp1.jar\f[R] at dump time, -but changes in \f[I]mp\f[R] cause it to be available from a different -\f[CB]mp2.jar\f[R] at run time, then the archived version of K will be -disregarded at run time; K will be loaded dynamically. -.PP -[3] Currently, only two system modules are upgradeable -(\f[CB]java.compiler\f[R] and \f[CB]jdk.internal.vm.compiler\f[R]). -However, these modules are seldom upgraded in production software. -.PP -[4] As documented in JEP 261, using \f[CB]\-\-patch\-module\f[R] is -strongly discouraged for production use. -.PP -[5] \f[CB]\-\-limit\-modules\f[R] is intended for testing purposes. -It is seldom used in production software. -.PP -If \f[CB]\-\-upgrade\-module\-path\f[R], \f[CB]\-\-patch\-module\f[R], or -\f[CB]\-\-limit\-modules\f[R] is specified at dump time, an error will be -printed and the JVM will exit. -For example, if the \f[CB]\-\-limit\-modules\f[R] option is specified at -dump time, the user will see the following error: -.IP -.nf -\f[CB] -Error\ occurred\ during\ initialization\ of\ VM -Cannot\ use\ the\ following\ option\ when\ dumping\ the\ shared\ archive:\ \-\-limit\-modules -\f[R] -.fi -.PP -If \f[CB]\-\-upgrade\-module\-path\f[R], \f[CB]\-\-patch\-module\f[R], or -\f[CB]\-\-limit\-modules\f[R] is specified at run time, a warning message -will be printed indicating that CDS is disabled. -For example, if the \f[CB]\-\-limit\-modules\f[R] options is specified at -run time, the user will see the following warning: -.IP -.nf -\f[CB] -Java\ HotSpot(TM)\ 64\-Bit\ Server\ VM\ warning:\ CDS\ is\ disabled\ when\ the\ \-\-limit\-modules\ option\ is\ specified. -\f[R] -.fi -.PP -Several other noteworthy things include: -.IP \[bu] 2 -Any valid combinations of \f[CB]\-cp\f[R] and \f[CB]\-\-module\-path\f[R] -are supported. -.IP \[bu] 2 -A non\-empty directory in the module path causes a fatal error. -The user will see the following error messages: -.RS 2 -.IP -.nf -\f[CB] -Error:\ non\-empty\ directory\ \ Hint:\ enable\ \-Xlog:class+path=info\ to\ diagnose\ the\ failure\ Error\ occurred\ during\ initialization\ of\ VM\ Cannot\ have\ non\-empty\ directory\ in\ paths -\f[R] -.fi -.RE +CDS archives can be created with several methods: .IP \[bu] 2 -Unlike the class path, there\[aq]s no restriction that the module path -at dump time must be equal to or be a prefix of the module path at run -time. +\f[CB]\-Xshare:dump\f[R] .IP \[bu] 2 -The archive is invalidated if an existing JAR in the module path is -updated after archive generation. +\f[CB]\-XX:ArchiveClassesAtExit\f[R] .IP \[bu] 2 -Removing a JAR from the module path does not invalidate the shared -archive. -Archived classes from the removed JAR are not used at runtime. -.SS Dynamic CDS archive -.PP -Dynamic CDS archive extends AppCDS to allow archiving of classes when a -Java application exits. -It improves the usability of AppCDS by eliminating the trial run step -for creating a class list for each application. -The archived classes include all loaded application classes and library -classes that are not present in the default CDS archive which is -included in the JDK. -.PP -A base archive is required when creating a dynamic archive. -If the base archive is not specified, the default CDS archive is used as -the base archive. +\f[CB]jcmd\ VM.cds\f[R] .PP -To create a dynamic CDS archive with the default CDS archive as the base -archive, just add the -\f[CB]\-XX:ArchiveClassesAtExit=\f[R] option to the -command line for running the Java application. +One common operation in all these methods is a "trial run", where you +run the application once to determine the classes that should be stored +in the archive. +.SS Creating a Static CDS Archive File with \-Xshare:dump .PP -If the default CDS archive does not exist, the VM will exit with the -following error: -.IP -.nf -\f[CB] -ArchiveClassesAtExit\ not\ supported\ when\ base\ CDS\ archive\ is\ not\ loaded -\f[R] -.fi -.PP -To run the Java application using a dynamic CDS archive, just add the -\f[CB]\-XX:SharedArchiveFile=\f[R] option to the command -line for running the Java application. -.PP -The base archive is not required to be specified in the command line. -The base archive information, including its name and full path, will be -retrieved from the dynamic archive header. -Note that the user could also use the \f[CB]\-XX:SharedArchiveFile\f[R] -option for specifying a regular AppCDS archive. -Therefore, the specified archive in the \f[CB]\-XX:SharedArchiveFile\f[R] -option could be either a regular or dynamic archive. -During VM start up the specified archive header will be read. -If \f[CB]\-XX:SharedArchiveFile\f[R] refers to a regular archive, then the -behavior will be unchanged. -If \f[CB]\-XX:SharedArchiveFile\f[R] refers to a dynamic archive, the VM -will retrieve the base archive location from the dynamic archive. -If the dynamic archive was created with the default CDS archive, then -the current default CDS archive will be used, and will be found relative -to the current run time environment. -.PP -Please refer to \f[B]JDK\-8221706\f[R] -[https://bugs.openjdk.java.net/browse/JDK\-8221706] for details on error -checking during dynamic CDS archive dump time and run time. -.SS Creating a Shared Archive File and Using It to Run an Application -.SS AppCDS archive -.PP -The following steps create a shared archive file that contains all the -classes used by the \f[CB]test.Hello\f[R] application. -The last step runs the application with the shared archive file. +The following steps create a static CDS archive file that contains all +the classes used by the \f[CB]test.Hello\f[R] application. .IP "1." 3 Create a list of all classes used by the \f[CB]test.Hello\f[R] application. @@ -5554,23 +5346,20 @@ contains a list of all classes used by this application: \f[CB]java\ \-Xshare:off\ \-XX:DumpLoadedClassList=hello.classlist\ \-cp\ hello.jar\ test.Hello\f[R] .RE .PP -Note that the classpath specified by the \f[CB]\-cp\f[R] parameter must -contain only JAR files. +The classpath specified by the \f[CB]\-cp\f[R] parameter must contain only +JAR files. .RE .IP "2." 3 -Create a shared archive, named \f[CB]hello.jsa\f[R], that contains all the +Create a static archive, named \f[CB]hello.jsa\f[R], that contains all the classes in \f[CB]hello.classlist\f[R]: .RS 4 .RS .PP \f[CB]java\ \-Xshare:dump\ \-XX:SharedArchiveFile=hello.jsa\ \-XX:SharedClassListFile=hello.classlist\ \-cp\ hello.jar\f[R] .RE -.PP -Note that the classpath used at archive creation time must be the same -as (or a prefix of) the classpath used at run time. .RE .IP "3." 3 -Run the application \f[CB]test.Hello\f[R] with the shared archive +Run the application \f[CB]test.Hello\f[R] with the archive \f[CB]hello.jsa\f[R]: .RS 4 .RS @@ -5584,23 +5373,27 @@ using the class contained in the \f[CB]hello.jsa\f[R] shared archive: .RS 4 .RS .PP -\f[CB]java\ \-XX:SharedArchiveFile=hello.jsa\ \-cp\ hello.jar\ \-verbose:class\ test.Hello\f[R] +\f[CB]java\ \-XX:SharedArchiveFile=hello.jsa\ \-cp\ hello.jar\ \-Xlog:class+load\ test.Hello\f[R] .RE .PP The output of this command should contain the following text: -.IP -.nf -\f[CB] -Loaded\ test.Hello\ from\ shared\ objects\ file\ by\ sun/misc/Launcher$AppClassLoader -\f[R] -.fi +.RS +.PP +\f[CB][info][class,load]\ test.Hello\ source:\ shared\ objects\ file\f[R] +.RE .RE -.SS Dynamic CDS archive +.SS Creating a Dynamic CDS Archive File with \-XX:SharedArchiveFile +.PP +Advantages of dynamic CDS archives are: +.IP \[bu] 2 +They usually use less disk space, since they don\[aq]t need to store the +classes that are already in the static archive. +.IP \[bu] 2 +They are created with one fewer step than the comparable static archive. .PP The following steps create a dynamic CDS archive file that contains the -classes used by the \f[CB]test.Hello\f[R] application and are not included -in the default CDS archive. -The second step runs the application with the dynamic CDS archive. +classes that are used by the \f[CB]test.Hello\f[R] application, excluding +those that are already in the default CDS archive. .IP "1." 3 Create a dynamic CDS archive, named \f[CB]hello.jsa\f[R], that contains all the classes in \f[CB]hello.jar\f[R] loaded by the application @@ -5610,9 +5403,6 @@ all the classes in \f[CB]hello.jar\f[R] loaded by the application .PP \f[CB]java\ \-XX:ArchiveClassesAtExit=hello.jsa\ \-cp\ hello.jar\ Hello\f[R] .RE -.PP -Note that the classpath used at archive creation time must be the same -as (or a prefix of) the classpath used at run time. .RE .IP "2." 3 Run the application \f[CB]test.Hello\f[R] with the shared archive @@ -5628,218 +5418,87 @@ Run the application \f[CB]test.Hello\f[R] with the shared archive the \f[CB]test.Hello\f[R] application is using the class contained in the \f[CB]hello.jsa\f[R] shared archive. .PP -To automate the above steps 1 and 2, one can write a script such as the -following: -.IP -.nf -\f[CB] -\ \ \ \ ARCHIVE=hello.jsa -\ \ \ \ if\ test\ \-f\ $ARCHIVE;\ then -\ \ \ \ \ \ \ \ FLAG="\-XX:SharedArchiveFile=$ARCHIVE" -\ \ \ \ else -\ \ \ \ \ \ \ \ FLAG="\-XX:ArchiveClassesAtExit=$ARCHIVE" -\ \ \ \ fi -\ \ \ \ $JAVA_HOME/bin/java\ \-cp\ hello.jar\ $FLAG\ test.Hello -\f[R] -.fi -.PP -Like an AppCDS archive, the archive needs to be re\-generated if the -Java version has changed. -The above script could be adjusted to account for the Java version as -follows: -.IP -.nf -\f[CB] -\ \ \ \ ARCHIVE=hello.jsa -\ \ \ \ VERSION=foo.version -\ \ \ \ if\ test\ \-f\ $ARCHIVE\ \-a\ \-f\ $VERSION\ &&\ cmp\ \-s\ $VERSION\ $JAVA_HOME/release;\ then -\ \ \ \ \ \ \ \ FLAG="\-XX:SharedArchiveFile=$ARCHIVE" -\ \ \ \ else -\ \ \ \ \ \ \ \ FLAG="\-XX:ArchiveClassesAtExit=$ARCHIVE" -\ \ \ \ \ \ \ \ cp\ \-f\ $JAVA_HOME/release\ $VERSION -\ \ \ \ fi -\ \ \ \ $JAVA_HOME/bin/java\ \-cp\ hello.jar\ $FLAG\ test.Hello -\f[R] -.fi -.PP -Currently, we don\[aq]t support concurrent dumping operations to the -same CDS archive. -Care should be taken to avoid multiple writers to the same CDS archive. -.PP -The user could also create a dynamic CDS archive with a specific base -archive, e.g. -named as \f[CB]base.jsa\f[R] as follows: +It\[aq]s also possible to create a dynamic CDS archive with a +non\-default static CDS archive. +E.g., .RS .PP \f[CB]java\ \-XX:SharedArchiveFile=base.jsa\ \-XX:ArchiveClassesAtExit=hello.jsa\ \-cp\ hello.jar\ Hello\f[R] .RE .PP -To run the application using the dynamic CDS archive \f[CB]hello.jsa\f[R] -and a specific base CDS archive \f[CB]base.jsa\f[R]: +To run the application using this dynamic CDS archive: .RS .PP \f[CB]java\ \-XX:SharedArchiveFile=base.jsa:hello.jsa\ \-cp\ hello.jar\ Hello\f[R] .RE .PP -Note that on Windows, the above path delimiter \f[CB]:\f[R] should be -replaced with \f[CB];\f[R]. -.PP -The above command for specifying a base archive is useful if the base -archive used for creating the dynamic archive has been moved. -Normally, just specifying the dynamic archive should be sufficient since -the base archive info can be retrieved from the dynamic archive header. -.SS Sharing a Shared Archive Across Multiple Application Processes -.PP -You can share the same archive file across multiple applications -processes. -This reduces memory usage because the archive is memory\-mapped into the -address space of the processes. -The operating system automatically shares the read\-only pages across -these processes. -.PP -The following steps demonstrate how to create a common archive that can -be shared by different applications. -Classes from \f[CB]common.jar\f[R], \f[CB]hello.jar\f[R] and \f[CB]hi.jar\f[R] -are archived in the \f[CB]common.jsa\f[R] because they are all in the -classpath during the archiving step (step 3). -.PP -To include classes from \f[CB]hello.jar\f[R] and \f[CB]hi.jar\f[R], the -\f[CB]\&.jar\f[R] files must be added to the classpath specified by the -\f[CB]\-cp\f[R] parameter. -.IP "1." 3 -Create a list of all classes used by the \f[CB]Hello\f[R] application and -another list for the \f[CB]Hi\f[R] application: -.RS 4 -.RS -.PP -\f[CB]java\ \-XX:DumpLoadedClassList=hello.classlist\ \-cp\ common.jar:hello.jar\ Hello\f[R] -.RE -.RS -.PP -\f[CB]java\ \-XX:DumpLoadedClassList=hi.classlist\ \-cp\ common.jar:hi.jar\ Hi\f[R] -.RE -.RE -.IP "2." 3 -Create a single list of classes used by all the applications that will -share the shared archive file. -.RS 4 +(On Windows, the above path delimiter \f[CB]:\f[R] should be replaced with +\f[CB];\f[R]) .PP -\f[B]Linux and macOS\f[R] The following commands combine the files -\f[CB]hello.classlist\f[R] and \f[CB]hi.classlist\f[R] into one file, -\f[CB]common.classlist\f[R]: +As mention above, the name of the static archive can be skipped: .RS .PP -\f[CB]cat\ hello.classlist\ hi.classlist\ >\ common.classlist\f[R] +\f[CB]java\ \-XX:SharedArchiveFile=hello.jsa\ \-cp\ hello.jar\ Hello\f[R] .RE +.SS Creating CDS Archive Files with jcmd .PP -\f[B]Windows\f[R] The following commands combine the files -\f[CB]hello.classlist\f[R] and \f[CB]hi.classlist\f[R] into one file, -\f[CB]common.classlist\f[R]: -.RS +The previous two sections require you to modify the application\[aq]s +start\-up script in order to create a CDS archive. +Sometimes this could be difficult, for example, if the application\[aq]s +class path is set up by complex routines. .PP -\f[CB]type\ hello.classlist\ hi.classlist\ >\ common.classlist\f[R] -.RE -.RE -.IP "3." 3 -Create a shared archive named \f[CB]common.jsa\f[R] that contains all the -classes in \f[CB]common.classlist\f[R]: -.RS 4 +The \f[CB]jcmd\ VM.cds\f[R] command provides a less intrusive way for +creating a CDS archive by connecting to a running JVM process. +You can create either a static: .RS .PP -\f[CB]java\ \-Xshare:dump\ \-XX:SharedArchiveFile=common.jsa\ \-XX:SharedClassListFile=common.classlist\ \-cp\ common.jar:hello.jar:hi.jar\f[R] +\f[CB]jcmd\ \ VM.cds\ static_dump\ my_static_archive.jsa\f[R] .RE .PP -The classpath parameter used is the common class path prefix shared by -the \f[CB]Hello\f[R] and \f[CB]Hi\f[R] applications. -.RE -.IP "4." 3 -Run the \f[CB]Hello\f[R] and \f[CB]Hi\f[R] applications with the same shared -archive: -.RS 4 -.RS -.PP -\f[CB]java\ \-XX:SharedArchiveFile=common.jsa\ \-cp\ common.jar:hello.jar:hi.jar\ Hello\f[R] -.RE +or a dynamic archive: .RS .PP -\f[CB]java\ \-XX:SharedArchiveFile=common.jsa\ \-cp\ common.jar:hello.jar:hi.jar\ Hi\f[R] -.RE +\f[CB]jcmd\ \ VM.cds\ dynamic_dump\ my_dynamic_archive.jsa\f[R] .RE -.SS Specifying Additional Shared Data Added to an Archive File .PP -The \f[CB]SharedArchiveConfigFile\f[R] option is used to specify -additional shared data to add to the archive file. +To use the resulting archive file in a subsequent run of the application +without modifying the application\[aq]s start\-up script, you can use +the following technique: .RS .PP -\f[CB]\-XX:SharedArchiveConfigFile=\f[R]\f[I]shared_config_file\f[R] +\f[CB]env\ JAVA_TOOL_OPTIONS=\-XX:SharedArchiveFile=my_static_archive.jsa\ bash\ app_start.sh\f[R] .RE .PP -JDK 9 and later supports adding both symbols and string objects to an -archive for memory sharing when you have multiple JVM processes running -on the same host. -An example of this is having multiple JVM processes that use the same -set of Java EE classes. -When these common classes are loaded and used, new symbols and strings -may be created and added to the JVM\[aq]s internal "symbol" and "string" -tables. -At runtime, the symbols or string objects mapped from the archive file -can be shared across multiple JVM processes, resulting in a reduction of -overall memory usage. -In addition, archiving strings also provides added performance benefits -in both startup time and runtime execution. -.PP -In JDK 10 and later, CONSTANT_String entries in archived classes are -resolved to interned String objects at dump time, and all interned -String objects are archived. -However, even though all CONSTANT_String literals in all archived -classes are resolved, it might still beneficial to add additional -strings that are not string literals in class files, but are likely to -be used by your application at run time. -.PP -Symbol data should be generated by the \f[CB]jcmd\f[R] tool attaching to a -running JVM process. -See \f[B]jcmd\f[R]. -.PP -The following is an example of the symbol dumping command in -\f[CB]jcmd\f[R]: +Note: to use \f[CB]jcmd\ \ VM.cds\ dynamic_dump\f[R], the JVM process +identified by \f[CB]\f[R] must be started with +\f[CB]\-XX:+RecordDynamicDumpInfo\f[R], which can also be passed to the +application start\-up script with the same technique: .RS .PP -\f[CB]jcmd\f[R] \f[I]pid\f[R] \f[CB]VM.symboltable\ \-verbose\f[R] +\f[CB]env\ JAVA_TOOL_OPTIONS=\-XX:+RecordDynamicDumpInfo\ bash\ app_start.sh\f[R] .RE -.RS -.PP -\f[B]Note:\f[R] The first line (process ID) and the second line -(\f[CB]\@VERSION\ ...\f[R]) of this \f[CB]jcmd\f[R] output should be -excluded from the configuration file. -.RE -.SS Example of a Configuration File -.PP -The following is an example of a configuration file: -.IP -.nf -\f[CB] -VERSION:\ 1.0 -\@SECTION:\ Symbol -10\ \-1:\ linkMethod -\f[R] -.fi -.PP -In the configuration file example, the \f[CB]\@SECTION:\ Symbol\f[R] entry -uses the following format: -.RS -.PP -\f[I]length\f[R] \f[I]refcount\f[R]\f[CB]:\f[R] \f[I]symbol\f[R] -.RE -.PP -The \f[I]refcount\f[R] for a shared symbol is always \f[CB]\-1\f[R]. -.PP -\f[CB]\@SECTION\f[R] specifies the type of the section that follows it. -All data within the section must be the same type that\[aq]s specified -by \f[CB]\@SECTION\f[R]. -Different types of data can\[aq]t be mixed. -Multiple separated data sections for the same type specified by -different \f[CB]\@SECTION\f[R] are allowed within one -\f[CB]shared_config_file\f[R] . +.SS Restrictions on Class Path and Module Path +.IP \[bu] 2 +Neither the class path (\f[CB]\-classpath\f[R] and +\f[CB]\-Xbootclasspath/a\f[R]) nor the module path +(\f[CB]\-\-module\-path\f[R]) can contain non\-empty directories. +.IP \[bu] 2 +Only modular JAR files are supported in \f[CB]\-\-module\-path\f[R]. +Exploded modules are not supported. +.IP \[bu] 2 +The class path used at archive creation time must be the same as (or a +prefix of) the class path used at run time. +(There\[aq]s no such requirement for the module path.) +.IP \[bu] 2 +The CDS archive cannot be loaded if any JAR files in the class path or +module path are modified after the archive is generated. +.IP \[bu] 2 +If any of the VM options \f[CB]\-\-upgrade\-module\-path\f[R], +\f[CB]\-\-patch\-module\f[R] or \f[CB]\-\-limit\-modules\f[R] are specified, +CDS is disabled. +This means that the JVM will execute without loading any CDS archives. +In addition, if you try to create a CDS archive with any of these 3 +options specified, the JVM will report an error. .SH PERFORMANCE TUNING EXAMPLES .PP You can use the Java advanced runtime options to optimize the diff --git a/src/jdk.jcmd/share/man/jcmd.1 b/src/jdk.jcmd/share/man/jcmd.1 index 65adf880911..9342943ac2a 100644 --- a/src/jdk.jcmd/share/man/jcmd.1 +++ b/src/jdk.jcmd/share/man/jcmd.1 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. +.\" Copyright (c) 2012, 2022, 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 @@ -802,7 +802,8 @@ false) .RE .TP .B \f[CB]VM.cds\f[R] [\f[I]arguments\f[R]] -Dump a static or dynamic shared archive including all shareable classes. +Dumps a static or dynamic shared archive that includes all currently +loaded classes. .RS .PP Impact: Medium \-\-\- pause time depends on number of loaded classes @@ -811,11 +812,22 @@ Permission: \f[CB]java.lang.management.ManagementPermission(monitor)\f[R] .PP \f[I]arguments\f[R]: .IP \[bu] 2 -\f[CB]subcmd\f[R]: \f[CB]static_dump\f[R] | \f[CB]dynamic_dump\f[R] (STRING, -no default value) +\f[CB]subcmd\f[R]: must be either \f[CB]static_dump\f[R] or +\f[CB]dynamic_dump\f[R] (STRING, no default value) .IP \[bu] 2 \f[CB]filename\f[R]: (Optional) Name of the shared archive to be dumped (STRING, no default value) +.PP +If \f[CB]filename\f[R] is not specified, a default file name is chosen +using the pid of the target JVM process. +For example, java_pid1234_static.jsa, java_pid5678_dynamic.jsa, etc. +.PP +If \f[CB]filename\f[R] is not specified as an absolute path, the archive +file is created in a directory relative to the current directory of the +target JVM process. +.PP +If \f[CB]dynamic_dump\f[R] is specified, the target JVM must be started +with the JVM option \f[CB]\-XX:+RecordDynamicDumpInfo\f[R]. .RE .TP .B \f[CB]VM.classloaders\f[R] [\f[I]options\f[R]] -- GitLab From 74921e8422ce31a22516b279a00935b1917c089d Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Mon, 31 Jan 2022 22:45:16 +0000 Subject: [PATCH 346/564] 8280738: Minor cleanup for HtmlStyle Reviewed-by: hannesw --- .../formats/html/markup/HtmlStyle.java | 84 ++++++++++++------- 1 file changed, 56 insertions(+), 28 deletions(-) diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java index ad74b81eee5..8301e9b9255 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java @@ -48,20 +48,14 @@ import java.util.regex.Pattern; * or {@link javax.lang.model.element.Element "language model elements"}. * The usage is made explicit when it is not clear from the surrounding context. * + * @apiNote + * The stylized use of {@code editor-fold} comments and line comments (beginning {@code //}) + * is to support extracting details of declarations with external tools. Edit with care! + * * @see WhatWG: {@code class} attribute */ public enum HtmlStyle { - /** - * The class of the {@code div} element containing a snippet element. - */ - snippetContainer, - - /** - * The class of the {@code a} element to copy snippet content to the clipboard. - */ - snippetCopy, - // // // The following constants are used for the main navigation bar that appears in the @@ -324,17 +318,6 @@ public enum HtmlStyle { */ propertyDetails, - /** - * The class for the list containing the {@code @see} tags of an element. - */ - seeList, - - /** - * The class for the list containing the {@code @see} tags of an element - * when some of the tags have longer labels. - */ - seeListLong, - /** * The class for a {@code section} element containing details of the * serialized form of an element, on the "Serialized Form" page. @@ -391,6 +374,17 @@ public enum HtmlStyle { */ previewLabel, + /** + * The class for the list containing the {@code @see} tags of an element. + */ + seeList, + + /** + * The class for the list containing the {@code @see} tags of an element + * when some of the tags have longer labels. + */ + seeListLong, + // // @@ -844,6 +838,44 @@ public enum HtmlStyle { // + // + // + // The following constants are used for the contents of snippets. + // In addition, the translation of a snippet may use the class + // {@code language-LANG} where LANG is either specified explicitly + // by the "lang" attribute in a snippet tag, or can be inferred + // from the kind of an external snippet. + + /** + * The class of the {@code pre} element presenting a snippet. + */ + snippet, + + /** + * The class of the {@code div} element containing a snippet element. + */ + snippetContainer, + + /** + * The class of the UI element to copy snippet content to the clipboard. + */ + snippetCopy, + + /** + * The class of text highlighted with the type {@code bold}. + */ + bold, + + /** + * The class of text highlighted with the type {@code italic}. + */ + italic, + + /** + * The class of text highlighted with the type {@code highlighted}. + */ + highlighted, + // // // The following constants are used in various places across a variety of pages. @@ -908,7 +940,8 @@ public enum HtmlStyle { inheritedList, /** - * The class of an element that acts as a notification for an invalid tag. + * The class of an element that acts as a notification for an invalid tag + * or other invalid items. */ invalidTag, @@ -923,7 +956,7 @@ public enum HtmlStyle { memberNameLink, /** - * The class for a {@code dl} element containing serial UID information in + * The class of a {@code dl} element containing serial UID information in * the serialized form page. */ nameValue, @@ -964,11 +997,6 @@ public enum HtmlStyle { */ sourceLineNo, - /** - * The class of the {@code pre} element presenting a snippet. - */ - snippet, - /** * The class of an {@code a} element for a link to a class or interface. */ -- GitLab From ee3be0bb567f0e28fd3e920ef3685607d0a8d656 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Mon, 31 Jan 2022 22:47:46 +0000 Subject: [PATCH 347/564] 8280488: doclint reference checks withstand warning suppression Reviewed-by: darcy --- .../jdk/javadoc/internal/doclint/Checker.java | 25 +- .../jdk/javadoc/internal/doclint/DocLint.java | 18 ++ .../jdk/javadoc/internal/doclint/Env.java | 14 + .../doclint/resources/doclint.properties | 1 + .../tool/doclint/DocLintReferencesTest.java | 255 ++++++++++++++++++ 5 files changed, 311 insertions(+), 2 deletions(-) create mode 100644 test/langtools/jdk/javadoc/tool/doclint/DocLintReferencesTest.java diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/Checker.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/Checker.java index abf8c698bba..446757513a1 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/Checker.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/Checker.java @@ -41,6 +41,7 @@ import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; +import javax.lang.model.SourceVersion; import javax.lang.model.element.Element; import javax.lang.model.element.ElementKind; import javax.lang.model.element.ExecutableElement; @@ -952,11 +953,31 @@ public class Checker extends DocTreePathScanner { @Override @DefinedBy(Api.COMPILER_TREE) public Void visitReference(ReferenceTree tree, Void ignore) { Element e = env.trees.getElement(getCurrentPath()); - if (e == null) - env.messages.error(REFERENCE, tree, "dc.ref.not.found"); + if (e == null) { + reportBadReference(tree); + } return super.visitReference(tree, ignore); } + private void reportBadReference(ReferenceTree tree) { + if (!env.strictReferenceChecks) { + String refSig = tree.getSignature(); + int sep = refSig.indexOf("/"); + if (sep > 0) { + String moduleName = refSig.substring(0, sep); + if (SourceVersion.isName(moduleName)) { + Element m = env.elements.getModuleElement(moduleName); + if (m == null) { + env.messages.warning(REFERENCE, tree, "dc.ref.in.missing.module", moduleName); + return; + } + } + } + } + + env.messages.error(REFERENCE, tree, "dc.ref.not.found"); + } + @Override @DefinedBy(Api.COMPILER_TREE) public Void visitReturn(ReturnTree tree, Void ignore) { if (foundReturn) { diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/DocLint.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/DocLint.java index 1c4f3a3d650..9a1d0f2e4cc 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/DocLint.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/DocLint.java @@ -274,6 +274,14 @@ public class DocLint extends com.sun.tools.doclint.DocLint { // + /** + * Initialize DocLint for use with a {@code JavacTask}. + * {@link Env#strictReferenceChecks Strict reference checks} are not enabled by default. + * + * @param task the task + * @param args arguments to configure DocLint + * @param addTaskListener whether or not to register a {@code TaskListener} to invoke DocLint + */ public void init(JavacTask task, String[] args, boolean addTaskListener) { env = new Env(); env.init(task); @@ -319,9 +327,19 @@ public class DocLint extends com.sun.tools.doclint.DocLint { } } + /** + * Initialize DocLint with the given utility objects and arguments. + * {@link Env#strictReferenceChecks Strict reference checks} are enabled by default. + * + * @param trees the {@code DocTrees} utility class + * @param elements the {@code Elements} utility class + * @param types the {@code Types} utility class + * @param args arguments to configure DocLint + */ public void init(DocTrees trees, Elements elements, Types types, String... args) { env = new Env(); env.init(trees, elements, types); + env.strictReferenceChecks = true; processArgs(env, args); checker = new Checker(env); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/Env.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/Env.java index 01a0a867673..be13ca43fd1 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/Env.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/Env.java @@ -108,6 +108,20 @@ public class Env { Set includePackages; Set excludePackages; + /** + * How to handle bad references. + * + * If {@code false}, a reference into a module that is not + * in the module graph will just be reported as a warning. + * All other bad references will be reported as errors. + * This is the desired behavior for javac. + * + * If {@code true}, all bad references will be reported as + * errors. This is the desired behavior for javadoc. + * + */ + boolean strictReferenceChecks = false; + // Utility classes DocTrees trees; Elements elements; diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/resources/doclint.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/resources/doclint.properties index 091316f0e29..fbcb2c00881 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/resources/doclint.properties +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/resources/doclint.properties @@ -61,6 +61,7 @@ dc.no.alt.attr.for.image = no "alt" attribute for image dc.no.summary.or.caption.for.table=no caption for table dc.param.name.not.found = @param name not found dc.ref.not.found = reference not found +dc.ref.in.missing.module = module for reference not found: {0} dc.return.not.first = '{@return} not at beginning of description dc.service.not.found = service-type not found dc.tag.code.within.code = '{@code} within diff --git a/test/langtools/jdk/javadoc/tool/doclint/DocLintReferencesTest.java b/test/langtools/jdk/javadoc/tool/doclint/DocLintReferencesTest.java new file mode 100644 index 00000000000..ee316135e37 --- /dev/null +++ b/test/langtools/jdk/javadoc/tool/doclint/DocLintReferencesTest.java @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2022, 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 8280688 + * @summary doclint reference checks withstand warning suppression + * @library /tools/lib ../../lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + * jdk.javadoc/jdk.javadoc.internal.api + * jdk.javadoc/jdk.javadoc.internal.tool + * @build toolbox.JavacTask toolbox.JavadocTask toolbox.TestRunner toolbox.ToolBox + * @run main DocLintReferencesTest + */ + +import toolbox.JavacTask; +import toolbox.JavadocTask; +import toolbox.Task; +import toolbox.TestRunner; +import toolbox.ToolBox; + +import java.nio.file.Files; +import java.nio.file.Path; + +/** + * Combo test for how javac and javadoc handle {@code @see MODULE/TYPE} + * for different combinations of MODULE and TYPE, with and without + * {@code @SuppressWarnings("doclint") }. + * + * Generally, in javac, references to unknown elements are reported + * as suppressible warnings if the module is not resolved in the module graph. + * Otherwise, in both javac and javadoc, any issues with references + * are reported as errors. + * + * This allows references to other modules to appear in documentation comments + * without causing a hard error if the modules are not available at compile-time. + */ +public class DocLintReferencesTest extends TestRunner { + + public static void main(String... args) throws Exception { + DocLintReferencesTest t = new DocLintReferencesTest(); + t.runTests(); + } + + DocLintReferencesTest() { + super(System.err); + } + + private final ToolBox tb = new ToolBox(); + + enum SuppressKind { NO, YES } + enum ModuleKind { NONE, BAD, NOT_FOUND, GOOD } + enum TypeKind { NONE, BAD, NOT_FOUND, GOOD } + + @Test + public void comboTest () { + for (SuppressKind sk : SuppressKind.values() ) { + for (ModuleKind mk : ModuleKind.values() ) { + for (TypeKind tk: TypeKind.values() ) { + if (mk == ModuleKind.NONE && tk == TypeKind.NONE) { + continue; + } + + try { + test(sk, mk, tk); + } catch (Throwable e) { + error("Exception " + e); + } + } + } + } + } + + void test(SuppressKind sk, ModuleKind mk, TypeKind tk) throws Exception { + out.println(); + out.println("*** Test SuppressKind:" + sk + " ModuleKind: " + mk + " TypeKind: " + tk); + Path base = Path.of(sk + "-" + mk + "-" + tk); + + String sw = switch (sk) { + case NO -> ""; + case YES -> "@SuppressWarnings(\"doclint\")"; + }; + String m = switch (mk) { + case NONE -> ""; + case BAD -> "bad-name/"; + case NOT_FOUND -> "not.found/"; + case GOOD -> "java.base/"; + }; + String t = switch (tk) { + case NONE -> ""; + case BAD -> "bad-name"; + case NOT_FOUND -> "java.lang.NotFound"; + case GOOD -> "java.lang.Object"; + }; + + Path src = base.resolve("src"); + tb.writeJavaFiles(src, """ + package p; + /** + * Comment. + * @see #M##T# + */ + #SW# + public class C { + private C() { } + } + """ + .replace("#M#", m) + .replace("#T#", t) + .replace("#SW#", sw)); + + testJavac(sk, mk, tk, base, src); + testJavadoc(sk, mk, tk, base, src); + } + + void testJavac(SuppressKind sk, ModuleKind mk, TypeKind tk, Path base, Path src) throws Exception { + Files.createDirectories(base.resolve("classes")); + + out.println("javac:"); + try { + String s = predictOutput(sk, mk, tk, false); + Task.Expect e = s.isEmpty() ? Task.Expect.SUCCESS : Task.Expect.FAIL; + + String o = new JavacTask(tb) + .outdir(base.resolve("classes")) + .options("-Xdoclint:all/protected", "-Werror") + .files(tb.findJavaFiles(src)) + .run(e) + .writeAll() + .getOutput(Task.OutputKind.DIRECT); + + checkOutput(s, o); + + } catch (Throwable t) { + error("Error: " + t); + } + out.println(); + } + + void testJavadoc(SuppressKind sk, ModuleKind mk, TypeKind tk, Path base, Path src) throws Exception { + Files.createDirectories(base.resolve("api")); + + out.println("javadoc:"); + try { + String s = predictOutput(sk, mk, tk, true); + Task.Expect e = s.isEmpty() ? Task.Expect.SUCCESS : Task.Expect.FAIL; + + String o = new JavadocTask(tb) + .outdir(base.resolve("api")) + .options("-Xdoclint", "-Werror", "-quiet", "-sourcepath", src.toString(), "p") + .run(e) + .writeAll() + .getOutput(Task.OutputKind.DIRECT); + + checkOutput(s, o); + + } catch (Throwable t) { + error("Error: " + t); + } + out.println(); + } + + private static final String ERROR_UNEXPECTED_TEXT = "error: unexpected text"; + private static final String ERROR_REFERENCE_NOT_FOUND = "error: reference not found"; + private static final String WARNING_MODULE_FOR_REFERENCE_NOT_FOUND = "warning: module for reference not found: not.found"; + private static final String EMPTY = ""; + + /** + * Returns the expected diagnostic, if any, based on the parameters of the test case. + * + * The "interesting" cases are those for which the module name is not found, + * in which case an error for "reference not found" is reduced to warning, + * which may be suppressed. + * + * @param sk whether @SuppressWarnings is present of not + * @param mk the kind of module in the reference + * @param tk the kind of class or interface name in the reference + * @param strict whether all "not found" references are errors, + * or just warnings if the module name is not found + * @return a diagnostic string, or an empty string if no diagnostic should be generated + */ + String predictOutput(SuppressKind sk, ModuleKind mk, TypeKind tk, boolean strict) { + return switch (mk) { + case NONE -> switch(tk) { + case NONE -> throw new Error("should not happen"); // filtered out in combo loops + case BAD -> ERROR_UNEXPECTED_TEXT; + case NOT_FOUND -> ERROR_REFERENCE_NOT_FOUND; + case GOOD -> EMPTY; + }; + + case BAD -> ERROR_UNEXPECTED_TEXT; + + case NOT_FOUND -> switch(tk) { + case BAD -> ERROR_UNEXPECTED_TEXT; + case NONE, NOT_FOUND, GOOD -> strict + ? ERROR_REFERENCE_NOT_FOUND + : sk == SuppressKind.YES + ? EMPTY + : WARNING_MODULE_FOR_REFERENCE_NOT_FOUND; + }; + + case GOOD -> switch(tk) { + case BAD -> ERROR_UNEXPECTED_TEXT; + case NOT_FOUND -> ERROR_REFERENCE_NOT_FOUND; + case GOOD, NONE -> EMPTY; + }; + }; + } + + /** + * Checks the actual output against the expected string, generated by {@code predictError}. + * If the expected string is empty, the output should be empty. + * If the expected string is not empty, it should be present in the output. + * + * @param expect the expected string + * @param found the output + */ + void checkOutput(String expect, String found) { + if (expect.isEmpty()) { + if (found.isEmpty()) { + out.println("Output OK"); + } else { + error("unexpected output"); + } + } else { + if (found.contains(expect)) { + out.println("Output OK"); + } else { + error("expected output not found: " + expect); + } + } + + } +} -- GitLab From 96d0df72db277f127bd4c6b8c51bfc64d1c593e0 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Mon, 31 Jan 2022 22:54:18 +0000 Subject: [PATCH 348/564] 8272984: javadoc support for reproducible builds Reviewed-by: hannesw --- .../formats/html/HtmlConfiguration.java | 21 ++- .../formats/html/HtmlDocletWriter.java | 4 +- .../formats/html/IndexRedirectWriter.java | 4 +- .../formats/html/SourceToHTMLConverter.java | 4 +- .../doclets/formats/html/markup/Head.java | 19 ++- .../html/resources/standard.properties | 14 +- .../internal/doclets/toolkit/BaseOptions.java | 54 ++++++- .../doclet/testDateOption/TestDateOption.java | 147 ++++++++++++++++++ .../doclet/testXOption/TestXOption.java | 5 +- .../jdk/javadoc/tool/CheckManPageOptions.java | 4 +- 10 files changed, 255 insertions(+), 21 deletions(-) create mode 100644 test/langtools/jdk/javadoc/doclet/testDateOption/TestDateOption.java diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlConfiguration.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlConfiguration.java index 100ad33940b..a11ad5db044 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlConfiguration.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ package jdk.javadoc.internal.doclets.formats.html; +import java.time.ZonedDateTime; import java.util.ArrayList; import java.util.Date; import java.util.EnumSet; @@ -166,6 +167,11 @@ public class HtmlConfiguration extends BaseConfiguration { */ public final Set conditionalPages; + /** + * The build date, to be recorded in generated files. + */ + private ZonedDateTime buildDate; + /** * Constructs the full configuration needed by the doclet, including * the format-specific part, defined in this class, and the format-independent @@ -215,6 +221,7 @@ public class HtmlConfiguration extends BaseConfiguration { conditionalPages = EnumSet.noneOf(ConditionalPage.class); } + protected void initConfiguration(DocletEnvironment docEnv, Function resourceKeyMapper) { super.initConfiguration(docEnv, resourceKeyMapper); @@ -223,7 +230,6 @@ public class HtmlConfiguration extends BaseConfiguration { } private final Runtime.Version docletVersion; - public final Date startTime = new Date(); @Override public Runtime.Version getDocletVersion() { @@ -259,6 +265,10 @@ public class HtmlConfiguration extends BaseConfiguration { if (!options.validateOptions()) { return false; } + + ZonedDateTime zdt = options.date(); + buildDate = zdt != null ? zdt : ZonedDateTime.now(); + if (!getSpecifiedTypeElements().isEmpty()) { Map map = new HashMap<>(); PackageElement pkg; @@ -279,6 +289,13 @@ public class HtmlConfiguration extends BaseConfiguration { return true; } + /** + * {@return the date to be recorded in generated files} + */ + public ZonedDateTime getBuildDate() { + return buildDate; + } + /** * Decide the page which will appear first in the right-hand frame. It will * be "overview-summary.html" if "-overview" option is used or no diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java index 7efa7b85992..8934d547213 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2022, 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 @@ -453,7 +453,7 @@ public class HtmlDocletWriter { throws DocFileIOException { List additionalStylesheets = configuration.getAdditionalStylesheets(); additionalStylesheets.addAll(localStylesheets); - Head head = new Head(path, configuration.getDocletVersion(), configuration.startTime) + Head head = new Head(path, configuration.getDocletVersion(), configuration.getBuildDate()) .setTimestamp(!options.noTimestamp()) .setDescription(description) .setGenerator(getGenerator(getClass())) diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/IndexRedirectWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/IndexRedirectWriter.java index 3e169dab6f0..299e565a657 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/IndexRedirectWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/IndexRedirectWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, 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 @@ -74,7 +74,7 @@ public class IndexRedirectWriter extends HtmlDocletWriter { * @throws DocFileIOException if there is a problem generating the file */ private void generateIndexFile() throws DocFileIOException { - Head head = new Head(path, configuration.getDocletVersion(), configuration.startTime) + Head head = new Head(path, configuration.getDocletVersion(), configuration.getBuildDate()) .setTimestamp(!options.noTimestamp()) .setDescription("index redirect") .setGenerator(getGenerator(getClass())) diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SourceToHTMLConverter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SourceToHTMLConverter.java index 7bc1f96b648..4efa6a70d22 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SourceToHTMLConverter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SourceToHTMLConverter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2022, 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 @@ -232,7 +232,7 @@ public class SourceToHTMLConverter { * @param path the path for the file. */ private void writeToFile(Content body, DocPath path, TypeElement te) throws DocFileIOException { - Head head = new Head(path, configuration.getDocletVersion(), configuration.startTime) + Head head = new Head(path, configuration.getDocletVersion(), configuration.getBuildDate()) // .setTimestamp(!options.notimestamp) // temporary: compatibility! .setTitle(resources.getText("doclet.Window_Source_title")) // .setCharset(options.charset) // temporary: compatibility! diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Head.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Head.java index 975154b7d1d..adbd5ef09fd 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Head.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Head.java @@ -27,12 +27,14 @@ package jdk.javadoc.internal.doclets.formats.html.markup; import java.io.IOException; import java.io.Writer; -import java.text.SimpleDateFormat; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Date; import java.util.List; +import java.util.Locale; import jdk.javadoc.internal.doclets.toolkit.Content; import jdk.javadoc.internal.doclets.toolkit.util.DocPath; @@ -50,7 +52,7 @@ import jdk.javadoc.internal.doclets.toolkit.util.DocPaths; */ public class Head extends Content { private final Runtime.Version docletVersion; - private final Date generatedDate; + private final ZonedDateTime generatedDate; private final DocPath pathToRoot; private String title; private String charset; @@ -78,7 +80,7 @@ public class Head extends Content { * @param path the path for the file that will include this HEAD element * @param docletVersion the doclet version */ - public Head(DocPath path, Runtime.Version docletVersion, Date generatedDate) { + public Head(DocPath path, Runtime.Version docletVersion, ZonedDateTime generatedDate) { this.docletVersion = docletVersion; this.generatedDate = generatedDate; pathToRoot = path.parent().invert(); @@ -279,8 +281,8 @@ public class Head extends Content { } if (showTimestamp) { - SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); - tree.add(HtmlTree.META("dc.created", dateFormat.format(generatedDate))); + DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + tree.add(HtmlTree.META("dc.created", generatedDate.format(dateFormat))); } if (description != null) { @@ -309,11 +311,14 @@ public class Head extends Content { return tree; } - private Comment getGeneratedBy(boolean timestamp, Date now) { + + private Comment getGeneratedBy(boolean timestamp, ZonedDateTime buildDate) { String text = "Generated by javadoc"; // marker string, deliberately not localized text += " (" + docletVersion.feature() + ")"; if (timestamp) { - text += " on " + now; + DateTimeFormatter fmt = + DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss zzz yyyy").withLocale(Locale.US); + text += " on " + buildDate.format(fmt); } return new Comment(text); } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties index 8a511b8ca4f..285acb051fd 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2010, 2021, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2010, 2022, 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 @@ -169,6 +169,12 @@ doclet.systemPropertiesSummary=System Properties Summary doclet.Window_Source_title=Source code doclet.Window_Help_title=API Help +# 0: a date +doclet.Option_date_out_of_range=value for ''--date'' out of range: {0} + +# 0: a date +doclet.Option_date_not_valid=value for ''--date'' not valid: {0} + doclet.help.main_heading=\ JavaDoc Help doclet.help.navigation.head=\ @@ -420,6 +426,12 @@ doclet.usage.windowtitle.parameters=\ doclet.usage.windowtitle.description=\ Browser window title for the documentation +doclet.usage.date.parameters=\ + +doclet.usage.date.description=\ + Specifies the value to be used to timestamp the generated\n\ + pages, in ISO 8601 format + doclet.usage.doctitle.parameters=\ doclet.usage.doctitle.description=\ diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/BaseOptions.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/BaseOptions.java index 6445f4fc6a0..42110c4aa70 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/BaseOptions.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/BaseOptions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,8 +30,16 @@ import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.UnsupportedEncodingException; +import java.time.Instant; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; +import java.time.temporal.ChronoUnit; +import java.time.temporal.TemporalUnit; import java.util.ArrayList; import java.util.Arrays; +import java.util.Calendar; import java.util.Collections; import java.util.HashSet; import java.util.LinkedHashSet; @@ -82,6 +90,12 @@ public abstract class BaseOptions { */ private final LinkedHashSet> customTagStrs = new LinkedHashSet<>(); + /** + * Argument for command-line option {@code --date}. + * {@code null} if option not given. + */ + private ZonedDateTime date; + /** * Argument for command-line option {@code -d}. * Destination directory name, in which doclet will generate the entire @@ -338,6 +352,33 @@ public abstract class BaseOptions { } }, + new XOption(resources, "--date", 1) { + // Valid --date range: within ten years of now + private static final ZonedDateTime now = ZonedDateTime.now(); + static final ZonedDateTime DATE_MIN = now.minusYears(10); + static final ZonedDateTime DATE_MAX = now.plusYears(10); + + @Override + public boolean process(String opt, List args) { + if (noTimestamp) { + messages.error("doclet.Option_conflict", "--date", "-notimestamp"); + return false; + } + String arg = args.get(0); + try { + date = ZonedDateTime.parse(arg, DateTimeFormatter.ISO_ZONED_DATE_TIME); + if (date.isBefore(DATE_MIN) || date.isAfter(DATE_MAX)) { + messages.error("doclet.Option_date_out_of_range", arg); + return false; + } + return true; + } catch (DateTimeParseException x) { + messages.error("doclet.Option_date_not_valid", arg); + return false; + } + } + }, + new Option(resources, "-docencoding", 1) { @Override public boolean process(String opt, List args) { @@ -471,6 +512,10 @@ public abstract class BaseOptions { @Override public boolean process(String opt, List args) { noTimestamp = true; + if (date != null) { + messages.error("doclet.Option_conflict", "--date", "-notimestamp"); + return false; + } return true; } }, @@ -739,6 +784,13 @@ public abstract class BaseOptions { return customTagStrs; } + /** + * Argument for command-line option {@code --date}. + */ + public ZonedDateTime date() { + return date; + } + /** * Argument for command-line option {@code -d}. * Destination directory name, in which doclet will generate the entire diff --git a/test/langtools/jdk/javadoc/doclet/testDateOption/TestDateOption.java b/test/langtools/jdk/javadoc/doclet/testDateOption/TestDateOption.java new file mode 100644 index 00000000000..411e37efab9 --- /dev/null +++ b/test/langtools/jdk/javadoc/doclet/testDateOption/TestDateOption.java @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2022, 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 8272984 + * @summary javadoc support for SOURCE_DATE_EPOCH + * @library /tools/lib ../../lib + * @modules jdk.javadoc/jdk.javadoc.internal.tool + * @build toolbox.ToolBox javadoc.tester.* + * @run main TestDateOption + */ + +import java.nio.file.Path; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Date; +import java.util.Locale; + +import javadoc.tester.JavadocTester; +import toolbox.ToolBox; + +public class TestDateOption extends JavadocTester { + + /** + * The entry point of the test. + * + * @param args the array of command line arguments + * @throws Exception if the test fails + */ + public static void main(String... args) throws Exception { + TestDateOption tester = new TestDateOption(); + tester.runTests(m -> new Object[] { Path.of(m.getName()) }); + } + + ToolBox tb = new ToolBox(); + + @Test + public void testDateOption(Path base) throws Exception { + + ZonedDateTime zdt = ZonedDateTime.now(); // uses current date, time, timezone etc + // adjust the calendar to some date before the default used by javadoc (i.e. today/now) + // set a specific time, such as 10 to 3. (Rupert Brooke, Grantchester) + ZonedDateTime testDate = zdt.minusDays(100) + .withHour(14) + .withMinute(50) + .withSecond(0); + + out.println("Test Date: '" + testDate + "'"); + + Path srcDir = base.resolve("src"); + tb.writeJavaFiles(srcDir, """ + package p; + /** Comment. */ + public interface I { } + """); + Path outDir = base.resolve("out"); + + javadoc("-d", outDir.toString(), + "-sourcepath", srcDir.toString(), + "--date", testDate.toString(), + "p"); + checkExit(Exit.OK); + + int featureVersion = Runtime.version().feature(); + + // The following format is as used by javadoc; it is the historical format used by Date.toString() + DateTimeFormatter fmt = + DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss zzz yyyy").withLocale(Locale.US); + String generatedByStamp = testDate.format(fmt); + String generatedBy = String.format("", + featureVersion, generatedByStamp); + + DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + String dcCreatedStamp = testDate.format(dateFormat); + String dcCreated = String.format(""" + """, + dcCreatedStamp); + + // check the timestamps in all generated HTML files + for (Path file : tb.findFiles(".html", outputDir)) { + checkOutput(outputDir.relativize(file).toString(), true, + generatedBy, + dcCreated); + } + } + + @Test + public void testBadDateOption(Path base) throws Exception { + Path srcDir = base.resolve("src"); + tb.writeJavaFiles(srcDir, """ + package p; + /** Comment. */ + public interface I { } + """); + Path outDir = base.resolve("out"); + + javadoc("-d", outDir.toString(), + "-sourcepath", srcDir.toString(), + "--date", "NOT A DATE", + "p"); + checkExit(Exit.CMDERR); + + checkOutput(Output.OUT, true, + "error: value for '--date' not valid: NOT A DATE"); + } + + @Test + public void testInvalidDateOption(Path base) throws Exception { + Path srcDir = base.resolve("src"); + tb.writeJavaFiles(srcDir, """ + package p; + /** Comment. */ + public interface I { } + """); + Path outDir = base.resolve("out"); + + javadoc("-d", outDir.toString(), + "-sourcepath", srcDir.toString(), + "--date", new Date(0).toInstant().toString(), + "p"); + checkExit(Exit.CMDERR); + + checkOutput(Output.OUT, true, + "error: value for '--date' out of range: 1970-01-01T00:00:00Z"); + } +} \ No newline at end of file diff --git a/test/langtools/jdk/javadoc/doclet/testXOption/TestXOption.java b/test/langtools/jdk/javadoc/doclet/testXOption/TestXOption.java index 7d00116fccc..3c65066419c 100644 --- a/test/langtools/jdk/javadoc/doclet/testXOption/TestXOption.java +++ b/test/langtools/jdk/javadoc/doclet/testXOption/TestXOption.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, 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 @@ -98,6 +98,7 @@ public class TestXOption extends JavadocTester { "-Xmaxwarns ", "-Xdocrootparent ", "-Xdoclint ", - "-Xdoclint:"); + "-Xdoclint:", + "--date "); } } diff --git a/test/langtools/jdk/javadoc/tool/CheckManPageOptions.java b/test/langtools/jdk/javadoc/tool/CheckManPageOptions.java index a5b853c7aa4..6d49b54559e 100644 --- a/test/langtools/jdk/javadoc/tool/CheckManPageOptions.java +++ b/test/langtools/jdk/javadoc/tool/CheckManPageOptions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022, 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 @@ -66,7 +66,7 @@ public class CheckManPageOptions { static final PrintStream out = System.err; - List MISSING_IN_MAN_PAGE = List.of(); + List MISSING_IN_MAN_PAGE = List.of("--date"); void run(String... args) throws Exception { var file = args.length == 0 ? findDefaultFile() : Path.of(args[0]); -- GitLab From 4191b2b9b98c1137e5f27e3b64efb83857fa2c91 Mon Sep 17 00:00:00 2001 From: Igor Veresov Date: Mon, 31 Jan 2022 23:02:34 +0000 Subject: [PATCH 349/564] 8275337: C1: assert(false) failed: live_in set of first block must be empty Reviewed-by: kvn --- .../share/c1/c1_RangeCheckElimination.cpp | 7 +- .../jtreg/compiler/c1/Test8275337.java | 65 +++++++++++++++++++ 2 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 test/hotspot/jtreg/compiler/c1/Test8275337.java diff --git a/src/hotspot/share/c1/c1_RangeCheckElimination.cpp b/src/hotspot/share/c1/c1_RangeCheckElimination.cpp index fc5df4a4201..f5275eb9d5c 100644 --- a/src/hotspot/share/c1/c1_RangeCheckElimination.cpp +++ b/src/hotspot/share/c1/c1_RangeCheckElimination.cpp @@ -365,7 +365,12 @@ void RangeCheckEliminator::update_bound(IntegerStack &pushed, Value v, Instructi bool RangeCheckEliminator::loop_invariant(BlockBegin *loop_header, Instruction *instruction) { assert(loop_header, "Loop header must not be null!"); if (!instruction) return true; - return instruction->dominator_depth() < loop_header->dominator_depth(); + for (BlockBegin *d = loop_header->dominator(); d != NULL; d = d->dominator()) { + if (d == instruction->block()) { + return true; + } + } + return false; } // Update bound. Pushes a new bound onto the stack. Tries to do a conjunction with the current bound. diff --git a/test/hotspot/jtreg/compiler/c1/Test8275337.java b/test/hotspot/jtreg/compiler/c1/Test8275337.java new file mode 100644 index 00000000000..5e7ab912e20 --- /dev/null +++ b/test/hotspot/jtreg/compiler/c1/Test8275337.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2022, 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 8275337 + * @run main/othervm -Xcomp -XX:TieredStopAtLevel=1 compiler.c1.Test8275337 + */ + + +package compiler.c1; + +public class Test8275337 { + public static final int N = 400; + + public static void mainTest() { + int iArr1[] = new int[N]; + float fArr1[][] = new float[N][N]; + + for (int i = 9; i < 171; i++) { + int z; + try { + z = i % i; + } catch (ArithmeticException a_e) {} + for (int j = 1; j < 155; ++j) { + fArr1[j - 1][i] -= 1; + iArr1[i - 1] = 1; + } + for (int j = 4; j < 155; j++) { + for (int k = 1; k < 2; ++k) { + iArr1[i - 1] += 1; + fArr1[k - 1][j] -= 2; + } + } + } + } + public static void main(String[] strArr) { + + try { + for (int i = 0; i < 10; i++) { + mainTest(); + } + } catch (Exception ex) { + } + } +} -- GitLab From 4dbebb62aa264adda8d96a06f608ef9d13155a26 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Mon, 31 Jan 2022 23:22:38 +0000 Subject: [PATCH 350/564] 8280534: Enable compile-time doclint reference checking Reviewed-by: serb, naoto, mchung, lancea, iris --- make/modules/java.base/Java.gmk | 2 +- make/modules/java.datatransfer/Java.gmk | 2 +- make/modules/java.logging/Java.gmk | 2 +- make/modules/java.management/Java.gmk | 2 +- src/java.base/share/classes/java/io/FilenameFilter.java | 1 + src/java.base/share/classes/java/lang/Character.java | 4 ++++ src/java.base/share/classes/java/lang/System.java | 2 ++ .../share/classes/java/lang/invoke/MethodHandleProxies.java | 3 ++- .../share/classes/java/lang/invoke/MethodHandles.java | 1 + src/java.base/share/classes/java/net/package-info.java | 1 + .../share/classes/java/text/AttributedCharacterIterator.java | 2 +- src/java.base/share/classes/java/text/Bidi.java | 1 + src/java.base/share/classes/java/util/Observable.java | 1 + src/java.base/share/classes/java/util/ServiceLoader.java | 1 + .../share/classes/java/awt/datatransfer/Clipboard.java | 1 + .../share/classes/java/util/logging/LogManager.java | 2 ++ .../share/classes/java/util/logging/LoggingMXBean.java | 1 + .../share/classes/java/lang/management/ManagementFactory.java | 3 ++- .../classes/java/lang/management/PlatformLoggingMXBean.java | 1 + .../share/classes/javax/management/remote/JMXAddressable.java | 1 + .../javax/management/remote/JMXServerErrorException.java | 1 + 21 files changed, 28 insertions(+), 7 deletions(-) diff --git a/make/modules/java.base/Java.gmk b/make/modules/java.base/Java.gmk index b5bd86ada54..25c14d2b1d2 100644 --- a/make/modules/java.base/Java.gmk +++ b/make/modules/java.base/Java.gmk @@ -23,7 +23,7 @@ # questions. # -DOCLINT += -Xdoclint:all/protected,-reference \ +DOCLINT += -Xdoclint:all/protected \ '-Xdoclint/package:java.*,javax.*' JAVAC_FLAGS += -XDstringConcat=inline COPY += .icu .dat .spp .nrm content-types.properties \ diff --git a/make/modules/java.datatransfer/Java.gmk b/make/modules/java.datatransfer/Java.gmk index a9f7c8f4f0a..29feb6df9f5 100644 --- a/make/modules/java.datatransfer/Java.gmk +++ b/make/modules/java.datatransfer/Java.gmk @@ -23,6 +23,6 @@ # questions. # -DOCLINT += -Xdoclint:all/protected,-reference \ +DOCLINT += -Xdoclint:all/protected \ '-Xdoclint/package:java.*,javax.*' COPY += flavormap.properties diff --git a/make/modules/java.logging/Java.gmk b/make/modules/java.logging/Java.gmk index a6641fc1485..f49e425718e 100644 --- a/make/modules/java.logging/Java.gmk +++ b/make/modules/java.logging/Java.gmk @@ -23,5 +23,5 @@ # questions. # -DOCLINT += -Xdoclint:all/protected,-reference \ +DOCLINT += -Xdoclint:all/protected \ '-Xdoclint/package:java.*,javax.*' diff --git a/make/modules/java.management/Java.gmk b/make/modules/java.management/Java.gmk index a6641fc1485..f49e425718e 100644 --- a/make/modules/java.management/Java.gmk +++ b/make/modules/java.management/Java.gmk @@ -23,5 +23,5 @@ # questions. # -DOCLINT += -Xdoclint:all/protected,-reference \ +DOCLINT += -Xdoclint:all/protected \ '-Xdoclint/package:java.*,javax.*' diff --git a/src/java.base/share/classes/java/io/FilenameFilter.java b/src/java.base/share/classes/java/io/FilenameFilter.java index 019ffb11771..43e041d546d 100644 --- a/src/java.base/share/classes/java/io/FilenameFilter.java +++ b/src/java.base/share/classes/java/io/FilenameFilter.java @@ -39,6 +39,7 @@ package java.io; * @see java.io.File#list(java.io.FilenameFilter) * @since 1.0 */ +@SuppressWarnings("doclint:reference") // cross-module links @FunctionalInterface public interface FilenameFilter { /** diff --git a/src/java.base/share/classes/java/lang/Character.java b/src/java.base/share/classes/java/lang/Character.java index 0fdd23997cc..92e9b5b43f5 100644 --- a/src/java.base/share/classes/java/lang/Character.java +++ b/src/java.base/share/classes/java/lang/Character.java @@ -10305,6 +10305,7 @@ class Character implements java.io.Serializable, Comparable, Constabl * @see java.compiler/javax.lang.model.SourceVersion#isIdentifier(CharSequence) * @since 1.1 */ + @SuppressWarnings("doclint:reference") // cross-module links public static boolean isJavaIdentifierStart(char ch) { return isJavaIdentifierStart((int)ch); } @@ -10334,6 +10335,7 @@ class Character implements java.io.Serializable, Comparable, Constabl * @see java.compiler/javax.lang.model.SourceVersion#isIdentifier(CharSequence) * @since 1.5 */ + @SuppressWarnings("doclint:reference") // cross-module links public static boolean isJavaIdentifierStart(int codePoint) { return CharacterData.of(codePoint).isJavaIdentifierStart(codePoint); } @@ -10371,6 +10373,7 @@ class Character implements java.io.Serializable, Comparable, Constabl * @see java.compiler/javax.lang.model.SourceVersion#isIdentifier(CharSequence) * @since 1.1 */ + @SuppressWarnings("doclint:reference") // cross-module links public static boolean isJavaIdentifierPart(char ch) { return isJavaIdentifierPart((int)ch); } @@ -10404,6 +10407,7 @@ class Character implements java.io.Serializable, Comparable, Constabl * @see java.compiler/javax.lang.model.SourceVersion#isIdentifier(CharSequence) * @since 1.5 */ + @SuppressWarnings("doclint:reference") // cross-module links public static boolean isJavaIdentifierPart(int codePoint) { return CharacterData.of(codePoint).isJavaIdentifierPart(codePoint); } diff --git a/src/java.base/share/classes/java/lang/System.java b/src/java.base/share/classes/java/lang/System.java index 2f9c205a327..96b32ecabb6 100644 --- a/src/java.base/share/classes/java/lang/System.java +++ b/src/java.base/share/classes/java/lang/System.java @@ -1240,6 +1240,7 @@ public final class System { * @see java.lang.System.LoggerFinder * @see java.lang.System.Logger */ + @SuppressWarnings("doclint:reference") // cross-module links public enum Level { // for convenience, we're reusing java.util.logging.Level int values @@ -1600,6 +1601,7 @@ public final class System { * * @since 9 */ + @SuppressWarnings("doclint:reference") // cross-module links public abstract static class LoggerFinder { /** * The {@code RuntimePermission("loggerFinder")} is diff --git a/src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java b/src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java index b2e93afea12..69d975a7289 100644 --- a/src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java @@ -154,7 +154,8 @@ public class MethodHandleProxies { // entry points, must be covered by hand-written or automatically // generated adapter classes. // - @SuppressWarnings("removal") + @SuppressWarnings({"removal", + "doclint:reference"}) // cross-module links @CallerSensitive public static T asInterfaceInstance(final Class intfc, final MethodHandle target) { if (!intfc.isInterface() || !Modifier.isPublic(intfc.getModifiers())) diff --git a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java index 908c277fa86..b7d5bde0aeb 100644 --- a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java @@ -2105,6 +2105,7 @@ public class MethodHandles { * @jvms 5.5 Initialization * @jls 12.7 Unloading of Classes and Interfaces */ + @SuppressWarnings("doclint:reference") // cross-module links public Lookup defineHiddenClass(byte[] bytes, boolean initialize, ClassOption... options) throws IllegalAccessException { diff --git a/src/java.base/share/classes/java/net/package-info.java b/src/java.base/share/classes/java/net/package-info.java index e0325f6a0f1..6fc9913dfed 100644 --- a/src/java.base/share/classes/java/net/package-info.java +++ b/src/java.base/share/classes/java/net/package-info.java @@ -157,4 +157,5 @@ * * @since 1.0 */ +@SuppressWarnings("doclint:reference") // cross-module links package java.net; diff --git a/src/java.base/share/classes/java/text/AttributedCharacterIterator.java b/src/java.base/share/classes/java/text/AttributedCharacterIterator.java index a77417462a7..6a2f33630e0 100644 --- a/src/java.base/share/classes/java/text/AttributedCharacterIterator.java +++ b/src/java.base/share/classes/java/text/AttributedCharacterIterator.java @@ -75,7 +75,7 @@ import java.util.Set; * @see Annotation * @since 1.2 */ - +@SuppressWarnings("doclint:reference") // cross-module links public interface AttributedCharacterIterator extends CharacterIterator { /** diff --git a/src/java.base/share/classes/java/text/Bidi.java b/src/java.base/share/classes/java/text/Bidi.java index 41269afac9b..2ec7bea6988 100644 --- a/src/java.base/share/classes/java/text/Bidi.java +++ b/src/java.base/share/classes/java/text/Bidi.java @@ -125,6 +125,7 @@ public final class Bidi { * @see java.desktop/java.awt.font.TextAttribute#NUMERIC_SHAPING * @see java.desktop/java.awt.font.TextAttribute#RUN_DIRECTION */ + @SuppressWarnings("doclint:reference") // cross-module links public Bidi(AttributedCharacterIterator paragraph) { if (paragraph == null) { throw new IllegalArgumentException("paragraph is null"); diff --git a/src/java.base/share/classes/java/util/Observable.java b/src/java.base/share/classes/java/util/Observable.java index 37a90f631ad..01956702c2d 100644 --- a/src/java.base/share/classes/java/util/Observable.java +++ b/src/java.base/share/classes/java/util/Observable.java @@ -73,6 +73,7 @@ package java.util; * {@link java.util.concurrent.Flow} API. */ @Deprecated(since="9") +@SuppressWarnings("doclint:reference") // cross-module links public class Observable { private boolean changed = false; private Vector obs; diff --git a/src/java.base/share/classes/java/util/ServiceLoader.java b/src/java.base/share/classes/java/util/ServiceLoader.java index c5d921896a0..531ffa3f09c 100644 --- a/src/java.base/share/classes/java/util/ServiceLoader.java +++ b/src/java.base/share/classes/java/util/ServiceLoader.java @@ -1647,6 +1647,7 @@ public final class ServiceLoader * @revised 9 */ @CallerSensitive + @SuppressWarnings("doclint:reference") // cross-module links public static ServiceLoader load(Class service, ClassLoader loader) { diff --git a/src/java.datatransfer/share/classes/java/awt/datatransfer/Clipboard.java b/src/java.datatransfer/share/classes/java/awt/datatransfer/Clipboard.java index 8aac4495547..bc3ed00a030 100644 --- a/src/java.datatransfer/share/classes/java/awt/datatransfer/Clipboard.java +++ b/src/java.datatransfer/share/classes/java/awt/datatransfer/Clipboard.java @@ -47,6 +47,7 @@ import sun.datatransfer.DataFlavorUtil; * @see java.desktop/java.awt.Toolkit#getSystemSelection * @since 1.1 */ +@SuppressWarnings("doclint:reference") // cross-module links public class Clipboard { String name; diff --git a/src/java.logging/share/classes/java/util/logging/LogManager.java b/src/java.logging/share/classes/java/util/logging/LogManager.java index 38e9ebafeb6..2d277602a4a 100644 --- a/src/java.logging/share/classes/java/util/logging/LogManager.java +++ b/src/java.logging/share/classes/java/util/logging/LogManager.java @@ -2563,6 +2563,7 @@ public class LogManager { * * @since 1.5 */ + @SuppressWarnings("doclint:reference") public static final String LOGGING_MXBEAN_NAME = "java.util.logging:type=Logging"; @@ -2581,6 +2582,7 @@ public class LogManager { * @since 1.5 */ @Deprecated(since="9") + @SuppressWarnings("doclint:reference") public static synchronized LoggingMXBean getLoggingMXBean() { return Logging.getInstance(); } diff --git a/src/java.logging/share/classes/java/util/logging/LoggingMXBean.java b/src/java.logging/share/classes/java/util/logging/LoggingMXBean.java index b966421f9b0..01eea1d0e1e 100644 --- a/src/java.logging/share/classes/java/util/logging/LoggingMXBean.java +++ b/src/java.logging/share/classes/java/util/logging/LoggingMXBean.java @@ -52,6 +52,7 @@ package java.util.logging; * @see java.management/java.lang.management.PlatformLoggingMXBean */ @Deprecated(since="9") +@SuppressWarnings("doclint:reference") public interface LoggingMXBean { /** diff --git a/src/java.management/share/classes/java/lang/management/ManagementFactory.java b/src/java.management/share/classes/java/lang/management/ManagementFactory.java index 76bc7417e68..13db85d0f09 100644 --- a/src/java.management/share/classes/java/lang/management/ManagementFactory.java +++ b/src/java.management/share/classes/java/lang/management/ManagementFactory.java @@ -246,7 +246,8 @@ import sun.management.spi.PlatformMBeanProvider.PlatformComponent; * @author Mandy Chung * @since 1.5 */ -@SuppressWarnings("removal") +@SuppressWarnings({"removal", + "doclint:reference"}) // cross-module links public class ManagementFactory { // A class with only static fields and methods. private ManagementFactory() {}; diff --git a/src/java.management/share/classes/java/lang/management/PlatformLoggingMXBean.java b/src/java.management/share/classes/java/lang/management/PlatformLoggingMXBean.java index 280d145be37..3a50dc20958 100644 --- a/src/java.management/share/classes/java/lang/management/PlatformLoggingMXBean.java +++ b/src/java.management/share/classes/java/lang/management/PlatformLoggingMXBean.java @@ -46,6 +46,7 @@ package java.lang.management; * * @since 1.7 */ +@SuppressWarnings("doclint:reference") // cross-module links public interface PlatformLoggingMXBean extends PlatformManagedObject { /** diff --git a/src/java.management/share/classes/javax/management/remote/JMXAddressable.java b/src/java.management/share/classes/javax/management/remote/JMXAddressable.java index 973626b99a1..b100004d51e 100644 --- a/src/java.management/share/classes/javax/management/remote/JMXAddressable.java +++ b/src/java.management/share/classes/javax/management/remote/JMXAddressable.java @@ -41,6 +41,7 @@ package javax.management.remote; * * @since 1.6 */ +@SuppressWarnings("doclint:reference") // cross-module links public interface JMXAddressable { /** *

    The address of this object.

    diff --git a/src/java.management/share/classes/javax/management/remote/JMXServerErrorException.java b/src/java.management/share/classes/javax/management/remote/JMXServerErrorException.java index 856234ad5dc..185912c6b66 100644 --- a/src/java.management/share/classes/javax/management/remote/JMXServerErrorException.java +++ b/src/java.management/share/classes/javax/management/remote/JMXServerErrorException.java @@ -41,6 +41,7 @@ import javax.management.MBeanServer; * @see java.rmi/java.rmi.ServerError * @since 1.5 */ +@SuppressWarnings("doclint:reference") // cross-module links public class JMXServerErrorException extends IOException { private static final long serialVersionUID = 3996732239558744666L; -- GitLab From 9c0104b9c96f012da1602f503f641824d78f4260 Mon Sep 17 00:00:00 2001 From: Mandy Chung Date: Tue, 1 Feb 2022 00:09:35 +0000 Subject: [PATCH 351/564] 8221642: AccessibleObject::setAccessible throws NPE when invoked by JNI code with no java frame on stack Reviewed-by: alanb --- .../java/lang/reflect/AccessibleObject.java | 81 +++++++++---- .../exeCallerAccessTest/CallerAccessTest.java | 9 +- .../exeCallerAccessTest/exeCallerAccessTest.c | 111 +++++++++++++++++- 3 files changed, 174 insertions(+), 27 deletions(-) diff --git a/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java b/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java index 19dbce14b75..2b620967a8a 100644 --- a/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java +++ b/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -168,6 +168,15 @@ public class AccessibleObject implements AnnotatedElement { * open module. * * + *

    This method may be used by JNI code + * with no caller class on the stack to enable access to a {@link Member member} + * of {@link Member#getDeclaringClass() declaring class} {@code D} if and only if: + *

      + *
    • The member is {@code public} and {@code D} is {@code public} in + * a package that the module containing {@code D} {@link + * Module#isExported(String,Module) exports} unconditionally.
    • + *
    + * *

    This method cannot be used to enable access to private members, * members with default (package) access, protected instance members, or * protected constructors when the declaring class is in a different module @@ -246,6 +255,11 @@ public class AccessibleObject implements AnnotatedElement { * } * }

    * + *

    If this method is invoked by JNI code + * with no caller class on the stack, the {@code accessible} flag can + * only be set if the member and the declaring class are public, and + * the class is in a package that is exported unconditionally.

    + * *

    If there is a security manager, its {@code checkPermission} method * is first called with a {@code ReflectPermission("suppressAccessChecks")} * permission.

    @@ -304,6 +318,16 @@ public class AccessibleObject implements AnnotatedElement { throw new IllegalCallerException(); // should not happen } + if (caller == null) { + // No caller frame when a native thread attaches to the VM + // only allow access to a public accessible member + boolean canAccess = Reflection.verifyPublicMemberAccess(declaringClass, declaringClass.getModifiers()); + if (!canAccess && throwExceptionIfDenied) { + throwInaccessibleObjectException(caller, declaringClass); + } + return canAccess; + } + Module callerModule = caller.getModule(); Module declaringModule = declaringClass.getModule(); @@ -312,12 +336,7 @@ public class AccessibleObject implements AnnotatedElement { if (!declaringModule.isNamed()) return true; String pn = declaringClass.getPackageName(); - int modifiers; - if (this instanceof Executable) { - modifiers = ((Executable) this).getModifiers(); - } else { - modifiers = ((Field) this).getModifiers(); - } + int modifiers = ((Member)this).getModifiers(); // class is public and package is exported to caller boolean isClassPublic = Modifier.isPublic(declaringClass.getModifiers()); @@ -341,25 +360,37 @@ public class AccessibleObject implements AnnotatedElement { } if (throwExceptionIfDenied) { - // not accessible - String msg = "Unable to make "; - if (this instanceof Field) - msg += "field "; - msg += this + " accessible: " + declaringModule + " does not \""; - if (isClassPublic && Modifier.isPublic(modifiers)) - msg += "exports"; - else - msg += "opens"; - msg += " " + pn + "\" to " + callerModule; - InaccessibleObjectException e = new InaccessibleObjectException(msg); - if (printStackTraceWhenAccessFails()) { - e.printStackTrace(System.err); - } - throw e; + throwInaccessibleObjectException(caller, declaringClass); } return false; } + private void throwInaccessibleObjectException(Class caller, Class declaringClass) { + boolean isClassPublic = Modifier.isPublic(declaringClass.getModifiers()); + String pn = declaringClass.getPackageName(); + int modifiers = ((Member)this).getModifiers(); + + // not accessible + String msg = "Unable to make "; + if (this instanceof Field) + msg += "field "; + msg += this + " accessible"; + msg += caller == null ? " by JNI attached native thread with no caller frame: " : ": "; + msg += declaringClass.getModule() + " does not \""; + if (isClassPublic && Modifier.isPublic(modifiers)) + msg += "exports"; + else + msg += "opens"; + msg += " " + pn + "\"" ; + if (caller != null) + msg += " to " + caller.getModule(); + InaccessibleObjectException e = new InaccessibleObjectException(msg); + if (printStackTraceWhenAccessFails()) { + e.printStackTrace(System.err); + } + throw e; + } + private boolean isSubclassOf(Class queryClass, Class ofClass) { while (queryClass != null) { if (queryClass == ofClass) { @@ -409,7 +440,11 @@ public class AccessibleObject implements AnnotatedElement { * is set to {@code true}, i.e. the checks for Java language access control * are suppressed, or if the caller can access the member as * specified in The Java Language Specification, - * with the variation noted in the class description.

    + * with the variation noted in the class description. + * If this method is invoked by JNI code + * with no caller class on the stack, this method returns {@code true} + * if the member and the declaring class are public, and the class is in + * a package that is exported unconditionally.

    * * @param obj an instance object of the declaring class of this reflected * object if it is an instance method or field diff --git a/test/jdk/java/lang/reflect/exeCallerAccessTest/CallerAccessTest.java b/test/jdk/java/lang/reflect/exeCallerAccessTest/CallerAccessTest.java index 9f625a34a93..85ee270244d 100644 --- a/test/jdk/java/lang/reflect/exeCallerAccessTest/CallerAccessTest.java +++ b/test/jdk/java/lang/reflect/exeCallerAccessTest/CallerAccessTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /** * @test - * @bug 8221530 + * @bug 8221530 8221642 * @summary Test uses custom launcher that starts VM using JNI that verifies * reflection API with null caller class * @library /test/lib @@ -61,7 +61,10 @@ public class CallerAccessTest { System.out.println("Launching: " + launcher + " shared library path: " + env.get(sharedLibraryPathEnvName)); - new OutputAnalyzer(pb.start()).shouldHaveExitValue(0); + new OutputAnalyzer(pb.start()) + .outputTo(System.out) + .errorTo(System.err) + .shouldHaveExitValue(0); } } diff --git a/test/jdk/java/lang/reflect/exeCallerAccessTest/exeCallerAccessTest.c b/test/jdk/java/lang/reflect/exeCallerAccessTest/exeCallerAccessTest.c index c38a0cb094e..31710138aac 100644 --- a/test/jdk/java/lang/reflect/exeCallerAccessTest/exeCallerAccessTest.c +++ b/test/jdk/java/lang/reflect/exeCallerAccessTest/exeCallerAccessTest.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,9 +32,15 @@ static jclass iaeClass; static jmethodID mid_Class_forName; static jmethodID mid_Class_getField; static jmethodID mid_Field_get; +static jmethodID mid_Field_canAccess; +static jmethodID mid_Field_trySetAccessible; +static jmethodID mid_Field_setAccessible; int getField(JNIEnv *env, char* declaringClass_name, char* field_name); int checkAndClearIllegalAccessExceptionThrown(JNIEnv *env); +int setAccessible(JNIEnv *env, char* declaringClass_name, char* field_name); +int trySetAccessible(JNIEnv *env, char* declaringClass_name, char* field_name, jboolean canAccess); +int checkAccess(JNIEnv *env, char* declaringClass_name, char* field_name, jboolean canAccess); int main(int argc, char** args) { JavaVM *jvm; @@ -65,6 +71,12 @@ int main(int argc, char** args) { jclass fieldClass = (*env)->FindClass(env, "java/lang/reflect/Field"); mid_Field_get = (*env)->GetMethodID(env, fieldClass, "get", "(Ljava/lang/Object;)Ljava/lang/Object;"); assert(mid_Class_getField != NULL); + mid_Field_canAccess = (*env)->GetMethodID(env, fieldClass, "canAccess", "(Ljava/lang/Object;)Z"); + assert(mid_Field_canAccess != NULL); + mid_Field_setAccessible = (*env)->GetMethodID(env, fieldClass, "setAccessible", "(Z)V"); + assert(mid_Field_setAccessible != NULL); + mid_Field_trySetAccessible = (*env)->GetMethodID(env, fieldClass, "trySetAccessible", "()Z"); + assert(mid_Field_trySetAccessible != NULL); // can access to public member of an exported type if ((rc = getField(env, "java.lang.Integer", "TYPE")) != 0) { @@ -92,6 +104,32 @@ int main(int argc, char** args) { exit(-1); } + // expect IAE to jdk.internal.misc.Unsafe class + if ((rc = setAccessible(env, "jdk.internal.misc.Unsafe", "INVALID_FIELD_OFFSET")) == 0) { + printf("ERROR: IAE not thrown\n"); + exit(-1); + } + if (checkAndClearIllegalAccessExceptionThrown(env) != JNI_TRUE) { + printf("ERROR: exception is not an instance of IAE\n"); + exit(-1); + } + + if ((rc = trySetAccessible(env, "java.lang.reflect.Modifier", "PUBLIC", JNI_TRUE)) != 0) { + printf("ERROR: unexpected result from trySetAccessible on Modifier::PUBLIC field\n"); + exit(-1); + } + if ((rc = trySetAccessible(env, "jdk.internal.misc.Unsafe", "INVALID_FIELD_OFFSET", JNI_FALSE)) != 0) { + printf("ERROR: unexpected result from trySetAccessible on Unsafe public field\n"); + exit(-1); + } + + if ((rc = checkAccess(env, "java.lang.reflect.Modifier", "PUBLIC", JNI_TRUE)) != 0) { + printf("ERROR: unexpected result from trySetAccessible on Modifier::PUBLIC field\n"); + exit(-1); + } + if ((rc = checkAccess(env, "jdk.internal.misc.Unsafe", "INVALID_FIELD_OFFSET", JNI_FALSE)) != 0) { + printf("ERROR: unexpected result from trySetAccessible on Unsafe public field\n"); + } (*jvm)->DestroyJavaVM(jvm); return 0; } @@ -127,3 +165,74 @@ int getField(JNIEnv *env, char* declaringClass_name, char* field_name) { return 0; } +int setAccessible(JNIEnv *env, char* declaringClass_name, char* field_name) { + jobject c = (*env)->CallStaticObjectMethod(env, classClass, mid_Class_forName, + (*env)->NewStringUTF(env, declaringClass_name)); + if ((*env)->ExceptionOccurred(env) != NULL) { + (*env)->ExceptionDescribe(env); + return 1; + } + + jobject f = (*env)->CallObjectMethod(env, c, mid_Class_getField, (*env)->NewStringUTF(env, field_name)); + if ((*env)->ExceptionOccurred(env) != NULL) { + (*env)->ExceptionDescribe(env); + return 2; + } + + (*env)->CallVoidMethod(env, f, mid_Field_setAccessible, JNI_TRUE); + if ((*env)->ExceptionOccurred(env) != NULL) { + (*env)->ExceptionDescribe(env); + return 3; + } + return 0; +} + +int trySetAccessible(JNIEnv *env, char* declaringClass_name, char* field_name, jboolean canAccess) { + jobject c = (*env)->CallStaticObjectMethod(env, classClass, mid_Class_forName, + (*env)->NewStringUTF(env, declaringClass_name)); + if ((*env)->ExceptionOccurred(env) != NULL) { + (*env)->ExceptionDescribe(env); + return 1; + } + + jobject f = (*env)->CallObjectMethod(env, c, mid_Class_getField, (*env)->NewStringUTF(env, field_name)); + if ((*env)->ExceptionOccurred(env) != NULL) { + (*env)->ExceptionDescribe(env); + return 2; + } + + jboolean rc = (*env)->CallBooleanMethod(env, f, mid_Field_trySetAccessible); + if ((*env)->ExceptionOccurred(env) != NULL) { + (*env)->ExceptionDescribe(env); + return 3; + } + if (rc != canAccess) { + return 4; + } + return 0; +} + +int checkAccess(JNIEnv *env, char* declaringClass_name, char* field_name, jboolean canAccess) { + jobject c = (*env)->CallStaticObjectMethod(env, classClass, mid_Class_forName, + (*env)->NewStringUTF(env, declaringClass_name)); + if ((*env)->ExceptionOccurred(env) != NULL) { + (*env)->ExceptionDescribe(env); + return 1; + } + + jobject f = (*env)->CallObjectMethod(env, c, mid_Class_getField, (*env)->NewStringUTF(env, field_name)); + if ((*env)->ExceptionOccurred(env) != NULL) { + (*env)->ExceptionDescribe(env); + return 2; + } + + jboolean rc = (*env)->CallBooleanMethod(env, f, mid_Field_canAccess, NULL); + if ((*env)->ExceptionOccurred(env) != NULL) { + (*env)->ExceptionDescribe(env); + return 3; + } + if (rc != canAccess) { + return 4; + } + return 0; +} -- GitLab From 1ea01465ab06749a3177b9b724ccea0945a2de09 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Tue, 1 Feb 2022 00:31:19 +0000 Subject: [PATCH 352/564] 8281007: Test jdk/javadoc/doclet/checkStylesheetClasses/CheckStylesheetClasses.java fails after JDK-8280738 Reviewed-by: darcy --- .../doclet/checkStylesheetClasses/CheckStylesheetClasses.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/langtools/jdk/javadoc/doclet/checkStylesheetClasses/CheckStylesheetClasses.java b/test/langtools/jdk/javadoc/doclet/checkStylesheetClasses/CheckStylesheetClasses.java index 1cc649b2c27..ca3d24aed70 100644 --- a/test/langtools/jdk/javadoc/doclet/checkStylesheetClasses/CheckStylesheetClasses.java +++ b/test/langtools/jdk/javadoc/doclet/checkStylesheetClasses/CheckStylesheetClasses.java @@ -139,9 +139,6 @@ public class CheckStylesheetClasses { "search-tag-desc-result", "search-tag-holder-result", "ui-autocomplete", "ui-autocomplete-category", "expanded"); - // snippet-related - removeAll(styleSheetNames, "bold", "highlighted", "italic"); - // very JDK specific styleSheetNames.remove("module-graph"); -- GitLab From 0e70d4504c267174738485c7da82a2ac0ef09770 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Tue, 1 Feb 2022 01:27:18 +0000 Subject: [PATCH 353/564] 8280950: RandomGenerator:NextDouble() default behavior non conformant after JDK-8280550 fix Reviewed-by: bpb, jlaskey --- .../internal/util/random/RandomSupport.java | 4 +- .../util/Random/RandomNextDoubleBoundary.java | 41 ++++++++++++++++++- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/java.base/share/classes/jdk/internal/util/random/RandomSupport.java b/src/java.base/share/classes/jdk/internal/util/random/RandomSupport.java index 99ca3da322d..14fe0d3906d 100644 --- a/src/java.base/share/classes/jdk/internal/util/random/RandomSupport.java +++ b/src/java.base/share/classes/jdk/internal/util/random/RandomSupport.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, 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 @@ -645,7 +645,7 @@ public class RandomSupport { if (origin < bound) { r = r * (bound - origin) + origin; if (r >= bound) // may need to correct a rounding problem - r = Math.nextAfter(r, origin); + r = Math.nextAfter(bound, origin); } return r; } diff --git a/test/jdk/java/util/Random/RandomNextDoubleBoundary.java b/test/jdk/java/util/Random/RandomNextDoubleBoundary.java index 511f251aed6..971b22d55c1 100644 --- a/test/jdk/java/util/Random/RandomNextDoubleBoundary.java +++ b/test/jdk/java/util/Random/RandomNextDoubleBoundary.java @@ -24,13 +24,19 @@ /* * @test * @summary Verify nextDouble stays within range - * @bug 8280550 + * @bug 8280550 8280950 */ import java.util.SplittableRandom; +import java.util.random.RandomGenerator; public class RandomNextDoubleBoundary { public static void main(String... args) { + negativeBounds(); + positiveBounds(); + } + + private static void negativeBounds() { // Both bounds are negative double lowerBound = -1.0000000000000002; double upperBound = -1.0; @@ -49,4 +55,37 @@ public class RandomNextDoubleBoundary { throw new RuntimeException("Less than lower bound"); } } + + private static void positiveBounds() { + double[][] originAndBounds = {{10, 100}, + {12345, 123456}, + {5432167.234, 54321678.1238}}; + for (double[] originAndBound : originAndBounds) { + nextDoublesWithRange(originAndBound[0], originAndBound[1]); + } + } + + public static void nextDoublesWithRange(double origin, double bound) { + RandomGenerator rg = new RandomGenerator() { + @Override + public double nextDouble() { + return Double.MAX_VALUE; + } + + @Override + public long nextLong() { + return 0; + } + }; + double value = rg.nextDouble(origin, bound); + + assertTrue(value >= origin); + assertTrue(value < bound); + } + + public static void assertTrue(boolean condition) { + if (!condition) { + throw new AssertionError(); + } + } } -- GitLab From de3113b998550021bb502cd6f766036fb8351e7d Mon Sep 17 00:00:00 2001 From: Michael McMahon Date: Tue, 1 Feb 2022 07:26:59 +0000 Subject: [PATCH 354/564] 8279842: HTTPS Channel Binding support for Java GSS/Kerberos Co-authored-by: Weijun Wang Reviewed-by: dfuchs, weijun, darcy --- .../java/net/doc-files/net-properties.html | 16 + .../classes/sun/net/www/http/HttpClient.java | 34 ++ .../net/www/protocol/http/HttpCallerInfo.java | 15 + .../www/protocol/http/HttpURLConnection.java | 21 +- .../AbstractDelegateHttpsURLConnection.java | 73 +++- .../util/ChannelBindingException.java | 60 ++++ .../sun/security/util}/TlsChannelBinding.java | 32 +- .../com/sun/jndi/ldap/sasl/LdapSasl.java | 41 ++- .../protocol/http/spnego/NegotiatorImpl.java | 15 +- .../sun/jndi/ldap/LdapCBPropertiesTest.java | 6 +- test/jdk/sun/security/krb5/auto/HttpsCB.java | 311 ++++++++++++++++++ 11 files changed, 587 insertions(+), 37 deletions(-) create mode 100644 src/java.base/share/classes/sun/security/util/ChannelBindingException.java rename src/{java.naming/share/classes/com/sun/jndi/ldap/sasl => java.base/share/classes/sun/security/util}/TlsChannelBinding.java (82%) create mode 100644 test/jdk/sun/security/krb5/auto/HttpsCB.java diff --git a/src/java.base/share/classes/java/net/doc-files/net-properties.html b/src/java.base/share/classes/java/net/doc-files/net-properties.html index 0c2d3e232da..2bd35580432 100644 --- a/src/java.base/share/classes/java/net/doc-files/net-properties.html +++ b/src/java.base/share/classes/java/net/doc-files/net-properties.html @@ -214,6 +214,22 @@ of proxies.

    property is defined, then its value will be used as the domain name.

    +
  • {@systemProperty jdk.https.negotiate.cbt} (default: <never>)
    + This controls the generation and sending of TLS channel binding tokens (CBT) when Kerberos + or the Negotiate authentication scheme using Kerberos are employed over HTTPS with + {@code HttpsURLConnection}. There are three possible settings:

    +
      +
    1. "never". This is also the default value if the property is not set. In this case, + CBTs are never sent.

      +
    2. "always". CBTs are sent for all Kerberos authentication attempts over HTTPS.

      +
    3. "domain:<comma separated domain list>" Each domain in the list specifies destination + host or hosts for which a CBT is sent. Domains can be single hosts like foo, or foo.com, + or literal IP addresses as specified in RFC 2732, or wildcards like *.foo.com which matches + all hosts under foo.com and its sub-domains. CBTs are not sent to any destinations + that don't match one of the list entries

      +
    +

    The channel binding tokens generated are of the type "tls-server-end-point" as defined in + RFC 5929.

    All these properties are checked only once at startup.

    diff --git a/src/java.base/share/classes/sun/net/www/http/HttpClient.java b/src/java.base/share/classes/sun/net/www/http/HttpClient.java index 4b3c40b4fc0..8993f0c2a0a 100644 --- a/src/java.base/share/classes/sun/net/www/http/HttpClient.java +++ b/src/java.base/share/classes/sun/net/www/http/HttpClient.java @@ -144,12 +144,27 @@ public class HttpClient extends NetworkClient { // Traffic capture tool, if configured. See HttpCapture class for info private HttpCapture capture = null; + /* "jdk.https.negotiate.cbt" property can be set to "always" (always sent), "never" (never sent) or + * "domain:a,c.d,*.e.f" (sent to host a, or c.d or to the domain e.f and any of its subdomains). This is + * a comma separated list of arbitrary length with no white-space allowed. + * If enabled (for a particular destination) then Negotiate/SPNEGO authentication requests will include + * a channel binding token for the destination server. The default behavior and setting for the + * property is "never" + */ + private static final String spnegoCBT; + private static final PlatformLogger logger = HttpURLConnection.getHttpLogger(); + private static void logFinest(String msg) { if (logger.isLoggable(PlatformLogger.Level.FINEST)) { logger.finest(msg); } } + private static void logError(String msg) { + if (logger.isLoggable(PlatformLogger.Level.SEVERE)) { + logger.severe(msg); + } + } protected volatile String authenticatorKey; @@ -165,6 +180,18 @@ public class HttpClient extends NetworkClient { return keepAliveTimeout; } + static String normalizeCBT(String s) { + if (s == null || s.equals("never")) { + return "never"; + } + if (s.equals("always") || s.startsWith("domain:")) { + return s; + } else { + logError("Unexpected value for \"jdk.https.negotiate.cbt\" system property"); + return "never"; + } + } + static { Properties props = GetPropertyAction.privilegedGetProperties(); String keepAlive = props.getProperty("http.keepAlive"); @@ -172,6 +199,9 @@ public class HttpClient extends NetworkClient { String cacheNTLM = props.getProperty("jdk.ntlm.cache"); String cacheSPNEGO = props.getProperty("jdk.spnego.cache"); + String s = props.getProperty("jdk.https.negotiate.cbt"); + spnegoCBT = normalizeCBT(s); + if (keepAlive != null) { keepAliveProp = Boolean.parseBoolean(keepAlive); } else { @@ -206,6 +236,10 @@ public class HttpClient extends NetworkClient { } + public String getSpnegoCBT() { + return spnegoCBT; + } + protected HttpClient() { } diff --git a/src/java.base/share/classes/sun/net/www/protocol/http/HttpCallerInfo.java b/src/java.base/share/classes/sun/net/www/protocol/http/HttpCallerInfo.java index 038f7adfe90..5afed084c7f 100644 --- a/src/java.base/share/classes/sun/net/www/protocol/http/HttpCallerInfo.java +++ b/src/java.base/share/classes/sun/net/www/protocol/http/HttpCallerInfo.java @@ -29,6 +29,7 @@ import java.net.Authenticator; import java.net.Authenticator.RequestorType; import java.net.InetAddress; import java.net.URL; +import java.security.cert.X509Certificate; /** * Used in HTTP/Negotiate, to feed HTTP request info into JGSS as a HttpCaller, @@ -51,6 +52,9 @@ public final class HttpCallerInfo { public final InetAddress addr; public final RequestorType authType; public final Authenticator authenticator; + // Used to obtain server cert for SPNEGO CBT. + // May be null in which case CBT is not set + public final X509Certificate serverCert; /** * Create a schemed object based on an un-schemed one. @@ -65,13 +69,19 @@ public final class HttpCallerInfo { this.authType = old.authType; this.scheme = scheme; this.authenticator = old.authenticator; + this.serverCert = old.serverCert; } /** * Constructor an un-schemed object for site access. */ public HttpCallerInfo(URL url, Authenticator a) { + this(url, null, a); + } + + public HttpCallerInfo(URL url, X509Certificate serverCert, Authenticator a) { this.url= url; + this.serverCert= serverCert; prompt = ""; host = url.getHost(); @@ -100,9 +110,14 @@ public final class HttpCallerInfo { * Constructor an un-schemed object for proxy access. */ public HttpCallerInfo(URL url, String host, int port, Authenticator a) { + this(url, host, port, null, a); + } + + public HttpCallerInfo(URL url, String host, int port, X509Certificate serverCert, Authenticator a) { this.url= url; this.host = host; this.port = port; + this.serverCert = serverCert; prompt = ""; addr = null; protocol = url.getProtocol(); diff --git a/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java b/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java index c3d33014409..0ce0d29ee67 100644 --- a/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java +++ b/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java @@ -1739,7 +1739,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection { AuthenticationHeader authhdr = new AuthenticationHeader ( "Proxy-Authenticate", responses, - new HttpCallerInfo(url, + getHttpCallerInfo(url, http.getProxyHostUsed(), http.getProxyPortUsed(), authenticator), @@ -1814,7 +1814,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection { srvHdr = new AuthenticationHeader ( "WWW-Authenticate", responses, - new HttpCallerInfo(url, authenticator), + getHttpCallerInfo(url, authenticator), dontUseNegotiate ); @@ -2210,7 +2210,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection { AuthenticationHeader authhdr = new AuthenticationHeader( "Proxy-Authenticate", responses, - new HttpCallerInfo(url, + getHttpCallerInfo(url, http.getProxyHostUsed(), http.getProxyPortUsed(), authenticator), @@ -2279,6 +2279,21 @@ public class HttpURLConnection extends java.net.HttpURLConnection { responses.reset(); } + /** + * Overridden in https to also include the server certificate + */ + protected HttpCallerInfo getHttpCallerInfo(URL url, String proxy, int port, + Authenticator authenticator) { + return new HttpCallerInfo(url, proxy, port, authenticator); + } + + /** + * Overridden in https to also include the server certificate + */ + protected HttpCallerInfo getHttpCallerInfo(URL url, Authenticator authenticator) { + return new HttpCallerInfo(url, authenticator); + } + static String connectRequestURI(URL url) { String host = url.getHost(); int port = url.getPort(); diff --git a/src/java.base/share/classes/sun/net/www/protocol/https/AbstractDelegateHttpsURLConnection.java b/src/java.base/share/classes/sun/net/www/protocol/https/AbstractDelegateHttpsURLConnection.java index 3828eb3cd29..7ed4381dda6 100644 --- a/src/java.base/share/classes/sun/net/www/protocol/https/AbstractDelegateHttpsURLConnection.java +++ b/src/java.base/share/classes/sun/net/www/protocol/https/AbstractDelegateHttpsURLConnection.java @@ -1,4 +1,4 @@ -/* +/** * Copyright (c) 2001, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -25,10 +25,13 @@ package sun.net.www.protocol.https; +import java.net.Authenticator; import java.net.URL; import java.net.Proxy; import java.net.SecureCacheResponse; import java.security.Principal; +import java.security.cert.Certificate; +import java.security.cert.X509Certificate; import java.io.IOException; import java.util.List; import java.util.Optional; @@ -36,6 +39,7 @@ import javax.net.ssl.SSLSession; import javax.net.ssl.SSLPeerUnverifiedException; import sun.net.www.http.*; import sun.net.www.protocol.http.HttpURLConnection; +import sun.net.www.protocol.http.HttpCallerInfo; /** * HTTPS URL connection support. @@ -309,4 +313,71 @@ public abstract class AbstractDelegateHttpsURLConnection extends return ((HttpsClient)http).getSSLSession(); } + + /* + * If no SSL Session available or if the system config does not allow it + * don't use the extended caller info (the server cert). + * Otherwise return true to include the server cert + */ + private boolean useExtendedCallerInfo(URL url) { + HttpsClient https = (HttpsClient)http; + if (https.getSSLSession() == null) { + return false; + } + String prop = http.getSpnegoCBT(); + if (prop.equals("never")) { + return false; + } + String target = url.getHost(); + if (prop.startsWith("domain:")) { + String[] domains = prop.substring(7).split(","); + for (String domain : domains) { + if (target.equals(domain)) { + return true; + } + if (domain.startsWith("*.") && target.endsWith(domain.substring(1))) { + return true; + } + } + return false; + } + return true; + } + + @Override + protected HttpCallerInfo getHttpCallerInfo(URL url, String proxy, int port, + Authenticator authenticator) + { + if (!useExtendedCallerInfo(url)) { + return super.getHttpCallerInfo(url, proxy, port, authenticator); + } + HttpsClient https = (HttpsClient)http; + try { + Certificate[] certs = https.getServerCertificates(); + if (certs[0] instanceof X509Certificate x509Cert) { + return new HttpCallerInfo(url, proxy, port, x509Cert, authenticator); + } + } catch (SSLPeerUnverifiedException e) { + // ignore + } + return super.getHttpCallerInfo(url, proxy, port, authenticator); + } + + @Override + protected HttpCallerInfo getHttpCallerInfo(URL url, Authenticator authenticator) + { + if (!useExtendedCallerInfo(url)) { + return super.getHttpCallerInfo(url, authenticator); + } + HttpsClient https = (HttpsClient)http; + try { + Certificate[] certs = https.getServerCertificates(); + if (certs[0] instanceof X509Certificate x509Cert) { + return new HttpCallerInfo(url, x509Cert, authenticator); + } + } catch (SSLPeerUnverifiedException e) { + // ignore + } + return super.getHttpCallerInfo(url, authenticator); + } } diff --git a/src/java.base/share/classes/sun/security/util/ChannelBindingException.java b/src/java.base/share/classes/sun/security/util/ChannelBindingException.java new file mode 100644 index 00000000000..847cd0741a0 --- /dev/null +++ b/src/java.base/share/classes/sun/security/util/ChannelBindingException.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.security.util; + +import java.security.GeneralSecurityException; + +/** + * Thrown by TlsChannelBinding if an error occurs + */ +public class ChannelBindingException extends GeneralSecurityException { + + @java.io.Serial + private static final long serialVersionUID = -5021387249782788460L; + + /** + * Constructs a ChannelBindingException with no detail message. A detail + * message is a String that describes this particular exception. + */ + public ChannelBindingException() { + super(); + } + + /** + * Constructs a ChannelBindingException with a detail message and + * specified cause. + */ + public ChannelBindingException(String msg, Exception e) { + super(msg, e); + } + + /** + * Constructs a ChannelBindingException with a detail message + */ + public ChannelBindingException(String msg) { + super(msg); + } +} diff --git a/src/java.naming/share/classes/com/sun/jndi/ldap/sasl/TlsChannelBinding.java b/src/java.base/share/classes/sun/security/util/TlsChannelBinding.java similarity index 82% rename from src/java.naming/share/classes/com/sun/jndi/ldap/sasl/TlsChannelBinding.java rename to src/java.base/share/classes/sun/security/util/TlsChannelBinding.java index 922fa18028c..8f7ac50bb5e 100644 --- a/src/java.naming/share/classes/com/sun/jndi/ldap/sasl/TlsChannelBinding.java +++ b/src/java.base/share/classes/sun/security/util/TlsChannelBinding.java @@ -22,10 +22,9 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.sun.jndi.ldap.sasl; -import javax.naming.NamingException; -import javax.security.sasl.SaslException; +package sun.security.util; + import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateEncodingException; @@ -47,14 +46,6 @@ import java.util.Hashtable; public class TlsChannelBinding { - // TLS channel binding type property - public static final String CHANNEL_BINDING_TYPE = - "com.sun.jndi.ldap.tls.cbtype"; - - // internal TLS channel binding property - public static final String CHANNEL_BINDING = - "jdk.internal.sasl.tlschannelbinding"; - public enum TlsChannelBindingType { /** @@ -80,19 +71,18 @@ public class TlsChannelBinding { } /** - * Parse value of "com.sun.jndi.ldap.tls.cbtype" property + * Parse given value to see if it is a recognized and supported channel binding type + * * @param cbType - * @return TLS Channel Binding type or null if - * "com.sun.jndi.ldap.tls.cbtype" property has not been set. - * @throws NamingException + * @return TLS Channel Binding type or null if given string is null + * @throws ChannelBindingException */ - public static TlsChannelBindingType parseType(String cbType) throws NamingException { + public static TlsChannelBindingType parseType(String cbType) throws ChannelBindingException { if (cbType != null) { if (cbType.equals(TlsChannelBindingType.TLS_SERVER_END_POINT.getName())) { return TlsChannelBindingType.TLS_SERVER_END_POINT; } else { - throw new NamingException("Illegal value for " + - CHANNEL_BINDING_TYPE + " property."); + throw new ChannelBindingException("Illegal value for channel binding type: " + cbType); } } return null; @@ -104,9 +94,9 @@ public class TlsChannelBinding { /** * Construct tls-server-end-point Channel Binding data * @param serverCertificate - * @throws SaslException + * @throws ChannelBindingException */ - public static TlsChannelBinding create(X509Certificate serverCertificate) throws SaslException { + public static TlsChannelBinding create(X509Certificate serverCertificate) throws ChannelBindingException { try { final byte[] prefix = TlsChannelBindingType.TLS_SERVER_END_POINT.getName().concat(":").getBytes(); @@ -127,7 +117,7 @@ public class TlsChannelBinding { System.arraycopy(hash, 0, cbData, prefix.length, hash.length); return new TlsChannelBinding(TlsChannelBindingType.TLS_SERVER_END_POINT, cbData); } catch (NoSuchAlgorithmException | CertificateEncodingException e) { - throw new SaslException("Cannot create TLS channel binding data", e); + throw new ChannelBindingException("Cannot create TLS channel binding data", e); } } diff --git a/src/java.naming/share/classes/com/sun/jndi/ldap/sasl/LdapSasl.java b/src/java.naming/share/classes/com/sun/jndi/ldap/sasl/LdapSasl.java index bc557bfaa35..23be4706041 100644 --- a/src/java.naming/share/classes/com/sun/jndi/ldap/sasl/LdapSasl.java +++ b/src/java.naming/share/classes/com/sun/jndi/ldap/sasl/LdapSasl.java @@ -42,7 +42,9 @@ import javax.security.sasl.*; import com.sun.jndi.ldap.Connection; import com.sun.jndi.ldap.LdapClient; import com.sun.jndi.ldap.LdapResult; -import com.sun.jndi.ldap.sasl.TlsChannelBinding.TlsChannelBindingType; +import sun.security.util.ChannelBindingException; +import sun.security.util.TlsChannelBinding; +import sun.security.util.TlsChannelBinding.TlsChannelBindingType; /** * Handles SASL support. @@ -62,6 +64,14 @@ public final class LdapSasl { private static final int LDAP_SUCCESS = 0; private static final int LDAP_SASL_BIND_IN_PROGRESS = 14; // LDAPv3 + // TLS channel binding type property + private static final String CHANNEL_BINDING_TYPE = + "com.sun.jndi.ldap.tls.cbtype"; + + // internal TLS channel binding property + private static final String CHANNEL_BINDING = + "jdk.internal.sasl.tlschannelbinding"; + private LdapSasl() { } @@ -113,8 +123,8 @@ public final class LdapSasl { String[] mechs = getSaslMechanismNames(authMech); // Internal TLS Channel Binding property cannot be set explicitly - if (env.get(TlsChannelBinding.CHANNEL_BINDING) != null) { - throw new NamingException(TlsChannelBinding.CHANNEL_BINDING + + if (env.get(CHANNEL_BINDING) != null) { + throw new NamingException(CHANNEL_BINDING + " property cannot be set explicitly"); } @@ -123,17 +133,24 @@ public final class LdapSasl { try { // Prepare TLS Channel Binding data if (conn.isTlsConnection()) { - TlsChannelBindingType cbType = - TlsChannelBinding.parseType( - (String)env.get(TlsChannelBinding.CHANNEL_BINDING_TYPE)); + TlsChannelBindingType cbType; + try { + cbType = TlsChannelBinding.parseType((String)env.get(CHANNEL_BINDING_TYPE)); + } catch (ChannelBindingException e) { + throw wrapInNamingException(e); + } if (cbType == TlsChannelBindingType.TLS_SERVER_END_POINT) { // set tls-server-end-point channel binding X509Certificate cert = conn.getTlsServerCertificate(); if (cert != null) { - TlsChannelBinding tlsCB = - TlsChannelBinding.create(cert); + TlsChannelBinding tlsCB; + try { + tlsCB = TlsChannelBinding.create(cert); + } catch (ChannelBindingException e) { + throw wrapInNamingException(e); + } envProps = (Hashtable) env.clone(); - envProps.put(TlsChannelBinding.CHANNEL_BINDING, tlsCB.getData()); + envProps.put(CHANNEL_BINDING, tlsCB.getData()); } else { throw new SaslException("No suitable certificate to generate " + "TLS Channel Binding data"); @@ -227,5 +244,11 @@ public final class LdapSasl { return mechNames; } + private static NamingException wrapInNamingException(Exception e) { + NamingException ne = new NamingException(); + ne.setRootCause(e); + return ne; + } + private static final byte[] NO_BYTES = new byte[0]; } diff --git a/src/java.security.jgss/share/classes/sun/net/www/protocol/http/spnego/NegotiatorImpl.java b/src/java.security.jgss/share/classes/sun/net/www/protocol/http/spnego/NegotiatorImpl.java index c17b54dd335..82f2391816b 100644 --- a/src/java.security.jgss/share/classes/sun/net/www/protocol/http/spnego/NegotiatorImpl.java +++ b/src/java.security.jgss/share/classes/sun/net/www/protocol/http/spnego/NegotiatorImpl.java @@ -40,6 +40,9 @@ import sun.security.jgss.GSSManagerImpl; import sun.security.jgss.GSSContextImpl; import sun.security.jgss.GSSUtil; import sun.security.jgss.HttpCaller; +import sun.security.jgss.krb5.internal.TlsChannelBindingImpl; +import sun.security.util.ChannelBindingException; +import sun.security.util.TlsChannelBinding; /** * This class encapsulates all JAAS and JGSS API calls in a separate class @@ -65,7 +68,7 @@ public class NegotiatorImpl extends Negotiator { *
  • Creating GSSContext *
  • A first call to initSecContext */ - private void init(HttpCallerInfo hci) throws GSSException { + private void init(HttpCallerInfo hci) throws GSSException, ChannelBindingException { final Oid oid; if (hci.scheme.equalsIgnoreCase("Kerberos")) { @@ -100,6 +103,14 @@ public class NegotiatorImpl extends Negotiator { if (context instanceof GSSContextImpl) { ((GSSContextImpl)context).requestDelegPolicy(true); } + if (hci.serverCert != null) { + if (DEBUG) { + System.out.println("Negotiate: Setting CBT"); + } + // set the channel binding token + TlsChannelBinding b = TlsChannelBinding.create(hci.serverCert); + context.setChannelBinding(new TlsChannelBindingImpl(b.getData())); + } oneToken = context.initSecContext(new byte[0], 0, 0); } @@ -110,7 +121,7 @@ public class NegotiatorImpl extends Negotiator { public NegotiatorImpl(HttpCallerInfo hci) throws IOException { try { init(hci); - } catch (GSSException e) { + } catch (GSSException | ChannelBindingException e) { if (DEBUG) { System.out.println("Negotiate support not initiated, will " + "fallback to other scheme if allowed. Reason:"); diff --git a/test/jdk/com/sun/jndi/ldap/LdapCBPropertiesTest.java b/test/jdk/com/sun/jndi/ldap/LdapCBPropertiesTest.java index 16b4400310a..2f2ce50e8d6 100644 --- a/test/jdk/com/sun/jndi/ldap/LdapCBPropertiesTest.java +++ b/test/jdk/com/sun/jndi/ldap/LdapCBPropertiesTest.java @@ -25,6 +25,7 @@ * @test * @bug 8245527 * @library lib/ /test/lib + * @modules java.base/sun.security.util * @run main/othervm LdapCBPropertiesTest true true com.sun.jndi.ldap.tls.cbtype tls-server-end-point * @run main/othervm LdapCBPropertiesTest false false com.sun.jndi.ldap.tls.cbtype tls-server-end-point * @run main/othervm LdapCBPropertiesTest true true com.sun.jndi.ldap.tls.cbtype tls-server-end-point com.sun.jndi.ldap.connect.timeout 2000 @@ -53,6 +54,8 @@ import javax.security.sasl.SaslException; import jdk.test.lib.net.URIBuilder; +import sun.security.util.ChannelBindingException; + public class LdapCBPropertiesTest { /* * Where do we find the keystores? @@ -187,7 +190,8 @@ public class LdapCBPropertiesTest { } } } - if (!shouldPass && ne.getRootCause() == null) { + Throwable rc = ne.getRootCause(); + if (!shouldPass && (rc == null || rc instanceof ChannelBindingException)) { // Expected exception caused by Channel Binding parameter inconsistency return true; } diff --git a/test/jdk/sun/security/krb5/auto/HttpsCB.java b/test/jdk/sun/security/krb5/auto/HttpsCB.java new file mode 100644 index 00000000000..a65aa5d0241 --- /dev/null +++ b/test/jdk/sun/security/krb5/auto/HttpsCB.java @@ -0,0 +1,311 @@ +/* + * Copyright (c) 2022, 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 8279842 + * @modules java.base/sun.security.util + * java.security.jgss/sun.security.jgss + * java.security.jgss/sun.security.jgss.krb5 + * java.security.jgss/sun.security.jgss.krb5.internal + * java.security.jgss/sun.security.krb5.internal:+open + * java.security.jgss/sun.security.krb5:+open + * java.security.jgss/sun.security.krb5.internal.ccache + * java.security.jgss/sun.security.krb5.internal.crypto + * java.security.jgss/sun.security.krb5.internal.ktab + * jdk.security.auth + * jdk.security.jgss + * jdk.httpserver + * @summary HTTPS Channel Binding support for Java GSS/Kerberos + * @library /test/lib + * @run main jdk.test.lib.FileInstaller TestHosts TestHosts + * @run main/othervm -Djdk.net.hosts.file=TestHosts + * -Djdk.https.negotiate.cbt=always HttpsCB true true + * @run main/othervm -Djdk.net.hosts.file=TestHosts + * -Djdk.https.negotiate.cbt=never HttpsCB false true + * @run main/othervm -Djdk.net.hosts.file=TestHosts + * -Djdk.https.negotiate.cbt=invalid HttpsCB false true + * @run main/othervm -Djdk.net.hosts.file=TestHosts + * HttpsCB false true + * @run main/othervm -Djdk.net.hosts.file=TestHosts + * -Djdk.https.negotiate.cbt=domain:other.com HttpsCB false true + * @run main/othervm -Djdk.net.hosts.file=TestHosts + * -Djdk.https.negotiate.cbt=domain:host.web.domain HttpsCB true true + * @run main/othervm -Djdk.net.hosts.file=TestHosts + * -Djdk.https.negotiate.cbt=domain:*.web.domain HttpsCB true true + */ + +import com.sun.net.httpserver.Headers; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; +import com.sun.net.httpserver.HttpPrincipal; +import com.sun.net.httpserver.HttpsConfigurator; +import com.sun.net.httpserver.HttpsExchange; +import com.sun.net.httpserver.HttpsServer; +import com.sun.security.auth.module.Krb5LoginModule; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.InetSocketAddress; +import java.net.PasswordAuthentication; +import java.net.Proxy; +import java.net.Socket; +import java.net.URL; +import java.security.cert.X509Certificate; +import java.util.HashMap; +import java.util.Map; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLEngine; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509ExtendedTrustManager; +import javax.security.auth.Subject; + +import jdk.test.lib.Asserts; +import jdk.test.lib.net.SimpleSSLContext; +import org.ietf.jgss.GSSContext; +import org.ietf.jgss.GSSCredential; +import org.ietf.jgss.GSSManager; +import sun.security.jgss.GSSUtil; +import sun.security.jgss.krb5.internal.TlsChannelBindingImpl; +import sun.security.krb5.Config; +import sun.security.util.TlsChannelBinding; + +import java.util.Base64; +import java.util.concurrent.Callable; + +public class HttpsCB { + + final static String REALM_WEB = "WEB.DOMAIN"; + final static String KRB5_CONF = "web.conf"; + final static String KRB5_TAB = "web.ktab"; + + final static String WEB_USER = "web"; + final static char[] WEB_PASS = "webby".toCharArray(); + final static String WEB_HOST = "host.web.domain"; + final static String CONTENT = "Hello, World!"; + + static int webPort; + static URL cbtURL; + static URL normalURL; + + public static void main(String[] args) + throws Exception { + + boolean expectCBT = Boolean.parseBoolean(args[0]); + boolean expectNoCBT = Boolean.parseBoolean(args[1]); + + System.setProperty("sun.security.krb5.debug", "true"); + + KDC kdcw = KDC.create(REALM_WEB); + kdcw.addPrincipal(WEB_USER, WEB_PASS); + kdcw.addPrincipalRandKey("krbtgt/" + REALM_WEB); + kdcw.addPrincipalRandKey("HTTP/" + WEB_HOST); + + KDC.saveConfig(KRB5_CONF, kdcw, + "default_keytab_name = " + KRB5_TAB, + "[domain_realm]", + "", + ".web.domain="+REALM_WEB); + + System.setProperty("java.security.krb5.conf", KRB5_CONF); + Config.refresh(); + KDC.writeMultiKtab(KRB5_TAB, kdcw); + + // Write a customized JAAS conf file, so that any kinit cache + // will be ignored. + System.setProperty("java.security.auth.login.config", OneKDC.JAAS_CONF); + File f = new File(OneKDC.JAAS_CONF); + FileOutputStream fos = new FileOutputStream(f); + fos.write(( + "com.sun.security.jgss.krb5.initiate {\n" + + " com.sun.security.auth.module.Krb5LoginModule required;\n};\n" + ).getBytes()); + fos.close(); + + HttpServer h1 = httpd("Negotiate", + "HTTP/" + WEB_HOST + "@" + REALM_WEB, KRB5_TAB); + webPort = h1.getAddress().getPort(); + + cbtURL = new URL("https://" + WEB_HOST +":" + webPort + "/cbt"); + normalURL = new URL("https://" + WEB_HOST +":" + webPort + "/normal"); + + java.net.Authenticator.setDefault(new java.net.Authenticator() { + public PasswordAuthentication getPasswordAuthentication () { + return new PasswordAuthentication( + WEB_USER+"@"+REALM_WEB, WEB_PASS); + } + }); + + // Client-side SSLContext needs to ignore hostname mismatch + // and untrusted certificate. + SSLContext sc = SSLContext.getInstance("SSL"); + sc.init(null, new TrustManager[] { + new X509ExtendedTrustManager() { + public X509Certificate[] getAcceptedIssuers() { + return null; + } + public void checkClientTrusted(X509Certificate[] chain, + String authType, Socket socket) { } + public void checkServerTrusted(X509Certificate[] chain, + String authType, Socket socket) { } + public void checkClientTrusted(X509Certificate[] chain, + String authType, SSLEngine engine) { } + public void checkServerTrusted(X509Certificate[] chain, + String authType, SSLEngine engine) { } + public void checkClientTrusted(X509Certificate[] certs, + String authType) { } + public void checkServerTrusted(X509Certificate[] certs, + String authType) { } + } + }, null); + + Asserts.assertEQ(visit(sc, cbtURL), expectCBT); + Asserts.assertEQ(visit(sc, normalURL), expectNoCBT); + } + + static boolean visit(SSLContext sc, URL url) { + try { + HttpsURLConnection conn = (HttpsURLConnection) + url.openConnection(Proxy.NO_PROXY); + conn.setSSLSocketFactory(sc.getSocketFactory()); + BufferedReader reader; + reader = new BufferedReader(new InputStreamReader( + conn.getInputStream())); + return reader.readLine().equals(CONTENT); + } catch (IOException e) { + return false; + } + } + + static HttpServer httpd(String scheme, String principal, String ktab) + throws Exception { + MyHttpHandler h = new MyHttpHandler(); + HttpsServer server = HttpsServer.create(new InetSocketAddress(0), 0); + server.setHttpsConfigurator( + new HttpsConfigurator(new SimpleSSLContext().get())); + server.createContext("/", h).setAuthenticator( + new MyServerAuthenticator(scheme, principal, ktab)); + server.start(); + return server; + } + + static class MyHttpHandler implements HttpHandler { + public void handle(HttpExchange t) throws IOException { + t.sendResponseHeaders(200, 0); + t.getResponseBody().write(CONTENT.getBytes()); + t.close(); + } + } + + static class MyServerAuthenticator + extends com.sun.net.httpserver.Authenticator { + Subject s = new Subject(); + GSSManager m; + GSSCredential cred; + String scheme = null; + String reqHdr = "WWW-Authenticate"; + String respHdr = "Authorization"; + int err = HttpURLConnection.HTTP_UNAUTHORIZED; + + public MyServerAuthenticator(String scheme, + String principal, String ktab) throws Exception { + + this.scheme = scheme; + Krb5LoginModule krb5 = new Krb5LoginModule(); + Map map = new HashMap<>(); + Map shared = new HashMap<>(); + + map.put("storeKey", "true"); + map.put("isInitiator", "false"); + map.put("useKeyTab", "true"); + map.put("keyTab", ktab); + map.put("principal", principal); + krb5.initialize(s, null, shared, map); + krb5.login(); + krb5.commit(); + m = GSSManager.getInstance(); + cred = Subject.callAs(s, new Callable() { + @Override + public GSSCredential call() throws Exception { + System.err.println("Creating GSSCredential"); + return m.createCredential( + null, + GSSCredential.INDEFINITE_LIFETIME, + MyServerAuthenticator.this.scheme + .equalsIgnoreCase("Negotiate") ? + GSSUtil.GSS_SPNEGO_MECH_OID : + GSSUtil.GSS_KRB5_MECH_OID, + GSSCredential.ACCEPT_ONLY); + } + }); + } + + @Override + public Result authenticate(HttpExchange exch) { + // The GSContext is stored in an HttpContext attribute named + // "GSSContext" and is created at the first request. + GSSContext c = null; + String auth = exch.getRequestHeaders().getFirst(respHdr); + try { + c = (GSSContext)exch.getHttpContext() + .getAttributes().get("GSSContext"); + if (auth == null) { // First request + Headers map = exch.getResponseHeaders(); + map.set (reqHdr, scheme); // Challenge! + c = Subject.callAs(s, () -> m.createContext(cred)); + // CBT is required for cbtURL + if (exch instanceof HttpsExchange sexch + && exch.getRequestURI().toString().equals("/cbt")) { + TlsChannelBinding b = TlsChannelBinding.create( + (X509Certificate) sexch.getSSLSession() + .getLocalCertificates()[0]); + c.setChannelBinding( + new TlsChannelBindingImpl(b.getData())); + } + exch.getHttpContext().getAttributes().put("GSSContext", c); + return new com.sun.net.httpserver.Authenticator.Retry(err); + } else { // Later requests + byte[] token = Base64.getMimeDecoder() + .decode(auth.split(" ")[1]); + token = c.acceptSecContext(token, 0, token.length); + Headers map = exch.getResponseHeaders(); + map.set (reqHdr, scheme + " " + Base64.getMimeEncoder() + .encodeToString(token).replaceAll("\\s", "")); + if (c.isEstablished()) { + return new com.sun.net.httpserver.Authenticator.Success( + new HttpPrincipal(c.getSrcName().toString(), "")); + } else { + return new com.sun.net.httpserver.Authenticator.Retry(err); + } + } + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } +} -- GitLab From 16ec47d5e5bf129fc0910358464ab62bf6ce7ed8 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Tue, 1 Feb 2022 08:47:10 +0000 Subject: [PATCH 355/564] 8279856: Parallel: Use PreservedMarks to record promotion-failed objects Reviewed-by: sjohanss, tschatzl --- src/hotspot/share/gc/parallel/psPromotionManager.cpp | 5 ++++- src/hotspot/share/gc/parallel/psScavenge.cpp | 10 +--------- src/hotspot/share/gc/shared/preservedMarks.cpp | 6 ++++-- src/hotspot/share/gc/shared/preservedMarks.hpp | 1 + src/hotspot/share/gc/shared/preservedMarks.inline.hpp | 6 ++++++ 5 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/hotspot/share/gc/parallel/psPromotionManager.cpp b/src/hotspot/share/gc/parallel/psPromotionManager.cpp index 0eef7667810..9c6b8acf624 100644 --- a/src/hotspot/share/gc/parallel/psPromotionManager.cpp +++ b/src/hotspot/share/gc/parallel/psPromotionManager.cpp @@ -339,7 +339,10 @@ oop PSPromotionManager::oop_promotion_failed(oop obj, markWord obj_mark) { push_contents(obj); - _preserved_marks->push_if_necessary(obj, obj_mark); + // Save the markWord of promotion-failed objs in _preserved_marks for later + // restoration. This way we don't have to walk the young-gen to locate + // these promotion-failed objs. + _preserved_marks->push_always(obj, obj_mark); } else { // We lost, someone else "owns" this object guarantee(obj->is_forwarded(), "Object must be forwarded if the cas failed."); diff --git a/src/hotspot/share/gc/parallel/psScavenge.cpp b/src/hotspot/share/gc/parallel/psScavenge.cpp index 995c5157dfc..b6ca29adefc 100644 --- a/src/hotspot/share/gc/parallel/psScavenge.cpp +++ b/src/hotspot/share/gc/parallel/psScavenge.cpp @@ -670,19 +670,11 @@ bool PSScavenge::invoke_no_policy() { return !promotion_failure_occurred; } -// This method iterates over all objects in the young generation, -// removing all forwarding references. It then restores any preserved marks. void PSScavenge::clean_up_failed_promotion() { - ParallelScavengeHeap* heap = ParallelScavengeHeap::heap(); - PSYoungGen* young_gen = heap->young_gen(); - - RemoveForwardedPointerClosure remove_fwd_ptr_closure; - young_gen->object_iterate(&remove_fwd_ptr_closure); - PSPromotionManager::restore_preserved_marks(); // Reset the PromotionFailureALot counters. - NOT_PRODUCT(heap->reset_promotion_should_fail();) + NOT_PRODUCT(ParallelScavengeHeap::heap()->reset_promotion_should_fail();) } bool PSScavenge::should_attempt_scavenge() { diff --git a/src/hotspot/share/gc/shared/preservedMarks.cpp b/src/hotspot/share/gc/shared/preservedMarks.cpp index 718f97085f6..70d7f6e8934 100644 --- a/src/hotspot/share/gc/shared/preservedMarks.cpp +++ b/src/hotspot/share/gc/shared/preservedMarks.cpp @@ -125,8 +125,10 @@ public: ~RestorePreservedMarksTask() { assert(_total_size == _total_size_before, "total_size = %zu before = %zu", _total_size, _total_size_before); - - log_trace(gc)("Restored %zu marks", _total_size); + size_t mem_size = _total_size * (sizeof(oop) + sizeof(markWord)); + log_trace(gc)("Restored %zu marks, occupying %zu %s", _total_size, + byte_size_in_proper_unit(mem_size), + proper_unit_for_byte_size(mem_size)); } }; diff --git a/src/hotspot/share/gc/shared/preservedMarks.hpp b/src/hotspot/share/gc/shared/preservedMarks.hpp index b172b68e49a..1aa202cfba4 100644 --- a/src/hotspot/share/gc/shared/preservedMarks.hpp +++ b/src/hotspot/share/gc/shared/preservedMarks.hpp @@ -57,6 +57,7 @@ private: public: size_t size() const { return _stack.size(); } inline void push_if_necessary(oop obj, markWord m); + inline void push_always(oop obj, markWord m); // Iterate over the stack, restore all preserved marks, and // reclaim the memory taken up by the stack segments. void restore(); diff --git a/src/hotspot/share/gc/shared/preservedMarks.inline.hpp b/src/hotspot/share/gc/shared/preservedMarks.inline.hpp index ea3b3b9da0e..e35ba38e429 100644 --- a/src/hotspot/share/gc/shared/preservedMarks.inline.hpp +++ b/src/hotspot/share/gc/shared/preservedMarks.inline.hpp @@ -42,6 +42,12 @@ inline void PreservedMarks::push_if_necessary(oop obj, markWord m) { } } +inline void PreservedMarks::push_always(oop obj, markWord m) { + assert(!m.is_marked(), "precondition"); + OopAndMarkWord elem(obj, m); + _stack.push(elem); +} + inline void PreservedMarks::init_forwarded_mark(oop obj) { obj->init_mark(); } -- GitLab From 18a7dc8c08fa15a260b4a39b18c068d30ee45962 Mon Sep 17 00:00:00 2001 From: Alexander Zuev Date: Tue, 1 Feb 2022 10:20:38 +0000 Subject: [PATCH 356/564] 8279586: [macos] custom JCheckBox and JRadioBox with custom icon set: focus is still displayed after unchecking Reviewed-by: serb, azvegint --- .../com/apple/laf/AquaButtonLabeledUI.java | 4 ++-- .../ImageCheckboxFocus/ImageCheckboxTest.java | 19 +++++++++++++++++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonLabeledUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonLabeledUI.java index 3a9ed6b12f5..3c21b325f36 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonLabeledUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonLabeledUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2022, 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 @@ -170,7 +170,7 @@ public abstract class AquaButtonLabeledUI extends AquaButtonToggleUI implements } int offset = 0; - if (b.isFocusOwner()) { + if (b.isFocusOwner() && b.isFocusPainted()) { offset = 2; altIcon = AquaFocus.createFocusedIcon(altIcon, c, 2); } diff --git a/test/jdk/javax/swing/JCheckBox/ImageCheckboxFocus/ImageCheckboxTest.java b/test/jdk/javax/swing/JCheckBox/ImageCheckboxFocus/ImageCheckboxTest.java index b63973229a2..c93715d8087 100644 --- a/test/jdk/javax/swing/JCheckBox/ImageCheckboxFocus/ImageCheckboxTest.java +++ b/test/jdk/javax/swing/JCheckBox/ImageCheckboxFocus/ImageCheckboxTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022, 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,7 +34,7 @@ import javax.swing.JCheckBox; /* * @test * @key headful - * @bug 8216358 + * @bug 8216358 8279586 * @summary [macos] The focus is invisible when tab to "Image Radio Buttons" and "Image CheckBoxes" * @library ../../regtesthelpers/ * @build Util @@ -51,8 +51,12 @@ public class ImageCheckboxTest { BufferedImage.TYPE_INT_ARGB); BufferedImage imageFocus = new BufferedImage(100, 50, BufferedImage.TYPE_INT_ARGB); + BufferedImage imageFocusNotPainted = new BufferedImage(100, 50, + BufferedImage.TYPE_INT_ARGB); + CustomCheckBox checkbox = new CustomCheckBox("Test", new MyIcon(Color.GREEN)); + checkbox.setFocusPainted(true); checkbox.setSize(100, 50); checkbox.setFocused(false); checkbox.paint(imageNoFocus.createGraphics()); @@ -64,6 +68,17 @@ public class ImageCheckboxTest { ImageIO.write(imageNoFocus, "png", new File("imageNoFocus.png")); throw new Exception("Changing focus is not visualized"); } + + checkbox.setFocusPainted(false); + checkbox.paint(imageFocusNotPainted.createGraphics()); + + if (!Util.compareBufferedImages(imageFocusNotPainted, imageNoFocus)) { + ImageIO.write(imageFocusNotPainted, "png", + new File("imageFocusNotPainted.png")); + ImageIO.write(imageFocus, "png", new File("imageFocus.png")); + ImageIO.write(imageNoFocus, "png", new File("imageNoFocus.png")); + throw new Exception("setFocusPainted(false) is ignored"); + } } class MyIcon implements Icon { -- GitLab From d37fb1df460ec980bd8d3029b1ce7896c3249a99 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Tue, 1 Feb 2022 10:56:07 +0000 Subject: [PATCH 357/564] 8280870: Parallel: Simplify CLD roots claim in Full GC cycle Reviewed-by: stefank, sjohanss --- .../share/gc/parallel/psParallelCompact.cpp | 50 ++++--------------- 1 file changed, 11 insertions(+), 39 deletions(-) diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.cpp b/src/hotspot/share/gc/parallel/psParallelCompact.cpp index d415de47ca5..cb8dd999f5d 100644 --- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp +++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp @@ -1948,36 +1948,6 @@ public: } }; -static void mark_from_roots_work(ParallelRootType::Value root_type, uint worker_id) { - assert(ParallelScavengeHeap::heap()->is_gc_active(), "called outside gc"); - - ParCompactionManager* cm = - ParCompactionManager::gc_thread_compaction_manager(worker_id); - PCMarkAndPushClosure mark_and_push_closure(cm); - - switch (root_type) { - case ParallelRootType::class_loader_data: - { - CLDToOopClosure cld_closure(&mark_and_push_closure, ClassLoaderData::_claim_strong); - ClassLoaderDataGraph::always_strong_cld_do(&cld_closure); - } - break; - - case ParallelRootType::code_cache: - // Do not treat nmethods as strong roots for mark/sweep, since we can unload them. - //ScavengableNMethods::scavengable_nmethods_do(CodeBlobToOopClosure(&mark_and_push_closure)); - break; - - case ParallelRootType::sentinel: - DEBUG_ONLY(default:) // DEBUG_ONLY hack will create compile error on release builds (-Wswitch) and runtime check on debug builds - fatal("Bad enumeration value: %u", root_type); - break; - } - - // Do the real work - cm->follow_marking_stacks(); -} - void steal_marking_work(TaskTerminator& terminator, uint worker_id) { assert(ParallelScavengeHeap::heap()->is_gc_active(), "called outside gc"); @@ -1999,7 +1969,6 @@ void steal_marking_work(TaskTerminator& terminator, uint worker_id) { class MarkFromRootsTask : public WorkerTask { StrongRootsScope _strong_roots_scope; // needed for Threads::possibly_parallel_threads_do OopStorageSetStrongParState _oop_storage_set_par_state; - SequentialSubTasksDone _subtasks; TaskTerminator _terminator; uint _active_workers; @@ -2007,14 +1976,19 @@ public: MarkFromRootsTask(uint active_workers) : WorkerTask("MarkFromRootsTask"), _strong_roots_scope(active_workers), - _subtasks(ParallelRootType::sentinel), _terminator(active_workers, ParCompactionManager::oop_task_queues()), - _active_workers(active_workers) { - } + _active_workers(active_workers) {} virtual void work(uint worker_id) { - for (uint task = 0; _subtasks.try_claim_task(task); /*empty*/ ) { - mark_from_roots_work(static_cast(task), worker_id); + ParCompactionManager* cm = ParCompactionManager::gc_thread_compaction_manager(worker_id); + PCMarkAndPushClosure mark_and_push_closure(cm); + + { + CLDToOopClosure cld_closure(&mark_and_push_closure, ClassLoaderData::_claim_strong); + ClassLoaderDataGraph::always_strong_cld_do(&cld_closure); + + // Do the real work + cm->follow_marking_stacks(); } PCAddThreadRootsMarkingTaskClosure closure(worker_id); @@ -2022,9 +1996,7 @@ public: // Mark from OopStorages { - ParCompactionManager* cm = ParCompactionManager::gc_thread_compaction_manager(worker_id); - PCMarkAndPushClosure closure(cm); - _oop_storage_set_par_state.oops_do(&closure); + _oop_storage_set_par_state.oops_do(&mark_and_push_closure); // Do the real work cm->follow_marking_stacks(); } -- GitLab From 86debf42f545a1aec0a065ebd5b016339a1ae09f Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Tue, 1 Feb 2022 11:03:31 +0000 Subject: [PATCH 358/564] 8280932: G1: Rename HeapRegionRemSet::_code_roots accessors Reviewed-by: iwalulya --- src/hotspot/share/gc/g1/g1CodeBlobClosure.cpp | 4 +- src/hotspot/share/gc/g1/g1CollectedHeap.cpp | 18 +++--- src/hotspot/share/gc/g1/g1CollectedHeap.hpp | 4 +- src/hotspot/share/gc/g1/g1ConcurrentMark.cpp | 10 ++-- src/hotspot/share/gc/g1/g1ConcurrentMark.hpp | 4 +- src/hotspot/share/gc/g1/g1EvacFailure.cpp | 2 +- src/hotspot/share/gc/g1/g1HeapVerifier.cpp | 4 +- src/hotspot/share/gc/g1/g1RemSet.cpp | 22 ++++---- src/hotspot/share/gc/g1/g1RemSetSummary.cpp | 18 +++--- src/hotspot/share/gc/g1/g1SharedClosures.hpp | 2 +- src/hotspot/share/gc/g1/g1YoungCollector.cpp | 2 +- src/hotspot/share/gc/g1/heapRegion.cpp | 56 +++++++++---------- src/hotspot/share/gc/g1/heapRegion.hpp | 14 ++--- src/hotspot/share/gc/g1/heapRegionRemSet.cpp | 16 +++--- src/hotspot/share/gc/g1/heapRegionRemSet.hpp | 35 ++++++------ 15 files changed, 105 insertions(+), 106 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1CodeBlobClosure.cpp b/src/hotspot/share/gc/g1/g1CodeBlobClosure.cpp index 725e0130388..f2dc595ef53 100644 --- a/src/hotspot/share/gc/g1/g1CodeBlobClosure.cpp +++ b/src/hotspot/share/gc/g1/g1CodeBlobClosure.cpp @@ -40,8 +40,8 @@ void G1CodeBlobClosure::HeapRegionGatheringOopClosure::do_oop_work(T* p) { if (!CompressedOops::is_null(oop_or_narrowoop)) { oop o = CompressedOops::decode_not_null(oop_or_narrowoop); HeapRegion* hr = _g1h->heap_region_containing(o); - assert(!_g1h->is_in_cset(o) || hr->rem_set()->strong_code_roots_list_contains(_nm), "if o still in collection set then evacuation failed and nm must already be in the remset"); - hr->add_strong_code_root(_nm); + assert(!_g1h->is_in_cset(o) || hr->rem_set()->code_roots_list_contains(_nm), "if o still in collection set then evacuation failed and nm must already be in the remset"); + hr->add_code_root(_nm); } } diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index 005ea4264ce..89c95c620ba 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -1042,8 +1042,8 @@ void G1CollectedHeap::prepare_heap_for_mutators() { resize_heap_if_necessary(); uncommit_regions_if_necessary(); - // Rebuild the strong code root lists for each region - rebuild_strong_code_roots(); + // Rebuild the code root lists for each region + rebuild_code_roots(); // Purge code root memory purge_code_root_memory(); @@ -3342,8 +3342,8 @@ public: " starting at " HR_FORMAT, p2i(_nm), HR_FORMAT_PARAMS(hr), HR_FORMAT_PARAMS(hr->humongous_start_region())); - // HeapRegion::add_strong_code_root_locked() avoids adding duplicate entries. - hr->add_strong_code_root_locked(_nm); + // HeapRegion::add_code_root_locked() avoids adding duplicate entries. + hr->add_code_root_locked(_nm); } } @@ -3368,7 +3368,7 @@ public: " starting at " HR_FORMAT, p2i(_nm), HR_FORMAT_PARAMS(hr), HR_FORMAT_PARAMS(hr->humongous_start_region())); - hr->remove_strong_code_root(_nm); + hr->remove_code_root(_nm); } } @@ -3411,11 +3411,11 @@ void G1CollectedHeap::purge_code_root_memory() { G1CodeRootSet::purge(); } -class RebuildStrongCodeRootClosure: public CodeBlobClosure { +class RebuildCodeRootClosure: public CodeBlobClosure { G1CollectedHeap* _g1h; public: - RebuildStrongCodeRootClosure(G1CollectedHeap* g1h) : + RebuildCodeRootClosure(G1CollectedHeap* g1h) : _g1h(g1h) {} void do_code_blob(CodeBlob* cb) { @@ -3428,8 +3428,8 @@ public: } }; -void G1CollectedHeap::rebuild_strong_code_roots() { - RebuildStrongCodeRootClosure blob_cl(this); +void G1CollectedHeap::rebuild_code_roots() { + RebuildCodeRootClosure blob_cl(this); CodeCache::blobs_do(&blob_cl); } diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp index 8c4a8307816..83da03019af 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp @@ -1287,9 +1287,9 @@ public: // Free up superfluous code root memory. void purge_code_root_memory(); - // Rebuild the strong code root lists for each region + // Rebuild the code root lists for each region // after a full GC. - void rebuild_strong_code_roots(); + void rebuild_code_roots(); // Performs cleaning of data structures after class unloading. void complete_cleaning(BoolObjectClosure* is_alive, bool class_unloading_occurred); diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp index c2800aacfbc..5d0c0dd605d 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp @@ -2954,7 +2954,7 @@ G1CMTask::G1CMTask(uint worker_id, G1PrintRegionLivenessInfoClosure::G1PrintRegionLivenessInfoClosure(const char* phase_name) : _total_used_bytes(0), _total_capacity_bytes(0), _total_prev_live_bytes(0), _total_next_live_bytes(0), - _total_remset_bytes(0), _total_strong_code_roots_bytes(0) + _total_remset_bytes(0), _total_code_roots_bytes(0) { if (!log_is_enabled(Trace, gc, liveness)) { return; @@ -3014,7 +3014,7 @@ bool G1PrintRegionLivenessInfoClosure::do_heap_region(HeapRegion* r) { size_t next_live_bytes = r->next_live_bytes(); double gc_eff = r->gc_efficiency(); size_t remset_bytes = r->rem_set()->mem_size(); - size_t strong_code_roots_bytes = r->rem_set()->strong_code_roots_mem_size(); + size_t code_roots_bytes = r->rem_set()->code_roots_mem_size(); const char* remset_type = r->rem_set()->get_short_state_str(); FormatBuffer<16> gc_efficiency(""); @@ -3023,7 +3023,7 @@ bool G1PrintRegionLivenessInfoClosure::do_heap_region(HeapRegion* r) { _total_prev_live_bytes += prev_live_bytes; _total_next_live_bytes += next_live_bytes; _total_remset_bytes += remset_bytes; - _total_strong_code_roots_bytes += strong_code_roots_bytes; + _total_code_roots_bytes += code_roots_bytes; if(gc_eff < 0) { gc_efficiency.append("-"); @@ -3044,7 +3044,7 @@ bool G1PrintRegionLivenessInfoClosure::do_heap_region(HeapRegion* r) { G1PPRL_BYTE_FORMAT, type, p2i(bottom), p2i(end), used_bytes, prev_live_bytes, next_live_bytes, gc_efficiency.buffer(), - remset_bytes, remset_type, strong_code_roots_bytes); + remset_bytes, remset_type, code_roots_bytes); return false; } @@ -3074,5 +3074,5 @@ G1PrintRegionLivenessInfoClosure::~G1PrintRegionLivenessInfoClosure() { bytes_to_mb(_total_next_live_bytes), percent_of(_total_next_live_bytes, _total_capacity_bytes), bytes_to_mb(_total_remset_bytes), - bytes_to_mb(_total_strong_code_roots_bytes)); + bytes_to_mb(_total_code_roots_bytes)); } diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp b/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp index d2e3ae624f2..cc603df18c4 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp @@ -847,8 +847,8 @@ class G1PrintRegionLivenessInfoClosure : public HeapRegionClosure { // Accumulator for the remembered set size size_t _total_remset_bytes; - // Accumulator for strong code roots memory size - size_t _total_strong_code_roots_bytes; + // Accumulator for code roots memory size + size_t _total_code_roots_bytes; static double bytes_to_mb(size_t val) { return (double) val / (double) M; diff --git a/src/hotspot/share/gc/g1/g1EvacFailure.cpp b/src/hotspot/share/gc/g1/g1EvacFailure.cpp index dbad25955ae..fd065df17c6 100644 --- a/src/hotspot/share/gc/g1/g1EvacFailure.cpp +++ b/src/hotspot/share/gc/g1/g1EvacFailure.cpp @@ -196,7 +196,7 @@ public: size_t live_bytes = remove_self_forward_ptr_by_walking_hr(hr, during_concurrent_start); - hr->rem_set()->clean_strong_code_roots(hr); + hr->rem_set()->clean_code_roots(hr); hr->rem_set()->clear_locked(true); hr->note_self_forwarding_removal_end(live_bytes); diff --git a/src/hotspot/share/gc/g1/g1HeapVerifier.cpp b/src/hotspot/share/gc/g1/g1HeapVerifier.cpp index 2c18b4a7346..1cf2c01a0e2 100644 --- a/src/hotspot/share/gc/g1/g1HeapVerifier.cpp +++ b/src/hotspot/share/gc/g1/g1HeapVerifier.cpp @@ -114,9 +114,9 @@ class G1VerifyCodeRootOopClosure: public OopClosure { // Now fetch the region containing the object HeapRegion* hr = _g1h->heap_region_containing(obj); HeapRegionRemSet* hrrs = hr->rem_set(); - // Verify that the strong code root list for this region + // Verify that the code root list for this region // contains the nmethod - if (!hrrs->strong_code_roots_list_contains(_nm)) { + if (!hrrs->code_roots_list_contains(_nm)) { log_error(gc, verify)("Code root location " PTR_FORMAT " " "from nmethod " PTR_FORMAT " not in strong " "code roots for region [" PTR_FORMAT "," PTR_FORMAT ")", diff --git a/src/hotspot/share/gc/g1/g1RemSet.cpp b/src/hotspot/share/gc/g1/g1RemSet.cpp index 13977348825..6496b6eaf64 100644 --- a/src/hotspot/share/gc/g1/g1RemSet.cpp +++ b/src/hotspot/share/gc/g1/g1RemSet.cpp @@ -946,8 +946,8 @@ class G1ScanCollectionSetRegionClosure : public HeapRegionClosure { size_t _opt_refs_scanned; size_t _opt_refs_memory_used; - Tickspan _strong_code_root_scan_time; - Tickspan _strong_code_trim_partially_time; + Tickspan _code_root_scan_time; + Tickspan _code_trim_partially_time; Tickspan _rem_set_opt_root_scan_time; Tickspan _rem_set_opt_trim_partially_time; @@ -979,8 +979,8 @@ public: _opt_roots_scanned(0), _opt_refs_scanned(0), _opt_refs_memory_used(0), - _strong_code_root_scan_time(), - _strong_code_trim_partially_time(), + _code_root_scan_time(), + _code_trim_partially_time(), _rem_set_opt_root_scan_time(), _rem_set_opt_trim_partially_time() { } @@ -997,9 +997,9 @@ public: if (_scan_state->claim_collection_set_region(region_idx)) { EventGCPhaseParallel event; - G1EvacPhaseWithTrimTimeTracker timer(_pss, _strong_code_root_scan_time, _strong_code_trim_partially_time); - // Scan the strong code root list attached to the current region - r->strong_code_roots_do(_pss->closures()->weak_codeblobs()); + G1EvacPhaseWithTrimTimeTracker timer(_pss, _code_root_scan_time, _code_trim_partially_time); + // Scan the code root list attached to the current region + r->code_roots_do(_pss->closures()->weak_codeblobs()); event.commit(GCId::current(), _worker_id, G1GCPhaseTimes::phase_name(_code_roots_phase)); } @@ -1007,8 +1007,8 @@ public: return false; } - Tickspan strong_code_root_scan_time() const { return _strong_code_root_scan_time; } - Tickspan strong_code_root_trim_partially_time() const { return _strong_code_trim_partially_time; } + Tickspan code_root_scan_time() const { return _code_root_scan_time; } + Tickspan code_root_trim_partially_time() const { return _code_trim_partially_time; } Tickspan rem_set_opt_root_scan_time() const { return _rem_set_opt_root_scan_time; } Tickspan rem_set_opt_trim_partially_time() const { return _rem_set_opt_trim_partially_time; } @@ -1031,8 +1031,8 @@ void G1RemSet::scan_collection_set_regions(G1ParScanThreadState* pss, p->record_or_add_time_secs(scan_phase, worker_id, cl.rem_set_opt_root_scan_time().seconds()); p->record_or_add_time_secs(scan_phase, worker_id, cl.rem_set_opt_trim_partially_time().seconds()); - p->record_or_add_time_secs(coderoots_phase, worker_id, cl.strong_code_root_scan_time().seconds()); - p->add_time_secs(objcopy_phase, worker_id, cl.strong_code_root_trim_partially_time().seconds()); + p->record_or_add_time_secs(coderoots_phase, worker_id, cl.code_root_scan_time().seconds()); + p->add_time_secs(objcopy_phase, worker_id, cl.code_root_trim_partially_time().seconds()); // At this time we record some metrics only for the evacuations after the initial one. if (scan_phase == G1GCPhaseTimes::OptScanHR) { diff --git a/src/hotspot/share/gc/g1/g1RemSetSummary.cpp b/src/hotspot/share/gc/g1/g1RemSetSummary.cpp index cae7df6f902..faf09063bc0 100644 --- a/src/hotspot/share/gc/g1/g1RemSetSummary.cpp +++ b/src/hotspot/share/gc/g1/g1RemSetSummary.cpp @@ -233,7 +233,7 @@ public: HeapRegionRemSet* hrrs = r->rem_set(); // HeapRegionRemSet::mem_size() includes the - // size of the strong code roots + // size of the code roots size_t rs_wasted_mem_sz = hrrs->wasted_mem_size(); size_t rs_mem_sz = hrrs->mem_size(); if (rs_mem_sz > _max_rs_mem_sz) { @@ -241,12 +241,12 @@ public: _max_rs_mem_sz_region = r; } size_t occupied_cards = hrrs->occupied(); - size_t code_root_mem_sz = hrrs->strong_code_roots_mem_size(); + size_t code_root_mem_sz = hrrs->code_roots_mem_size(); if (code_root_mem_sz > max_code_root_mem_sz()) { _max_code_root_mem_sz = code_root_mem_sz; _max_code_root_mem_sz_region = r; } - size_t code_root_elems = hrrs->strong_code_roots_list_length(); + size_t code_root_elems = hrrs->code_roots_list_length(); RegionTypeCounter* current = NULL; if (r->is_free()) { @@ -300,14 +300,14 @@ public: HeapRegionRemSet::print_static_mem_size(out); G1CardSetFreePool::free_list_pool()->print_on(out); - // Strong code root statistics + // Code root statistics HeapRegionRemSet* max_code_root_rem_set = max_code_root_mem_sz_region()->rem_set(); out->print_cr(" Total heap region code root sets sizes = " SIZE_FORMAT "%s." " Max = " SIZE_FORMAT "%s.", byte_size_in_proper_unit(total_code_root_mem_sz()), proper_unit_for_byte_size(total_code_root_mem_sz()), - byte_size_in_proper_unit(max_code_root_rem_set->strong_code_roots_mem_size()), - proper_unit_for_byte_size(max_code_root_rem_set->strong_code_roots_mem_size())); + byte_size_in_proper_unit(max_code_root_rem_set->code_roots_mem_size()), + proper_unit_for_byte_size(max_code_root_rem_set->code_roots_mem_size())); for (RegionTypeCounter** current = &counters[0]; *current != NULL; current++) { (*current)->print_code_root_mem_info_on(out, total_code_root_mem_sz()); } @@ -321,9 +321,9 @@ public: out->print_cr(" Region with largest amount of code roots = " HR_FORMAT ", " "size = " SIZE_FORMAT "%s, num_slots = " SIZE_FORMAT ".", HR_FORMAT_PARAMS(max_code_root_mem_sz_region()), - byte_size_in_proper_unit(max_code_root_rem_set->strong_code_roots_mem_size()), - proper_unit_for_byte_size(max_code_root_rem_set->strong_code_roots_mem_size()), - max_code_root_rem_set->strong_code_roots_list_length()); + byte_size_in_proper_unit(max_code_root_rem_set->code_roots_mem_size()), + proper_unit_for_byte_size(max_code_root_rem_set->code_roots_mem_size()), + max_code_root_rem_set->code_roots_list_length()); } }; diff --git a/src/hotspot/share/gc/g1/g1SharedClosures.hpp b/src/hotspot/share/gc/g1/g1SharedClosures.hpp index 55b9a1e62c5..4808f0ae84f 100644 --- a/src/hotspot/share/gc/g1/g1SharedClosures.hpp +++ b/src/hotspot/share/gc/g1/g1SharedClosures.hpp @@ -37,7 +37,7 @@ public: G1ParCopyClosure _oops_in_cld; // We do not need (and actually should not) collect oops from nmethods into the // optional collection set as we already automatically collect the corresponding - // nmethods in the region's strong code roots set. So set G1BarrierNoOptRoots in + // nmethods in the region's code roots set. So set G1BarrierNoOptRoots in // this closure. // If these were present there would be opportunity for multiple threads to try // to change this oop* at the same time. Since embedded oops are not necessarily diff --git a/src/hotspot/share/gc/g1/g1YoungCollector.cpp b/src/hotspot/share/gc/g1/g1YoungCollector.cpp index 1a73ed30e26..d5e1774a8bd 100644 --- a/src/hotspot/share/gc/g1/g1YoungCollector.cpp +++ b/src/hotspot/share/gc/g1/g1YoungCollector.cpp @@ -395,7 +395,7 @@ class G1PrepareEvacuationTask : public WorkerTask { cast_to_oop(hr->bottom())->size() * HeapWordSize, p2i(hr->bottom()), hr->rem_set()->occupied(), - hr->rem_set()->strong_code_roots_list_length(), + hr->rem_set()->code_roots_list_length(), _g1h->concurrent_mark()->next_mark_bitmap()->is_marked(hr->bottom()), _g1h->is_humongous_reclaim_candidate(index), cast_to_oop(hr->bottom())->is_typeArray() diff --git a/src/hotspot/share/gc/g1/heapRegion.cpp b/src/hotspot/share/gc/g1/heapRegion.cpp index 4994070eaca..a69fdea82a6 100644 --- a/src/hotspot/share/gc/g1/heapRegion.cpp +++ b/src/hotspot/share/gc/g1/heapRegion.cpp @@ -304,28 +304,28 @@ void HeapRegion::note_self_forwarding_removal_end(size_t marked_bytes) { // Code roots support -void HeapRegion::add_strong_code_root(nmethod* nm) { +void HeapRegion::add_code_root(nmethod* nm) { HeapRegionRemSet* hrrs = rem_set(); - hrrs->add_strong_code_root(nm); + hrrs->add_code_root(nm); } -void HeapRegion::add_strong_code_root_locked(nmethod* nm) { +void HeapRegion::add_code_root_locked(nmethod* nm) { assert_locked_or_safepoint(CodeCache_lock); HeapRegionRemSet* hrrs = rem_set(); - hrrs->add_strong_code_root_locked(nm); + hrrs->add_code_root_locked(nm); } -void HeapRegion::remove_strong_code_root(nmethod* nm) { +void HeapRegion::remove_code_root(nmethod* nm) { HeapRegionRemSet* hrrs = rem_set(); - hrrs->remove_strong_code_root(nm); + hrrs->remove_code_root(nm); } -void HeapRegion::strong_code_roots_do(CodeBlobClosure* blk) const { +void HeapRegion::code_roots_do(CodeBlobClosure* blk) const { HeapRegionRemSet* hrrs = rem_set(); - hrrs->strong_code_roots_do(blk); + hrrs->code_roots_do(blk); } -class VerifyStrongCodeRootOopClosure: public OopClosure { +class VerifyCodeRootOopClosure: public OopClosure { const HeapRegion* _hr; bool _failures; bool _has_oops_in_region; @@ -353,7 +353,7 @@ class VerifyStrongCodeRootOopClosure: public OopClosure { } public: - VerifyStrongCodeRootOopClosure(const HeapRegion* hr): + VerifyCodeRootOopClosure(const HeapRegion* hr): _hr(hr), _failures(false), _has_oops_in_region(false) {} void do_oop(narrowOop* p) { do_oop_work(p); } @@ -363,11 +363,11 @@ public: bool has_oops_in_region() { return _has_oops_in_region; } }; -class VerifyStrongCodeRootCodeBlobClosure: public CodeBlobClosure { +class VerifyCodeRootCodeBlobClosure: public CodeBlobClosure { const HeapRegion* _hr; bool _failures; public: - VerifyStrongCodeRootCodeBlobClosure(const HeapRegion* hr) : + VerifyCodeRootCodeBlobClosure(const HeapRegion* hr) : _hr(hr), _failures(false) {} void do_code_blob(CodeBlob* cb) { @@ -375,14 +375,14 @@ public: if (nm != NULL) { // Verify that the nemthod is live if (!nm->is_alive()) { - log_error(gc, verify)("region [" PTR_FORMAT "," PTR_FORMAT "] has dead nmethod " PTR_FORMAT " in its strong code roots", + log_error(gc, verify)("region [" PTR_FORMAT "," PTR_FORMAT "] has dead nmethod " PTR_FORMAT " in its code roots", p2i(_hr->bottom()), p2i(_hr->end()), p2i(nm)); _failures = true; } else { - VerifyStrongCodeRootOopClosure oop_cl(_hr); + VerifyCodeRootOopClosure oop_cl(_hr); nm->oops_do(&oop_cl); if (!oop_cl.has_oops_in_region()) { - log_error(gc, verify)("region [" PTR_FORMAT "," PTR_FORMAT "] has nmethod " PTR_FORMAT " in its strong code roots with no pointers into region", + log_error(gc, verify)("region [" PTR_FORMAT "," PTR_FORMAT "] has nmethod " PTR_FORMAT " in its code roots with no pointers into region", p2i(_hr->bottom()), p2i(_hr->end()), p2i(nm)); _failures = true; } else if (oop_cl.failures()) { @@ -397,47 +397,47 @@ public: bool failures() { return _failures; } }; -void HeapRegion::verify_strong_code_roots(VerifyOption vo, bool* failures) const { +void HeapRegion::verify_code_roots(VerifyOption vo, bool* failures) const { if (!G1VerifyHeapRegionCodeRoots) { // We're not verifying code roots. return; } if (vo == VerifyOption_G1UseFullMarking) { // Marking verification during a full GC is performed after class - // unloading, code cache unloading, etc so the strong code roots + // unloading, code cache unloading, etc so the code roots // attached to each heap region are in an inconsistent state. They won't - // be consistent until the strong code roots are rebuilt after the - // actual GC. Skip verifying the strong code roots in this particular + // be consistent until the code roots are rebuilt after the + // actual GC. Skip verifying the code roots in this particular // time. assert(VerifyDuringGC, "only way to get here"); return; } HeapRegionRemSet* hrrs = rem_set(); - size_t strong_code_roots_length = hrrs->strong_code_roots_list_length(); + size_t code_roots_length = hrrs->code_roots_list_length(); // if this region is empty then there should be no entries - // on its strong code root list + // on its code root list if (is_empty()) { - if (strong_code_roots_length > 0) { + if (code_roots_length > 0) { log_error(gc, verify)("region " HR_FORMAT " is empty but has " SIZE_FORMAT " code root entries", - HR_FORMAT_PARAMS(this), strong_code_roots_length); + HR_FORMAT_PARAMS(this), code_roots_length); *failures = true; } return; } if (is_continues_humongous()) { - if (strong_code_roots_length > 0) { + if (code_roots_length > 0) { log_error(gc, verify)("region " HR_FORMAT " is a continuation of a humongous region but has " SIZE_FORMAT " code root entries", - HR_FORMAT_PARAMS(this), strong_code_roots_length); + HR_FORMAT_PARAMS(this), code_roots_length); *failures = true; } return; } - VerifyStrongCodeRootCodeBlobClosure cb_cl(this); - strong_code_roots_do(&cb_cl); + VerifyCodeRootCodeBlobClosure cb_cl(this); + code_roots_do(&cb_cl); if (cb_cl.failures()) { *failures = true; @@ -730,7 +730,7 @@ void HeapRegion::verify(VerifyOption vo, return; } - verify_strong_code_roots(vo, failures); + verify_code_roots(vo, failures); } void HeapRegion::verify_rem_set(VerifyOption vo, bool* failures) const { diff --git a/src/hotspot/share/gc/g1/heapRegion.hpp b/src/hotspot/share/gc/g1/heapRegion.hpp index 782de66a1cb..e70c6481fde 100644 --- a/src/hotspot/share/gc/g1/heapRegion.hpp +++ b/src/hotspot/share/gc/g1/heapRegion.hpp @@ -572,20 +572,20 @@ public: // Routines for managing a list of code roots (attached to the // this region's RSet) that point into this heap region. - void add_strong_code_root(nmethod* nm); - void add_strong_code_root_locked(nmethod* nm); - void remove_strong_code_root(nmethod* nm); + void add_code_root(nmethod* nm); + void add_code_root_locked(nmethod* nm); + void remove_code_root(nmethod* nm); // Applies blk->do_code_blob() to each of the entries in - // the strong code roots list for this region - void strong_code_roots_do(CodeBlobClosure* blk) const; + // the code roots list for this region + void code_roots_do(CodeBlobClosure* blk) const; uint node_index() const { return _node_index; } void set_node_index(uint node_index) { _node_index = node_index; } - // Verify that the entries on the strong code root list for this + // Verify that the entries on the code root list for this // region are live and include at least one pointer into this region. - void verify_strong_code_roots(VerifyOption vo, bool* failures) const; + void verify_code_roots(VerifyOption vo, bool* failures) const; void print() const; void print_on(outputStream* st) const; diff --git a/src/hotspot/share/gc/g1/heapRegionRemSet.cpp b/src/hotspot/share/gc/g1/heapRegionRemSet.cpp index d4570173f0e..9e6c31ffdc1 100644 --- a/src/hotspot/share/gc/g1/heapRegionRemSet.cpp +++ b/src/hotspot/share/gc/g1/heapRegionRemSet.cpp @@ -122,19 +122,19 @@ void HeapRegionRemSet::print_static_mem_size(outputStream* out) { // When concurrent readers access the contains() function // (during the evacuation phase) no removals are allowed. -void HeapRegionRemSet::add_strong_code_root(nmethod* nm) { +void HeapRegionRemSet::add_code_root(nmethod* nm) { assert(nm != NULL, "sanity"); assert((!CodeCache_lock->owned_by_self() || SafepointSynchronize::is_at_safepoint()), - "should call add_strong_code_root_locked instead. CodeCache_lock->owned_by_self(): %s, is_at_safepoint(): %s", + "should call add_code_root_locked instead. CodeCache_lock->owned_by_self(): %s, is_at_safepoint(): %s", BOOL_TO_STR(CodeCache_lock->owned_by_self()), BOOL_TO_STR(SafepointSynchronize::is_at_safepoint())); // Optimistic unlocked contains-check if (!_code_roots.contains(nm)) { MutexLocker ml(&_m, Mutex::_no_safepoint_check_flag); - add_strong_code_root_locked(nm); + add_code_root_locked(nm); } } -void HeapRegionRemSet::add_strong_code_root_locked(nmethod* nm) { +void HeapRegionRemSet::add_code_root_locked(nmethod* nm) { assert(nm != NULL, "sanity"); assert((CodeCache_lock->owned_by_self() || (SafepointSynchronize::is_at_safepoint() && @@ -145,7 +145,7 @@ void HeapRegionRemSet::add_strong_code_root_locked(nmethod* nm) { _code_roots.add(nm); } -void HeapRegionRemSet::remove_strong_code_root(nmethod* nm) { +void HeapRegionRemSet::remove_code_root(nmethod* nm) { assert(nm != NULL, "sanity"); assert_locked_or_safepoint(CodeCache_lock); @@ -156,14 +156,14 @@ void HeapRegionRemSet::remove_strong_code_root(nmethod* nm) { guarantee(!_code_roots.contains(nm), "duplicate entry found"); } -void HeapRegionRemSet::strong_code_roots_do(CodeBlobClosure* blk) const { +void HeapRegionRemSet::code_roots_do(CodeBlobClosure* blk) const { _code_roots.nmethods_do(blk); } -void HeapRegionRemSet::clean_strong_code_roots(HeapRegion* hr) { +void HeapRegionRemSet::clean_code_roots(HeapRegion* hr) { _code_roots.clean(hr); } -size_t HeapRegionRemSet::strong_code_roots_mem_size() { +size_t HeapRegionRemSet::code_roots_mem_size() { return _code_roots.mem_size(); } diff --git a/src/hotspot/share/gc/g1/heapRegionRemSet.hpp b/src/hotspot/share/gc/g1/heapRegionRemSet.hpp index 2a1b3c5527b..04b585661f8 100644 --- a/src/hotspot/share/gc/g1/heapRegionRemSet.hpp +++ b/src/hotspot/share/gc/g1/heapRegionRemSet.hpp @@ -73,11 +73,11 @@ public: } bool is_empty() const { - return (strong_code_roots_list_length() == 0) && cardset_is_empty(); + return (code_roots_list_length() == 0) && cardset_is_empty(); } bool occupancy_less_or_equal_than(size_t occ) const { - return (strong_code_roots_list_length() == 0) && _card_set.occupancy_less_or_equal_to(occ); + return (code_roots_list_length() == 0) && _card_set.occupancy_less_or_equal_to(occ); } // Iterate the card based remembered set for merging them into the card table. @@ -128,12 +128,12 @@ public: G1SegmentedArrayMemoryStats card_set_memory_stats() const; - // The actual # of bytes this hr_remset takes up. Also includes the strong code + // The actual # of bytes this hr_remset takes up. Also includes the code // root set. size_t mem_size() { return _card_set.mem_size() - + (sizeof(HeapRegionRemSet) - sizeof(G1CardSet)) // Avoid double-counting G1CardSet. - + strong_code_roots_mem_size(); + + (sizeof(HeapRegionRemSet) - sizeof(G1CardSet)) // Avoid double-counting G1CardSet. + + code_roots_mem_size(); } size_t wasted_mem_size() { @@ -154,30 +154,29 @@ public: // Routines for managing the list of code roots that point into // the heap region that owns this RSet. - void add_strong_code_root(nmethod* nm); - void add_strong_code_root_locked(nmethod* nm); - void remove_strong_code_root(nmethod* nm); + void add_code_root(nmethod* nm); + void add_code_root_locked(nmethod* nm); + void remove_code_root(nmethod* nm); - // Applies blk->do_code_blob() to each of the entries in - // the strong code roots list - void strong_code_roots_do(CodeBlobClosure* blk) const; + // Applies blk->do_code_blob() to each of the entries in _code_roots + void code_roots_do(CodeBlobClosure* blk) const; - void clean_strong_code_roots(HeapRegion* hr); + void clean_code_roots(HeapRegion* hr); - // Returns the number of elements in the strong code roots list - size_t strong_code_roots_list_length() const { + // Returns the number of elements in _code_roots + size_t code_roots_list_length() const { return _code_roots.length(); } - // Returns true if the strong code roots contains the given + // Returns true if the code roots contains the given // nmethod. - bool strong_code_roots_list_contains(nmethod* nm) { + bool code_roots_list_contains(nmethod* nm) { return _code_roots.contains(nm); } // Returns the amount of memory, in bytes, currently - // consumed by the strong code roots. - size_t strong_code_roots_mem_size(); + // consumed by the code roots. + size_t code_roots_mem_size(); static void invalidate_from_card_cache(uint start_idx, size_t num_regions) { G1FromCardCache::invalidate(start_idx, num_regions); -- GitLab From c5a86120df7105cf612d513b5bd394501c00efed Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Tue, 1 Feb 2022 12:23:44 +0000 Subject: [PATCH 359/564] 8280458: G1: Remove G1BlockOffsetTablePart::_next_offset_threshold Reviewed-by: tschatzl, iwalulya, sjohanss --- .../share/gc/g1/g1BlockOffsetTable.cpp | 70 +++++++------------ .../share/gc/g1/g1BlockOffsetTable.hpp | 57 +++++---------- .../share/gc/g1/g1BlockOffsetTable.inline.hpp | 6 +- src/hotspot/share/gc/g1/g1CollectedHeap.cpp | 1 - src/hotspot/share/gc/g1/g1EvacFailure.cpp | 2 - .../share/gc/g1/g1FullGCCompactionPoint.cpp | 3 - .../share/gc/g1/g1ParScanThreadState.cpp | 2 +- src/hotspot/share/gc/g1/heapRegion.cpp | 8 +-- src/hotspot/share/gc/g1/heapRegion.hpp | 11 +-- src/hotspot/share/gc/g1/heapRegion.inline.hpp | 21 +----- 10 files changed, 50 insertions(+), 131 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1BlockOffsetTable.cpp b/src/hotspot/share/gc/g1/g1BlockOffsetTable.cpp index 017dd232531..7bbfe60e8a8 100644 --- a/src/hotspot/share/gc/g1/g1BlockOffsetTable.cpp +++ b/src/hotspot/share/gc/g1/g1BlockOffsetTable.cpp @@ -74,7 +74,6 @@ void G1BlockOffsetTable::check_index(size_t index, const char* msg) const { ////////////////////////////////////////////////////////////////////// G1BlockOffsetTablePart::G1BlockOffsetTablePart(G1BlockOffsetTable* array, HeapRegion* hr) : - _next_offset_threshold(NULL), _bot(array), _hr(hr) { @@ -204,45 +203,40 @@ void G1BlockOffsetTablePart::check_all_cards(size_t start_card, size_t end_card) } // -// threshold_ +// cur_card_boundary // | _index_ // v v // +-------+-------+-------+-------+-------+ // | i-1 | i | i+1 | i+2 | i+3 | // +-------+-------+-------+-------+-------+ // ( ^ ] -// block-start +// blk_start // -void G1BlockOffsetTablePart::alloc_block_work(HeapWord** threshold_, HeapWord* blk_start, +void G1BlockOffsetTablePart::alloc_block_work(HeapWord* blk_start, HeapWord* blk_end) { - // For efficiency, do copy-in/copy-out. - HeapWord* threshold = *threshold_; - size_t index = _bot->index_for_raw(threshold); + HeapWord* const cur_card_boundary = align_up_by_card_size(blk_start); + size_t const index = _bot->index_for_raw(cur_card_boundary); assert(blk_start != NULL && blk_end > blk_start, "phantom block"); - assert(blk_end > threshold, "should be past threshold"); - assert(blk_start <= threshold, "blk_start should be at or before threshold"); - assert(pointer_delta(threshold, blk_start) < BOTConstants::card_size_in_words(), + assert(blk_end > cur_card_boundary, "should be past cur_card_boundary"); + assert(blk_start <= cur_card_boundary, "blk_start should be at or before cur_card_boundary"); + assert(pointer_delta(cur_card_boundary, blk_start) < BOTConstants::card_size_in_words(), "offset should be < BOTConstants::card_size_in_words()"); assert(G1CollectedHeap::heap()->is_in_reserved(blk_start), "reference must be into the heap"); - assert(G1CollectedHeap::heap()->is_in_reserved(blk_end-1), + assert(G1CollectedHeap::heap()->is_in_reserved(blk_end - 1), "limit must be within the heap"); - assert(threshold == _bot->_reserved.start() + index*BOTConstants::card_size_in_words(), - "index must agree with threshold"); + assert(cur_card_boundary == _bot->_reserved.start() + index*BOTConstants::card_size_in_words(), + "index must agree with cur_card_boundary"); - DEBUG_ONLY(size_t orig_index = index;) + // Mark the card that holds the offset into the block. + _bot->set_offset_array(index, cur_card_boundary, blk_start); - // Mark the card that holds the offset into the block. Note - // that _next_offset_threshold is not updated until the end - // of this method. - _bot->set_offset_array(index, threshold, blk_start); + // We need to now mark the subsequent cards that this block spans. - // We need to now mark the subsequent cards that this blk spans. - - // Index of card on which blk ends. - size_t end_index = _bot->index_for(blk_end - 1); + // Index of card on which the block ends. + size_t end_index = _bot->index_for(blk_end - 1); // Are there more cards left to be updated? if (index + 1 <= end_index) { @@ -253,27 +247,25 @@ void G1BlockOffsetTablePart::alloc_block_work(HeapWord** threshold_, HeapWord* b set_remainder_to_point_to_start(rem_st, rem_end); } - // Calculate threshold_ this way because end_index +#ifdef ASSERT + // Calculate new_card_boundary this way because end_index // may be the last valid index in the covered region. - threshold = _bot->address_for_index(end_index) + BOTConstants::card_size_in_words(); - assert(threshold >= blk_end, "Incorrect offset threshold"); + HeapWord* new_card_boundary = _bot->address_for_index(end_index) + BOTConstants::card_size_in_words(); + assert(new_card_boundary >= blk_end, "postcondition"); - *threshold_ = threshold; - -#ifdef ASSERT // The offset can be 0 if the block starts on a boundary. That // is checked by an assertion above. size_t start_index = _bot->index_for(blk_start); HeapWord* boundary = _bot->address_for_index(start_index); - assert((_bot->offset_array(orig_index) == 0 && blk_start == boundary) || - (_bot->offset_array(orig_index) > 0 && _bot->offset_array(orig_index) < BOTConstants::card_size_in_words()), + assert((_bot->offset_array(index) == 0 && blk_start == boundary) || + (_bot->offset_array(index) > 0 && _bot->offset_array(index) < BOTConstants::card_size_in_words()), "offset array should have been set - " - "orig_index offset: %u, " + "index offset: %u, " "blk_start: " PTR_FORMAT ", " "boundary: " PTR_FORMAT, - (uint)_bot->offset_array(orig_index), + (uint)_bot->offset_array(index), p2i(blk_start), p2i(boundary)); - for (size_t j = orig_index + 1; j <= end_index; j++) { + for (size_t j = index + 1; j <= end_index; j++) { assert(_bot->offset_array(j) > 0 && _bot->offset_array(j) <= (u_char) (BOTConstants::card_size_in_words()+BOTConstants::N_powers-1), @@ -289,8 +281,6 @@ void G1BlockOffsetTablePart::alloc_block_work(HeapWord** threshold_, HeapWord* b void G1BlockOffsetTablePart::verify() const { assert(_hr->bottom() < _hr->top(), "Only non-empty regions should be verified."); size_t start_card = _bot->index_for(_hr->bottom()); - // Do not verify beyond the BOT allocation threshold. - assert(_hr->top() <= _next_offset_threshold, "invariant"); size_t end_card = _bot->index_for(_hr->top() - 1); for (size_t current_card = start_card; current_card < end_card; current_card++) { @@ -341,20 +331,10 @@ void G1BlockOffsetTablePart::print_on(outputStream* out) { i, p2i(_bot->address_for_index(i)), (uint) _bot->offset_array(i)); } - out->print_cr(" next offset threshold: " PTR_FORMAT, p2i(_next_offset_threshold)); } #endif // !PRODUCT -void G1BlockOffsetTablePart::reset_bot() { - _next_offset_threshold = _hr->bottom(); -} - -bool G1BlockOffsetTablePart::is_empty() const { - return _next_offset_threshold == _hr->bottom(); -} - void G1BlockOffsetTablePart::set_for_starts_humongous(HeapWord* obj_top, size_t fill_size) { - assert(is_empty(), "first obj"); alloc_block(_hr->bottom(), obj_top); if (fill_size > 0) { alloc_block(obj_top, fill_size); diff --git a/src/hotspot/share/gc/g1/g1BlockOffsetTable.hpp b/src/hotspot/share/gc/g1/g1BlockOffsetTable.hpp index 505c528da9f..04c966a29cc 100644 --- a/src/hotspot/share/gc/g1/g1BlockOffsetTable.hpp +++ b/src/hotspot/share/gc/g1/g1BlockOffsetTable.hpp @@ -111,9 +111,6 @@ class G1BlockOffsetTablePart { friend class HeapRegion; friend class VMStructs; private: - // allocation boundary at which offset array must be updated - HeapWord* _next_offset_threshold; - // This is the global BlockOffsetTable. G1BlockOffsetTable* _bot; @@ -140,19 +137,23 @@ private: inline HeapWord* forward_to_block_containing_addr(HeapWord* q, HeapWord* n, const void* addr) const; - // Requires that "*threshold_" be the first array entry boundary at or - // above "blk_start". If the block starts at or crosses "*threshold_", records - // "blk_start" as the appropriate block start for the array index - // starting at "*threshold_", and for any other indices crossed by the - // block. Updates "*threshold_" to correspond to the first index after - // the block end. - void alloc_block_work(HeapWord** threshold_, - HeapWord* blk_start, - HeapWord* blk_end); + // Update BOT entries corresponding to the mem range [blk_start, blk_end). + void alloc_block_work(HeapWord* blk_start, HeapWord* blk_end); void check_all_cards(size_t left_card, size_t right_card) const; public: + static HeapWord* align_up_by_card_size(HeapWord* const addr) { + return align_up(addr, BOTConstants::card_size()); + } + + static bool is_crossing_card_boundary(HeapWord* const obj_start, + HeapWord* const obj_end) { + HeapWord* cur_card_boundary = align_up_by_card_size(obj_start); + // strictly greater-than + return obj_end > cur_card_boundary; + } + // The elements of the array are initialized to zero. G1BlockOffsetTablePart(G1BlockOffsetTable* array, HeapRegion* hr); @@ -160,43 +161,21 @@ public: void verify() const; - inline HeapWord* align_up_by_card_size(HeapWord* const addr) const; - // Returns the address of the start of the block containing "addr", or // else "null" if it is covered by no block. (May have side effects, // namely updating of shared array entries that "point" too far // backwards. This can occur, for example, when lab allocation is used // in a space covered by the table.) inline HeapWord* block_start(const void* addr); - // Same as above, but does not have any of the possible side effects - // discussed above. - inline HeapWord* block_start_const(const void* addr) const; - // Reset bot to be empty. - void reset_bot(); - - bool is_empty() const; - - // Return the next threshold, the point at which the table should be - // updated. - HeapWord* threshold() const { return _next_offset_threshold; } - - // Sets the threshold explicitly to keep it consistent with what has been - // updated. This needs to be done when the threshold is not used for updating - // the bot, for example when promoting to old in young collections. - void set_threshold(HeapWord* threshold) { _next_offset_threshold = threshold; } - - // These must be guaranteed to work properly (i.e., do nothing) - // when "blk_start" ("blk" for second version) is "NULL". In this - // implementation, that's true because NULL is represented as 0, and thus - // never exceeds the "_next_offset_threshold". void alloc_block(HeapWord* blk_start, HeapWord* blk_end) { - if (blk_end > _next_offset_threshold) { - alloc_block_work(&_next_offset_threshold, blk_start, blk_end); + if (is_crossing_card_boundary(blk_start, blk_end)) { + alloc_block_work(blk_start, blk_end); } } - void alloc_block(HeapWord* blk, size_t size) { - alloc_block(blk, blk+size); + + void alloc_block(HeapWord* blk_start, size_t size) { + alloc_block(blk_start, blk_start + size); } void set_for_starts_humongous(HeapWord* obj_top, size_t fill_size); diff --git a/src/hotspot/share/gc/g1/g1BlockOffsetTable.inline.hpp b/src/hotspot/share/gc/g1/g1BlockOffsetTable.inline.hpp index 7ae313f2f70..f70cb118627 100644 --- a/src/hotspot/share/gc/g1/g1BlockOffsetTable.inline.hpp +++ b/src/hotspot/share/gc/g1/g1BlockOffsetTable.inline.hpp @@ -30,11 +30,7 @@ #include "gc/g1/heapRegion.hpp" #include "gc/shared/memset_with_concurrent_readers.hpp" #include "runtime/atomic.hpp" - -inline HeapWord* G1BlockOffsetTablePart::align_up_by_card_size(HeapWord* const addr) const { - assert(addr >= _hr->bottom() && addr < _hr->top(), "invalid address"); - return align_up(addr, BOTConstants::card_size()); -} +#include "oops/oop.inline.hpp" inline HeapWord* G1BlockOffsetTablePart::block_start(const void* addr) { assert(addr >= _hr->bottom() && addr < _hr->top(), "invalid address"); diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index 89c95c620ba..adc3e66d316 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -3295,7 +3295,6 @@ void G1CollectedHeap::retire_gc_alloc_region(HeapRegion* alloc_region, _bytes_used_during_gc += allocated_bytes; if (dest.is_old()) { old_set_add(alloc_region); - alloc_region->update_bot_threshold(); } else { assert(dest.is_young(), "Retiring alloc region should be young (%d)", dest.type()); _survivor.add_used_bytes(allocated_bytes); diff --git a/src/hotspot/share/gc/g1/g1EvacFailure.cpp b/src/hotspot/share/gc/g1/g1EvacFailure.cpp index fd065df17c6..2a4f46ff16e 100644 --- a/src/hotspot/share/gc/g1/g1EvacFailure.cpp +++ b/src/hotspot/share/gc/g1/g1EvacFailure.cpp @@ -187,8 +187,6 @@ public: hr->note_self_forwarding_removal_start(during_concurrent_start, during_concurrent_mark); - hr->reset_bot(); - _phase_times->record_or_add_thread_work_item(G1GCPhaseTimes::RestoreRetainedRegions, _worker_id, 1, diff --git a/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.cpp b/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.cpp index 25ff38da77f..527397de55e 100644 --- a/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.cpp +++ b/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.cpp @@ -47,9 +47,6 @@ void G1FullGCCompactionPoint::update() { void G1FullGCCompactionPoint::initialize_values(bool init_threshold) { _compaction_top = _current_region->compaction_top(); - if (init_threshold) { - _current_region->initialize_bot_threshold(); - } } bool G1FullGCCompactionPoint::has_regions() { diff --git a/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp b/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp index f2889e78779..3cc3c5c0120 100644 --- a/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp +++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp @@ -437,7 +437,7 @@ void G1ParScanThreadState::undo_allocation(G1HeapRegionAttr dest_attr, void G1ParScanThreadState::update_bot_after_copying(oop obj, size_t word_sz) { HeapWord* obj_start = cast_from_oop(obj); HeapRegion* region = _g1h->heap_region_containing(obj_start); - region->update_bot_if_crossing_boundary(obj_start, word_sz); + region->update_bot_for_obj(obj_start, word_sz); } // Private inline function, for direct internal use and providing the diff --git a/src/hotspot/share/gc/g1/heapRegion.cpp b/src/hotspot/share/gc/g1/heapRegion.cpp index a69fdea82a6..93baa238351 100644 --- a/src/hotspot/share/gc/g1/heapRegion.cpp +++ b/src/hotspot/share/gc/g1/heapRegion.cpp @@ -260,7 +260,6 @@ void HeapRegion::initialize(bool clear_space, bool mangle_space) { set_top(bottom()); set_compaction_top(bottom()); - reset_bot(); hr_clear(false /*clear_space*/); } @@ -780,7 +779,6 @@ void HeapRegion::clear(bool mangle_space) { if (ZapUnusedHeapArea && mangle_space) { mangle_unused_area(); } - reset_bot(); } #ifndef PRODUCT @@ -789,10 +787,6 @@ void HeapRegion::mangle_unused_area() { } #endif -void HeapRegion::initialize_bot_threshold() { - _bot_part.reset_bot(); -} - void HeapRegion::alloc_block_in_bot(HeapWord* start, HeapWord* end) { _bot_part.alloc_block(start, end); } @@ -810,7 +804,7 @@ void HeapRegion::object_iterate(ObjectClosure* blk) { void HeapRegion::fill_with_dummy_object(HeapWord* address, size_t word_size, bool zap) { // Keep the BOT in sync for old generation regions. if (is_old()) { - update_bot_if_crossing_boundary(address, word_size); + update_bot_for_obj(address, word_size); } // Fill in the object. CollectedHeap::fill_with_object(address, word_size, zap); diff --git a/src/hotspot/share/gc/g1/heapRegion.hpp b/src/hotspot/share/gc/g1/heapRegion.hpp index e70c6481fde..d3af9faf9c7 100644 --- a/src/hotspot/share/gc/g1/heapRegion.hpp +++ b/src/hotspot/share/gc/g1/heapRegion.hpp @@ -163,11 +163,10 @@ public: inline HeapWord* allocate(size_t min_word_size, size_t desired_word_size, size_t* actual_size); // Update BOT if this obj is the first entering a new card (i.e. crossing the card boundary). - inline void update_bot_if_crossing_boundary(HeapWord* obj_start, size_t obj_size); + inline void update_bot_for_obj(HeapWord* obj_start, size_t obj_size); // Full GC support methods. - void initialize_bot_threshold(); void alloc_block_in_bot(HeapWord* start, HeapWord* end); // Update heap region that has been compacted to be consistent after Full GC. @@ -192,18 +191,10 @@ public: template inline void apply_to_marked_objects(G1CMBitMap* bitmap, ApplyToMarkedClosure* closure); - void reset_bot() { - _bot_part.reset_bot(); - } - void update_bot() { _bot_part.update(); } - void update_bot_threshold() { - _bot_part.set_threshold(top()); - } - private: // The remembered set for this region. HeapRegionRemSet* _rem_set; diff --git a/src/hotspot/share/gc/g1/heapRegion.inline.hpp b/src/hotspot/share/gc/g1/heapRegion.inline.hpp index 2a47d92a475..2f78f30b419 100644 --- a/src/hotspot/share/gc/g1/heapRegion.inline.hpp +++ b/src/hotspot/share/gc/g1/heapRegion.inline.hpp @@ -183,10 +183,6 @@ inline void HeapRegion::reset_skip_compacting_after_full_gc() { } inline void HeapRegion::reset_after_full_gc_common() { - if (is_empty()) { - reset_bot(); - } - // Clear unused heap memory in debug builds. if (ZapUnusedHeapArea) { mangle_unused_area(); @@ -231,28 +227,17 @@ inline HeapWord* HeapRegion::allocate(size_t min_word_size, return allocate_impl(min_word_size, desired_word_size, actual_word_size); } -inline void HeapRegion::update_bot_if_crossing_boundary(HeapWord* obj_start, size_t obj_size) { +inline void HeapRegion::update_bot_for_obj(HeapWord* obj_start, size_t obj_size) { assert(is_old(), "should only do BOT updates for old regions"); - HeapWord* obj_end = obj_start + obj_size; + HeapWord* obj_end = obj_start + obj_size; assert(is_in(obj_start), "obj_start must be in this region: " HR_FORMAT " obj_start " PTR_FORMAT " obj_end " PTR_FORMAT, HR_FORMAT_PARAMS(this), p2i(obj_start), p2i(obj_end)); - HeapWord* cur_card_boundary = _bot_part.align_up_by_card_size(obj_start); - - // strictly greater-than - bool cross_card_boundary = (obj_end > cur_card_boundary); - - if (cross_card_boundary) { - // Creating a dummy variable inside this `if` as the arg of `&`; this - // avoids unnecessary loads in the assembly code on the fast path (the - // bot-not-updating case). - HeapWord* dummy = cur_card_boundary; - _bot_part.alloc_block_work(&dummy, obj_start, obj_end); - } + _bot_part.alloc_block(obj_start, obj_end); } inline void HeapRegion::note_start_of_marking() { -- GitLab From 1f6fcbe2f3da4c63976b1564ec2170e4757fadcc Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Tue, 1 Feb 2022 15:44:26 +0000 Subject: [PATCH 360/564] 8278475: G1 dirty card refinement by Java threads may get unnecessarily paused Reviewed-by: tschatzl, iwalulya --- src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp b/src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp index 4ef40d29f16..22e8e218057 100644 --- a/src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp +++ b/src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp @@ -501,6 +501,14 @@ void G1DirtyCardQueueSet::handle_completed_buffer(BufferNode* new_node, return; } + // Don't try to process a buffer that will just get immediately paused. + // When going into a safepoint it's just a waste of effort. + // When coming out of a safepoint, Java threads may be running before the + // yield request (for non-Java threads) has been cleared. + if (SuspendibleThreadSet::should_yield()) { + return; + } + // Only Java threads perform mutator refinement. if (!Thread::current()->is_Java_thread()) { return; -- GitLab From 5080e815b4385751734054b5f889c4d89cfcdeb4 Mon Sep 17 00:00:00 2001 From: Chris Plummer Date: Tue, 1 Feb 2022 15:59:35 +0000 Subject: [PATCH 361/564] 8280770: serviceability/sa/ClhsdbThreadContext.java sometimes fails with 'Thread "SteadyStateThread"' missing from stdout/stderr Reviewed-by: sspitsyn, dholmes --- .../sa/ClhsdbThreadContext.java | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbThreadContext.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbThreadContext.java index 207978ba5c6..e84ae52e920 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbThreadContext.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbThreadContext.java @@ -26,6 +26,7 @@ import java.util.List; import java.util.Map; import jdk.test.lib.apps.LingeredApp; +import jdk.test.lib.Platform; import jtreg.SkippedException; /** @@ -82,15 +83,22 @@ public class ClhsdbThreadContext { cmdStr = "threadcontext -v " + threadID; cmds = List.of(cmdStr); expStrMap = new HashMap<>(); - expStrMap.put(cmdStr, List.of( - "Thread \"SteadyStateThread\"", - "java.lang.Thread.State: BLOCKED", - "In java stack \\[0x\\p{XDigit}+,0x\\p{XDigit}+,0x\\p{XDigit}+\\] for thread")); unexpStrMap = new HashMap<>(); - unexpStrMap.put(cmdStr, List.of( - "Thread \"Common-Cleaner\"", - "Thread \"Service Thread\"", - "Thread \"Finalizer\"")); + if (Platform.isWindows()) { + // On windows thread IDs are not guaranteed to be the same each time you attach, + // so the ID we gleaned above for SteadyStateThread may not actually be for + // SteadyStateThread when we attach for the next threadcontext command, so we + // choose not to check the result on Windows. + } else { + expStrMap.put(cmdStr, List.of( + "Thread \"SteadyStateThread\"", + "java.lang.Thread.State: BLOCKED", + "In java stack \\[0x\\p{XDigit}+,0x\\p{XDigit}+,0x\\p{XDigit}+\\] for thread")); + unexpStrMap.put(cmdStr, List.of( + "Thread \"Common-Cleaner\"", + "Thread \"Service Thread\"", + "Thread \"Finalizer\"")); + } test.run(theApp.getPid(), cmds, expStrMap, unexpStrMap); // Run threadcontext on all threads in verbose mode -- GitLab From 4532c3a1639af0b4ff8c4f42c3796fa73ca5be83 Mon Sep 17 00:00:00 2001 From: Chris Plummer Date: Tue, 1 Feb 2022 16:02:10 +0000 Subject: [PATCH 362/564] 8280554: resourcehogs/serviceability/sa/ClhsdbRegionDetailsScanOopsForG1.java can fail if GC is triggered Reviewed-by: alanb, amenkov, lmesnik --- .../serviceability/sa/ClhsdbRegionDetailsScanOopsForG1.java | 3 +-- .../serviceability/sa/LingeredAppWithLargeStringArray.java | 5 ++++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/test/hotspot/jtreg/resourcehogs/serviceability/sa/ClhsdbRegionDetailsScanOopsForG1.java b/test/hotspot/jtreg/resourcehogs/serviceability/sa/ClhsdbRegionDetailsScanOopsForG1.java index 9e04c9ac89a..5694d0fb528 100644 --- a/test/hotspot/jtreg/resourcehogs/serviceability/sa/ClhsdbRegionDetailsScanOopsForG1.java +++ b/test/hotspot/jtreg/resourcehogs/serviceability/sa/ClhsdbRegionDetailsScanOopsForG1.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -63,7 +63,6 @@ public class ClhsdbRegionDetailsScanOopsForG1 { expStrMap.put("g1regiondetails", List.of( "Region", "Eden", - "Survivor", "StartsHumongous", "ContinuesHumongous", "Free")); diff --git a/test/hotspot/jtreg/resourcehogs/serviceability/sa/LingeredAppWithLargeStringArray.java b/test/hotspot/jtreg/resourcehogs/serviceability/sa/LingeredAppWithLargeStringArray.java index bc7aec91f99..adc81b1f46d 100644 --- a/test/hotspot/jtreg/resourcehogs/serviceability/sa/LingeredAppWithLargeStringArray.java +++ b/test/hotspot/jtreg/resourcehogs/serviceability/sa/LingeredAppWithLargeStringArray.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2022, 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,6 +23,8 @@ import jdk.test.lib.apps.LingeredApp; +import java.lang.ref.Reference; + public class LingeredAppWithLargeStringArray extends LingeredApp { public static void main(String args[]) { String[] hugeArray = new String[Integer.MAX_VALUE/8]; @@ -31,5 +33,6 @@ public class LingeredAppWithLargeStringArray extends LingeredApp { hugeArray[i] = new String(smallArray[i%3]); } LingeredApp.main(args); + Reference.reachabilityFence(hugeArray); } } -- GitLab From d1cc5fda8f9fe3480d661985f15c71a8a9a4a7f8 Mon Sep 17 00:00:00 2001 From: Thomas Stuefe Date: Tue, 1 Feb 2022 17:19:26 +0000 Subject: [PATCH 363/564] 8280941: os::print_memory_mappings() prints segment preceeding the inclusion range Reviewed-by: stefank, minqi --- src/hotspot/os/linux/os_linux.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index 31b110efcbc..28477ba8bcb 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -5380,21 +5380,20 @@ bool os::supports_map_sync() { } void os::print_memory_mappings(char* addr, size_t bytes, outputStream* st) { + // Note: all ranges are "[..)" unsigned long long start = (unsigned long long)addr; unsigned long long end = start + bytes; FILE* f = os::fopen("/proc/self/maps", "r"); int num_found = 0; if (f != NULL) { - st->print("Range [%llx-%llx) contains: ", start, end); + st->print_cr("Range [%llx-%llx) contains: ", start, end); char line[512]; while(fgets(line, sizeof(line), f) == line) { - unsigned long long a1 = 0; - unsigned long long a2 = 0; - if (::sscanf(line, "%llx-%llx", &a1, &a2) == 2) { + unsigned long long segment_start = 0; + unsigned long long segment_end = 0; + if (::sscanf(line, "%llx-%llx", &segment_start, &segment_end) == 2) { // Lets print out every range which touches ours. - if ((a1 >= start && a1 < end) || // left leg in - (a2 >= start && a2 < end) || // right leg in - (a1 < start && a2 >= end)) { // superimposition + if (segment_start < end && segment_end > start) { num_found ++; st->print("%s", line); // line includes \n } @@ -5402,7 +5401,7 @@ void os::print_memory_mappings(char* addr, size_t bytes, outputStream* st) { } ::fclose(f); if (num_found == 0) { - st->print("nothing."); + st->print_cr("nothing."); } st->cr(); } -- GitLab From 2531c332f89c5faedf71ce1737373581c9abf905 Mon Sep 17 00:00:00 2001 From: Tobias Hartmann Date: Tue, 1 Feb 2022 17:41:15 +0000 Subject: [PATCH 364/564] 8278871: [JVMCI] assert((uint)reason < 2* _trap_hist_limit) failed: oob Backport-of: 6f0e8da6d3bef340299e48977d5e17d05eabe682 --- src/hotspot/share/jvmci/vmStructs_jvmci.cpp | 4 ++-- src/hotspot/share/oops/methodData.hpp | 8 +++++--- src/hotspot/share/runtime/deoptimization.cpp | 3 ++- src/hotspot/share/runtime/deoptimization.hpp | 12 +++++++----- .../src/jdk/vm/ci/hotspot/HotSpotVMConfig.java | 2 +- 5 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp index 43493e65000..928b59a834f 100644 --- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp @@ -558,8 +558,8 @@ declare_constant(Deoptimization::Reason_not_compiled_exception_handler) \ declare_constant(Deoptimization::Reason_unresolved) \ declare_constant(Deoptimization::Reason_jsr_mismatch) \ - declare_constant(Deoptimization::Reason_LIMIT) \ - declare_constant(Deoptimization::_support_large_access_byte_array_virtualization) \ + declare_constant(Deoptimization::Reason_TRAP_HISTORY_LENGTH) \ + declare_constant(Deoptimization::_support_large_access_byte_array_virtualization) \ \ declare_constant(FieldInfo::access_flags_offset) \ declare_constant(FieldInfo::name_index_offset) \ diff --git a/src/hotspot/share/oops/methodData.hpp b/src/hotspot/share/oops/methodData.hpp index a33b118334e..55967e9ee19 100644 --- a/src/hotspot/share/oops/methodData.hpp +++ b/src/hotspot/share/oops/methodData.hpp @@ -30,6 +30,7 @@ #include "oops/method.hpp" #include "oops/oop.hpp" #include "runtime/atomic.hpp" +#include "runtime/deoptimization.hpp" #include "runtime/mutex.hpp" #include "utilities/align.hpp" #include "utilities/copy.hpp" @@ -1965,7 +1966,7 @@ public: // Whole-method sticky bits and flags enum { - _trap_hist_limit = 25 JVMCI_ONLY(+5), // decoupled from Deoptimization::Reason_LIMIT + _trap_hist_limit = Deoptimization::Reason_TRAP_HISTORY_LENGTH, _trap_hist_mask = max_jubyte, _extra_data_count = 4 // extra DataLayout headers, for trap history }; // Public flag values @@ -1980,6 +1981,7 @@ public: uint _nof_overflow_traps; // trap count, excluding _trap_hist union { intptr_t _align; + // JVMCI separates trap history for OSR compilations from normal compilations u1 _array[JVMCI_ONLY(2 *) MethodData::_trap_hist_limit]; } _trap_hist; @@ -1996,14 +1998,14 @@ public: // Return (uint)-1 for overflow. uint trap_count(int reason) const { - assert((uint)reason < JVMCI_ONLY(2*) _trap_hist_limit, "oob"); + assert((uint)reason < ARRAY_SIZE(_trap_hist._array), "oob"); return (int)((_trap_hist._array[reason]+1) & _trap_hist_mask) - 1; } uint inc_trap_count(int reason) { // Count another trap, anywhere in this method. assert(reason >= 0, "must be single trap"); - assert((uint)reason < JVMCI_ONLY(2*) _trap_hist_limit, "oob"); + assert((uint)reason < ARRAY_SIZE(_trap_hist._array), "oob"); uint cnt1 = 1 + _trap_hist._array[reason]; if ((cnt1 & _trap_hist_mask) != 0) { // if no counter overflow... _trap_hist._array[reason] = cnt1; diff --git a/src/hotspot/share/runtime/deoptimization.cpp b/src/hotspot/share/runtime/deoptimization.cpp index ad733dcfc5a..7a89069a025 100644 --- a/src/hotspot/share/runtime/deoptimization.cpp +++ b/src/hotspot/share/runtime/deoptimization.cpp @@ -2279,7 +2279,8 @@ Deoptimization::query_update_method_data(MethodData* trap_mdo, uint idx = reason; #if INCLUDE_JVMCI if (is_osr) { - idx += Reason_LIMIT; + // Upper half of history array used for traps in OSR compilations + idx += Reason_TRAP_HISTORY_LENGTH; } #endif uint prior_trap_count = trap_mdo->trap_count(idx); diff --git a/src/hotspot/share/runtime/deoptimization.hpp b/src/hotspot/share/runtime/deoptimization.hpp index 74b78a853b4..35904ab3c0f 100644 --- a/src/hotspot/share/runtime/deoptimization.hpp +++ b/src/hotspot/share/runtime/deoptimization.hpp @@ -46,6 +46,7 @@ class Deoptimization : AllStatic { public: // What condition caused the deoptimization? + // Note: Keep this enum in sync. with Deoptimization::_trap_reason_name. enum DeoptReason { Reason_many = -1, // indicates presence of several reasons Reason_none = 0, // indicates absence of a relevant deopt. @@ -98,20 +99,22 @@ class Deoptimization : AllStatic { Reason_jsr_mismatch, #endif + // Used to define MethodData::_trap_hist_limit where Reason_tenured isn't included + Reason_TRAP_HISTORY_LENGTH, + // Reason_tenured is counted separately, add normal counted Reasons above. - // Related to MethodData::_trap_hist_limit where Reason_tenured isn't included - Reason_tenured, // age of the code has reached the limit + Reason_tenured = Reason_TRAP_HISTORY_LENGTH, // age of the code has reached the limit Reason_LIMIT, - // Note: Keep this enum in sync. with _trap_reason_name. - Reason_RECORDED_LIMIT = Reason_profile_predicate // some are not recorded per bc // Note: Reason_RECORDED_LIMIT should fit into 31 bits of // DataLayout::trap_bits. This dependency is enforced indirectly // via asserts, to avoid excessive direct header-to-header dependencies. // See Deoptimization::trap_state_reason and class DataLayout. + Reason_RECORDED_LIMIT = Reason_profile_predicate, // some are not recorded per bc }; // What action must be taken by the runtime? + // Note: Keep this enum in sync. with Deoptimization::_trap_action_name. enum DeoptAction { Action_none, // just interpret, do not invalidate nmethod Action_maybe_recompile, // recompile the nmethod; need not invalidate @@ -119,7 +122,6 @@ class Deoptimization : AllStatic { Action_make_not_entrant, // invalidate the nmethod, recompile (probably) Action_make_not_compilable, // invalidate the nmethod and do not compile Action_LIMIT - // Note: Keep this enum in sync. with _trap_action_name. }; enum { diff --git a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java index 1a477cf02b0..927dbed4297 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java @@ -336,7 +336,7 @@ class HotSpotVMConfig extends HotSpotVMConfigAccess { final int deoptReasonLoopLimitCheck = getConstant("Deoptimization::Reason_loop_limit_check", Integer.class); final int deoptReasonAliasing = getConstant("Deoptimization::Reason_aliasing", Integer.class); final int deoptReasonTransferToInterpreter = getConstant("Deoptimization::Reason_transfer_to_interpreter", Integer.class); - final int deoptReasonOSROffset = getConstant("Deoptimization::Reason_LIMIT", Integer.class); + final int deoptReasonOSROffset = getConstant("Deoptimization::Reason_TRAP_HISTORY_LENGTH", Integer.class); final int deoptActionNone = getConstant("Deoptimization::Action_none", Integer.class); final int deoptActionMaybeRecompile = getConstant("Deoptimization::Action_maybe_recompile", Integer.class); -- GitLab From bde2b3783e0e9787cf2f270fcb3a54c2d4f1e5ab Mon Sep 17 00:00:00 2001 From: Jim Laskey Date: Tue, 1 Feb 2022 18:45:31 +0000 Subject: [PATCH 365/564] 8279954: java/lang/StringBuffer(StringBuilder)/HugeCapacity.java intermittently fails Reviewed-by: shade, dholmes --- test/jdk/java/lang/StringBuffer/HugeCapacity.java | 4 ++-- test/jdk/java/lang/StringBuilder/HugeCapacity.java | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/test/jdk/java/lang/StringBuffer/HugeCapacity.java b/test/jdk/java/lang/StringBuffer/HugeCapacity.java index d30d2d945b5..e3c98496c50 100644 --- a/test/jdk/java/lang/StringBuffer/HugeCapacity.java +++ b/test/jdk/java/lang/StringBuffer/HugeCapacity.java @@ -26,8 +26,8 @@ * @bug 8218227 * @summary StringBuilder/StringBuffer constructor throws confusing * NegativeArraySizeException - * @requires (sun.arch.data.model == "64" & os.maxMemory >= 6G) - * @run main/othervm -Xms5G -Xmx5G HugeCapacity + * @requires (sun.arch.data.model == "64" & os.maxMemory >= 8G) + * @run main/othervm -Xms6G -Xmx6G HugeCapacity */ public class HugeCapacity { diff --git a/test/jdk/java/lang/StringBuilder/HugeCapacity.java b/test/jdk/java/lang/StringBuilder/HugeCapacity.java index 9f1617a9dd2..a584ce1f07a 100644 --- a/test/jdk/java/lang/StringBuilder/HugeCapacity.java +++ b/test/jdk/java/lang/StringBuilder/HugeCapacity.java @@ -26,9 +26,9 @@ * @bug 8149330 8218227 * @summary Capacity should not get close to Integer.MAX_VALUE unless * necessary - * @requires (sun.arch.data.model == "64" & os.maxMemory >= 6G) - * @run main/othervm -Xms5G -Xmx5G -XX:+CompactStrings HugeCapacity true - * @run main/othervm -Xms5G -Xmx5G -XX:-CompactStrings HugeCapacity false + * @requires (sun.arch.data.model == "64" & os.maxMemory >= 8G) + * @run main/othervm -Xms6G -Xmx6G -XX:+CompactStrings HugeCapacity true + * @run main/othervm -Xms6G -Xmx6G -XX:-CompactStrings HugeCapacity false */ public class HugeCapacity { -- GitLab From d95de5c7fea4b224d6cd073a6d6921d7108bb7e1 Mon Sep 17 00:00:00 2001 From: Calvin Cheung Date: Tue, 1 Feb 2022 19:33:36 +0000 Subject: [PATCH 366/564] 8255495: Support CDS Archived Heap for uncompressed oops Reviewed-by: iklam, tschatzl --- src/hotspot/share/cds/archiveUtils.cpp | 24 +++- src/hotspot/share/cds/filemap.cpp | 104 +++++++++++---- src/hotspot/share/cds/filemap.hpp | 5 +- src/hotspot/share/cds/heapShared.cpp | 61 +++++++-- src/hotspot/share/cds/heapShared.hpp | 21 ++- src/hotspot/share/cds/metaspaceShared.cpp | 34 ++++- src/hotspot/share/cds/metaspaceShared.hpp | 3 + src/hotspot/share/classfile/stringTable.cpp | 36 +++++- src/hotspot/share/gc/epsilon/epsilonHeap.hpp | 2 +- src/hotspot/share/gc/serial/serialHeap.hpp | 2 +- src/hotspot/share/memory/universe.cpp | 4 + test/hotspot/jtreg/TEST.groups | 7 + .../cds/appcds/DumpingWithNoCoops.java | 120 ++++++++++++++++++ .../cacheObject/DifferentHeapSizes.java | 6 +- 14 files changed, 367 insertions(+), 62 deletions(-) create mode 100644 test/hotspot/jtreg/runtime/cds/appcds/DumpingWithNoCoops.java diff --git a/src/hotspot/share/cds/archiveUtils.cpp b/src/hotspot/share/cds/archiveUtils.cpp index 27c94290c23..073c5f829d2 100644 --- a/src/hotspot/share/cds/archiveUtils.cpp +++ b/src/hotspot/share/cds/archiveUtils.cpp @@ -266,7 +266,7 @@ void WriteClosure::do_oop(oop* o) { } else { assert(HeapShared::can_write(), "sanity"); _dump_region->append_intptr_t( - (intptr_t)CompressedOops::encode_not_null(*o)); + UseCompressedOops ? (intptr_t)CompressedOops::encode_not_null(*o) : (intptr_t)((void*)(*o))); } } @@ -308,13 +308,23 @@ void ReadClosure::do_tag(int tag) { } void ReadClosure::do_oop(oop *p) { - narrowOop o = CompressedOops::narrow_oop_cast(nextPtr()); - if (CompressedOops::is_null(o) || !HeapShared::is_fully_available()) { - *p = NULL; + if (UseCompressedOops) { + narrowOop o = CompressedOops::narrow_oop_cast(nextPtr()); + if (CompressedOops::is_null(o) || !HeapShared::is_fully_available()) { + *p = NULL; + } else { + assert(HeapShared::can_use(), "sanity"); + assert(HeapShared::is_fully_available(), "must be"); + *p = HeapShared::decode_from_archive(o); + } } else { - assert(HeapShared::can_use(), "sanity"); - assert(HeapShared::is_fully_available(), "must be"); - *p = HeapShared::decode_from_archive(o); + intptr_t dumptime_oop = nextPtr(); + if (dumptime_oop == 0 || !HeapShared::is_fully_available()) { + *p = NULL; + } else { + intptr_t runtime_oop = dumptime_oop + HeapShared::runtime_delta(); + *p = cast_to_oop(runtime_oop); + } } } diff --git a/src/hotspot/share/cds/filemap.cpp b/src/hotspot/share/cds/filemap.cpp index 5bf1887cfce..5128565803b 100644 --- a/src/hotspot/share/cds/filemap.cpp +++ b/src/hotspot/share/cds/filemap.cpp @@ -245,8 +245,13 @@ void FileMapHeader::populate(FileMapInfo *info, size_t core_region_alignment, _narrow_oop_mode = CompressedOops::mode(); _narrow_oop_base = CompressedOops::base(); _narrow_oop_shift = CompressedOops::shift(); - _heap_begin = CompressedOops::begin(); - _heap_end = CompressedOops::end(); + if (UseCompressedOops) { + _heap_begin = CompressedOops::begin(); + _heap_end = CompressedOops::end(); + } else { + _heap_begin = (address)G1CollectedHeap::heap()->reserved().start(); + _heap_end = (address)G1CollectedHeap::heap()->reserved().end(); + } } _compressed_oops = UseCompressedOops; _compressed_class_ptrs = UseCompressedClassPointers; @@ -316,6 +321,7 @@ void FileMapHeader::print(outputStream* st) { st->print_cr("- compressed_class_ptrs: %d", _compressed_class_ptrs); st->print_cr("- cloned_vtables_offset: " SIZE_FORMAT_HEX, _cloned_vtables_offset); st->print_cr("- serialized_data_offset: " SIZE_FORMAT_HEX, _serialized_data_offset); + st->print_cr("- heap_begin: " INTPTR_FORMAT, p2i(_heap_begin)); st->print_cr("- heap_end: " INTPTR_FORMAT, p2i(_heap_end)); st->print_cr("- jvm_ident: %s", _jvm_ident); st->print_cr("- shared_path_table_offset: " SIZE_FORMAT_HEX, _shared_path_table_offset); @@ -1491,7 +1497,11 @@ void FileMapInfo::write_region(int region, char* base, size_t size, } else if (HeapShared::is_heap_region(region)) { assert(!DynamicDumpSharedSpaces, "must be"); requested_base = base; - mapping_offset = (size_t)CompressedOops::encode_not_null(cast_to_oop(base)); + if (UseCompressedOops) { + mapping_offset = (size_t)CompressedOops::encode_not_null(cast_to_oop(base)); + } else { + mapping_offset = requested_base - (char*)G1CollectedHeap::heap()->reserved().start(); + } assert(mapping_offset == (size_t)(uint32_t)mapping_offset, "must be 32-bit only"); } else { char* requested_SharedBaseAddress = (char*)MetaspaceShared::requested_base_address(); @@ -2013,7 +2023,10 @@ bool FileMapInfo::can_use_heap_regions() { log_info(cds)(" narrow_oop_mode = %d, narrow_oop_base = " PTR_FORMAT ", narrow_oop_shift = %d", CompressedOops::mode(), p2i(CompressedOops::base()), CompressedOops::shift()); log_info(cds)(" heap range = [" PTR_FORMAT " - " PTR_FORMAT "]", - p2i(CompressedOops::begin()), p2i(CompressedOops::end())); + UseCompressedOops ? p2i(CompressedOops::begin()) : + UseG1GC ? p2i((address)G1CollectedHeap::heap()->reserved().start()) : 0L, + UseCompressedOops ? p2i(CompressedOops::end()) : + UseG1GC ? p2i((address)G1CollectedHeap::heap()->reserved().end()) : 0L); if (narrow_klass_base() != CompressedKlassPointers::base() || narrow_klass_shift() != CompressedKlassPointers::shift()) { @@ -2023,6 +2036,26 @@ bool FileMapInfo::can_use_heap_regions() { return true; } +// The address where the bottom of this shared heap region should be mapped +// at runtime +address FileMapInfo::heap_region_runtime_start_address(FileMapRegion* spc) { + assert(UseSharedSpaces, "runtime only"); + spc->assert_is_heap_region(); + if (UseCompressedOops) { + return start_address_as_decoded_from_archive(spc); + } else { + assert(is_aligned(spc->mapping_offset(), sizeof(HeapWord)), "must be"); + return header()->heap_begin() + spc->mapping_offset() + HeapShared::runtime_delta(); + } +} + +void FileMapInfo::set_shared_heap_runtime_delta(ptrdiff_t delta) { + if (UseCompressedOops) { + HeapShared::init_narrow_oop_decoding(narrow_oop_base() + delta, narrow_oop_shift()); + } else { + HeapShared::set_runtime_delta(delta); + } +} // // Map the closed and open archive heap objects to the runtime java heap. @@ -2045,39 +2078,66 @@ void FileMapInfo::map_heap_regions_impl() { log_info(cds)("CDS heap data needs to be relocated because the archive was created with an incompatible oop encoding mode."); _heap_pointers_need_patching = true; } else { - MemRegion range = get_heap_regions_range_with_current_oop_encoding_mode(); - if (!CompressedOops::is_in(range)) { - log_info(cds)("CDS heap data needs to be relocated because"); - log_info(cds)("the desired range " PTR_FORMAT " - " PTR_FORMAT, p2i(range.start()), p2i(range.end())); - log_info(cds)("is outside of the heap " PTR_FORMAT " - " PTR_FORMAT, p2i(CompressedOops::begin()), p2i(CompressedOops::end())); - _heap_pointers_need_patching = true; - } else if (header()->heap_end() != CompressedOops::end()) { - log_info(cds)("CDS heap data needs to be relocated to the end of the runtime heap to reduce fragmentation"); - _heap_pointers_need_patching = true; + if (UseCompressedOops) { + MemRegion range = get_heap_regions_range_with_current_oop_encoding_mode(); + if (!CompressedOops::is_in(range)) { + log_info(cds)("CDS heap data needs to be relocated because"); + log_info(cds)("the desired range " PTR_FORMAT " - " PTR_FORMAT, p2i(range.start()), p2i(range.end())); + log_info(cds)("is outside of the heap " PTR_FORMAT " - " PTR_FORMAT, p2i(CompressedOops::begin()), p2i(CompressedOops::end())); + _heap_pointers_need_patching = true; + } else if (header()->heap_end() != CompressedOops::end()) { + log_info(cds)("CDS heap data needs to be relocated to the end of the runtime heap to reduce fragmentation"); + _heap_pointers_need_patching = true; + } + } else { + MemRegion range((HeapWord*)header()->heap_begin(), (HeapWord*)header()->heap_end()); + if (!G1CollectedHeap::heap()->reserved().contains(range)) { + log_info(cds)("CDS heap data needs to be relocated because"); + log_info(cds)("the desired range " PTR_FORMAT " - " PTR_FORMAT, p2i(range.start()), p2i(range.end())); + log_info(cds)("is outside of the heap " PTR_FORMAT " - " PTR_FORMAT, + p2i((address)G1CollectedHeap::heap()->reserved().start()), p2i((address)G1CollectedHeap::heap()->reserved().end())); + _heap_pointers_need_patching = true; + } else if (header()->heap_end() != (address)G1CollectedHeap::heap()->reserved().end()) { + log_info(cds)("CDS heap data needs to be relocated to the end of the runtime heap to reduce fragmentation"); + _heap_pointers_need_patching = true; + } } } ptrdiff_t delta = 0; if (_heap_pointers_need_patching) { // dumptime heap end ------------v - // [ |archived heap regions| ] runtime heap end ------v + // [ |archived heap regions| ] run time heap end -----v // [ |archived heap regions| ] + // ^ + // D ^ + // R // |<-----delta-------------------->| // // At dump time, the archived heap regions were near the top of the heap. - // At run time, they may not be inside the heap, so we move them so - // that they are now near the top of the runtime time. This can be done by + // At run time, if the heap ends at a different address, we need to + // move them near to top of the run time heap. This can be done by // the simple math of adding the delta as shown above. + // + // Also: D = bottom of a heap region at dump time + // R = bottom of a heap region at run time + // + // FileMapRegion* spc = ...; + // address D = header()->heap_begin() + spc->mapping_offset(); + // address R = D + delta; address dumptime_heap_end = header()->heap_end(); - address runtime_heap_end = CompressedOops::end(); + address runtime_heap_end = UseCompressedOops ? CompressedOops::end() : + (address)G1CollectedHeap::heap()->reserved().end(); delta = runtime_heap_end - dumptime_heap_end; } log_info(cds)("CDS heap data relocation delta = " INTX_FORMAT " bytes", delta); - HeapShared::init_narrow_oop_decoding(narrow_oop_base() + delta, narrow_oop_shift()); + + set_shared_heap_runtime_delta(delta); FileMapRegion* si = space_at(MetaspaceShared::first_closed_heap_region); - address relocated_closed_heap_region_bottom = start_address_as_decoded_from_archive(si); + address relocated_closed_heap_region_bottom = heap_region_runtime_start_address(si); + if (!is_aligned(relocated_closed_heap_region_bottom, HeapRegion::GrainBytes)) { // Align the bottom of the closed archive heap regions at G1 region boundary. // This will avoid the situation where the highest open region and the lowest @@ -2088,9 +2148,9 @@ void FileMapInfo::map_heap_regions_impl() { log_info(cds)("CDS heap data needs to be relocated lower by a further " SIZE_FORMAT " bytes to " INTX_FORMAT " to be aligned with HeapRegion::GrainBytes", align, delta); - HeapShared::init_narrow_oop_decoding(narrow_oop_base() + delta, narrow_oop_shift()); + set_shared_heap_runtime_delta(delta); + relocated_closed_heap_region_bottom = heap_region_runtime_start_address(si); _heap_pointers_need_patching = true; - relocated_closed_heap_region_bottom = start_address_as_decoded_from_archive(si); } assert(is_aligned(relocated_closed_heap_region_bottom, HeapRegion::GrainBytes), "must be"); @@ -2148,7 +2208,7 @@ bool FileMapInfo::map_heap_regions(int first, int max, bool is_open_archive, si = space_at(i); size_t size = si->used(); if (size > 0) { - HeapWord* start = (HeapWord*)start_address_as_decoded_from_archive(si); + HeapWord* start = (HeapWord*)heap_region_runtime_start_address(si); regions[num_regions] = MemRegion(start, size / HeapWordSize); num_regions ++; log_info(cds)("Trying to map heap data: region[%d] at " INTPTR_FORMAT ", size = " SIZE_FORMAT_W(8) " bytes", diff --git a/src/hotspot/share/cds/filemap.hpp b/src/hotspot/share/cds/filemap.hpp index ac2ad867f79..e6655858187 100644 --- a/src/hotspot/share/cds/filemap.hpp +++ b/src/hotspot/share/cds/filemap.hpp @@ -351,9 +351,8 @@ private: static bool _memory_mapping_failed; static GrowableArray* _non_existent_class_paths; - FileMapHeader *header() const { return _header; } - public: + FileMapHeader *header() const { return _header; } static bool get_base_archive_name_from_header(const char* archive_name, char** base_archive_name); static SharedPathTable shared_path_table() { @@ -568,6 +567,8 @@ public: bool can_use_heap_regions(); bool load_heap_regions() NOT_CDS_JAVA_HEAP_RETURN_(false); bool map_heap_regions() NOT_CDS_JAVA_HEAP_RETURN_(false); + address heap_region_runtime_start_address(FileMapRegion* spc) NOT_CDS_JAVA_HEAP_RETURN_(NULL); + void set_shared_heap_runtime_delta(ptrdiff_t delta) NOT_CDS_JAVA_HEAP_RETURN; void map_heap_regions_impl() NOT_CDS_JAVA_HEAP_RETURN; MapArchiveResult map_region(int i, intx addr_delta, char* mapped_base_address, ReservedSpace rs); bool relocate_pointers_in_core_regions(intx addr_delta); diff --git a/src/hotspot/share/cds/heapShared.cpp b/src/hotspot/share/cds/heapShared.cpp index a224db848bb..f519daabbe5 100644 --- a/src/hotspot/share/cds/heapShared.cpp +++ b/src/hotspot/share/cds/heapShared.cpp @@ -76,6 +76,7 @@ address HeapShared::_narrow_oop_base; int HeapShared::_narrow_oop_shift; DumpedInternedStrings *HeapShared::_dumped_interned_strings = NULL; +// Support for loaded heap. uintptr_t HeapShared::_loaded_heap_bottom = 0; uintptr_t HeapShared::_loaded_heap_top = 0; uintptr_t HeapShared::_dumptime_base_0 = UINTPTR_MAX; @@ -88,6 +89,10 @@ intx HeapShared::_runtime_offset_1 = 0; intx HeapShared::_runtime_offset_2 = 0; intx HeapShared::_runtime_offset_3 = 0; bool HeapShared::_loading_failed = false; + +// Suport for mapped heap (!UseCompressedOops only) +ptrdiff_t HeapShared::_runtime_delta = 0; + // // If you add new entries to the following tables, you should know what you're doing! // @@ -362,7 +367,10 @@ void HeapShared::archive_objects(GrowableArray* closed_regions, create_archived_object_cache(); log_info(cds)("Heap range = [" PTR_FORMAT " - " PTR_FORMAT "]", - p2i(CompressedOops::begin()), p2i(CompressedOops::end())); + UseCompressedOops ? p2i(CompressedOops::begin()) : + p2i((address)G1CollectedHeap::heap()->reserved().start()), + UseCompressedOops ? p2i(CompressedOops::end()) : + p2i((address)G1CollectedHeap::heap()->reserved().end())); log_info(cds)("Dumping objects to closed archive heap region ..."); copy_closed_objects(closed_regions); @@ -658,7 +666,6 @@ void HeapShared::write_subgraph_info_table() { CompactHashtableWriter writer(d_table->_count, &stats); CopyKlassSubGraphInfoToArchive copy(&writer); d_table->iterate(©); - writer.dump(&_run_time_subgraph_info_table, "subgraphs"); } @@ -1400,39 +1407,44 @@ void HeapShared::add_to_dumped_interned_strings(oop string) { // region. This way we can quickly relocate all the pointers without using // BasicOopIterateClosure at runtime. class FindEmbeddedNonNullPointers: public BasicOopIterateClosure { - narrowOop* _start; + void* _start; BitMap *_oopmap; int _num_total_oops; int _num_null_oops; public: - FindEmbeddedNonNullPointers(narrowOop* start, BitMap* oopmap) + FindEmbeddedNonNullPointers(void* start, BitMap* oopmap) : _start(start), _oopmap(oopmap), _num_total_oops(0), _num_null_oops(0) {} virtual void do_oop(narrowOop* p) { _num_total_oops ++; narrowOop v = *p; if (!CompressedOops::is_null(v)) { - size_t idx = p - _start; + size_t idx = p - (narrowOop*)_start; _oopmap->set_bit(idx); } else { _num_null_oops ++; } } - virtual void do_oop(oop *p) { - ShouldNotReachHere(); + virtual void do_oop(oop* p) { + _num_total_oops ++; + if ((*p) != NULL) { + size_t idx = p - (oop*)_start; + _oopmap->set_bit(idx); + } else { + _num_null_oops ++; + } } int num_total_oops() const { return _num_total_oops; } int num_null_oops() const { return _num_null_oops; } }; ResourceBitMap HeapShared::calculate_oopmap(MemRegion region) { - assert(UseCompressedOops, "must be"); - size_t num_bits = region.byte_size() / sizeof(narrowOop); + size_t num_bits = region.byte_size() / (UseCompressedOops ? sizeof(narrowOop) : sizeof(oop)); ResourceBitMap oopmap(num_bits); HeapWord* p = region.start(); HeapWord* end = region.end(); - FindEmbeddedNonNullPointers finder((narrowOop*)p, &oopmap); + FindEmbeddedNonNullPointers finder((void*)p, &oopmap); ArchiveBuilder* builder = DumpSharedSpaces ? ArchiveBuilder::current() : NULL; int num_objs = 0; @@ -1453,11 +1465,11 @@ ResourceBitMap HeapShared::calculate_oopmap(MemRegion region) { // Patch all the embedded oop pointers inside an archived heap region, // to be consistent with the runtime oop encoding. -class PatchEmbeddedPointers: public BitMapClosure { +class PatchCompressedEmbeddedPointers: public BitMapClosure { narrowOop* _start; public: - PatchEmbeddedPointers(narrowOop* start) : _start(start) {} + PatchCompressedEmbeddedPointers(narrowOop* start) : _start(start) {} bool do_bit(size_t offset) { narrowOop* p = _start + offset; @@ -1469,6 +1481,22 @@ class PatchEmbeddedPointers: public BitMapClosure { } }; +class PatchUncompressedEmbeddedPointers: public BitMapClosure { + oop* _start; + + public: + PatchUncompressedEmbeddedPointers(oop* start) : _start(start) {} + + bool do_bit(size_t offset) { + oop* p = _start + offset; + intptr_t dumptime_oop = (intptr_t)((void*)*p); + assert(dumptime_oop != 0, "null oops should have been filtered out at dump time"); + intptr_t runtime_oop = dumptime_oop + HeapShared::runtime_delta(); + RawAccess::oop_store(p, cast_to_oop(runtime_oop)); + return true; + } +}; + // Patch all the non-null pointers that are embedded in the archived heap objects // in this region void HeapShared::patch_embedded_pointers(MemRegion region, address oopmap, @@ -1481,8 +1509,13 @@ void HeapShared::patch_embedded_pointers(MemRegion region, address oopmap, assert(bm.is_same(checkBm), "sanity"); #endif - PatchEmbeddedPointers patcher((narrowOop*)region.start()); - bm.iterate(&patcher); + if (UseCompressedOops) { + PatchCompressedEmbeddedPointers patcher((narrowOop*)region.start()); + bm.iterate(&patcher); + } else { + PatchUncompressedEmbeddedPointers patcher((oop*)region.start()); + bm.iterate(&patcher); + } } // The CDS archive remembers each heap object by its address at dump time, but diff --git a/src/hotspot/share/cds/heapShared.hpp b/src/hotspot/share/cds/heapShared.hpp index 6447b124d2f..fc7a0bcb57a 100644 --- a/src/hotspot/share/cds/heapShared.hpp +++ b/src/hotspot/share/cds/heapShared.hpp @@ -159,7 +159,7 @@ public: if (_disable_writing) { return false; } - return (UseG1GC && UseCompressedOops && UseCompressedClassPointers); + return (UseG1GC && UseCompressedClassPointers); ) NOT_CDS_JAVA_HEAP(return false;) } @@ -169,7 +169,7 @@ public: } // Can this VM map archived heap regions? Currently only G1+compressed{oops,cp} static bool can_map() { - CDS_JAVA_HEAP_ONLY(return (UseG1GC && UseCompressedOops && UseCompressedClassPointers);) + CDS_JAVA_HEAP_ONLY(return (UseG1GC && UseCompressedClassPointers);) NOT_CDS_JAVA_HEAP(return false;) } static bool is_mapped() { @@ -297,10 +297,13 @@ private: static void init_subgraph_entry_fields(ArchivableStaticFieldInfo fields[], int num, TRAPS); - // Used by decode_from_archive + // UseCompressedOops only: Used by decode_from_archive static address _narrow_oop_base; static int _narrow_oop_shift; + // !UseCompressedOops only: used to relocate pointers to the archived objects + static ptrdiff_t _runtime_delta; + typedef ResourceHashtable max_heap_size) { + log_debug(cds)("Setting MinHeapSize to 4G for CDS dumping, original size = " SIZE_FORMAT "M", MinHeapSize/M); + FLAG_SET_ERGO(MinHeapSize, max_heap_size); + } + if (InitialHeapSize > max_heap_size) { + log_debug(cds)("Setting InitialHeapSize to 4G for CDS dumping, original size = " SIZE_FORMAT "M", InitialHeapSize/M); + FLAG_SET_ERGO(InitialHeapSize, max_heap_size); + } + if (MaxHeapSize > max_heap_size) { + log_debug(cds)("Setting MaxHeapSize to 4G for CDS dumping, original size = " SIZE_FORMAT "M", MaxHeapSize/M); + FLAG_SET_ERGO(MaxHeapSize, max_heap_size); + } +} +#endif // INCLUDE_CDS_JAVA_HEAP && _LP64 + void MetaspaceShared::preload_classes(TRAPS) { char default_classlist[JVM_MAXPATHLEN]; const char* classlist_path; @@ -834,11 +859,10 @@ bool MetaspaceShared::try_link_class(JavaThread* current, InstanceKlass* ik) { void VM_PopulateDumpSharedSpace::dump_java_heap_objects(GrowableArray* klasses) { if(!HeapShared::can_write()) { log_info(cds)( - "Archived java heap is not supported as UseG1GC, " - "UseCompressedOops and UseCompressedClassPointers are required." - "Current settings: UseG1GC=%s, UseCompressedOops=%s, UseCompressedClassPointers=%s.", - BOOL_TO_STR(UseG1GC), BOOL_TO_STR(UseCompressedOops), - BOOL_TO_STR(UseCompressedClassPointers)); + "Archived java heap is not supported as UseG1GC " + "and UseCompressedClassPointers are required." + "Current settings: UseG1GC=%s, UseCompressedClassPointers=%s.", + BOOL_TO_STR(UseG1GC), BOOL_TO_STR(UseCompressedClassPointers)); return; } // Find all the interned strings that should be dumped. diff --git a/src/hotspot/share/cds/metaspaceShared.hpp b/src/hotspot/share/cds/metaspaceShared.hpp index c7d64d7de0c..63c1089bd27 100644 --- a/src/hotspot/share/cds/metaspaceShared.hpp +++ b/src/hotspot/share/cds/metaspaceShared.hpp @@ -82,6 +82,9 @@ class MetaspaceShared : AllStatic { static void prepare_for_dumping() NOT_CDS_RETURN; static void preload_and_dump() NOT_CDS_RETURN; +#ifdef _LP64 + static void adjust_heap_sizes_for_dumping() NOT_CDS_JAVA_HEAP_RETURN; +#endif private: static void preload_and_dump_impl(TRAPS) NOT_CDS_RETURN; diff --git a/src/hotspot/share/classfile/stringTable.cpp b/src/hotspot/share/classfile/stringTable.cpp index c43f940b790..e3015a02eb5 100644 --- a/src/hotspot/share/classfile/stringTable.cpp +++ b/src/hotspot/share/classfile/stringTable.cpp @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "cds/archiveBuilder.hpp" +#include "cds/filemap.hpp" #include "cds/heapShared.inline.hpp" #include "classfile/altHashing.hpp" #include "classfile/compactHashtable.hpp" @@ -55,6 +56,9 @@ #include "utilities/macros.hpp" #include "utilities/resizeableResourceHash.hpp" #include "utilities/utf8.hpp" +#if INCLUDE_G1GC +#include "gc/g1/g1CollectedHeap.hpp" +#endif // We prefer short chains of avg 2 const double PREF_AVG_LIST_LEN = 2.0; @@ -67,9 +71,18 @@ const double CLEAN_DEAD_HIGH_WATER_MARK = 0.5; #if INCLUDE_CDS_JAVA_HEAP inline oop read_string_from_compact_hashtable(address base_address, u4 offset) { - assert(sizeof(narrowOop) == sizeof(offset), "must be"); - narrowOop v = CompressedOops::narrow_oop_cast(offset); - return HeapShared::decode_from_archive(v); + if (UseCompressedOops) { + assert(sizeof(narrowOop) == sizeof(offset), "must be"); + narrowOop v = CompressedOops::narrow_oop_cast(offset); + return HeapShared::decode_from_archive(v); + } else { + intptr_t dumptime_oop = (uintptr_t)offset; + assert(dumptime_oop != 0, "null strings cannot be interned"); + intptr_t runtime_oop = dumptime_oop + + (intptr_t)FileMapInfo::current_info()->header()->heap_begin() + + (intptr_t)HeapShared::runtime_delta(); + return (oop)cast_to_oop(runtime_oop); + } } typedef CompactHashtable< @@ -746,6 +759,16 @@ oop StringTable::create_archived_string(oop s) { class CopyToArchive : StackObj { CompactHashtableWriter* _writer; +private: + u4 compute_delta(oop s) { + HeapWord* start = G1CollectedHeap::heap()->reserved().start(); + intx offset = ((address)(void*)s) - ((address)(void*)start); + assert(offset >= 0, "must be"); + if (offset > 0xffffffff) { + fatal("too large"); + } + return (u4)offset; + } public: CopyToArchive(CompactHashtableWriter* writer) : _writer(writer) {} bool do_entry(oop s, bool value_ignored) { @@ -757,7 +780,11 @@ public: } // add to the compact table - _writer->add(hash, CompressedOops::narrow_oop_value(new_s)); + if (UseCompressedOops) { + _writer->add(hash, CompressedOops::narrow_oop_value(new_s)); + } else { + _writer->add(hash, compute_delta(new_s)); + } return true; } }; @@ -771,7 +798,6 @@ void StringTable::write_to_archive(const DumpedInternedStrings* dumped_interned_ // Copy the interned strings into the "string space" within the java heap CopyToArchive copier(&writer); dumped_interned_strings->iterate(&copier); - writer.dump(&_shared_table, "string"); } diff --git a/src/hotspot/share/gc/epsilon/epsilonHeap.hpp b/src/hotspot/share/gc/epsilon/epsilonHeap.hpp index 0f929b64bd9..036593c72ae 100644 --- a/src/hotspot/share/gc/epsilon/epsilonHeap.hpp +++ b/src/hotspot/share/gc/epsilon/epsilonHeap.hpp @@ -132,7 +132,7 @@ public: bool is_in_reserved(const void* addr) const { return _reserved.contains(addr); } // Support for loading objects from CDS archive into the heap - virtual bool can_load_archived_objects() const { return true; } + virtual bool can_load_archived_objects() const { return UseCompressedOops; } virtual HeapWord* allocate_loaded_archive_space(size_t size); virtual void print_on(outputStream* st) const; diff --git a/src/hotspot/share/gc/serial/serialHeap.hpp b/src/hotspot/share/gc/serial/serialHeap.hpp index 0451a9679a4..f71b4a6740c 100644 --- a/src/hotspot/share/gc/serial/serialHeap.hpp +++ b/src/hotspot/share/gc/serial/serialHeap.hpp @@ -105,7 +105,7 @@ public: virtual void safepoint_synchronize_end(); // Support for loading objects from CDS archive into the heap - bool can_load_archived_objects() const { return true; } + bool can_load_archived_objects() const { return UseCompressedOops; } HeapWord* allocate_loaded_archive_space(size_t size); void complete_loaded_archive_space(MemRegion archive_space); }; diff --git a/src/hotspot/share/memory/universe.cpp b/src/hotspot/share/memory/universe.cpp index 5ec4f4860ab..998ff620f08 100644 --- a/src/hotspot/share/memory/universe.cpp +++ b/src/hotspot/share/memory/universe.cpp @@ -748,6 +748,10 @@ jint universe_init() { GCLogPrecious::initialize(); +#ifdef _LP64 + MetaspaceShared::adjust_heap_sizes_for_dumping(); +#endif // _LP64 + GCConfig::arguments()->initialize_heap_sizes(); jint status = Universe::initialize_heap(); diff --git a/test/hotspot/jtreg/TEST.groups b/test/hotspot/jtreg/TEST.groups index 63759898530..dece67b5474 100644 --- a/test/hotspot/jtreg/TEST.groups +++ b/test/hotspot/jtreg/TEST.groups @@ -46,6 +46,10 @@ hotspot_gc = \ hotspot_runtime = \ runtime +hotspot_runtime_no_cds = \ + runtime \ + -runtime/cds + hotspot_handshake = \ runtime/handshake @@ -384,6 +388,8 @@ hotspot_cds = \ runtime/cds/ \ runtime/CompressedOops/ +hotspot_cds_only = \ + runtime/cds/ hotspot_appcds_dynamic = \ runtime/cds/appcds/ \ @@ -405,6 +411,7 @@ hotspot_appcds_dynamic = \ -runtime/cds/appcds/BadBSM.java \ -runtime/cds/appcds/DumpClassList.java \ -runtime/cds/appcds/DumpClassListWithLF.java \ + -runtime/cds/appcds/DumpingWithNoCoops.java \ -runtime/cds/appcds/ExtraSymbols.java \ -runtime/cds/appcds/LambdaContainsOldInf.java \ -runtime/cds/appcds/LambdaEagerInit.java \ diff --git a/test/hotspot/jtreg/runtime/cds/appcds/DumpingWithNoCoops.java b/test/hotspot/jtreg/runtime/cds/appcds/DumpingWithNoCoops.java new file mode 100644 index 00000000000..00fed755b7e --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/DumpingWithNoCoops.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2022, 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 8255495 + * @summary Test CDS with UseCompressedOops disable with various heap sizes. + * @requires vm.cds.write.archived.java.heap + * @requires vm.gc.G1 + * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds + * @compile test-classes/Hello.java + * @run driver DumpingWithNoCoops + */ + +import java.util.ArrayList; +import java.util.List; + +import jdk.test.lib.process.OutputAnalyzer; + +public class DumpingWithNoCoops { + static class HeapArgs { + int initialSize, minSize, maxSize; + HeapArgs(int initial, int min, int max) { + initialSize = initial; + minSize = min; + maxSize = max; + } + String heapArgsString(HeapArgs ha) { + String heapArgs = ""; + if (ha.initialSize > 0) { + heapArgs += "-XX:InitialHeapSize=" + ha.initialSize + "g"; + } + if (ha.minSize > 0) { + if (heapArgs.length() > 0) { + heapArgs += " "; + } + heapArgs += "-XX:MinHeapSize=" + ha.minSize + "g"; + } + if (ha.maxSize > 0) { + if (heapArgs.length() > 0) { + heapArgs += " "; + } + heapArgs += "-XX:MaxHeapSize=" + ha.maxSize + "g"; + } + return heapArgs; + } + } + + static HeapArgs[] heapArgsCases = { + // InitialHeapSize, MinHeapSize, MaxHeapSize + // all sizes are in the unit of GB + // size of 0 means don't set the heap size + new HeapArgs( 0, 0, 0), + new HeapArgs( 8, 0, 0), + new HeapArgs( 0, 8, 0), + new HeapArgs( 0, 0, 8), + new HeapArgs( 8, 8, 0), + new HeapArgs( 0, 8, 8), + new HeapArgs( 8, 0, 8), + new HeapArgs( 8, 8, 8), + new HeapArgs( 2, 1, 33), + }; + + public static void main(String[] args) throws Exception { + final String noCoops = "-XX:-UseCompressedOops"; + final String logArg = "-Xlog:gc+heap=trace,cds=debug"; + JarBuilder.getOrCreateHelloJar(); + String appJar = TestCommon.getTestJar("hello.jar"); + String appClasses[] = TestCommon.list("Hello"); + + for (HeapArgs ha : heapArgsCases) { + String heapArg = ha.heapArgsString(ha); + List dumptimeArgs = new ArrayList(); + // UseCompressedOops is ergonomically disabled for MaxHeapSize > 32g. + if (ha.maxSize < 32) { + dumptimeArgs.add(noCoops); + } + dumptimeArgs.add(logArg); + OutputAnalyzer output; + if (heapArg.length() == 0) { + System.out.println("\n Test without heap args\n"); + output = TestCommon.dump(appJar, appClasses, dumptimeArgs.toArray(new String[0])); + } else { + System.out.println("\n Test with heap args: " + heapArg + "\n"); + String[] heapSizes = heapArg.split(" "); + for (String heapSize : heapSizes) { + dumptimeArgs.add(heapSize); + } + output = TestCommon.dump(appJar, appClasses, dumptimeArgs.toArray(new String[0])); + output.shouldContain("Setting MaxHeapSize to 4G for CDS dumping"); + } + TestCommon.checkDump(output); + + TestCommon.run("-cp", appJar, + logArg, "-Xlog:class+load", noCoops, "Hello") + .assertNormalExit("Hello source: shared objects file"); + } + } +} diff --git a/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/DifferentHeapSizes.java b/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/DifferentHeapSizes.java index 4afbb705c88..fa9482abebd 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/DifferentHeapSizes.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/DifferentHeapSizes.java @@ -62,6 +62,8 @@ public class DifferentHeapSizes { JarBuilder.getOrCreateHelloJar(); String appJar = TestCommon.getTestJar("hello.jar"); String appClasses[] = TestCommon.list("Hello"); + WhiteBox wb = WhiteBox.getWhiteBox(); + boolean useCompressedOops = wb.getBooleanVMFlag("UseCompressedOops"); for (Scenario s : scenarios) { String dumpXmx = "-Xmx" + s.dumpSize + "m"; @@ -71,7 +73,7 @@ public class DifferentHeapSizes { String runXmx = "-Xmx" + runSize + "m"; CDSTestUtils.Result result = TestCommon.run("-cp", appJar, "-showversion", "-Xlog:cds", runXmx, DEDUP, "Hello"); - if (runSize < 32768) { + if (runSize < 32768 || !useCompressedOops) { result .assertNormalExit("Hello World") .assertNormalExit(out -> { @@ -88,7 +90,7 @@ public class DifferentHeapSizes { // Test various settings of -XX:HeapBaseMinAddress that would trigger // "CDS heap data need to be relocated because the desired range ... is outside of the heap" - long default_base = WhiteBox.getWhiteBox().getSizeTVMFlag("HeapBaseMinAddress").longValue(); + long default_base = wb.getSizeTVMFlag("HeapBaseMinAddress").longValue(); long M = 1024 * 1024; long bases[] = new long[] { /* dump xmx */ /* run xmx */ /* dump base */ /* run base */ -- GitLab From fdd9ca74bd6ca87c30be2bcdcfd22e19b7687a5a Mon Sep 17 00:00:00 2001 From: Roger Riggs Date: Tue, 1 Feb 2022 20:13:14 +0000 Subject: [PATCH 367/564] 8280642: ObjectInputStream.readObject should throw InvalidClassException instead of IllegalAccessError Reviewed-by: naoto, mchung --- .../classes/java/io/ObjectInputStream.java | 4 ++++ .../loadProxyClasses/LoadProxyClasses.java | 17 +++++++++-------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/java.base/share/classes/java/io/ObjectInputStream.java b/src/java.base/share/classes/java/io/ObjectInputStream.java index dec50deb9c9..714785cd117 100644 --- a/src/java.base/share/classes/java/io/ObjectInputStream.java +++ b/src/java.base/share/classes/java/io/ObjectInputStream.java @@ -1995,6 +1995,10 @@ public class ObjectInputStream } } catch (ClassNotFoundException ex) { resolveEx = ex; + } catch (IllegalAccessError aie) { + IOException ice = new InvalidClassException(aie.getMessage()); + ice.initCause(aie); + throw ice; } catch (OutOfMemoryError memerr) { IOException ex = new InvalidObjectException("Proxy interface limit exceeded: " + Arrays.toString(ifaces)); diff --git a/test/jdk/java/rmi/server/RMIClassLoader/loadProxyClasses/LoadProxyClasses.java b/test/jdk/java/rmi/server/RMIClassLoader/loadProxyClasses/LoadProxyClasses.java index 9b8ed213160..568eeb1e6be 100644 --- a/test/jdk/java/rmi/server/RMIClassLoader/loadProxyClasses/LoadProxyClasses.java +++ b/test/jdk/java/rmi/server/RMIClassLoader/loadProxyClasses/LoadProxyClasses.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,7 +22,7 @@ */ /* @test - * + * @bug 8280642 * @summary functional test for RMIClassLoader.loadProxyClass; test * ensures that the default RMI class loader provider implements * RMIClassLoader.loadProxyClass correctly. @@ -48,6 +48,7 @@ import java.rmi.MarshalledObject; import java.net.URL; import java.net.URLClassLoader; import java.io.Serializable; +import java.io.InvalidClassException; import java.io.IOException; import java.util.Arrays; @@ -205,20 +206,20 @@ public class LoadProxyClasses { currentThread.getContextClassLoader(); currentThread.setContextClassLoader(nonpublicLoaderB); - IllegalAccessError illegal = null; + InvalidClassException invalid = null; try { unmarshalProxyClass(proxy4, fnnLoader2, nonpublicLoaderB, 4, null); - } catch (IllegalAccessError e) { - illegal = e; + } catch (InvalidClassException e) { + invalid = e; } - if (illegal == null) { - TestLibrary.bomb("case4: IllegalAccessError not thrown " + + if (invalid == null) { + TestLibrary.bomb("case4: InvalidClassException not thrown " + "when multiple nonpublic interfaces have \n" + "different class loaders"); } else { - System.err.println("\ncase4: IllegalAccessError correctly " + + System.err.println("\ncase4: InvalidClassException correctly " + "thrown \n when trying to load proxy " + "with multiple nonpublic interfaces in \n" + " different class loaders"); -- GitLab From a18beb4797a1ca6fc6b31e997be48b2bd91c6ac0 Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Tue, 1 Feb 2022 20:55:39 +0000 Subject: [PATCH 368/564] 8280867: Cpuid1Ecx feature parsing is incorrect for AMD CPUs Reviewed-by: kvn, dlong --- src/hotspot/cpu/x86/vm_version_x86.hpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/hotspot/cpu/x86/vm_version_x86.hpp b/src/hotspot/cpu/x86/vm_version_x86.hpp index 27342dbdc96..2fd1bbc9617 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.hpp +++ b/src/hotspot/cpu/x86/vm_version_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -148,12 +148,11 @@ class VM_Version : public Abstract_VM_Version { uint32_t LahfSahf : 1, CmpLegacy : 1, : 3, - lzcnt_intel : 1, lzcnt : 1, sse4a : 1, misalignsse : 1, prefetchw : 1, - : 22; + : 23; } bits; }; @@ -640,10 +639,10 @@ protected: // Intel features. if (is_intel()) { - if (_cpuid_info.ext_cpuid1_ecx.bits.lzcnt_intel != 0) + if (_cpuid_info.ext_cpuid1_ecx.bits.lzcnt != 0) { result |= CPU_LZCNT; - // for Intel, ecx.bits.misalignsse bit (bit 8) indicates support for prefetchw - if (_cpuid_info.ext_cpuid1_ecx.bits.misalignsse != 0) { + } + if (_cpuid_info.ext_cpuid1_ecx.bits.prefetchw != 0) { result |= CPU_3DNOW_PREFETCH; } if (_cpuid_info.sef_cpuid7_ebx.bits.clwb != 0) { @@ -655,10 +654,10 @@ protected: // ZX features. if (is_zx()) { - if (_cpuid_info.ext_cpuid1_ecx.bits.lzcnt_intel != 0) + if (_cpuid_info.ext_cpuid1_ecx.bits.lzcnt != 0) { result |= CPU_LZCNT; - // for ZX, ecx.bits.misalignsse bit (bit 8) indicates support for prefetchw - if (_cpuid_info.ext_cpuid1_ecx.bits.misalignsse != 0) { + } + if (_cpuid_info.ext_cpuid1_ecx.bits.prefetchw != 0) { result |= CPU_3DNOW_PREFETCH; } } -- GitLab From c74b8f48fad8380dbd811e4a42c361006e13021d Mon Sep 17 00:00:00 2001 From: Boris Ulasevich Date: Tue, 1 Feb 2022 20:56:57 +0000 Subject: [PATCH 369/564] 8275914: SHA3: changing java implementation to help C2 create high-performance code Reviewed-by: ascarpino, phh --- .../classes/sun/security/provider/SHA3.java | 211 ++++++++++-------- 1 file changed, 116 insertions(+), 95 deletions(-) diff --git a/src/java.base/share/classes/sun/security/provider/SHA3.java b/src/java.base/share/classes/sun/security/provider/SHA3.java index fb21e3ceb6e..f8fdf8790a8 100644 --- a/src/java.base/share/classes/sun/security/provider/SHA3.java +++ b/src/java.base/share/classes/sun/security/provider/SHA3.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, 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 @@ -158,99 +158,6 @@ abstract class SHA3 extends DigestBase { } } - /** - * Step mapping Theta as defined in section 3.2.1 . - */ - private static long[] smTheta(long[] a) { - long c0 = a[0]^a[5]^a[10]^a[15]^a[20]; - long c1 = a[1]^a[6]^a[11]^a[16]^a[21]; - long c2 = a[2]^a[7]^a[12]^a[17]^a[22]; - long c3 = a[3]^a[8]^a[13]^a[18]^a[23]; - long c4 = a[4]^a[9]^a[14]^a[19]^a[24]; - long d0 = c4 ^ Long.rotateLeft(c1, 1); - long d1 = c0 ^ Long.rotateLeft(c2, 1); - long d2 = c1 ^ Long.rotateLeft(c3, 1); - long d3 = c2 ^ Long.rotateLeft(c4, 1); - long d4 = c3 ^ Long.rotateLeft(c0, 1); - for (int y = 0; y < a.length; y += DM) { - a[y] ^= d0; - a[y+1] ^= d1; - a[y+2] ^= d2; - a[y+3] ^= d3; - a[y+4] ^= d4; - } - return a; - } - - /** - * Merged Step mapping Rho (section 3.2.2) and Pi (section 3.2.3). - * for performance. Optimization is achieved by precalculating - * shift constants for the following loop - * int xNext, yNext; - * for (int t = 0, x = 1, y = 0; t <= 23; t++, x = xNext, y = yNext) { - * int numberOfShift = ((t + 1)*(t + 2)/2) % 64; - * a[y][x] = Long.rotateLeft(a[y][x], numberOfShift); - * xNext = y; - * yNext = (2 * x + 3 * y) % DM; - * } - * and with inplace permutation. - */ - private static long[] smPiRho(long[] a) { - long tmp = Long.rotateLeft(a[10], 3); - a[10] = Long.rotateLeft(a[1], 1); - a[1] = Long.rotateLeft(a[6], 44); - a[6] = Long.rotateLeft(a[9], 20); - a[9] = Long.rotateLeft(a[22], 61); - a[22] = Long.rotateLeft(a[14], 39); - a[14] = Long.rotateLeft(a[20], 18); - a[20] = Long.rotateLeft(a[2], 62); - a[2] = Long.rotateLeft(a[12], 43); - a[12] = Long.rotateLeft(a[13], 25); - a[13] = Long.rotateLeft(a[19], 8); - a[19] = Long.rotateLeft(a[23], 56); - a[23] = Long.rotateLeft(a[15], 41); - a[15] = Long.rotateLeft(a[4], 27); - a[4] = Long.rotateLeft(a[24], 14); - a[24] = Long.rotateLeft(a[21], 2); - a[21] = Long.rotateLeft(a[8], 55); - a[8] = Long.rotateLeft(a[16], 45); - a[16] = Long.rotateLeft(a[5], 36); - a[5] = Long.rotateLeft(a[3], 28); - a[3] = Long.rotateLeft(a[18], 21); - a[18] = Long.rotateLeft(a[17], 15); - a[17] = Long.rotateLeft(a[11], 10); - a[11] = Long.rotateLeft(a[7], 6); - a[7] = tmp; - return a; - } - - /** - * Step mapping Chi as defined in section 3.2.4. - */ - private static long[] smChi(long[] a) { - for (int y = 0; y < a.length; y+=DM) { - long ay0 = a[y]; - long ay1 = a[y+1]; - long ay2 = a[y+2]; - long ay3 = a[y+3]; - long ay4 = a[y+4]; - a[y] = ay0 ^ ((~ay1) & ay2); - a[y+1] = ay1 ^ ((~ay2) & ay3); - a[y+2] = ay2 ^ ((~ay3) & ay4); - a[y+3] = ay3 ^ ((~ay4) & ay0); - a[y+4] = ay4 ^ ((~ay0) & ay1); - } - return a; - } - - /** - * Step mapping Iota as defined in section 3.2.5. - */ - private static long[] smIota(long[] a, int rndIndex) { - a[0] ^= RC_CONSTANTS[rndIndex]; - return a; - } - /** * The function Keccak as defined in section 5.2 with * rate r = 1600 and capacity c = (digest length x 2). @@ -258,10 +165,124 @@ abstract class SHA3 extends DigestBase { private void keccak() { // convert the 200-byte state into 25 lanes bytes2Lanes(state, lanes); + + long a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12; + long a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24; + // move data into local variables + a0 = lanes[0]; a1 = lanes[1]; a2 = lanes[2]; a3 = lanes[3]; a4 = lanes[4]; + a5 = lanes[5]; a6 = lanes[6]; a7 = lanes[7]; a8 = lanes[8]; a9 = lanes[9]; + a10 = lanes[10]; a11 = lanes[11]; a12 = lanes[12]; a13 = lanes[13]; a14 = lanes[14]; + a15 = lanes[15]; a16 = lanes[16]; a17 = lanes[17]; a18 = lanes[18]; a19 = lanes[19]; + a20 = lanes[20]; a21 = lanes[21]; a22 = lanes[22]; a23 = lanes[23]; a24 = lanes[24]; + // process the lanes through step mappings for (int ir = 0; ir < NR; ir++) { - smIota(smChi(smPiRho(smTheta(lanes))), ir); + // Step mapping Theta as defined in section 3.2.1. + long c0 = a0^a5^a10^a15^a20; + long c1 = a1^a6^a11^a16^a21; + long c2 = a2^a7^a12^a17^a22; + long c3 = a3^a8^a13^a18^a23; + long c4 = a4^a9^a14^a19^a24; + long d0 = c4 ^ Long.rotateLeft(c1, 1); + long d1 = c0 ^ Long.rotateLeft(c2, 1); + long d2 = c1 ^ Long.rotateLeft(c3, 1); + long d3 = c2 ^ Long.rotateLeft(c4, 1); + long d4 = c3 ^ Long.rotateLeft(c0, 1); + a0 ^= d0; a1 ^= d1; a2 ^= d2; a3 ^= d3; a4 ^= d4; + a5 ^= d0; a6 ^= d1; a7 ^= d2; a8 ^= d3; a9 ^= d4; + a10 ^= d0; a11 ^= d1; a12 ^= d2; a13 ^= d3; a14 ^= d4; + a15 ^= d0; a16 ^= d1; a17 ^= d2; a18 ^= d3; a19 ^= d4; + a20 ^= d0; a21 ^= d1; a22 ^= d2; a23 ^= d3; a24 ^= d4; + + /** + * Merged Step mapping Rho (section 3.2.2) and Pi (section 3.2.3). + * for performance. Optimization is achieved by precalculating + * shift constants for the following loop + * int xNext, yNext; + * for (int t = 0, x = 1, y = 0; t <= 23; t++, x = xNext, y = yNext) { + * int numberOfShift = ((t + 1)*(t + 2)/2) % 64; + * a[y][x] = Long.rotateLeft(a[y][x], numberOfShift); + * xNext = y; + * yNext = (2 * x + 3 * y) % DM; + * } + * and with inplace permutation. + */ + long ay = Long.rotateLeft(a10, 3); + a10 = Long.rotateLeft(a1, 1); + a1 = Long.rotateLeft(a6, 44); + a6 = Long.rotateLeft(a9, 20); + a9 = Long.rotateLeft(a22, 61); + a22 = Long.rotateLeft(a14, 39); + a14 = Long.rotateLeft(a20, 18); + a20 = Long.rotateLeft(a2, 62); + a2 = Long.rotateLeft(a12, 43); + a12 = Long.rotateLeft(a13, 25); + a13 = Long.rotateLeft(a19, 8); + a19 = Long.rotateLeft(a23, 56); + a23 = Long.rotateLeft(a15, 41); + a15 = Long.rotateLeft(a4, 27); + a4 = Long.rotateLeft(a24, 14); + a24 = Long.rotateLeft(a21, 2); + a21 = Long.rotateLeft(a8, 55); + a8 = Long.rotateLeft(a16, 45); + a16 = Long.rotateLeft(a5, 36); + a5 = Long.rotateLeft(a3, 28); + a3 = Long.rotateLeft(a18, 21); + a18 = Long.rotateLeft(a17, 15); + a17 = Long.rotateLeft(a11, 10); + a11 = Long.rotateLeft(a7, 6); + a7 = ay; + + // Step mapping Chi as defined in section 3.2.4. + long tmp0 = a0; + long tmp1 = a1; + long tmp2 = a2; + long tmp3 = a3; + long tmp4 = a4; + a0 = tmp0 ^ ((~tmp1) & tmp2); + a1 = tmp1 ^ ((~tmp2) & tmp3); + a2 = tmp2 ^ ((~tmp3) & tmp4); + a3 = tmp3 ^ ((~tmp4) & tmp0); + a4 = tmp4 ^ ((~tmp0) & tmp1); + + tmp0 = a5; tmp1 = a6; tmp2 = a7; tmp3 = a8; tmp4 = a9; + a5 = tmp0 ^ ((~tmp1) & tmp2); + a6 = tmp1 ^ ((~tmp2) & tmp3); + a7 = tmp2 ^ ((~tmp3) & tmp4); + a8 = tmp3 ^ ((~tmp4) & tmp0); + a9 = tmp4 ^ ((~tmp0) & tmp1); + + tmp0 = a10; tmp1 = a11; tmp2 = a12; tmp3 = a13; tmp4 = a14; + a10 = tmp0 ^ ((~tmp1) & tmp2); + a11 = tmp1 ^ ((~tmp2) & tmp3); + a12 = tmp2 ^ ((~tmp3) & tmp4); + a13 = tmp3 ^ ((~tmp4) & tmp0); + a14 = tmp4 ^ ((~tmp0) & tmp1); + + tmp0 = a15; tmp1 = a16; tmp2 = a17; tmp3 = a18; tmp4 = a19; + a15 = tmp0 ^ ((~tmp1) & tmp2); + a16 = tmp1 ^ ((~tmp2) & tmp3); + a17 = tmp2 ^ ((~tmp3) & tmp4); + a18 = tmp3 ^ ((~tmp4) & tmp0); + a19 = tmp4 ^ ((~tmp0) & tmp1); + + tmp0 = a20; tmp1 = a21; tmp2 = a22; tmp3 = a23; tmp4 = a24; + a20 = tmp0 ^ ((~tmp1) & tmp2); + a21 = tmp1 ^ ((~tmp2) & tmp3); + a22 = tmp2 ^ ((~tmp3) & tmp4); + a23 = tmp3 ^ ((~tmp4) & tmp0); + a24 = tmp4 ^ ((~tmp0) & tmp1); + + // Step mapping Iota as defined in section 3.2.5. + a0 ^= RC_CONSTANTS[ir]; } + + lanes[0] = a0; lanes[1] = a1; lanes[2] = a2; lanes[3] = a3; lanes[4] = a4; + lanes[5] = a5; lanes[6] = a6; lanes[7] = a7; lanes[8] = a8; lanes[9] = a9; + lanes[10] = a10; lanes[11] = a11; lanes[12] = a12; lanes[13] = a13; lanes[14] = a14; + lanes[15] = a15; lanes[16] = a16; lanes[17] = a17; lanes[18] = a18; lanes[19] = a19; + lanes[20] = a20; lanes[21] = a21; lanes[22] = a22; lanes[23] = a23; lanes[24] = a24; + // convert the resulting 25 lanes back into 200-byte state lanes2Bytes(lanes, state); } -- GitLab From 9ca7ff3e4f0a944bacf38da7e5426082d64c52bd Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Tue, 1 Feb 2022 22:30:08 +0000 Subject: [PATCH 370/564] 8281082: Improve javadoc references to JOSS Reviewed-by: iris, rriggs, naoto, lancea --- .../share/classes/java/io/ObjectOutputStream.java | 7 ++++--- src/java.base/share/classes/java/io/Serial.java | 5 +++-- src/java.base/share/classes/java/lang/Enum.java | 7 ++++--- src/java.base/share/classes/java/lang/String.java | 2 +- src/java.base/share/classes/java/security/Key.java | 4 ++-- src/java.base/share/classes/java/security/KeyRep.java | 4 ++-- 6 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/java.base/share/classes/java/io/ObjectOutputStream.java b/src/java.base/share/classes/java/io/ObjectOutputStream.java index 811ef3bcc20..1ac6f60614f 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, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2022, 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 @@ -656,10 +656,11 @@ public class ObjectOutputStream * stream. Subclasses of ObjectOutputStream may override this method to * customize the way in which class descriptors are written to the * serialization stream. The corresponding method in ObjectInputStream, - * {@code readClassDescriptor}, should then be overridden to + * {@link ObjectInputStream#readClassDescriptor readClassDescriptor}, should then be overridden to * reconstitute the class descriptor from its custom stream representation. * By default, this method writes class descriptors according to the format - * defined in the Object Serialization specification. + * defined in the + * Java Object Serialization Specification. * *

    Note that this method will only be called if the ObjectOutputStream * is not using the old serialization stream format (set by calling diff --git a/src/java.base/share/classes/java/io/Serial.java b/src/java.base/share/classes/java/io/Serial.java index 60ba804d3a2..d648f046159 100644 --- a/src/java.base/share/classes/java/io/Serial.java +++ b/src/java.base/share/classes/java/io/Serial.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,8 @@ import java.lang.annotation.*; /** * Indicates that an annotated field or method is part of the {@linkplain * Serializable serialization mechanism} defined by the - * Java Object Serialization Specification. This + * + * Java Object Serialization Specification. This * annotation type is intended to allow compile-time checking of * serialization-related declarations, analogous to the checking * enabled by the {@link java.lang.Override} annotation type to diff --git a/src/java.base/share/classes/java/lang/Enum.java b/src/java.base/share/classes/java/lang/Enum.java index 886461c3a91..55926fc3a40 100644 --- a/src/java.base/share/classes/java/lang/Enum.java +++ b/src/java.base/share/classes/java/lang/Enum.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, 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 @@ -51,8 +51,9 @@ import static java.util.Objects.requireNonNull; * by the serialization mechanism. The serialized representation used * for enum constants cannot be customized. Declarations of methods * and fields that would otherwise interact with serialization are - * ignored, including {@code serialVersionUID}; see the Java - * Object Serialization Specification for details. + * ignored, including {@code serialVersionUID}; see the + * Java + * Object Serialization Specification for details. * *

    Note that when using an enumeration type as the type of a set * or as the type of the keys in a map, specialized and efficient diff --git a/src/java.base/share/classes/java/lang/String.java b/src/java.base/share/classes/java/lang/String.java index 43c76d5eb3e..e79884bd4cc 100644 --- a/src/java.base/share/classes/java/lang/String.java +++ b/src/java.base/share/classes/java/lang/String.java @@ -230,7 +230,7 @@ public final class String * * A String instance is written into an ObjectOutputStream according to * - * Object Serialization Specification, Section 6.2, "Stream Elements" + * Java Object Serialization Specification, Section 6.2, "Stream Elements" */ @java.io.Serial private static final ObjectStreamField[] serialPersistentFields = diff --git a/src/java.base/share/classes/java/security/Key.java b/src/java.base/share/classes/java/security/Key.java index b0159f0b33e..4ea5ae0887b 100644 --- a/src/java.base/share/classes/java/security/Key.java +++ b/src/java.base/share/classes/java/security/Key.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2022, 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 @@ -84,7 +84,7 @@ package java.security; * which should not be exposed in untrusted environments. See the * * Security Appendix - * of the Serialization Specification for more information. + * of the Java Object Serialization Specification for more information. * * @see PublicKey * @see PrivateKey diff --git a/src/java.base/share/classes/java/security/KeyRep.java b/src/java.base/share/classes/java/security/KeyRep.java index 341c3d99af1..779f5a7181a 100644 --- a/src/java.base/share/classes/java/security/KeyRep.java +++ b/src/java.base/share/classes/java/security/KeyRep.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,7 +44,7 @@ import javax.crypto.spec.SecretKeySpec; * which should not be exposed in untrusted environments. See the * * Security Appendix - * of the Serialization Specification for more information. + * of the Java Object Serialization Specification for more information. * * @see Key * @see KeyFactory -- GitLab From 85d839fb4f3f820d130ea95f9a54ae137a95c20a Mon Sep 17 00:00:00 2001 From: Chris Plummer Date: Tue, 1 Feb 2022 23:02:06 +0000 Subject: [PATCH 371/564] 8280601: ClhsdbThreadContext.java test is triggering codecache related asserts Reviewed-by: kevinw, sspitsyn --- .../jvm/hotspot/utilities/PointerFinder.java | 16 ++++++++--- .../hotspot/utilities/PointerLocation.java | 27 ++++++++++++------- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PointerFinder.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PointerFinder.java index 90572eefb79..cd9e8264f28 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PointerFinder.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PointerFinder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2022, 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 @@ -135,9 +135,17 @@ public class PointerFinder { CodeCache c = VM.getVM().getCodeCache(); if (c.contains(a)) { loc.inCodeCache = true; - loc.blob = c.findBlobUnsafe(a); - if (Assert.ASSERTS_ENABLED) { - Assert.that(loc.blob != null, "Should have found CodeBlob"); + try { + loc.blob = c.findBlobUnsafe(a); + } catch (Exception e) { + // Since we potentially have a random address in the codecache and therefore could + // be dealing with a freed or partialy intialized blob, exceptions are possible. + } + if (loc.blob == null) { + // It's possible that there is no CodeBlob for this address. Let + // PointerLocation deal with it. + loc.inBlobUnknownLocation = true; + return loc; } loc.inBlobCode = loc.blob.codeContains(a); loc.inBlobData = loc.blob.dataContains(a); diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PointerLocation.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PointerLocation.java index aa2da619b46..a7cfa5de983 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PointerLocation.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PointerLocation.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2022, 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 @@ -301,18 +301,25 @@ public class PointerLocation { } else if (isInBlobOops()) { tty.print("oops"); } else { - if (Assert.ASSERTS_ENABLED) { - Assert.that(isInBlobUnknownLocation(), "Should have known location in CodeBlob"); - } - tty.print("unknown location"); + tty.print("unknown CodeCache location"); } - tty.print(" in "); - if (verbose) { - b.printOn(tty); // includes "\n" + if (b == null) { + tty.println(); } else { - tty.println(b.toString()); + tty.print(" in "); + // Since we potentially have a random address in the codecache and therefore could + // be dealing with a freed or partialy intialized blob, exceptions are possible. + // One known case is an NMethod where the method is still null, resulting in an NPE. + try { + if (verbose) { + b.printOn(tty); // includes "\n" + } else { + tty.println(b.toString()); + } + } catch (Exception e) { + tty.println(""); + } } - // FIXME: add more detail } else if (isInStrongGlobalJNIHandles()) { tty.println("In JNI strong global"); -- GitLab From d32f99ee65679601d6e160e7975fc1e367bfa6f4 Mon Sep 17 00:00:00 2001 From: Roland Westrelin Date: Wed, 2 Feb 2022 07:34:22 +0000 Subject: [PATCH 372/564] 8279219: [REDO] C2 crash when allocating array of size too large Reviewed-by: thartmann, neliasso --- src/hotspot/share/opto/callnode.cpp | 49 +----------- src/hotspot/share/opto/callnode.hpp | 10 +-- src/hotspot/share/opto/cfgnode.cpp | 11 +++ src/hotspot/share/opto/compile.cpp | 29 ++++--- src/hotspot/share/opto/graphKit.cpp | 16 +++- src/hotspot/share/opto/macro.cpp | 14 +++- src/hotspot/share/opto/macro.hpp | 4 +- src/hotspot/share/opto/split_if.cpp | 13 +-- .../TestAllocArrayAfterAllocNoUse.java | 52 ++++++++++++ .../allocation/TestCCPAllocateArray.java | 53 +++++++++++++ .../TestFailedAllocationBadGraph.java | 79 +++++++++++++++++++ 11 files changed, 254 insertions(+), 76 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/allocation/TestAllocArrayAfterAllocNoUse.java create mode 100644 test/hotspot/jtreg/compiler/allocation/TestCCPAllocateArray.java create mode 100644 test/hotspot/jtreg/compiler/allocation/TestFailedAllocationBadGraph.java diff --git a/src/hotspot/share/opto/callnode.cpp b/src/hotspot/share/opto/callnode.cpp index 7345f49cbf1..b4cf07cfbbb 100644 --- a/src/hotspot/share/opto/callnode.cpp +++ b/src/hotspot/share/opto/callnode.cpp @@ -1656,6 +1656,7 @@ AllocateNode::AllocateNode(Compile* C, const TypeFunc *atype, init_req( KlassNode , klass_node); init_req( InitialTest , initial_test); init_req( ALength , topnode); + init_req( ValidLengthTest , topnode); C->add_macro_node(this); } @@ -1682,54 +1683,6 @@ Node *AllocateNode::make_ideal_mark(PhaseGVN *phase, Node* obj, Node* control, N return mark_node; } -//============================================================================= -Node* AllocateArrayNode::Ideal(PhaseGVN *phase, bool can_reshape) { - if (remove_dead_region(phase, can_reshape)) return this; - // Don't bother trying to transform a dead node - if (in(0) && in(0)->is_top()) return NULL; - - const Type* type = phase->type(Ideal_length()); - if (type->isa_int() && type->is_int()->_hi < 0) { - if (can_reshape) { - PhaseIterGVN *igvn = phase->is_IterGVN(); - // Unreachable fall through path (negative array length), - // the allocation can only throw so disconnect it. - Node* proj = proj_out_or_null(TypeFunc::Control); - Node* catchproj = NULL; - if (proj != NULL) { - for (DUIterator_Fast imax, i = proj->fast_outs(imax); i < imax; i++) { - Node *cn = proj->fast_out(i); - if (cn->is_Catch()) { - catchproj = cn->as_Multi()->proj_out_or_null(CatchProjNode::fall_through_index); - break; - } - } - } - if (catchproj != NULL && catchproj->outcnt() > 0 && - (catchproj->outcnt() > 1 || - catchproj->unique_out()->Opcode() != Op_Halt)) { - assert(catchproj->is_CatchProj(), "must be a CatchProjNode"); - Node* nproj = catchproj->clone(); - igvn->register_new_node_with_optimizer(nproj); - - Node *frame = new ParmNode( phase->C->start(), TypeFunc::FramePtr ); - frame = phase->transform(frame); - // Halt & Catch Fire - Node* halt = new HaltNode(nproj, frame, "unexpected negative array length"); - phase->C->root()->add_req(halt); - phase->transform(halt); - - igvn->replace_node(catchproj, phase->C->top()); - return this; - } - } else { - // Can't correct it during regular GVN so register for IGVN - phase->C->record_for_igvn(this); - } - } - return NULL; -} - // Retrieve the length from the AllocateArrayNode. Narrow the type with a // CastII, if appropriate. If we are not allowed to create new nodes, and // a CastII is appropriate, return NULL. diff --git a/src/hotspot/share/opto/callnode.hpp b/src/hotspot/share/opto/callnode.hpp index 7c8baefbca9..1017a76a25e 100644 --- a/src/hotspot/share/opto/callnode.hpp +++ b/src/hotspot/share/opto/callnode.hpp @@ -913,6 +913,7 @@ public: KlassNode, // type (maybe dynamic) of the obj. InitialTest, // slow-path test (may be constant) ALength, // array length (or TOP if none) + ValidLengthTest, ParmLimit }; @@ -922,6 +923,7 @@ public: fields[KlassNode] = TypeInstPtr::NOTNULL; fields[InitialTest] = TypeInt::BOOL; fields[ALength] = t; // length (can be a bad length) + fields[ValidLengthTest] = TypeInt::BOOL; const TypeTuple *domain = TypeTuple::make(ParmLimit, fields); @@ -1016,18 +1018,16 @@ public: // class AllocateArrayNode : public AllocateNode { public: - AllocateArrayNode(Compile* C, const TypeFunc *atype, Node *ctrl, Node *mem, Node *abio, - Node* size, Node* klass_node, Node* initial_test, - Node* count_val - ) + AllocateArrayNode(Compile* C, const TypeFunc* atype, Node* ctrl, Node* mem, Node* abio, Node* size, Node* klass_node, + Node* initial_test, Node* count_val, Node* valid_length_test) : AllocateNode(C, atype, ctrl, mem, abio, size, klass_node, initial_test) { init_class_id(Class_AllocateArray); set_req(AllocateNode::ALength, count_val); + set_req(AllocateNode::ValidLengthTest, valid_length_test); } virtual int Opcode() const; - virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); // Dig the length operand out of a array allocation site. Node* Ideal_length() { diff --git a/src/hotspot/share/opto/cfgnode.cpp b/src/hotspot/share/opto/cfgnode.cpp index e583dd9deec..14357ec8e46 100644 --- a/src/hotspot/share/opto/cfgnode.cpp +++ b/src/hotspot/share/opto/cfgnode.cpp @@ -2687,6 +2687,17 @@ const Type* CatchNode::Value(PhaseGVN* phase) const { // Rethrows always throw exceptions, never return if (call->entry_point() == OptoRuntime::rethrow_stub()) { f[CatchProjNode::fall_through_index] = Type::TOP; + } else if (call->is_AllocateArray()) { + Node* klass_node = call->in(AllocateNode::KlassNode); + Node* length = call->in(AllocateNode::ALength); + const Type* length_type = phase->type(length); + const Type* klass_type = phase->type(klass_node); + Node* valid_length_test = call->in(AllocateNode::ValidLengthTest); + const Type* valid_length_test_t = phase->type(valid_length_test); + if (length_type == Type::TOP || klass_type == Type::TOP || valid_length_test_t == Type::TOP || + valid_length_test_t->is_int()->is_con(0)) { + f[CatchProjNode::fall_through_index] = Type::TOP; + } } else if( call->req() > TypeFunc::Parms ) { const Type *arg0 = phase->type( call->in(TypeFunc::Parms) ); // Check for null receiver to virtual or interface calls diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index 9adda4961e5..1296a3ff8b8 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -3812,7 +3812,7 @@ bool Compile::final_graph_reshaping() { // 'fall-thru' path, so expected kids is 1 less. if (n->is_PCTable() && n->in(0) && n->in(0)->in(0)) { if (n->in(0)->in(0)->is_Call()) { - CallNode *call = n->in(0)->in(0)->as_Call(); + CallNode* call = n->in(0)->in(0)->as_Call(); if (call->entry_point() == OptoRuntime::rethrow_stub()) { required_outcnt--; // Rethrow always has 1 less kid } else if (call->req() > TypeFunc::Parms && @@ -3821,22 +3821,25 @@ bool Compile::final_graph_reshaping() { // detected that the virtual call will always result in a null // pointer exception. The fall-through projection of this CatchNode // will not be populated. - Node *arg0 = call->in(TypeFunc::Parms); + Node* arg0 = call->in(TypeFunc::Parms); if (arg0->is_Type() && arg0->as_Type()->type()->higher_equal(TypePtr::NULL_PTR)) { required_outcnt--; } - } else if (call->entry_point() == OptoRuntime::new_array_Java() && - call->req() > TypeFunc::Parms+1 && - call->is_CallStaticJava()) { - // Check for negative array length. In such case, the optimizer has + } else if (call->entry_point() == OptoRuntime::new_array_Java() || + call->entry_point() == OptoRuntime::new_array_nozero_Java()) { + // Check for illegal array length. In such case, the optimizer has // detected that the allocation attempt will always result in an // exception. There is no fall-through projection of this CatchNode . - Node *arg1 = call->in(TypeFunc::Parms+1); - if (arg1->is_Type() && - arg1->as_Type()->type()->join(TypeInt::POS)->empty()) { + assert(call->is_CallStaticJava(), "static call expected"); + assert(call->req() == call->jvms()->endoff() + 1, "missing extra input"); + Node* valid_length_test = call->in(call->req()-1); + call->del_req(call->req()-1); + if (valid_length_test->find_int_con(1) == 0) { required_outcnt--; } + assert(n->outcnt() == required_outcnt, "malformed control flow"); + continue; } } } @@ -3845,6 +3848,14 @@ bool Compile::final_graph_reshaping() { record_method_not_compilable("malformed control flow"); return true; // Not all targets reachable! } + } else if (n->is_PCTable() && n->in(0) && n->in(0)->in(0) && n->in(0)->in(0)->is_Call()) { + CallNode* call = n->in(0)->in(0)->as_Call(); + if (call->entry_point() == OptoRuntime::new_array_Java() || + call->entry_point() == OptoRuntime::new_array_nozero_Java()) { + assert(call->is_CallStaticJava(), "static call expected"); + assert(call->req() == call->jvms()->endoff() + 1, "missing extra input"); + call->del_req(call->req()-1); // valid length test useless now + } } // Check that I actually visited all kids. Unreached kids // must be infinite loops. diff --git a/src/hotspot/share/opto/graphKit.cpp b/src/hotspot/share/opto/graphKit.cpp index da96ebd9169..ecee3147787 100644 --- a/src/hotspot/share/opto/graphKit.cpp +++ b/src/hotspot/share/opto/graphKit.cpp @@ -2728,7 +2728,9 @@ void GraphKit::make_slow_call_ex(Node* call, ciInstanceKlass* ex_klass, bool sep // Make a catch node with just two handlers: fall-through and catch-all Node* i_o = _gvn.transform( new ProjNode(call, TypeFunc::I_O, separate_io_proj) ); Node* catc = _gvn.transform( new CatchNode(control(), i_o, 2) ); - Node* norm = _gvn.transform( new CatchProjNode(catc, CatchProjNode::fall_through_index, CatchProjNode::no_handler_bci) ); + Node* norm = new CatchProjNode(catc, CatchProjNode::fall_through_index, CatchProjNode::no_handler_bci); + _gvn.set_type_bottom(norm); + C->record_for_igvn(norm); Node* excp = _gvn.transform( new CatchProjNode(catc, CatchProjNode::catch_all_index, CatchProjNode::no_handler_bci) ); { PreserveJVMState pjvms(this); @@ -3969,20 +3971,28 @@ Node* GraphKit::new_array(Node* klass_node, // array klass (maybe variable) initial_slow_test = initial_slow_test->as_Bool()->as_int_value(&_gvn); } + const TypeOopPtr* ary_type = _gvn.type(klass_node)->is_klassptr()->as_instance_type(); + Node* valid_length_test = _gvn.intcon(1); + if (ary_type->klass()->is_array_klass()) { + BasicType bt = ary_type->klass()->as_array_klass()->element_type()->basic_type(); + jint max = TypeAryPtr::max_array_length(bt); + Node* valid_length_cmp = _gvn.transform(new CmpUNode(length, intcon(max))); + valid_length_test = _gvn.transform(new BoolNode(valid_length_cmp, BoolTest::le)); + } + // Create the AllocateArrayNode and its result projections AllocateArrayNode* alloc = new AllocateArrayNode(C, AllocateArrayNode::alloc_type(TypeInt::INT), control(), mem, i_o(), size, klass_node, initial_slow_test, - length); + length, valid_length_test); // Cast to correct type. Note that the klass_node may be constant or not, // and in the latter case the actual array type will be inexact also. // (This happens via a non-constant argument to inline_native_newArray.) // In any case, the value of klass_node provides the desired array type. const TypeInt* length_type = _gvn.find_int_type(length); - const TypeOopPtr* ary_type = _gvn.type(klass_node)->is_klassptr()->as_instance_type(); if (ary_type->isa_aryptr() && length_type != NULL) { // Try to get a better type than POS for the size ary_type = ary_type->is_aryptr()->cast_to_size(length_type); diff --git a/src/hotspot/share/opto/macro.cpp b/src/hotspot/share/opto/macro.cpp index a4bdcecb12a..5f45ffc09c3 100644 --- a/src/hotspot/share/opto/macro.cpp +++ b/src/hotspot/share/opto/macro.cpp @@ -1208,7 +1208,8 @@ void PhaseMacroExpand::expand_allocate_common( AllocateNode* alloc, // allocation node to be expanded Node* length, // array length for an array allocation const TypeFunc* slow_call_type, // Type of slow call - address slow_call_address // Address of slow call + address slow_call_address, // Address of slow call + Node* valid_length_test // whether length is valid or not ) { Node* ctrl = alloc->in(TypeFunc::Control); @@ -1393,6 +1394,12 @@ void PhaseMacroExpand::expand_allocate_common( // Copy debug information and adjust JVMState information, then replace // allocate node with the call call->copy_call_debug_info(&_igvn, alloc); + // For array allocations, copy the valid length check to the call node so Compile::final_graph_reshaping() can verify + // that the call has the expected number of CatchProj nodes (in case the allocation always fails and the fallthrough + // path dies). + if (valid_length_test != NULL) { + call->add_req(valid_length_test); + } if (expand_fast_path) { call->set_cnt(PROB_UNLIKELY_MAG(4)); // Same effect as RC_UNCOMMON. } else { @@ -1875,11 +1882,12 @@ Node* PhaseMacroExpand::prefetch_allocation(Node* i_o, Node*& needgc_false, void PhaseMacroExpand::expand_allocate(AllocateNode *alloc) { expand_allocate_common(alloc, NULL, OptoRuntime::new_instance_Type(), - OptoRuntime::new_instance_Java()); + OptoRuntime::new_instance_Java(), NULL); } void PhaseMacroExpand::expand_allocate_array(AllocateArrayNode *alloc) { Node* length = alloc->in(AllocateNode::ALength); + Node* valid_length_test = alloc->in(AllocateNode::ValidLengthTest); InitializeNode* init = alloc->initialization(); Node* klass_node = alloc->in(AllocateNode::KlassNode); ciKlass* k = _igvn.type(klass_node)->is_klassptr()->klass(); @@ -1894,7 +1902,7 @@ void PhaseMacroExpand::expand_allocate_array(AllocateArrayNode *alloc) { } expand_allocate_common(alloc, length, OptoRuntime::new_array_Type(), - slow_call_address); + slow_call_address, valid_length_test); } //-------------------mark_eliminated_box---------------------------------- diff --git a/src/hotspot/share/opto/macro.hpp b/src/hotspot/share/opto/macro.hpp index b65b97fec87..c028120a0fc 100644 --- a/src/hotspot/share/opto/macro.hpp +++ b/src/hotspot/share/opto/macro.hpp @@ -92,8 +92,8 @@ private: void expand_allocate_common(AllocateNode* alloc, Node* length, const TypeFunc* slow_call_type, - address slow_call_address); - void yank_initalize_node(InitializeNode* node); + address slow_call_address, + Node* valid_length_test); void yank_alloc_node(AllocateNode* alloc); Node *value_from_mem(Node *mem, Node *ctl, BasicType ft, const Type *ftype, const TypeOopPtr *adr_t, AllocateNode *alloc); Node *value_from_mem_phi(Node *mem, BasicType ft, const Type *ftype, const TypeOopPtr *adr_t, AllocateNode *alloc, Node_Stack *value_phis, int level); diff --git a/src/hotspot/share/opto/split_if.cpp b/src/hotspot/share/opto/split_if.cpp index 060d3464514..05babc625c6 100644 --- a/src/hotspot/share/opto/split_if.cpp +++ b/src/hotspot/share/opto/split_if.cpp @@ -128,8 +128,8 @@ bool PhaseIdealLoop::split_up( Node *n, Node *blk1, Node *blk2 ) { } } else { // We might see an Opaque1 from a loop limit check here - assert(use->is_If() || use->is_CMove() || use->Opcode() == Op_Opaque1, "unexpected node type"); - Node *use_c = use->is_If() ? use->in(0) : get_ctrl(use); + assert(use->is_If() || use->is_CMove() || use->Opcode() == Op_Opaque1 || use->is_AllocateArray(), "unexpected node type"); + Node *use_c = (use->is_If() || use->is_AllocateArray()) ? use->in(0) : get_ctrl(use); if (use_c == blk1 || use_c == blk2) { assert(use->is_CMove(), "unexpected node type"); continue; @@ -166,14 +166,15 @@ bool PhaseIdealLoop::split_up( Node *n, Node *blk1, Node *blk2 ) { --j; } else { // We might see an Opaque1 from a loop limit check here - assert(u->is_If() || u->is_CMove() || u->Opcode() == Op_Opaque1, "unexpected node type"); - assert(u->in(1) == bol, ""); + assert(u->is_If() || u->is_CMove() || u->Opcode() == Op_Opaque1 || u->is_AllocateArray(), "unexpected node type"); + assert(u->is_AllocateArray() || u->in(1) == bol, ""); + assert(!u->is_AllocateArray() || u->in(AllocateNode::ValidLengthTest) == bol, "wrong input to AllocateArray"); // Get control block of either the CMove or the If input - Node *u_ctrl = u->is_If() ? u->in(0) : get_ctrl(u); + Node *u_ctrl = (u->is_If() || u->is_AllocateArray()) ? u->in(0) : get_ctrl(u); assert((u_ctrl != blk1 && u_ctrl != blk2) || u->is_CMove(), "won't converge"); Node *x = bol->clone(); register_new_node(x, u_ctrl); - _igvn.replace_input_of(u, 1, x); + _igvn.replace_input_of(u, u->is_AllocateArray() ? AllocateNode::ValidLengthTest : 1, x); --j; } } diff --git a/test/hotspot/jtreg/compiler/allocation/TestAllocArrayAfterAllocNoUse.java b/test/hotspot/jtreg/compiler/allocation/TestAllocArrayAfterAllocNoUse.java new file mode 100644 index 00000000000..e2bc9bfdd16 --- /dev/null +++ b/test/hotspot/jtreg/compiler/allocation/TestAllocArrayAfterAllocNoUse.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2022, Red Hat, Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8279125 + * @summary fatal error: no reachable node should have no use + * @requires vm.flavor == "server" + * + * @run main/othervm -XX:-BackgroundCompilation -XX:-DoEscapeAnalysis TestAllocArrayAfterAllocNoUse + * + */ + +public class TestAllocArrayAfterAllocNoUse { + private static Object field; + + public static void main(String[] args) { + for (int i = 0; i < 20_000; i++) { + test(); + } + } + + private static void test() { + try { + final TestAllocArrayAfterAllocNoUse o = new TestAllocArrayAfterAllocNoUse(); + } catch (Exception e) { + final int[] array = new int[100]; + field = array; + } + + } +} diff --git a/test/hotspot/jtreg/compiler/allocation/TestCCPAllocateArray.java b/test/hotspot/jtreg/compiler/allocation/TestCCPAllocateArray.java new file mode 100644 index 00000000000..9e312a79530 --- /dev/null +++ b/test/hotspot/jtreg/compiler/allocation/TestCCPAllocateArray.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2022, Red Hat, Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8279062 + * @summary C2: assert(t->meet(t0) == t) failed: Not monotonic after JDK-8278413 + * + * @run main/othervm -XX:-BackgroundCompilation TestCCPAllocateArray + * + */ + +public class TestCCPAllocateArray { + public static void main(String[] args) { + for (int i = 0; i < 20_000; i++) { + try { + test(); + } catch (OutOfMemoryError e) { + } + length(42); + } + } + + private static int[] test() { + int i = 2; + for (; i < 4; i *= 2); + return new int[length(i)]; + } + + private static int length(int i) { + return i == 4 ? Integer.MAX_VALUE : 0; + } +} diff --git a/test/hotspot/jtreg/compiler/allocation/TestFailedAllocationBadGraph.java b/test/hotspot/jtreg/compiler/allocation/TestFailedAllocationBadGraph.java new file mode 100644 index 00000000000..bd720a9b4f1 --- /dev/null +++ b/test/hotspot/jtreg/compiler/allocation/TestFailedAllocationBadGraph.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2022, Red Hat, Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * bug 8279219 + * @summary C2 crash when allocating array of size too large + * @library /test/lib / + * @build sun.hotspot.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -ea -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:-BackgroundCompilation TestFailedAllocationBadGraph + */ + +import sun.hotspot.WhiteBox; +import java.lang.reflect.Method; +import compiler.whitebox.CompilerWhiteBoxTest; + +public class TestFailedAllocationBadGraph { + private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); + + private static long[] array; + private static int field; + private static volatile int barrier; + + public static void main(String[] args) throws Exception { + run("test1"); + run("test2"); + } + + private static void run(String method) throws Exception { + Method m = TestFailedAllocationBadGraph.class.getDeclaredMethod(method); + WHITE_BOX.enqueueMethodForCompilation(m, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION); + if (!WHITE_BOX.isMethodCompiled(m) || WHITE_BOX.getMethodCompilationLevel(m) != CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION) { + throw new RuntimeException("should still be compiled"); + } + } + + private static int test1() { + int length = Integer.MAX_VALUE; + try { + array = new long[length]; + } catch (OutOfMemoryError outOfMemoryError) { + barrier = 0x42; + length = field; + } + return length; + } + + private static int test2() { + int length = -1; + try { + array = new long[length]; + } catch (OutOfMemoryError outOfMemoryError) { + barrier = 0x42; + length = field; + } + return length; + } +} -- GitLab From 97af32304101397bb33cbbd1e35fd9124f9e2311 Mon Sep 17 00:00:00 2001 From: Roland Westrelin Date: Wed, 2 Feb 2022 07:35:34 +0000 Subject: [PATCH 373/564] 8280842: Access violation in ciTypeFlow::profiled_count Reviewed-by: neliasso, vlivanov, kvn --- src/hotspot/share/ci/ciTypeFlow.cpp | 3 +- .../TestSharedHeadExceptionBackedges.java | 60 +++++++++++++++++++ 2 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/profiling/TestSharedHeadExceptionBackedges.java diff --git a/src/hotspot/share/ci/ciTypeFlow.cpp b/src/hotspot/share/ci/ciTypeFlow.cpp index 240cb654380..fc8553aac48 100644 --- a/src/hotspot/share/ci/ciTypeFlow.cpp +++ b/src/hotspot/share/ci/ciTypeFlow.cpp @@ -2462,9 +2462,8 @@ int ciTypeFlow::profiled_count(ciTypeFlow::Loop* loop) { } ciProfileData* data = methodData->bci_to_data(tail->control()); - assert(data != NULL, "some profile data expected at branch"); - if (!data->is_JumpData()) { + if (data == NULL || !data->is_JumpData()) { return 0; } diff --git a/test/hotspot/jtreg/compiler/profiling/TestSharedHeadExceptionBackedges.java b/test/hotspot/jtreg/compiler/profiling/TestSharedHeadExceptionBackedges.java new file mode 100644 index 00000000000..e02df36fa1c --- /dev/null +++ b/test/hotspot/jtreg/compiler/profiling/TestSharedHeadExceptionBackedges.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2022, Red Hat, Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * bug 8280842 + * @summary Access violation in ciTypeFlow::profiled_count + * @run main/othervm -XX:-BackgroundCompilation TestSharedHeadExceptionBackedges + */ + +public class TestSharedHeadExceptionBackedges { + public static void main(String[] args) { + for (int i = 0; i < 20_000; i++) { + test(); + } + } + + static class MyException extends Exception { + } + + private static void test() { + int i = 0; + while (i < 10) { + try { + int j = 0; + i++; + if (i % 2 == 0) { + throw new MyException(); + } + do { + j++; + } while (j < 100); + + throw new MyException(); + + } catch (MyException me) { + } + } + } +} -- GitLab From 48a32b5f3aa1b238bc9857002325579a5b041685 Mon Sep 17 00:00:00 2001 From: Jatin Bhateja Date: Wed, 2 Feb 2022 07:36:47 +0000 Subject: [PATCH 374/564] 8280976: Incorrect encoding of avx512 vpsraq instruction with mask and constant shift. Reviewed-by: neliasso, thartmann --- src/hotspot/cpu/x86/assembler_x86.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/cpu/x86/assembler_x86.cpp b/src/hotspot/cpu/x86/assembler_x86.cpp index 3b1e42f3f95..c645e5461de 100644 --- a/src/hotspot/cpu/x86/assembler_x86.cpp +++ b/src/hotspot/cpu/x86/assembler_x86.cpp @@ -9301,7 +9301,7 @@ void Assembler::evpsraq(XMMRegister dst, KRegister mask, XMMRegister src, int sh attributes.reset_is_clear_context(); } int encode = vex_prefix_and_encode(xmm4->encoding(), dst->encoding(), src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F, &attributes); - emit_int24(0x73, (0xC0 | encode), shift & 0xFF); + emit_int24(0x72, (0xC0 | encode), shift & 0xFF); } void Assembler::evpsllw(XMMRegister dst, KRegister mask, XMMRegister nds, XMMRegister src, bool merge, int vector_len) { -- GitLab From ab638341de164965e06bb1d59808670260916b82 Mon Sep 17 00:00:00 2001 From: Roland Westrelin Date: Wed, 2 Feb 2022 07:37:44 +0000 Subject: [PATCH 375/564] 8280885: Shenandoah: Some tests failed with "EA: missing allocation reference path" Reviewed-by: rkennke --- .../shenandoah/c2/shenandoahBarrierSetC2.cpp | 2 +- .../compiler/TestUnexpectedIUBarrierEA.java | 74 +++++++++++++++++++ 2 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 test/hotspot/jtreg/gc/shenandoah/compiler/TestUnexpectedIUBarrierEA.java diff --git a/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp b/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp index 8bd18c1aa66..a9974783c79 100644 --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp @@ -718,7 +718,7 @@ Node* ShenandoahBarrierSetC2::atomic_xchg_at_resolved(C2AtomicParseAccess& acces // Support for GC barriers emitted during parsing bool ShenandoahBarrierSetC2::is_gc_barrier_node(Node* node) const { - if (node->Opcode() == Op_ShenandoahLoadReferenceBarrier) return true; + if (node->Opcode() == Op_ShenandoahLoadReferenceBarrier || node->Opcode() == Op_ShenandoahIUBarrier) return true; if (node->Opcode() != Op_CallLeaf && node->Opcode() != Op_CallLeafNoFP) { return false; } diff --git a/test/hotspot/jtreg/gc/shenandoah/compiler/TestUnexpectedIUBarrierEA.java b/test/hotspot/jtreg/gc/shenandoah/compiler/TestUnexpectedIUBarrierEA.java new file mode 100644 index 00000000000..8662130c378 --- /dev/null +++ b/test/hotspot/jtreg/gc/shenandoah/compiler/TestUnexpectedIUBarrierEA.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2022, Red Hat, Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * bug 8280885 + * @summary Shenandoah: Some tests failed with "EA: missing allocation reference path" + * @requires vm.gc.Shenandoah + * + * @run main/othervm -XX:-BackgroundCompilation -XX:+UseShenandoahGC -XX:+UnlockExperimentalVMOptions -XX:ShenandoahGCMode=iu + * -XX:CompileCommand=dontinline,TestUnexpectedIUBarrierEA::notInlined TestUnexpectedIUBarrierEA + */ + +public class TestUnexpectedIUBarrierEA { + + private static Object field; + + public static void main(String[] args) { + for (int i = 0; i < 20_000; i++) { + test(false); + } + } + + private static void test(boolean flag) { + A a = new A(); + B b = new B(); + b.field = a; + notInlined(); + Object o = b.field; + if (!(o instanceof A)) { + + } + C c = new C(); + c.field = o; + if (flag) { + field = c.field; + } + } + + private static void notInlined() { + + } + + private static class A { + } + + private static class B { + public Object field; + } + + private static class C { + public Object field; + } +} -- GitLab From 4304a7728ec60f7937e0198c4f85384064fe560e Mon Sep 17 00:00:00 2001 From: Roland Westrelin Date: Wed, 2 Feb 2022 07:38:36 +0000 Subject: [PATCH 376/564] 8279535: C2: Dead code in PhaseIdealLoop::create_loop_nest after JDK-8276116 Reviewed-by: thartmann --- src/hotspot/share/opto/loopnode.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/hotspot/share/opto/loopnode.cpp b/src/hotspot/share/opto/loopnode.cpp index d7ec4d6ee64..e2b01f61d49 100644 --- a/src/hotspot/share/opto/loopnode.cpp +++ b/src/hotspot/share/opto/loopnode.cpp @@ -830,10 +830,7 @@ bool PhaseIdealLoop::create_loop_nest(IdealLoopTree* loop, Node_List &old_new) { return false; } - IfNode* exit_test = head->loopexit(); - BoolTest::mask mask = exit_test->as_BaseCountedLoopEnd()->test_trip(); - Node* cmp = exit_test->as_BaseCountedLoopEnd()->cmp_node(); assert(back_control->Opcode() == Op_IfTrue, "wrong projection for back edge"); -- GitLab From de826ba18a5e98586029581c2d4bcd27334fbdd1 Mon Sep 17 00:00:00 2001 From: Roland Westrelin Date: Wed, 2 Feb 2022 08:01:00 +0000 Subject: [PATCH 377/564] 8280600: C2: assert(!had_error) failed: bad dominance Reviewed-by: kvn, thartmann --- src/hotspot/share/opto/loopTransform.cpp | 2 +- .../TestCastIIMakesMainLoopPhiDead.java | 53 +++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 test/hotspot/jtreg/compiler/loopopts/TestCastIIMakesMainLoopPhiDead.java diff --git a/src/hotspot/share/opto/loopTransform.cpp b/src/hotspot/share/opto/loopTransform.cpp index 033ab5d47ab..21dab9335c0 100644 --- a/src/hotspot/share/opto/loopTransform.cpp +++ b/src/hotspot/share/opto/loopTransform.cpp @@ -1234,7 +1234,7 @@ Node *PhaseIdealLoop::clone_up_backedge_goo(Node *back_ctrl, Node *preheader_ctr } Node* PhaseIdealLoop::cast_incr_before_loop(Node* incr, Node* ctrl, Node* loop) { - Node* castii = new CastIINode(incr, TypeInt::INT, ConstraintCastNode::StrongDependency); + Node* castii = new CastIINode(incr, TypeInt::INT, ConstraintCastNode::UnconditionalDependency); castii->set_req(0, ctrl); register_new_node(castii, ctrl); for (DUIterator_Fast imax, i = incr->fast_outs(imax); i < imax; i++) { diff --git a/test/hotspot/jtreg/compiler/loopopts/TestCastIIMakesMainLoopPhiDead.java b/test/hotspot/jtreg/compiler/loopopts/TestCastIIMakesMainLoopPhiDead.java new file mode 100644 index 00000000000..3c40761a77d --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/TestCastIIMakesMainLoopPhiDead.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2022, Red Hat, Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * bug 8280600 + * @summary C2: assert(!had_error) failed: bad dominance + * @run main/othervm -Xcomp -XX:CompileOnly=TestCastIIMakesMainLoopPhiDead TestCastIIMakesMainLoopPhiDead + */ + +public class TestCastIIMakesMainLoopPhiDead { + int iArr[] = new int[0]; + + void test() { + int x = 8; + try { + for (int i = 0; i < 8; i++) { + iArr[1] = 9; + for (int j = -400; 1 > j; j++) { + iArr[j] = 4; + x -= 2; + } + } + } catch (ArrayIndexOutOfBoundsException e) { + } + } + public static void main(String[] k) { + TestCastIIMakesMainLoopPhiDead t = new TestCastIIMakesMainLoopPhiDead(); + for (int i = 0; i < 3; i++) { + t.test(); + } + } +} -- GitLab From ae2504b4692a5298b5835727b04a44e1edc8a4d6 Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Wed, 2 Feb 2022 10:04:50 +0000 Subject: [PATCH 378/564] 8278254: Cleanup doclint warnings in java.desktop module Reviewed-by: aivanov, serb --- .../classes/java/awt/BufferCapabilities.java | 27 ++- .../share/classes/java/awt/Component.java | 10 +- .../classes/java/awt/event/KeyEvent.java | 183 +++++++++++++++--- .../BeanContextServicesSupport.java | 9 +- .../beans/beancontext/BeanContextSupport.java | 15 +- .../swing/DefaultListSelectionModel.java | 8 +- .../share/classes/javax/swing/JApplet.java | 6 +- .../share/classes/javax/swing/JDialog.java | 6 +- .../share/classes/javax/swing/JScrollBar.java | 11 +- .../swing/filechooser/FileSystemView.java | 10 +- .../swing/plaf/basic/BasicMenuItemUI.java | 2 +- .../javax/swing/plaf/basic/BasicMenuUI.java | 1 - .../javax/swing/plaf/metal/MetalBorders.java | 5 +- .../javax/swing/text/LayeredHighlighter.java | 5 +- .../classes/javax/swing/text/html/HTML.java | 7 +- .../javax/swing/text/html/HTMLEditorKit.java | 7 +- .../swing/text/html/parser/AttributeList.java | 15 +- .../javax/swing/text/html/parser/Parser.java | 3 +- .../javax/swing/undo/UndoableEditSupport.java | 3 +- 19 files changed, 251 insertions(+), 82 deletions(-) diff --git a/src/java.desktop/share/classes/java/awt/BufferCapabilities.java b/src/java.desktop/share/classes/java/awt/BufferCapabilities.java index 8d2288023b5..22df13cfb50 100644 --- a/src/java.desktop/share/classes/java/awt/BufferCapabilities.java +++ b/src/java.desktop/share/classes/java/awt/BufferCapabilities.java @@ -33,7 +33,6 @@ package java.awt; * @author Michael Martak * @since 1.4 */ -@SuppressWarnings("doclint:missing") public class BufferCapabilities implements Cloneable { private ImageCapabilities frontCaps; @@ -63,6 +62,8 @@ public class BufferCapabilities implements Cloneable { } /** + * Returns the image capabilities of the front (displayed) buffer. + * * @return the image capabilities of the front (displayed) buffer */ public ImageCapabilities getFrontBufferCapabilities() { @@ -70,6 +71,9 @@ public class BufferCapabilities implements Cloneable { } /** + * Returns the image capabilities of all back buffers (intermediate buffers + * are considered back buffers). + * * @return the image capabilities of all back buffers (intermediate buffers * are considered back buffers) */ @@ -78,27 +82,31 @@ public class BufferCapabilities implements Cloneable { } /** - * @return whether or not the buffer strategy uses page flipping; a set of - * buffers that uses page flipping + * Returns whether or not the buffer strategy uses page flipping. + * A set of buffers that uses page flipping * can swap the contents internally between the front buffer and one or * more back buffers by switching the video pointer (or by copying memory * internally). A non-flipping set of * buffers uses blitting to copy the contents from one buffer to * another; when this is the case, {@code getFlipContents} returns - * {@code null} + * {@code null}. + * + * @return whether or not the buffer strategy uses page flipping */ public boolean isPageFlipping() { return (getFlipContents() != null); } /** - * @return the resulting contents of the back buffer after page-flipping. + * Returns the resulting contents of the back buffer after page-flipping. * This value is {@code null} when the {@code isPageFlipping} * returns {@code false}, implying blitting. It can be one of * {@code FlipContents.UNDEFINED} * (the assumed default), {@code FlipContents.BACKGROUND}, * {@code FlipContents.PRIOR}, or * {@code FlipContents.COPIED}. + * + * @return the resulting contents of the back buffer after page-flipping * @see #isPageFlipping * @see FlipContents#UNDEFINED * @see FlipContents#BACKGROUND @@ -110,9 +118,11 @@ public class BufferCapabilities implements Cloneable { } /** - * @return whether page flipping is only available in full-screen mode. If this + * Returns whether page flipping is only available in full-screen mode. If this * is {@code true}, full-screen exclusive mode is required for * page-flipping. + * + * @return whether page flipping is only available in full-screen mode * @see #isPageFlipping * @see GraphicsDevice#setFullScreenWindow */ @@ -121,9 +131,12 @@ public class BufferCapabilities implements Cloneable { } /** - * @return whether or not + * Returns whether or not * page flipping can be performed using more than two buffers (one or more * intermediate buffers as well as the front and back buffer). + * + * @return whether or not + * page flipping can be performed using more than two buffers * @see #isPageFlipping */ public boolean isMultiBufferAvailable() { diff --git a/src/java.desktop/share/classes/java/awt/Component.java b/src/java.desktop/share/classes/java/awt/Component.java index 2378588b033..813f9bd0c79 100644 --- a/src/java.desktop/share/classes/java/awt/Component.java +++ b/src/java.desktop/share/classes/java/awt/Component.java @@ -214,7 +214,6 @@ import static sun.java2d.pipe.hw.ExtendedBufferCapabilities.VSyncType.VSYNC_ON; * @author Arthur van Hoff * @author Sami Shaio */ -@SuppressWarnings("doclint:missing") public abstract class Component implements ImageObserver, MenuContainer, Serializable { @@ -4133,7 +4132,9 @@ public abstract class Component implements ImageObserver, MenuContainer, } /** - * @return direct access to the back buffer, as an image. + * Provides direct access to the back buffer as an image. + * + * @return the back buffer as an image * @exception IllegalStateException if the buffers have not yet * been created */ @@ -4693,9 +4694,12 @@ public abstract class Component implements ImageObserver, MenuContainer, } /** - * @return whether or not paint messages received from the operating system + * Returns whether or not paint messages received from the operating system * should be ignored. * + * @return whether or not paint messages received from the operating system + * should be ignored + * * @since 1.4 * @see #setIgnoreRepaint */ diff --git a/src/java.desktop/share/classes/java/awt/event/KeyEvent.java b/src/java.desktop/share/classes/java/awt/event/KeyEvent.java index f416719fd2e..21bf7ec1716 100644 --- a/src/java.desktop/share/classes/java/awt/event/KeyEvent.java +++ b/src/java.desktop/share/classes/java/awt/event/KeyEvent.java @@ -151,7 +151,6 @@ import sun.awt.AWTAccessor; * * @since 1.1 */ -@SuppressWarnings("doclint:missing") public class KeyEvent extends InputEvent { /** @@ -650,53 +649,142 @@ public class KeyEvent extends InputEvent { public static final int VK_KP_RIGHT = 0xE3; /* For European keyboards */ - /** @since 1.2 */ + /** + * Constant for the Dead Grave key. + * @since 1.2 + */ public static final int VK_DEAD_GRAVE = 0x80; - /** @since 1.2 */ + + /** + * Constant for the Dead Acute key. + * @since 1.2 + */ public static final int VK_DEAD_ACUTE = 0x81; - /** @since 1.2 */ + + /** + * Constant for the Dead Circumflex key. + * @since 1.2 + */ public static final int VK_DEAD_CIRCUMFLEX = 0x82; - /** @since 1.2 */ + + /** + * Constant for the Dead Tilde key. + * @since 1.2 + */ public static final int VK_DEAD_TILDE = 0x83; - /** @since 1.2 */ + + /** + * Constant for the Dead Macron key. + * @since 1.2 + */ public static final int VK_DEAD_MACRON = 0x84; - /** @since 1.2 */ + + /** + * Constant for the Dead Breve key. + * @since 1.2 + */ public static final int VK_DEAD_BREVE = 0x85; - /** @since 1.2 */ + + /** + * Constant for the Dead Above Dot key. + * @since 1.2 + */ public static final int VK_DEAD_ABOVEDOT = 0x86; - /** @since 1.2 */ + + /** + * Constant for the Dead Diaeresis key. + * @since 1.2 + */ public static final int VK_DEAD_DIAERESIS = 0x87; - /** @since 1.2 */ + + /** + * Constant for the Dead Above Ring key. + * @since 1.2 + */ public static final int VK_DEAD_ABOVERING = 0x88; - /** @since 1.2 */ + + /** + * Constant for the Dead Double Acute key. + * @since 1.2 + */ public static final int VK_DEAD_DOUBLEACUTE = 0x89; - /** @since 1.2 */ + + /** + * Constant for the Dead Caron key. + * @since 1.2 + */ public static final int VK_DEAD_CARON = 0x8a; - /** @since 1.2 */ + + /** + * Constant for the Dead Cedilla key. + * @since 1.2 + */ public static final int VK_DEAD_CEDILLA = 0x8b; - /** @since 1.2 */ + + /** + * Constant for the Dead Ogonek key. + * @since 1.2 + */ public static final int VK_DEAD_OGONEK = 0x8c; - /** @since 1.2 */ + + /** + * Constant for the Dead Iota key. + * @since 1.2 + */ public static final int VK_DEAD_IOTA = 0x8d; - /** @since 1.2 */ + + /** + * Constant for the Dead Voiced Sound key. + * @since 1.2 + */ public static final int VK_DEAD_VOICED_SOUND = 0x8e; - /** @since 1.2 */ + + /** + * Constant for the Dead Semivoiced Sound key. + * @since 1.2 + */ public static final int VK_DEAD_SEMIVOICED_SOUND = 0x8f; - /** @since 1.2 */ + /** + * Constant for the "&" key. + * @since 1.2 + */ public static final int VK_AMPERSAND = 0x96; - /** @since 1.2 */ + + /** + * Constant for the "*" key. + * @since 1.2 + */ public static final int VK_ASTERISK = 0x97; - /** @since 1.2 */ + + /** + * Constant for the """" key. + * @since 1.2 + */ public static final int VK_QUOTEDBL = 0x98; - /** @since 1.2 */ + + /** + * Constant for the "<" key. + * @since 1.2 + */ public static final int VK_LESS = 0x99; - /** @since 1.2 */ + /** + * Constant for the ">" key. + * @since 1.2 + */ public static final int VK_GREATER = 0xa0; - /** @since 1.2 */ + + /** + * Constant for the "{" key. + * @since 1.2 + */ public static final int VK_BRACELEFT = 0xa1; - /** @since 1.2 */ + + /** + * Constant for the "}" key. + * @since 1.2 + */ public static final int VK_BRACERIGHT = 0xa2; /** @@ -926,21 +1014,52 @@ public class KeyEvent extends InputEvent { public static final int VK_INPUT_METHOD_ON_OFF = 0x0107; /* for Sun keyboards */ - /** @since 1.2 */ + /** + * Constant for the Cut key. + * @since 1.2 + */ public static final int VK_CUT = 0xFFD1; - /** @since 1.2 */ + + /** + * Constant for the Copy key. + * @since 1.2 + */ public static final int VK_COPY = 0xFFCD; - /** @since 1.2 */ + + /** + * Constant for the Paste key. + * @since 1.2 + */ public static final int VK_PASTE = 0xFFCF; - /** @since 1.2 */ + + /** + * Constant for the Undo key. + * @since 1.2 + */ public static final int VK_UNDO = 0xFFCB; - /** @since 1.2 */ + + /** + * Constant for the Again key. + * @since 1.2 + */ public static final int VK_AGAIN = 0xFFC9; - /** @since 1.2 */ + + /** + * Constant for the Find key. + * @since 1.2 + */ public static final int VK_FIND = 0xFFD0; - /** @since 1.2 */ + + /** + * Constant for the Props key. + * @since 1.2 + */ public static final int VK_PROPS = 0xFFCA; - /** @since 1.2 */ + + /** + * Constant for the Stop key. + * @since 1.2 + */ public static final int VK_STOP = 0xFFC8; /** diff --git a/src/java.desktop/share/classes/java/beans/beancontext/BeanContextServicesSupport.java b/src/java.desktop/share/classes/java/beans/beancontext/BeanContextServicesSupport.java index d3e6c6ea87a..21e136ba9e5 100644 --- a/src/java.desktop/share/classes/java/beans/beancontext/BeanContextServicesSupport.java +++ b/src/java.desktop/share/classes/java/beans/beancontext/BeanContextServicesSupport.java @@ -54,7 +54,6 @@ import java.util.TooManyListenersException; * @author Laurence P. G. Cable * @since 1.2 */ -@SuppressWarnings("doclint:missing") public class BeanContextServicesSupport extends BeanContextSupport implements BeanContextServices { @@ -157,6 +156,10 @@ public class BeanContextServicesSupport extends BeanContextSupport * when the BeanContextSupport is serialized. */ + /** + * A protected nested class containing per-child information + * in the {@code children} hashtable. + */ protected class BCSSChild extends BeanContextSupport.BCSChild { /** @@ -787,6 +790,10 @@ public class BeanContextServicesSupport extends BeanContextSupport * to an enclosing BeanContext. */ + /** + * Subclasses may subclass this nested class to represent a proxy for + * each BeanContextServiceProvider. + */ protected class BCSSProxyServiceProvider implements BeanContextServiceProvider, BeanContextServiceRevokedListener { BCSSProxyServiceProvider(BeanContextServices bcs) { diff --git a/src/java.desktop/share/classes/java/beans/beancontext/BeanContextSupport.java b/src/java.desktop/share/classes/java/beans/beancontext/BeanContextSupport.java index e5e53db3dfe..66b0995bf02 100644 --- a/src/java.desktop/share/classes/java/beans/beancontext/BeanContextSupport.java +++ b/src/java.desktop/share/classes/java/beans/beancontext/BeanContextSupport.java @@ -59,7 +59,6 @@ import java.util.Map; * @author Laurence P. G. Cable * @since 1.2 */ -@SuppressWarnings("doclint:missing") public class BeanContextSupport extends BeanContextChildSupport implements BeanContext, Serializable, @@ -305,13 +304,17 @@ public class BeanContextSupport extends BeanContextChildSupport * when the BeanContextSupport is serialized. */ - protected class BCSChild implements Serializable { - /** - * Use serialVersionUID from JDK 1.7 for interoperability. + * A protected nested class containing per-child information + * in the {@code children} hashtable. */ - @Serial - private static final long serialVersionUID = -5815286101609939109L; + protected class BCSChild implements Serializable { + + /** + * Use serialVersionUID from JDK 1.7 for interoperability. + */ + @Serial + private static final long serialVersionUID = -5815286101609939109L; BCSChild(Object bcc, Object peer) { super(); diff --git a/src/java.desktop/share/classes/javax/swing/DefaultListSelectionModel.java b/src/java.desktop/share/classes/javax/swing/DefaultListSelectionModel.java index 1924df3123e..55b8fbba66c 100644 --- a/src/java.desktop/share/classes/javax/swing/DefaultListSelectionModel.java +++ b/src/java.desktop/share/classes/javax/swing/DefaultListSelectionModel.java @@ -50,8 +50,7 @@ import javax.swing.event.*; * @see ListSelectionModel * @since 1.2 */ -@SuppressWarnings({"serial", // Same-version serialization only - "doclint:missing"}) +@SuppressWarnings({"serial"}) // Same-version serialization only public class DefaultListSelectionModel implements ListSelectionModel, Cloneable, Serializable { private static final int MIN = -1; @@ -206,6 +205,11 @@ public class DefaultListSelectionModel implements ListSelectionModel, Cloneable, } /** + * Notifies ListSelectionListeners that the value + * of the selection, in the closed interval firstIndex, + * lastIndex, has changed and if this is the final change + * in the series of adjustments. + * * @param firstIndex the first index in the interval * @param lastIndex the last index in the interval * @param isAdjusting true if this is the final change in a series of diff --git a/src/java.desktop/share/classes/javax/swing/JApplet.java b/src/java.desktop/share/classes/javax/swing/JApplet.java index a1ba64dcf0d..a1d51bf0069 100644 --- a/src/java.desktop/share/classes/javax/swing/JApplet.java +++ b/src/java.desktop/share/classes/javax/swing/JApplet.java @@ -99,13 +99,15 @@ import javax.accessibility.AccessibleContext; @Deprecated(since = "9", forRemoval = true) @JavaBean(defaultProperty = "JMenuBar", description = "Swing's Applet subclass.") @SwingContainer(delegate = "getContentPane") -@SuppressWarnings({"serial", "removal", // Same-version serialization only - "doclint:missing"}) +@SuppressWarnings({"serial", "removal"}) // Same-version serialization only public class JApplet extends Applet implements Accessible, RootPaneContainer, TransferHandler.HasGetTransferHandler { /** + * The JRootPane instance that manages the + * contentPane. + * * @see #getRootPane * @see #setRootPane */ diff --git a/src/java.desktop/share/classes/javax/swing/JDialog.java b/src/java.desktop/share/classes/javax/swing/JDialog.java index 97013e59a6b..ace7d15adad 100644 --- a/src/java.desktop/share/classes/javax/swing/JDialog.java +++ b/src/java.desktop/share/classes/javax/swing/JDialog.java @@ -95,8 +95,7 @@ import javax.accessibility.*; */ @JavaBean(defaultProperty = "JMenuBar", description = "A toplevel window for creating dialog boxes.") @SwingContainer(delegate = "getContentPane") -@SuppressWarnings({"serial", // Same-version serialization only - "doclint:missing"}) +@SuppressWarnings({"serial"}) // Same-version serialization only public class JDialog extends Dialog implements WindowConstants, Accessible, RootPaneContainer, @@ -112,6 +111,9 @@ public class JDialog extends Dialog implements WindowConstants, private int defaultCloseOperation = HIDE_ON_CLOSE; /** + * The JRootPane instance that manages the + * contentPane. + * * @see #getRootPane * @see #setRootPane */ diff --git a/src/java.desktop/share/classes/javax/swing/JScrollBar.java b/src/java.desktop/share/classes/javax/swing/JScrollBar.java index 25cdb0886a9..6bb997a6150 100644 --- a/src/java.desktop/share/classes/javax/swing/JScrollBar.java +++ b/src/java.desktop/share/classes/javax/swing/JScrollBar.java @@ -83,8 +83,7 @@ import javax.swing.plaf.ScrollBarUI; */ @JavaBean(defaultProperty = "UI", description = "A component that helps determine the visible content range of an area.") @SwingContainer(false) -@SuppressWarnings({"serial", // Same-version serialization only - "doclint:missing"}) +@SuppressWarnings({"serial"}) // Same-version serialization only public class JScrollBar extends JComponent implements Adjustable, Accessible { /** @@ -109,18 +108,26 @@ public class JScrollBar extends JComponent implements Adjustable, Accessible /** + * Orientation of this scrollBar. + * * @see #setOrientation */ protected int orientation; /** + * Stores the amount by which the value of the scrollbar is changed + * upon a unit up/down request. + * * @see #setUnitIncrement */ protected int unitIncrement; /** + * Stores the amount by which the value of the scrollbar is changed + * upon a block (usually "page") up/down request. + * * @see #setBlockIncrement */ protected int blockIncrement; diff --git a/src/java.desktop/share/classes/javax/swing/filechooser/FileSystemView.java b/src/java.desktop/share/classes/javax/swing/filechooser/FileSystemView.java index 0f30ef14d88..8b0b1190aef 100644 --- a/src/java.desktop/share/classes/javax/swing/filechooser/FileSystemView.java +++ b/src/java.desktop/share/classes/javax/swing/filechooser/FileSystemView.java @@ -65,7 +65,6 @@ import sun.awt.shell.ShellFolder; // PENDING(jeff) - need to provide a specification for // how Mac/OS2/BeOS/etc file systems can modify FileSystemView // to handle their particular type of file system. -@SuppressWarnings("doclint:missing") public abstract class FileSystemView { static FileSystemView windowsFileSystemView = null; @@ -348,13 +347,14 @@ public abstract class FileSystemView { } /** + * Returns a File object which is normally constructed with new + * File(parent, fileName) except when the parent and child are both + * special folders, in which case the File is a wrapper containing + * a ShellFolder object. * * @param parent a File object representing a directory or special folder * @param fileName a name of a file or folder which exists in parent - * @return a File object. This is normally constructed with new - * File(parent, fileName) except when parent and child are both - * special folders, in which case the File is a wrapper containing - * a ShellFolder object. + * @return a File object. * @since 1.4 */ public File getChild(File parent, String fileName) { diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java index fa6a5312767..db9eee52f1f 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java @@ -45,7 +45,6 @@ import sun.swing.*; * @author Arnaud Weber * @author Fredrik Lagerblad */ -@SuppressWarnings("doclint:missing") public class BasicMenuItemUI extends MenuItemUI { /** @@ -257,6 +256,7 @@ public class BasicMenuItemUI extends MenuItemUI } /** + * Registers the subcomponents of the menu. * * @param menuItem a menu item * @since 1.3 diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuUI.java index 78727a729c4..0d2b0fde15e 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuUI.java @@ -46,7 +46,6 @@ import java.util.ArrayList; * @author David Karlton * @author Arnaud Weber */ -@SuppressWarnings("doclint:missing") public class BasicMenuUI extends BasicMenuItemUI { /** diff --git a/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalBorders.java b/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalBorders.java index 9513b723490..d43dd59544a 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalBorders.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalBorders.java @@ -47,7 +47,6 @@ import sun.swing.SwingUtilities2; * Factory object that can vend Borders appropriate for the metal L & F. * @author Steve Wilson */ -@SuppressWarnings("doclint:missing") public class MetalBorders { /** @@ -926,7 +925,7 @@ public class MetalBorders { } /** - * The class represents the border of a {@code JTestField}. + * Border for a {@code JTextField}. */ @SuppressWarnings("serial") // Superclass is not serializable across versions public static class TextFieldBorder extends Flush3DBorder { @@ -1027,6 +1026,8 @@ public class MetalBorders { } /** + * Border for a {@code JToggleButton}. + * * @since 1.3 */ @SuppressWarnings("serial") // Superclass is not serializable across versions diff --git a/src/java.desktop/share/classes/javax/swing/text/LayeredHighlighter.java b/src/java.desktop/share/classes/javax/swing/text/LayeredHighlighter.java index c50710233fc..e484a0d9af2 100644 --- a/src/java.desktop/share/classes/javax/swing/text/LayeredHighlighter.java +++ b/src/java.desktop/share/classes/javax/swing/text/LayeredHighlighter.java @@ -28,12 +28,13 @@ import java.awt.Graphics; import java.awt.Shape; /** + * Implementation of {@code Highlighter} interface to mark up the + * background of leaf views with colored areas. * * @author Scott Violet * @author Timothy Prinzing * @see Highlighter */ -@SuppressWarnings("doclint:missing") public abstract class LayeredHighlighter implements Highlighter { /** * Constructor for subclasses to call. @@ -68,6 +69,8 @@ public abstract class LayeredHighlighter implements Highlighter { protected LayerPainter() {} /** + * Paints a portion of a highlight. + * * @return a shape * @param g Graphics used to draw * @param p0 starting offset of view diff --git a/src/java.desktop/share/classes/javax/swing/text/html/HTML.java b/src/java.desktop/share/classes/javax/swing/text/html/HTML.java index a27893d9fcc..23e3f089b73 100644 --- a/src/java.desktop/share/classes/javax/swing/text/html/HTML.java +++ b/src/java.desktop/share/classes/javax/swing/text/html/HTML.java @@ -43,7 +43,6 @@ import javax.swing.text.StyleContext; * @author Sunita Mani * */ -@SuppressWarnings("doclint:missing") public class HTML { /** @@ -60,7 +59,11 @@ public class HTML { */ public static class Tag { - /** @since 1.3 */ + /** + * Constructs a {@code Tag}. + * + * @since 1.3 + */ public Tag() {} /** diff --git a/src/java.desktop/share/classes/javax/swing/text/html/HTMLEditorKit.java b/src/java.desktop/share/classes/javax/swing/text/html/HTMLEditorKit.java index fb507ed0aea..8d78819b0e8 100644 --- a/src/java.desktop/share/classes/javax/swing/text/html/HTMLEditorKit.java +++ b/src/java.desktop/share/classes/javax/swing/text/html/HTMLEditorKit.java @@ -216,8 +216,7 @@ import static java.nio.charset.StandardCharsets.ISO_8859_1; * * @author Timothy Prinzing */ -@SuppressWarnings({"serial", // Same-version serialization only - "doclint:missing"}) +@SuppressWarnings({"serial"}) // Same-version serialization only public class HTMLEditorKit extends StyledEditorKit implements Accessible { private JEditorPane theEditor; @@ -1684,6 +1683,8 @@ public class HTMLEditorKit extends StyledEditorKit implements Accessible { } /** + * Returns HTMLDocument of the given JEditorPane. + * * @param e the JEditorPane * @return HTMLDocument of e. */ @@ -1696,6 +1697,8 @@ public class HTMLEditorKit extends StyledEditorKit implements Accessible { } /** + * Returns HTMLEditorKit of the given JEditorPane. + * * @param e the JEditorPane * @return HTMLEditorKit for e. */ diff --git a/src/java.desktop/share/classes/javax/swing/text/html/parser/AttributeList.java b/src/java.desktop/share/classes/javax/swing/text/html/parser/AttributeList.java index f57a7f2a917..36d1d0087c5 100644 --- a/src/java.desktop/share/classes/javax/swing/text/html/parser/AttributeList.java +++ b/src/java.desktop/share/classes/javax/swing/text/html/parser/AttributeList.java @@ -44,8 +44,7 @@ import java.io.*; * @author Arthur Van Hoff * */ -@SuppressWarnings({"serial", // Same-version serialization only - "doclint:missing"}) +@SuppressWarnings({"serial"}) // Same-version serialization only public final class AttributeList implements DTDConstants, Serializable { @@ -111,14 +110,14 @@ class AttributeList implements DTDConstants, Serializable { } /** - * @return attribute name + * {@return the attribute name} */ public String getName() { return name; } /** - * @return attribute type + * {@return the attribute type} * @see DTDConstants */ public int getType() { @@ -126,7 +125,7 @@ class AttributeList implements DTDConstants, Serializable { } /** - * @return attribute modifier + * {@return the attribute modifier} * @see DTDConstants */ public int getModifier() { @@ -134,21 +133,21 @@ class AttributeList implements DTDConstants, Serializable { } /** - * @return possible attribute values + * {@return possible attribute values} */ public Enumeration getValues() { return (values != null) ? values.elements() : null; } /** - * @return default attribute value + * {@return default attribute value} */ public String getValue() { return value; } /** - * @return the next attribute in the list + * {@return the next attribute in the list} */ public AttributeList getNext() { return next; diff --git a/src/java.desktop/share/classes/javax/swing/text/html/parser/Parser.java b/src/java.desktop/share/classes/javax/swing/text/html/parser/Parser.java index fc7cac3cdc1..f8a78440fba 100644 --- a/src/java.desktop/share/classes/javax/swing/text/html/parser/Parser.java +++ b/src/java.desktop/share/classes/javax/swing/text/html/parser/Parser.java @@ -75,7 +75,6 @@ import java.net.URL; * @author Arthur van Hoff * @author Sunita Mani */ -@SuppressWarnings("doclint:missing") public class Parser implements DTDConstants { @@ -211,6 +210,8 @@ class Parser implements DTDConstants { /** + * Returns the line number of the line currently being parsed. + * * @return the line number of the line currently being parsed */ protected int getCurrentLine() { diff --git a/src/java.desktop/share/classes/javax/swing/undo/UndoableEditSupport.java b/src/java.desktop/share/classes/javax/swing/undo/UndoableEditSupport.java index 5646222ecb1..f7228d4dc42 100644 --- a/src/java.desktop/share/classes/javax/swing/undo/UndoableEditSupport.java +++ b/src/java.desktop/share/classes/javax/swing/undo/UndoableEditSupport.java @@ -33,7 +33,6 @@ import java.util.*; * * @author Ray Ryan */ -@SuppressWarnings("doclint:missing") public class UndoableEditSupport { /** * The update level. @@ -148,7 +147,7 @@ public class UndoableEditSupport { } /** - * + * Starts a compound edit update. */ public synchronized void beginUpdate() { if (updateLevel == 0) { -- GitLab From 4ea6037ea57ce7bbad00ef172dfc3c122b2317fc Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Wed, 2 Feb 2022 10:43:02 +0000 Subject: [PATCH 379/564] 8281035: Serial: Move RemoveForwardedPointerClosure to local scope Reviewed-by: kbarrett, tschatzl --- .../share/gc/serial/defNewGeneration.cpp | 18 +++++++++++++++--- src/hotspot/share/gc/shared/preservedMarks.cpp | 6 ------ src/hotspot/share/gc/shared/preservedMarks.hpp | 5 ----- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/hotspot/share/gc/serial/defNewGeneration.cpp b/src/hotspot/share/gc/serial/defNewGeneration.cpp index 4b64494d242..dac84ffb78a 100644 --- a/src/hotspot/share/gc/serial/defNewGeneration.cpp +++ b/src/hotspot/share/gc/serial/defNewGeneration.cpp @@ -669,9 +669,21 @@ void DefNewGeneration::init_assuming_no_promotion_failure() { } void DefNewGeneration::remove_forwarding_pointers() { - RemoveForwardedPointerClosure rspc; - eden()->object_iterate(&rspc); - from()->object_iterate(&rspc); + assert(_promotion_failed, "precondition"); + + // Will enter Full GC soon due to failed promotion. Must reset the mark word + // of objs in young-gen so that no objs are marked (forwarded) when Full GC + // starts. (The mark word is overloaded: `is_marked()` == `is_forwarded()`.) + struct ResetForwardedMarkWord : ObjectClosure { + void do_object(oop obj) override { + if (obj->is_forwarded()) { + obj->init_mark(); + } + } + } cl; + eden()->object_iterate(&cl); + from()->object_iterate(&cl); + restore_preserved_marks(); } diff --git a/src/hotspot/share/gc/shared/preservedMarks.cpp b/src/hotspot/share/gc/shared/preservedMarks.cpp index 70d7f6e8934..9003ccb1697 100644 --- a/src/hotspot/share/gc/shared/preservedMarks.cpp +++ b/src/hotspot/share/gc/shared/preservedMarks.cpp @@ -71,12 +71,6 @@ void PreservedMarks::assert_empty() { } #endif // ndef PRODUCT -void RemoveForwardedPointerClosure::do_object(oop obj) { - if (obj->is_forwarded()) { - PreservedMarks::init_forwarded_mark(obj); - } -} - void PreservedMarksSet::init(uint num) { assert(_stacks == nullptr && _num == 0, "do not re-initialize"); assert(num > 0, "pre-condition"); diff --git a/src/hotspot/share/gc/shared/preservedMarks.hpp b/src/hotspot/share/gc/shared/preservedMarks.hpp index 1aa202cfba4..9a09e78bd46 100644 --- a/src/hotspot/share/gc/shared/preservedMarks.hpp +++ b/src/hotspot/share/gc/shared/preservedMarks.hpp @@ -75,11 +75,6 @@ public: ~PreservedMarks() { assert_empty(); } }; -class RemoveForwardedPointerClosure: public ObjectClosure { -public: - virtual void do_object(oop obj); -}; - class PreservedMarksSet : public CHeapObj { private: // true -> _stacks will be allocated in the C heap -- GitLab From ce71e8b281176d39cc879ae4ecf95f3d643ebd29 Mon Sep 17 00:00:00 2001 From: Roman Kennke Date: Wed, 2 Feb 2022 14:56:52 +0000 Subject: [PATCH 380/564] 8279917: Refactor subclassAudits in Thread to use ClassValue Reviewed-by: alanb, rriggs --- .../share/classes/java/lang/Thread.java | 93 ++----------------- 1 file changed, 8 insertions(+), 85 deletions(-) diff --git a/src/java.base/share/classes/java/lang/Thread.java b/src/java.base/share/classes/java/lang/Thread.java index 77e0bbc6129..0d41973b99e 100644 --- a/src/java.base/share/classes/java/lang/Thread.java +++ b/src/java.base/share/classes/java/lang/Thread.java @@ -25,16 +25,11 @@ package java.lang; -import java.lang.ref.Reference; -import java.lang.ref.ReferenceQueue; -import java.lang.ref.WeakReference; import java.security.AccessController; import java.security.AccessControlContext; import java.security.PrivilegedAction; import java.util.Map; import java.util.HashMap; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.LockSupport; @@ -1672,16 +1667,15 @@ public class Thread implements Runnable { } /** cache of subclass security audit results */ - /* Replace with ConcurrentReferenceHashMap when/if it appears in a future - * release */ private static class Caches { /** cache of subclass security audit results */ - static final ConcurrentMap subclassAudits = - new ConcurrentHashMap<>(); - - /** queue for WeakReferences to audited subclasses */ - static final ReferenceQueue> subclassAuditsQueue = - new ReferenceQueue<>(); + static final ClassValue subclassAudits = + new ClassValue<>() { + @Override + protected Boolean computeValue(Class type) { + return auditSubclass(type); + } + }; } /** @@ -1694,15 +1688,7 @@ public class Thread implements Runnable { if (cl == Thread.class) return false; - processQueue(Caches.subclassAuditsQueue, Caches.subclassAudits); - WeakClassKey key = new WeakClassKey(cl, Caches.subclassAuditsQueue); - Boolean result = Caches.subclassAudits.get(key); - if (result == null) { - result = Boolean.valueOf(auditSubclass(cl)); - Caches.subclassAudits.putIfAbsent(key, result); - } - - return result.booleanValue(); + return Caches.subclassAudits.get(cl); } /** @@ -2008,69 +1994,6 @@ public class Thread implements Runnable { getUncaughtExceptionHandler().uncaughtException(this, e); } - /** - * Removes from the specified map any keys that have been enqueued - * on the specified reference queue. - */ - static void processQueue(ReferenceQueue> queue, - ConcurrentMap>, ?> map) - { - Reference> ref; - while((ref = queue.poll()) != null) { - map.remove(ref); - } - } - - /** - * Weak key for Class objects. - **/ - static class WeakClassKey extends WeakReference> { - /** - * saved value of the referent's identity hash code, to maintain - * a consistent hash code after the referent has been cleared - */ - private final int hash; - - /** - * Create a new WeakClassKey to the given object, registered - * with a queue. - */ - WeakClassKey(Class cl, ReferenceQueue> refQueue) { - super(cl, refQueue); - hash = System.identityHashCode(cl); - } - - /** - * Returns the identity hash code of the original referent. - */ - @Override - public int hashCode() { - return hash; - } - - /** - * Returns true if the given object is this identical - * WeakClassKey instance, or, if this object's referent has not - * been cleared, if the given object is another WeakClassKey - * instance with the identical non-null referent as this one. - */ - @Override - public boolean equals(Object obj) { - if (obj == this) - return true; - - if (obj instanceof WeakClassKey) { - Class referent = get(); - return (referent != null) && - (((WeakClassKey) obj).refersTo(referent)); - } else { - return false; - } - } - } - - // The following three initially uninitialized fields are exclusively // managed by class java.util.concurrent.ThreadLocalRandom. These // fields are used to build the high-performance PRNGs in the -- GitLab From 87ab0994ded3b535a160bb87b6540bd072042c44 Mon Sep 17 00:00:00 2001 From: Michael McMahon Date: Wed, 2 Feb 2022 15:04:59 +0000 Subject: [PATCH 381/564] 8280944: Enable Unix domain sockets in Windows Selector notification mechanism Reviewed-by: dfuchs, alanb --- .../windows/classes/sun/nio/ch/PipeImpl.java | 43 ++++++++++++++----- .../sun/nio/ch/WEPollSelectorImpl.java | 2 +- .../sun/nio/ch/WindowsSelectorImpl.java | 2 +- 3 files changed, 34 insertions(+), 13 deletions(-) diff --git a/src/java.base/windows/classes/sun/nio/ch/PipeImpl.java b/src/java.base/windows/classes/sun/nio/ch/PipeImpl.java index b78ac0e3a20..005a0a93339 100644 --- a/src/java.base/windows/classes/sun/nio/ch/PipeImpl.java +++ b/src/java.base/windows/classes/sun/nio/ch/PipeImpl.java @@ -33,6 +33,7 @@ import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.net.StandardSocketOptions; +import java.net.UnixDomainSocketAddress; import java.nio.*; import java.nio.channels.*; import java.nio.file.Files; @@ -44,6 +45,7 @@ import java.security.PrivilegedActionException; import java.security.SecureRandom; import java.util.Random; +import static java.net.StandardProtocolFamily.UNIX; /** * A simple Pipe implementation based on a socket connection. @@ -67,12 +69,14 @@ class PipeImpl { private final SelectorProvider sp; + private final boolean preferUnixDomain; private IOException ioe; SourceChannelImpl source; SinkChannelImpl sink; - private Initializer(SelectorProvider sp) { + private Initializer(SelectorProvider sp, boolean preferUnixDomain) { this.sp = sp; + this.preferUnixDomain = preferUnixDomain; } @Override @@ -120,7 +124,7 @@ class PipeImpl // Bind ServerSocketChannel to a port on the loopback // address if (ssc == null || !ssc.isOpen()) { - ssc = createListener(); + ssc = createListener(preferUnixDomain); sa = ssc.getLocalAddress(); } @@ -162,6 +166,9 @@ class PipeImpl try { if (ssc != null) ssc.close(); + if (sa instanceof UnixDomainSocketAddress uaddr) { + Files.deleteIfExists(uaddr.getPath()); + } } catch (IOException e2) {} } } @@ -169,21 +176,24 @@ class PipeImpl } /** - * Creates a Pipe implementation that supports buffering. + * Creates a (TCP) Pipe implementation that supports buffering. */ PipeImpl(SelectorProvider sp) throws IOException { - this(sp, true); + this(sp, true, false); } /** - * Creates Pipe implementation that supports optionally buffering. + * Creates Pipe implementation that supports optionally buffering + * and is TCP by default, but if Unix domain is supported and + * preferAfUnix is true, then Unix domain sockets are used. + * + * @param preferAfUnix use Unix domain sockets if supported * - * @implNote Uses a loopback connection. When buffering is - * disabled then it sets TCP_NODELAY on the sink channel. + * @param buffering if false set TCP_NODELAY on TCP sockets */ @SuppressWarnings("removal") - PipeImpl(SelectorProvider sp, boolean buffering) throws IOException { - Initializer initializer = new Initializer(sp); + PipeImpl(SelectorProvider sp, boolean preferAfUnix, boolean buffering) throws IOException { + Initializer initializer = new Initializer(sp, preferAfUnix); try { AccessController.doPrivileged(initializer); SinkChannelImpl sink = initializer.sink; @@ -205,8 +215,19 @@ class PipeImpl return sink; } - private static ServerSocketChannel createListener() throws IOException { - ServerSocketChannel listener = ServerSocketChannel.open(); + private static ServerSocketChannel createListener(boolean preferUnixDomain) throws IOException { + ServerSocketChannel listener = null; + if (preferUnixDomain && UnixDomainSockets.isSupported()) { + try { + listener = ServerSocketChannel.open(UNIX); + listener.bind(null); + return listener; + } catch (IOException | UnsupportedOperationException e) { + if (listener != null) + listener.close(); + } + } + listener = ServerSocketChannel.open(); InetAddress lb = InetAddress.getLoopbackAddress(); listener.bind(new InetSocketAddress(lb, 0)); return listener; diff --git a/src/java.base/windows/classes/sun/nio/ch/WEPollSelectorImpl.java b/src/java.base/windows/classes/sun/nio/ch/WEPollSelectorImpl.java index 89331e1211d..8a2f26ef2b7 100644 --- a/src/java.base/windows/classes/sun/nio/ch/WEPollSelectorImpl.java +++ b/src/java.base/windows/classes/sun/nio/ch/WEPollSelectorImpl.java @@ -75,7 +75,7 @@ class WEPollSelectorImpl extends SelectorImpl { // wakeup support try { - this.pipe = new PipeImpl(sp, /*buffering*/ false); + this.pipe = new PipeImpl(sp, /* AF_UNIX */ true, /*buffering*/ false); } catch (IOException ioe) { WEPoll.freePollArray(pollArrayAddress); WEPoll.close(eph); diff --git a/src/java.base/windows/classes/sun/nio/ch/WindowsSelectorImpl.java b/src/java.base/windows/classes/sun/nio/ch/WindowsSelectorImpl.java index 1df7cb76b32..4aa565674a4 100644 --- a/src/java.base/windows/classes/sun/nio/ch/WindowsSelectorImpl.java +++ b/src/java.base/windows/classes/sun/nio/ch/WindowsSelectorImpl.java @@ -139,7 +139,7 @@ class WindowsSelectorImpl extends SelectorImpl { WindowsSelectorImpl(SelectorProvider sp) throws IOException { super(sp); pollWrapper = new PollArrayWrapper(INIT_CAP); - wakeupPipe = new PipeImpl(sp, false); + wakeupPipe = new PipeImpl(sp, /* AF_UNIX */ true, /*buffering*/ false); wakeupSourceFd = ((SelChImpl)wakeupPipe.source()).getFDVal(); wakeupSinkFd = ((SelChImpl)wakeupPipe.sink()).getFDVal(); pollWrapper.addWakeupSocket(wakeupSourceFd, 0); -- GitLab From 9d578537ced356eb0526a70f717b5669e30eadc6 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Wed, 2 Feb 2022 15:17:50 +0000 Subject: [PATCH 382/564] 8281042: G1: Remove unused init_threshold in G1FullGCCompactionPoint Reviewed-by: tschatzl, kbarrett --- src/hotspot/share/gc/g1/g1FullCollector.cpp | 2 +- src/hotspot/share/gc/g1/g1FullGCCompactionPoint.cpp | 8 ++++---- src/hotspot/share/gc/g1/g1FullGCCompactionPoint.hpp | 4 ++-- src/hotspot/share/gc/g1/g1FullGCPrepareTask.inline.hpp | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1FullCollector.cpp b/src/hotspot/share/gc/g1/g1FullCollector.cpp index 37c1e1476eb..e6e7dd25c0a 100644 --- a/src/hotspot/share/gc/g1/g1FullCollector.cpp +++ b/src/hotspot/share/gc/g1/g1FullCollector.cpp @@ -353,7 +353,7 @@ void G1FullCollector::phase2c_prepare_serial_compaction() { if (!cp->is_initialized()) { // Initialize the compaction point. Nothing more is needed for the first heap region // since it is already prepared for compaction. - cp->initialize(current, false); + cp->initialize(current); } else { assert(!current->is_humongous(), "Should be no humongous regions in compaction queue"); G1SerialRePrepareClosure re_prepare(cp, current); diff --git a/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.cpp b/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.cpp index 527397de55e..0e7543ec63d 100644 --- a/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.cpp +++ b/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.cpp @@ -45,7 +45,7 @@ void G1FullGCCompactionPoint::update() { } } -void G1FullGCCompactionPoint::initialize_values(bool init_threshold) { +void G1FullGCCompactionPoint::initialize_values() { _compaction_top = _current_region->compaction_top(); } @@ -57,9 +57,9 @@ bool G1FullGCCompactionPoint::is_initialized() { return _current_region != NULL; } -void G1FullGCCompactionPoint::initialize(HeapRegion* hr, bool init_threshold) { +void G1FullGCCompactionPoint::initialize(HeapRegion* hr) { _current_region = hr; - initialize_values(init_threshold); + initialize_values(); } HeapRegion* G1FullGCCompactionPoint::current_region() { @@ -86,7 +86,7 @@ void G1FullGCCompactionPoint::switch_region() { _current_region->set_compaction_top(_compaction_top); // Get the next region and re-initialize the values. _current_region = next_region(); - initialize_values(true); + initialize_values(); } void G1FullGCCompactionPoint::forward(oop object, size_t size) { diff --git a/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.hpp b/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.hpp index 21bb75ee2e9..41a9783a07c 100644 --- a/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.hpp +++ b/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.hpp @@ -38,7 +38,7 @@ class G1FullGCCompactionPoint : public CHeapObj { GrowableArrayIterator _compaction_region_iterator; bool object_will_fit(size_t size); - void initialize_values(bool init_threshold); + void initialize_values(); void switch_region(); HeapRegion* next_region(); @@ -48,7 +48,7 @@ public: bool has_regions(); bool is_initialized(); - void initialize(HeapRegion* hr, bool init_threshold); + void initialize(HeapRegion* hr); void update(); void forward(oop object, size_t size); void add(HeapRegion* hr); diff --git a/src/hotspot/share/gc/g1/g1FullGCPrepareTask.inline.hpp b/src/hotspot/share/gc/g1/g1FullGCPrepareTask.inline.hpp index 75493b7de4f..a5807c33c37 100644 --- a/src/hotspot/share/gc/g1/g1FullGCPrepareTask.inline.hpp +++ b/src/hotspot/share/gc/g1/g1FullGCPrepareTask.inline.hpp @@ -70,7 +70,7 @@ inline void G1DetermineCompactionQueueClosure::add_to_compaction_queue(HeapRegio hr->set_compaction_top(hr->bottom()); G1FullGCCompactionPoint* cp = next_compaction_point(); if (!cp->is_initialized()) { - cp->initialize(hr, true); + cp->initialize(hr); } // Add region to the compaction queue. cp->add(hr); -- GitLab From 47800bf3da181ae0ee612b14d95773fd1dc90350 Mon Sep 17 00:00:00 2001 From: Daniel Fuchs Date: Wed, 2 Feb 2022 17:11:22 +0000 Subject: [PATCH 383/564] 8280868: LineBodyHandlerTest.java creates and discards too many clients Reviewed-by: michaelm --- .../net/httpclient/LineBodyHandlerTest.java | 27 ++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/test/jdk/java/net/httpclient/LineBodyHandlerTest.java b/test/jdk/java/net/httpclient/LineBodyHandlerTest.java index 601f1ad4080..10717a848bd 100644 --- a/test/jdk/java/net/httpclient/LineBodyHandlerTest.java +++ b/test/jdk/java/net/httpclient/LineBodyHandlerTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2022, 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 @@ -84,7 +84,7 @@ import static org.testng.Assert.assertTrue; * java.logging * jdk.httpserver * @library /test/lib http2/server - * @build Http2TestServer LineBodyHandlerTest HttpServerAdapters + * @build Http2TestServer LineBodyHandlerTest HttpServerAdapters ReferenceTracker * @build jdk.test.lib.net.SimpleSSLContext * @run testng/othervm -XX:+UnlockDiagnosticVMOptions -XX:DiagnoseSyncOnValueBasedClasses=1 LineBodyHandlerTest */ @@ -101,6 +101,10 @@ public class LineBodyHandlerTest implements HttpServerAdapters { String http2URI; String https2URI; + final ReferenceTracker TRACKER = ReferenceTracker.INSTANCE; + final AtomicInteger clientCount = new AtomicInteger(); + HttpClient sharedClient; + @DataProvider(name = "uris") public Object[][] variants() { return new Object[][]{ @@ -189,10 +193,14 @@ public class LineBodyHandlerTest implements HttpServerAdapters { } HttpClient newClient() { - return HttpClient.newBuilder() + if (sharedClient != null) { + return sharedClient; + } + clientCount.incrementAndGet(); + return sharedClient = TRACKER.track(HttpClient.newBuilder() .sslContext(sslContext) .proxy(Builder.NO_PROXY) - .build(); + .build()); } @Test(dataProvider = "uris") @@ -695,10 +703,21 @@ public class LineBodyHandlerTest implements HttpServerAdapters { @AfterTest public void teardown() throws Exception { + sharedClient = null; + try { + System.gc(); + Thread.sleep(200); + } catch (InterruptedException io) { + // don't care; + } + AssertionError fail = TRACKER.check(500); + System.out.printf("Tear down: %s client created.%n", clientCount.get()); + System.err.printf("Tear down: %s client created.%n", clientCount.get()); httpTestServer.stop(); httpsTestServer.stop(); http2TestServer.stop(); https2TestServer.stop(); + if (fail != null) throw fail; } static void printBytes(PrintStream out, String prefix, byte[] bytes) { -- GitLab From e3d5c9e7c4ab210ae7a4417a47632603910744a1 Mon Sep 17 00:00:00 2001 From: Masanori Yano Date: Wed, 2 Feb 2022 21:02:19 +0000 Subject: [PATCH 384/564] 8266974: duplicate property key in java.sql.rowset resource bundle Reviewed-by: lancea --- .../classes/com/sun/rowset/RowSetResourceBundle.properties | 3 +-- .../classes/com/sun/rowset/RowSetResourceBundle_de.properties | 3 +-- .../classes/com/sun/rowset/RowSetResourceBundle_es.properties | 3 +-- .../classes/com/sun/rowset/RowSetResourceBundle_fr.properties | 3 +-- .../classes/com/sun/rowset/RowSetResourceBundle_it.properties | 3 +-- .../classes/com/sun/rowset/RowSetResourceBundle_ja.properties | 3 +-- .../classes/com/sun/rowset/RowSetResourceBundle_ko.properties | 3 +-- .../com/sun/rowset/RowSetResourceBundle_pt_BR.properties | 3 +-- .../classes/com/sun/rowset/RowSetResourceBundle_sv.properties | 3 +-- .../com/sun/rowset/RowSetResourceBundle_zh_CN.properties | 3 +-- .../com/sun/rowset/RowSetResourceBundle_zh_TW.properties | 3 +-- 11 files changed, 11 insertions(+), 22 deletions(-) diff --git a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle.properties b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle.properties index 47ad98d28ae..f84ede5eb41 100644 --- a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle.properties +++ b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2022, 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 @@ -60,7 +60,6 @@ cachedrowsetimpl.movetoins1 = moveToInsertRow : no meta data cachedrowsetimpl.movetoins2 = moveToInsertRow : invalid number of columns cachedrowsetimpl.tablename = Table name cannot be null cachedrowsetimpl.keycols = Invalid key columns -cachedrowsetimpl.invalidcol = Invalid column index cachedrowsetimpl.opnotsupp = Operation not supported by Database cachedrowsetimpl.matchcols = Match columns are not the same as those set cachedrowsetimpl.setmatchcols = Set Match columns before getting them diff --git a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_de.properties b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_de.properties index fe9d17299e7..e1e43a16010 100644 --- a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_de.properties +++ b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_de.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2022, 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 @@ -60,7 +60,6 @@ cachedrowsetimpl.movetoins1 = moveToInsertRow: keine Metadaten cachedrowsetimpl.movetoins2 = moveToInsertRow: ung\u00FCltige Spaltenanzahl cachedrowsetimpl.tablename = Tabellenname darf nicht null sein cachedrowsetimpl.keycols = Ung\u00FCltige Schl\u00FCsselspalten -cachedrowsetimpl.invalidcol = Ung\u00FCltiger Spaltenindex cachedrowsetimpl.opnotsupp = Vorgang nicht von Datenbank unterst\u00FCtzt cachedrowsetimpl.matchcols = \u00DCbereinstimmungsspalten entsprechen nicht den festgelegten Spalten cachedrowsetimpl.setmatchcols = \u00DCbereinstimmungsspalten m\u00FCssen vor dem Abrufen festgelegt werden diff --git a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_es.properties b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_es.properties index 8f9cb1f2392..a07408974a3 100644 --- a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_es.properties +++ b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_es.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2022, 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 @@ -60,7 +60,6 @@ cachedrowsetimpl.movetoins1 = moveToInsertRow: no hay metadatos cachedrowsetimpl.movetoins2 = moveToInsertRow: n\u00FAmero de columnas no v\u00E1lido cachedrowsetimpl.tablename = El nombre de la tabla no puede ser nulo cachedrowsetimpl.keycols = Columnas clave no v\u00E1lidas -cachedrowsetimpl.invalidcol = \u00CDndice de columnas no v\u00E1lido cachedrowsetimpl.opnotsupp = La base de datos no admite esta operaci\u00F3n cachedrowsetimpl.matchcols = Las columnas coincidentes no concuerdan con las definidas cachedrowsetimpl.setmatchcols = Defina las columnas coincidentes antes de obtenerlas diff --git a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_fr.properties b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_fr.properties index 4beab2bf8f1..585ed33b035 100644 --- a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_fr.properties +++ b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_fr.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2022, 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 @@ -60,7 +60,6 @@ cachedrowsetimpl.movetoins1 = moveToInsertRow : aucune m\u00E9tadonn\u00E9e cachedrowsetimpl.movetoins2 = moveToInsertRow : nombre de colonnes non valide cachedrowsetimpl.tablename = Le nom de la table ne peut pas \u00EAtre NULL cachedrowsetimpl.keycols = Colonnes de cl\u00E9 non valides -cachedrowsetimpl.invalidcol = Index de colonne non valide cachedrowsetimpl.opnotsupp = Op\u00E9ration non prise en charge par la base de donn\u00E9es cachedrowsetimpl.matchcols = Les colonnes correspondantes ne sont pas les m\u00EAmes que les colonnes d\u00E9finies cachedrowsetimpl.setmatchcols = D\u00E9finir les colonnes correspondantes avant de les prendre diff --git a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_it.properties b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_it.properties index 4261aedea70..f971660d290 100644 --- a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_it.properties +++ b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_it.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2022, 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 @@ -60,7 +60,6 @@ cachedrowsetimpl.movetoins1 = moveToInsertRow: nessun metadato cachedrowsetimpl.movetoins2 = moveToInsertRow: numero di colonne non valido cachedrowsetimpl.tablename = Il nome di tabella non pu\u00F2 essere nullo cachedrowsetimpl.keycols = Colonne chiave non valide -cachedrowsetimpl.invalidcol = Indice di colonna non valido cachedrowsetimpl.opnotsupp = Operazione non supportata dal database cachedrowsetimpl.matchcols = Le colonne di corrispondenza non coincidono con le colonne impostate cachedrowsetimpl.setmatchcols = Impostare le colonne di corrispondenza prima di recuperarle diff --git a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_ja.properties b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_ja.properties index 3192a22063e..cd40ad2ef42 100644 --- a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_ja.properties +++ b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_ja.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2022, 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 @@ -60,7 +60,6 @@ cachedrowsetimpl.movetoins1 = moveToInsertRow: \u30E1\u30BF\u30C7\u30FC\u30BF\u3 cachedrowsetimpl.movetoins2 = moveToInsertRow: \u7121\u52B9\u306A\u5217\u6570 cachedrowsetimpl.tablename = \u8868\u540D\u306Bnull\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093 cachedrowsetimpl.keycols = \u7121\u52B9\u306A\u30AD\u30FC\u5217 -cachedrowsetimpl.invalidcol = \u7121\u52B9\u306A\u5217\u7D22\u5F15 cachedrowsetimpl.opnotsupp = \u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3067\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u306A\u3044\u64CD\u4F5C cachedrowsetimpl.matchcols = \u4E00\u81F4\u5217\u304C\u5217\u306E\u30BB\u30C3\u30C8\u3068\u540C\u3058\u3067\u306F\u3042\u308A\u307E\u305B\u3093 cachedrowsetimpl.setmatchcols = \u4E00\u81F4\u5217\u3092\u53D6\u5F97\u3059\u308B\u524D\u306B\u8A2D\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044 diff --git a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_ko.properties b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_ko.properties index 81e468eeb1d..9041d671483 100644 --- a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_ko.properties +++ b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_ko.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2022, 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 @@ -60,7 +60,6 @@ cachedrowsetimpl.movetoins1 = moveToInsertRow: \uBA54\uD0C0\uB370\uC774\uD130\uA cachedrowsetimpl.movetoins2 = moveToInsertRow: \uC5F4 \uC218\uAC00 \uBD80\uC801\uD569\uD569\uB2C8\uB2E4. cachedrowsetimpl.tablename = \uD14C\uC774\uBE14 \uC774\uB984\uC740 \uB110\uC77C \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. cachedrowsetimpl.keycols = \uD0A4 \uC5F4\uC774 \uBD80\uC801\uD569\uD569\uB2C8\uB2E4. -cachedrowsetimpl.invalidcol = \uC5F4 \uC778\uB371\uC2A4\uAC00 \uBD80\uC801\uD569\uD569\uB2C8\uB2E4. cachedrowsetimpl.opnotsupp = \uB370\uC774\uD130\uBCA0\uC774\uC2A4\uC5D0\uC11C \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 \uC791\uC5C5\uC785\uB2C8\uB2E4. cachedrowsetimpl.matchcols = \uC77C\uCE58 \uC5F4\uC774 \uC124\uC815\uB41C \uC5F4\uACFC \uB3D9\uC77C\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. cachedrowsetimpl.setmatchcols = \uC77C\uCE58 \uC5F4\uC744 \uC124\uC815\uD55C \uD6C4 \uAC00\uC838\uC624\uC2ED\uC2DC\uC624. diff --git a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_pt_BR.properties b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_pt_BR.properties index 6a2ebe4fa31..05a783ee8fc 100644 --- a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_pt_BR.properties +++ b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_pt_BR.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2022, 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 @@ -60,7 +60,6 @@ cachedrowsetimpl.movetoins1 = moveToInsertRow : sem metadados cachedrowsetimpl.movetoins2 = moveToInsertRow : n\u00FAmero de colunas inv\u00E1lido cachedrowsetimpl.tablename = O nome da tabela n\u00E3o pode ser nulo cachedrowsetimpl.keycols = Colunas de chaves inv\u00E1lidas -cachedrowsetimpl.invalidcol = \u00CDndice de coluna inv\u00E1lido cachedrowsetimpl.opnotsupp = Opera\u00E7\u00E3o n\u00E3o suportada pelo Banco de Dados cachedrowsetimpl.matchcols = As colunas correspondentes n\u00E3o s\u00E3o iguais \u00E0s colunas definidas cachedrowsetimpl.setmatchcols = Definir Colunas correspondentes antes de obt\u00EA-las diff --git a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_sv.properties b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_sv.properties index 912dc257219..5cac0f3c502 100644 --- a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_sv.properties +++ b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_sv.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2022, 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 @@ -60,7 +60,6 @@ cachedrowsetimpl.movetoins1 = moveToInsertRow: inga metadata cachedrowsetimpl.movetoins2 = moveToInsertRow: ogiltigt antal kolumner cachedrowsetimpl.tablename = Tabellnamnet kan inte vara null cachedrowsetimpl.keycols = Ogiltiga nyckelkolumner -cachedrowsetimpl.invalidcol = Ogiltigt kolumnindex cachedrowsetimpl.opnotsupp = Databasen har inte st\u00F6d f\u00F6r denna \u00E5tg\u00E4rd cachedrowsetimpl.matchcols = Matchningskolumnerna \u00E4r inte samma som de som st\u00E4llts in cachedrowsetimpl.setmatchcols = St\u00E4ll in matchningskolumnerna innan du h\u00E4mtar dem diff --git a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_zh_CN.properties b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_zh_CN.properties index adb91c4e8d8..a9f1203518c 100644 --- a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_zh_CN.properties +++ b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_zh_CN.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2022, 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 @@ -60,7 +60,6 @@ cachedrowsetimpl.movetoins1 = moveToInsertRow: \u65E0\u5143\u6570\u636E cachedrowsetimpl.movetoins2 = moveToInsertRow: \u5217\u6570\u65E0\u6548 cachedrowsetimpl.tablename = \u8868\u540D\u4E0D\u80FD\u4E3A\u7A7A\u503C cachedrowsetimpl.keycols = \u5173\u952E\u5B57\u5217\u65E0\u6548 -cachedrowsetimpl.invalidcol = \u5217\u7D22\u5F15\u65E0\u6548 cachedrowsetimpl.opnotsupp = \u64CD\u4F5C\u4E0D\u53D7\u6570\u636E\u5E93\u652F\u6301 cachedrowsetimpl.matchcols = \u5339\u914D\u5217\u4E0E\u8BBE\u7F6E\u7684\u90A3\u4E9B\u5339\u914D\u5217\u4E0D\u540C cachedrowsetimpl.setmatchcols = \u5728\u83B7\u53D6\u5339\u914D\u5217\u4E4B\u524D\u5148\u8BBE\u7F6E\u5339\u914D\u5217 diff --git a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_zh_TW.properties b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_zh_TW.properties index dba19053aee..d42340d39e4 100644 --- a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_zh_TW.properties +++ b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_zh_TW.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2022, 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 @@ -60,7 +60,6 @@ cachedrowsetimpl.movetoins1 = moveToInsertRow: \u6C92\u6709\u63CF\u8FF0\u8CC7\u6 cachedrowsetimpl.movetoins2 = moveToInsertRow: \u6B04\u6578\u7121\u6548 cachedrowsetimpl.tablename = \u8868\u683C\u540D\u7A31\u4E0D\u80FD\u70BA\u7A7A\u503C cachedrowsetimpl.keycols = \u95DC\u9375\u6B04\u7121\u6548 -cachedrowsetimpl.invalidcol = \u6B04\u7D22\u5F15\u7121\u6548 cachedrowsetimpl.opnotsupp = \u8CC7\u6599\u5EAB\u4E0D\u652F\u63F4\u4F5C\u696D cachedrowsetimpl.matchcols = \u5339\u914D\u6B04\u548C\u8A2D\u5B9A\u7684\u6B04\u4E0D\u540C cachedrowsetimpl.setmatchcols = \u5728\u53D6\u5F97\u5339\u914D\u6B04\u4E4B\u524D\u8A2D\u5B9A\u5B83\u5011 -- GitLab From fe0118f8040ce7e5e3d605942443e3a5d442fa92 Mon Sep 17 00:00:00 2001 From: Chris Plummer Date: Wed, 2 Feb 2022 21:51:39 +0000 Subject: [PATCH 385/564] 8279662: serviceability/sa/ClhsdbScanOops.java can fail do to unexpected GC Reviewed-by: sspitsyn, kevinw --- .../serviceability/sa/ClhsdbScanOops.java | 56 +++++++++++++------ 1 file changed, 38 insertions(+), 18 deletions(-) diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbScanOops.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbScanOops.java index c390fc61dca..c032b71a000 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbScanOops.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbScanOops.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022, 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,6 +47,7 @@ import java.util.Map; import java.util.ArrayList; import jdk.test.lib.Utils; import jdk.test.lib.apps.LingeredApp; +import jdk.test.lib.process.OutputAnalyzer; import jtreg.SkippedException; public class ClhsdbScanOops { @@ -71,35 +72,54 @@ public class ClhsdbScanOops { Map> expStrMap = new HashMap<>(); Map> unExpStrMap = new HashMap<>(); - String startAddress = null; - String endAddress = null; - String[] snippets = null; + String startAddress; + String endAddress; + String[] snippets; + String[] words; + String cmd; + // Run scanoops on the old gen + if (gc.contains("UseParallelGC")) { + snippets = universeOutput.split("PSOldGen \\[ "); + } else { + snippets = universeOutput.split("old \\["); + } + words = snippets[1].split(","); + // Get the addresses for Old gen + startAddress = words[0].replace("[", ""); + endAddress = words[1]; + cmd = "scanoops " + startAddress + " " + endAddress; + String output1 = test.run(theApp.getPid(), List.of(cmd), null, null); + + // Run scanoops on the eden gen if (gc.contains("UseParallelGC")) { snippets = universeOutput.split("eden = "); } else { snippets = universeOutput.split("eden \\["); } - String[] words = snippets[1].split(","); - // Get the addresses from Eden + words = snippets[1].split(","); + // Get the addresses for Eden gen startAddress = words[0].replace("[", ""); endAddress = words[1]; - String cmd = "scanoops " + startAddress + " " + endAddress; - cmds.add(cmd); - - expStrMap.put(cmd, List.of - ("java/lang/Object", "java/lang/Class", "java/lang/Thread", - "java/lang/String", "\\[B", "\\[I")); + cmd = "scanoops " + startAddress + " " + endAddress; + String output2 = test.run(theApp.getPid(), List.of(cmd), null, null); + + // Look for expected types in the combined eden and old gens + OutputAnalyzer out = new OutputAnalyzer(output1 + output2); + List expectStrs = List.of( + "java/lang/Object", "java/lang/Class", "java/lang/Thread", + "java/lang/String", "\\[B", "\\[I"); + for (String expectStr : expectStrs) { + out.shouldMatch(expectStr); + } - // Test the 'type' option also - // scanoops java/lang/String + // Test the 'type' option also: + // scanoops java/lang/String // Ensure that only the java/lang/String oops are printed. cmd = cmd + " java/lang/String"; - cmds.add(cmd); expStrMap.put(cmd, List.of("java/lang/String")); - unExpStrMap.put(cmd, List.of("java/lang/Thread")); - - test.run(theApp.getPid(), cmds, expStrMap, unExpStrMap); + unExpStrMap.put(cmd, List.of("java/lang/Thread", "java/lang/Class", "java/lang/Object")); + test.run(theApp.getPid(), List.of(cmd), expStrMap, unExpStrMap); } catch (SkippedException e) { throw e; } catch (Exception ex) { -- GitLab From a95ee5ada230a0177517efd3a417f319066169dd Mon Sep 17 00:00:00 2001 From: Xue-Lei Andrew Fan Date: Thu, 3 Feb 2022 06:28:19 +0000 Subject: [PATCH 386/564] 8065422: Trailing dot in hostname causes TLS handshake to fail with SNI disabled Reviewed-by: weijun --- .../classes/sun/security/ssl/Utilities.java | 11 +- .../security/ssl/X509TrustManagerImpl.java | 6 + .../net/ssl/ServerName/EndingDotHostname.java | 251 +++++++++++++ .../net/ssl/templates/SSLExampleCert.java | 351 ++++++++++++++++++ 4 files changed, 616 insertions(+), 3 deletions(-) create mode 100644 test/jdk/javax/net/ssl/ServerName/EndingDotHostname.java create mode 100644 test/jdk/javax/net/ssl/templates/SSLExampleCert.java diff --git a/src/java.base/share/classes/sun/security/ssl/Utilities.java b/src/java.base/share/classes/sun/security/ssl/Utilities.java index 19fe784e0ca..8317d9ae3cb 100644 --- a/src/java.base/share/classes/sun/security/ssl/Utilities.java +++ b/src/java.base/share/classes/sun/security/ssl/Utilities.java @@ -101,14 +101,19 @@ final class Utilities { * not look like a FQDN */ private static SNIHostName rawToSNIHostName(String hostname) { - SNIHostName sniHostName = null; + // Is it a Fully-Qualified Domain Names (FQDN) ending with a dot? + if (hostname != null && hostname.endsWith(".")) { + // Remove the ending dot, which is not allowed in SNIHostName. + hostname = hostname.substring(0, hostname.length() - 1); + } + if (hostname != null && hostname.indexOf('.') > 0 && !hostname.endsWith(".") && !IPAddressUtil.isIPv4LiteralAddress(hostname) && !IPAddressUtil.isIPv6LiteralAddress(hostname)) { try { - sniHostName = new SNIHostName(hostname); + return new SNIHostName(hostname); } catch (IllegalArgumentException iae) { // don't bother to handle illegal host_name if (SSLLogger.isOn && SSLLogger.isOn("ssl")) { @@ -118,7 +123,7 @@ final class Utilities { } } - return sniHostName; + return null; } /** diff --git a/src/java.base/share/classes/sun/security/ssl/X509TrustManagerImpl.java b/src/java.base/share/classes/sun/security/ssl/X509TrustManagerImpl.java index 63651db53c3..5b18641b3ad 100644 --- a/src/java.base/share/classes/sun/security/ssl/X509TrustManagerImpl.java +++ b/src/java.base/share/classes/sun/security/ssl/X509TrustManagerImpl.java @@ -404,6 +404,12 @@ final class X509TrustManagerImpl extends X509ExtendedTrustManager boolean identifiable = false; String peerHost = session.getPeerHost(); + // Is it a Fully-Qualified Domain Names (FQDN) ending with a dot? + if (peerHost != null && peerHost.endsWith(".")) { + // Remove the ending dot, which is not allowed in SNIHostName. + peerHost = peerHost.substring(0, peerHost.length() - 1); + } + if (!checkClientTrusted) { List sniNames = getRequestedServerNames(session); String sniHostName = getHostNameInSNI(sniNames); diff --git a/test/jdk/javax/net/ssl/ServerName/EndingDotHostname.java b/test/jdk/javax/net/ssl/ServerName/EndingDotHostname.java new file mode 100644 index 00000000000..20ebc144088 --- /dev/null +++ b/test/jdk/javax/net/ssl/ServerName/EndingDotHostname.java @@ -0,0 +1,251 @@ +/* + * Copyright (C) 2022 THL A29 Limited, a Tencent company. 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 8806542 + * @summary Trailing dot in hostname causes TLS handshake to fail + * @library /javax/net/ssl/templates + * @run main/othervm -Djdk.net.hosts.file=hostsForExample EndingDotHostname + */ + +import javax.net.ssl.*; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.*; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +public class EndingDotHostname { + public static void main(String[] args) throws Exception { + System.setProperty("jdk.net.hosts.file", "hostsForExample"); + (new EndingDotHostname()).run(); + } + + public void run() throws Exception { + bootUp(); + } + + // ================================================= + // Stuffs to boot up the client-server mode testing. + private Thread serverThread = null; + private volatile Exception serverException = null; + private volatile Exception clientException = null; + + // Is the server ready to serve? + protected final CountDownLatch serverCondition = new CountDownLatch(1); + + // Is the client ready to handshake? + protected final CountDownLatch clientCondition = new CountDownLatch(1); + + // What's the server port? Use any free port by default + protected volatile int serverPort = 0; + + // Boot up the testing, used to drive remainder of the test. + private void bootUp() throws Exception { + Exception startException = null; + try { + startServer(); + startClient(); + } catch (Exception e) { + startException = e; + } + + // Wait for other side to close down. + if (serverThread != null) { + serverThread.join(); + } + + // The test is pretty much over. Which side threw an exception? + Exception local = clientException; + Exception remote = serverException; + + Exception exception = null; + + // Check various exception conditions. + if ((local != null) && (remote != null)) { + // If both failed, return the curthread's exception. + local.initCause(remote); + exception = local; + } else if (local != null) { + exception = local; + } else if (remote != null) { + exception = remote; + } else if (startException != null) { + exception = startException; + } + + // If there was an exception *AND* a startException, output it. + if (exception != null) { + if (exception != startException && startException != null) { + exception.addSuppressed(startException); + } + throw exception; + } + + // Fall-through: no exception to throw! + } + + private void startServer() { + serverThread = new Thread(() -> { + try { + doServerSide(); + } catch (Exception e) { + // Our server thread just died. Release the client, + // if not active already... + serverException = e; + } + }); + + serverThread.start(); + } + + private void startClient() { + try { + doClientSide(); + } catch (Exception e) { + clientException = e; + } + } + + protected void doServerSide() throws Exception { + // kick off the server side service + SSLContext context = SSLExampleCert.createServerSSLContext(); + SSLServerSocketFactory sslssf = context.getServerSocketFactory(); + + SSLServerSocket sslServerSocket = + (SSLServerSocket)sslssf.createServerSocket(); + sslServerSocket.bind(new InetSocketAddress( + InetAddress.getLoopbackAddress(), 0)); + serverPort = sslServerSocket.getLocalPort(); + + // Signal the client, the server is ready to accept connection. + serverCondition.countDown(); + + // Try to accept a connection in 30 seconds. + SSLSocket sslSocket; + try { + sslServerSocket.setSoTimeout(30000); + sslSocket = (SSLSocket)sslServerSocket.accept(); + } catch (SocketTimeoutException ste) { + // Ignore the test case if no connection within 30 seconds. + System.out.println( + "No incoming client connection in 30 seconds. " + + "Ignore in server side."); + return; + } finally { + sslServerSocket.close(); + } + + // handle the connection + try { + // Is it the expected client connection? + // + // Naughty test cases or third party routines may try to + // connection to this server port unintentionally. In + // order to mitigate the impact of unexpected client + // connections and avoid intermittent failure, it should + // be checked that the accepted connection is really linked + // to the expected client. + boolean clientIsReady = + clientCondition.await(30L, TimeUnit.SECONDS); + + if (clientIsReady) { + // Run the application in server side. + runServerApplication(sslSocket); + } else { // Otherwise, ignore + // We don't actually care about plain socket connections + // for TLS communication testing generally. Just ignore + // the test if the accepted connection is not linked to + // the expected client or the client connection timeout + // in 30 seconds. + System.out.println( + "The client is not the expected one or timeout. " + + "Ignore in server side."); + } + } finally { + sslSocket.close(); + } + } + + // Define the server side application of the test for the specified socket. + protected void runServerApplication(SSLSocket socket) throws Exception { + // here comes the test logic + InputStream sslIS = socket.getInputStream(); + OutputStream sslOS = socket.getOutputStream(); + + sslIS.read(); + sslOS.write(85); + sslOS.flush(); + } + + protected void doClientSide() throws Exception { + // Wait for server to get started. + // + // The server side takes care of the issue if the server cannot + // get started in 90 seconds. The client side would just ignore + // the test case if the serer is not ready. + boolean serverIsReady = + serverCondition.await(90L, TimeUnit.SECONDS); + if (!serverIsReady) { + System.out.println( + "The server is not ready yet in 90 seconds. " + + "Ignore in client side."); + return; + } + + SSLContext context = SSLExampleCert.createClientSSLContext(); + SSLSocketFactory sslsf = context.getSocketFactory(); + + try (SSLSocket sslSocket = (SSLSocket)sslsf.createSocket( + "www.example.com.", serverPort)) { + // OK, here the client and server get connected. + SSLParameters sslParameters = sslSocket.getSSLParameters(); + sslParameters.setEndpointIdentificationAlgorithm("HTTPS"); + sslSocket.setSSLParameters(sslParameters); + + // Signal the server, the client is ready to communicate. + clientCondition.countDown(); + + // There is still a chance in theory that the server thread may + // wait client-ready timeout and then quit. The chance should + // be really rare so we don't consider it until it becomes a + // real problem. + + // Run the application in client side. + runClientApplication(sslSocket); + } + } + + // Define the client side application of the test for the specified socket. + protected void runClientApplication(SSLSocket socket) throws Exception { + InputStream sslIS = socket.getInputStream(); + OutputStream sslOS = socket.getOutputStream(); + + sslOS.write(280); + sslOS.flush(); + sslIS.read(); + } +} + diff --git a/test/jdk/javax/net/ssl/templates/SSLExampleCert.java b/test/jdk/javax/net/ssl/templates/SSLExampleCert.java new file mode 100644 index 00000000000..bc8a1fdb2e9 --- /dev/null +++ b/test/jdk/javax/net/ssl/templates/SSLExampleCert.java @@ -0,0 +1,351 @@ +/* + * Copyright (C) 2022 THL A29 Limited, a Tencent company. 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 javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManagerFactory; +import java.io.*; +import java.net.InetAddress; +import java.security.KeyFactory; +import java.security.KeyStore; +import java.security.PrivateKey; +import java.security.cert.Certificate; +import java.security.cert.CertificateFactory; +import java.security.spec.PKCS8EncodedKeySpec; +import java.util.Base64; + +// A template to use "www.example.com" as the server name. The caller should +// set a virtual hosts file with System Property, "jdk.net.hosts.file". This +// class will map the loopback address to "www.example.com", and write to +// the specified hosts file. +public enum SSLExampleCert { + // Version: 3 (0x2) + // Serial Number: 15223159159760931473 (0xd34386999cc8ca91) + // Signature Algorithm: sha256WithRSAEncryption + // Issuer: C=US, ST=California, O=Example, OU=Test + // Validity + // Not Before: Jan 26 04:50:29 2022 GMT + // Not After : Feb 25 04:50:29 2022 GMT + // Subject: C=US, ST=California, O=Example, OU=Test + // Public Key Algorithm: rsaEncryption + CA_RSA("RSA", + """ + -----BEGIN CERTIFICATE----- + MIIDXDCCAkSgAwIBAgIJANNDhpmcyMqRMA0GCSqGSIb3DQEBCwUAMEMxCzAJBgNV + BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRAwDgYDVQQKDAdFeGFtcGxlMQ0w + CwYDVQQLDARUZXN0MB4XDTIyMDEyNjA0NTAyOVoXDTIyMDIyNTA0NTAyOVowQzEL + MAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExEDAOBgNVBAoMB0V4YW1w + bGUxDTALBgNVBAsMBFRlc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB + AQDnOL2hB/GYyYziXo/ppxi7V1LfMMLeHt0lZbYlrmNxUlln4naI4B4Lkg75eb1Y + DgC7MZQd5nKijK9Dkq52Z2zLxaqBYnLxKJ36qKPqbtTL3I8mfUvVEeNIDN/8YTAt + suIEQi54dNtQVrB4YReMdnUq+xCKLAfEio4QLEQr7KtyCBXHZpM7RYRT0giQFvDU + 2kls9lFLeqKXgocnA7VpoL0V12hpxDeJoRm1szf0M5YXGJumQLaE5qM/+P2OOhw/ + T+xkupy2GF02s6FBXkH7NrFIjtuBSaVhSvCG/N7njWSn339thr3kiPEaCS4KSH5E + E6FEazxZQrTCbkQQ+v3y1pS1AgMBAAGjUzBRMA8GA1UdEwEB/wQFMAMBAf8wHQYD + VR0OBBYEFMFw2FWUvwZx3FJjm1G9TujCjAJSMB8GA1UdIwQYMBaAFMFw2FWUvwZx + 3FJjm1G9TujCjAJSMA0GCSqGSIb3DQEBCwUAA4IBAQCJsJjeYcT/GtKp64C+9KCi + Vgw/WnBZwbosSFZmqyID8aAnAxaGMkZ2B2pUZHTtCkBf6d9c0tuWb5yF8npV77sE + bZqeNg2GU7EvH3WPgPbQVT7+Qb+WbY3EEPgJHLytch61Rm/TRQ3OqD0B+Gs7YjAU + fEspmk1JJ6DWuXX13SHoGWgVnO7rXBnCJaGnGpONtggG4oO5hrwnMzQZKh5eZDhC + 7tkNPqVDoLv+QqnFk8q6k8hhxnVf+aw56IdsebN+9Bi+Lv6OQ+stKUo/u/RTW2z1 + odCOwc8DPF3jbacJsOmLhl3ciuWGOckx9KCvaBeTTgkPdLQH1gpNha2tnqgxUXmC + -----END CERTIFICATE-----""", + + """ + MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDnOL2hB/GYyYzi + Xo/ppxi7V1LfMMLeHt0lZbYlrmNxUlln4naI4B4Lkg75eb1YDgC7MZQd5nKijK9D + kq52Z2zLxaqBYnLxKJ36qKPqbtTL3I8mfUvVEeNIDN/8YTAtsuIEQi54dNtQVrB4 + YReMdnUq+xCKLAfEio4QLEQr7KtyCBXHZpM7RYRT0giQFvDU2kls9lFLeqKXgocn + A7VpoL0V12hpxDeJoRm1szf0M5YXGJumQLaE5qM/+P2OOhw/T+xkupy2GF02s6FB + XkH7NrFIjtuBSaVhSvCG/N7njWSn339thr3kiPEaCS4KSH5EE6FEazxZQrTCbkQQ + +v3y1pS1AgMBAAECggEBAJQAKLkTWZx/njMjbiCT+Wuo6H2+O21r+ge/BAk4h6R4 + nou1VEQmmHS1h+o992mOhP9NK867vDK5tFGfaRaW+vevzYTF3GbqpbxVB56+VG0s + /2AWoVx/96gdvZ1RJEKMFsm9BvvJaLwS0SAsnaMmC7d4Ps0Cg/JU8bv+aaBn/BGf + TWiofYWeUk6llco4kO9H2APxUVzlaUUU/cPAJqX7XktnhDCI9/esuVg7nVR0XxOF + GDrV/jdqSYmSbp4aTRXgI9nwxOmlKiGgevTrCUXl3/KaJxZekllVjushY1VVzgbY + K5R4bcN5MXMmFdgF9DTEW72RqEfg9iXqyhYbZp3Q/UECgYEA/yiaJd0w2HS22HSg + o4dJ072WbyR3qUqQmPbSUn9hBQTJAz1eX3cci8u4oawo/S+jN38b/DfpSg3eIMLB + vnXW3wZtodpJnFaweKd3yUaSF2r9vZRHJgfPfe67VbruEOF6BsCjTq/deGeNnGeH + /IDVn9WtSeRX/bv/s5YHvGaHGGUCgYEA5/vugmilOBq979EqksCG/7EQHSOoEukO + J/aunDyEwz+BMEHOEW7tDMUefdiSfnGXSW+ZTmpmvc+aLk37Xuo34jpugK5ayUFY + iYVgiqdnygGiBevBM2o0O/parQkAGEB8GPButrYItUzubUgXnuw+EdMiXGnpjJaK + S3dPYJEHvhECgYEAjqIIwV/LPUTJLWjMn30yBN43KLvu9ECNYiSfX6R6/I43O8tj + ZOQ1nePsutt9MkMd7xjr8OrkSxRDdnbITQqcaaGzSUW33mALV/btnCMJ6XNSklZA + C39UOuZn7D2JdQBF8V5gK81ddUAVxjeNqdXvFOEidGrj0R/1iVM10dhSbo0CgYBk + P8GtR02Gtj+4P/qW2m48VqbxALSkH2SHrpl8WMbCnVHVqcpETFxSNWjc11dPHwVS + rdBhS6fEhM9LDVYAiVTHBZs1LqN67ys0mpfCs18ts5Dx4BRohI+4D5NZzVbmJA+8 + s0IU4QtYVbt/LDVQ7yRPjZ7+sqJDp9ZxkEiUIXhoEQKBgQCPG2f8BhsCYNAOV60F + hJVjhDdf59Mia3B2J9SSnrg6Tl2rWB7GPP19TiSPFS6Sn95mWrMjZ2ZuOXtCYV4H + +hmu87AV2CXFhW5c588cajXMT92GFVMSXdE1OHRzDjhpH+/ll8SnmQa7sXmEV36+ + sawd7mwcB9IEi562wglADxBUCA== + """), + + // Version: 3 (0x2) + // Serial Number: 14845986384898254166 (0xce0789f5ac256556) + // Signature Algorithm: sha1WithRSAEncryption + // Issuer: C=US, ST=California, O=Example, OU=Test + // Validity + // Not Before: Jan 26 04:50:29 2022 GMT + // Not After : Feb 25 04:50:29 2022 GMT + // Subject: C=US, ST=California, O=Example, OU=Test, CN=www.example.com + // Public Key Algorithm: rsaEncryption + SERVER_EXAMPLE_RSA("RSA", + """ + -----BEGIN CERTIFICATE----- + MIIDjDCCAnSgAwIBAgIJAM4HifWsJWVWMA0GCSqGSIb3DQEBBQUAMEMxCzAJBgNV + BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRAwDgYDVQQKDAdFeGFtcGxlMQ0w + CwYDVQQLDARUZXN0MB4XDTIyMDEyNjA0NTAyOVoXDTIyMDIyNTA0NTAyOVowXTEL + MAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExEDAOBgNVBAoMB0V4YW1w + bGUxDTALBgNVBAsMBFRlc3QxGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTCCASIw + DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK/i4bVSAF6/aFHyzrFAON8Uwn2a + Q9jFoAMowUkH6+PCexlt4wCOEMVH9IQPa1yzeVlkYRqHggz3i6aVYvd27Q+c6vOF + FuRegWdJusyEuoXd5nwxSGiZZMLmFQswODSPmucroCG+Tq9RKY5oEKiRP8tUDqyn + eE52PaeSR2Q6mng7BM5Llj7amVgimO3jlH2AWLLpHNTkc3j/M1QrLFV2PqN4dpxT + OeFuVWzpfTWJSH+9Kq4u/zBMbYl8ON7DSgJAzc2BOw8VPIYIK6JIw6IDbLn4dIQf + GikdgHKB2K6EDOc9LuX6UqQQODDFU88muAyPgpGfUQjxKZeUoTqoAFyisI0CAwEA + AaNpMGcwCQYDVR0TBAIwADAdBgNVHQ4EFgQUQqf/4nqluVMZ8huD3I5FNqLXTqAw + HwYDVR0jBBgwFoAUwXDYVZS/BnHcUmObUb1O6MKMAlIwGgYDVR0RBBMwEYIPd3d3 + LmV4YW1wbGUuY29tMA0GCSqGSIb3DQEBBQUAA4IBAQBl8FJD98fJh/0KY+3LtZDW + CQZDeBSfnpq4milrvHH+gcOCaKYlB9702tAQ6rL1c1dLz/Lpw1x7EYvO8XIwXMRc + DZghf8EJ6wMpZbLVLAQLCTggiB65XPwmhUoMvgVRVLYoXT3ozmNPt7P+ZURisqem + 0/xVVfxqmHw9Hb4DNlc7oZDgOK7IrqriaBK6Amsu3m2eThsvkwTdJfeFG3ZdV6x5 + mbaGZDMt/wgWIqyq5CZNpXPaFRH7KM4zhcoqXvFAoq9jxWOuBkJUUx5EHaxGhhPw + SMgE1yl4O+N7GJmF/WMR5zp2LGKMqJ3vwLPv6QNkUmLwB5ZLYJ8E2dpj6DjQWa7X + -----END CERTIFICATE-----""", + + """ + MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCv4uG1UgBev2hR + 8s6xQDjfFMJ9mkPYxaADKMFJB+vjwnsZbeMAjhDFR/SED2tcs3lZZGEah4IM94um + lWL3du0PnOrzhRbkXoFnSbrMhLqF3eZ8MUhomWTC5hULMDg0j5rnK6Ahvk6vUSmO + aBCokT/LVA6sp3hOdj2nkkdkOpp4OwTOS5Y+2plYIpjt45R9gFiy6RzU5HN4/zNU + KyxVdj6jeHacUznhblVs6X01iUh/vSquLv8wTG2JfDjew0oCQM3NgTsPFTyGCCui + SMOiA2y5+HSEHxopHYBygdiuhAznPS7l+lKkEDgwxVPPJrgMj4KRn1EI8SmXlKE6 + qABcorCNAgMBAAECggEBAJb2SvfP7BVmf+lmV9V249lE/jHECFu0M8TCZDOEowiX + 0gRfdqjxRp+tRMdcXK/yM0Nwjo+wowTyK2DNc2YnIw11h4uAPcfA/ZxjgfssKNPh + Q4Rw4E826W8HACTcPEGQyEmF/ik4KFz9coeR9kpYcMLZ4MZ77xyZDA4Z1UDHs/Fg + egrd4k35fxIFOavsjNuekMIjZlyQ2xU1a11QDBrZAu/pjITXXulg4jCxLbeNOOPs + hH+Sx+jnsVV7qIBNwulzxEdpb3+NkWIMmOQK4HOSeHgjRVvSXXBPgYadMaP/Bzvx + AwJ9WeLZg7KWHE03aOc7CSMoyHfmhXx3gD8icGpSq8ECgYEA3TWGBSgny/wket+V + 65ldWjp4NOKHbLPtBdL9ygIO+1bGfLl5srCxUWHBYdcWCXKuB5ALCBu0hMY+TlwF + s/BzZmvVW7RLAEZZ3Q5HpawDlr9j8Kenm4X2Mqh0MSkmwIDRDHF8jRXAvWIzcBiS + +rPZm2CMZpznUSE4X+GrvTSCBbkCgYEAy4yJ58wNUavj/tR8KySn5ygPABFZ1Uoy + pIyabm18Oe3gCl5UulBskoN0WreTKnA4r9jGlnrgeuu5WfMK53AZKbC+YduZixW4 + QFuJBSMbFCBDt4nkhkMMR7VcV4jIqaOK7qNrs7ubGTZhsG8wj6/WWdCp3Avnx1rS + WCCoYNhAK3UCgYADaLnCBpZmbGJbimqTEPABXflQR1Vy9WrnthK3NETq1rGEZo9b + k6GH8Yu7aEcsqhnIgA3LeDHWAgAf0Qc9eK0unObS3Ppy7KKh54BvKzF690QhB1Rr + 7yqWKUZxI4M3YETYfj8/JWCtCoBkb9yEBJWL8Xb4dd6Sv4JQ5/dvmQmP8QKBgBX+ + 5+Aeksnik060U36uBV7bW1OcjGKaFALoFsAcILJ53B4Ct5Eyo6jpf6dV8xdA7T9D + Y6JbQOrHkk4AD4uW94Ej0k7s1hjLjg+WVKYzdvejzO2GfyVrFWaiWIo1A8ohHCBR + lI/llAsTb1cLjOnaDIXEILbgqnlGfTh8vvVIKRcJAoGALF6Q1Ca2GIx4kJZ2/Az5 + qx89q95wQoWVHcJCA91g/GKg/bD0ZJMWEhhVH3QcnDOU7afRGKOPGdSSBdPQnspQ + 1OPpPjA3U5Mffy5PJ2bHTpPBeeHOzDO4Jt073zK3N81QovJzS8COoOwuGdcocURH + mFMnEtK7d+EK1C1NTWDyNzU= + """), + + + // Version: 3 (0x2) + // Serial Number: 14845986384898254167 (0xce0789f5ac256557) + // Signature Algorithm: sha1WithRSAEncryption + // Issuer: C=US, ST=California, O=Example, OU=Test + // Validity + // Not Before: Jan 26 04:50:29 2022 GMT + // Not After : Feb 25 04:50:29 2022 GMT + // Subject: C=US, ST=California, O=Example, OU=Test, CN=Do-Not-Reply + // Public Key Algorithm: rsaEncryption + CLIENT_EXAMPLE_RSA("RSA", + """ + -----BEGIN CERTIFICATE----- + MIIDkjCCAnqgAwIBAgIJAM4HifWsJWVXMA0GCSqGSIb3DQEBBQUAMEMxCzAJBgNV + BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRAwDgYDVQQKDAdFeGFtcGxlMQ0w + CwYDVQQLDARUZXN0MB4XDTIyMDEyNjA0NTAyOVoXDTIyMDIyNTA0NTAyOVowWjEL + MAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExEDAOBgNVBAoMB0V4YW1w + bGUxDTALBgNVBAsMBFRlc3QxFTATBgNVBAMMDERvLU5vdC1SZXBseTCCASIwDQYJ + KoZIhvcNAQEBBQADggEPADCCAQoCggEBAODbsCteHcAg3dktUO5fiPTytIahKZMg + U2h6h0+BT803tYcdN6WDHnLNlU/3iFnBMpyTwzWhYIftC9c/TIkXBAGfWl4HHQgc + x08NHPms0E+GF6CDthvHERSvRCBrIyVna0KIZPemBzUfeBeNdiqwsLvg+C5dqWu5 + YcILvL6GzTMvdMwJeEX+c2ZYHibqd8aZydWsT+IPVZnueDX6KTOnYvexLFIoid2a + 62FavnMWiPKnICertDDg+gHlN2XceW3tlYQwO+HMig4DH3u2x0SApOoM3y8k29Ew + Fn6wquSRomcbDiI8SEOeaBFenu6W0g24iaxIZfqEM52kPbQFdzqg+O0CAwEAAaNy + MHAwCQYDVR0TBAIwADAdBgNVHQ4EFgQU0t+I5iAfPq6C/I2CSvTKHGK6+2kwHwYD + VR0jBBgwFoAUwXDYVZS/BnHcUmObUb1O6MKMAlIwIwYDVR0RBBwwGoEYZG8tbm90 + LXJlcGx5QGV4YW1wbGUuY29tMA0GCSqGSIb3DQEBBQUAA4IBAQBqWk35XXpb3L+N + 7kPlNmSlhfamenVOVYxPBq/tSFpl728CV0OrGAy79awEFDvzhpbBg9Mz7HS/a7ax + f+lBbsAt1maWlsVSsaaJrmy3znl9CZiIg+ykZ5ZzLS5FkIbQ6LkzvxYZJ1JYCzXm + P/5+rbQyIvQaDGL23PmE7AB2Q0q+imt4b9HKs+SnI4XERyj8OF/kseRtILtP2ltV + r+3XgcBxwyU17CLwsHrjnQ8/1eGovBKzGAfUXeHBdzOuD3ZemjnqwlzQTf2TAkBP + OuMc8gr2Umc5tMtdiRUFPODO7DG7vB7LKEsJGKWLUtGbR+3S55lIcCF5NFZ//TNZ + 4x2GPOJ+ + -----END CERTIFICATE-----""", + + """ + MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDg27ArXh3AIN3Z + LVDuX4j08rSGoSmTIFNoeodPgU/NN7WHHTelgx5yzZVP94hZwTKck8M1oWCH7QvX + P0yJFwQBn1peBx0IHMdPDRz5rNBPhhegg7YbxxEUr0QgayMlZ2tCiGT3pgc1H3gX + jXYqsLC74PguXalruWHCC7y+hs0zL3TMCXhF/nNmWB4m6nfGmcnVrE/iD1WZ7ng1 + +ikzp2L3sSxSKIndmuthWr5zFojypyAnq7Qw4PoB5Tdl3Hlt7ZWEMDvhzIoOAx97 + tsdEgKTqDN8vJNvRMBZ+sKrkkaJnGw4iPEhDnmgRXp7ultINuImsSGX6hDOdpD20 + BXc6oPjtAgMBAAECggEAKjqX900RoUeK4oKUNHBUtEvwg2g4+pyTjYeVaeULK6tO + uDVQghEB4uWhKQd/3/tcmfNWMfhAvMZT9vS4Vvavle5rdkU3upJNDBeWXX2LEaRJ + Q6f4x3a3Sn8v+DamvxuRFUmwTKItsFhcoW+7xYCxcFdrxKlqbATAy0SRCecfGoFw + 9pAsFIgIqLGQtV9V9fZWKdXIfLkH3venNImHt0n5pYadl4kZu0gNCmOGRO1MqB51 + bdAck3dBg22TE5+sZBIZmCjBAEbrc2RUQu5mAoDs8eeenxBlFYszWZxqM8BkJL5e + SqQkbc18E8Gzdx52xEx6BCLTq0MITKliKX4B2tsQsQKBgQD1DIvt13yg9LlyoiAb + Fc1zzKZQBPRgDUJCGzCPeC6AqbPUjoxvFAHxGNgmJXqAXwsqcs88qlSGAjk6ANAx + fHWUQ3UmkZjGvV0ru3rIPcXvS7isjzm/cbq1YZua6+ohFl4+hojc/iyUrOaCd9uY + V2zwrr+A0JJrlev72niEuAtEmwKBgQDq6CaLP79dHqAOIV43+SyX7KdwNkMMWIR7 + El6E/74V0IWOYWFXLmV4sX6BKi0ZBTFZ3wKwMTDqQBYD2/a7gq43HjzuWu+2dFhA + pCQumMOKNqcNS9NldqoxAiGLxC+JMhGGyf3RO0Ey9gdPnQuje3133Wce8WWaHHv2 + lD5BcmzdFwKBgQCCeca7wiPy07s2ZUqxAT/eq5XWP30a85RW/IEzsusXyMQepjPy + JPYPuInGbeg3F+QrGuxrQco1fFOaJbq0zq8QXYawHY/6KfPFCFMM8Y9FpczT3IME + A3tFfo5Kw9hq+6z8n8eZ26BDHXiy+Tysdchksrb20JdVv4LiG+ZVzGT7hwKBgG+b + Bp0IF4JFh6PPBLWxRBeWT2MH1Mkr0R2r945W91fj72BbMeU63Oj/42u4vx5xEiZx + xxQw+t2AvzTsMAicqOr1CdvxBoz4L+neUnZ1DApBtxKhIPnG7EtGiOuftToIuL0C + gP4EmhB9RbH0mk/83vqxDUptRGl4+QiJHB76H3DXAoGASGT6tfs1/92rGqe0COm3 + aHpelvW7Wwr9AuBumE7/ur/JWAAiM4pm6w7m5H5duYZtG3eWz1s+jvjy8jIPBIkN + RA2DoneC2J/tsRRNFBqZrOWon5Jv4dc9R79qR13B/Oqu8H6FYSB2oDyh67Csud3q + PRrz4o7UKM+HQ/obr1rUYqM= + """); + + final String keyAlgo; + final String certStr; + final String privateKeyStr; + + // Trusted certificate + private final static SSLExampleCert[] TRUSTED_CERTS = { + SSLExampleCert.CA_RSA + }; + + // Server certificate. + private final static SSLExampleCert[] SERVER_CERTS = { + SSLExampleCert.SERVER_EXAMPLE_RSA + }; + + // Client certificate. + private final static SSLExampleCert[] CLIENT_CERTS = { + SSLExampleCert.CLIENT_EXAMPLE_RSA + }; + + // Set "www.example.com" to loopback address. + static { + String hostsFileName = System.getProperty("jdk.net.hosts.file"); + String loopbackHostname = + InetAddress.getLoopbackAddress().getHostAddress() + + " " + "www.example.com www.example.com.\n"; + try (FileWriter writer= new FileWriter(hostsFileName, false)) { + writer.write(loopbackHostname); + } catch (IOException ioe) { + // ignore + } + } + + SSLExampleCert(String keyAlgo, String certStr, String privateKeyStr) { + this.keyAlgo = keyAlgo; + this.certStr = certStr; + this.privateKeyStr = privateKeyStr; + } + + public static SSLContext createClientSSLContext() throws Exception { + return createSSLContext(TRUSTED_CERTS, CLIENT_CERTS); + } + + public static SSLContext createServerSSLContext() throws Exception { + return createSSLContext(TRUSTED_CERTS, SERVER_CERTS); + } + + private static SSLContext createSSLContext( + SSLExampleCert[] trustedCerts, + SSLExampleCert[] endEntityCerts) throws Exception { + char[] passphrase = "passphrase".toCharArray(); + + // Generate certificate from cert string. + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + + // Import the trusted certs. + KeyStore ts = null; // trust store + if (trustedCerts != null && trustedCerts.length != 0) { + ts = KeyStore.getInstance("PKCS12"); + ts.load(null, null); + + Certificate[] trustedCert = new Certificate[trustedCerts.length]; + for (int i = 0; i < trustedCerts.length; i++) { + try (ByteArrayInputStream is = new ByteArrayInputStream( + trustedCerts[i].certStr.getBytes())) { + trustedCert[i] = cf.generateCertificate(is); + } + + ts.setCertificateEntry("trusted-cert-" + + trustedCerts[i].name(), trustedCert[i]); + } + } + + // Import the key materials. + KeyStore ks = null; // trust store + if (endEntityCerts != null && endEntityCerts.length != 0) { + ks = KeyStore.getInstance("PKCS12"); + ks.load(null, null); + + for (SSLExampleCert endEntityCert : endEntityCerts) { + // generate the private key. + PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec( + Base64.getMimeDecoder() + .decode(endEntityCert.privateKeyStr)); + KeyFactory kf = + KeyFactory.getInstance( + endEntityCert.keyAlgo); + PrivateKey priKey = kf.generatePrivate(priKeySpec); + + // generate certificate chain + Certificate keyCert; + try (ByteArrayInputStream is = new ByteArrayInputStream( + endEntityCert.certStr.getBytes())) { + keyCert = cf.generateCertificate(is); + } + + Certificate[] chain = new Certificate[]{keyCert}; + + // import the key entry. + ks.setKeyEntry("end-entity-cert-" + + endEntityCert.name(), + priKey, passphrase, chain); + } + } + + // Create an SSLContext object. + TrustManagerFactory tmf = + TrustManagerFactory.getInstance("PKIX"); + tmf.init(ts); + + SSLContext context = SSLContext.getInstance("TLS"); + if (endEntityCerts != null && endEntityCerts.length != 0) { + KeyManagerFactory kmf = + KeyManagerFactory.getInstance("NewSunX509"); + kmf.init(ks, passphrase); + + context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + } else { + context.init(null, tmf.getTrustManagers(), null); + } + + return context; + } +} -- GitLab From fe547eacd71b4eb8119ecc7ca2d0bbe8e757f854 Mon Sep 17 00:00:00 2001 From: Artem Semenov Date: Thu, 3 Feb 2022 07:22:30 +0000 Subject: [PATCH 387/564] 8280956: Re-examine copyright headers on files in src/java.desktop/macosx/native/libawt_lwawt/awt/a11y Reviewed-by: kizune, prr --- .../macosx/native/libawt_lwawt/awt/a11y/CellAccessibility.h | 4 +++- .../macosx/native/libawt_lwawt/awt/a11y/CellAccessibility.m | 4 +++- .../macosx/native/libawt_lwawt/awt/a11y/ColumnAccessibility.h | 4 +++- .../macosx/native/libawt_lwawt/awt/a11y/ColumnAccessibility.m | 4 +++- .../native/libawt_lwawt/awt/a11y/ComboBoxAccessibility.h | 4 +++- .../native/libawt_lwawt/awt/a11y/ComboBoxAccessibility.m | 4 +++- .../libawt_lwawt/awt/a11y/ComponentWrapperAccessibility.h | 4 +++- .../libawt_lwawt/awt/a11y/ComponentWrapperAccessibility.m | 4 +++- .../macosx/native/libawt_lwawt/awt/a11y/ListAccessibility.h | 4 +++- .../macosx/native/libawt_lwawt/awt/a11y/ListAccessibility.m | 4 +++- .../native/libawt_lwawt/awt/a11y/ListRowAccessibility.h | 4 +++- .../native/libawt_lwawt/awt/a11y/ListRowAccessibility.m | 4 +++- .../native/libawt_lwawt/awt/a11y/NavigableTextAccessibility.h | 4 +++- .../native/libawt_lwawt/awt/a11y/NavigableTextAccessibility.m | 4 +++- .../native/libawt_lwawt/awt/a11y/OutlineAccessibility.h | 4 +++- .../native/libawt_lwawt/awt/a11y/OutlineAccessibility.m | 4 +++- .../native/libawt_lwawt/awt/a11y/OutlineRowAccessibility.h | 4 +++- .../native/libawt_lwawt/awt/a11y/OutlineRowAccessibility.m | 4 +++- .../native/libawt_lwawt/awt/a11y/TabButtonAccessibility.h | 4 +++- .../native/libawt_lwawt/awt/a11y/TabButtonAccessibility.m | 4 +++- .../native/libawt_lwawt/awt/a11y/TabGroupAccessibility.h | 4 +++- .../native/libawt_lwawt/awt/a11y/TabGroupAccessibility.m | 4 +++- .../macosx/native/libawt_lwawt/awt/a11y/TableAccessibility.h | 4 +++- .../macosx/native/libawt_lwawt/awt/a11y/TableAccessibility.m | 4 +++- .../native/libawt_lwawt/awt/a11y/TableRowAccessibility.h | 4 +++- .../native/libawt_lwawt/awt/a11y/TableRowAccessibility.m | 4 +++- 26 files changed, 78 insertions(+), 26 deletions(-) diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CellAccessibility.h b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CellAccessibility.h index ef67c92a06d..103f2c31912 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CellAccessibility.h +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CellAccessibility.h @@ -5,7 +5,9 @@ * * 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. + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CellAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CellAccessibility.m index c44309a1e3c..ba91dbb8b6f 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CellAccessibility.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CellAccessibility.m @@ -5,7 +5,9 @@ * * 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. + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ColumnAccessibility.h b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ColumnAccessibility.h index a78afaa924b..80f633f4a91 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ColumnAccessibility.h +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ColumnAccessibility.h @@ -5,7 +5,9 @@ * * 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. + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ColumnAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ColumnAccessibility.m index 238b82f609e..fb41511275b 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ColumnAccessibility.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ColumnAccessibility.m @@ -5,7 +5,9 @@ * * 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. + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ComboBoxAccessibility.h b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ComboBoxAccessibility.h index 4a39938a826..cfdd1faee61 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ComboBoxAccessibility.h +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ComboBoxAccessibility.h @@ -5,7 +5,9 @@ * * 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. + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ComboBoxAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ComboBoxAccessibility.m index 0fd70eb8151..0029436579f 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ComboBoxAccessibility.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ComboBoxAccessibility.m @@ -5,7 +5,9 @@ * * 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. + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ComponentWrapperAccessibility.h b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ComponentWrapperAccessibility.h index fd1e774c274..269ea2d5ff8 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ComponentWrapperAccessibility.h +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ComponentWrapperAccessibility.h @@ -5,7 +5,9 @@ * * 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. + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ComponentWrapperAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ComponentWrapperAccessibility.m index 2101d7042fe..c2ce3260871 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ComponentWrapperAccessibility.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ComponentWrapperAccessibility.m @@ -5,7 +5,9 @@ * * 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. + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ListAccessibility.h b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ListAccessibility.h index ddfcd2217f8..88f55f99c34 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ListAccessibility.h +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ListAccessibility.h @@ -5,7 +5,9 @@ * * 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. + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ListAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ListAccessibility.m index 4dc958886bb..fc75efc6029 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ListAccessibility.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ListAccessibility.m @@ -5,7 +5,9 @@ * * 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. + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ListRowAccessibility.h b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ListRowAccessibility.h index 130d12721e6..2b3b4412beb 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ListRowAccessibility.h +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ListRowAccessibility.h @@ -5,7 +5,9 @@ * * 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. + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ListRowAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ListRowAccessibility.m index 8b30080c85b..dc9e617d43c 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ListRowAccessibility.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ListRowAccessibility.m @@ -5,7 +5,9 @@ * * 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. + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/NavigableTextAccessibility.h b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/NavigableTextAccessibility.h index 33a05318b5a..ebf314c7394 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/NavigableTextAccessibility.h +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/NavigableTextAccessibility.h @@ -5,7 +5,9 @@ * * 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. + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/NavigableTextAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/NavigableTextAccessibility.m index 84d8785e205..138d502f10f 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/NavigableTextAccessibility.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/NavigableTextAccessibility.m @@ -5,7 +5,9 @@ * * 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. + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineAccessibility.h b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineAccessibility.h index 48074b209e0..2992d82cbe4 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineAccessibility.h +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineAccessibility.h @@ -5,7 +5,9 @@ * * 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. + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineAccessibility.m index acc5727cd6b..cdf6dbbd4ab 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineAccessibility.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineAccessibility.m @@ -5,7 +5,9 @@ * * 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. + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineRowAccessibility.h b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineRowAccessibility.h index 8cc8e1760c6..4185c0a27b9 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineRowAccessibility.h +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineRowAccessibility.h @@ -5,7 +5,9 @@ * * 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. + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineRowAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineRowAccessibility.m index e4d7e66027d..4653821283d 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineRowAccessibility.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineRowAccessibility.m @@ -5,7 +5,9 @@ * * 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. + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabButtonAccessibility.h b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabButtonAccessibility.h index 0b497d4afc2..892225cf2ac 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabButtonAccessibility.h +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabButtonAccessibility.h @@ -5,7 +5,9 @@ * * 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. + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabButtonAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabButtonAccessibility.m index 538240028b8..2b22db80aa8 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabButtonAccessibility.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabButtonAccessibility.m @@ -5,7 +5,9 @@ * * 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. + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabGroupAccessibility.h b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabGroupAccessibility.h index c99b18c904e..c660ff0e780 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabGroupAccessibility.h +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabGroupAccessibility.h @@ -5,7 +5,9 @@ * * 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. + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabGroupAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabGroupAccessibility.m index 76fafc0faaf..06375fc2934 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabGroupAccessibility.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabGroupAccessibility.m @@ -5,7 +5,9 @@ * * 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. + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableAccessibility.h b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableAccessibility.h index 5fe04aa257f..6fa9fd0b636 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableAccessibility.h +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableAccessibility.h @@ -5,7 +5,9 @@ * * 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. + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableAccessibility.m index d6382822e1e..d9d18b24fce 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableAccessibility.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableAccessibility.m @@ -5,7 +5,9 @@ * * 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. + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableRowAccessibility.h b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableRowAccessibility.h index afa9eb44e3f..d9c19ccbc42 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableRowAccessibility.h +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableRowAccessibility.h @@ -5,7 +5,9 @@ * * 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. + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableRowAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableRowAccessibility.m index 31636dd99bb..890ac973311 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableRowAccessibility.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableRowAccessibility.m @@ -5,7 +5,9 @@ * * 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. + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -- GitLab From 5ab22e88da8d79f9e19e8afffdd06206f42bab94 Mon Sep 17 00:00:00 2001 From: Roman Kennke Date: Thu, 3 Feb 2022 07:24:59 +0000 Subject: [PATCH 388/564] 8276990: Memory leak in invoker.c fillInvokeRequest() during JDI operations Reviewed-by: sspitsyn, cjplummer --- src/jdk.jdwp.agent/share/native/libjdwp/invoker.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/jdk.jdwp.agent/share/native/libjdwp/invoker.c b/src/jdk.jdwp.agent/share/native/libjdwp/invoker.c index 42e6741d467..2f6eb5f40a1 100644 --- a/src/jdk.jdwp.agent/share/native/libjdwp/invoker.c +++ b/src/jdk.jdwp.agent/share/native/libjdwp/invoker.c @@ -232,6 +232,7 @@ fillInvokeRequest(JNIEnv *env, InvokeRequest *request, /* * Squirrel away the method signature */ + JDI_ASSERT_MSG(request->methodSignature == NULL, "Request methodSignature not null"); error = methodSignature(method, NULL, &request->methodSignature, NULL); if (error != JVMTI_ERROR_NONE) { return error; @@ -775,6 +776,10 @@ invoker_completeInvokeRequest(jthread thread) */ deleteGlobalArgumentRefs(env, request); + JDI_ASSERT_MSG(request->methodSignature != NULL, "methodSignature is NULL"); + jvmtiDeallocate(request->methodSignature); + request->methodSignature = NULL; + /* From now on, do not access the request structure anymore * for this request id, because once we give up the invokerLock it may * be immediately reused by a new invoke request. -- GitLab From 63a00a0df24b154ef459936dbd69bcd2f0626235 Mon Sep 17 00:00:00 2001 From: Kevin Walls Date: Thu, 3 Feb 2022 10:10:45 +0000 Subject: [PATCH 389/564] 8272777: Clean up remaining AccessController warnings in test library Reviewed-by: rriggs, sspitsyn --- test/lib/jdk/test/lib/SA/SATestUtils.java | 1 + test/lib/jdk/test/lib/net/IPSupport.java | 3 ++- test/lib/jdk/test/lib/net/SimpleSSLContext.java | 3 ++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/test/lib/jdk/test/lib/SA/SATestUtils.java b/test/lib/jdk/test/lib/SA/SATestUtils.java index d4daf5ef145..2f98cf99357 100644 --- a/test/lib/jdk/test/lib/SA/SATestUtils.java +++ b/test/lib/jdk/test/lib/SA/SATestUtils.java @@ -159,6 +159,7 @@ public class SATestUtils { * if we are root, so return true. Then return false for an expected denial * if "ptrace_scope" is 1, and true otherwise. */ + @SuppressWarnings("removal") private static boolean canPtraceAttachLinux() throws IOException { // SELinux deny_ptrace: var deny_ptrace = Paths.get("/sys/fs/selinux/booleans/deny_ptrace"); diff --git a/test/lib/jdk/test/lib/net/IPSupport.java b/test/lib/jdk/test/lib/net/IPSupport.java index b86354a2503..78efba3a172 100644 --- a/test/lib/jdk/test/lib/net/IPSupport.java +++ b/test/lib/jdk/test/lib/net/IPSupport.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -71,6 +71,7 @@ public class IPSupport { } } + @SuppressWarnings("removal") private static T runPrivilegedAction(Callable callable) { try { PrivilegedExceptionAction pa = () -> callable.call(); diff --git a/test/lib/jdk/test/lib/net/SimpleSSLContext.java b/test/lib/jdk/test/lib/net/SimpleSSLContext.java index 5660ed048aa..e8611fb007f 100644 --- a/test/lib/jdk/test/lib/net/SimpleSSLContext.java +++ b/test/lib/jdk/test/lib/net/SimpleSSLContext.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2022, 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 @@ -54,6 +54,7 @@ public class SimpleSSLContext { this(() -> "TLS"); } + @SuppressWarnings("removal") private SimpleSSLContext(Supplier protocols) throws IOException { try { final String proto = protocols.get(); -- GitLab From 010965c86ab39260b882df807c4f5d6420b20ca9 Mon Sep 17 00:00:00 2001 From: Thomas Stuefe Date: Thu, 3 Feb 2022 14:12:29 +0000 Subject: [PATCH 390/564] 8281023: NMT integration into pp debug command does not work Reviewed-by: zgu, iklam --- src/hotspot/share/services/mallocTracker.cpp | 30 ++++++++++++++ src/hotspot/share/services/mallocTracker.hpp | 10 +++++ .../share/services/virtualMemoryTracker.cpp | 30 ++++++++------ .../share/services/virtualMemoryTracker.hpp | 4 +- src/hotspot/share/utilities/debug.cpp | 41 ++++++------------- 5 files changed, 72 insertions(+), 43 deletions(-) diff --git a/src/hotspot/share/services/mallocTracker.cpp b/src/hotspot/share/services/mallocTracker.cpp index e27d312ad81..04cf12be94f 100644 --- a/src/hotspot/share/services/mallocTracker.cpp +++ b/src/hotspot/share/services/mallocTracker.cpp @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "runtime/os.hpp" +#include "runtime/safefetch.inline.hpp" #include "services/mallocSiteTable.hpp" #include "services/mallocTracker.hpp" #include "services/mallocTracker.inline.hpp" @@ -289,3 +290,32 @@ void* MallocTracker::record_free(void* memblock) { header->release(); return (void*)header; } + +// Given a pointer, if it seems to point to the start of a valid malloced block, +// print the block. Note that since there is very low risk of memory looking +// accidentally like a valid malloc block header (canaries and all) this is not +// totally failproof. Only use this during debugging or when you can afford +// signals popping up, e.g. when writing an hs_err file. +bool MallocTracker::print_pointer_information(const void* p, outputStream* st) { + assert(MemTracker::enabled(), "NMT must be enabled"); + if (CanUseSafeFetch32() && os::is_readable_pointer(p)) { + const NMT_TrackingLevel tracking_level = MemTracker::tracking_level(); + const MallocHeader* mhdr = (const MallocHeader*)MallocTracker::get_base(const_cast(p), tracking_level); + char msg[256]; + address p_corrupted; + if (os::is_readable_pointer(mhdr) && + mhdr->check_block_integrity(msg, sizeof(msg), &p_corrupted)) { + st->print_cr(PTR_FORMAT " malloc'd " SIZE_FORMAT " bytes by %s", + p2i(p), mhdr->size(), NMTUtil::flag_to_name(mhdr->flags())); + if (tracking_level == NMT_detail) { + NativeCallStack ncs; + if (mhdr->get_stack(ncs)) { + ncs.print_on(st); + st->cr(); + } + } + return true; + } + } + return false; +} diff --git a/src/hotspot/share/services/mallocTracker.hpp b/src/hotspot/share/services/mallocTracker.hpp index ac8eaf17c5c..78e20c30f15 100644 --- a/src/hotspot/share/services/mallocTracker.hpp +++ b/src/hotspot/share/services/mallocTracker.hpp @@ -31,6 +31,8 @@ #include "services/nmtCommon.hpp" #include "utilities/nativeCallStack.hpp" +class outputStream; + /* * This counter class counts memory allocation and deallocation, * records total memory allocation size and number of allocations. @@ -438,6 +440,14 @@ class MallocTracker : AllStatic { static inline void record_arena_size_change(ssize_t size, MEMFLAGS flags) { MallocMemorySummary::record_arena_size_change(size, flags); } + + // Given a pointer, if it seems to point to the start of a valid malloced block, + // print the block. Note that since there is very low risk of memory looking + // accidentally like a valid malloc block header (canaries and all) this is not + // totally failproof. Only use this during debugging or when you can afford + // signals popping up, e.g. when writing an hs_err file. + static bool print_pointer_information(const void* p, outputStream* st); + private: static inline MallocHeader* malloc_header(void *memblock) { assert(memblock != NULL, "NULL pointer"); diff --git a/src/hotspot/share/services/virtualMemoryTracker.cpp b/src/hotspot/share/services/virtualMemoryTracker.cpp index 53a2cf10642..d259966e611 100644 --- a/src/hotspot/share/services/virtualMemoryTracker.cpp +++ b/src/hotspot/share/services/virtualMemoryTracker.cpp @@ -672,28 +672,32 @@ bool VirtualMemoryTracker::walk_virtual_memory(VirtualMemoryWalker* walker) { return true; } -class FindAndSnapshotRegionWalker : public VirtualMemoryWalker { +class PrintRegionWalker : public VirtualMemoryWalker { private: - ReservedMemoryRegion& _region; - const address _p; - bool _found_region; + const address _p; + outputStream* _st; public: - FindAndSnapshotRegionWalker(void* p, ReservedMemoryRegion& region) : - _region(region), _p((address)p), _found_region(false) { } + PrintRegionWalker(const void* p, outputStream* st) : + _p((address)p), _st(st) { } bool do_allocation_site(const ReservedMemoryRegion* rgn) { if (rgn->contain_address(_p)) { - _region = *rgn; - _found_region = true; + _st->print_cr(PTR_FORMAT " in mmap'd memory region [" PTR_FORMAT " - " PTR_FORMAT "] by %s", + p2i(_p), p2i(rgn->base()), p2i(rgn->base() + rgn->size()), rgn->flag_name()); + if (MemTracker::tracking_level() == NMT_detail) { + rgn->call_stack()->print_on(_st); + _st->cr(); + } return false; } return true; } - bool found_region() const { return _found_region; } }; -const bool VirtualMemoryTracker::snapshot_region_contains(void* p, ReservedMemoryRegion& region) { - FindAndSnapshotRegionWalker walker(p, region); - walk_virtual_memory(&walker); - return walker.found_region(); +// If p is contained within a known memory region, print information about it to the +// given stream and return true; false otherwise. +bool VirtualMemoryTracker::print_containing_region(const void* p, outputStream* st) { + PrintRegionWalker walker(p, st); + return !walk_virtual_memory(&walker); + } diff --git a/src/hotspot/share/services/virtualMemoryTracker.hpp b/src/hotspot/share/services/virtualMemoryTracker.hpp index 15627470f78..9ae61a605fb 100644 --- a/src/hotspot/share/services/virtualMemoryTracker.hpp +++ b/src/hotspot/share/services/virtualMemoryTracker.hpp @@ -385,7 +385,9 @@ class VirtualMemoryTracker : AllStatic { // Walk virtual memory data structure for creating baseline, etc. static bool walk_virtual_memory(VirtualMemoryWalker* walker); - static const bool snapshot_region_contains(void* p, ReservedMemoryRegion& region); + // If p is contained within a known memory region, print information about it to the + // given stream and return true; false otherwise. + static bool print_containing_region(const void* p, outputStream* st); // Snapshot current thread stacks static void snapshot_thread_stacks(); diff --git a/src/hotspot/share/utilities/debug.cpp b/src/hotspot/share/utilities/debug.cpp index bb2a0446aee..e8d95ebec1c 100644 --- a/src/hotspot/share/utilities/debug.cpp +++ b/src/hotspot/share/utilities/debug.cpp @@ -44,7 +44,6 @@ #include "runtime/handles.inline.hpp" #include "runtime/java.hpp" #include "runtime/os.hpp" -#include "runtime/safefetch.inline.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/stubCodeGenerator.hpp" #include "runtime/stubRoutines.hpp" @@ -483,39 +482,23 @@ extern "C" JNIEXPORT void pp(void* p) { oop obj = cast_to_oop(p); obj->print(); } else { + // Ask NMT about this pointer. + // GDB note: We will be using SafeFetch to access the supposed malloc header. If the address is + // not readable, this will generate a signal. That signal will trip up the debugger: gdb will + // catch the signal and disable the pp() command for further use. + // In order to avoid that, switch off SIGSEGV handling with "handle SIGSEGV nostop" before + // invoking pp() if (MemTracker::enabled()) { - const NMT_TrackingLevel tracking_level = MemTracker::tracking_level(); - ReservedMemoryRegion region(0, 0); - // Check and snapshot a mmap'd region that contains the pointer - if (VirtualMemoryTracker::snapshot_region_contains(p, region)) { - tty->print_cr(PTR_FORMAT " in mmap'd memory region [" PTR_FORMAT " - " PTR_FORMAT "] by %s", - p2i(p), p2i(region.base()), p2i(region.base() + region.size()), region.flag_name()); - if (tracking_level == NMT_detail) { - region.call_stack()->print_on(tty); - tty->cr(); - } + // Does it point into a known mmaped region? + if (VirtualMemoryTracker::print_containing_region(p, tty)) { return; } - // Check if it is a malloc'd memory block - if (CanUseSafeFetchN() && SafeFetchN((intptr_t*)p, 0) != 0) { - const MallocHeader* mhdr = (const MallocHeader*)MallocTracker::get_base(p, tracking_level); - char msg[256]; - address p_corrupted; - if (SafeFetchN((intptr_t*)mhdr, 0) != 0 && mhdr->check_block_integrity(msg, sizeof(msg), &p_corrupted)) { - tty->print_cr(PTR_FORMAT " malloc'd " SIZE_FORMAT " bytes by %s", - p2i(p), mhdr->size(), NMTUtil::flag_to_name(mhdr->flags())); - if (tracking_level == NMT_detail) { - NativeCallStack ncs; - if (mhdr->get_stack(ncs)) { - ncs.print_on(tty); - tty->cr(); - } - } - return; - } + // Does it look like the start of a malloced block? + if (MallocTracker::print_pointer_information(p, tty)) { + return; } } - tty->print(PTR_FORMAT, p2i(p)); + tty->print_cr(PTR_FORMAT, p2i(p)); } } -- GitLab From 1f926609372c9b80dde831a014310a3729768c92 Mon Sep 17 00:00:00 2001 From: Pavel Rappo Date: Thu, 3 Feb 2022 14:55:08 +0000 Subject: [PATCH 391/564] 8281057: Fix doc references to overriding in JLS Reviewed-by: darcy, iris, dholmes, cjplummer --- src/hotspot/share/oops/klassVtable.cpp | 4 ++-- .../share/classes/com/sun/tools/javac/code/Symbol.java | 10 +++++----- .../share/classes/com/sun/tools/javac/comp/Attr.java | 4 ++-- .../share/classes/com/sun/tools/javac/comp/Check.java | 8 ++++---- .../share/classes/com/sun/jdi/ReferenceType.java | 10 +++++----- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/hotspot/share/oops/klassVtable.cpp b/src/hotspot/share/oops/klassVtable.cpp index b107f5d70b2..f96db693de3 100644 --- a/src/hotspot/share/oops/klassVtable.cpp +++ b/src/hotspot/share/oops/klassVtable.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -274,7 +274,7 @@ void klassVtable::initialize_vtable(GrowableArray* supers) { } // Returns true iff super_method can be overridden by a method in targetclassname -// See JLS 3rd edition 8.4.6.1 +// See JLS 8.4.8.1 // Assumes name-signature match // Note that the InstanceKlass of the method in the targetclassname has not always been created yet static bool can_be_overridden(Method* super_method, Handle targetclassloader, Symbol* targetclassname) { diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java index f72a943a2a2..558d2b3107c 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2022, 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 @@ -667,7 +667,7 @@ public abstract class Symbol extends AnnoConstruct implements PoolConstant, Elem * It is assumed that both symbols have the same name. The static * modifier is ignored for this test. * - * See JLS 8.4.6.1 (without transitivity) and 8.4.6.4 + * See JLS 8.4.8.1 (without transitivity) and 8.4.8.4 */ public boolean overrides(Symbol _other, TypeSymbol origin, Types types, boolean checkResult) { return false; @@ -2060,7 +2060,7 @@ public abstract class Symbol extends AnnoConstruct implements PoolConstant, Elem * origin) don't get rejected as summarily and are put to test against the * suitable criteria. * - * See JLS 8.4.6.1 (without transitivity) and 8.4.6.4 + * See JLS 8.4.8.1 (without transitivity) and 8.4.8.4 */ public boolean overrides(Symbol _other, TypeSymbol origin, Types types, boolean checkResult) { return overrides(_other, origin, types, checkResult, true); @@ -2077,7 +2077,7 @@ public abstract class Symbol extends AnnoConstruct implements PoolConstant, Elem * It is assumed that both symbols have the same name. The static * modifier is ignored for this test. * - * See JLS 8.4.6.1 (without transitivity) and 8.4.6.4 + * See JLS 8.4.8.1 (without transitivity) and 8.4.8.4 */ public boolean overrides(Symbol _other, TypeSymbol origin, Types types, boolean checkResult, boolean requireConcreteIfInherited) { @@ -2115,7 +2115,7 @@ public abstract class Symbol extends AnnoConstruct implements PoolConstant, Elem } private boolean isOverridableIn(TypeSymbol origin) { - // JLS 8.4.6.1 + // JLS 8.4.8.1 switch ((int)(flags_field & Flags.AccessFlags)) { case Flags.PRIVATE: return false; diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java index 230539f6e0e..b7fd5a76c09 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2022, 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 @@ -5470,7 +5470,7 @@ public class Attr extends JCTree.Visitor { } else { // Check that all extended classes and interfaces // are compatible (i.e. no two define methods with same arguments - // yet different return types). (JLS 8.4.6.3) + // yet different return types). (JLS 8.4.8.3) chk.checkCompatibleSupertypes(tree.pos(), c.type); if (allowDefaultMethods) { chk.checkDefaultMethodClashes(tree.pos(), c.type); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java index 55f71a2b871..96d91f22c21 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2022, 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 @@ -1790,7 +1790,7 @@ public class Check { return; } - // Error if static method overrides instance method (JLS 8.4.6.2). + // Error if static method overrides instance method (JLS 8.4.8.2). if ((m.flags() & STATIC) != 0 && (other.flags() & STATIC) == 0) { log.error(TreeInfo.diagnosticPositionFor(m, tree), @@ -1800,7 +1800,7 @@ public class Check { } // Error if instance method overrides static or final - // method (JLS 8.4.6.1). + // method (JLS 8.4.8.1). if ((other.flags() & FINAL) != 0 || (m.flags() & STATIC) == 0 && (other.flags() & STATIC) != 0) { @@ -1816,7 +1816,7 @@ public class Check { return; } - // Error if overriding method has weaker access (JLS 8.4.6.3). + // Error if overriding method has weaker access (JLS 8.4.8.3). if (protection(m.flags()) > protection(other.flags())) { log.error(TreeInfo.diagnosticPositionFor(m, tree), (other.flags() & AccessFlags) == 0 ? diff --git a/src/jdk.jdi/share/classes/com/sun/jdi/ReferenceType.java b/src/jdk.jdi/share/classes/com/sun/jdi/ReferenceType.java index 2e84651fbd0..043acc839f7 100644 --- a/src/jdk.jdi/share/classes/com/sun/jdi/ReferenceType.java +++ b/src/jdk.jdi/share/classes/com/sun/jdi/ReferenceType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2022, 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 @@ -413,13 +413,13 @@ public interface ReferenceType /** * Returns a list containing each {@link Method} * declared or inherited by this type. Methods from superclasses - * or superinterfaces that that have been hidden or overridden + * or superinterfaces that have been hidden or overridden * are not included. *

    * Note that despite this exclusion, multiple inherited methods * with the same signature can be present in the returned list, but * at most one can be a member of a {@link ClassType}. - * See JLS section 8.4.6 for details. + * See JLS section 8.4.8 for details. *

    * For arrays ({@link ArrayType}) and primitive classes, the returned * list is always empty. @@ -454,7 +454,7 @@ public interface ReferenceType * find overloaded methods. *

    * Overridden and hidden methods are not included. - * See JLS (8.4.6) for details. + * See JLS (8.4.8) for details. *

    * For arrays ({@link ArrayType}) and primitive classes, the returned * list is always empty. @@ -478,7 +478,7 @@ public interface ReferenceType *

  • (IIII)Z * * This method follows the inheritance rules specified - * in the JLS (8.4.6) to determine visibility. + * in the JLS (8.4.8) to determine visibility. *

    * At most one method in the list is a concrete method and a * component of {@link ClassType}; any other methods in the list -- GitLab From 86c24b319ed5e2f0097cfb4b1afe2eb358eb5f75 Mon Sep 17 00:00:00 2001 From: Alex Menkov Date: Thu, 3 Feb 2022 15:51:16 +0000 Subject: [PATCH 392/564] 8240908: RetransformClass does not know about MethodParameters attribute Reviewed-by: cjplummer, sspitsyn --- .../prims/jvmtiClassFileReconstituter.cpp | 33 ++- .../prims/jvmtiClassFileReconstituter.hpp | 3 +- .../share/prims/jvmtiRedefineClasses.cpp | 30 +-- .../RetransformWithMethodParametersTest.java | 255 ++++++++++++++++++ .../jdk/test/lib/util/ClassTransformer.java | 163 +++++++++++ 5 files changed, 466 insertions(+), 18 deletions(-) create mode 100644 test/jdk/java/lang/instrument/RetransformWithMethodParametersTest.java create mode 100644 test/lib/jdk/test/lib/util/ClassTransformer.java diff --git a/src/hotspot/share/prims/jvmtiClassFileReconstituter.cpp b/src/hotspot/share/prims/jvmtiClassFileReconstituter.cpp index f530ae37caf..4fb97970036 100644 --- a/src/hotspot/share/prims/jvmtiClassFileReconstituter.cpp +++ b/src/hotspot/share/prims/jvmtiClassFileReconstituter.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2022, 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 @@ -287,6 +287,31 @@ void JvmtiClassFileReconstituter::write_exceptions_attribute(ConstMethod* const_ } } +// Write MethodParameters attribute +// JVMSpec| MethodParameters_attribute { +// JVMSpec| u2 attribute_name_index; +// JVMSpec| u4 attribute_length; +// JVMSpec| u1 parameters_count; +// JVMSpec| { u2 name_index; +// JVMSpec| u2 access_flags; +// JVMSpec| } parameters[parameters_count]; +// JVMSpec| } +void JvmtiClassFileReconstituter::write_method_parameter_attribute(const ConstMethod* const_method) { + const MethodParametersElement *parameters = const_method->method_parameters_start(); + int length = const_method->method_parameters_length(); + assert(length <= max_jubyte, "must fit u1"); + int size = 1 // parameters_count + + (2 + 2) * length; // parameters + + write_attribute_name_index("MethodParameters"); + write_u4(size); + write_u1(length); + for (int index = 0; index < length; index++) { + write_u2(parameters[index].name_cp_index); + write_u2(parameters[index].flags); + } +} + // Write SourceFile attribute // JVMSpec| SourceFile_attribute { // JVMSpec| u2 attribute_name_index; @@ -689,6 +714,9 @@ void JvmtiClassFileReconstituter::write_method_info(const methodHandle& method) if (default_anno != NULL) { ++attr_count; // has AnnotationDefault attribute } + if (const_method->has_method_parameters()) { + ++attr_count; // has MethodParameters attribute + } // Deprecated attribute would go here if (access_flags.is_synthetic()) { // FIXME // ++attr_count; @@ -716,6 +744,9 @@ void JvmtiClassFileReconstituter::write_method_info(const methodHandle& method) if (default_anno != NULL) { write_annotations_attribute("AnnotationDefault", default_anno); } + if (const_method->has_method_parameters()) { + write_method_parameter_attribute(const_method); + } // Deprecated attribute would go here if (access_flags.is_synthetic()) { // write_synthetic_attribute(); diff --git a/src/hotspot/share/prims/jvmtiClassFileReconstituter.hpp b/src/hotspot/share/prims/jvmtiClassFileReconstituter.hpp index 86d15b4c34a..3948e7af9b3 100644 --- a/src/hotspot/share/prims/jvmtiClassFileReconstituter.hpp +++ b/src/hotspot/share/prims/jvmtiClassFileReconstituter.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2022, 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,6 +101,7 @@ class JvmtiClassFileReconstituter : public JvmtiConstantPoolReconstituter { void write_method_info(const methodHandle& method); void write_code_attribute(const methodHandle& method); void write_exceptions_attribute(ConstMethod* const_method); + void write_method_parameter_attribute(const ConstMethod* const_method); void write_synthetic_attribute(); void write_class_attributes(); void write_source_file_attribute(); diff --git a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp index 89e41730ed9..586c0679177 100644 --- a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp +++ b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, 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 @@ -2266,21 +2266,6 @@ void VM_RedefineClasses::rewrite_cp_refs_in_method(methodHandle method, break; } } // end for each bytecode - - // We also need to rewrite the parameter name indexes, if there is - // method parameter data present - if(method->has_method_parameters()) { - const int len = method->method_parameters_length(); - MethodParametersElement* elem = method->method_parameters_start(); - - for (int i = 0; i < len; i++) { - const u2 cp_index = elem[i].name_cp_index; - const u2 new_cp_index = find_new_index(cp_index); - if (new_cp_index != 0) { - elem[i].name_cp_index = new_cp_index; - } - } - } } // end rewrite_cp_refs_in_method() @@ -3694,6 +3679,19 @@ void VM_RedefineClasses::set_new_constant_pool( } // end for each local variable table entry } // end if there are local variable table entries + // Update constant pool indices in the method's method_parameters. + int mp_length = method->method_parameters_length(); + if (mp_length > 0) { + MethodParametersElement* elem = method->method_parameters_start(); + for (int j = 0; j < mp_length; j++) { + const int cp_index = elem[j].name_cp_index; + const int new_cp_index = find_new_index(cp_index); + if (new_cp_index != 0) { + elem[j].name_cp_index = (u2)new_cp_index; + } + } + } + rewrite_cp_refs_in_stack_map_table(method); } // end for each method } // end set_new_constant_pool() diff --git a/test/jdk/java/lang/instrument/RetransformWithMethodParametersTest.java b/test/jdk/java/lang/instrument/RetransformWithMethodParametersTest.java new file mode 100644 index 00000000000..ef7e3818eb0 --- /dev/null +++ b/test/jdk/java/lang/instrument/RetransformWithMethodParametersTest.java @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2022, 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 8240908 + * + * @library /test/lib + * @run compile -g -parameters RetransformWithMethodParametersTest.java + * @run shell MakeJAR.sh retransformAgent + * + * @run main/othervm -javaagent:retransformAgent.jar RetransformWithMethodParametersTest + */ + +import java.io.File; +import java.io.FileOutputStream; +import java.lang.instrument.ClassFileTransformer; +import java.lang.reflect.Method; +import java.lang.reflect.Parameter; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.security.ProtectionDomain; +import java.util.Arrays; + +import jdk.test.lib.JDKToolLauncher; +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.util.ClassTransformer; + +/* + * The test verifies Instrumentation.retransformClasses() (and JVMTI function RetransformClasses) + * correctly handles MethodParameter attribute: + * 1) classfile bytes passed to transformers (and JVMTI ClassFileLoadHook event callback) contain the attribute; + * 2) the attribute is updated if new version has the attribute with different values; + * 3) the attribute is removed if new version doesn't contain the attribute. + */ + +// See ClassTransformer.transform(int) comment for @1 tag explanations. +class MethodParametersTarget { + // The class contains the only method, so we don't have issue with method sorting + // and ClassFileReconstituter should restore the same bytes as original classbytes. + public void method1( + int intParam1, String stringParam1 // @1 commentout + // @1 uncomment int intParam2, String stringParam2 + ) + { + // @1 uncomment System.out.println(stringParam2); // change CP + } +} + +public class RetransformWithMethodParametersTest extends ATransformerManagementTestCase { + + public static void main (String[] args) throws Throwable { + ATestCaseScaffold test = new RetransformWithMethodParametersTest(); + test.runTest(); + } + + private String targetClassName = "MethodParametersTarget"; + private String classFileName = targetClassName + ".class"; + private String sourceFileName = "RetransformWithMethodParametersTest.java"; + private Class targetClass; + private byte[] originalClassBytes; + + private byte[] seenClassBytes; + private byte[] newClassBytes; + + public RetransformWithMethodParametersTest() throws Throwable { + super("RetransformWithMethodParametersTest"); + + File origClassFile = new File(System.getProperty("test.classes", "."), classFileName); + log("Reading test class from " + origClassFile); + originalClassBytes = Files.readAllBytes(origClassFile.toPath()); + log("Read " + originalClassBytes.length + " bytes."); + } + + private void log(Object o) { + System.out.println(String.valueOf(o)); + } + + private Parameter[] getTargetMethodParameters() throws ClassNotFoundException { + Class cls = Class.forName(targetClassName); + // the class contains 1 method (method1) + Method method = cls.getDeclaredMethods()[0]; + Parameter[] params = method.getParameters(); + log("Params of " + method.getName() + " method (" + params.length + "):"); + for (int i = 0; i < params.length; i++) { + log(" " + i + ": " + params[i].getName() + + " (" + (params[i].isNamePresent() ? "present" : "absent") + ")"); + } + return params; + } + + // Verifies MethodParameters attribute is present and contains the expected values. + private void verifyPresentMethodParams(String... expectedNames) throws Throwable { + Parameter[] params = getTargetMethodParameters(); + assertEquals(expectedNames.length, params.length); + for (int i = 0; i < params.length; i++) { + assertTrue(params[i].isNamePresent()); + assertEquals(expectedNames[i], params[i].getName()); + } + } + + // Verifies MethodParameters attribute is absent. + private void verifyAbsentMethodParams() throws Throwable { + Parameter[] params = getTargetMethodParameters(); + for (int i = 0; i < params.length; i++) { + assertTrue(!params[i].isNamePresent()); + } + } + + // Retransforms target class using provided class bytes; + // Returns class bytes passed to the transformer. + private byte[] retransform(byte[] classBytes) throws Throwable { + seenClassBytes = null; + newClassBytes = classBytes; + fInst.retransformClasses(targetClass); + assertTrue(targetClassName + " was not seen by transform()", seenClassBytes != null); + return seenClassBytes; + } + + // Prints dissassembled class bytes. + private void printDisassembled(String description, byte[] bytes) throws Exception { + log(description + " -------------------"); + + File f = new File(classFileName); + try (FileOutputStream fos = new FileOutputStream(f)) { + fos.write(bytes); + } + JDKToolLauncher javap = JDKToolLauncher.create("javap") + .addToolArg("-verbose") + .addToolArg("-p") // Shows all classes and members. + //.addToolArg("-c") // Prints out disassembled code + //.addToolArg("-s") // Prints internal type signatures. + .addToolArg(f.toString()); + ProcessBuilder pb = new ProcessBuilder(javap.getCommand()); + OutputAnalyzer out = ProcessTools.executeProcess(pb); + out.shouldHaveExitValue(0); + try { + Files.delete(f.toPath()); + } catch (Exception ex) { + // ignore + } + out.asLines().forEach(s -> log(s)); + log("=========================================="); + } + + // Verifies class bytes are equal. + private void compareClassBytes(byte[] expected, byte[] actual) throws Exception { + + int pos = Arrays.mismatch(expected, actual); + if (pos < 0) { + log("Class bytes are identical."); + return; + } + log("Class bytes are different."); + printDisassembled("expected", expected); + printDisassembled("expected", actual); + fail(targetClassName + " did not match .class file"); + } + + protected final void doRunTest() throws Throwable { + beVerbose(); + + ClassLoader loader = getClass().getClassLoader(); + targetClass = loader.loadClass(targetClassName); + // sanity check + assertEquals(targetClassName, targetClass.getName()); + // sanity check + verifyPresentMethodParams("intParam1", "stringParam1"); + + addTransformerToManager(fInst, new Transformer(), true); + + { + log("Testcase 1: ensure ClassFileReconstituter restores MethodParameters attribute"); + + byte[] classBytes = retransform(null); + compareClassBytes(originalClassBytes, classBytes); + + log(""); + } + + { + log("Testcase 2: redefine class with changed parameter names"); + + byte[] classBytes = Files.readAllBytes(Paths.get( + ClassTransformer.fromTestSource(sourceFileName) + .transform(1, targetClassName, "-g", "-parameters"))); + retransform(classBytes); + // MethodParameters attribute should be updated. + verifyPresentMethodParams("intParam2", "stringParam2"); + + log(""); + } + + { + log("Testcase 3: redefine class with no parameter names"); + // compile without "-parameters" + byte[] classBytes = Files.readAllBytes(Paths.get( + ClassTransformer.fromTestSource(sourceFileName) + .transform(1, targetClassName, "-g"))); + retransform(classBytes); + // MethodParameters attribute should be dropped. + verifyAbsentMethodParams(); + + log(""); + } + } + + + public class Transformer implements ClassFileTransformer { + public Transformer() { + } + + public String toString() { + return Transformer.this.getClass().getName(); + } + + public byte[] transform(ClassLoader loader, String className, + Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) { + + if (className.equals(targetClassName)) { + log(this + ".transform() sees '" + className + + "' of " + classfileBuffer.length + " bytes."); + seenClassBytes = classfileBuffer; + if (newClassBytes != null) { + log(this + ".transform() sets new classbytes for '" + className + + "' of " + newClassBytes.length + " bytes."); + } + return newClassBytes; + } + + return null; + } + } +} diff --git a/test/lib/jdk/test/lib/util/ClassTransformer.java b/test/lib/jdk/test/lib/util/ClassTransformer.java new file mode 100644 index 00000000000..7ace81df87b --- /dev/null +++ b/test/lib/jdk/test/lib/util/ClassTransformer.java @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.util; + +import jdk.test.lib.compiler.CompilerUtils; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.text.MessageFormat; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +// ClassTransformer provides functionality to transform java source and compile it. +// We cannot use InMemoryJavaCompiler as test files usually contain 2 classes (the test itself and debuggee) +// and InMemoryJavaCompiler cannot compile them. +public class ClassTransformer { + + private final List lines; + private String fileName; + private String workDir = "ver{0}"; + private static final String LINE_SEPARATOR = System.getProperty("line.separator"); + + private ClassTransformer(List lines) { + this.lines = lines; + } + + public ClassTransformer setFileName(String fileName) { + this.fileName = fileName; + return this; + } + + // workDir is a MessageFormat pattern, id (int) is an {0} arg of the pattern. + // can be relative (relatively "scratch" dir) or absolute. + public ClassTransformer setWorkDir(String dir) { + workDir = dir; + return this; + } + + public static ClassTransformer fromString(String content) { + return new ClassTransformer(Arrays.asList(content.split("\\R"))); + } + + public static ClassTransformer fromFile(Path filePath) { + try { + return new ClassTransformer(Files.readAllLines(filePath)) + .setFileName(filePath.getFileName().toString()); + } catch (IOException e) { + throw new RuntimeException("failed to read " + filePath, e); + } + } + public static ClassTransformer fromFile(String filePath) { + return fromFile(Paths.get(filePath)); + } + + public static ClassTransformer fromTestSource(String fileName) { + return fromFile(Paths.get(System.getProperty("test.src")).resolve(fileName)); + } + + // returns path to the .class file of the transformed class + public String transform(int id, String className, String... compilerOptions) { + Path subdir = Paths.get(".").resolve(MessageFormat.format(workDir, id)); + Path transformedSrc = subdir.resolve(fileName); + try { + Files.createDirectories(subdir); + Files.write(transformedSrc, transform(id).getBytes()); + } catch (IOException e) { + throw new RuntimeException("failed to write transformed " + transformedSrc, e); + } + try { + // need to add extra classpath args + List args = new LinkedList<>(Arrays.asList(compilerOptions)); + args.add("-cp"); + args.add(System.getProperty("java.class.path")); + CompilerUtils.compile(subdir, subdir, false, args.toArray(new String[args.size()])); + } catch (IOException e) { + throw new RuntimeException("failed to compile " + transformedSrc, e); + } + return subdir.resolve(className + ".class").toString(); + } + + /* + * To do RedefineClasses operations, embed @1 tags in the .java + * file to tell this script how to modify it to produce the 2nd + * version of the .class file to be used in the redefine operation. + * Here are examples of each editing tag and what change + * it causes in the new file. Note that blanks are not preserved + * in these editing operations. + * + * @1 uncomment + * orig: // @1 uncomment gus = 89; + * new: gus = 89; + * + * @1 commentout + * orig: gus = 89 // @1 commentout + * new: // gus = 89 // @1 commentout + * + * @1 delete + * orig: gus = 89 // @1 delete + * new: entire line deleted + * + * @1 newline + * orig: gus = 89; // @1 newline gus++; + * new: gus = 89; // + * gus++; + * + * @1 replace + * orig: gus = 89; // @1 replace gus = 90; + * new: gus = 90; + */ + public String transform(int id) { + Pattern delete = Pattern.compile("@" + id + " *delete"); + Pattern uncomment = Pattern.compile("// *@" + id + " *uncomment (.*)"); + Pattern commentout = Pattern.compile(".* @" + id + " *commentout"); + Pattern newline = Pattern.compile("(.*) @" + id + " *newline (.*)"); + Pattern replace = Pattern.compile("@" + id + " *replace (.*)"); + return lines.stream() + .filter(s -> !delete.matcher(s).find()) // @1 delete + .map(s -> { + Matcher m = uncomment.matcher(s); // @1 uncomment + return m.find() ? m.group(1) : s; + }) + .map(s-> { + Matcher m = commentout.matcher(s); // @1 commentout + return m.find() ? "//" + s : s; + }) + .map(s -> { + Matcher m = newline.matcher(s); // @1 newline + return m.find() ? m.group(1) + LINE_SEPARATOR + m.group(2) : s; + }) + .map(s -> { + Matcher m = replace.matcher(s); // @1 replace + return m.find() ? m.group(1) : s; + }) + .collect(Collectors.joining(LINE_SEPARATOR)); + } + +} -- GitLab From cda9c3011beeec8df68e78e096132e712255ce1b Mon Sep 17 00:00:00 2001 From: Yumin Qi Date: Thu, 3 Feb 2022 18:02:40 +0000 Subject: [PATCH 393/564] 8278753: Runtime crashes with access violation during JNI_CreateJavaVM call Reviewed-by: dholmes, stuefe --- make/data/hotspot-symbols/symbols-unix | 3 ++- src/hotspot/share/classfile/classLoader.cpp | 20 ++++++++-------- src/hotspot/share/classfile/classLoader.hpp | 8 +++++-- src/hotspot/share/include/jvm.h | 5 +++- src/hotspot/share/prims/jvm.cpp | 7 +++++- .../native/libjimage/imageDecompressor.cpp | 23 ++++++------------- 6 files changed, 35 insertions(+), 31 deletions(-) diff --git a/make/data/hotspot-symbols/symbols-unix b/make/data/hotspot-symbols/symbols-unix index 9ec0c1ec7c7..d51fcb3727d 100644 --- a/make/data/hotspot-symbols/symbols-unix +++ b/make/data/hotspot-symbols/symbols-unix @@ -1,5 +1,5 @@ # -# Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2016, 2022, 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 @@ -158,6 +158,7 @@ JVM_IsSupportedJNIVersion JVM_IsThreadAlive JVM_IsVMGeneratedMethodIx JVM_LatestUserDefinedLoader +JVM_LoadZipLibrary JVM_LoadLibrary JVM_LookupDefineClass JVM_LookupLambdaProxyClassFromArchive diff --git a/src/hotspot/share/classfile/classLoader.cpp b/src/hotspot/share/classfile/classLoader.cpp index 7fb8f71cbc8..bf450cbf407 100644 --- a/src/hotspot/share/classfile/classLoader.cpp +++ b/src/hotspot/share/classfile/classLoader.cpp @@ -99,7 +99,8 @@ static FindEntry_t FindEntry = NULL; static ReadEntry_t ReadEntry = NULL; static GetNextEntry_t GetNextEntry = NULL; static Crc32_t Crc32 = NULL; -int ClassLoader::_libzip_loaded = 0; +int ClassLoader::_libzip_loaded = 0; +void* ClassLoader::_zip_handle = NULL; // Entry points for jimage.dll for loading jimage file entries @@ -942,20 +943,19 @@ void ClassLoader::load_zip_library() { assert(ZipOpen == NULL, "should not load zip library twice"); char path[JVM_MAXPATHLEN]; char ebuf[1024]; - void* handle = NULL; if (os::dll_locate_lib(path, sizeof(path), Arguments::get_dll_dir(), "zip")) { - handle = os::dll_load(path, ebuf, sizeof ebuf); + _zip_handle = os::dll_load(path, ebuf, sizeof ebuf); } - if (handle == NULL) { + if (_zip_handle == NULL) { vm_exit_during_initialization("Unable to load zip library", path); } - ZipOpen = CAST_TO_FN_PTR(ZipOpen_t, dll_lookup(handle, "ZIP_Open", path)); - ZipClose = CAST_TO_FN_PTR(ZipClose_t, dll_lookup(handle, "ZIP_Close", path)); - FindEntry = CAST_TO_FN_PTR(FindEntry_t, dll_lookup(handle, "ZIP_FindEntry", path)); - ReadEntry = CAST_TO_FN_PTR(ReadEntry_t, dll_lookup(handle, "ZIP_ReadEntry", path)); - GetNextEntry = CAST_TO_FN_PTR(GetNextEntry_t, dll_lookup(handle, "ZIP_GetNextEntry", path)); - Crc32 = CAST_TO_FN_PTR(Crc32_t, dll_lookup(handle, "ZIP_CRC32", path)); + ZipOpen = CAST_TO_FN_PTR(ZipOpen_t, dll_lookup(_zip_handle, "ZIP_Open", path)); + ZipClose = CAST_TO_FN_PTR(ZipClose_t, dll_lookup(_zip_handle, "ZIP_Close", path)); + FindEntry = CAST_TO_FN_PTR(FindEntry_t, dll_lookup(_zip_handle, "ZIP_FindEntry", path)); + ReadEntry = CAST_TO_FN_PTR(ReadEntry_t, dll_lookup(_zip_handle, "ZIP_ReadEntry", path)); + GetNextEntry = CAST_TO_FN_PTR(GetNextEntry_t, dll_lookup(_zip_handle, "ZIP_GetNextEntry", path)); + Crc32 = CAST_TO_FN_PTR(Crc32_t, dll_lookup(_zip_handle, "ZIP_CRC32", path)); } void ClassLoader::load_jimage_library() { diff --git a/src/hotspot/share/classfile/classLoader.hpp b/src/hotspot/share/classfile/classLoader.hpp index c454a503a2e..d2f2c6ccef1 100644 --- a/src/hotspot/share/classfile/classLoader.hpp +++ b/src/hotspot/share/classfile/classLoader.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -229,6 +229,9 @@ class ClassLoader: AllStatic { bool check_for_duplicates); CDS_ONLY(static void add_to_module_path_entries(const char* path, ClassPathEntry* entry);) + + // cache the zip library handle + static void* _zip_handle; public: CDS_ONLY(static ClassPathEntry* app_classpath_entries() {return _app_classpath_entries;}) CDS_ONLY(static ClassPathEntry* module_path_entries() {return _module_path_entries;}) @@ -253,9 +256,10 @@ class ClassLoader: AllStatic { private: static int _libzip_loaded; // used to sync loading zip. static void release_load_zip_library(); - static inline void load_zip_library_if_needed(); public: + static inline void load_zip_library_if_needed(); + static void* zip_library_handle() { return _zip_handle; } static jzfile* open_zip_file(const char* canonical_path, char** error_msg, JavaThread* thread); static ClassPathEntry* create_class_path_entry(JavaThread* current, const char *path, const struct stat* st, diff --git a/src/hotspot/share/include/jvm.h b/src/hotspot/share/include/jvm.h index e4f56c552b7..dfdd2219869 100644 --- a/src/hotspot/share/include/jvm.h +++ b/src/hotspot/share/include/jvm.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -150,6 +150,9 @@ JVM_ActiveProcessorCount(void); JNIEXPORT jboolean JNICALL JVM_IsUseContainerSupport(void); +JNIEXPORT void * JNICALL +JVM_LoadZipLibrary(); + JNIEXPORT void * JNICALL JVM_LoadLibrary(const char *name, jboolean throwException); diff --git a/src/hotspot/share/prims/jvm.cpp b/src/hotspot/share/prims/jvm.cpp index 776e1d10011..4f54235cd4d 100644 --- a/src/hotspot/share/prims/jvm.cpp +++ b/src/hotspot/share/prims/jvm.cpp @@ -30,7 +30,7 @@ #include "cds/heapShared.hpp" #include "cds/lambdaFormInvokers.hpp" #include "classfile/classFileStream.hpp" -#include "classfile/classLoader.hpp" +#include "classfile/classLoader.inline.hpp" #include "classfile/classLoaderData.hpp" #include "classfile/classLoaderData.inline.hpp" #include "classfile/classLoadInfo.hpp" @@ -3373,6 +3373,11 @@ JVM_END // Library support /////////////////////////////////////////////////////////////////////////// +JVM_LEAF(void*, JVM_LoadZipLibrary()) + ClassLoader::load_zip_library_if_needed(); + return ClassLoader::zip_library_handle(); +JVM_END + JVM_ENTRY_NO_ENV(void*, JVM_LoadLibrary(const char* name, jboolean throwException)) //%note jvm_ct char ebuf[1024]; diff --git a/src/java.base/share/native/libjimage/imageDecompressor.cpp b/src/java.base/share/native/libjimage/imageDecompressor.cpp index 5deebe350f7..65bda0957b8 100644 --- a/src/java.base/share/native/libjimage/imageDecompressor.cpp +++ b/src/java.base/share/native/libjimage/imageDecompressor.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,6 +30,7 @@ */ #include "jni.h" +#include "jvm.h" #include "imageDecompressor.hpp" #include "endian.hpp" #ifdef WIN32 @@ -57,24 +58,14 @@ static ZipInflateFully_t ZipInflateFully = NULL; * @return the address of the entry point or NULL */ static void* findEntry(const char* name) { - void *addr = NULL; -#ifdef WIN32 - HMODULE handle = GetModuleHandle("zip.dll"); - if (handle == NULL) { - handle = LoadLibrary("zip.dll"); - } - if (handle == NULL) { - return NULL; - } - addr = (void*) GetProcAddress(handle, name); - return addr; -#else - addr = dlopen(JNI_LIB_PREFIX "zip" JNI_LIB_SUFFIX, RTLD_GLOBAL|RTLD_LAZY); + void *addr = JVM_LoadZipLibrary(); if (addr == NULL) { return NULL; } - addr = dlsym(addr, name); - return addr; +#ifdef WIN32 + return (void*) GetProcAddress(static_cast(addr), name); +#else + return dlsym(addr, name); #endif } -- GitLab From 130cf46dcb7b089fcf4a4e950cdc701513f7b53f Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Thu, 3 Feb 2022 19:12:27 +0000 Subject: [PATCH 394/564] 4750574: (se spec) Selector spec should clarify calculation of select return value Reviewed-by: alanb --- .../share/classes/java/nio/channels/Selector.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/java.base/share/classes/java/nio/channels/Selector.java b/src/java.base/share/classes/java/nio/channels/Selector.java index 4fb98f3a8ce..d8c0dc261bd 100644 --- a/src/java.base/share/classes/java/nio/channels/Selector.java +++ b/src/java.base/share/classes/java/nio/channels/Selector.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2022, 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 @@ -355,7 +355,8 @@ public abstract class Selector implements Closeable { * of the {@link #wakeup wakeup} method.

    * * @return The number of keys, possibly zero, whose ready-operation sets - * were updated by the selection operation + * now indicate readiness for at least one category of operations + * for which the channel was not previously detected to be ready * * @throws IOException * If an I/O error occurs @@ -383,8 +384,9 @@ public abstract class Selector implements Closeable { * channel to become ready; if zero, block indefinitely; * must not be negative * - * @return The number of keys, possibly zero, - * whose ready-operation sets were updated + * @return The number of keys, possibly zero, whose ready-operation sets + * now indicate readiness for at least one category of operations + * for which the channel was not previously detected to be ready * * @throws IOException * If an I/O error occurs @@ -406,8 +408,9 @@ public abstract class Selector implements Closeable { * this selector's {@link #wakeup wakeup} method is invoked, or the current * thread is interrupted, whichever comes first.

    * - * @return The number of keys, possibly zero, - * whose ready-operation sets were updated + * @return The number of keys, possibly zero, whose ready-operation sets + * now indicate readiness for at least one category of operations + * for which the channel was not previously detected to be ready * * @throws IOException * If an I/O error occurs -- GitLab From b6935dfb86a1c011355d2dfb2140be26ec536351 Mon Sep 17 00:00:00 2001 From: Yi-Fan Tsai Date: Thu, 3 Feb 2022 19:34:28 +0000 Subject: [PATCH 395/564] 8251505: Use of types in compiler shared code should be consistent. Reviewed-by: phh --- src/hotspot/share/code/nmethod.hpp | 6 ++--- src/hotspot/share/compiler/compileBroker.cpp | 2 +- src/hotspot/share/compiler/compileBroker.hpp | 6 ++--- src/hotspot/share/jvmci/jvmciEnv.cpp | 2 +- src/hotspot/share/jvmci/jvmciEnv.hpp | 2 +- .../share/runtime/interfaceSupport.cpp | 2 +- .../share/runtime/interfaceSupport.inline.hpp | 2 +- src/hotspot/share/runtime/sweeper.cpp | 27 ++++++++++--------- src/hotspot/share/runtime/sweeper.hpp | 12 ++++----- src/hotspot/share/runtime/vmStructs.cpp | 3 ++- 10 files changed, 33 insertions(+), 31 deletions(-) diff --git a/src/hotspot/share/code/nmethod.hpp b/src/hotspot/share/code/nmethod.hpp index d0154bc85a3..d31e62f404a 100644 --- a/src/hotspot/share/code/nmethod.hpp +++ b/src/hotspot/share/code/nmethod.hpp @@ -256,7 +256,7 @@ class nmethod : public CompiledMethod { // stack. An not_entrant method can be removed when there are no // more activations, i.e., when the _stack_traversal_mark is less than // current sweep traversal index. - volatile long _stack_traversal_mark; + volatile int64_t _stack_traversal_mark; // The _hotness_counter indicates the hotness of a method. The higher // the value the hotter the method. The hotness counter of a nmethod is @@ -538,8 +538,8 @@ public: void fix_oop_relocations() { fix_oop_relocations(NULL, NULL, false); } // Sweeper support - long stack_traversal_mark() { return _stack_traversal_mark; } - void set_stack_traversal_mark(long l) { _stack_traversal_mark = l; } + int64_t stack_traversal_mark() { return _stack_traversal_mark; } + void set_stack_traversal_mark(int64_t l) { _stack_traversal_mark = l; } // On-stack replacement support int osr_entry_bci() const { assert(is_osr_method(), "wrong kind of nmethod"); return _entry_bci; } diff --git a/src/hotspot/share/compiler/compileBroker.cpp b/src/hotspot/share/compiler/compileBroker.cpp index 1e2b5e395ba..4ae7bc21ce6 100644 --- a/src/hotspot/share/compiler/compileBroker.cpp +++ b/src/hotspot/share/compiler/compileBroker.cpp @@ -186,7 +186,7 @@ int CompileBroker::_sum_standard_bytes_compiled = 0; int CompileBroker::_sum_nmethod_size = 0; int CompileBroker::_sum_nmethod_code_size = 0; -long CompileBroker::_peak_compilation_time = 0; +jlong CompileBroker::_peak_compilation_time = 0; CompilerStatistics CompileBroker::_stats_per_level[CompLevel_full_optimization]; diff --git a/src/hotspot/share/compiler/compileBroker.hpp b/src/hotspot/share/compiler/compileBroker.hpp index 33fde0dace6..be770aac9c2 100644 --- a/src/hotspot/share/compiler/compileBroker.hpp +++ b/src/hotspot/share/compiler/compileBroker.hpp @@ -222,7 +222,7 @@ class CompileBroker: AllStatic { static int _sum_standard_bytes_compiled; static int _sum_nmethod_size; static int _sum_nmethod_code_size; - static long _peak_compilation_time; + static jlong _peak_compilation_time; static CompilerStatistics _stats_per_level[]; @@ -411,8 +411,8 @@ public: static int get_sum_standard_bytes_compiled() { return _sum_standard_bytes_compiled; } static int get_sum_nmethod_size() { return _sum_nmethod_size;} static int get_sum_nmethod_code_size() { return _sum_nmethod_code_size; } - static long get_peak_compilation_time() { return _peak_compilation_time; } - static long get_total_compilation_time() { return _t_total_compilation.milliseconds(); } + static jlong get_peak_compilation_time() { return _peak_compilation_time; } + static jlong get_total_compilation_time() { return _t_total_compilation.milliseconds(); } // Log that compilation profiling is skipped because metaspace is full. static void log_metaspace_failure(); diff --git a/src/hotspot/share/jvmci/jvmciEnv.cpp b/src/hotspot/share/jvmci/jvmciEnv.cpp index aa4989acf28..f789cd6ac0b 100644 --- a/src/hotspot/share/jvmci/jvmciEnv.cpp +++ b/src/hotspot/share/jvmci/jvmciEnv.cpp @@ -553,7 +553,7 @@ void JVMCIEnv::put_int_at(JVMCIPrimitiveArray array, int index, jint value) { } } -long JVMCIEnv::get_long_at(JVMCIPrimitiveArray array, int index) { +jlong JVMCIEnv::get_long_at(JVMCIPrimitiveArray array, int index) { if (is_hotspot()) { return HotSpotJVMCI::resolve(array)->long_at(index); } else { diff --git a/src/hotspot/share/jvmci/jvmciEnv.hpp b/src/hotspot/share/jvmci/jvmciEnv.hpp index 18a80accd8b..61b7cd4e331 100644 --- a/src/hotspot/share/jvmci/jvmciEnv.hpp +++ b/src/hotspot/share/jvmci/jvmciEnv.hpp @@ -251,7 +251,7 @@ public: jint get_int_at(JVMCIPrimitiveArray array, int index); void put_int_at(JVMCIPrimitiveArray array, int index, jint value); - long get_long_at(JVMCIPrimitiveArray array, int index); + jlong get_long_at(JVMCIPrimitiveArray array, int index); void put_long_at(JVMCIPrimitiveArray array, int index, jlong value); void copy_bytes_to(JVMCIPrimitiveArray src, jbyte* dest, int offset, jsize length); diff --git a/src/hotspot/share/runtime/interfaceSupport.cpp b/src/hotspot/share/runtime/interfaceSupport.cpp index 2037b732e50..ffacf150e58 100644 --- a/src/hotspot/share/runtime/interfaceSupport.cpp +++ b/src/hotspot/share/runtime/interfaceSupport.cpp @@ -78,7 +78,7 @@ VMNativeEntryWrapper::~VMNativeEntryWrapper() { unsigned int InterfaceSupport::_scavenge_alot_counter = 1; unsigned int InterfaceSupport::_fullgc_alot_counter = 1; -int InterfaceSupport::_fullgc_alot_invocation = 0; +intx InterfaceSupport::_fullgc_alot_invocation = 0; void InterfaceSupport::gc_alot() { Thread *thread = Thread::current(); diff --git a/src/hotspot/share/runtime/interfaceSupport.inline.hpp b/src/hotspot/share/runtime/interfaceSupport.inline.hpp index 13ecf2d80ce..7cbdb00995c 100644 --- a/src/hotspot/share/runtime/interfaceSupport.inline.hpp +++ b/src/hotspot/share/runtime/interfaceSupport.inline.hpp @@ -54,7 +54,7 @@ class InterfaceSupport: AllStatic { public: static unsigned int _scavenge_alot_counter; static unsigned int _fullgc_alot_counter; - static int _fullgc_alot_invocation; + static intx _fullgc_alot_invocation; // Helper methods used to implement +ScavengeALot and +FullGCALot static void check_gc_alot() { if (ScavengeALot || FullGCALot) gc_alot(); } diff --git a/src/hotspot/share/runtime/sweeper.cpp b/src/hotspot/share/runtime/sweeper.cpp index 31c9220ea78..ec394559247 100644 --- a/src/hotspot/share/runtime/sweeper.cpp +++ b/src/hotspot/share/runtime/sweeper.cpp @@ -55,9 +55,9 @@ // Sweeper logging code class SweeperRecord { public: - int traversal; + int64_t traversal; int compile_id; - long traversal_mark; + int64_t traversal_mark; int state; const char* kind; address vep; @@ -65,8 +65,8 @@ class SweeperRecord { int line; void print() { - tty->print_cr("traversal = %d compile_id = %d %s uep = " PTR_FORMAT " vep = " - PTR_FORMAT " state = %d traversal_mark %ld line = %d", + tty->print_cr("traversal = " INT64_FORMAT " compile_id = %d %s uep = " PTR_FORMAT " vep = " + PTR_FORMAT " state = %d traversal_mark " INT64_FORMAT " line = %d", traversal, compile_id, kind == NULL ? "" : kind, @@ -107,8 +107,8 @@ void NMethodSweeper::init_sweeper_log() { #endif CompiledMethodIterator NMethodSweeper::_current(CompiledMethodIterator::all_blobs); // Current compiled method -long NMethodSweeper::_traversals = 0; // Stack scan count, also sweep ID. -long NMethodSweeper::_total_nof_code_cache_sweeps = 0; // Total number of full sweeps of the code cache +int64_t NMethodSweeper::_traversals = 0; // Stack scan count, also sweep ID. +int64_t NMethodSweeper::_total_nof_code_cache_sweeps = 0; // Total number of full sweeps of the code cache int NMethodSweeper::_seen = 0; // Nof. nmethod we have currently processed in current pass of CodeCache size_t NMethodSweeper::_sweep_threshold_bytes = 0; // Threshold for when to sweep. Updated after ergonomics @@ -119,8 +119,8 @@ volatile size_t NMethodSweeper::_bytes_changed = 0; // Counts the tot // 2) not_entrant -> zombie int NMethodSweeper::_hotness_counter_reset_val = 0; -long NMethodSweeper::_total_nof_methods_reclaimed = 0; // Accumulated nof methods flushed -long NMethodSweeper::_total_nof_c2_methods_reclaimed = 0; // Accumulated nof methods flushed +int64_t NMethodSweeper::_total_nof_methods_reclaimed = 0; // Accumulated nof methods flushed +int64_t NMethodSweeper::_total_nof_c2_methods_reclaimed = 0; // Accumulated nof methods flushed size_t NMethodSweeper::_total_flushed_size = 0; // Total number of bytes flushed from the code cache Tickspan NMethodSweeper::_total_time_sweeping; // Accumulated time sweeping Tickspan NMethodSweeper::_total_time_this_sweep; // Total time this sweep @@ -187,7 +187,7 @@ CodeBlobClosure* NMethodSweeper::prepare_mark_active_nmethods() { _total_time_this_sweep = Tickspan(); if (PrintMethodFlushing) { - tty->print_cr("### Sweep: stack traversal %ld", _traversals); + tty->print_cr("### Sweep: stack traversal " INT64_FORMAT, _traversals); } return &mark_activation_closure; } @@ -217,7 +217,7 @@ void NMethodSweeper::sweeper_loop() { { ThreadBlockInVM tbivm(JavaThread::current()); MonitorLocker waiter(CodeSweeper_lock, Mutex::_no_safepoint_check_flag); - const long wait_time = 60*60*24 * 1000; + const int64_t wait_time = 60*60*24 * 1000; timeout = waiter.wait(wait_time); } if (!timeout && (_should_sweep || _force_sweep)) { @@ -646,7 +646,7 @@ void NMethodSweeper::log_sweep(const char* msg, const char* format, ...) { CodeCache::log_state(&s); ttyLocker ttyl; - xtty->begin_elem("sweeper state='%s' traversals='" INTX_FORMAT "' ", msg, (intx)traversal_count()); + xtty->begin_elem("sweeper state='%s' traversals='" INT64_FORMAT "' ", msg, traversal_count()); if (format != NULL) { va_list ap; va_start(ap, format); @@ -664,8 +664,9 @@ void NMethodSweeper::print(outputStream* out) { out = (out == NULL) ? tty : out; out->print_cr("Code cache sweeper statistics:"); out->print_cr(" Total sweep time: %1.0lf ms", (double)_total_time_sweeping.value()/1000000); - out->print_cr(" Total number of full sweeps: %ld", _total_nof_code_cache_sweeps); - out->print_cr(" Total number of flushed methods: %ld (thereof %ld C2 methods)", _total_nof_methods_reclaimed, + out->print_cr(" Total number of full sweeps: " INT64_FORMAT, _total_nof_code_cache_sweeps); + out->print_cr(" Total number of flushed methods: " INT64_FORMAT " (thereof " INT64_FORMAT " C2 methods)", + _total_nof_methods_reclaimed, _total_nof_c2_methods_reclaimed); out->print_cr(" Total size of flushed methods: " SIZE_FORMAT " kB", _total_flushed_size/K); } diff --git a/src/hotspot/share/runtime/sweeper.hpp b/src/hotspot/share/runtime/sweeper.hpp index 9ba2298e9ef..ecf5a353cfd 100644 --- a/src/hotspot/share/runtime/sweeper.hpp +++ b/src/hotspot/share/runtime/sweeper.hpp @@ -66,8 +66,8 @@ class NMethodSweeper : public AllStatic { MadeZombie, Flushed }; - static long _traversals; // Stack scan count, also sweep ID. - static long _total_nof_code_cache_sweeps; // Total number of full sweeps of the code cache + static int64_t _traversals; // Stack scan count, also sweep ID. + static int64_t _total_nof_code_cache_sweeps; // Total number of full sweeps of the code cache static CompiledMethodIterator _current; // Current compiled method static int _seen; // Nof. nmethod we have currently processed in current pass of CodeCache static size_t _sweep_threshold_bytes; // The threshold for when to invoke sweeps @@ -78,8 +78,8 @@ class NMethodSweeper : public AllStatic { // 1) alive -> not_entrant // 2) not_entrant -> zombie // Stat counters - static long _total_nof_methods_reclaimed; // Accumulated nof methods flushed - static long _total_nof_c2_methods_reclaimed; // Accumulated nof C2-compiled methods flushed + static int64_t _total_nof_methods_reclaimed; // Accumulated nof methods flushed + static int64_t _total_nof_c2_methods_reclaimed; // Accumulated nof C2-compiled methods flushed static size_t _total_flushed_size; // Total size of flushed methods static int _hotness_counter_reset_val; @@ -97,10 +97,10 @@ class NMethodSweeper : public AllStatic { static void do_stack_scanning(); static void sweep(); public: - static long traversal_count() { return _traversals; } + static int64_t traversal_count() { return _traversals; } static size_t sweep_threshold_bytes() { return _sweep_threshold_bytes; } static void set_sweep_threshold_bytes(size_t threshold) { _sweep_threshold_bytes = threshold; } - static int total_nof_methods_reclaimed() { return _total_nof_methods_reclaimed; } + static int64_t total_nof_methods_reclaimed() { return _total_nof_methods_reclaimed; } static const Tickspan total_time_sweeping() { return _total_time_sweeping; } static const Tickspan peak_sweep_time() { return _peak_sweep_time; } static const Tickspan peak_sweep_fraction_time() { return _peak_sweep_fraction_time; } diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp index 3ec853d38f0..7fc64c94385 100644 --- a/src/hotspot/share/runtime/vmStructs.cpp +++ b/src/hotspot/share/runtime/vmStructs.cpp @@ -660,7 +660,7 @@ nonstatic_field(nmethod, _verified_entry_point, address) \ nonstatic_field(nmethod, _osr_entry_point, address) \ volatile_nonstatic_field(nmethod, _lock_count, jint) \ - volatile_nonstatic_field(nmethod, _stack_traversal_mark, long) \ + volatile_nonstatic_field(nmethod, _stack_traversal_mark, int64_t) \ nonstatic_field(nmethod, _compile_id, int) \ nonstatic_field(nmethod, _comp_level, int) \ \ @@ -1199,6 +1199,7 @@ declare_integer_type(ssize_t) \ declare_integer_type(intx) \ declare_integer_type(intptr_t) \ + declare_integer_type(int64_t) \ declare_unsigned_integer_type(uintx) \ declare_unsigned_integer_type(uintptr_t) \ declare_unsigned_integer_type(uint8_t) \ -- GitLab From e44dc638b8936b1b76ca9ddf9ece0c5c4705a19c Mon Sep 17 00:00:00 2001 From: Dean Long Date: Thu, 3 Feb 2022 22:10:44 +0000 Subject: [PATCH 396/564] 8271055: Crash during deoptimization with "assert(bb->is_reachable()) failed: getting result from unreachable basicblock" with -XX:+VerifyStack Co-authored-by: Yi Yang Co-authored-by: Yi Yang Reviewed-by: vlivanov, thartmann --- src/hotspot/share/runtime/deoptimization.cpp | 17 ++++- .../jtreg/compiler/interpreter/Custom.jasm | 63 +++++++++++++++++++ .../VerifyStackWithUnreachableBlock.java | 42 +++++++++++++ 3 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 test/hotspot/jtreg/compiler/interpreter/Custom.jasm create mode 100644 test/hotspot/jtreg/compiler/interpreter/VerifyStackWithUnreachableBlock.java diff --git a/src/hotspot/share/runtime/deoptimization.cpp b/src/hotspot/share/runtime/deoptimization.cpp index 206e5951304..fee21540809 100644 --- a/src/hotspot/share/runtime/deoptimization.cpp +++ b/src/hotspot/share/runtime/deoptimization.cpp @@ -704,6 +704,21 @@ void Deoptimization::unwind_callee_save_values(frame* f, vframeArray* vframe_arr assert(f->is_interpreted_frame(), "must be interpreted"); } +#ifndef PRODUCT +static bool falls_through(Bytecodes::Code bc) { + switch (bc) { + // List may be incomplete. Here we really only care about bytecodes where compiled code + // can deoptimize. + case Bytecodes::_goto: + case Bytecodes::_goto_w: + case Bytecodes::_athrow: + return false; + default: + return true; + } +} +#endif + // Return BasicType of value being returned JRT_LEAF(BasicType, Deoptimization::unpack_frames(JavaThread* thread, int exec_mode)) @@ -801,7 +816,7 @@ JRT_LEAF(BasicType, Deoptimization::unpack_frames(JavaThread* thread, int exec_m // calls. It seems to be hard to tell whether the compiler // has emitted debug information matching the "state before" // a given bytecode or the state after, so we try both - if (!Bytecodes::is_invoke(cur_code) && cur_code != Bytecodes::_athrow) { + if (!Bytecodes::is_invoke(cur_code) && falls_through(cur_code)) { // Get expression stack size for the next bytecode InterpreterOopMap next_mask; OopMapCache::compute_one_oop_map(mh, str.bci(), &next_mask); diff --git a/test/hotspot/jtreg/compiler/interpreter/Custom.jasm b/test/hotspot/jtreg/compiler/interpreter/Custom.jasm new file mode 100644 index 00000000000..e52d513d2fa --- /dev/null +++ b/test/hotspot/jtreg/compiler/interpreter/Custom.jasm @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2022, 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 compiler/interpreter; + +/* JASM simplified from the following Java pattern: + * + * public class Custom { + * + * static void test(int v) { + * int i8 = 1; + * try { + * v += 1; + * } catch (ArithmeticException exc1) { + * } finally { + * for (; i8 < 100; i8++) { + * } + * } + * } + * + */ + +super public class Custom { + + public static Method test:"(I)V" stack 2 locals 3 { + iconst_1; + istore_1; + try t0; + iinc 0, 1; + endtry t0; +Loop: + iload_1; + bipush 100; + if_icmpge Lexit; + iinc 1, 1; + goto Loop; // deoptimize here on backwards branch + catch t0 java/lang/ArithmeticException; // unreachable block + astore_2; +Lexit: + return + } + +} diff --git a/test/hotspot/jtreg/compiler/interpreter/VerifyStackWithUnreachableBlock.java b/test/hotspot/jtreg/compiler/interpreter/VerifyStackWithUnreachableBlock.java new file mode 100644 index 00000000000..f8aace2b31b --- /dev/null +++ b/test/hotspot/jtreg/compiler/interpreter/VerifyStackWithUnreachableBlock.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, Alibaba Group Holding Limited. 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 VerifyStackWithUnreachableBlock + * @bug 8271055 + * @compile Custom.jasm VerifyStackWithUnreachableBlock.java + * @summary Using VerifyStack for method that contains unreachable basic blocks + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+VerifyStack compiler.interpreter.VerifyStackWithUnreachableBlock + */ + +package compiler.interpreter; + +public class VerifyStackWithUnreachableBlock { + public static void main(String[] strArr) { + for (int i = 0; i < 10000; i++) { + Custom.test(i); + } + } +} -- GitLab From 63e11cfa3f887515ca36ab5147c3e6fa540978d3 Mon Sep 17 00:00:00 2001 From: Andrey Turbanov Date: Fri, 4 Feb 2022 07:08:07 +0000 Subject: [PATCH 397/564] 8280970: Cleanup dead code in java.security.Provider Reviewed-by: valeriep --- .../share/classes/java/security/Provider.java | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/java.base/share/classes/java/security/Provider.java b/src/java.base/share/classes/java/security/Provider.java index c1c4bea90cd..4a458cae7f8 100644 --- a/src/java.base/share/classes/java/security/Provider.java +++ b/src/java.base/share/classes/java/security/Provider.java @@ -1116,11 +1116,6 @@ public abstract class Provider extends Properties { return new String[] {type, alg}; } - // utility method for getting a String with service type and algorithm - private static String getKey(Service s) { - return s.getType() + "." + s.getAlgorithm(); - } - private static final String ALIAS_PREFIX = "Alg.Alias."; private static final String ALIAS_PREFIX_LOWER = "alg.alias."; private static final int ALIAS_LENGTH = ALIAS_PREFIX.length(); @@ -1544,21 +1539,12 @@ public abstract class Provider extends Properties { final String name; final boolean supportsParameter; final String constructorParameterClassName; - private volatile Class constructorParameterClass; EngineDescription(String name, boolean sp, String paramName) { this.name = name; this.supportsParameter = sp; this.constructorParameterClassName = paramName; } - Class getConstructorParameterClass() throws ClassNotFoundException { - Class clazz = constructorParameterClass; - if (clazz == null) { - clazz = Class.forName(constructorParameterClassName); - constructorParameterClass = clazz; - } - return clazz; - } } // built in knowledge of the engine types shipped as part of the JDK -- GitLab From 01f93ddf18daea5c0798ac949c6717c37d9cefa0 Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Fri, 4 Feb 2022 07:47:42 +0000 Subject: [PATCH 398/564] 8279385: [test] Adjust sun/security/pkcs12/KeytoolOpensslInteropTest.java after 8278344 Reviewed-by: mullan, xuelei Backport-of: 9bdf6eb7b2412ecff523015f1430dfb6a0e4dd09 --- test/jdk/sun/security/pkcs12/KeytoolOpensslInteropTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/jdk/sun/security/pkcs12/KeytoolOpensslInteropTest.java b/test/jdk/sun/security/pkcs12/KeytoolOpensslInteropTest.java index 7fcbd95ca7d..c35bf47d56d 100644 --- a/test/jdk/sun/security/pkcs12/KeytoolOpensslInteropTest.java +++ b/test/jdk/sun/security/pkcs12/KeytoolOpensslInteropTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2022, 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 @@ -462,7 +462,7 @@ public class KeytoolOpensslInteropTest { "pkcs12", "-in", "ksnormal", "-passin", "pass:changeit", "-info", "-nokeys", "-nocerts"); output1.shouldHaveExitValue(0) - .shouldContain("MAC:").shouldContain("sha256").shouldContain("Iteration 10000") + .shouldMatch("MAC:.*sha256.*Iteration 10000") .shouldContain("Shrouded Keybag: PBES2, PBKDF2, AES-256-CBC," + " Iteration 10000, PRF hmacWithSHA256") .shouldContain("PKCS7 Encrypted data: PBES2, PBKDF2, AES-256-CBC," @@ -505,7 +505,7 @@ public class KeytoolOpensslInteropTest { "ksnewic", "-passin", "pass:changeit", "-info", "-nokeys", "-nocerts"); output1.shouldHaveExitValue(0) - .shouldContain("MAC:").shouldContain("sha256").shouldContain("Iteration 5555") + .shouldMatch("MAC:.*sha256.*Iteration 5555") .shouldContain("Shrouded Keybag: PBES2, PBKDF2, AES-256-CBC," + " Iteration 7777, PRF hmacWithSHA256") .shouldContain("Shrouded Keybag: pbeWithSHA1And128BitRC4," -- GitLab From c936e7059b848d0e0be5f3234c4367657f2af2a7 Mon Sep 17 00:00:00 2001 From: Richard Reingruber Date: Fri, 4 Feb 2022 07:57:55 +0000 Subject: [PATCH 399/564] 8280593: [PPC64, S390] redundant allocation of MacroAssembler in StubGenerator ctor Reviewed-by: mdoerr, lucy --- src/hotspot/cpu/ppc/stubGenerator_ppc.cpp | 6 ++---- src/hotspot/cpu/s390/stubGenerator_s390.cpp | 7 ++----- src/hotspot/share/runtime/stubCodeGenerator.cpp | 2 +- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp b/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp index 0e68a38dbaf..901918f7b37 100644 --- a/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp +++ b/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2021 SAP SE. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022 SAP SE. 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 @@ -4656,8 +4656,6 @@ class StubGenerator: public StubCodeGenerator { public: StubGenerator(CodeBuffer* code, bool all) : StubCodeGenerator(code) { - // replace the standard masm with a special one: - _masm = new MacroAssembler(code); if (all) { generate_all(); } else { diff --git a/src/hotspot/cpu/s390/stubGenerator_s390.cpp b/src/hotspot/cpu/s390/stubGenerator_s390.cpp index 218b0b378b9..102200fc08f 100644 --- a/src/hotspot/cpu/s390/stubGenerator_s390.cpp +++ b/src/hotspot/cpu/s390/stubGenerator_s390.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016, 2019 SAP SE. All rights reserved. + * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022 SAP SE. 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 @@ -2404,9 +2404,6 @@ class StubGenerator: public StubCodeGenerator { public: StubGenerator(CodeBuffer* code, bool all) : StubCodeGenerator(code) { - // Replace the standard masm with a special one: - _masm = new MacroAssembler(code); - _stub_count = !all ? 0x100 : 0x200; if (all) { generate_all(); diff --git a/src/hotspot/share/runtime/stubCodeGenerator.cpp b/src/hotspot/share/runtime/stubCodeGenerator.cpp index 68a82d78326..fb546bc8ebe 100644 --- a/src/hotspot/share/runtime/stubCodeGenerator.cpp +++ b/src/hotspot/share/runtime/stubCodeGenerator.cpp @@ -69,7 +69,7 @@ void StubCodeDesc::print() const { print_on(tty); } // Implementation of StubCodeGenerator StubCodeGenerator::StubCodeGenerator(CodeBuffer* code, bool print_code) { - _masm = new MacroAssembler(code ); + _masm = new MacroAssembler(code); _print_code = PrintStubCode || print_code; } -- GitLab From 46c6c6f308b5ec0ec3b762df4b76de555287474c Mon Sep 17 00:00:00 2001 From: Martin Doerr Date: Fri, 4 Feb 2022 09:13:41 +0000 Subject: [PATCH 400/564] 8281043: Intrinsify recursive ObjectMonitor locking for PPC64 Reviewed-by: rrich, lucy --- src/hotspot/cpu/ppc/macroAssembler_ppc.cpp | 35 ++++++++++++---------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp index 57d65c3aa08..d8397ed6fa5 100644 --- a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2021 SAP SE. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022 SAP SE. 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 @@ -2732,16 +2732,17 @@ void MacroAssembler::compiler_fast_lock_object(ConditionRegister flag, Register // Store a non-null value into the box. std(box, BasicLock::displaced_header_offset_in_bytes(), box); + beq(flag, cont); -# ifdef ASSERT + // Check for recursive locking. + cmpd(flag, current_header, R16_thread); bne(flag, cont); - // We have acquired the monitor, check some invariants. - addi(/*monitor=*/temp, temp, -ObjectMonitor::owner_offset_in_bytes()); - // Invariant 1: _recursions should be 0. - //assert(ObjectMonitor::recursions_size_in_bytes() == 8, "unexpected size"); - asm_assert_mem8_is_zero(ObjectMonitor::recursions_offset_in_bytes(), temp, - "monitor->_recursions should be 0"); -# endif + + // Current thread already owns the lock. Just increment recursions. + Register recursions = displaced_header; + ld(recursions, ObjectMonitor::recursions_offset_in_bytes()-ObjectMonitor::owner_offset_in_bytes(), temp); + addi(recursions, recursions, 1); + std(recursions, ObjectMonitor::recursions_offset_in_bytes()-ObjectMonitor::owner_offset_in_bytes(), temp); #if INCLUDE_RTM_OPT } // use_rtm() @@ -2757,8 +2758,7 @@ void MacroAssembler::compiler_fast_unlock_object(ConditionRegister flag, Registe bool use_rtm) { assert_different_registers(oop, box, temp, displaced_header, current_header); assert(flag != CCR0, "bad condition register"); - Label cont; - Label object_has_monitor; + Label cont, object_has_monitor, notRecursive; #if INCLUDE_RTM_OPT if (UseRTMForStackLocks && use_rtm) { @@ -2830,11 +2830,16 @@ void MacroAssembler::compiler_fast_unlock_object(ConditionRegister flag, Registe #endif ld(displaced_header, ObjectMonitor::recursions_offset_in_bytes(), current_header); - xorr(temp, R16_thread, temp); // Will be 0 if we are the owner. - orr(temp, temp, displaced_header); // Will be 0 if there are 0 recursions. - cmpdi(flag, temp, 0); + + cmpd(flag, temp, R16_thread); bne(flag, cont); + addic_(displaced_header, displaced_header, -1); + blt(CCR0, notRecursive); // Not recursive if negative after decrement. + std(displaced_header, ObjectMonitor::recursions_offset_in_bytes(), current_header); + b(cont); // flag is already EQ here. + + bind(notRecursive); ld(temp, ObjectMonitor::EntryList_offset_in_bytes(), current_header); ld(displaced_header, ObjectMonitor::cxq_offset_in_bytes(), current_header); orr(temp, temp, displaced_header); // Will be 0 if both are 0. -- GitLab From 51b53a821bb3cfb962f80a637f5fb8cde988975a Mon Sep 17 00:00:00 2001 From: Manukumar V S Date: Fri, 4 Feb 2022 10:51:30 +0000 Subject: [PATCH 401/564] 8280913: Create a regression test for JRootPane.setDefaultButton() method Reviewed-by: aivanov --- .../swing/JRootPane/DefaultButtonTest.java | 111 ++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 test/jdk/javax/swing/JRootPane/DefaultButtonTest.java diff --git a/test/jdk/javax/swing/JRootPane/DefaultButtonTest.java b/test/jdk/javax/swing/JRootPane/DefaultButtonTest.java new file mode 100644 index 00000000000..cff2ea73c93 --- /dev/null +++ b/test/jdk/javax/swing/JRootPane/DefaultButtonTest.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Robot; +import java.awt.event.KeyEvent; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; + +/* + * @test + * @key headful + * @bug 8280913 + * @summary Check whether the default button is honored when key is pressed. + * @run main DefaultButtonTest + */ +public class DefaultButtonTest { + private volatile boolean buttonPressed; + private JFrame frame; + + public static void main(String[] s) throws Exception { + DefaultButtonTest test = new DefaultButtonTest(); + test.runTest(); + } + + private static void setLookAndFeel(String lafName) { + try { + UIManager.setLookAndFeel(lafName); + } catch (UnsupportedLookAndFeelException ignored) { + System.out.println("Ignoring Unsupported L&F: " + lafName); + } catch (ClassNotFoundException | InstantiationException + | IllegalAccessException e) { + throw new RuntimeException(e); + } + } + + private void disposeFrame() { + if (frame != null) { + frame.dispose(); + frame = null; + } + } + + private void createUI() { + frame = new JFrame("Default Button Test"); + JPanel panel = new JPanel(); + panel.add(new JTextField("Text field")); + JButton button1 = new JButton("Default"); + button1.addActionListener(e -> buttonPressed = true); + panel.add(button1); + panel.add(new JButton("Button2")); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.add(panel); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.getRootPane().setDefaultButton(button1); + frame.setVisible(true); + } + + public void runTest() throws Exception { + Robot robot = new Robot(); + robot.setAutoDelay(100); + for (UIManager.LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels()) { + try { + buttonPressed = false; + String lafName = laf.getClassName(); + System.out.println("Testing L&F: " + lafName); + SwingUtilities.invokeAndWait(() -> { + setLookAndFeel(lafName); + createUI(); + }); + robot.waitForIdle(); + robot.keyPress(KeyEvent.VK_ENTER); + robot.keyRelease(KeyEvent.VK_ENTER); + robot.waitForIdle(); + + if (buttonPressed) { + System.out.println("Test Passed for L&F: " + lafName); + } else { + throw new RuntimeException("Test Failed, Default Button not pressed for L&F: " + lafName); + } + } finally { + SwingUtilities.invokeAndWait(this::disposeFrame); + } + } + } +} -- GitLab From 3d926dd66ef6551e91a4ebbbc59dcff58f5ede5a Mon Sep 17 00:00:00 2001 From: Rob McKenna Date: Fri, 4 Feb 2022 13:07:03 +0000 Subject: [PATCH 402/564] 8277795: ldap connection timeout not honoured under contention Reviewed-by: dfuchs, aefimov --- .../com/sun/jndi/ldap/LdapClientFactory.java | 16 ++ .../com/sun/jndi/ldap/pool/Connections.java | 265 ++++++++++-------- .../classes/com/sun/jndi/ldap/pool/Pool.java | 109 +++++-- .../ldap/pool/PooledConnectionFactory.java | 9 + .../sun/jndi/ldap/LdapPoolTimeoutTest.java | 139 +++++++++ 5 files changed, 395 insertions(+), 143 deletions(-) create mode 100644 test/jdk/com/sun/jndi/ldap/LdapPoolTimeoutTest.java diff --git a/src/java.naming/share/classes/com/sun/jndi/ldap/LdapClientFactory.java b/src/java.naming/share/classes/com/sun/jndi/ldap/LdapClientFactory.java index af94713155f..eaaccac2ffe 100644 --- a/src/java.naming/share/classes/com/sun/jndi/ldap/LdapClientFactory.java +++ b/src/java.naming/share/classes/com/sun/jndi/ldap/LdapClientFactory.java @@ -65,7 +65,23 @@ final class LdapClientFactory implements PooledConnectionFactory { connTimeout, readTimeout, trace, pcb); } + public PooledConnection createPooledConnection(PoolCallback pcb, long timeout) + throws NamingException { + return new LdapClient(host, port, socketFactory, + guardedIntegerCast(timeout), + readTimeout, trace, pcb); + } + public String toString() { return host + ":" + port; } + + private int guardedIntegerCast(long timeout) { + if (timeout < Integer.MIN_VALUE) { + return Integer.MIN_VALUE; + } else if (timeout > Integer.MAX_VALUE) { + return Integer.MAX_VALUE; + } + return (int) timeout; + } } diff --git a/src/java.naming/share/classes/com/sun/jndi/ldap/pool/Connections.java b/src/java.naming/share/classes/com/sun/jndi/ldap/pool/Connections.java index f64769ad51a..d485288ccac 100644 --- a/src/java.naming/share/classes/com/sun/jndi/ldap/pool/Connections.java +++ b/src/java.naming/share/classes/com/sun/jndi/ldap/pool/Connections.java @@ -27,6 +27,9 @@ package com.sun.jndi.ldap.pool; import java.util.ArrayList; // JDK 1.2 import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.ReentrantLock; import java.lang.ref.Reference; import java.lang.ref.SoftReference; @@ -68,13 +71,19 @@ final class Connections implements PoolCallback { com.sun.jndi.ldap.LdapPoolManager.trace; private static final int DEFAULT_SIZE = 10; + final private int initSize; private final int maxSize; private final int prefSize; private final List conns; + final private PooledConnectionFactory factory; private boolean closed = false; // Closed for business private Reference ref; // maintains reference to id to prevent premature GC + private boolean initialized = false; + private final ReentrantLock lock; + private final Condition connectionsAvailable; + /** * @param id the identity (connection request) of the connections in the list * @param initSize the number of connections to create initially @@ -87,105 +96,73 @@ final class Connections implements PoolCallback { * when one is removed. * @param factory The factory responsible for creating a connection */ - Connections(Object id, int initSize, int prefSize, int maxSize, - PooledConnectionFactory factory) throws NamingException { - + Connections(Object id, int initSize, int prefSize, int maxSize, PooledConnectionFactory factory, + ReentrantLock lock) throws NamingException { this.maxSize = maxSize; + this.lock = lock; + this.connectionsAvailable = lock.newCondition(); + this.factory = factory; + if (maxSize > 0) { // prefSize and initSize cannot exceed specified maxSize this.prefSize = Math.min(prefSize, maxSize); - initSize = Math.min(initSize, maxSize); + this.initSize = Math.min(initSize, maxSize); } else { this.prefSize = prefSize; + this.initSize = initSize; } - conns = new ArrayList<>(maxSize > 0 ? maxSize : DEFAULT_SIZE); + this.conns = new ArrayList<>(maxSize > 0 ? maxSize : DEFAULT_SIZE); + this.initialized = initSize <= 0; // Maintain soft ref to id so that this Connections' entry in // Pool doesn't get GC'ed prematurely - ref = new SoftReference<>(id); + this.ref = new SoftReference<>(id); d("init size=", initSize); d("max size=", maxSize); d("preferred size=", prefSize); + } - // Create initial connections - PooledConnection conn; - for (int i = 0; i < initSize; i++) { - conn = factory.createPooledConnection(this); - td("Create ", conn ,factory); - conns.add(new ConnectionDesc(conn)); // Add new idle conn to pool + void waitForAvailableConnection() throws InterruptedNamingException { + try { + d("get(): waiting"); + connectionsAvailable.await(); + } catch (InterruptedException e) { + throw new InterruptedNamingException( + "Interrupted while waiting for a connection"); } } - /** - * Retrieves a PooledConnection from this list of connections. - * Use an existing one if one is idle, or create one if the list's - * max size hasn't been reached. If max size has been reached, wait - * for a PooledConnection to be returned, or one to be removed (thus - * not reaching the max size any longer). - * - * @param timeout if > 0, msec to wait until connection is available - * @param factory creates the PooledConnection if one needs to be created - * - * @return A non-null PooledConnection - * @throws NamingException PooledConnection cannot be created, because this - * thread was interrupted while it waited for an available connection, - * or if it timed out while waiting, or the creation of a connection - * resulted in an error. - */ - synchronized PooledConnection get(long timeout, - PooledConnectionFactory factory) throws NamingException { - PooledConnection conn; - long start = (timeout > 0 ? System.currentTimeMillis() : 0); - long waittime = timeout; - - d("get(): before"); - while ((conn = getOrCreateConnection(factory)) == null) { - if (timeout > 0 && waittime <= 0) { - throw new CommunicationException( - "Timeout exceeded while waiting for a connection: " + - timeout + "ms"); - } - try { - d("get(): waiting"); - if (waittime > 0) { - wait(waittime); // Wait until one is released or removed - } else { - wait(); - } - } catch (InterruptedException e) { - throw new InterruptedNamingException( + void waitForAvailableConnection(long waitTime) throws InterruptedNamingException { + try { + d("get(): waiting"); + connectionsAvailable.await(waitTime, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + throw new InterruptedNamingException( "Interrupted while waiting for a connection"); - } - // Check whether we timed out - if (timeout > 0) { - long now = System.currentTimeMillis(); - waittime = timeout - (now - start); - } } - - d("get(): after"); - return conn; } /** * Retrieves an idle connection from this list if one is available. - * If none is available, create a new one if maxSize hasn't been reached. - * If maxSize has been reached, return null. - * Always called from a synchronized method. */ - private PooledConnection getOrCreateConnection( - PooledConnectionFactory factory) throws NamingException { - + PooledConnection getAvailableConnection(long timeout) throws NamingException { + if (!initialized) { + PooledConnection conn = createConnection(factory, timeout); + if (conns.size() >= initSize) { + this.initialized = true; + } + return conn; + } int size = conns.size(); // Current number of idle/nonidle conns - PooledConnection conn = null; if (prefSize <= 0 || size >= prefSize) { // If no prefSize specified, or list size already meets or // exceeds prefSize, then first look for an idle connection ConnectionDesc entry; - for (int i = 0; i < size; i++) { - entry = conns.get(i); + for (ConnectionDesc connectionDesc : conns) { + PooledConnection conn; + entry = connectionDesc; if ((conn = entry.tryUse()) != null) { d("get(): use ", conn); td("Use ", conn); @@ -193,17 +170,25 @@ final class Connections implements PoolCallback { } } } + return null; + } - // Check if list size already at maxSize specified - if (maxSize > 0 && size >= maxSize) { - return null; // List size is at limit; cannot create any more + /* + * Creates a new Connection if maxSize hasn't been reached. + * If maxSize has been reached, return null. + * Caller must hold the ReentrantLock. + */ + PooledConnection createConnection(PooledConnectionFactory factory, long timeout) + throws NamingException { + int size = conns.size(); // Current number of idle/non-idle connections + if (maxSize == 0 || size < maxSize) { + PooledConnection conn = factory.createPooledConnection(this, timeout); + td("Create and use ", conn, factory); + conns.add(new ConnectionDesc(conn, true)); // Add new conn to pool + return conn; } - conn = factory.createPooledConnection(this); - td("Create and use ", conn, factory); - conns.add(new ConnectionDesc(conn, true)); // Add new conn to pool - - return conn; + return null; } /** @@ -211,43 +196,45 @@ final class Connections implements PoolCallback { * If the list size is below prefSize, the connection may be reused. * If the list size exceeds prefSize, then the connection is closed * and removed from the list. - * + *

    * public because implemented as part of PoolCallback. */ - public synchronized boolean releasePooledConnection(PooledConnection conn) { - ConnectionDesc entry; - int loc = conns.indexOf(entry=new ConnectionDesc(conn)); - - d("release(): ", conn); - - if (loc >= 0) { - // Found entry + public boolean releasePooledConnection(PooledConnection conn) { + lock.lock(); + try { + ConnectionDesc entry; + int loc = conns.indexOf(entry = new ConnectionDesc(conn)); - if (closed || (prefSize > 0 && conns.size() > prefSize)) { - // If list size exceeds prefSize, close connection + d("release(): ", conn); - d("release(): closing ", conn); - td("Close ", conn); + if (loc >= 0) { + // Found entry - // size must be >= 2 so don't worry about empty list - conns.remove(entry); - conn.closeConnection(); + if (closed || (prefSize > 0 && conns.size() > prefSize)) { + // If list size exceeds prefSize, close connection - } else { - d("release(): release ", conn); - td("Release ", conn); + d("release(): closing ", conn); + td("Close ", conn); - // Get ConnectionDesc from list to get correct state info - entry = conns.get(loc); - // Return connection to list, ready for reuse - entry.release(); + // size must be >= 2 so don't worry about empty list + conns.remove(entry); + conn.closeConnection(); + } else { + d("release(): release ", conn); + td("Release ", conn); + // Get ConnectionDesc from list to get correct state info + entry = conns.get(loc); + // Return connection to list, ready for reuse + entry.release(); + } + connectionsAvailable.signalAll(); + d("release(): notify"); + return true; } - notifyAll(); - d("release(): notify"); - return true; - } else { - return false; + } finally { + lock.unlock(); } + return false; } /** @@ -257,29 +244,34 @@ final class Connections implements PoolCallback { * when using the connection and wants it removed from the pool. * * @return true if conn removed; false if it was not in pool - * + *

    * public because implemented as part of PoolCallback. */ - public synchronized boolean removePooledConnection(PooledConnection conn) { - if (conns.remove(new ConnectionDesc(conn))) { - d("remove(): ", conn); + public boolean removePooledConnection(PooledConnection conn) { + lock.lock(); + try { + if (conns.remove(new ConnectionDesc(conn))) { + d("remove(): ", conn); - notifyAll(); + connectionsAvailable.signalAll(); - d("remove(): notify"); - td("Remove ", conn); + d("remove(): notify"); + td("Remove ", conn); - if (conns.isEmpty()) { - // Remove softref to make pool entry eligible for GC. - // Once ref has been removed, it cannot be reinstated. - ref = null; - } + if (conns.isEmpty()) { + // Remove softref to make pool entry eligible for GC. + // Once ref has been removed, it cannot be reinstated. + ref = null; + } - return true; - } else { - d("remove(): not found ", conn); - return false; + return true; + } else { + d("remove(): not found ", conn); + } + } finally { + lock.unlock(); } + return false; } /** @@ -291,8 +283,11 @@ final class Connections implements PoolCallback { */ boolean expire(long threshold) { List clonedConns; - synchronized(this) { + lock.lock(); + try { clonedConns = new ArrayList<>(conns); + } finally { + lock.unlock(); } List expired = new ArrayList<>(); @@ -304,12 +299,15 @@ final class Connections implements PoolCallback { } } - synchronized (this) { + lock.lock(); + try { conns.removeAll(expired); // Don't need to call notify() because we're // removing only idle connections. If there were // idle connections, then there should be no waiters. return conns.isEmpty(); // whether whole list has 'expired' + } finally { + lock.unlock(); } } @@ -355,6 +353,29 @@ final class Connections implements PoolCallback { + "; idle=" + idle + "; expired=" + expired; } + boolean grabLock(long timeout) throws InterruptedNamingException { + final long start = System.nanoTime(); + long current = start; + long remaining = timeout; + boolean locked = false; + while (!locked && remaining > 0) { + try { + locked = lock.tryLock(remaining, TimeUnit.MILLISECONDS); + remaining -= TimeUnit.NANOSECONDS.toMillis(current - start); + } catch (InterruptedException ignore) { + throw new InterruptedNamingException( + "Interrupted while waiting for the connection pool lock"); + } + current = System.nanoTime(); + remaining -= TimeUnit.NANOSECONDS.toMillis(current - start); + } + return locked; + } + + void unlock() { + lock.unlock(); + } + private void d(String msg, Object o1) { if (debug) { d(msg + o1); diff --git a/src/java.naming/share/classes/com/sun/jndi/ldap/pool/Pool.java b/src/java.naming/share/classes/com/sun/jndi/ldap/pool/Pool.java index 24700cbdd13..b7bc3ba98bf 100644 --- a/src/java.naming/share/classes/com/sun/jndi/ldap/pool/Pool.java +++ b/src/java.naming/share/classes/com/sun/jndi/ldap/pool/Pool.java @@ -31,10 +31,13 @@ import java.util.WeakHashMap; import java.util.Collection; import java.util.Collections; import java.util.LinkedList; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.ReentrantLock; import java.io.PrintStream; import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; +import javax.naming.CommunicationException; import javax.naming.NamingException; /** @@ -117,45 +120,109 @@ public final class Pool { public PooledConnection getPooledConnection(Object id, long timeout, PooledConnectionFactory factory) throws NamingException { + final long start = System.nanoTime(); + long remaining = timeout; + d("get(): ", id); if (debug) { synchronized (map) { d("size: ", map.size()); } + remaining = checkRemaining(start, remaining); } expungeStaleConnections(); + Connections conns = getOrCreateConnections(factory, id); + d("get(): size after: ", map.size()); + remaining = checkRemaining(start, remaining); + + if (!conns.grabLock(remaining)) { + throw new CommunicationException("Timed out waiting for lock"); + } + + try { + remaining = checkRemaining(start, remaining); + PooledConnection conn = null; + while (remaining > 0 && conn == null) { + conn = getOrCreatePooledConnection(factory, conns, start, remaining); + // don't loop if the timeout has expired + remaining = checkRemaining(start, timeout); + } + return conn; + } finally { + conns.unlock(); + } + } + + private Connections getOrCreateConnections(PooledConnectionFactory factory, Object id) + throws NamingException { + Connections conns; synchronized (map) { - conns = getConnections(id); - if (conns == null) { - d("get(): creating new connections list for ", id); - - // No connections for this id so create a new list - conns = new Connections(id, initSize, prefSize, maxSize, - factory); - ConnectionsRef connsRef = new ConnectionsRef(conns); - map.put(id, connsRef); - - // Create a weak reference to ConnectionsRef - Reference weakRef = - new ConnectionsWeakRef(connsRef, queue); - - // Keep the weak reference through the element of a linked list - weakRefs.add(weakRef); + ConnectionsRef ref = map.get(id); + if (ref != null) { + return ref.getConnections(); } - d("get(): size after: ", map.size()); + + d("get(): creating new connections list for ", id); + + // No connections for this id so create a new list + conns = new Connections(id, initSize, prefSize, maxSize, + factory, new ReentrantLock()); + + ConnectionsRef connsRef = new ConnectionsRef(conns); + map.put(id, connsRef); + + // Create a weak reference to ConnectionsRef + Reference weakRef = new ConnectionsWeakRef(connsRef, queue); + + // Keep the weak reference through the element of a linked list + weakRefs.add(weakRef); } + return conns; + } - return conns.get(timeout, factory); // get one connection from list + private PooledConnection getOrCreatePooledConnection( + PooledConnectionFactory factory, Connections conns, long start, long timeout) + throws NamingException { + PooledConnection conn = conns.getAvailableConnection(timeout); + if (conn != null) { + return conn; + } + // no available cached connection + // check if list size already at maxSize before creating a new one + conn = conns.createConnection(factory, timeout); + if (conn != null) { + return conn; + } + // max number of connections already created, + // try waiting around for one to become available + if (timeout <= 0) { + conns.waitForAvailableConnection(); + } else { + long remaining = checkRemaining(start, timeout); + conns.waitForAvailableConnection(remaining); + } + return null; } - private Connections getConnections(Object id) { - ConnectionsRef ref = map.get(id); - return (ref != null) ? ref.getConnections() : null; + // Check whether we timed out + private long checkRemaining(long start, long timeout) throws CommunicationException { + if (timeout > 0) { + long current = System.nanoTime(); + long remaining = timeout - TimeUnit.NANOSECONDS.toMillis(current - start); + if (remaining <= 0) { + throw new CommunicationException( + "Timeout exceeded while waiting for a connection: " + + timeout + "ms"); + } + return remaining; + } + return Long.MAX_VALUE; } + /** * Goes through the connections in this Pool and expires ones that * have been idle before 'threshold'. An expired connection is closed diff --git a/src/java.naming/share/classes/com/sun/jndi/ldap/pool/PooledConnectionFactory.java b/src/java.naming/share/classes/com/sun/jndi/ldap/pool/PooledConnectionFactory.java index 3aa41769d4a..3f294497968 100644 --- a/src/java.naming/share/classes/com/sun/jndi/ldap/pool/PooledConnectionFactory.java +++ b/src/java.naming/share/classes/com/sun/jndi/ldap/pool/PooledConnectionFactory.java @@ -44,4 +44,13 @@ public interface PooledConnectionFactory { */ public abstract PooledConnection createPooledConnection(PoolCallback pcb) throws NamingException; + + /** + * Creates a pooled connection. + * @param pcb callback responsible for removing and releasing the pooled + * connection from the pool. + * @param timeout the connection timeout + */ + public abstract PooledConnection createPooledConnection(PoolCallback pcb, long timeout) + throws NamingException; }; diff --git a/test/jdk/com/sun/jndi/ldap/LdapPoolTimeoutTest.java b/test/jdk/com/sun/jndi/ldap/LdapPoolTimeoutTest.java new file mode 100644 index 00000000000..7a5df545655 --- /dev/null +++ b/test/jdk/com/sun/jndi/ldap/LdapPoolTimeoutTest.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2021, 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 8277795 + * @summary Multi-threaded client timeout tests for ldap pool + * @library /test/lib + * lib/ + * @run testng/othervm LdapPoolTimeoutTest + */ + +import org.testng.Assert; +import org.testng.annotations.Test; + +import java.io.IOException; +import javax.naming.Context; +import javax.naming.NamingException; +import javax.naming.directory.InitialDirContext; +import java.util.ArrayList; +import java.util.Hashtable; +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.TimeUnit; + +import static jdk.test.lib.Utils.adjustTimeout; +import static org.testng.Assert.assertTrue; +import static org.testng.Assert.expectThrows; + +public class LdapPoolTimeoutTest { + /* + * Practical representation of an infinite timeout. + */ + private static final long INFINITY_MILLIS = adjustTimeout(20_000); + /* + * The acceptable variation in timeout measurements. + */ + private static final long TOLERANCE = adjustTimeout( 3_500); + + private static final long CONNECT_MILLIS = adjustTimeout( 3_000); + private static final long READ_MILLIS = adjustTimeout(10_000); + + static { + // a series of checks to make sure this timeouts configuration is + // consistent and the timeouts do not overlap + + assert (TOLERANCE >= 0); + // context creation + assert (2 * CONNECT_MILLIS + TOLERANCE < READ_MILLIS); + // context creation immediately followed by search + assert (2 * CONNECT_MILLIS + READ_MILLIS + TOLERANCE < INFINITY_MILLIS); + } + + @Test + public void test() throws Exception { + List> futures = new ArrayList<>(); + ExecutorService executorService = Executors.newCachedThreadPool(); + + Hashtable env = new Hashtable<>(); + env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); + env.put("com.sun.jndi.ldap.read.timeout", String.valueOf(READ_MILLIS)); + env.put("com.sun.jndi.ldap.connect.timeout", String.valueOf(CONNECT_MILLIS)); + env.put("com.sun.jndi.ldap.connect.pool", "true"); + env.put(Context.PROVIDER_URL, "ldap://example.com:1234"); + + try { + futures.add(executorService.submit(() -> { attemptConnect(env); return null; })); + futures.add(executorService.submit(() -> { attemptConnect(env); return null; })); + futures.add(executorService.submit(() -> { attemptConnect(env); return null; })); + futures.add(executorService.submit(() -> { attemptConnect(env); return null; })); + futures.add(executorService.submit(() -> { attemptConnect(env); return null; })); + futures.add(executorService.submit(() -> { attemptConnect(env); return null; })); + futures.add(executorService.submit(() -> { attemptConnect(env); return null; })); + futures.add(executorService.submit(() -> { attemptConnect(env); return null; })); + } finally { + executorService.shutdown(); + } + int failedCount = 0; + for (var f : futures) { + try { + f.get(); + } catch (ExecutionException e) { + failedCount++; + e.getCause().printStackTrace(System.out); + } + } + if (failedCount > 0) + throw new RuntimeException(failedCount + " (sub)tests failed"); + } + + private static void attemptConnect(Hashtable env) throws Exception { + try { + LdapTimeoutTest.assertCompletion(CONNECT_MILLIS - 1000, + 2 * CONNECT_MILLIS + TOLERANCE, + () -> new InitialDirContext(env)); + } catch (RuntimeException e) { + String msg = e.getCause() == null ? e.getMessage() : e.getCause().getMessage(); + System.err.println("MSG RTE: " + msg); + // assertCompletion may wrap a CommunicationException in an RTE + assertTrue(msg != null && msg.contains("Network is unreachable")); + } catch (NamingException ex) { + String msg = ex.getCause() == null ? ex.getMessage() : ex.getCause().getMessage(); + System.err.println("MSG: " + msg); + assertTrue(msg != null && + (msg.contains("Network is unreachable") + || msg.contains("Timed out waiting for lock") + || msg.contains("Connect timed out") + || msg.contains("Timeout exceeded while waiting for a connection"))); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + +} + -- GitLab From 66b2c3b66e253ac3d8718c0c6d7c7551dbe04001 Mon Sep 17 00:00:00 2001 From: Manukumar V S Date: Fri, 4 Feb 2022 15:25:13 +0000 Subject: [PATCH 403/564] 8280948: [TESTBUG] Write a regression test for JDK-4659800 Reviewed-by: aivanov --- .../4659800/EnterKeyActivatesButton.java | 124 ++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 test/jdk/javax/swing/JButton/4659800/EnterKeyActivatesButton.java diff --git a/test/jdk/javax/swing/JButton/4659800/EnterKeyActivatesButton.java b/test/jdk/javax/swing/JButton/4659800/EnterKeyActivatesButton.java new file mode 100644 index 00000000000..9bbb794fdbe --- /dev/null +++ b/test/jdk/javax/swing/JButton/4659800/EnterKeyActivatesButton.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.event.KeyEvent; +import java.awt.Robot; +import java.util.Arrays; +import java.util.List; + +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; + +import static java.util.stream.Collectors.toList; + +/* + * @test + * @key headful + * @requires (os.family == "windows") + * @bug 4659800 + * @summary Check whether pressing key generates + * ActionEvent on focused Button or not. This is applicable only for + * WindowsLookAndFeel and WindowsClassicLookAndFeel. + * @run main EnterKeyActivatesButton + */ +public class EnterKeyActivatesButton { + private static volatile boolean buttonPressed; + private static JFrame frame; + + public static void main(String[] s) throws Exception { + runTest(); + } + + private static void setLookAndFeel(String lafName) { + try { + UIManager.setLookAndFeel(lafName); + } catch (UnsupportedLookAndFeelException ignored) { + System.out.println("Ignoring Unsupported L&F: " + lafName); + } catch (ClassNotFoundException | InstantiationException + | IllegalAccessException e) { + throw new RuntimeException(e); + } + } + + private static void disposeFrame() { + if (frame != null) { + frame.dispose(); + frame = null; + } + } + + private static void createUI() { + frame = new JFrame(); + JPanel panel = new JPanel(); + JButton focusedButton = new JButton("Button1"); + focusedButton.addActionListener(e -> buttonPressed = true); + panel.add(focusedButton); + panel.add(new JButton("Button2")); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.add(panel); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + focusedButton.requestFocusInWindow(); + } + + public static void runTest() throws Exception { + Robot robot = new Robot(); + robot.setAutoDelay(100); + // Consider only Windows and Windows Classic LnFs. + List winlafs = Arrays.stream(UIManager.getInstalledLookAndFeels()) + .filter(laf -> laf.getName().startsWith("Windows")) + .map(laf -> laf.getClassName()) + .collect(toList()); + + for (String laf : winlafs) { + try { + buttonPressed = false; + System.out.println("Testing L&F: " + laf); + SwingUtilities.invokeAndWait(() -> { + setLookAndFeel(laf); + createUI(); + }); + + robot.waitForIdle(); + robot.keyPress(KeyEvent.VK_ENTER); + robot.keyRelease(KeyEvent.VK_ENTER); + robot.waitForIdle(); + + if (buttonPressed) { + System.out.println("Test Passed for L&F: " + laf); + } else { + throw new RuntimeException("Test Failed, button not pressed for L&F: " + laf); + } + + } finally { + SwingUtilities.invokeAndWait(EnterKeyActivatesButton::disposeFrame); + } + } + + } +} -- GitLab From d4b99bc029771d29c2119a9b5f381cae3fe21ec1 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Fri, 4 Feb 2022 16:03:50 +0000 Subject: [PATCH 404/564] 8281120: G1: Rename G1BlockOffsetTablePart::alloc_block to update_for_block Reviewed-by: tschatzl, iwalulya, sjohanss --- src/hotspot/share/gc/g1/g1BlockOffsetTable.cpp | 10 +++++----- src/hotspot/share/gc/g1/g1BlockOffsetTable.hpp | 10 +++++----- src/hotspot/share/gc/g1/g1EvacFailure.cpp | 6 +++--- src/hotspot/share/gc/g1/g1FullGCCompactionPoint.cpp | 2 +- src/hotspot/share/gc/g1/heapRegion.cpp | 4 ++-- src/hotspot/share/gc/g1/heapRegion.hpp | 2 +- src/hotspot/share/gc/g1/heapRegion.inline.hpp | 2 +- 7 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1BlockOffsetTable.cpp b/src/hotspot/share/gc/g1/g1BlockOffsetTable.cpp index 7bbfe60e8a8..d5032957d78 100644 --- a/src/hotspot/share/gc/g1/g1BlockOffsetTable.cpp +++ b/src/hotspot/share/gc/g1/g1BlockOffsetTable.cpp @@ -87,7 +87,7 @@ void G1BlockOffsetTablePart::update() { while (next_addr < limit) { prev_addr = next_addr; next_addr = prev_addr + block_size(prev_addr); - alloc_block(prev_addr, next_addr); + update_for_block(prev_addr, next_addr); } assert(next_addr == limit, "Should stop the scan at the limit."); } @@ -212,8 +212,8 @@ void G1BlockOffsetTablePart::check_all_cards(size_t start_card, size_t end_card) // ( ^ ] // blk_start // -void G1BlockOffsetTablePart::alloc_block_work(HeapWord* blk_start, - HeapWord* blk_end) { +void G1BlockOffsetTablePart::update_for_block_work(HeapWord* blk_start, + HeapWord* blk_end) { HeapWord* const cur_card_boundary = align_up_by_card_size(blk_start); size_t const index = _bot->index_for_raw(cur_card_boundary); @@ -335,8 +335,8 @@ void G1BlockOffsetTablePart::print_on(outputStream* out) { #endif // !PRODUCT void G1BlockOffsetTablePart::set_for_starts_humongous(HeapWord* obj_top, size_t fill_size) { - alloc_block(_hr->bottom(), obj_top); + update_for_block(_hr->bottom(), obj_top); if (fill_size > 0) { - alloc_block(obj_top, fill_size); + update_for_block(obj_top, fill_size); } } diff --git a/src/hotspot/share/gc/g1/g1BlockOffsetTable.hpp b/src/hotspot/share/gc/g1/g1BlockOffsetTable.hpp index 04c966a29cc..b70435bf21d 100644 --- a/src/hotspot/share/gc/g1/g1BlockOffsetTable.hpp +++ b/src/hotspot/share/gc/g1/g1BlockOffsetTable.hpp @@ -138,7 +138,7 @@ private: const void* addr) const; // Update BOT entries corresponding to the mem range [blk_start, blk_end). - void alloc_block_work(HeapWord* blk_start, HeapWord* blk_end); + void update_for_block_work(HeapWord* blk_start, HeapWord* blk_end); void check_all_cards(size_t left_card, size_t right_card) const; @@ -168,14 +168,14 @@ public: // in a space covered by the table.) inline HeapWord* block_start(const void* addr); - void alloc_block(HeapWord* blk_start, HeapWord* blk_end) { + void update_for_block(HeapWord* blk_start, HeapWord* blk_end) { if (is_crossing_card_boundary(blk_start, blk_end)) { - alloc_block_work(blk_start, blk_end); + update_for_block_work(blk_start, blk_end); } } - void alloc_block(HeapWord* blk_start, size_t size) { - alloc_block(blk_start, blk_start + size); + void update_for_block(HeapWord* blk_start, size_t size) { + update_for_block(blk_start, blk_start + size); } void set_for_starts_humongous(HeapWord* obj_top, size_t fill_size); diff --git a/src/hotspot/share/gc/g1/g1EvacFailure.cpp b/src/hotspot/share/gc/g1/g1EvacFailure.cpp index 2a4f46ff16e..7d9dd4d7ead 100644 --- a/src/hotspot/share/gc/g1/g1EvacFailure.cpp +++ b/src/hotspot/share/gc/g1/g1EvacFailure.cpp @@ -98,7 +98,7 @@ public: HeapWord* obj_end = obj_addr + obj_size; _last_forwarded_object_end = obj_end; - _hr->alloc_block_in_bot(obj_addr, obj_end); + _hr->update_bot_for_block(obj_addr, obj_end); return obj_size; } @@ -116,13 +116,13 @@ public: CollectedHeap::fill_with_objects(start, gap_size); HeapWord* end_first_obj = start + cast_to_oop(start)->size(); - _hr->alloc_block_in_bot(start, end_first_obj); + _hr->update_bot_for_block(start, end_first_obj); // Fill_with_objects() may have created multiple (i.e. two) // objects, as the max_fill_size() is half a region. // After updating the BOT for the first object, also update the // BOT for the second object to make the BOT complete. if (end_first_obj != end) { - _hr->alloc_block_in_bot(end_first_obj, end); + _hr->update_bot_for_block(end_first_obj, end); #ifdef ASSERT size_t size_second_obj = cast_to_oop(end_first_obj)->size(); HeapWord* end_of_second_obj = end_first_obj + size_second_obj; diff --git a/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.cpp b/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.cpp index 0e7543ec63d..195707424c3 100644 --- a/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.cpp +++ b/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.cpp @@ -107,7 +107,7 @@ void G1FullGCCompactionPoint::forward(oop object, size_t size) { // Update compaction values. _compaction_top += size; - _current_region->alloc_block_in_bot(_compaction_top - size, _compaction_top); + _current_region->update_bot_for_block(_compaction_top - size, _compaction_top); } void G1FullGCCompactionPoint::add(HeapRegion* hr) { diff --git a/src/hotspot/share/gc/g1/heapRegion.cpp b/src/hotspot/share/gc/g1/heapRegion.cpp index 93baa238351..3fc709bba94 100644 --- a/src/hotspot/share/gc/g1/heapRegion.cpp +++ b/src/hotspot/share/gc/g1/heapRegion.cpp @@ -787,8 +787,8 @@ void HeapRegion::mangle_unused_area() { } #endif -void HeapRegion::alloc_block_in_bot(HeapWord* start, HeapWord* end) { - _bot_part.alloc_block(start, end); +void HeapRegion::update_bot_for_block(HeapWord* start, HeapWord* end) { + _bot_part.update_for_block(start, end); } void HeapRegion::object_iterate(ObjectClosure* blk) { diff --git a/src/hotspot/share/gc/g1/heapRegion.hpp b/src/hotspot/share/gc/g1/heapRegion.hpp index d3af9faf9c7..dbca49f93c4 100644 --- a/src/hotspot/share/gc/g1/heapRegion.hpp +++ b/src/hotspot/share/gc/g1/heapRegion.hpp @@ -167,7 +167,7 @@ public: // Full GC support methods. - void alloc_block_in_bot(HeapWord* start, HeapWord* end); + void update_bot_for_block(HeapWord* start, HeapWord* end); // Update heap region that has been compacted to be consistent after Full GC. void reset_compacted_after_full_gc(); diff --git a/src/hotspot/share/gc/g1/heapRegion.inline.hpp b/src/hotspot/share/gc/g1/heapRegion.inline.hpp index 2f78f30b419..3d61cc1620a 100644 --- a/src/hotspot/share/gc/g1/heapRegion.inline.hpp +++ b/src/hotspot/share/gc/g1/heapRegion.inline.hpp @@ -237,7 +237,7 @@ inline void HeapRegion::update_bot_for_obj(HeapWord* obj_start, size_t obj_size) HR_FORMAT_PARAMS(this), p2i(obj_start), p2i(obj_end)); - _bot_part.alloc_block(obj_start, obj_end); + _bot_part.update_for_block(obj_start, obj_end); } inline void HeapRegion::note_start_of_marking() { -- GitLab From f5d6fddc6df8c5c5456a2544b131833d5227292b Mon Sep 17 00:00:00 2001 From: "Daniel D. Daugherty" Date: Fri, 4 Feb 2022 17:37:01 +0000 Subject: [PATCH 405/564] 8280476: [macOS] : hotspot arm64 bug exposed by latest clang Reviewed-by: kbarrett, adinn --- src/hotspot/cpu/aarch64/immediate_aarch64.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/hotspot/cpu/aarch64/immediate_aarch64.cpp b/src/hotspot/cpu/aarch64/immediate_aarch64.cpp index 3e38b7cca04..916494605bc 100644 --- a/src/hotspot/cpu/aarch64/immediate_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/immediate_aarch64.cpp @@ -129,8 +129,17 @@ static inline uint32_t uimm(uint32_t val, int hi, int lo) uint64_t replicate(uint64_t bits, int nbits, int count) { + assert(count > 0, "must be"); + assert(nbits > 0, "must be"); + assert(count * nbits <= 64, "must be"); + + // Special case nbits == 64 since the shift below with that nbits value + // would result in undefined behavior. + if (nbits == 64) { + return bits; + } + uint64_t result = 0; - // nbits may be 64 in which case we want mask to be -1 uint64_t mask = ones(nbits); for (int i = 0; i < count ; i++) { result <<= nbits; -- GitLab From 8e4ef818a90de35ae75e7f82a780653d623bb29c Mon Sep 17 00:00:00 2001 From: Yumin Qi Date: Fri, 4 Feb 2022 19:20:22 +0000 Subject: [PATCH 406/564] 8280767: -XX:ArchiveClassesAtExit does not archive BoundMethodHandle$Species classes Reviewed-by: iklam, ccheung --- src/hotspot/share/cds/lambdaFormInvokers.cpp | 27 ++++--- src/hotspot/share/cds/lambdaFormInvokers.hpp | 3 +- .../classfile/systemDictionaryShared.cpp | 7 +- src/hotspot/share/oops/klass.hpp | 10 ++- src/hotspot/share/prims/jvm.cpp | 4 +- .../dynamicArchive/CDSLambdaInvoker.java | 58 +++++++++++++++ .../dynamicArchive/TestLambdaInvokers.java | 73 +++++++++++++++++++ 7 files changed, 167 insertions(+), 15 deletions(-) create mode 100644 test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/CDSLambdaInvoker.java create mode 100644 test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestLambdaInvokers.java diff --git a/src/hotspot/share/cds/lambdaFormInvokers.cpp b/src/hotspot/share/cds/lambdaFormInvokers.cpp index 59666085d04..bf49f94b682 100644 --- a/src/hotspot/share/cds/lambdaFormInvokers.cpp +++ b/src/hotspot/share/cds/lambdaFormInvokers.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, 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 @@ -67,12 +67,6 @@ static bool should_be_archived(char* line) { } return false; } - -void LambdaFormInvokers::append_filtered(char* line) { - if (should_be_archived(line)) { - append(line); - } -} #undef NUM_FILTER void LambdaFormInvokers::append(char* line) { @@ -180,6 +174,15 @@ void LambdaFormInvokers::regenerate_holder_classes(TRAPS) { } } +// check if a class name is a species +bool is_a_species(const char* species_name) { + log_info(cds)("Checking class %s", species_name); + if (strstr(species_name, "java/lang/invoke/BoundMethodHandle$Species_") != nullptr) { + return true; + } + return false; +} + void LambdaFormInvokers::regenerate_class(char* name, ClassFileStream& st, TRAPS) { Symbol* class_name = SymbolTable::new_symbol((const char*)name); // the class must exist @@ -188,6 +191,12 @@ void LambdaFormInvokers::regenerate_class(char* name, ClassFileStream& st, TRAPS log_info(cds)("Class %s not present, skip", name); return; } + // the species is shared in base archive, skip it. + if (klass->is_regenerated() && is_a_species(name)) { + log_info(cds)("Skip regenerating for shared %s", name); + return; + } + assert(klass->is_instance_klass(), "Should be"); ClassLoaderData* cld = ClassLoaderData::the_null_class_loader_data(); @@ -211,8 +220,8 @@ void LambdaFormInvokers::regenerate_class(char* name, ClassFileStream& st, TRAPS MetaspaceShared::try_link_class(THREAD, result); assert(!HAS_PENDING_EXCEPTION, "Invariant"); - // exclude the existing class from dump - SystemDictionaryShared::set_excluded(InstanceKlass::cast(klass)); + result->set_regenerated(); // mark for regenerated + SystemDictionaryShared::set_excluded(InstanceKlass::cast(klass)); // exclude the existing class from dump SystemDictionaryShared::init_dumptime_info(result); log_info(cds, lambda)("Regenerated class %s, old: " INTPTR_FORMAT " new: " INTPTR_FORMAT, name, p2i(klass), p2i(result)); diff --git a/src/hotspot/share/cds/lambdaFormInvokers.hpp b/src/hotspot/share/cds/lambdaFormInvokers.hpp index c3b151790f1..9463427eeca 100644 --- a/src/hotspot/share/cds/lambdaFormInvokers.hpp +++ b/src/hotspot/share/cds/lambdaFormInvokers.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, 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 @@ -43,7 +43,6 @@ class LambdaFormInvokers : public AllStatic { static void add_regenerated_class(oop regenerated_class); public: static void append(char* line); - static void append_filtered(char* line); static void dump_static_archive_invokers(); static void read_static_archive_invokers(); static void regenerate_holder_classes(TRAPS); diff --git a/src/hotspot/share/classfile/systemDictionaryShared.cpp b/src/hotspot/share/classfile/systemDictionaryShared.cpp index 6272503fe93..29b01851ac8 100644 --- a/src/hotspot/share/classfile/systemDictionaryShared.cpp +++ b/src/hotspot/share/classfile/systemDictionaryShared.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2022, 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 @@ -1415,6 +1415,11 @@ InstanceKlass* SystemDictionaryShared::find_builtin_class(Symbol* name) { if (record != NULL) { assert(!record->_klass->is_hidden(), "hidden class cannot be looked up by name"); assert(check_alignment(record->_klass), "Address not aligned"); + // We did not save the classfile data of the regenerated LambdaForm invoker classes, + // so we cannot support CLFH for such classes. + if (record->_klass->is_regenerated() && JvmtiExport::should_post_class_file_load_hook()) { + return NULL; + } return record->_klass; } else { return NULL; diff --git a/src/hotspot/share/oops/klass.hpp b/src/hotspot/share/oops/klass.hpp index 7bbff72e25a..24f7df02cc8 100644 --- a/src/hotspot/share/oops/klass.hpp +++ b/src/hotspot/share/oops/klass.hpp @@ -175,7 +175,8 @@ private: enum { _archived_lambda_proxy_is_available = 2, _has_value_based_class_annotation = 4, - _verified_at_dump_time = 8 + _verified_at_dump_time = 8, + _regenerated = 16 }; #endif @@ -339,6 +340,13 @@ protected: NOT_CDS(return false;) } + void set_regenerated() { + CDS_ONLY(_shared_class_flags |= _regenerated;) + } + bool is_regenerated() const { + CDS_ONLY(return (_shared_class_flags & _regenerated) != 0;) + NOT_CDS(return false;) + } // Obtain the module or package for this class virtual ModuleEntry* module() const = 0; diff --git a/src/hotspot/share/prims/jvm.cpp b/src/hotspot/share/prims/jvm.cpp index 4f54235cd4d..d8a5a025b9d 100644 --- a/src/hotspot/share/prims/jvm.cpp +++ b/src/hotspot/share/prims/jvm.cpp @@ -3689,9 +3689,9 @@ JVM_ENTRY(void, JVM_LogLambdaFormInvoker(JNIEnv *env, jstring line)) Handle h_line (THREAD, JNIHandles::resolve_non_null(line)); char* c_line = java_lang_String::as_utf8_string(h_line()); if (DynamicDumpSharedSpaces) { - // Note: LambdaFormInvokers::append_filtered and LambdaFormInvokers::append take same format which is not + // Note: LambdaFormInvokers::append take same format which is not // same as below the print format. The line does not include LAMBDA_FORM_TAG. - LambdaFormInvokers::append_filtered(os::strdup((const char*)c_line, mtInternal)); + LambdaFormInvokers::append(os::strdup((const char*)c_line, mtInternal)); } if (ClassListWriter::is_enabled()) { ClassListWriter w; diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/CDSLambdaInvoker.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/CDSLambdaInvoker.java new file mode 100644 index 00000000000..ae0772427d4 --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/CDSLambdaInvoker.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2022, 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.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; + +public class CDSLambdaInvoker { + public static void main(String args[]) throws Throwable { + invoke(MethodHandles.identity(double.class), 1.0); + invoke(MethodHandles.identity(long.class), 1); + invoke(MethodHandles.identity(int.class), 1); + invoke(MethodHandles.identity(float.class), 1.0f); + + MethodHandles.Lookup lookup = MethodHandles.lookup(); + MethodType mt = MethodType.methodType(void.class, float.class, double.class, int.class, + boolean.class, Object.class, long.class, double.class); + MethodHandle mh = lookup.findStatic(CDSLambdaInvoker.class, "callme", mt); + mh.invokeExact(4.0f, 5.0, 6, true, (Object)args, 7L, 8.0); + } + + private static Object invoke(MethodHandle mh, Object ... args) throws Throwable { + try { + for (Object o : args) { + mh = MethodHandles.insertArguments(mh, 0, o); + } + return mh.invoke(); + } catch (Throwable t) { + System.out.println("Failed to find, link and/or invoke " + mh.toString() + ": " + t.getMessage()); + throw t; + } + } + + private static void callme(float f, double d, int i, boolean b, Object o, long l, double d2) { + + } +} diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestLambdaInvokers.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestLambdaInvokers.java new file mode 100644 index 00000000000..69a8d4219e2 --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestLambdaInvokers.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2022, 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 + * @key randomness + * @summary test archive lambda invoker species type in dynamic dump + * @bug 8280767 + * @requires vm.cds + * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds /test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive + * @compile CDSLambdaInvoker.java + * @build sun.hotspot.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar cds-test.jar CDSLambdaInvoker + * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. TestLambdaInvokers + */ + +public class TestLambdaInvokers extends DynamicArchiveTestBase { + private static final String mainClass = "CDSLambdaInvoker"; + private static final String jarFile = "cds-test.jar"; + private static void doTest(String topArchiveName) throws Exception { + dump(topArchiveName, + "-Xlog:cds", + "-Xlog:cds+dynamic=debug", + "-cp", + jarFile, + mainClass) + .assertNormalExit(output -> { + output.shouldContain("Skip regenerating for shared"); + }); + run(topArchiveName, + "-Xlog:cds", + "-Xlog:cds+dynamic=debug", + "-Xlog:class+load", + "-cp", + jarFile, + mainClass) + .assertNormalExit(output -> { + // java.lang.invoke.BoundMethodHandle$Species_JL is generated from CDSLambdaInvoker + output.shouldContain("java.lang.invoke.BoundMethodHandle$Species_JL source: shared objects file (top)"); + }); + } + + static void testWithDefaultBase() throws Exception { + String topArchiveName = getNewArchiveName("top"); + doTest(topArchiveName); + } + + public static void main(String[] args) throws Exception { + runTest(TestLambdaInvokers::testWithDefaultBase); + } +} -- GitLab From 48523b090886f7b24ed4009f0c150efaa6f7b056 Mon Sep 17 00:00:00 2001 From: Kevin Walls Date: Fri, 4 Feb 2022 21:23:58 +0000 Subject: [PATCH 407/564] 8281049: man page update for jstatd Security Manager dependency removal Reviewed-by: cjplummer --- src/jdk.jstatd/share/man/jstatd.1 | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/src/jdk.jstatd/share/man/jstatd.1 b/src/jdk.jstatd/share/man/jstatd.1 index d13f06b59b1..d5181f3668c 100644 --- a/src/jdk.jstatd/share/man/jstatd.1 +++ b/src/jdk.jstatd/share/man/jstatd.1 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. +.\" Copyright (c) 2004, 2022, 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,15 +120,12 @@ local security policies should be considered before you start the \f[CB]jstatd\f[R] process, particularly in production environments or on networks that aren\[aq]t secure. .PP -The \f[CB]jstatd\f[R] server installs an instance of -\f[CB]RMISecurityPolicy\f[R] when no other security manager is installed, -and therefore, requires a security policy file to be specified. -The policy file must conform to Default Policy Implementation and Policy -File Syntax. +For security purposes, the \f[CB]jstatd\f[R] server uses an RMI +ObjectInputFilter to allow only essential classes to be deserialized. .PP -If your security concerns can\[aq]t be addressed with a customized -policy file, then the safest action is to not run the \f[CB]jstatd\f[R] -server and use the \f[CB]jstat\f[R] and \f[CB]jps\f[R] tools locally. +If your security concerns can\[aq]t be addressed, then the safest action +is to not run the \f[CB]jstatd\f[R] server and use the \f[CB]jstat\f[R] and +\f[CB]jps\f[R] tools locally. However, when using \f[CB]jps\f[R] to get a list of instrumented JVMs, the list will not include any JVMs running in docker containers. .SH REMOTE INTERFACE @@ -149,7 +146,7 @@ This example assumes that no other server is bound to the default RMI registry port (port \f[CB]1099\f[R]). .RS .PP -\f[CB]jstatd\ \-J\-Djava.security.policy=all.policy\f[R] +\f[CB]jstatd\f[R] .RE .SH EXTERNAL RMI REGISTRY .PP @@ -159,7 +156,7 @@ registry. .nf \f[CB] rmiregistry& -jstatd\ \-J\-Djava.security.policy=all.policy +jstatd \f[R] .fi .PP @@ -169,7 +166,7 @@ registry server on port \f[CB]2020\f[R]. .nf \f[CB] jrmiregistry\ 2020& -jstatd\ \-J\-Djava.security.policy=all.policy\ \-p\ 2020 +jstatd\ \-p\ 2020 \f[R] .fi .PP @@ -180,7 +177,7 @@ registry server on port \f[CB]2020\f[R] and JMX connector bound to port .nf \f[CB] jrmiregistry\ 2020& -jstatd\ \-J\-Djava.security.policy=all.policy\ \-p\ 2020\ \-r\ 2021 +jstatd\ \-p\ 2020\ \-r\ 2021 \f[R] .fi .PP @@ -191,7 +188,7 @@ registry on port 2020 that\[aq]s bound to .nf \f[CB] rmiregistry\ 2020& -jstatd\ \-J\-Djava.security.policy=all.policy\ \-p\ 2020\ \-n\ AlternateJstatdServerName +jstatd\ \-p\ 2020\ \-n\ AlternateJstatdServerName \f[R] .fi .SH STOP THE CREATION OF AN IN\-PROCESS RMI REGISTRY @@ -203,7 +200,7 @@ If an RMI registry isn\[aq]t running, then an error message is displayed. .RS .PP -\f[CB]jstatd\ \-J\-Djava.security.policy=all.policy\ \-nr\f[R] +\f[CB]jstatd\ \-nr\f[R] .RE .SH ENABLE RMI LOGGING .PP @@ -213,5 +210,5 @@ This technique is useful as a troubleshooting aid or for monitoring server activities. .RS .PP -\f[CB]jstatd\ \-J\-Djava.security.policy=all.policy\ \-J\-Djava.rmi.server.logCalls=true\f[R] +\f[CB]jstatd\ \-J\-Djava.rmi.server.logCalls=true\f[R] .RE -- GitLab From 42e272e181f188c89fa88f144715f19235943fca Mon Sep 17 00:00:00 2001 From: Xue-Lei Andrew Fan Date: Sat, 5 Feb 2022 07:44:57 +0000 Subject: [PATCH 408/564] 8281289: Improve with List.copyOf Reviewed-by: jnimeh, hchao --- .../share/classes/javax/net/ssl/SSLParameters.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/java.base/share/classes/javax/net/ssl/SSLParameters.java b/src/java.base/share/classes/javax/net/ssl/SSLParameters.java index 83b83c84270..5fbf52436a5 100644 --- a/src/java.base/share/classes/javax/net/ssl/SSLParameters.java +++ b/src/java.base/share/classes/javax/net/ssl/SSLParameters.java @@ -29,7 +29,6 @@ import java.security.AlgorithmConstraints; import java.util.Map; import java.util.List; import java.util.HashMap; -import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.LinkedHashMap; @@ -391,8 +390,7 @@ public class SSLParameters { public final List getServerNames() { if (sniNames != null) { if (!sniNames.isEmpty()) { - return Collections.unmodifiableList( - new ArrayList<>(sniNames.values())); + return List.copyOf(sniNames.values()); } else { return Collections.emptyList(); } @@ -466,8 +464,7 @@ public class SSLParameters { public final Collection getSNIMatchers() { if (sniMatchers != null) { if (!sniMatchers.isEmpty()) { - return Collections.unmodifiableList( - new ArrayList<>(sniMatchers.values())); + return List.copyOf(sniMatchers.values()); } else { return Collections.emptyList(); } -- GitLab From 77b0240d44fd356711d75bc241e198f6f89ada8f Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Sun, 6 Feb 2022 02:19:32 +0000 Subject: [PATCH 409/564] 8281183: RandomGenerator:NextDouble() default behavior partially fixed by JDK-8280950 Reviewed-by: jlaskey --- .../classes/jdk/internal/util/random/RandomSupport.java | 2 +- test/jdk/java/util/Random/RandomNextDoubleBoundary.java | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/java.base/share/classes/jdk/internal/util/random/RandomSupport.java b/src/java.base/share/classes/jdk/internal/util/random/RandomSupport.java index 14fe0d3906d..1fc1eeff46a 100644 --- a/src/java.base/share/classes/jdk/internal/util/random/RandomSupport.java +++ b/src/java.base/share/classes/jdk/internal/util/random/RandomSupport.java @@ -677,7 +677,7 @@ public class RandomSupport { double r = rng.nextDouble(); r = r * bound; if (r >= bound) // may need to correct a rounding problem - r = Math.nextDown(r); + r = Math.nextDown(bound); return r; } diff --git a/test/jdk/java/util/Random/RandomNextDoubleBoundary.java b/test/jdk/java/util/Random/RandomNextDoubleBoundary.java index 971b22d55c1..f913d22ab02 100644 --- a/test/jdk/java/util/Random/RandomNextDoubleBoundary.java +++ b/test/jdk/java/util/Random/RandomNextDoubleBoundary.java @@ -24,7 +24,7 @@ /* * @test * @summary Verify nextDouble stays within range - * @bug 8280550 8280950 + * @bug 8280550 8280950 8281183 */ import java.util.SplittableRandom; @@ -79,8 +79,11 @@ public class RandomNextDoubleBoundary { }; double value = rg.nextDouble(origin, bound); - assertTrue(value >= origin); - assertTrue(value < bound); + if (bound > 0) { + value = rg.nextDouble(bound); // Equivalent to nextDouble(0.0, bound) + assertTrue(value >= 0.0); + assertTrue(value < bound); + } } public static void assertTrue(boolean condition) { -- GitLab From f7814c120bf84d7e9b459f81a6ce19b44fa122ec Mon Sep 17 00:00:00 2001 From: Toshio Nakamura Date: Sun, 6 Feb 2022 18:39:44 +0000 Subject: [PATCH 410/564] 8139173: [macosx] JInternalFrame shadow is not properly drawn Reviewed-by: prr, serb --- .../apple/laf/AquaInternalFrameBorder.java | 6 +- .../plaf/aqua/JInternalFrameBorderTest.java | 143 ++++++++++++++++++ 2 files changed, 145 insertions(+), 4 deletions(-) create mode 100644 test/jdk/javax/swing/plaf/aqua/JInternalFrameBorderTest.java diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameBorder.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameBorder.java index a5165710ea7..74697ed417b 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameBorder.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameBorder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2022, 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 @@ -378,9 +378,7 @@ public class AquaInternalFrameBorder implements Border, UIResource { final int x = inX; final int y = inY; final int w = inW; - int h = inH; - - h = metrics.titleBarHeight + inH; + final int h = inH; // paint the background titleBarPainter.state.set(frame.isSelected() ? State.ACTIVE : State.INACTIVE); diff --git a/test/jdk/javax/swing/plaf/aqua/JInternalFrameBorderTest.java b/test/jdk/javax/swing/plaf/aqua/JInternalFrameBorderTest.java new file mode 100644 index 00000000000..ef6c517fe3c --- /dev/null +++ b/test/jdk/javax/swing/plaf/aqua/JInternalFrameBorderTest.java @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2022, 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 + * @key headful + * @bug 8139173 + * @requires (os.family == "mac") + * @summary Verify JInternalFrame's border + * @run main JInternalFrameBorderTest + */ + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import javax.swing.JDesktopPane; +import javax.swing.JFrame; +import javax.swing.JInternalFrame; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; + +public class JInternalFrameBorderTest { + + private static JFrame frame; + private static JDesktopPane desktopPane; + private static JInternalFrame internalFrame; + private static final int LIMIT = 100; + private static Robot robot; + private static Point pos; + private static Rectangle rect; + private static Insets insets; + + public static void main(String[] args) throws Exception { + robot = new Robot(); + createUI(); + robot.waitForIdle(); + robot.delay(1000); + + SwingUtilities.invokeAndWait(() -> { + pos = internalFrame.getLocationOnScreen(); + rect = internalFrame.getBounds(); + insets = internalFrame.getInsets(); + }); + robot.waitForIdle(); + + // bottom + int x = pos.x + rect.x + rect.width/2; + int y = pos.y + rect.y + rect.height - insets.bottom + 1; + Color colorBottom = robot.getPixelColor(x, y); + + // left + x = pos.x + rect.x + insets.left - 1; + y = pos.y + rect.y + rect.height/2; + Color colorLeft = robot.getPixelColor(x, y); + + // right + x = pos.x + rect.x + rect.width - insets.left + 1; + y = pos.y + rect.y + rect.height/2; + Color colorRight = robot.getPixelColor(x, y); + + robot.waitForIdle(); + cleanUp(); + + int diff = getDiff(colorLeft, colorBottom); + if (diff > LIMIT) { + throw new RuntimeException("Unexpected border bottom=" + + colorBottom + " left=" + colorLeft); + } + diff = getDiff(colorRight, colorBottom); + if (diff > LIMIT) { + throw new RuntimeException("Unexpected border bottom=" + + colorBottom + " right=" + colorRight); + } + } + + private static void createUI() throws Exception { + SwingUtilities.invokeAndWait(() -> { + try { + UIManager.setLookAndFeel("com.apple.laf.AquaLookAndFeel"); + } catch (Exception e) { + throw new RuntimeException("Cannot initialize Aqua L&F"); + } + desktopPane = new JDesktopPane() { + @Override + protected void paintComponent(Graphics g) { + super.paintComponent(g); + g.setColor(Color.BLUE); + g.fillRect(0, 0, getWidth(), getHeight()); + } + }; + internalFrame = new JInternalFrame(); + frame = new JFrame(); + internalFrame.setSize(500, 200); + internalFrame.setVisible(true); + desktopPane.add(internalFrame); + + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.getContentPane().setLayout(new BorderLayout()); + frame.getContentPane().add(desktopPane, "Center"); + frame.setSize(500, 500); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + frame.toFront(); + }); + } + + private static int getDiff(Color c1, Color c2) { + int r = Math.abs(c1.getRed() - c2.getRed()); + int g = Math.abs(c1.getGreen() - c2.getGreen()); + int b = Math.abs(c1.getBlue() - c2.getBlue()); + return r + g + b; + } + + private static void cleanUp() throws Exception { + SwingUtilities.invokeAndWait(() -> { + frame.dispose(); + }); + } +} -- GitLab From 2f48a3f032dcfe159a7ab4a3d0afd0a0760d0a04 Mon Sep 17 00:00:00 2001 From: Phil Race Date: Sun, 6 Feb 2022 21:13:17 +0000 Subject: [PATCH 411/564] 8279878: java/awt/font/JNICheck/JNICheck.sh test fails on Ubuntu 21.10 Reviewed-by: serb --- test/jdk/java/awt/font/JNICheck/JNICheck.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/jdk/java/awt/font/JNICheck/JNICheck.sh b/test/jdk/java/awt/font/JNICheck/JNICheck.sh index 4244b510b23..cc019e72d56 100644 --- a/test/jdk/java/awt/font/JNICheck/JNICheck.sh +++ b/test/jdk/java/awt/font/JNICheck/JNICheck.sh @@ -49,7 +49,7 @@ else fi $JAVA_HOME/bin/java ${TESTVMOPTS} \ - -cp "${CP}" -Xcheck:jni JNICheck | grep -v SIG | grep -v Signal | grep -v CallStatic > "${CP}"/log.txt + -cp "${CP}" -Xcheck:jni JNICheck | grep -v SIG | grep -v Signal | grep -v Handler | grep -v jsig | grep -v CallStatic > "${CP}"/log.txt # any messages logged may indicate a failure. if [ -s "${CP}"/log.txt ]; then -- GitLab From 5dfff7406ef3dc37a77ce9545f6f56c49b41e466 Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Mon, 7 Feb 2022 04:48:02 +0000 Subject: [PATCH 412/564] 8166050: partialArray is not created in javax.swing.text.html.parser.NPrintWriter.println(...) method Reviewed-by: prr --- .../swing/text/html/parser/TagStack.java | 40 ------------------- 1 file changed, 40 deletions(-) diff --git a/src/java.desktop/share/classes/javax/swing/text/html/parser/TagStack.java b/src/java.desktop/share/classes/javax/swing/text/html/parser/TagStack.java index e9f7dfcd0e9..ab33370b14b 100644 --- a/src/java.desktop/share/classes/javax/swing/text/html/parser/TagStack.java +++ b/src/java.desktop/share/classes/javax/swing/text/html/parser/TagStack.java @@ -162,43 +162,3 @@ class TagStack implements DTDConstants { next + " <" + tag.getElement().getName() + ">"; } } - -class NPrintWriter extends PrintWriter { - - private int numLines = 5; - private int numPrinted = 0; - - public NPrintWriter (int numberOfLines) { - super(System.out); - numLines = numberOfLines; - } - - public void println(char[] array) { - if (numPrinted >= numLines) { - return; - } - - char[] partialArray = null; - - for (int i = 0; i < array.length; i++) { - if (array[i] == '\n') { - numPrinted++; - } - - if (numPrinted == numLines) { - System.arraycopy(array, 0, partialArray, 0, i); - } - } - - if (partialArray != null) { - super.print(partialArray); - } - - if (numPrinted == numLines) { - return; - } - - super.println(array); - numPrinted++; - } -} -- GitLab From f2302822c0ef30fbf7cb4e31b8dc1513e9413a23 Mon Sep 17 00:00:00 2001 From: Xue-Lei Andrew Fan Date: Mon, 7 Feb 2022 06:30:10 +0000 Subject: [PATCH 413/564] 8281298: Revise the creation of unmodifiable list Reviewed-by: redestad --- .../classes/javax/net/ssl/SSLParameters.java | 99 +++++++++---------- 1 file changed, 46 insertions(+), 53 deletions(-) diff --git a/src/java.base/share/classes/javax/net/ssl/SSLParameters.java b/src/java.base/share/classes/javax/net/ssl/SSLParameters.java index 5fbf52436a5..5926c48aed0 100644 --- a/src/java.base/share/classes/javax/net/ssl/SSLParameters.java +++ b/src/java.base/share/classes/javax/net/ssl/SSLParameters.java @@ -26,12 +26,7 @@ package javax.net.ssl; import java.security.AlgorithmConstraints; -import java.util.Map; -import java.util.List; -import java.util.HashMap; -import java.util.Collection; -import java.util.Collections; -import java.util.LinkedHashMap; +import java.util.*; /** * Encapsulates parameters for an SSL/TLS/DTLS connection. The parameters @@ -81,8 +76,8 @@ public class SSLParameters { private boolean needClientAuth; private String identificationAlgorithm; private AlgorithmConstraints algorithmConstraints; - private Map sniNames = null; - private Map sniMatchers = null; + private List sniNames = null; // immutable list + private Collection sniMatchers = null; // immutable collection private boolean preferLocalCipherSuites; private boolean enableRetransmissions = true; private int maximumPacketSize = 0; @@ -331,22 +326,29 @@ public class SSLParameters { * @since 1.8 */ public final void setServerNames(List serverNames) { - if (serverNames != null) { - if (!serverNames.isEmpty()) { - sniNames = new LinkedHashMap<>(serverNames.size()); - for (SNIServerName serverName : serverNames) { - if (sniNames.put(serverName.getType(), - serverName) != null) { - throw new IllegalArgumentException( - "Duplicated server name of type " + + if (this.sniNames == serverNames) { + return; + } + + if (serverNames == null) { + sniNames = null; + } else if (serverNames.isEmpty()) { + sniNames = Collections.emptyList(); + } else { + List sniTypes = new ArrayList<>(serverNames.size()); + List sniValues = new ArrayList<>(serverNames.size()); + for (SNIServerName serverName : serverNames) { + if (sniTypes.contains(serverName.getType())) { + throw new IllegalArgumentException( + "Duplicated server name of type " + serverName.getType()); - } + } else { + sniTypes.add(serverName.getType()); + sniValues.add(serverName); } - } else { - sniNames = Collections.emptyMap(); } - } else { - sniNames = null; + + sniNames = Collections.unmodifiableList(sniValues); } } @@ -388,15 +390,7 @@ public class SSLParameters { * @since 1.8 */ public final List getServerNames() { - if (sniNames != null) { - if (!sniNames.isEmpty()) { - return List.copyOf(sniNames.values()); - } else { - return Collections.emptyList(); - } - } - - return null; + return sniNames; } /** @@ -424,22 +418,29 @@ public class SSLParameters { * @since 1.8 */ public final void setSNIMatchers(Collection matchers) { - if (matchers != null) { - if (!matchers.isEmpty()) { - sniMatchers = new HashMap<>(matchers.size()); - for (SNIMatcher matcher : matchers) { - if (sniMatchers.put(matcher.getType(), - matcher) != null) { - throw new IllegalArgumentException( - "Duplicated server name of type " + - matcher.getType()); - } + if (this.sniMatchers == matchers) { + return; + } + + if (matchers == null) { + this.sniMatchers = null; + } else if (matchers.isEmpty()) { + sniMatchers = Collections.emptyList(); + } else { + List matcherTypes = new ArrayList<>(matchers.size()); + List matcherValues = new ArrayList<>(matchers.size()); + for (SNIMatcher matcher : matchers) { + if (matcherTypes.contains(matcher.getType())) { + throw new IllegalArgumentException( + "Duplicated server name of type " + + matcher.getType()); + } else { + matcherTypes.add(matcher.getType()); + matcherValues.add(matcher); } - } else { - sniMatchers = Collections.emptyMap(); } - } else { - sniMatchers = null; + + this.sniMatchers = Collections.unmodifiableList(matcherValues); } } @@ -462,15 +463,7 @@ public class SSLParameters { * @since 1.8 */ public final Collection getSNIMatchers() { - if (sniMatchers != null) { - if (!sniMatchers.isEmpty()) { - return List.copyOf(sniMatchers.values()); - } else { - return Collections.emptyList(); - } - } - - return null; + return sniMatchers; } /** -- GitLab From f5e0870091ad9534e7a3dd08ef2e3ee7cd781c6d Mon Sep 17 00:00:00 2001 From: Emanuel Peter Date: Mon, 7 Feb 2022 08:18:07 +0000 Subject: [PATCH 414/564] 8281117: Add regression test for JDK-8280587 Reviewed-by: chagedorn, thartmann, xliu --- .../TestCastIIMakesMainLoopPhiDead2.java | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 test/hotspot/jtreg/compiler/loopopts/TestCastIIMakesMainLoopPhiDead2.java diff --git a/test/hotspot/jtreg/compiler/loopopts/TestCastIIMakesMainLoopPhiDead2.java b/test/hotspot/jtreg/compiler/loopopts/TestCastIIMakesMainLoopPhiDead2.java new file mode 100644 index 00000000000..1aa233abe5f --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/TestCastIIMakesMainLoopPhiDead2.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2022, 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 8280600 + * @summary C2: assert(!had_error) failed: bad dominance + * @run main/othervm -Xcomp -XX:CompileOnly=TestCastIIMakesMainLoopPhiDead2 TestCastIIMakesMainLoopPhiDead2 + */ + +public class TestCastIIMakesMainLoopPhiDead2 { + static int zero = 0; + + public static void main(String[] args) { + for (int i = 0; i < 100000; i++) { + test(); + } + } + + static void test() { + int h[] = new int[zero]; + for (int m = 0; m < 5; m++) { + try { + for (int f = -400; f < 1; f++) { + h[f] = 1; // Out of bounds store. + } + } catch (ArrayIndexOutOfBoundsException i) { + // Expected + } + } + } +} + + -- GitLab From 95fd9d20f329b15d68e613ec7f932254715e9130 Mon Sep 17 00:00:00 2001 From: Alex Menkov Date: Mon, 7 Feb 2022 09:08:34 +0000 Subject: [PATCH 415/564] 8281243: Test java/lang/instrument/RetransformWithMethodParametersTest.java is failing Reviewed-by: sspitsyn, dcubed, lmesnik --- .../RetransformWithMethodParametersTest.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/test/jdk/java/lang/instrument/RetransformWithMethodParametersTest.java b/test/jdk/java/lang/instrument/RetransformWithMethodParametersTest.java index ef7e3818eb0..74be14f33cf 100644 --- a/test/jdk/java/lang/instrument/RetransformWithMethodParametersTest.java +++ b/test/jdk/java/lang/instrument/RetransformWithMethodParametersTest.java @@ -35,7 +35,7 @@ import java.io.File; import java.io.FileOutputStream; import java.lang.instrument.ClassFileTransformer; -import java.lang.reflect.Method; +import java.lang.reflect.Executable; import java.lang.reflect.Parameter; import java.nio.file.Files; import java.nio.file.Paths; @@ -59,7 +59,8 @@ import jdk.test.lib.util.ClassTransformer; class MethodParametersTarget { // The class contains the only method, so we don't have issue with method sorting // and ClassFileReconstituter should restore the same bytes as original classbytes. - public void method1( + // This method should be ctor, otherwise default ctor will be implicitly declared. + public MethodParametersTarget( int intParam1, String stringParam1 // @1 commentout // @1 uncomment int intParam2, String stringParam2 ) @@ -99,8 +100,8 @@ public class RetransformWithMethodParametersTest extends ATransformerManagementT private Parameter[] getTargetMethodParameters() throws ClassNotFoundException { Class cls = Class.forName(targetClassName); - // the class contains 1 method (method1) - Method method = cls.getDeclaredMethods()[0]; + // the class contains 1 method (ctor) + Executable method = cls.getDeclaredConstructors()[0]; Parameter[] params = method.getParameters(); log("Params of " + method.getName() + " method (" + params.length + "):"); for (int i = 0; i < params.length; i++) { @@ -174,7 +175,7 @@ public class RetransformWithMethodParametersTest extends ATransformerManagementT } log("Class bytes are different."); printDisassembled("expected", expected); - printDisassembled("expected", actual); + printDisassembled("actual", actual); fail(targetClassName + " did not match .class file"); } -- GitLab From f3e8242683f6c729d89e2f49b0977889b4786f4a Mon Sep 17 00:00:00 2001 From: Julia Boes Date: Mon, 7 Feb 2022 09:28:05 +0000 Subject: [PATCH 416/564] 8280965: Tests com/sun/net/httpserver/simpleserver fail with FileSystemException on Windows 11 Reviewed-by: dfuchs --- .../simpleserver/CustomFileSystemTest.java | 17 ++++++++++++++--- .../simpleserver/SimpleFileServerTest.java | 17 ++++++++++++++--- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/test/jdk/com/sun/net/httpserver/simpleserver/CustomFileSystemTest.java b/test/jdk/com/sun/net/httpserver/simpleserver/CustomFileSystemTest.java index 0826ca259ae..d6ec3eb0695 100644 --- a/test/jdk/com/sun/net/httpserver/simpleserver/CustomFileSystemTest.java +++ b/test/jdk/com/sun/net/httpserver/simpleserver/CustomFileSystemTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022, 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 @@ -74,6 +74,7 @@ import jdk.test.lib.net.URIBuilder; import org.testng.annotations.BeforeTest; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; +import org.testng.SkipException; import static java.net.http.HttpClient.Builder.NO_PROXY; import static java.nio.charset.StandardCharsets.UTF_8; import static java.nio.file.StandardOpenOption.CREATE; @@ -395,7 +396,7 @@ public class CustomFileSystemTest { var root = createDirectoryInCustomFs("testSymlinkGET"); var symlink = root.resolve("symlink"); var target = Files.writeString(root.resolve("target.txt"), "some text", CREATE); - Files.createSymbolicLink(symlink, target); + createSymLink(symlink, target); var server = SimpleFileServer.createFileServer(LOOPBACK_ADDR, root, OutputLevel.VERBOSE); server.start(); @@ -422,7 +423,7 @@ public class CustomFileSystemTest { var symlink = root.resolve("symlink"); var target = Files.createDirectory(root.resolve("target")); Files.writeString(target.resolve("aFile.txt"), "some text", CREATE); - Files.createSymbolicLink(symlink, target); + createSymLink(symlink, target); var server = SimpleFileServer.createFileServer(LOOPBACK_ADDR, root, OutputLevel.VERBOSE); server.start(); @@ -438,6 +439,16 @@ public class CustomFileSystemTest { } } + private void createSymLink(Path symlink, Path target) { + try { + Files.createSymbolicLink(symlink, target); + } catch (UnsupportedOperationException uoe) { + throw new SkipException("sym link creation not supported", uoe); + } catch (IOException ioe) { + throw new SkipException("probably insufficient privileges to create sym links (Windows)", ioe); + } + } + @Test public void testHiddenFileGET() throws Exception { var root = createDirectoryInCustomFs("testHiddenFileGET"); diff --git a/test/jdk/com/sun/net/httpserver/simpleserver/SimpleFileServerTest.java b/test/jdk/com/sun/net/httpserver/simpleserver/SimpleFileServerTest.java index 440e106c682..b3134640925 100644 --- a/test/jdk/com/sun/net/httpserver/simpleserver/SimpleFileServerTest.java +++ b/test/jdk/com/sun/net/httpserver/simpleserver/SimpleFileServerTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022, 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 @@ -56,6 +56,7 @@ import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeTest; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; +import org.testng.SkipException; import static java.net.http.HttpClient.Builder.NO_PROXY; import static java.nio.charset.StandardCharsets.UTF_8; import static java.nio.file.StandardOpenOption.CREATE; @@ -387,7 +388,7 @@ public class SimpleFileServerTest { var root = Files.createDirectory(TEST_DIR.resolve("testSymlinkGET")); var symlink = root.resolve("symlink"); var target = Files.writeString(root.resolve("target.txt"), "some text", CREATE); - Files.createSymbolicLink(symlink, target); + createSymLink(symlink, target); var server = SimpleFileServer.createFileServer(LOOPBACK_ADDR, root, OutputLevel.VERBOSE); server.start(); @@ -414,7 +415,7 @@ public class SimpleFileServerTest { var symlink = root.resolve("symlink"); var target = Files.createDirectory(root.resolve("target")); Files.writeString(target.resolve("aFile.txt"), "some text", CREATE); - Files.createSymbolicLink(symlink, target); + createSymLink(symlink, target); var server = SimpleFileServer.createFileServer(LOOPBACK_ADDR, root, OutputLevel.VERBOSE); server.start(); @@ -430,6 +431,16 @@ public class SimpleFileServerTest { } } + private void createSymLink(Path symlink, Path target) { + try { + Files.createSymbolicLink(symlink, target); + } catch (UnsupportedOperationException uoe) { + throw new SkipException("sym link creation not supported", uoe); + } catch (IOException ioe) { + throw new SkipException("probably insufficient privileges to create sym links (Windows)", ioe); + } + } + @Test public void testHiddenFileGET() throws Exception { var root = Files.createDirectory(TEST_DIR.resolve("testHiddenFileGET")); -- GitLab From 4c169495a2c4bfdcbc82e94e9ca1ee0cc050daf9 Mon Sep 17 00:00:00 2001 From: Aleksei Efimov Date: Mon, 7 Feb 2022 12:10:14 +0000 Subject: [PATCH 417/564] 8272996: JNDI DNS provider fails to resolve SRV entries when IPV6 stack is enabled Reviewed-by: dfuchs --- .../classes/com/sun/jndi/dns/DnsClient.java | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/jdk.naming.dns/share/classes/com/sun/jndi/dns/DnsClient.java b/src/jdk.naming.dns/share/classes/com/sun/jndi/dns/DnsClient.java index a5508ec45db..7083b4cd115 100644 --- a/src/jdk.naming.dns/share/classes/com/sun/jndi/dns/DnsClient.java +++ b/src/jdk.naming.dns/share/classes/com/sun/jndi/dns/DnsClient.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,10 +26,12 @@ package com.sun.jndi.dns; import java.io.IOException; +import java.io.UncheckedIOException; import java.net.DatagramSocket; import java.net.DatagramPacket; import java.net.InetAddress; import java.net.InetSocketAddress; +import java.net.PortUnreachableException; import java.net.Socket; import java.net.SocketTimeoutException; import java.security.SecureRandom; @@ -275,7 +277,16 @@ public class DnsClient { } // servers } return new ResourceRecords(msg, msg.length, hdr, false); - + } catch (UncheckedIOException | PortUnreachableException ex) { + // DatagramSocket.connect in doUdpQuery can throw UncheckedIOException + // DatagramSocket.send in doUdpQuery can throw PortUnreachableException + if (debug) { + dprint("Caught Exception:" + ex); + } + if (caughtException == null) { + caughtException = ex; + } + doNotRetry[i] = true; } catch (IOException e) { if (debug) { dprint("Caught IOException:" + e); @@ -283,12 +294,6 @@ public class DnsClient { if (caughtException == null) { caughtException = e; } - // Use reflection to allow pre-1.4 compilation. - // This won't be needed much longer. - if (e.getClass().getName().equals( - "java.net.PortUnreachableException")) { - doNotRetry[i] = true; - } } catch (NameNotFoundException e) { // This is authoritative, so return immediately throw e; -- GitLab From 76677716abf1124992c8f5d4d5b159b1ec0f3cab Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Mon, 7 Feb 2022 12:26:47 +0000 Subject: [PATCH 418/564] 8281114: G1: Remove PreservedMarks::init_forwarded_mark Reviewed-by: tschatzl, sjohanss --- src/hotspot/share/gc/g1/g1EvacFailure.cpp | 6 +++--- src/hotspot/share/gc/shared/preservedMarks.hpp | 3 +-- src/hotspot/share/gc/shared/preservedMarks.inline.hpp | 6 +----- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1EvacFailure.cpp b/src/hotspot/share/gc/g1/g1EvacFailure.cpp index 7d9dd4d7ead..9f93239bab0 100644 --- a/src/hotspot/share/gc/g1/g1EvacFailure.cpp +++ b/src/hotspot/share/gc/g1/g1EvacFailure.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022, 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 @@ -33,7 +33,6 @@ #include "gc/g1/g1OopClosures.inline.hpp" #include "gc/g1/heapRegion.hpp" #include "gc/g1/heapRegionRemSet.inline.hpp" -#include "gc/shared/preservedMarks.inline.hpp" #include "oops/access.inline.hpp" #include "oops/compressedOops.inline.hpp" #include "oops/oop.inline.hpp" @@ -94,7 +93,8 @@ public: size_t obj_size = obj->size(); _marked_words += obj_size; - PreservedMarks::init_forwarded_mark(obj); + // Reset the markWord + obj->init_mark(); HeapWord* obj_end = obj_addr + obj_size; _last_forwarded_object_end = obj_end; diff --git a/src/hotspot/share/gc/shared/preservedMarks.hpp b/src/hotspot/share/gc/shared/preservedMarks.hpp index 9a09e78bd46..959287ef99d 100644 --- a/src/hotspot/share/gc/shared/preservedMarks.hpp +++ b/src/hotspot/share/gc/shared/preservedMarks.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, 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 @@ -66,7 +66,6 @@ public: void adjust_during_full_gc(); void restore_and_increment(volatile size_t* const _total_size_addr); - inline static void init_forwarded_mark(oop obj); // Assert the stack is empty and has no cached segments. void assert_empty() PRODUCT_RETURN; diff --git a/src/hotspot/share/gc/shared/preservedMarks.inline.hpp b/src/hotspot/share/gc/shared/preservedMarks.inline.hpp index e35ba38e429..107acdba510 100644 --- a/src/hotspot/share/gc/shared/preservedMarks.inline.hpp +++ b/src/hotspot/share/gc/shared/preservedMarks.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,10 +48,6 @@ inline void PreservedMarks::push_always(oop obj, markWord m) { _stack.push(elem); } -inline void PreservedMarks::init_forwarded_mark(oop obj) { - obj->init_mark(); -} - inline PreservedMarks::PreservedMarks() : _stack(OopAndMarkWordStack::default_segment_size(), // This stack should be used very infrequently so there's -- GitLab From 22a1a32c7e5ceb7be6725f5369dcfc2a11fecc2f Mon Sep 17 00:00:00 2001 From: Stephanie Crater Date: Mon, 7 Feb 2022 12:43:28 +0000 Subject: [PATCH 419/564] 8268387: Rename maximum compaction to maximal compaction in G1 Reviewed-by: ayang, tschatzl --- src/hotspot/share/gc/g1/g1CollectedHeap.cpp | 24 ++++++++++----------- src/hotspot/share/gc/g1/g1CollectedHeap.hpp | 6 +++--- src/hotspot/share/gc/g1/g1FullCollector.cpp | 4 ++-- src/hotspot/share/gc/g1/g1FullCollector.hpp | 2 +- src/hotspot/share/gc/g1/g1FullGCScope.cpp | 4 ++-- src/hotspot/share/gc/g1/g1VMOperations.cpp | 2 +- 6 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index adc3e66d316..bfa29e39ccc 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -1098,7 +1098,7 @@ void G1CollectedHeap::verify_after_full_collection() { bool G1CollectedHeap::do_full_collection(bool explicit_gc, bool clear_all_soft_refs, - bool do_maximum_compaction) { + bool do_maximal_compaction) { assert_at_safepoint_on_vm_thread(); if (GCLocker::check_active_before_gc()) { @@ -1111,7 +1111,7 @@ bool G1CollectedHeap::do_full_collection(bool explicit_gc, G1FullGCMark gc_mark; GCTraceTime(Info, gc) tm("Pause Full", NULL, gc_cause(), true); - G1FullCollector collector(this, explicit_gc, do_clear_all_soft_refs, do_maximum_compaction); + G1FullCollector collector(this, explicit_gc, do_clear_all_soft_refs, do_maximal_compaction); collector.prepare_collection(); collector.collect(); @@ -1125,12 +1125,12 @@ void G1CollectedHeap::do_full_collection(bool clear_all_soft_refs) { // Currently, there is no facility in the do_full_collection(bool) API to notify // the caller that the collection did not succeed (e.g., because it was locked // out by the GC locker). So, right now, we'll ignore the return value. - // When clear_all_soft_refs is set we want to do a maximum compaction + // When clear_all_soft_refs is set we want to do a maximal compaction // not leaving any dead wood. - bool do_maximum_compaction = clear_all_soft_refs; + bool do_maximal_compaction = clear_all_soft_refs; bool dummy = do_full_collection(true, /* explicit_gc */ clear_all_soft_refs, - do_maximum_compaction); + do_maximal_compaction); } bool G1CollectedHeap::upgrade_to_full_collection() { @@ -1138,7 +1138,7 @@ bool G1CollectedHeap::upgrade_to_full_collection() { log_info(gc, ergo)("Attempting full compaction clearing soft references"); bool success = do_full_collection(false /* explicit gc */, true /* clear_all_soft_refs */, - false /* do_maximum_compaction */); + false /* do_maximal_compaction */); // do_full_collection only fails if blocked by GC locker and that can't // be the case here since we only call this when already completed one gc. assert(success, "invariant"); @@ -1162,7 +1162,7 @@ void G1CollectedHeap::resize_heap_if_necessary() { HeapWord* G1CollectedHeap::satisfy_failed_allocation_helper(size_t word_size, bool do_gc, - bool maximum_compaction, + bool maximal_compaction, bool expect_null_mutator_alloc_region, bool* gc_succeeded) { *gc_succeeded = true; @@ -1186,16 +1186,16 @@ HeapWord* G1CollectedHeap::satisfy_failed_allocation_helper(size_t word_size, if (do_gc) { GCCauseSetter compaction(this, GCCause::_g1_compaction_pause); // Expansion didn't work, we'll try to do a Full GC. - // If maximum_compaction is set we clear all soft references and don't + // If maximal_compaction is set we clear all soft references and don't // allow any dead wood to be left on the heap. - if (maximum_compaction) { - log_info(gc, ergo)("Attempting maximum full compaction clearing soft references"); + if (maximal_compaction) { + log_info(gc, ergo)("Attempting maximal full compaction clearing soft references"); } else { log_info(gc, ergo)("Attempting full compaction"); } *gc_succeeded = do_full_collection(false, /* explicit_gc */ - maximum_compaction /* clear_all_soft_refs */ , - maximum_compaction /* do_maximum_compaction */); + maximal_compaction /* clear_all_soft_refs */ , + maximal_compaction /* do_maximal_compaction */); } return NULL; diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp index 83da03019af..d6a8fe026d7 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp @@ -486,13 +486,13 @@ private: // otherwise it's for a failed allocation. // - if clear_all_soft_refs is true, all soft references should be // cleared during the GC. - // - if do_maximum_compaction is true, full gc will do a maximally + // - if do_maximal_compaction is true, full gc will do a maximally // compacting collection, leaving no dead wood. // - it returns false if it is unable to do the collection due to the // GC locker being active, true otherwise. bool do_full_collection(bool explicit_gc, bool clear_all_soft_refs, - bool do_maximum_compaction); + bool do_maximal_compaction); // Callback from VM_G1CollectFull operation, or collect_as_vm_thread. void do_full_collection(bool clear_all_soft_refs) override; @@ -518,7 +518,7 @@ private: // Helper method for satisfy_failed_allocation() HeapWord* satisfy_failed_allocation_helper(size_t word_size, bool do_gc, - bool maximum_compaction, + bool maximal_compaction, bool expect_null_mutator_alloc_region, bool* gc_succeeded); diff --git a/src/hotspot/share/gc/g1/g1FullCollector.cpp b/src/hotspot/share/gc/g1/g1FullCollector.cpp index e6e7dd25c0a..7e07ff4757c 100644 --- a/src/hotspot/share/gc/g1/g1FullCollector.cpp +++ b/src/hotspot/share/gc/g1/g1FullCollector.cpp @@ -111,9 +111,9 @@ uint G1FullCollector::calc_active_workers() { G1FullCollector::G1FullCollector(G1CollectedHeap* heap, bool explicit_gc, bool clear_soft_refs, - bool do_maximum_compaction) : + bool do_maximal_compaction) : _heap(heap), - _scope(heap->monitoring_support(), explicit_gc, clear_soft_refs, do_maximum_compaction), + _scope(heap->monitoring_support(), explicit_gc, clear_soft_refs, do_maximal_compaction), _num_workers(calc_active_workers()), _oop_queue_set(_num_workers), _array_queue_set(_num_workers), diff --git a/src/hotspot/share/gc/g1/g1FullCollector.hpp b/src/hotspot/share/gc/g1/g1FullCollector.hpp index f9087298b86..2d4bfc26feb 100644 --- a/src/hotspot/share/gc/g1/g1FullCollector.hpp +++ b/src/hotspot/share/gc/g1/g1FullCollector.hpp @@ -93,7 +93,7 @@ public: G1FullCollector(G1CollectedHeap* heap, bool explicit_gc, bool clear_soft_refs, - bool do_maximum_compaction); + bool do_maximal_compaction); ~G1FullCollector(); void prepare_collection(); diff --git a/src/hotspot/share/gc/g1/g1FullGCScope.cpp b/src/hotspot/share/gc/g1/g1FullGCScope.cpp index 0437d157eb0..38752db1bff 100644 --- a/src/hotspot/share/gc/g1/g1FullGCScope.cpp +++ b/src/hotspot/share/gc/g1/g1FullGCScope.cpp @@ -38,7 +38,7 @@ G1FullGCJFRTracerMark::~G1FullGCJFRTracerMark() { G1FullGCScope::G1FullGCScope(G1MonitoringSupport* monitoring_support, bool explicit_gc, bool clear_soft, - bool do_maximum_compaction) : + bool do_maximal_compaction) : _rm(), _explicit_gc(explicit_gc), _g1h(G1CollectedHeap::heap()), @@ -50,7 +50,7 @@ G1FullGCScope::G1FullGCScope(G1MonitoringSupport* monitoring_support, _soft_refs(clear_soft, _g1h->soft_ref_policy()), _monitoring_scope(monitoring_support, true /* full_gc */, true /* all_memory_pools_affected */), _heap_printer(_g1h), - _region_compaction_threshold(do_maximum_compaction ? + _region_compaction_threshold(do_maximal_compaction ? HeapRegion::GrainWords : (1 - MarkSweepDeadRatio / 100.0) * HeapRegion::GrainWords) { } diff --git a/src/hotspot/share/gc/g1/g1VMOperations.cpp b/src/hotspot/share/gc/g1/g1VMOperations.cpp index 94699a0c718..a4633f9c2b9 100644 --- a/src/hotspot/share/gc/g1/g1VMOperations.cpp +++ b/src/hotspot/share/gc/g1/g1VMOperations.cpp @@ -52,7 +52,7 @@ void VM_G1CollectFull::doit() { GCCauseSetter x(g1h, _gc_cause); _gc_succeeded = g1h->do_full_collection(true /* explicit_gc */, false /* clear_all_soft_refs */, - false /* do_maximum_compaction */); + false /* do_maximal_compaction */); } VM_G1TryInitiateConcMark::VM_G1TryInitiateConcMark(uint gc_count_before, -- GitLab From a0f6f2409ea61ff9ed9dc2e2b46e309c751d456d Mon Sep 17 00:00:00 2001 From: Sean Mullan Date: Mon, 7 Feb 2022 14:06:08 +0000 Subject: [PATCH 420/564] 8280890: Cannot use '-Djava.system.class.loader' with class loader in signed JAR Reviewed-by: weijun, hchao --- .../sun/security/tools/keytool/Main.java | 13 --- .../util/DisabledAlgorithmConstraints.java | 52 +++++----- .../security/SignedJar/CustomClassLoader.java | 43 +++++++++ .../SignedJarWithCustomClassLoader.java | 94 +++++++++++++++++++ 4 files changed, 158 insertions(+), 44 deletions(-) create mode 100644 test/jdk/java/security/SignedJar/CustomClassLoader.java create mode 100644 test/jdk/java/security/SignedJar/SignedJarWithCustomClassLoader.java diff --git a/src/java.base/share/classes/sun/security/tools/keytool/Main.java b/src/java.base/share/classes/sun/security/tools/keytool/Main.java index de13f75aea9..c9fb5178de5 100644 --- a/src/java.base/share/classes/sun/security/tools/keytool/Main.java +++ b/src/java.base/share/classes/sun/security/tools/keytool/Main.java @@ -47,8 +47,6 @@ import java.security.interfaces.EdECKey; import java.security.spec.ECParameterSpec; import java.text.Collator; import java.text.MessageFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; import java.util.*; import java.util.function.BiFunction; import java.util.jar.JarEntry; @@ -4926,17 +4924,6 @@ public final class Main { "Unable.to.parse.denyAfter.string.in.exception.message")); } - SimpleDateFormat formatter = new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy"); - Date dateObj = null; - try { - dateObj = formatter.parse(denyAfterDate); - } catch (ParseException e2) { - throw new Exception(rb.getString( - "Unable.to.parse.denyAfter.string.in.exception.message")); - } - formatter = new SimpleDateFormat("yyyy-MM-dd"); - denyAfterDate = formatter.format(dateObj); - weakWarnings.add(String.format( rb.getString("whose.sigalg.usagesignedjar"), label, sigAlg, denyAfterDate)); diff --git a/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java b/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java index 8a2650ff580..03e9cf6a2c6 100644 --- a/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java +++ b/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,9 +39,12 @@ import java.security.spec.InvalidParameterSpecException; import java.security.spec.MGF1ParameterSpec; import java.security.spec.NamedParameterSpec; import java.security.spec.PSSParameterSpec; +import java.time.DateTimeException; +import java.time.Instant; +import java.time.ZonedDateTime; +import java.time.ZoneId; import java.util.ArrayList; import java.util.Arrays; -import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util.HashSet; @@ -51,7 +54,6 @@ import java.util.Map; import java.util.Set; import java.util.Collection; import java.util.StringTokenizer; -import java.util.TimeZone; import java.util.regex.Pattern; import java.util.regex.Matcher; @@ -686,41 +688,30 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { * timezone. */ private static class DenyAfterConstraint extends Constraint { - private Date denyAfterDate; + private ZonedDateTime zdt; + private Instant denyAfterDate; DenyAfterConstraint(String algo, int year, int month, int day) { - Calendar c; algorithm = algo; if (debug != null) { - debug.println("DenyAfterConstraint read in as: year " + + debug.println("DenyAfterConstraint read in as: year " + year + ", month = " + month + ", day = " + day); } - c = new Calendar.Builder().setTimeZone(TimeZone.getTimeZone("GMT")) - .setDate(year, month - 1, day).build(); - - if (year > c.getActualMaximum(Calendar.YEAR) || - year < c.getActualMinimum(Calendar.YEAR)) { - throw new IllegalArgumentException( - "Invalid year given in constraint: " + year); - } - if ((month - 1) > c.getActualMaximum(Calendar.MONTH) || - (month - 1) < c.getActualMinimum(Calendar.MONTH)) { - throw new IllegalArgumentException( - "Invalid month given in constraint: " + month); - } - if (day > c.getActualMaximum(Calendar.DAY_OF_MONTH) || - day < c.getActualMinimum(Calendar.DAY_OF_MONTH)) { + try { + zdt = ZonedDateTime + .of(year, month, day, 0, 0, 0, 0, ZoneId.of("GMT")); + denyAfterDate = zdt.toInstant(); + } catch (DateTimeException dte) { throw new IllegalArgumentException( - "Invalid Day of Month given in constraint: " + day); + "Invalid denyAfter date", dte); } - denyAfterDate = c.getTime(); if (debug != null) { debug.println("DenyAfterConstraint date set to: " + - denyAfterDate); + zdt.toLocalDate()); } } @@ -735,23 +726,22 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { @Override public void permits(ConstraintsParameters cp) throws CertPathValidatorException { - Date currentDate; - String errmsg; + Instant currentDate; if (cp.getDate() != null) { - currentDate = cp.getDate(); + currentDate = cp.getDate().toInstant(); } else { - currentDate = new Date(); + currentDate = Instant.now(); } - if (!denyAfterDate.after(currentDate)) { + if (!denyAfterDate.isAfter(currentDate)) { if (next(cp)) { return; } throw new CertPathValidatorException( "denyAfter constraint check failed: " + algorithm + " used with Constraint date: " + - denyAfterDate + "; params date: " + + zdt.toLocalDate() + "; params date: " + currentDate + cp.extendedExceptionMsg(), null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); } @@ -770,7 +760,7 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { debug.println("DenyAfterConstraints.permits(): " + algorithm); } - return denyAfterDate.after(new Date()); + return denyAfterDate.isAfter(Instant.now()); } } diff --git a/test/jdk/java/security/SignedJar/CustomClassLoader.java b/test/jdk/java/security/SignedJar/CustomClassLoader.java new file mode 100644 index 00000000000..99242f3a877 --- /dev/null +++ b/test/jdk/java/security/SignedJar/CustomClassLoader.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2022, 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.io.IOException; +import java.io.InputStream; + +public class CustomClassLoader extends ClassLoader { + + public CustomClassLoader(ClassLoader parent) { + super(parent); + } + + @Override + public Class findClass(String name) throws ClassNotFoundException { + try (InputStream is = getClass().getClassLoader() + .getResourceAsStream(name + ".class")) { + byte[] buf = is.readAllBytes(); + return defineClass(name, buf, 0, buf.length); + } catch (IOException e) { + throw new ClassNotFoundException(e.getMessage()); + } + } +} diff --git a/test/jdk/java/security/SignedJar/SignedJarWithCustomClassLoader.java b/test/jdk/java/security/SignedJar/SignedJarWithCustomClassLoader.java new file mode 100644 index 00000000000..1f335c87f14 --- /dev/null +++ b/test/jdk/java/security/SignedJar/SignedJarWithCustomClassLoader.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2022, 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 8280890 + * @library /test/lib + * @build SignedJarWithCustomClassLoader CustomClassLoader + * @run main/othervm SignedJarWithCustomClassLoader + * @summary Make sure java.system.class.loader property can be used when custom + * class loader is inside signed jar + */ + +import java.nio.file.Path; +import java.nio.file.Paths; + +import jdk.test.lib.SecurityTools; +import jdk.test.lib.compiler.InMemoryJavaCompiler; +import jdk.test.lib.helpers.ClassFileInstaller; +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.util.JarUtils; + +public class SignedJarWithCustomClassLoader { + + public static void main(String[] args) throws Exception { + + // compile the Main program + String main = """ + public class Main { + public static void main(String[] args) {} + } + """; + String testClasses = System.getProperty("test.classes", ""); + ClassFileInstaller.writeClassToDisk("Main", + InMemoryJavaCompiler.compile("Main", main), + testClasses); + + // create the jar file + Path classes = Paths.get(testClasses); + JarUtils.createJarFile(Paths.get("test.jar"), classes, + classes.resolve("CustomClassLoader.class"), + classes.resolve("Main.class")); + + // create signer's keypair + SecurityTools.keytool("-genkeypair -keyalg RSA -keystore ks " + + "-storepass changeit -dname CN=test -alias test") + .shouldHaveExitValue(0); + + // sign jar + SecurityTools.jarsigner("-keystore ks -storepass changeit " + + "-signedjar signed.jar test.jar test") + .shouldHaveExitValue(0); + + // run app with system class loader set to custom classloader + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-cp", "signed.jar", + "-Djava.system.class.loader=CustomClassLoader", "Main"); + ProcessTools.executeProcess(pb) + .shouldHaveExitValue(0); + + // sign jar again, but this time with SHA-1 which is disabled + SecurityTools.jarsigner("-keystore ks -storepass changeit " + + "-digestalg SHA-1 -sigalg SHA1withRSA " + + "-signedjar signed.jar test.jar test") + .shouldHaveExitValue(0); + + // run app again, should still succeed even though SHA-1 is disabled + pb = ProcessTools.createJavaProcessBuilder( + "-cp", "signed.jar", + "-Djava.system.class.loader=CustomClassLoader", "Main"); + ProcessTools.executeProcess(pb) + .shouldHaveExitValue(0); + } +} -- GitLab From 2ed1f4cf32b1cef4ccb129d622f9368c3469d1d4 Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Mon, 7 Feb 2022 15:05:30 +0000 Subject: [PATCH 421/564] 8281175: Add a -providerPath option to jarsigner Reviewed-by: xuelei, hchao --- .../sun/security/tools/keytool/Main.java | 4 +--- .../sun/security/tools/jarsigner/Main.java | 24 +++++++++++++++++-- .../security/tools/jarsigner/Resources.java | 4 +++- .../security/tools/jarsigner/AltProvider.java | 19 ++++++--------- 4 files changed, 33 insertions(+), 18 deletions(-) diff --git a/src/java.base/share/classes/sun/security/tools/keytool/Main.java b/src/java.base/share/classes/sun/security/tools/keytool/Main.java index c9fb5178de5..ae012d3747a 100644 --- a/src/java.base/share/classes/sun/security/tools/keytool/Main.java +++ b/src/java.base/share/classes/sun/security/tools/keytool/Main.java @@ -824,9 +824,7 @@ public final class Main { if (providerClasses != null) { ClassLoader cl = null; if (pathlist != null) { - String path = null; - path = PathList.appendPath( - path, System.getProperty("java.class.path")); + String path = System.getProperty("java.class.path"); path = PathList.appendPath( path, System.getProperty("env.class.path")); path = PathList.appendPath(path, pathlist); diff --git a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java index 8758b99e18e..87ff579a7c1 100644 --- a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java +++ b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ package sun.security.tools.jarsigner; import java.io.*; import java.net.UnknownHostException; +import java.net.URLClassLoader; import java.security.cert.CertPathValidatorException; import java.security.cert.PKIXBuilderParameters; import java.util.*; @@ -59,6 +60,7 @@ import sun.security.pkcs.SignerInfo; import sun.security.provider.certpath.CertPathConstraintsParameters; import sun.security.timestamp.TimestampToken; import sun.security.tools.KeyStoreUtil; +import sun.security.tools.PathList; import sun.security.validator.Validator; import sun.security.validator.ValidatorException; import sun.security.x509.*; @@ -152,6 +154,7 @@ public class Main { List providerClasses = null; // list of provider classes // arguments for provider constructors HashMap providerArgs = new HashMap<>(); + String pathlist = null; char[] keypass; // private key password String sigfile; // name of .SF file String sigalg; // name of signature algorithm @@ -246,7 +249,18 @@ public class Main { } if (providerClasses != null) { - ClassLoader cl = ClassLoader.getSystemClassLoader(); + ClassLoader cl; + if (pathlist != null) { + String path = System.getProperty("java.class.path"); + path = PathList.appendPath( + path, System.getProperty("env.class.path")); + path = PathList.appendPath(path, pathlist); + + URL[] urls = PathList.pathToURLs(path); + cl = new URLClassLoader(urls); + } else { + cl = ClassLoader.getSystemClassLoader(); + } for (String provClass: providerClasses) { try { KeyStoreUtil.loadProviderByClass(provClass, @@ -434,6 +448,9 @@ public class Main { n += 2; } } + } else if (collator.compare(flags, "-providerpath") == 0) { + if (++n == args.length) usageNoArg(); + pathlist = args[n]; } else if (collator.compare(flags, "-protected") ==0) { protectedPath = true; } else if (collator.compare(flags, "-certchain") ==0) { @@ -705,6 +722,9 @@ public class Main { System.out.println(rb.getString (".providerArg.option.2")); System.out.println(); + System.out.println(rb.getString + (".providerPath.option")); + System.out.println(); System.out.println(rb.getString (".strict.treat.warnings.as.errors")); System.out.println(); diff --git a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources.java b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources.java index 45e56f4d049..265af66f9b3 100644 --- a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources.java +++ b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2022, 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 @@ -119,6 +119,8 @@ public class Resources extends java.util.ListResourceBundle { "[-providerClass add security provider by fully-qualified class name"}, {".providerArg.option.2", " [-providerArg ]] ... configure argument for -providerClass"}, + {".providerPath.option", + "[-providerPath ] provider classpath"}, {".strict.treat.warnings.as.errors", "[-strict] treat warnings as errors"}, {".conf.url.specify.a.pre.configured.options.file", diff --git a/test/jdk/sun/security/tools/jarsigner/AltProvider.java b/test/jdk/sun/security/tools/jarsigner/AltProvider.java index c359734b8c7..d4a57ca55da 100644 --- a/test/jdk/sun/security/tools/jarsigner/AltProvider.java +++ b/test/jdk/sun/security/tools/jarsigner/AltProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, 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 4906940 8130302 8194152 + * @bug 4906940 8130302 8194152 8281175 * @summary -providerPath, -providerClass, -addprovider, and -providerArg * @library /test/lib * @modules java.base/jdk.internal.misc @@ -81,33 +81,28 @@ public class AltProvider { // Without new provider testBoth("", 1, "DUMMYKS not found"); - // legacy use (-providerPath only supported by keytool) - testKeytool("-providerPath mods/test.dummy " + - "-providerClass org.test.dummy.DummyProvider -providerArg full", - 0, "loadProviderByClass: org.test.dummy.DummyProvider"); - // legacy, on classpath - testBoth("-J-cp -Jmods/test.dummy " + + testBoth("-providerpath mods/test.dummy " + "-providerClass org.test.dummy.DummyProvider -providerArg full", 0, "loadProviderByClass: org.test.dummy.DummyProvider"); // Wrong name - testBoth("-J-cp -Jmods/test.dummy " + + testBoth("-providerpath mods/test.dummy " + "-providerClass org.test.dummy.Dummy -providerArg full", 1, "Provider \"org.test.dummy.Dummy\" not found"); // Not a provider name - testBoth("-J-cp -Jmods/test.dummy " + + testBoth("-providerpath mods/test.dummy " + "-providerClass java.lang.Object -providerArg full", 1, "java.lang.Object not a provider"); // without arg - testBoth("-J-cp -Jmods/test.dummy " + + testBoth("-providerpath mods/test.dummy " + "-providerClass org.test.dummy.DummyProvider", 1, "DUMMYKS not found"); // old -provider still works - testBoth("-J-cp -Jmods/test.dummy " + + testBoth("-providerpath mods/test.dummy " + "-provider org.test.dummy.DummyProvider -providerArg full", 0, "loadProviderByClass: org.test.dummy.DummyProvider"); -- GitLab From 1dfc94dd561f6a91ef3784fe28c83f839f8188c4 Mon Sep 17 00:00:00 2001 From: Kevin Walls Date: Mon, 7 Feb 2022 17:36:40 +0000 Subject: [PATCH 422/564] 8281377: Remove vmTestbase/nsk/monitoring/ThreadMXBean/ThreadInfo/Deadlock/JavaDeadlock001/TestDescription.java from problemlist. Reviewed-by: sspitsyn --- test/hotspot/jtreg/ProblemList.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index e08217cd776..a09185a4b19 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -145,7 +145,6 @@ vmTestbase/nsk/monitoring/MemoryPoolMBean/isUsageThresholdExceeded/isexceeded002 vmTestbase/nsk/monitoring/MemoryPoolMBean/isUsageThresholdExceeded/isexceeded003/TestDescription.java 8198668 generic-all vmTestbase/nsk/monitoring/MemoryPoolMBean/isUsageThresholdExceeded/isexceeded004/TestDescription.java 8153598 generic-all vmTestbase/nsk/monitoring/MemoryPoolMBean/isUsageThresholdExceeded/isexceeded005/TestDescription.java 8153598 generic-all -vmTestbase/nsk/monitoring/ThreadMXBean/ThreadInfo/Deadlock/JavaDeadlock001/TestDescription.java 8060733 generic-all vmTestbase/nsk/jdi/HiddenClass/events/events001.java 8257705 generic-all vmTestbase/nsk/jdi/ThreadReference/stop/stop001/TestDescription.java 7034630 generic-all -- GitLab From 8a662105c2da1f0fb9b7ecc5058fc85858439ed9 Mon Sep 17 00:00:00 2001 From: Kevin Walls Date: Mon, 7 Feb 2022 18:16:23 +0000 Subject: [PATCH 423/564] 6779701: Wrong defect ID in the code of test LocalRMIServerSocketFactoryTest.java Reviewed-by: cjplummer, dfuchs --- .../jmxremote/LocalRMIServerSocketFactoryTest.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/jdk/sun/management/jmxremote/LocalRMIServerSocketFactoryTest.java b/test/jdk/sun/management/jmxremote/LocalRMIServerSocketFactoryTest.java index 223d252686f..3b51f32c99e 100644 --- a/test/jdk/sun/management/jmxremote/LocalRMIServerSocketFactoryTest.java +++ b/test/jdk/sun/management/jmxremote/LocalRMIServerSocketFactoryTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2022, 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 @@ -64,17 +64,17 @@ public class LocalRMIServerSocketFactoryTest { } - // case of 6674166: this is very unlikely to happen, even if - // both 6674166 and 6774170 aren't fixed. If it happens + // case of 6774166: this is very unlikely to happen, even if + // both 6774166 and 6774170 aren't fixed. If it happens // however, it might indicate that neither defects are fixed. if (x instanceof NullPointerException) { throw new Exception(message + " - " + - "Congratulations! it seems you have triggered 6674166. " + - "Neither 6674166 nor 6774170 seem to be fixed: " + x, x); + "Congratulations! it seems you have triggered 6774166. " + + "Neither 6774166 nor 6774170 seem to be fixed: " + x, x); } else if (x instanceof IOException) { throw new Exception(message + " - " + - "Unexpected IOException. Maybe you triggered 6674166? " + + "Unexpected IOException. Maybe you triggered 6774166? " + x, x); } else if (x != null) { throw new Exception(message + " - " + -- GitLab From 2f71a6b39ed6bb869b4eb3e81bc1d87f4b3328ff Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Mon, 7 Feb 2022 19:54:05 +0000 Subject: [PATCH 424/564] 8279613: JFR: Snippify Javadoc Reviewed-by: mgronlun --- .../classes/jdk/jfr/AnnotationElement.java | 17 +- src/jdk.jfr/share/classes/jdk/jfr/Event.java | 22 +- .../share/classes/jdk/jfr/EventFactory.java | 24 +- .../share/classes/jdk/jfr/EventSettings.java | 16 +- .../share/classes/jdk/jfr/FlightRecorder.java | 10 +- .../classes/jdk/jfr/MetadataDefinition.java | 31 +- .../share/classes/jdk/jfr/Recording.java | 22 +- .../share/classes/jdk/jfr/SettingControl.java | 71 +---- .../classes/jdk/jfr/consumer/EventStream.java | 20 +- .../jdk/jfr/consumer/RecordedObject.java | 18 +- .../jdk/jfr/consumer/RecordingFile.java | 9 +- .../jdk/jfr/consumer/RecordingStream.java | 43 +-- .../jdk/jfr/consumer/package-info.java | 23 +- .../jfr/consumer/snippet-files/Snippets.java | 169 ++++++++++ .../jdk/jfr/snippet-files/Snippets.java | 291 ++++++++++++++++++ 15 files changed, 487 insertions(+), 299 deletions(-) create mode 100644 src/jdk.jfr/share/classes/jdk/jfr/consumer/snippet-files/Snippets.java create mode 100644 src/jdk.jfr/share/classes/jdk/jfr/snippet-files/Snippets.java diff --git a/src/jdk.jfr/share/classes/jdk/jfr/AnnotationElement.java b/src/jdk.jfr/share/classes/jdk/jfr/AnnotationElement.java index 19c1f4db14f..f35b4911b15 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/AnnotationElement.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/AnnotationElement.java @@ -46,22 +46,7 @@ import jdk.jfr.internal.Utils; *

    * The following example shows how {@code AnnotationElement} can be used to dynamically define events. * - *

    {@literal
    - *   List typeAnnotations = new ArrayList<>();
    - *   typeAnnotations.add(new AnnotationElement(Name.class, "com.example.HelloWorld"));
    - *   typeAnnotations.add(new AnnotationElement(Label.class, "Hello World"));
    - *   typeAnnotations.add(new AnnotationElement(Description.class, "Helps programmer getting started"));
    - *
    - *   List fieldAnnotations = new ArrayList<>();
    - *   fieldAnnotations.add(new AnnotationElement(Label.class, "Message"));
    - *
    - *   List fields = new ArrayList<>();
    - *   fields.add(new ValueDescriptor(String.class, "message", fieldAnnotations));
    - *
    - *   EventFactory f = EventFactory.create(typeAnnotations, fields);
    - *   Event event = f.newEvent();
    - *   event.commit();
    - * }
    + * {@snippet class="Snippets" region="AnnotationElementOverview"} * * @since 9 */ diff --git a/src/jdk.jfr/share/classes/jdk/jfr/Event.java b/src/jdk.jfr/share/classes/jdk/jfr/Event.java index be9ed57eebe..c33d7749b5c 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/Event.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/Event.java @@ -31,27 +31,7 @@ package jdk.jfr; *

    * The following example shows how to implement an {@code Event} class. * - *

    {@literal
    - * import jdk.jfr.Event;
    - * import jdk.jfr.Description;
    - * import jdk.jfr.Label;
    - *
    - * public class Example {
    - *
    - *   @Label("Hello World")
    - *   @Description("Helps programmer getting started")
    - *   static class HelloWorld extends Event {
    - *       @Label("Message")
    - *       String message;
    - *   }
    - *
    - *   public static void main(String... args) {
    - *       HelloWorld event = new HelloWorld();
    - *       event.message = "hello, world!";
    - *       event.commit();
    - *   }
    - * }
    - * }
    + * {@snippet class="Snippets" region="EventOverview"} *

    * After an event is allocated and its field members are populated, it can be * written to the Flight Recorder system by using the {@link #commit()} method. diff --git a/src/jdk.jfr/share/classes/jdk/jfr/EventFactory.java b/src/jdk.jfr/share/classes/jdk/jfr/EventFactory.java index 71b08e74baa..a918bed40cf 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/EventFactory.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/EventFactory.java @@ -52,29 +52,7 @@ import jdk.jfr.internal.Utils; *

    * The following example shows how to implement a dynamic {@code Event} class. * - *

    - * {@code
    - * List fields = new ArrayList<>();
    - * List messageAnnotations = Collections.singletonList(new AnnotationElement(Label.class, "Message"));
    - * fields.add(new ValueDescriptor(String.class, "message", messageAnnotations));
    - * List numberAnnotations = Collections.singletonList(new AnnotationElement(Label.class, "Number"));
    - * fields.add(new ValueDescriptor(int.class, "number", numberAnnotations));
    - *
    - * String[] category = { "Example", "Getting Started" };
    - * List eventAnnotations = new ArrayList<>();
    - * eventAnnotations.add(new AnnotationElement(Name.class, "com.example.HelloWorld"));
    - * eventAnnotations.add(new AnnotationElement(Label.class, "Hello World"));
    - * eventAnnotations.add(new AnnotationElement(Description.class, "Helps programmer getting started"));
    - * eventAnnotations.add(new AnnotationElement(Category.class, category));
    - *
    - * EventFactory f = EventFactory.create(eventAnnotations, fields);
    - *
    - * Event event = f.newEvent();
    - * event.set(0, "hello, world!");
    - * event.set(1, 4711);
    - * event.commit();
    - * }
    - * 
    + * {@snippet class="Snippets" region="EventFactoryOverview"} * * @since 9 */ diff --git a/src/jdk.jfr/share/classes/jdk/jfr/EventSettings.java b/src/jdk.jfr/share/classes/jdk/jfr/EventSettings.java index 0d4c20aad45..128ae2b20a3 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/EventSettings.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/EventSettings.java @@ -38,21 +38,9 @@ import jdk.jfr.internal.management.EventSettingsModifier; * chaining. *

    * The following example shows how to use the {@code EventSettings} class. - *

    - * {@code
    - * Recording r = new Recording();
    - * r.enable("jdk.CPULoad")
    - *    .withPeriod(Duration.ofSeconds(1));
    - * r.enable("jdk.FileWrite")
    - *    .withoutStackTrace()
    - *    .withThreshold(Duration.ofNanos(10));
    - * r.start();
    - * Thread.sleep(10_000);
    - * r.stop();
    - * r.dump(Files.createTempFile("recording", ".jfr"));
      *
    - * }
    - * 
    + * {@snippet class="Snippets" region="EventSettingOverview"} + * * @since 9 */ public abstract class EventSettings { diff --git a/src/jdk.jfr/share/classes/jdk/jfr/FlightRecorder.java b/src/jdk.jfr/share/classes/jdk/jfr/FlightRecorder.java index 5e2bac1ba74..398fe2eb13a 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/FlightRecorder.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/FlightRecorder.java @@ -92,15 +92,7 @@ public final class FlightRecorder { *

    * The following example shows how to create a snapshot and write a subset of the data to a file. * - *

    {@literal
    -     * try (Recording snapshot = FlightRecorder.getFlightRecorder().takeSnapshot()) {
    -     *   if (snapshot.getSize() > 0) {
    -     *     snapshot.setMaxSize(100_000_000);
    -     *     snapshot.setMaxAge(Duration.ofMinutes(5));
    -     *     snapshot.dump(Paths.get("snapshot.jfr"));
    -     *   }
    -     * }
    -     * }
    + * {@snippet class="Snippets" region="FlightRecorderTakeSnapshot"} * * The caller must close the recording when access to the data is no longer * needed. diff --git a/src/jdk.jfr/share/classes/jdk/jfr/MetadataDefinition.java b/src/jdk.jfr/share/classes/jdk/jfr/MetadataDefinition.java index 919c7b01cff..56c669a2b34 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/MetadataDefinition.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/MetadataDefinition.java @@ -36,36 +36,7 @@ import java.lang.annotation.Target; * In the following example, a transaction event is defined with two * user-defined annotations, {@code @Severity} and {@code @TransactionId}. * - *
    {@literal
    - * @MetadataDefinition
    - * @Label("Severity")
    - * @Description("Value between 0 and 100 that indicates severity. 100 is most severe.")
    - * @Retention(RetentionPolicy.RUNTIME)
    - * @Target({ElementType.TYPE})
    - * public @interface Severity {
    - *     int value() default 50;
    - * }
    - *
    - * @MetadataDefinition
    - * @Label("Transaction Id")
    - * @Relational
    - * @Retention(RetentionPolicy.RUNTIME)
    - * @Target({ElementType.FIELD})
    - * public @interface TransactionId {
    - * }
    - *
    - * @Severity(80)
    - * @Label("Transaction Blocked")
    - * class TransactionBlocked extends Event {
    - *     @TransactionId
    - *     @Label("Transaction")
    - *     long transactionId1;
    - *
    - *     @TransactionId
    - *     @Label("Transaction Blocker")
    - *     long transactionId2;
    - * }
    - * }
    + * {@snippet class="Snippets" region="MetadataDefinitionOverview"} * * Adding {@code @MetadataDefinition} to the declaration of {@code @Severity} and {@code @TransactionId} * ensures the information is saved by Flight Recorder. diff --git a/src/jdk.jfr/share/classes/jdk/jfr/Recording.java b/src/jdk.jfr/share/classes/jdk/jfr/Recording.java index 1dd4b303013..4f07bca6641 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/Recording.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/Recording.java @@ -46,15 +46,7 @@ import jdk.jfr.internal.WriteableUserPath; *

    * The following example shows how configure, start, stop and dump recording data to disk. * - *

    {@literal
    - *   Configuration c = Configuration.getConfiguration("default");
    - *   Recording r = new Recording(c);
    - *   r.start();
    - *   System.gc();
    - *   Thread.sleep(5000);
    - *   r.stop();
    - *   r.dump(Files.createTempFile("my-recording", ".jfr"));
    - * }
    + * {@snippet class="Snippets" region="RecordingOverview"} * * @since 9 */ @@ -143,9 +135,9 @@ public final class Recording implements Closeable { *

    * The following example shows how create a recording that uses a predefined configuration. * - *

    {@literal
    +     * {@snippet :
          * Recording r = new Recording(Configuration.getConfiguration("default"));
    -     * }
    + * } * * The newly created recording is in the {@link RecordingState#NEW} state. To * start the recording, invoke the {@link Recording#start()} method. @@ -307,21 +299,21 @@ public final class Recording implements Closeable { *

    * The following example shows how to set event settings for a recording. * - *

    {@literal
    +     * {@snippet :
          *     Map settings = new HashMap<>();
          *     settings.putAll(EventSettings.enabled("jdk.CPUSample").withPeriod(Duration.ofSeconds(2)).toMap());
          *     settings.putAll(EventSettings.enabled(MyEvent.class).withThreshold(Duration.ofSeconds(2)).withoutStackTrace().toMap());
          *     settings.put("jdk.ExecutionSample#period", "10 ms");
          *     recording.setSettings(settings);
    -     * }
    + * } * * The following example shows how to merge settings. * - *
    {@literal
    +     * {@snippet :
          *     Map settings = recording.getSettings();
          *     settings.putAll(additionalSettings);
          *     recording.setSettings(settings);
    -     * }
    + * } * * @param settings the settings to set, not {@code null} */ diff --git a/src/jdk.jfr/share/classes/jdk/jfr/SettingControl.java b/src/jdk.jfr/share/classes/jdk/jfr/SettingControl.java index 431b984ebf2..1c699247800 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/SettingControl.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/SettingControl.java @@ -37,30 +37,7 @@ import jdk.jfr.internal.settings.JDKSettingControl; * The following example shows a naive implementation of a setting control for * regular expressions: * - *
    {@literal
    - * final class RegExpControl extends SettingControl {
    - *   private Pattern pattern = Pattern.compile(".*");
    - *
    - *   @Override
    - *   public void setValue(String value) {
    - *     this.pattern = Pattern.compile(value);
    - *   }
    - *
    - *   @Override
    - *   public String combine(Set values) {
    - *     return String.join("|", values);
    - *   }
    - *
    - *   @Override
    - *   public String getValue() {
    - *     return pattern.toString();
    - *   }
    - *
    - *   public boolean matches(String s) {
    - *     return pattern.matcher(s).find();
    - *   }
    - * }
    - * }
    + * {@snippet class="Snippets" region="SettingControlOverview1"} * * The {@code setValue(String)}, {@code getValue()} and * {@code combine(Set)} methods are invoked when a setting value @@ -85,55 +62,13 @@ import jdk.jfr.internal.settings.JDKSettingControl; * The following example shows how to create an event that uses the * regular expression filter defined above. * - *
    {@literal
    - * abstract class HTTPRequest extends Event {
    - *   @Label("Request URI")
    - *   protected String uri;
    - *
    - *   @Label("Servlet URI Filter")
    - *   @SettingDefinition
    - *   protected boolean uriFilter(RegExpControl regExp) {
    - *     return regExp.matches(uri);
    - *   }
    - * }
    - *
    - * @Label("HTTP Get Request")
    - * class HTTPGetRequest extends HTTPRequest {
    - * }
    - *
    - * @Label("HTTP Post Request")
    - * class HTTPPostRequest extends HTTPRequest {
    - * }
    - *
    - * class ExampleServlet extends HttpServlet {
    - *   protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
    - *     HTTPGetRequest request = new HTTPGetRequest();
    - *     request.begin();
    - *     request.uri = req.getRequestURI();
    - *     ...
    - *     request.commit();
    - *   }
    - *
    - *   protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
    - *     HTTPPostRequest request = new HTTPPostRequest();
    - *     request.begin();
    - *     request.uri = req.getRequestURI();
    - *     ...
    - *     request.commit();
    - *   }
    - * }
    - * }
    + * {@snippet class="Snippets" region="SettingControlOverview2"} * *

    * The following example shows how an event can be filtered by assigning the * {@code "uriFilter"} setting with the specified regular expressions. * - *

    {@literal
    - * Recording r = new Recording();
    - * r.enable("HTTPGetRequest").with("uriFilter", "https://www.example.com/list/.*");
    - * r.enable("HTTPPostRequest").with("uriFilter", "https://www.example.com/login/.*");
    - * r.start();
    - * }
    + * {@snippet class="Snippets" region="SettingControlOverview3"} * * @see SettingDefinition * diff --git a/src/jdk.jfr/share/classes/jdk/jfr/consumer/EventStream.java b/src/jdk.jfr/share/classes/jdk/jfr/consumer/EventStream.java index dc877b52efd..8b55f669ef2 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/EventStream.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/EventStream.java @@ -95,25 +95,7 @@ import jdk.jfr.internal.consumer.FileAccess; * The following example shows how an {@code EventStream} can be used to listen * to events on a JVM running Flight Recorder * - *
    {@literal
    - * try (var es = EventStream.openRepository()) {
    - *   es.onEvent("jdk.CPULoad", event -> {
    - *     System.out.println("CPU Load " + event.getEndTime());
    - *     System.out.println(" Machine total: " + 100 * event.getFloat("machineTotal") + "%");
    - *     System.out.println(" JVM User: " + 100 * event.getFloat("jvmUser") + "%");
    - *     System.out.println(" JVM System: " + 100 * event.getFloat("jvmSystem") + "%");
    - *     System.out.println();
    - *   });
    - *   es.onEvent("jdk.GarbageCollection", event -> {
    - *     System.out.println("Garbage collection: " + event.getLong("gcId"));
    - *     System.out.println(" Cause: " + event.getString("cause"));
    - *     System.out.println(" Total pause: " + event.getDuration("sumOfPauses"));
    - *     System.out.println(" Longest pause: " + event.getDuration("longestPause"));
    - *     System.out.println();
    - *   });
    - *   es.start();
    - * }
    - * }
    + * {@snippet class="Snippets" region="EventStreamOverview"} *

    * To start recording together with the stream, see {@link RecordingStream}. * diff --git a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedObject.java b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedObject.java index d9def94ff8a..277c9899def 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedObject.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedObject.java @@ -225,23 +225,7 @@ public class RecordedObject { * for callers of this method is to validate the field before attempting access. *

    * Example - * - *

    {@literal
    -     * if (event.hasField("intValue")) {
    -     *   int intValue = event.getValue("intValue");
    -     *   System.out.println("Int value: " + intValue);
    -     * }
    -     *
    -     * if (event.hasField("objectClass")) {
    -     *   RecordedClass clazz = event.getValue("objectClass");
    -     *   System.out.println("Class name: " + clazz.getName());
    -     * }
    -     *
    -     * if (event.hasField("sampledThread")) {
    -     *   RecordedThread sampledThread = event.getValue("sampledThread");
    -     *   System.out.println("Sampled thread: " + sampledThread.getJavaName());
    -     * }
    -     * }
    + * {@snippet class="Snippets" region="RecordedObjectGetValue"} * * @param the return type * @param name of the field to get, not {@code null} diff --git a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingFile.java b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingFile.java index 3b8163e717b..15501bc6880 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingFile.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingFile.java @@ -49,14 +49,7 @@ import jdk.jfr.internal.consumer.RecordingInput; *

    * The following example shows how read and print all events in a recording file. * - *

    {@literal
    - * try (RecordingFile recordingFile = new RecordingFile(Paths.get("recording.jfr"))) {
    - *   while (recordingFile.hasMoreEvents()) {
    - *     RecordedEvent event = recordingFile.readEvent();
    - *     System.out.println(event);
    - *   }
    - * }
    - * }
    + * {@snippet class="Snippets" region="RecordingFileOverview"} * * @since 9 */ diff --git a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingStream.java b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingStream.java index ea6d2a05bf9..64347196948 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingStream.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingStream.java @@ -56,15 +56,8 @@ import jdk.jfr.internal.consumer.EventDirectoryStream; * The following example shows how to record events using the default * configuration and print the Garbage Collection, CPU Load and JVM Information * event to standard out. - *
    {@literal
    - * Configuration c = Configuration.getConfiguration("default");
    - * try (var rs = new RecordingStream(c)) {
    - *     rs.onEvent("jdk.GarbageCollection", System.out::println);
    - *     rs.onEvent("jdk.CPULoad", System.out::println);
    - *     rs.onEvent("jdk.JVMInformation", System.out::println);
    - *     rs.start();
    - * }
    - * }
    + * + * {@snippet class="Snippets" region="RecordingStreamOverview"} * * @since 14 */ @@ -140,13 +133,7 @@ public final class RecordingStream implements AutoCloseable, EventStream { * The following example shows how to create a recording stream that uses a * predefined configuration. * - *
    {@literal
    -     * var c = Configuration.getConfiguration("default");
    -     * try (var rs = new RecordingStream(c)) {
    -     *   rs.onEvent(System.out::println);
    -     *   rs.start();
    -     * }
    -     * }
    + * {@snippet class="Snippets" region="RecordingStreamConstructor"} * * @param configuration configuration that contains the settings to use, * not {@code null} @@ -189,17 +176,7 @@ public final class RecordingStream implements AutoCloseable, EventStream { * The following example records 20 seconds using the "default" configuration * and then changes settings to the "profile" configuration. * - *
    {@literal
    -     * Configuration defaultConfiguration = Configuration.getConfiguration("default");
    -     * Configuration profileConfiguration = Configuration.getConfiguration("profile");
    -     * try (var rs = new RecordingStream(defaultConfiguration)) {
    -     *    rs.onEvent(System.out::println);
    -     *    rs.startAsync();
    -     *    Thread.sleep(20_000);
    -     *    rs.setSettings(profileConfiguration.getSettings());
    -     *    Thread.sleep(20_000);
    -     * }
    -     * }
    + * {@snippet class="Snippets" region="RecordingStreamSetSettings"} * * @param settings the settings to set, not {@code null} * @@ -384,16 +361,8 @@ public final class RecordingStream implements AutoCloseable, EventStream { * The following example prints the CPU usage for ten seconds. When * the current thread leaves the try-with-resources block the * stream is stopped/closed. - *
    {@literal
    -     * try (var stream = new RecordingStream()) {
    -     *   stream.enable("jdk.CPULoad").withPeriod(Duration.ofSeconds(1));
    -     *   stream.onEvent("jdk.CPULoad", event -> {
    -     *     System.out.println(event);
    -     *   });
    -     *   stream.startAsync();
    -     *   Thread.sleep(10_000);
    -     * }
    -     * }
    + * + * {@snippet class="Snippets" region="RecordingStreamStartAsync"} * * @throws IllegalStateException if the stream is already started or closed */ diff --git a/src/jdk.jfr/share/classes/jdk/jfr/consumer/package-info.java b/src/jdk.jfr/share/classes/jdk/jfr/consumer/package-info.java index 5b34deaf249..81f7977deba 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/package-info.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/package-info.java @@ -27,29 +27,8 @@ * This package contains classes for consuming Flight Recorder data. *

    * In the following example, the program prints a histogram of all method samples in a recording. - *

    {@literal
    - * public static void main(String[] args) throws IOException {
    - *     if (args.length != 1) {
    - *         System.err.println("Must specify a recording file.");
    - *         return;
    - *     }
      *
    - *     RecordingFile.readAllEvents(Path.of(args[0])).stream()
    - *         .filter(e -> e.getEventType().getName().equals("jdk.ExecutionSample"))
    - *         .map(e -> e.getStackTrace())
    - *         .filter(s -> s != null)
    - *         .map(s -> s.getFrames().get(0))
    - *         .filter(f -> f.isJavaFrame())
    - *         .map(f -> f.getMethod())
    - *         .collect(
    - *             Collectors.groupingBy(m -> m.getType().getName() + "." + m.getName() + " " + m.getDescriptor(),
    - *             Collectors.counting()))
    - *         .entrySet()
    - *         .stream()
    - *         .sorted((a, b) -> b.getValue().compareTo(a.getValue()))
    - *         .forEach(e -> System.out.printf("%8d %s\n", e.getValue(), e.getKey()));
    - *     }
    - * }
    + * {@snippet class="Snippets" region="PackageOverview"} *

    * Null-handling *

    diff --git a/src/jdk.jfr/share/classes/jdk/jfr/consumer/snippet-files/Snippets.java b/src/jdk.jfr/share/classes/jdk/jfr/consumer/snippet-files/Snippets.java new file mode 100644 index 00000000000..d80879a22ec --- /dev/null +++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/snippet-files/Snippets.java @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package example2; + +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.time.Duration; +import java.util.stream.Collectors; +import jdk.jfr.consumer.EventStream; +import jdk.jfr.consumer.RecordingFile; +import jdk.jfr.consumer.RecordedClass; +import jdk.jfr.consumer.RecordedThread; +import jdk.jfr.consumer.RecordingStream; +import jdk.jfr.Configuration; +import jdk.jfr.consumer.RecordedEvent; + +public class Snippets { + + class PackageOveriview { + // @start region="PackageOverview" + public static void main(String[] args) throws IOException { + if (args.length != 1) { + System.err.println("Must specify a recording file."); + return; + } + + RecordingFile.readAllEvents(Path.of(args[0])).stream() + .filter(e -> e.getEventType().getName().equals("jdk.ExecutionSample")) + .map(e -> e.getStackTrace()) + .filter(s -> s != null) + .map(s -> s.getFrames().get(0)) + .filter(f -> f.isJavaFrame()) + .map(f -> f.getMethod()) + .collect( + Collectors.groupingBy(m -> m.getType().getName() + "." + m.getName() + " " + m.getDescriptor(), + Collectors.counting())) + .entrySet() + .stream() + .sorted((a, b) -> b.getValue().compareTo(a.getValue())) + .forEach(e -> System.out.printf("%8d %s\n", e.getValue(), e.getKey())); + } + // @end + } + + void EventStreamOverview() throws Exception { + // @start region="EventStreamOverview" + try (var es = EventStream.openRepository()) { + es.onEvent("jdk.CPULoad", event -> { + System.out.println("CPU Load " + event.getEndTime()); + System.out.println(" Machine total: " + 100 * event.getFloat("machineTotal") + "%"); + System.out.println(" JVM User: " + 100 * event.getFloat("jvmUser") + "%"); + System.out.println(" JVM System: " + 100 * event.getFloat("jvmSystem") + "%"); + System.out.println(); + }); + es.onEvent("jdk.GarbageCollection", event -> { + System.out.println("Garbage collection: " + event.getLong("gcId")); + System.out.println(" Cause: " + event.getString("cause")); + System.out.println(" Total pause: " + event.getDuration("sumOfPauses")); + System.out.println(" Longest pause: " + event.getDuration("longestPause")); + System.out.println(); + }); + es.start(); + } + // @end + } + + void RecordingFileOverview() throws Exception { + // @start region="RecordingFileOverview" + try (RecordingFile recordingFile = new RecordingFile(Paths.get("recording.jfr"))) { + while (recordingFile.hasMoreEvents()) { + RecordedEvent event = recordingFile.readEvent(); + System.out.println(event); + } + } + // @end + } + + void RecordedObjectGetValue() { + RecordedEvent event = null; + // @start region="RecordedObjectGetValue" + if (event.hasField("intValue")) { + int intValue = event.getValue("intValue"); + System.out.println("Int value: " + intValue); + } + + if (event.hasField("objectClass")) { + RecordedClass clazz = event.getValue("objectClass"); + System.out.println("Class name: " + clazz.getName()); + } + + if (event.hasField("sampledThread")) { + RecordedThread sampledThread = event.getValue("sampledThread"); + System.out.println("Sampled thread: " + sampledThread.getJavaName()); + } + // @end + } + + void RecordingStreamOverview() throws Exception { + // @start region="RecordingStreamOverview" + Configuration c = Configuration.getConfiguration("default"); + try (var rs = new RecordingStream(c)) { + rs.onEvent("jdk.GarbageCollection", System.out::println); + rs.onEvent("jdk.CPULoad", System.out::println); + rs.onEvent("jdk.JVMInformation", System.out::println); + rs.start(); + } + // @end + } + + void RecordingStreamConstructor() throws Exception { + // @start region="RecordingStreamConstructor" + var c = Configuration.getConfiguration("default"); + try (var rs = new RecordingStream(c)) { + rs.onEvent(System.out::println); + rs.start(); + } + // @end + } + + void RecordingStreamSetSettings() throws Exception { + // @start region="RecordingStreamSetSettings" + Configuration defaultConfiguration = Configuration.getConfiguration("default"); + Configuration profileConfiguration = Configuration.getConfiguration("profile"); + try (var rs = new RecordingStream(defaultConfiguration)) { + rs.onEvent(System.out::println); + rs.startAsync(); + Thread.sleep(20_000); + rs.setSettings(profileConfiguration.getSettings()); + Thread.sleep(20_000); + } + // @end + } + + void RecordingStreamStartAsync() throws Exception { + // @start region="RecordingStreamStartAsync" + try (var stream = new RecordingStream()) { + stream.enable("jdk.CPULoad").withPeriod(Duration.ofSeconds(1)); + stream.onEvent("jdk.CPULoad", event -> { + System.out.println(event); + }); + stream.startAsync(); + Thread.sleep(10_000); + } + // @end + } +} diff --git a/src/jdk.jfr/share/classes/jdk/jfr/snippet-files/Snippets.java b/src/jdk.jfr/share/classes/jdk/jfr/snippet-files/Snippets.java new file mode 100644 index 00000000000..b2d4fff29de --- /dev/null +++ b/src/jdk.jfr/share/classes/jdk/jfr/snippet-files/Snippets.java @@ -0,0 +1,291 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package example1; + +import jdk.jfr.AnnotationElement; +import jdk.jfr.ValueDescriptor; +import jdk.jfr.EventFactory; +import jdk.jfr.Event; +import jdk.jfr.Name; +import jdk.jfr.Label; +import jdk.jfr.Description; +import jdk.jfr.Category; +import jdk.jfr.Recording; +import jdk.jfr.MetadataDefinition; +import jdk.jfr.Relational; +import jdk.jfr.consumer.RecordingFile; +import jdk.jfr.Configuration; +import jdk.jfr.SettingDefinition; +import jdk.jfr.SettingControl; +import jdk.jfr.FlightRecorder; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.time.Duration; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; + +public class Snippets { + + void AnnotationElementOverview() { + // @start region="AnnotationElementOverview" + List typeAnnotations = new ArrayList<>(); + typeAnnotations.add(new AnnotationElement(Name.class, "com.example.HelloWorld")); + typeAnnotations.add(new AnnotationElement(Label.class, "Hello World")); + typeAnnotations.add(new AnnotationElement(Description.class, "Helps programmer getting started")); + + List fieldAnnotations = new ArrayList<>(); + fieldAnnotations.add(new AnnotationElement(Label.class, "Message")); + + List fields = new ArrayList<>(); + fields.add(new ValueDescriptor(String.class, "message", fieldAnnotations)); + + EventFactory f = EventFactory.create(typeAnnotations, fields); + Event event = f.newEvent(); + event.commit(); + // @end + } + + // @start region="EventOverview" + public class Example { + + @Label("Hello World") + @Description("Helps programmer getting started") + static class HelloWorld extends Event { + @Label("Message") + String message; + } + + public static void main(String... args) { + HelloWorld event = new HelloWorld(); + event.message = "hello, world!"; + event.commit(); + } + } + // @end + + void EventFactoryOverview() { + // @start region="EventFactoryOverview" + List fields = new ArrayList<>(); + List messageAnnotations = Collections.singletonList(new AnnotationElement(Label.class, "Message")); + fields.add(new ValueDescriptor(String.class, "message", messageAnnotations)); + List numberAnnotations = Collections.singletonList(new AnnotationElement(Label.class, "Number")); + fields.add(new ValueDescriptor(int.class, "number", numberAnnotations)); + + String[] category = { "Example", "Getting Started" }; + List eventAnnotations = new ArrayList<>(); + eventAnnotations.add(new AnnotationElement(Name.class, "com.example.HelloWorld")); + eventAnnotations.add(new AnnotationElement(Label.class, "Hello World")); + eventAnnotations.add(new AnnotationElement(Description.class, "Helps programmer getting started")); + eventAnnotations.add(new AnnotationElement(Category.class, category)); + + EventFactory f = EventFactory.create(eventAnnotations, fields); + + Event event = f.newEvent(); + event.set(0, "hello, world!"); + event.set(1, 4711); + event.commit(); + // @end + } + + void EventSettingOverview() throws Exception { + // @start region="EventSettingOverview" + Recording r = new Recording(); + r.enable("jdk.CPULoad") + .withPeriod(Duration.ofSeconds(1)); + r.enable("jdk.FileWrite") + .withoutStackTrace() + .withThreshold(Duration.ofNanos(10)); + r.start(); + Thread.sleep(10_000); + r.stop(); + r.dump(Files.createTempFile("recording", ".jfr")); + // @end + } + + void FlightRecorderTakeSnapshot() throws Exception { + // @start region="FlightRecorderTakeSnapshot" + try (Recording snapshot = FlightRecorder.getFlightRecorder().takeSnapshot()) { + if (snapshot.getSize() > 0) { + snapshot.setMaxSize(100_000_000); + snapshot.setMaxAge(Duration.ofMinutes(5)); + snapshot.dump(Paths.get("snapshot.jfr")); + } + } + // @end + } + + // @start region="MetadataDefinitionOverview" + @MetadataDefinition + @Label("Severity") + @Description("Value between 0 and 100 that indicates severity. 100 is most severe.") + @Retention(RetentionPolicy.RUNTIME) + @Target({ ElementType.TYPE }) + public @interface Severity { + int value() default 50; + } + + @MetadataDefinition + @Label("Transaction Id") + @Relational + @Retention(RetentionPolicy.RUNTIME) + @Target({ ElementType.FIELD }) + public @interface TransactionId { + } + + @Severity(80) + @Label("Transaction Blocked") + class TransactionBlocked extends Event { + @TransactionId + @Label("Transaction") + long transactionId1; + + @TransactionId + @Label("Transaction Blocker") + long transactionId2; + } + // @end + + void RecordingnOverview() throws Exception { + // @start region="RecordingOverview" + Configuration c = Configuration.getConfiguration("default"); + Recording r = new Recording(c); + r.start(); + System.gc(); + Thread.sleep(5000); + r.stop(); + r.dump(Files.createTempFile("my-recording", ".jfr")); + // @end + } + + // @start region="SettingControlOverview1" + final class RegExpControl extends SettingControl { + private Pattern pattern = Pattern.compile(".*"); + + @Override + public void setValue(String value) { + this.pattern = Pattern.compile(value); + } + + @Override + public String combine(Set values) { + return String.join("|", values); + } + + @Override + public String getValue() { + return pattern.toString(); + } + + public boolean matches(String s) { + return pattern.matcher(s).find(); + } + } + // @end + + class HttpServlet { + } + + class HttpServletRequest { + public String getRequestURI() { + return null; + } + } + + class HttpServletResponse { + } + + // @start region="SettingControlOverview2" + abstract class HTTPRequest extends Event { + @Label("Request URI") + protected String uri; + + @Label("Servlet URI Filter") + @SettingDefinition + protected boolean uriFilter(RegExpControl regExp) { + return regExp.matches(uri); + } + } + + @Label("HTTP Get Request") + class HTTPGetRequest extends HTTPRequest { + } + + @Label("HTTP Post Request") + class HTTPPostRequest extends HTTPRequest { + } + + class ExampleServlet extends HttpServlet { + protected void doGet(HttpServletRequest req, HttpServletResponse resp) { + HTTPGetRequest request = new HTTPGetRequest(); + request.begin(); + request.uri = req.getRequestURI(); + code: // @replace regex='code:' replacement="..." + request.commit(); + } + + protected void doPost(HttpServletRequest req, HttpServletResponse resp) { + HTTPPostRequest request = new HTTPPostRequest(); + request.begin(); + request.uri = req.getRequestURI(); + code: // @replace regex='code:' replacement="..." + request.commit(); + } + } + // @end + + void SettingControlOverview3() { + // @start region="SettingControlOverview3" + Recording r = new Recording(); + r.enable("HTTPGetRequest").with("uriFilter", "https://www.example.com/list/.*"); + r.enable("HTTPPostRequest").with("uriFilter", "https://www.example.com/login/.*"); + r.start(); + // @end + } + + // @start region="SettingDefinitionOverview" + class HelloWorld extends Event { + + @Label("Message") + String message; + + @SettingDefinition + @Label("Message Filter") + public boolean filter(RegExpControl regExp) { + return regExp.matches(message); + } + } + // @end +} -- GitLab From 4eacacb5ad61020c11a521111c40af9fa72e2ff5 Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Tue, 8 Feb 2022 07:19:57 +0000 Subject: [PATCH 425/564] 8281314: Rename Stack{Red,Yellow,Reserved,Shadow}Pages multipliers Reviewed-by: stuefe, coleenp, xliu --- src/hotspot/share/runtime/stackOverflow.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/hotspot/share/runtime/stackOverflow.cpp b/src/hotspot/share/runtime/stackOverflow.cpp index 942f3a29e3f..1004ca265d3 100644 --- a/src/hotspot/share/runtime/stackOverflow.cpp +++ b/src/hotspot/share/runtime/stackOverflow.cpp @@ -39,19 +39,20 @@ void StackOverflow::initialize_stack_zone_sizes() { // Stack zone sizes must be page aligned. size_t page_size = os::vm_page_size(); - // We need to adapt the configured number of stack protection pages given - // in 4K pages to the actual os page size. We must do this before setting - // up minimal stack sizes etc. in os::init_2(). - size_t alignment = 4*K; + // We need to adapt the configured number of stack protection pages to the + // actual OS page size. We must do this before setting up minimal stack + // sizes etc. in os::init_2(). The option values are given in 4K units, + // matching the smallest page size in supported platforms. + size_t unit = 4*K; assert(_stack_red_zone_size == 0, "This should be called only once."); - _stack_red_zone_size = align_up(StackRedPages * alignment, page_size); + _stack_red_zone_size = align_up(StackRedPages * unit, page_size); assert(_stack_yellow_zone_size == 0, "This should be called only once."); - _stack_yellow_zone_size = align_up(StackYellowPages * alignment, page_size); + _stack_yellow_zone_size = align_up(StackYellowPages * unit, page_size); assert(_stack_reserved_zone_size == 0, "This should be called only once."); - _stack_reserved_zone_size = align_up(StackReservedPages * alignment, page_size); + _stack_reserved_zone_size = align_up(StackReservedPages * unit, page_size); // The shadow area is not allocated or protected, so // it needs not be page aligned. @@ -63,7 +64,7 @@ void StackOverflow::initialize_stack_zone_sizes() { // suffices to touch all pages. (Some pages are banged // several times, though.) assert(_stack_shadow_zone_size == 0, "This should be called only once."); - _stack_shadow_zone_size = align_up(StackShadowPages * alignment, page_size); + _stack_shadow_zone_size = align_up(StackShadowPages * unit, page_size); } bool StackOverflow::stack_guards_enabled() const { -- GitLab From f2a9627c05f9ef82eb83d8c1b9d4209bf42e7d8d Mon Sep 17 00:00:00 2001 From: Masanori Yano Date: Tue, 8 Feb 2022 08:31:10 +0000 Subject: [PATCH 426/564] 8279329: Remove hardcoded IPv4 available policy on Windows Reviewed-by: djelinski, alanb, dfuchs, aefimov --- src/java.base/windows/native/libnet/net_util_md.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/java.base/windows/native/libnet/net_util_md.c b/src/java.base/windows/native/libnet/net_util_md.c index 83e30287196..3282ff64402 100644 --- a/src/java.base/windows/native/libnet/net_util_md.c +++ b/src/java.base/windows/native/libnet/net_util_md.c @@ -215,7 +215,12 @@ NET_GetFileDescriptorID(JNIEnv *env) jint IPv4_supported() { - /* TODO: properly check for IPv4 support on Windows */ + SOCKET s = socket(AF_INET, SOCK_STREAM, 0); + if (s == INVALID_SOCKET) { + return JNI_FALSE; + } + closesocket(s); + return JNI_TRUE; } -- GitLab From 861f2797f7d56ab185117f27dae2660af9250f6a Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Tue, 8 Feb 2022 09:02:53 +0000 Subject: [PATCH 427/564] 8280917: Simplify G1ConcurrentRefineThread activation Reviewed-by: iwalulya, sjohanss --- src/hotspot/share/gc/g1/g1CollectedHeap.cpp | 8 +- .../share/gc/g1/g1ConcurrentRefine.cpp | 68 ++++-- .../share/gc/g1/g1ConcurrentRefine.hpp | 18 +- .../share/gc/g1/g1ConcurrentRefineThread.cpp | 225 +++++++++++++----- .../share/gc/g1/g1ConcurrentRefineThread.hpp | 77 ++++-- src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp | 19 +- src/hotspot/share/gc/g1/g1DirtyCardQueue.hpp | 37 +-- 7 files changed, 300 insertions(+), 152 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index bfa29e39ccc..3d885b862be 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2022, 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 @@ -1726,12 +1726,6 @@ jint G1CollectedHeap::initialize() { _free_segmented_array_memory_task = new G1SegmentedArrayFreeMemoryTask("Card Set Free Memory Task"); _service_thread->register_task(_free_segmented_array_memory_task); - { - G1DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set(); - dcqs.set_process_cards_threshold(concurrent_refine()->yellow_zone()); - dcqs.set_max_cards(concurrent_refine()->red_zone()); - } - // Here we allocate the dummy HeapRegion that is required by the // G1AllocRegion class. HeapRegion* dummy_region = _hrm.get_dummy_region(); diff --git a/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp b/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp index 3393d3b6012..d879568e34c 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2022, 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 @@ -42,7 +42,7 @@ G1ConcurrentRefineThread* G1ConcurrentRefineThreadControl::create_refinement_thread(uint worker_id, bool initializing) { G1ConcurrentRefineThread* result = NULL; if (initializing || !InjectGCWorkerCreationFailure) { - result = new G1ConcurrentRefineThread(_cr, worker_id); + result = G1ConcurrentRefineThread::create(_cr, worker_id); } if (result == NULL || result->osthread() == NULL) { log_warning(gc)("Failed to create refinement thread %u, no more %s", @@ -53,8 +53,9 @@ G1ConcurrentRefineThread* G1ConcurrentRefineThreadControl::create_refinement_thr } G1ConcurrentRefineThreadControl::G1ConcurrentRefineThreadControl() : - _cr(NULL), - _threads(NULL), + _cr(nullptr), + _primary_thread(nullptr), + _threads(nullptr), _num_max_threads(0) { } @@ -76,22 +77,27 @@ jint G1ConcurrentRefineThreadControl::initialize(G1ConcurrentRefine* cr, uint nu _threads = NEW_C_HEAP_ARRAY(G1ConcurrentRefineThread*, num_max_threads, mtGC); - for (uint i = 0; i < num_max_threads; i++) { - if (UseDynamicNumberOfGCThreads && i != 0 /* Always start first thread. */) { - _threads[i] = NULL; - } else { - _threads[i] = create_refinement_thread(i, true); - if (_threads[i] == NULL) { - vm_shutdown_during_initialization("Could not allocate refinement threads."); - return JNI_ENOMEM; + if (num_max_threads > 0) { + auto primary = G1PrimaryConcurrentRefineThread::create(cr); + if (primary == nullptr) { + vm_shutdown_during_initialization("Could not allocate primary refinement thread"); + return JNI_ENOMEM; + } + _threads[0] = _primary_thread = primary; + + for (uint i = 1; i < num_max_threads; ++i) { + if (UseDynamicNumberOfGCThreads) { + _threads[i] = nullptr; + } else { + _threads[i] = create_refinement_thread(i, true); + if (_threads[i] == nullptr) { + vm_shutdown_during_initialization("Could not allocate refinement threads."); + return JNI_ENOMEM; + } } } } - if (num_max_threads > 0) { - G1BarrierSet::dirty_card_queue_set().set_primary_refinement_thread(_threads[0]); - } - return JNI_OK; } @@ -237,7 +243,18 @@ G1ConcurrentRefine::G1ConcurrentRefine(size_t green_zone, } jint G1ConcurrentRefine::initialize() { - return _thread_control.initialize(this, max_num_threads()); + jint result = _thread_control.initialize(this, max_num_threads()); + if (result != JNI_OK) return result; + + G1DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set(); + dcqs.set_max_cards(red_zone()); + if (max_num_threads() > 0) { + G1PrimaryConcurrentRefineThread* primary_thread = _thread_control.primary_thread(); + primary_thread->update_notify_threshold(primary_activation_threshold()); + dcqs.set_refinement_notification_thread(primary_thread); + } + + return JNI_OK; } static size_t calc_min_yellow_zone_size() { @@ -392,14 +409,9 @@ void G1ConcurrentRefine::adjust(double logged_cards_scan_time, update_zones(logged_cards_scan_time, processed_logged_cards, goal_ms); // Change the barrier params - if (max_num_threads() == 0) { - // Disable dcqs notification when there are no threads to notify. - dcqs.set_process_cards_threshold(G1DirtyCardQueueSet::ProcessCardsThresholdNever); - } else { - // Worker 0 is the primary; wakeup is via dcqs notification. - STATIC_ASSERT(max_yellow_zone <= INT_MAX); - size_t activate = activation_threshold(0); - dcqs.set_process_cards_threshold(activate); + if (max_num_threads() > 0) { + size_t threshold = primary_activation_threshold(); + _thread_control.primary_thread()->update_notify_threshold(threshold); } dcqs.set_max_cards(red_zone()); } @@ -411,7 +423,6 @@ void G1ConcurrentRefine::adjust(double logged_cards_scan_time, } else { dcqs.set_max_cards_padding(0); } - dcqs.notify_if_necessary(); } G1ConcurrentRefineStats G1ConcurrentRefine::get_and_reset_refinement_stats() { @@ -438,6 +449,11 @@ size_t G1ConcurrentRefine::deactivation_threshold(uint worker_id) const { return deactivation_level(thresholds); } +size_t G1ConcurrentRefine::primary_activation_threshold() const { + assert(max_num_threads() > 0, "No primary refinement thread"); + return activation_threshold(0); +} + uint G1ConcurrentRefine::worker_id_offset() { return G1DirtyCardQueueSet::num_par_ids(); } diff --git a/src/hotspot/share/gc/g1/g1ConcurrentRefine.hpp b/src/hotspot/share/gc/g1/g1ConcurrentRefine.hpp index b904e47a76a..feb82dd2067 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentRefine.hpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentRefine.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,20 +27,20 @@ #include "gc/g1/g1ConcurrentRefineStats.hpp" #include "memory/allocation.hpp" +#include "utilities/debug.hpp" #include "utilities/globalDefinitions.hpp" -#include "utilities/ticks.hpp" // Forward decl class G1ConcurrentRefine; class G1ConcurrentRefineThread; -class outputStream; +class G1PrimaryConcurrentRefineThread; class ThreadClosure; // Helper class for refinement thread management. Used to start, stop and // iterate over them. class G1ConcurrentRefineThreadControl { G1ConcurrentRefine* _cr; - + G1PrimaryConcurrentRefineThread* _primary_thread; G1ConcurrentRefineThread** _threads; uint _num_max_threads; @@ -53,6 +53,12 @@ public: jint initialize(G1ConcurrentRefine* cr, uint num_max_threads); + G1PrimaryConcurrentRefineThread* primary_thread() const { + assert(_num_max_threads > 0, "precondition"); + assert(_primary_thread != nullptr, "uninitialized"); + return _primary_thread; + } + // If there is a "successor" thread that can be activated given the current id, // activate it. void maybe_activate_next(uint cur_worker_id); @@ -116,6 +122,10 @@ public: void stop(); + // The minimum number of pending cards for activation of the primary + // refinement thread. + size_t primary_activation_threshold() const; + // Adjust refinement thresholds based on work done during the pause and the goal time. void adjust(double logged_cards_scan_time, size_t processed_logged_cards, double goal_ms); diff --git a/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.cpp b/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.cpp index 45defd5e713..ece63ed805a 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2022, 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,8 @@ #include "gc/shared/suspendibleThreadSet.hpp" #include "logging/log.hpp" #include "runtime/atomic.hpp" +#include "runtime/init.hpp" +#include "runtime/safepoint.hpp" #include "runtime/thread.hpp" G1ConcurrentRefineThread::G1ConcurrentRefineThread(G1ConcurrentRefine* cr, uint worker_id) : @@ -39,71 +41,20 @@ G1ConcurrentRefineThread::G1ConcurrentRefineThread(G1ConcurrentRefine* cr, uint _vtime_accum(0.0), _refinement_stats(new G1ConcurrentRefineStats()), _worker_id(worker_id), - _notifier(new Semaphore(0)), - _should_notify(true), _cr(cr) { // set name set_name("G1 Refine#%d", worker_id); - create_and_start(); } G1ConcurrentRefineThread::~G1ConcurrentRefineThread() { delete _refinement_stats; - delete _notifier; -} - -void G1ConcurrentRefineThread::wait_for_completed_buffers() { - assert(this == Thread::current(), "precondition"); - while (Atomic::load_acquire(&_should_notify)) { - _notifier->wait(); - } -} - -void G1ConcurrentRefineThread::activate() { - assert(this != Thread::current(), "precondition"); - // Notify iff transitioning from needing activation to not. This helps - // keep the semaphore count bounded and minimizes the work done by - // activators when the thread is already active. - if (Atomic::load_acquire(&_should_notify) && - Atomic::cmpxchg(&_should_notify, true, false)) { - _notifier->signal(); - } -} - -bool G1ConcurrentRefineThread::maybe_deactivate(bool more_work) { - assert(this == Thread::current(), "precondition"); - - if (more_work) { - // Suppress unnecessary notifications. - Atomic::release_store(&_should_notify, false); - return false; - } else if (Atomic::load_acquire(&_should_notify)) { - // Deactivate if no notifications since enabled (see below). - return true; - } else { - // Try for more refinement work with notifications enabled, to close - // race; there could be a plethora of suppressed activation attempts - // after we found no work but before we enable notifications here - // (so there could be lots of work for this thread to do), followed - // by a long time without activation after enabling notifications. - // But first, clear any pending signals to prevent accumulation. - while (_notifier->trywait()) {} - Atomic::release_store(&_should_notify, true); - return false; - } } void G1ConcurrentRefineThread::run_service() { _vtime_start = os::elapsedVTime(); - while (!should_terminate()) { - // Wait for work - wait_for_completed_buffers(); - if (should_terminate()) { - break; - } - + while (wait_for_completed_buffers()) { // For logging. G1ConcurrentRefineStats start_stats = *_refinement_stats; G1ConcurrentRefineStats total_stats; // Accumulate over activation. @@ -125,8 +76,11 @@ void G1ConcurrentRefineThread::run_service() { continue; // Re-check for termination after yield delay. } - bool more_work = _cr->do_refinement_step(_worker_id, _refinement_stats); - if (maybe_deactivate(more_work)) break; + if (!_cr->do_refinement_step(_worker_id, _refinement_stats)) { + if (maybe_deactivate()) { + break; + } + } } } @@ -151,3 +105,164 @@ void G1ConcurrentRefineThread::run_service() { void G1ConcurrentRefineThread::stop_service() { activate(); } + +G1PrimaryConcurrentRefineThread* +G1PrimaryConcurrentRefineThread::create(G1ConcurrentRefine* cr) { + G1PrimaryConcurrentRefineThread* crt = + new (std::nothrow) G1PrimaryConcurrentRefineThread(cr); + if (crt != nullptr) { + crt->create_and_start(); + } + return crt; +} + +G1PrimaryConcurrentRefineThread::G1PrimaryConcurrentRefineThread(G1ConcurrentRefine* cr) : + G1ConcurrentRefineThread(cr, 0), + _notifier(0), + _threshold(0) +{} + +void G1PrimaryConcurrentRefineThread::stop_service() { + G1DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set(); + dcqs.set_refinement_notification_thread(nullptr); + G1ConcurrentRefineThread::stop_service(); +} + +// The primary refinement thread is notified when buffers/cards are added to +// the dirty card queue. That can happen in fairly arbitrary contexts. +// This means there may be arbitrary other locks held when notifying. We +// also don't want to have to take a lock on the fairly common notification +// path, as contention for that lock can significantly impact performance. +// +// We use a semaphore to implement waiting and unblocking, to avoid +// lock rank checking issues. (We could alternatively use an +// arbitrarily low ranked mutex.) The atomic variable _threshold is +// used to decide when to signal the semaphore. When its value is +// SIZE_MAX then the thread is running. Otherwise, the thread should +// be requested to run when notified that the number of cards has +// exceeded the threshold value. + +bool G1PrimaryConcurrentRefineThread::wait_for_completed_buffers() { + assert(this == Thread::current(), "precondition"); + _notifier.wait(); + assert(Atomic::load(&_threshold) == SIZE_MAX || should_terminate(), "incorrect state"); + return !should_terminate(); +} + +bool G1PrimaryConcurrentRefineThread::maybe_deactivate() { + assert(this == Thread::current(), "precondition"); + assert(Atomic::load(&_threshold) == SIZE_MAX, "incorrect state"); + Atomic::store(&_threshold, cr()->primary_activation_threshold()); + // Always deactivate when no refinement work found. New refinement + // work may have arrived after we tried, but checking for that would + // still be racy. Instead, the next time additional work is made + // available we'll get reactivated. + return true; +} + +void G1PrimaryConcurrentRefineThread::activate() { + assert(this != Thread::current(), "precondition"); + // The thread is running when notifications are disabled, so shouldn't + // signal is this case. But there's a race between stop requests and + // maybe_deactivate, so also signal if stop requested. + size_t threshold = Atomic::load(&_threshold); + if (((threshold != SIZE_MAX) && + (threshold == Atomic::cmpxchg(&_threshold, threshold, SIZE_MAX))) || + should_terminate()) { + _notifier.signal(); + } +} + +void G1PrimaryConcurrentRefineThread::notify(size_t num_cards) { + // Only activate if the number of pending cards exceeds the activation + // threshold. Notification is disabled when the thread is running, by + // setting _threshold to SIZE_MAX. A relaxed load is sufficient; we don't + // need to be precise about this. + if (num_cards > Atomic::load(&_threshold)) { + // Discard notifications occurring during a safepoint. A GC safepoint + // may dirty some cards (such as during reference processing), possibly + // leading to notification. End-of-GC update_notify_threshold activates + // the primary thread if needed. Non-GC safepoints are expected to + // rarely (if ever) dirty cards, so defer activation to a post-safepoint + // notification. + if (!SafepointSynchronize::is_at_safepoint()) { + activate(); + } + } +} + +void G1PrimaryConcurrentRefineThread::update_notify_threshold(size_t threshold) { +#ifdef ASSERT + if (is_init_completed()) { + assert_at_safepoint(); + assert(Thread::current()->is_VM_thread(), "precondition"); + } +#endif // ASSERT + // If _threshold is SIZE_MAX then the thread is active and the value + // of _threshold shouldn't be changed. + if (Atomic::load(&_threshold) != SIZE_MAX) { + Atomic::store(&_threshold, threshold); + if (G1BarrierSet::dirty_card_queue_set().num_cards() > threshold) { + activate(); + } + } +} + +class G1SecondaryConcurrentRefineThread final : public G1ConcurrentRefineThread { + Monitor _notifier; + bool _requested_active; + + bool wait_for_completed_buffers() override; + bool maybe_deactivate() override; + +public: + G1SecondaryConcurrentRefineThread(G1ConcurrentRefine* cr, uint worker_id); + + void activate() override; +}; + +G1SecondaryConcurrentRefineThread::G1SecondaryConcurrentRefineThread(G1ConcurrentRefine* cr, + uint worker_id) : + G1ConcurrentRefineThread(cr, worker_id), + _notifier(Mutex::nosafepoint, this->name(), true), + _requested_active(false) +{ + assert(worker_id > 0, "precondition"); +} + +bool G1SecondaryConcurrentRefineThread::wait_for_completed_buffers() { + assert(this == Thread::current(), "precondition"); + MonitorLocker ml(&_notifier, Mutex::_no_safepoint_check_flag); + while (!_requested_active && !should_terminate()) { + ml.wait(); + } + return !should_terminate(); +} + +void G1SecondaryConcurrentRefineThread::activate() { + assert(this != Thread::current(), "precondition"); + MonitorLocker ml(&_notifier, Mutex::_no_safepoint_check_flag); + if (!_requested_active || should_terminate()) { + _requested_active = true; + ml.notify(); + } +} + +bool G1SecondaryConcurrentRefineThread::maybe_deactivate() { + assert(this == Thread::current(), "precondition"); + MutexLocker ml(&_notifier, Mutex::_no_safepoint_check_flag); + bool requested = _requested_active; + _requested_active = false; + return !requested; // Deactivate if not recently requested active. +} + +G1ConcurrentRefineThread* +G1ConcurrentRefineThread::create(G1ConcurrentRefine* cr, uint worker_id) { + assert(worker_id > 0, "precondition"); + G1ConcurrentRefineThread* crt = + new (std::nothrow) G1SecondaryConcurrentRefineThread(cr, worker_id); + if (crt != nullptr) { + crt->create_and_start(); + } + return crt; +} diff --git a/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.hpp b/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.hpp index cdcab6b2285..218609dd76c 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.hpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,9 @@ #define SHARE_GC_G1_G1CONCURRENTREFINETHREAD_HPP #include "gc/shared/concurrentGCThread.hpp" -#include "utilities/ticks.hpp" +#include "memory/padded.hpp" +#include "runtime/semaphore.hpp" +#include "utilities/macros.hpp" // Forward Decl. class G1ConcurrentRefine; @@ -45,36 +47,34 @@ class G1ConcurrentRefineThread: public ConcurrentGCThread { uint _worker_id; - // _notifier and _should_notify form a single-reader / multi-writer - // notification mechanism. The owning concurrent refinement thread is the - // single reader. The writers are (other) threads that call activate() on - // the thread. The i-th concurrent refinement thread is responsible for - // activating thread i+1 if the number of buffers in the queue exceeds a - // threshold for that i+1th thread. The 0th (primary) thread is activated - // by threads that add cards to the dirty card queue set when the primary - // thread's threshold is exceeded. activate() is also used to wake up the - // threads during termination, so even the non-primary thread case is - // multi-writer. - Semaphore* _notifier; - volatile bool _should_notify; + G1ConcurrentRefine* _cr; + + NONCOPYABLE(G1ConcurrentRefineThread); + +protected: + G1ConcurrentRefineThread(G1ConcurrentRefine* cr, uint worker_id); + + // Returns !should_terminate(). + // precondition: this is the current thread. + virtual bool wait_for_completed_buffers() = 0; // Called when no refinement work found for this thread. // Returns true if should deactivate. - bool maybe_deactivate(bool more_work); + // precondition: this is the current thread. + virtual bool maybe_deactivate() = 0; - G1ConcurrentRefine* _cr; - - void wait_for_completed_buffers(); + G1ConcurrentRefine* cr() const { return _cr; } - virtual void run_service(); - virtual void stop_service(); + void run_service() override; + void stop_service() override; public: - G1ConcurrentRefineThread(G1ConcurrentRefine* cg1r, uint worker_id); + static G1ConcurrentRefineThread* create(G1ConcurrentRefine* cr, uint worker_id); virtual ~G1ConcurrentRefineThread(); // Activate this thread. - void activate(); + // precondition: this is not the current thread. + virtual void activate() = 0; G1ConcurrentRefineStats* refinement_stats() const { return _refinement_stats; @@ -84,4 +84,37 @@ public: double vtime_accum() { return _vtime_accum; } }; +// Singleton special refinement thread, registered with the dirty card queue. +// This thread supports notification of increases to the number of cards in +// the dirty card queue, which may trigger activation of this thread when it +// is not already running. +class G1PrimaryConcurrentRefineThread final : public G1ConcurrentRefineThread { + // Support for activation. The thread waits on this semaphore when idle. + // Calls to activate signal it to wake the thread. + Semaphore _notifier; + DEFINE_PAD_MINUS_SIZE(0, DEFAULT_CACHE_LINE_SIZE, 0); + // Used as both the activation threshold and also the "is active" state. + // The value is SIZE_MAX when the thread is active, otherwise the threshold + // for signaling the semaphore. + volatile size_t _threshold; + DEFINE_PAD_MINUS_SIZE(1, DEFAULT_CACHE_LINE_SIZE, sizeof(size_t)); + + bool wait_for_completed_buffers() override; + bool maybe_deactivate() override; + + G1PrimaryConcurrentRefineThread(G1ConcurrentRefine* cr); + + void stop_service() override; + +public: + static G1PrimaryConcurrentRefineThread* create(G1ConcurrentRefine* cr); + + void activate() override; + + // Used by the write barrier support to activate the thread if needed when + // there are new refinement buffers. + void notify(size_t num_cards); + void update_notify_threshold(size_t threshold); +}; + #endif // SHARE_GC_G1_G1CONCURRENTREFINETHREAD_HPP diff --git a/src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp b/src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp index 22e8e218057..136f5849dbb 100644 --- a/src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp +++ b/src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp @@ -66,12 +66,11 @@ static uint par_ids_start() { return 0; } G1DirtyCardQueueSet::G1DirtyCardQueueSet(BufferNode::Allocator* allocator) : PtrQueueSet(allocator), - _primary_refinement_thread(NULL), + _refinement_notification_thread(nullptr), _num_cards(0), _completed(), _paused(), _free_ids(par_ids_start(), num_par_ids()), - _process_cards_threshold(ProcessCardsThresholdNever), _max_cards(MaxCardsUnlimited), _padded_max_cards(MaxCardsUnlimited), _detached_refinement_stats() @@ -118,6 +117,10 @@ void G1DirtyCardQueueSet::handle_zero_index_for_thread(Thread* t) { G1BarrierSet::dirty_card_queue_set().handle_zero_index(queue); } +size_t G1DirtyCardQueueSet::num_cards() const { + return Atomic::load(&_num_cards); +} + void G1DirtyCardQueueSet::enqueue_completed_buffer(BufferNode* cbn) { assert(cbn != NULL, "precondition"); // Increment _num_cards before adding to queue, so queue removal doesn't @@ -130,9 +133,8 @@ void G1DirtyCardQueueSet::enqueue_completed_buffer(BufferNode* cbn) { GlobalCounter::CriticalSection cs(Thread::current()); _completed.push(*cbn); } - if ((new_num_cards > process_cards_threshold()) && - (_primary_refinement_thread != NULL)) { - _primary_refinement_thread->activate(); + if (_refinement_notification_thread != nullptr) { + _refinement_notification_thread->notify(new_num_cards); } } @@ -323,13 +325,6 @@ void G1DirtyCardQueueSet::abandon_completed_buffers() { } } -void G1DirtyCardQueueSet::notify_if_necessary() { - if ((_primary_refinement_thread != NULL) && - (num_cards() > process_cards_threshold())) { - _primary_refinement_thread->activate(); - } -} - // Merge lists of buffers. The source queue set is emptied as a // result. The queue sets must share the same allocator. void G1DirtyCardQueueSet::merge_bufferlists(G1RedirtyCardsQueueSet* src) { diff --git a/src/hotspot/share/gc/g1/g1DirtyCardQueue.hpp b/src/hotspot/share/gc/g1/g1DirtyCardQueue.hpp index 051e29058eb..097efe957f7 100644 --- a/src/hotspot/share/gc/g1/g1DirtyCardQueue.hpp +++ b/src/hotspot/share/gc/g1/g1DirtyCardQueue.hpp @@ -34,7 +34,7 @@ #include "memory/padded.hpp" #include "utilities/nonblockingQueue.hpp" -class G1ConcurrentRefineThread; +class G1PrimaryConcurrentRefineThread; class G1DirtyCardQueueSet; class G1RedirtyCardsQueueSet; class Thread; @@ -156,10 +156,10 @@ class G1DirtyCardQueueSet: public PtrQueueSet { HeadTail take_all(); }; - // The primary refinement thread, for activation when the processing - // threshold is reached. NULL if there aren't any refinement threads. - G1ConcurrentRefineThread* _primary_refinement_thread; - DEFINE_PAD_MINUS_SIZE(1, DEFAULT_CACHE_LINE_SIZE, sizeof(G1ConcurrentRefineThread*)); + // The refinement notification thread, for activation when the notification + // threshold is reached. nullptr if there aren't any refinement threads. + G1PrimaryConcurrentRefineThread* _refinement_notification_thread; + DEFINE_PAD_MINUS_SIZE(1, DEFAULT_CACHE_LINE_SIZE, sizeof(G1PrimaryConcurrentRefineThread*)); // Upper bound on the number of cards in the completed and paused buffers. volatile size_t _num_cards; DEFINE_PAD_MINUS_SIZE(2, DEFAULT_CACHE_LINE_SIZE, sizeof(size_t)); @@ -174,9 +174,6 @@ class G1DirtyCardQueueSet: public PtrQueueSet { G1FreeIdSet _free_ids; - // Activation threshold for the primary refinement thread. - size_t _process_cards_threshold; - // If the queue contains more cards than configured here, the // mutator must start doing some of the concurrent refinement work. size_t _max_cards; @@ -242,10 +239,6 @@ public: G1DirtyCardQueueSet(BufferNode::Allocator* allocator); ~G1DirtyCardQueueSet(); - void set_primary_refinement_thread(G1ConcurrentRefineThread* thread) { - _primary_refinement_thread = thread; - } - // The number of parallel ids that can be claimed to allow collector or // mutator threads to do card-processing work. static uint num_par_ids(); @@ -254,24 +247,16 @@ public: virtual void enqueue_completed_buffer(BufferNode* node); - // Upper bound on the number of cards currently in in this queue set. + // Upper bound on the number of cards currently in this queue set. // Read without synchronization. The value may be high because there // is a concurrent modification of the set of buffers. - size_t num_cards() const { return _num_cards; } + size_t num_cards() const; - // Get/Set the number of cards that triggers log processing. - // Log processing should be done when the number of cards exceeds the - // threshold. - void set_process_cards_threshold(size_t sz) { - _process_cards_threshold = sz; + // Record the primary concurrent refinement thread. This is the thread to + // be notified when num_cards() exceeds the refinement notification threshold. + void set_refinement_notification_thread(G1PrimaryConcurrentRefineThread* thread) { + _refinement_notification_thread = thread; } - size_t process_cards_threshold() const { - return _process_cards_threshold; - } - static const size_t ProcessCardsThresholdNever = SIZE_MAX; - - // Notify the consumer if the number of buffers crossed the threshold - void notify_if_necessary(); void merge_bufferlists(G1RedirtyCardsQueueSet* src); -- GitLab From f5d8cebbb6f1b38247c3b30ba8859874a0e98115 Mon Sep 17 00:00:00 2001 From: Manukumar V S Date: Tue, 8 Feb 2022 12:39:43 +0000 Subject: [PATCH 428/564] 8281296: Create a regression test for JDK-4515999 Reviewed-by: aivanov --- .../4515999/JSpinnerMouseAndKeyPressTest.java | 201 ++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100644 test/jdk/javax/swing/JSpinner/4515999/JSpinnerMouseAndKeyPressTest.java diff --git a/test/jdk/javax/swing/JSpinner/4515999/JSpinnerMouseAndKeyPressTest.java b/test/jdk/javax/swing/JSpinner/4515999/JSpinnerMouseAndKeyPressTest.java new file mode 100644 index 00000000000..6e5fb3ad97f --- /dev/null +++ b/test/jdk/javax/swing/JSpinner/4515999/JSpinnerMouseAndKeyPressTest.java @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.ComponentOrientation; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Date; +import java.util.List; +import java.util.stream.Collectors; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JSpinner; +import javax.swing.SpinnerDateModel; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; + + +import static javax.swing.UIManager.getInstalledLookAndFeels; + +/* + * @test + * @key headful + * @bug 4515999 + * @summary Check whether incrementing dates via the keyboard (up/down) gives + * the same results as using mouse press on the arrow buttons in a JSpinner. + * @run main JSpinnerMouseAndKeyPressTest + */ +public class JSpinnerMouseAndKeyPressTest { + // 2 days in milliseconds + private static final int EXPECTED_VALUE_2_DAYS = 2 * 24 * 60 * 60 * 1000; + + private static JFrame frame; + private static JSpinner spinner; + private static volatile Point spinnerUpButtonCenter; + private static volatile Point spinnerDownButtonCenter; + private static volatile Date spinnerValue; + + public static void main(String[] s) throws Exception { + runTest(); + } + + private static void setLookAndFeel(final String laf) { + try { + UIManager.setLookAndFeel(laf); + System.out.println("LookAndFeel: " + laf); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private static void createUI() { + frame = new JFrame(); + JPanel panel = new JPanel(); + spinner = new JSpinner(); + spinner.setModel(new DateModel()); + JSpinner.DateEditor editor = new JSpinner.DateEditor(spinner, "dd/MM/yy"); + spinner.setEditor(editor); + spinner.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT); + panel.add(spinner); + frame.add(panel); + frame.setUndecorated(true); + frame.pack(); + frame.setAlwaysOnTop(true); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + + public static void runTest() throws Exception { + Robot robot = new Robot(); + robot.setAutoWaitForIdle(true); + robot.setAutoDelay(100); + List lafs = Arrays.stream(getInstalledLookAndFeels()) + .map(UIManager.LookAndFeelInfo::getClassName) + .collect(Collectors.toList()); + for (final String laf : lafs) { + try { + SwingUtilities.invokeAndWait(() -> { + setLookAndFeel(laf); + createUI(); + }); + + SwingUtilities.invokeAndWait(() -> { + Point loc = spinner.getLocationOnScreen(); + int editorWidth = spinner.getEditor().getWidth(); + int buttonWidth = spinner.getWidth() - editorWidth; + int quarterHeight = spinner.getHeight() / 4; + + spinnerUpButtonCenter = new Point(loc.x + editorWidth + + (buttonWidth / 2), + loc.y + quarterHeight); + spinnerDownButtonCenter = new Point(spinnerUpButtonCenter.x, + loc.y + (3 * quarterHeight)); + }); + + // Mouse press use-case + // Move Mouse pointer to UP button center and click it + robot.mouseMove(spinnerUpButtonCenter.x, spinnerUpButtonCenter.y); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + + updateSpinnerValue(); + long upValue = spinnerValue.getTime(); + + // Move Mouse pointer to DOWN button center and click it + robot.mouseMove(spinnerDownButtonCenter.x, spinnerDownButtonCenter.y); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + + updateSpinnerValue(); + long downValue = spinnerValue.getTime(); + + long mouseIncrement = upValue - downValue; + + // Key press use-case + // Up Key press + robot.keyPress(KeyEvent.VK_UP); + robot.keyRelease(KeyEvent.VK_UP); + + updateSpinnerValue(); + upValue = spinnerValue.getTime(); + + // Down Key press + robot.keyPress(KeyEvent.VK_DOWN); + robot.keyRelease(KeyEvent.VK_DOWN); + + updateSpinnerValue(); + downValue = spinnerValue.getTime(); + + long keyIncrement = upValue - downValue; + + if ((keyIncrement == EXPECTED_VALUE_2_DAYS) && + (mouseIncrement == EXPECTED_VALUE_2_DAYS)) { + System.out.println("Test passed"); + } else { + throw new RuntimeException("Test failed because keyIncrement: " + + keyIncrement + " and mouseIncrement: " + + mouseIncrement + " should match with the expected value " + + EXPECTED_VALUE_2_DAYS + " for LnF " + laf); + } + + } finally { + SwingUtilities.invokeAndWait(JSpinnerMouseAndKeyPressTest::disposeFrame); + } + } + } + + private static void updateSpinnerValue() throws Exception { + SwingUtilities.invokeAndWait(() -> spinnerValue = (Date) spinner.getValue()); + } + + private static void disposeFrame() { + if (frame != null) { + frame.dispose(); + frame = null; + } + } + + private static class DateModel extends SpinnerDateModel { + + private final Calendar cal = Calendar.getInstance(); + + @Override + public Object getNextValue() { + cal.setTime(getDate()); + cal.add(Calendar.DAY_OF_MONTH, 2); // Increment two days + return cal.getTime(); + } + + @Override + public Object getPreviousValue() { + cal.setTime(getDate()); + cal.add(Calendar.DAY_OF_MONTH, -2); // Decrement two days + return cal.getTime(); + } + } +} -- GitLab From 83d67452da248db17bc72de80247a670d6813cf5 Mon Sep 17 00:00:00 2001 From: Thomas Stuefe Date: Tue, 8 Feb 2022 14:43:45 +0000 Subject: [PATCH 429/564] 8281450: Remove unnecessary operator new and delete from ObjectMonitor Reviewed-by: dholmes --- src/hotspot/share/runtime/objectMonitor.cpp | 15 +-------------- src/hotspot/share/runtime/objectMonitor.hpp | 7 +------ 2 files changed, 2 insertions(+), 20 deletions(-) diff --git a/src/hotspot/share/runtime/objectMonitor.cpp b/src/hotspot/share/runtime/objectMonitor.cpp index e56b18a84c9..a6e279cfcb2 100644 --- a/src/hotspot/share/runtime/objectMonitor.cpp +++ b/src/hotspot/share/runtime/objectMonitor.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2022, 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 @@ -233,19 +233,6 @@ OopStorage* ObjectMonitor::_oop_storage = NULL; // * See also http://blogs.sun.com/dave -void* ObjectMonitor::operator new (size_t size) throw() { - return AllocateHeap(size, mtInternal); -} -void* ObjectMonitor::operator new[] (size_t size) throw() { - return operator new (size); -} -void ObjectMonitor::operator delete(void* p) { - FreeHeap(p); -} -void ObjectMonitor::operator delete[] (void *p) { - operator delete(p); -} - // Check that object() and set_object() are called from the right context: static void check_object_context() { #ifdef ASSERT diff --git a/src/hotspot/share/runtime/objectMonitor.hpp b/src/hotspot/share/runtime/objectMonitor.hpp index 4f85c429b70..4ca4cc28c86 100644 --- a/src/hotspot/share/runtime/objectMonitor.hpp +++ b/src/hotspot/share/runtime/objectMonitor.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2022, 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 @@ -203,11 +203,6 @@ class ObjectMonitor : public CHeapObj { static int Knob_SpinLimit; - void* operator new (size_t size) throw(); - void* operator new[] (size_t size) throw(); - void operator delete(void* p); - void operator delete[] (void* p); - // TODO-FIXME: the "offset" routines should return a type of off_t instead of int ... // ByteSize would also be an appropriate type. static int header_offset_in_bytes() { return offset_of(ObjectMonitor, _header); } -- GitLab From 380378c551b4243ef72d868571f725b390e12124 Mon Sep 17 00:00:00 2001 From: Harold Seigel Date: Tue, 8 Feb 2022 16:00:58 +0000 Subject: [PATCH 430/564] 8281400: Remove unused wcslen() function Reviewed-by: dcubed, coleenp, lfoltan --- src/hotspot/share/utilities/globalDefinitions_gcc.hpp | 7 +------ src/hotspot/share/utilities/globalDefinitions_xlc.hpp | 6 +----- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/src/hotspot/share/utilities/globalDefinitions_gcc.hpp b/src/hotspot/share/utilities/globalDefinitions_gcc.hpp index 30cca9ee7ae..4aed8605182 100644 --- a/src/hotspot/share/utilities/globalDefinitions_gcc.hpp +++ b/src/hotspot/share/utilities/globalDefinitions_gcc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2022, 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 @@ -127,11 +127,6 @@ inline int g_isfinite(jfloat f) { return isfinite(f); } inline int g_isfinite(jdouble f) { return isfinite(f); } -// Wide characters - -inline int wcslen(const jchar* x) { return wcslen((const wchar_t*)x); } - - // Formatting. #ifdef _LP64 # ifdef __APPLE__ diff --git a/src/hotspot/share/utilities/globalDefinitions_xlc.hpp b/src/hotspot/share/utilities/globalDefinitions_xlc.hpp index 4bfb6a2d5df..80c27729c7d 100644 --- a/src/hotspot/share/utilities/globalDefinitions_xlc.hpp +++ b/src/hotspot/share/utilities/globalDefinitions_xlc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2021 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -109,10 +109,6 @@ inline int g_isnan(double f) { return isnan(f); } inline int g_isfinite(jfloat f) { return finite(f); } inline int g_isfinite(jdouble f) { return finite(f); } -// Wide characters -inline int wcslen(const jchar* x) { return wcslen((const wchar_t*)x); } - - // Formatting. #ifdef _LP64 #define FORMAT64_MODIFIER "l" -- GitLab From 7f19c700707573000a37910dd6d2f2bb6e8439ad Mon Sep 17 00:00:00 2001 From: Martin Doerr Date: Tue, 8 Feb 2022 17:48:48 +0000 Subject: [PATCH 431/564] 8281061: [s390] JFR runs into assertions while validating interpreter frames Reviewed-by: lucy, rrich --- src/hotspot/cpu/s390/frame_s390.cpp | 18 ++++++++---------- .../os_cpu/linux_s390/thread_linux_s390.cpp | 13 +++++++------ 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/src/hotspot/cpu/s390/frame_s390.cpp b/src/hotspot/cpu/s390/frame_s390.cpp index bfb38ffcdaf..3588915f79d 100644 --- a/src/hotspot/cpu/s390/frame_s390.cpp +++ b/src/hotspot/cpu/s390/frame_s390.cpp @@ -117,8 +117,8 @@ bool frame::safe_for_sender(JavaThread *thread) { return false; } - z_abi_160* sender_abi = (z_abi_160*) fp; - intptr_t* sender_sp = (intptr_t*) sender_abi->callers_sp; + z_abi_16* sender_abi = (z_abi_16*)fp; + intptr_t* sender_sp = (intptr_t*) fp; address sender_pc = (address) sender_abi->return_pc; // We must always be able to find a recognizable pc. @@ -142,7 +142,7 @@ bool frame::safe_for_sender(JavaThread *thread) { // sender_fp must be within the stack and above (but not // equal) current frame's fp. if (!thread->is_in_stack_range_excl(sender_fp, fp)) { - return false; + return false; } // If the potential sender is the interpreter then we can do some more checking. @@ -319,8 +319,8 @@ bool frame::is_interpreted_frame_valid(JavaThread* thread) const { // do some validation of frame elements // first the method - - Method* m = *interpreter_frame_method_addr(); + // Need to use "unchecked" versions to avoid "z_istate_magic_number" assertion. + Method* m = (Method*)(ijava_state_unchecked()->method); // validate the method we'd find in this potential sender if (!Method::is_valid_method(m)) return false; @@ -335,19 +335,17 @@ bool frame::is_interpreted_frame_valid(JavaThread* thread) const { } // validate bci/bcx - - address bcp = interpreter_frame_bcp(); + address bcp = (address)(ijava_state_unchecked()->bcp); if (m->validate_bci_from_bcp(bcp) < 0) { return false; } // validate constantPoolCache* - ConstantPoolCache* cp = *interpreter_frame_cache_addr(); + ConstantPoolCache* cp = (ConstantPoolCache*)(ijava_state_unchecked()->cpoolCache); if (MetaspaceObj::is_valid(cp) == false) return false; // validate locals - - address locals = (address) *interpreter_frame_locals_addr(); + address locals = (address)(ijava_state_unchecked()->locals); return thread->is_in_stack_range_incl(locals, (address)fp()); } diff --git a/src/hotspot/os_cpu/linux_s390/thread_linux_s390.cpp b/src/hotspot/os_cpu/linux_s390/thread_linux_s390.cpp index d06b851a99f..3b16096784f 100644 --- a/src/hotspot/os_cpu/linux_s390/thread_linux_s390.cpp +++ b/src/hotspot/os_cpu/linux_s390/thread_linux_s390.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016, 2019 SAP SE. All rights reserved. + * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -58,14 +58,15 @@ bool JavaThread::pd_get_top_frame_for_profiling(frame* fr_addr, void* ucontext, // if we were running Java code when SIGPROF came in. if (isInJava) { ucontext_t* uc = (ucontext_t*) ucontext; - frame ret_frame((intptr_t*)uc->uc_mcontext.gregs[15/*Z_SP*/], - (address)uc->uc_mcontext.psw.addr); + address pc = (address)uc->uc_mcontext.psw.addr; - if (ret_frame.pc() == NULL) { + if (pc == NULL) { // ucontext wasn't useful return false; } + frame ret_frame((intptr_t*)uc->uc_mcontext.gregs[15/*Z_SP*/], pc); + if (ret_frame.fp() == NULL) { // The found frame does not have a valid frame pointer. // Bail out because this will create big trouble later on, either @@ -100,7 +101,7 @@ bool JavaThread::pd_get_top_frame_for_profiling(frame* fr_addr, void* ucontext, if (ret_frame.is_interpreted_frame()) { frame::z_ijava_state* istate = ret_frame.ijava_state_unchecked(); - if (is_in_full_stack((address)istate)) { + if (!is_in_full_stack((address)istate)) { return false; } const Method *m = (const Method*)(istate->method); -- GitLab From 92f4f40da6c4ff55c7ed334007c9c6ca0dc15d99 Mon Sep 17 00:00:00 2001 From: Christian Stein Date: Tue, 8 Feb 2022 17:53:42 +0000 Subject: [PATCH 432/564] 8281104: jar --create should create missing parent directories Reviewed-by: lancea --- .../share/classes/sun/tools/jar/Main.java | 15 ++- .../sun/tools/jar/resources/jar.properties | 6 +- .../jar/CreateMissingParentDirectories.java | 114 ++++++++++++++++++ 3 files changed, 128 insertions(+), 7 deletions(-) create mode 100644 test/jdk/tools/jar/CreateMissingParentDirectories.java diff --git a/src/jdk.jartool/share/classes/sun/tools/jar/Main.java b/src/jdk.jartool/share/classes/sun/tools/jar/Main.java index 3436c01928b..c582f2d80ce 100644 --- a/src/jdk.jartool/share/classes/sun/tools/jar/Main.java +++ b/src/jdk.jartool/share/classes/sun/tools/jar/Main.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2022, 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 @@ -427,10 +427,10 @@ public class Main { fatalError(e); ok = false; } catch (Error ee) { - ee.printStackTrace(); + ee.printStackTrace(err); ok = false; } catch (Throwable t) { - t.printStackTrace(); + t.printStackTrace(err); ok = false; } finally { if (tmpFile != null && tmpFile.exists()) @@ -461,7 +461,12 @@ public class Main { try { if (ok) { if (fname != null) { - Files.move(path, Paths.get(fname), StandardCopyOption.REPLACE_EXISTING); + Path target = Paths.get(fname); + Path parent = target.getParent(); + if (parent != null) { + Files.createDirectories(parent); + } + Files.move(path, target, StandardCopyOption.REPLACE_EXISTING); } else { Files.copy(path, new FileOutputStream(FileDescriptor.out)); } @@ -1653,7 +1658,7 @@ public class Main { * A fatal exception has been caught. No recovery possible */ void fatalError(Exception e) { - e.printStackTrace(); + e.printStackTrace(err); } /** diff --git a/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties b/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties index 87bff689102..c08c6ff7f06 100644 --- a/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties +++ b/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties @@ -169,7 +169,7 @@ usage.compat=\ \n\ Usage: jar {ctxui}[vfmn0PMe] [jar-file] [manifest-file] [entry-point] [-C dir] files] ...\n\ Options:\n\ -\ \ -c create new archive\n\ +\ \ -c create new archive (including missing parent directories)\n\ \ \ -t list table of contents for archive\n\ \ \ -x extract named (or all) files from archive\n\ \ \ -u update existing archive\n\ @@ -227,7 +227,9 @@ text file and pass it to the jar command with the at sign (@) as a prefix.\n\ main.help.opt.main=\ \ Main operation mode:\n main.help.opt.main.create=\ -\ -c, --create Create the archive +\ -c, --create Create the archive. When the archive file name specified\n\ +\ by -f or --file contains a path, missing parent directories\n\ +\ will also be created main.help.opt.main.generate-index=\ \ -i, --generate-index=FILE Generate index information for the specified jar\n\ \ archives diff --git a/test/jdk/tools/jar/CreateMissingParentDirectories.java b/test/jdk/tools/jar/CreateMissingParentDirectories.java new file mode 100644 index 00000000000..93d6d4ce01d --- /dev/null +++ b/test/jdk/tools/jar/CreateMissingParentDirectories.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2022, 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 8281104 + * @modules jdk.jartool + * @summary jar --create --file a/b/test.jar should create directories a/b + */ + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.spi.ToolProvider; +import java.util.stream.Stream; + +public class CreateMissingParentDirectories { + private static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar") + .orElseThrow(() -> + new RuntimeException("jar tool not found") + ); + + /** + * Remove dirs & files needed for test. + */ + private static void cleanup(Path dir) { + try { + if (Files.isDirectory(dir)) { + try (Stream s = Files.list(dir)) { + s.forEach(p -> cleanup(p)); + } + } + Files.delete(dir); + } catch (Exception x) { + fail(x.toString()); + } + } + + public static void realMain(String[] args) throws Throwable { + Path topDir = Files.createTempDirectory("delete"); + try { + Path entry = Files.writeString(topDir.resolve("test.txt"), "Some text..."); + + doHappyPathTest(topDir.resolve("test.jar"), entry); + doHappyPathTest(topDir.resolve("a/test.jar"), entry); + doHappyPathTest(topDir.resolve("a/b/test.jar"), entry); + + doFailingTest(topDir.toString() + "/a/*/test.jar", entry); + Path blocker = Files.writeString(topDir.resolve("blocker.txt"), "Blocked!"); + doFailingTest(topDir.resolve("blocker.txt/test.jar").toString(), entry); + } finally { + cleanup(topDir); + } + } + + private static void doHappyPathTest(Path jar, Path entry) throws Throwable { + String[] jarArgs = new String[]{"cf", jar.toString(), entry.toString()}; + if (JAR_TOOL.run(System.out, System.err, jarArgs) != 0) { + fail("Could not create jar file: " + jar); + return; + } + pass(); + } + + private static void doFailingTest(String jar, Path entry) throws Throwable { + StringWriter out = new StringWriter(); + StringWriter err = new StringWriter(); + String[] jarArgs = new String[]{"cf", jar, entry.toString()}; + + if (JAR_TOOL.run(new PrintWriter(out, true), new PrintWriter(err, true), jarArgs) == 0) { + fail("Should have failed creating jar file: " + jar); + return; + } + // non-zero exit code expected, check error message contains jar file's name + check(err.toString().contains(jar)); + pass(); + } + + //--------------------- Infrastructure --------------------------- + static volatile int passed = 0, failed = 0; + static void pass() {passed++;} + static void fail() {failed++; Thread.dumpStack();} + static void fail(String msg) {System.out.println(msg); fail();} + static void unexpected(Throwable t) {failed++; t.printStackTrace();} + static void check(boolean cond) {if (cond) pass(); else fail();} + static void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) pass(); + else fail(x + " not equal to " + y);} + public static void main(String[] args) throws Throwable { + try {realMain(args);} catch (Throwable t) {unexpected(t);} + System.out.println("\nPassed = " + passed + " failed = " + failed); + if (failed > 0) throw new AssertionError("Some tests failed");} +} -- GitLab From 5fb56dbb0b4e3345ca6f48ba9c01bd467f04aa6f Mon Sep 17 00:00:00 2001 From: "Daniel D. Daugherty" Date: Tue, 8 Feb 2022 20:16:34 +0000 Subject: [PATCH 433/564] 8281476: ProblemList tools/jar/CreateMissingParentDirectories.java Reviewed-by: azvegint, bpb, lancea --- test/jdk/ProblemList.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 6b54c726277..1d08673243f 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -765,6 +765,7 @@ javax/swing/JTree/4908142/bug4908142.java 8278348 macosx-all # core_tools tools/jlink/plugins/CompressorPluginTest.java 8247407 generic-all +tools/jar/CreateMissingParentDirectories.java 8281470 generic-all ############################################################################ -- GitLab From d658d945cf57bab8e61302841dcb56b36e48eff3 Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Tue, 8 Feb 2022 20:29:04 +0000 Subject: [PATCH 434/564] 8280828: Improve invariants in NonblockingQueue::append Reviewed-by: iwalulya, tschatzl --- .../utilities/nonblockingQueue.inline.hpp | 65 +++++++++++-------- 1 file changed, 39 insertions(+), 26 deletions(-) diff --git a/src/hotspot/share/utilities/nonblockingQueue.inline.hpp b/src/hotspot/share/utilities/nonblockingQueue.inline.hpp index 2fbd26f2dca..e16c8cb57d0 100644 --- a/src/hotspot/share/utilities/nonblockingQueue.inline.hpp +++ b/src/hotspot/share/utilities/nonblockingQueue.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022, 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 @@ -94,34 +94,41 @@ size_t NonblockingQueue::length() const { // push/append operations, each may introduce another such segment. But they // all eventually get resolved by their respective updates of their old tail's // "next" value. This also means that try_pop operation must handle an object -// with a NULL "next" value specially. +// differently depending on its "next" value. // // A push operation is just a degenerate append, where the object being pushed // is both the head and the tail of the list being appended. template void NonblockingQueue::append(T& first, T& last) { assert(next(last) == NULL, "precondition"); + // Make last the new end of the queue. Any further push/appends will + // extend after last. We will try to extend from the previous end of + // queue. set_next(last, end_marker()); T* old_tail = Atomic::xchg(&_tail, &last); - bool is_old_tail_null = (old_tail == NULL); - if (is_old_tail_null || - // Try to install first as old_tail's next. - !is_end(Atomic::cmpxchg(next_ptr(*old_tail), end_marker(), &first))) { - // Install first as the new head if either - // (1) the list was empty, or - // (2) a concurrent try_pop claimed old_tail, so it is no longer in the list. - // Note that multiple concurrent push/append operations cannot modify - // _head simultaneously, because the Atomic::xchg() above orders these - // push/append operations so they perform Atomic::cmpxchg() on different - // old_tail. Thus, the cmpxchg can only fail because of a concurrent try_pop. + if (old_tail == NULL) { + // If old_tail is NULL then the queue was empty, and _head must also be + // NULL. The correctness of this assertion depends on try_pop clearing + // first _head then _tail when taking the last entry. + assert(Atomic::load(&_head) == NULL, "invariant"); + // Fall through to common update of _head. + } else if (is_end(Atomic::cmpxchg(next_ptr(*old_tail), end_marker(), &first))) { + // Successfully extended the queue list from old_tail to first. No + // other push/append could have competed with us, because we claimed + // old_tail for extension. We won any races with try_pop by changing + // away from end-marker. So we're done. + return; + } else { + // A concurrent try_pop has claimed old_tail, so it is no longer in the + // list. The queue was logically empty. _head is either NULL or + // old_tail, depending on how far try_pop operations have progressed. DEBUG_ONLY(T* old_head = Atomic::load(&_head);) - // If old_tail is NULL, old_head could be NULL, or an unseen object - // that is being popped. Otherwise, old_head must be either NULL - // or the same as old_tail. - assert(is_old_tail_null || - old_head == NULL || old_head == old_tail, "invariant"); - Atomic::store(&_head, &first); + assert((old_head == NULL) || (old_head == old_tail), "invariant"); + // Fall through to common update of _head. } + // The queue was empty, and first should become the new _head. The queue + // will appear to be empty to any further try_pops until done. + Atomic::store(&_head, &first); } template @@ -161,7 +168,9 @@ bool NonblockingQueue::try_pop(T** node_ptr) { // _head to NULL, "helping" the competing try_pop. _head will remain // NULL until a subsequent push/append. This is a lost race, and we // report it as such for consistency, though we could report the queue - // was empty. + // was empty. We don't attempt to further help [Clause 2] by also + // trying to set _tail to NULL, as that would just ensure that one or + // the other cmpxchg is a wasted failure. return false; } else { // [Clause 1c] @@ -181,17 +190,21 @@ bool NonblockingQueue::try_pop(T** node_ptr) { // Any further try_pops will consider the queue empty until a // push/append completes by installing a new head. - // Attempt to change the queue tail from result to NULL. Failure of the - // cmpxchg indicates that a concurrent push/append updated the tail first. - // That operation will eventually recognize the old tail (our result) is - // no longer in the list and update head from the list being appended. - Atomic::cmpxchg(&_tail, result, (T*)NULL); + // The order of the two cmpxchgs doesn't matter algorithmically, but + // dealing with _head first gives a stronger invariant in append, and is + // also consistent with [Clause 1b]. // Attempt to change the queue head from result to NULL. Failure of the // cmpxchg indicates a concurrent operation updated _head first. That - // could be either a push/extend or a try_pop in [Clause 1b]. + // could be either a push/append or a try_pop in [Clause 1b]. Atomic::cmpxchg(&_head, result, (T*)NULL); + // Attempt to change the queue tail from result to NULL. Failure of the + // cmpxchg indicates that a concurrent push/append updated _tail first. + // That operation will eventually recognize the old tail (our result) is + // no longer in the list and update _head from the list being appended. + Atomic::cmpxchg(&_tail, result, (T*)NULL); + // The queue has been restored to order, and we can return the result. *node_ptr = result; return true; -- GitLab From fb17a8ece0a3593c51a8be60533916bf70778a93 Mon Sep 17 00:00:00 2001 From: Quan Anh Mai Date: Tue, 8 Feb 2022 23:38:09 +0000 Subject: [PATCH 435/564] 8278947: Support for array constants in constant table Reviewed-by: kvn, vlivanov --- src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp | 20 +++ src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp | 2 + src/hotspot/cpu/x86/x86.ad | 161 ++++++------------ src/hotspot/share/asm/assembler.hpp | 27 ++- src/hotspot/share/opto/constantTable.cpp | 137 ++++++++------- src/hotspot/share/opto/constantTable.hpp | 25 ++- 6 files changed, 200 insertions(+), 172 deletions(-) diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp index 65166197616..1f86ac0ebb9 100644 --- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp @@ -1493,6 +1493,26 @@ void C2_MacroAssembler::load_vector_mask(KRegister dst, XMMRegister src, XMMRegi } } +void C2_MacroAssembler::load_vector(XMMRegister dst, Address src, int vlen_in_bytes) { + switch (vlen_in_bytes) { + case 4: movdl(dst, src); break; + case 8: movq(dst, src); break; + case 16: movdqu(dst, src); break; + case 32: vmovdqu(dst, src); break; + case 64: evmovdquq(dst, src, Assembler::AVX_512bit); break; + default: ShouldNotReachHere(); + } +} + +void C2_MacroAssembler::load_vector(XMMRegister dst, AddressLiteral src, int vlen_in_bytes, Register rscratch) { + if (reachable(src)) { + load_vector(dst, as_Address(src), vlen_in_bytes); + } else { + lea(rscratch, src); + load_vector(dst, Address(rscratch, 0), vlen_in_bytes); + } +} + void C2_MacroAssembler::load_iota_indices(XMMRegister dst, Register scratch, int vlen_in_bytes) { ExternalAddress addr(StubRoutines::x86::vector_iota_indices()); if (vlen_in_bytes == 4) { diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp index b97c1ed607d..3df87043f09 100644 --- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp @@ -144,6 +144,8 @@ public: void load_vector_mask(XMMRegister dst, XMMRegister src, int vlen_in_bytes, BasicType elem_bt, bool is_legacy); void load_vector_mask(KRegister dst, XMMRegister src, XMMRegister xtmp, Register tmp, bool novlbwdq, int vlen_enc); + void load_vector(XMMRegister dst, Address src, int vlen_in_bytes); + void load_vector(XMMRegister dst, AddressLiteral src, int vlen_in_bytes, Register rscratch = rscratch1); void load_iota_indices(XMMRegister dst, Register scratch, int vlen_in_bytes); // Reductions for vectors of bytes, shorts, ints, longs, floats, and doubles. diff --git a/src/hotspot/cpu/x86/x86.ad b/src/hotspot/cpu/x86/x86.ad index a9dc2997e21..664f630a8cd 100644 --- a/src/hotspot/cpu/x86/x86.ad +++ b/src/hotspot/cpu/x86/x86.ad @@ -2552,15 +2552,21 @@ void vec_spill_helper(CodeBuffer *cbuf, bool is_load, } } -static inline jlong replicate8_imm(int con, int width) { - // Load a constant of "width" (in bytes) and replicate it to fill 64bit. - assert(width == 1 || width == 2 || width == 4, "only byte, short or int types here"); - int bit_width = width * 8; - jlong val = con; - val &= (((jlong) 1) << bit_width) - 1; // mask off sign bits - while(bit_width < 64) { - val |= (val << bit_width); - bit_width <<= 1; +template +static inline GrowableArray* vreplicate_imm(BasicType bt, T con, int len) { + GrowableArray* val = new GrowableArray(len); + jvalue ele; + switch (bt) { + case T_BYTE: ele.b = con; break; + case T_SHORT: ele.s = con; break; + case T_INT: ele.i = con; break; + case T_LONG: ele.j = con; break; + case T_FLOAT: ele.f = con; break; + case T_DOUBLE: ele.d = con; break; + default: ShouldNotReachHere(); + } + for (int i = 0; i < len; i++) { + val->append(ele); } return val; } @@ -3824,14 +3830,7 @@ instruct loadV(vec dst, memory mem) %{ ins_cost(125); format %{ "load_vector $dst,$mem" %} ins_encode %{ - switch (Matcher::vector_length_in_bytes(this)) { - case 4: __ movdl ($dst$$XMMRegister, $mem$$Address); break; - case 8: __ movq ($dst$$XMMRegister, $mem$$Address); break; - case 16: __ movdqu ($dst$$XMMRegister, $mem$$Address); break; - case 32: __ vmovdqu ($dst$$XMMRegister, $mem$$Address); break; - case 64: __ evmovdqul($dst$$XMMRegister, $mem$$Address, Assembler::AVX_512bit); break; - default: ShouldNotReachHere(); - } + __ load_vector($dst$$XMMRegister, $mem$$Address, Matcher::vector_length_in_bytes(this)); %} ins_pipe( pipe_slow ); %} @@ -4009,43 +4008,12 @@ instruct ReplB_imm(vec dst, immI con) %{ match(Set dst (ReplicateB con)); format %{ "replicateB $dst,$con" %} ins_encode %{ - uint vlen = Matcher::vector_length(this); - InternalAddress const_addr = $constantaddress(replicate8_imm($con$$constant, 1)); - if (vlen == 4) { - __ movdl($dst$$XMMRegister, const_addr); - } else { - __ movq($dst$$XMMRegister, const_addr); - if (vlen >= 16) { - if (VM_Version::supports_avx2()) { - int vlen_enc = vector_length_encoding(this); - __ vpbroadcastq($dst$$XMMRegister, $dst$$XMMRegister, vlen_enc); - } else { - assert(vlen == 16, "sanity"); - __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); - } - } - } + InternalAddress addr = $constantaddress(T_BYTE, vreplicate_imm(T_BYTE, $con$$constant, Matcher::vector_length(this))); + __ load_vector($dst$$XMMRegister, addr, Matcher::vector_length_in_bytes(this)); %} ins_pipe( pipe_slow ); %} -// Replicate byte scalar zero to be vector -instruct ReplB_zero(vec dst, immI_0 zero) %{ - match(Set dst (ReplicateB zero)); - format %{ "replicateB $dst,$zero" %} - ins_encode %{ - uint vlen = Matcher::vector_length(this); - if (vlen <= 16) { - __ pxor($dst$$XMMRegister, $dst$$XMMRegister); - } else { - // Use vpxor since AVX512F does not have 512bit vxorpd (requires AVX512DQ). - int vlen_enc = vector_length_encoding(this); - __ vpxor($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister, vlen_enc); - } - %} - ins_pipe( fpu_reg_reg ); -%} - // ====================ReplicateS======================================= instruct ReplS_reg(vec dst, rRegI src) %{ @@ -4091,39 +4059,10 @@ instruct ReplS_imm(vec dst, immI con) %{ match(Set dst (ReplicateS con)); format %{ "replicateS $dst,$con" %} ins_encode %{ - uint vlen = Matcher::vector_length(this); - InternalAddress const_addr = $constantaddress(replicate8_imm($con$$constant, 2)); - if (vlen == 2) { - __ movdl($dst$$XMMRegister, const_addr); - } else { - __ movq($dst$$XMMRegister, const_addr); - if (vlen >= 8) { - if (VM_Version::supports_avx2()) { - int vlen_enc = vector_length_encoding(this); - __ vpbroadcastw($dst$$XMMRegister, $dst$$XMMRegister, vlen_enc); - } else { - assert(vlen == 8, "sanity"); - __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); - } - } - } - %} - ins_pipe( fpu_reg_reg ); -%} - -instruct ReplS_zero(vec dst, immI_0 zero) %{ - match(Set dst (ReplicateS zero)); - format %{ "replicateS $dst,$zero" %} - ins_encode %{ - uint vlen = Matcher::vector_length(this); - if (vlen <= 8) { - __ pxor($dst$$XMMRegister, $dst$$XMMRegister); - } else { - int vlen_enc = vector_length_encoding(this); - __ vpxor($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister, vlen_enc); - } + InternalAddress addr = $constantaddress(T_SHORT, vreplicate_imm(T_SHORT, $con$$constant, Matcher::vector_length(this))); + __ load_vector($dst$$XMMRegister, addr, Matcher::vector_length_in_bytes(this)); %} - ins_pipe( fpu_reg_reg ); + ins_pipe( pipe_slow ); %} // ====================ReplicateI======================================= @@ -4173,30 +4112,21 @@ instruct ReplI_imm(vec dst, immI con) %{ match(Set dst (ReplicateI con)); format %{ "replicateI $dst,$con" %} ins_encode %{ - uint vlen = Matcher::vector_length(this); - InternalAddress const_addr = $constantaddress(replicate8_imm($con$$constant, 4)); - if (vlen <= 4) { - __ movq($dst$$XMMRegister, const_addr); - if (vlen == 4) { - __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); - } - } else { - assert(VM_Version::supports_avx2(), "sanity"); - int vlen_enc = vector_length_encoding(this); - __ movq($dst$$XMMRegister, const_addr); - __ vpbroadcastd($dst$$XMMRegister, $dst$$XMMRegister, vlen_enc); - } + InternalAddress addr = $constantaddress(T_INT, vreplicate_imm(T_INT, $con$$constant, Matcher::vector_length(this))); + __ load_vector($dst$$XMMRegister, addr, Matcher::vector_length_in_bytes(this)); %} ins_pipe( pipe_slow ); %} -// Replicate integer (4 byte) scalar zero to be vector +// Replicate scalar zero to be vector instruct ReplI_zero(vec dst, immI_0 zero) %{ + match(Set dst (ReplicateB zero)); + match(Set dst (ReplicateS zero)); match(Set dst (ReplicateI zero)); format %{ "replicateI $dst,$zero" %} ins_encode %{ - uint vlen = Matcher::vector_length(this); - if (vlen <= 4) { + uint vsize = Matcher::vector_length_in_bytes(this); + if (vsize <= 16) { __ pxor($dst$$XMMRegister, $dst$$XMMRegister); } else { int vlen_enc = vector_length_encoding(this); @@ -4327,17 +4257,8 @@ instruct ReplL_imm(vec dst, immL con) %{ match(Set dst (ReplicateL con)); format %{ "replicateL $dst,$con" %} ins_encode %{ - uint vlen = Matcher::vector_length(this); - InternalAddress const_addr = $constantaddress($con); - if (vlen == 2) { - __ movq($dst$$XMMRegister, const_addr); - __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); - } else { - assert(VM_Version::supports_avx2(), "sanity"); - int vlen_enc = vector_length_encoding(this); - __ movq($dst$$XMMRegister, const_addr); - __ vpbroadcastq($dst$$XMMRegister, $dst$$XMMRegister, vlen_enc); - } + InternalAddress addr = $constantaddress(T_LONG, vreplicate_imm(T_LONG, $con$$constant, Matcher::vector_length(this))); + __ load_vector($dst$$XMMRegister, addr, Matcher::vector_length_in_bytes(this)); %} ins_pipe( pipe_slow ); %} @@ -4407,6 +4328,17 @@ instruct ReplF_mem(vec dst, memory mem) %{ ins_pipe( pipe_slow ); %} +// Replicate float scalar immediate to be vector by loading from const table. +instruct ReplF_imm(vec dst, immF con) %{ + match(Set dst (ReplicateF con)); + format %{ "replicateF $dst,$con" %} + ins_encode %{ + InternalAddress addr = $constantaddress(T_FLOAT, vreplicate_imm(T_FLOAT, $con$$constant, Matcher::vector_length(this))); + __ load_vector($dst$$XMMRegister, addr, Matcher::vector_length_in_bytes(this)); + %} + ins_pipe( pipe_slow ); +%} + instruct ReplF_zero(vec dst, immF0 zero) %{ match(Set dst (ReplicateF zero)); format %{ "replicateF $dst,$zero" %} @@ -4461,6 +4393,17 @@ instruct ReplD_mem(vec dst, memory mem) %{ ins_pipe( pipe_slow ); %} +// Replicate double (8 byte) scalar immediate to be vector by loading from const table. +instruct ReplD_imm(vec dst, immD con) %{ + match(Set dst (ReplicateD con)); + format %{ "replicateD $dst,$con" %} + ins_encode %{ + InternalAddress addr = $constantaddress(T_DOUBLE, vreplicate_imm(T_DOUBLE, $con$$constant, Matcher::vector_length(this))); + __ load_vector($dst$$XMMRegister, addr, Matcher::vector_length_in_bytes(this)); + %} + ins_pipe( pipe_slow ); +%} + instruct ReplD_zero(vec dst, immD0 zero) %{ match(Set dst (ReplicateD zero)); format %{ "replicateD $dst,$zero" %} diff --git a/src/hotspot/share/asm/assembler.hpp b/src/hotspot/share/asm/assembler.hpp index 10fa79eb30a..dc38a53b031 100644 --- a/src/hotspot/share/asm/assembler.hpp +++ b/src/hotspot/share/asm/assembler.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -429,6 +429,31 @@ class AbstractAssembler : public ResourceObj { } return ptr; } + address array_constant(BasicType bt, GrowableArray* c) { + CodeSection* c1 = _code_section; + int len = c->length(); + int size = type2aelembytes(bt) * len; + address ptr = start_a_const(size, MIN2(round_up_power_of_2(size), 8)); + if (ptr != NULL) { + for (int i = 0; i < len; i++) { + jvalue e = c->at(i); + switch(bt) { + case T_BOOLEAN: emit_int8(e.z); break; + case T_BYTE: emit_int8(e.b); break; + case T_CHAR: emit_int16(e.c); break; + case T_SHORT: emit_int16(e.s); break; + case T_INT: emit_int32(e.i); break; + case T_LONG: emit_int64(e.j); break; + case T_FLOAT: emit_float(e.f); break; + case T_DOUBLE: emit_double(e.d); break; + default: + ShouldNotReachHere(); + } + } + end_a_const(c1); + } + return ptr; + } // Bang stack to trigger StackOverflowError at a safe location // implementation delegates to machine-specific bang_stack_with_offset diff --git a/src/hotspot/share/opto/constantTable.cpp b/src/hotspot/share/opto/constantTable.cpp index 285c273bb22..c3bb5c97730 100644 --- a/src/hotspot/share/opto/constantTable.cpp +++ b/src/hotspot/share/opto/constantTable.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,12 +35,15 @@ bool ConstantTable::Constant::operator==(const Constant& other) { if (type() != other.type() ) return false; if (can_be_reused() != other.can_be_reused()) return false; + if (is_array() || other.is_array()) { + return is_array() && other.is_array() && _v._array == other._v._array; + } // For floating point values we compare the bit pattern. switch (type()) { - case T_INT: - case T_FLOAT: return (_v._value.i == other._v._value.i); - case T_LONG: - case T_DOUBLE: return (_v._value.j == other._v._value.j); + case T_INT: return (_v._value.i == other._v._value.i); + case T_FLOAT: return jint_cast(_v._value.f) == jint_cast(other._v._value.f); + case T_LONG: return (_v._value.j == other._v._value.j); + case T_DOUBLE: return jlong_cast(_v._value.d) == jlong_cast(other._v._value.d); case T_OBJECT: case T_ADDRESS: return (_v._value.l == other._v._value.l); case T_VOID: return (_v._value.l == other._v._value.l); // jump-table entries @@ -56,8 +59,11 @@ int ConstantTable::qsort_comparator(Constant* a, Constant* b) { return 0; } -static int type_to_size_in_bytes(BasicType t) { - switch (t) { +static int constant_size(ConstantTable::Constant* con) { + if (con->is_array()) { + return type2aelembytes(con->type()) * con->get_array()->length(); + } + switch (con->type()) { case T_INT: return sizeof(jint ); case T_LONG: return sizeof(jlong ); case T_FLOAT: return sizeof(jfloat ); @@ -96,8 +102,9 @@ void ConstantTable::calculate_offsets_and_size() { Constant* con = _constants.adr_at(i); // Align offset for type. - int typesize = type_to_size_in_bytes(con->type()); - offset = align_up(offset, typesize); + int typesize = constant_size(con); + assert(typesize <= 8 || con->is_array(), "sanity"); + offset = align_up(offset, MIN2(round_up_power_of_2(typesize), 8)); con->set_offset(offset); // set constant's offset if (con->type() == T_VOID) { @@ -119,62 +126,66 @@ bool ConstantTable::emit(CodeBuffer& cb) const { for (int i = 0; i < _constants.length(); i++) { Constant con = _constants.at(i); address constant_addr = NULL; - switch (con.type()) { - case T_INT: constant_addr = _masm.int_constant( con.get_jint() ); break; - case T_LONG: constant_addr = _masm.long_constant( con.get_jlong() ); break; - case T_FLOAT: constant_addr = _masm.float_constant( con.get_jfloat() ); break; - case T_DOUBLE: constant_addr = _masm.double_constant(con.get_jdouble()); break; - case T_OBJECT: { - jobject obj = con.get_jobject(); - int oop_index = _masm.oop_recorder()->find_index(obj); - constant_addr = _masm.address_constant((address) obj, oop_Relocation::spec(oop_index)); - break; - } - case T_ADDRESS: { - address addr = (address) con.get_jobject(); - constant_addr = _masm.address_constant(addr); - break; - } - // We use T_VOID as marker for jump-table entries (labels) which - // need an internal word relocation. - case T_VOID: { - MachConstantNode* n = (MachConstantNode*) con.get_jobject(); - // Fill the jump-table with a dummy word. The real value is - // filled in later in fill_jump_table. - address dummy = (address) n; - constant_addr = _masm.address_constant(dummy); - if (constant_addr == NULL) { - return false; + if (con.is_array()) { + constant_addr = _masm.array_constant(con.type(), con.get_array()); + } else { + switch (con.type()) { + case T_INT: constant_addr = _masm.int_constant( con.get_jint() ); break; + case T_LONG: constant_addr = _masm.long_constant( con.get_jlong() ); break; + case T_FLOAT: constant_addr = _masm.float_constant( con.get_jfloat() ); break; + case T_DOUBLE: constant_addr = _masm.double_constant(con.get_jdouble()); break; + case T_OBJECT: { + jobject obj = con.get_jobject(); + int oop_index = _masm.oop_recorder()->find_index(obj); + constant_addr = _masm.address_constant((address) obj, oop_Relocation::spec(oop_index)); + break; } - assert((constant_addr - _masm.code()->consts()->start()) == con.offset(), - "must be: %d == %d", (int)(constant_addr - _masm.code()->consts()->start()), (int)(con.offset())); - - // Expand jump-table - address last_addr = NULL; - for (uint j = 1; j < n->outcnt(); j++) { - last_addr = _masm.address_constant(dummy + j); - if (last_addr == NULL) { + case T_ADDRESS: { + address addr = (address) con.get_jobject(); + constant_addr = _masm.address_constant(addr); + break; + } + // We use T_VOID as marker for jump-table entries (labels) which + // need an internal word relocation. + case T_VOID: { + MachConstantNode* n = (MachConstantNode*) con.get_jobject(); + // Fill the jump-table with a dummy word. The real value is + // filled in later in fill_jump_table. + address dummy = (address) n; + constant_addr = _masm.address_constant(dummy); + if (constant_addr == NULL) { return false; } - } + assert((constant_addr - _masm.code()->consts()->start()) == con.offset(), + "must be: %d == %d", (int)(constant_addr - _masm.code()->consts()->start()), (int)(con.offset())); + + // Expand jump-table + address last_addr = NULL; + for (uint j = 1; j < n->outcnt(); j++) { + last_addr = _masm.address_constant(dummy + j); + if (last_addr == NULL) { + return false; + } + } #ifdef ASSERT - address start = _masm.code()->consts()->start(); - address new_constant_addr = last_addr - ((n->outcnt() - 1) * sizeof(address)); - // Expanding the jump-table could result in an expansion of the const code section. - // In that case, we need to check if the new constant address matches the offset. - assert((constant_addr - start == con.offset()) || (new_constant_addr - start == con.offset()), - "must be: %d == %d or %d == %d (after an expansion)", (int)(constant_addr - start), (int)(con.offset()), - (int)(new_constant_addr - start), (int)(con.offset())); + address start = _masm.code()->consts()->start(); + address new_constant_addr = last_addr - ((n->outcnt() - 1) * sizeof(address)); + // Expanding the jump-table could result in an expansion of the const code section. + // In that case, we need to check if the new constant address matches the offset. + assert((constant_addr - start == con.offset()) || (new_constant_addr - start == con.offset()), + "must be: %d == %d or %d == %d (after an expansion)", (int)(constant_addr - start), (int)(con.offset()), + (int)(new_constant_addr - start), (int)(con.offset())); #endif - continue; // Loop - } - case T_METADATA: { - Metadata* obj = con.get_metadata(); - int metadata_index = _masm.oop_recorder()->find_index(obj); - constant_addr = _masm.address_constant((address) obj, metadata_Relocation::spec(metadata_index)); - break; - } - default: ShouldNotReachHere(); + continue; // Loop + } + case T_METADATA: { + Metadata* obj = con.get_metadata(); + int metadata_index = _masm.oop_recorder()->find_index(obj); + constant_addr = _masm.address_constant((address) obj, metadata_Relocation::spec(metadata_index)); + break; + } + default: ShouldNotReachHere(); + } } if (constant_addr == NULL) { @@ -218,6 +229,12 @@ ConstantTable::Constant ConstantTable::add(Metadata* metadata) { return con; } +ConstantTable::Constant ConstantTable::add(MachConstantNode* n, BasicType bt, GrowableArray* array) { + Constant con(bt, array); + add(con); + return con; +} + ConstantTable::Constant ConstantTable::add(MachConstantNode* n, MachOper* oper) { jvalue value; BasicType type = oper->type()->basic_type(); diff --git a/src/hotspot/share/opto/constantTable.hpp b/src/hotspot/share/opto/constantTable.hpp index fe0d0e3f1a5..1452a27d046 100644 --- a/src/hotspot/share/opto/constantTable.hpp +++ b/src/hotspot/share/opto/constantTable.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,18 +38,21 @@ public: class Constant { private: BasicType _type; + bool _is_array; union { jvalue _value; Metadata* _metadata; + GrowableArray* _array; } _v; int _offset; // offset of this constant (in bytes) relative to the constant table base. float _freq; bool _can_be_reused; // true (default) if the value can be shared with other users. public: - Constant() : _type(T_ILLEGAL), _offset(-1), _freq(0.0f), _can_be_reused(true) { _v._value.l = 0; } + Constant() : _type(T_ILLEGAL), _is_array(false), _offset(-1), _freq(0.0f), _can_be_reused(true) { _v._value.l = 0; } Constant(BasicType type, jvalue value, float freq = 0.0f, bool can_be_reused = true) : _type(type), + _is_array(false), _offset(-1), _freq(freq), _can_be_reused(can_be_reused) @@ -59,16 +62,31 @@ public: } Constant(Metadata* metadata, bool can_be_reused = true) : _type(T_METADATA), + _is_array(false), _offset(-1), _freq(0.0f), _can_be_reused(can_be_reused) { _v._metadata = metadata; } + Constant(BasicType type, GrowableArray* array) : + _type(type), + _is_array(true), + _offset(-1), + _freq(0.0f), + _can_be_reused(false) + { + assert(is_java_primitive(type), "not applicable for %s", type2name(type)); + _v._array = new GrowableArray(array->length()); + for (jvalue ele : *array) { + _v._array->append(ele); + } + } bool operator==(const Constant& other); BasicType type() const { return _type; } + bool is_array() const { return _is_array; } jint get_jint() const { return _v._value.i; } jlong get_jlong() const { return _v._value.j; } @@ -78,6 +96,8 @@ public: Metadata* get_metadata() const { return _v._metadata; } + GrowableArray* get_array() const { return _v._array; } + int offset() const { return _offset; } void set_offset(int offset) { _offset = offset; } @@ -124,6 +144,7 @@ public: void add(Constant& con); Constant add(MachConstantNode* n, BasicType type, jvalue value); Constant add(Metadata* metadata); + Constant add(MachConstantNode* n, BasicType bt, GrowableArray* array); Constant add(MachConstantNode* n, MachOper* oper); Constant add(MachConstantNode* n, jint i) { jvalue value; value.i = i; -- GitLab From 2f46af05ce2d43e19e0095680eb3a52fd904c774 Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Wed, 9 Feb 2022 01:26:42 +0000 Subject: [PATCH 436/564] 8280132: Incorrect comparator com.sun.beans.introspect.MethodInfo.MethodOrder Reviewed-by: prr --- .../com/sun/beans/introspect/MethodInfo.java | 20 +- .../Introspector/MethodOrderException.java | 1537 ++++++++++++++++- 2 files changed, 1528 insertions(+), 29 deletions(-) diff --git a/src/java.desktop/share/classes/com/sun/beans/introspect/MethodInfo.java b/src/java.desktop/share/classes/com/sun/beans/introspect/MethodInfo.java index e5e79dc2a2f..5216f4423d4 100644 --- a/src/java.desktop/share/classes/com/sun/beans/introspect/MethodInfo.java +++ b/src/java.desktop/share/classes/com/sun/beans/introspect/MethodInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2022, 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 @@ -98,10 +98,7 @@ final class MethodInfo { /** * A comparator that defines a total order so that methods have the same - * name and identical signatures appear next to each others. The methods are - * sorted in such a way that methods which override each other will sit next - * to each other, with the overridden method last - e.g. is Integer getFoo() - * placed before Object getFoo(). + * name and identical signatures appear next to each others. **/ private static final class MethodOrder implements Comparator { @@ -132,18 +129,7 @@ final class MethodInfo { } final Class aret = a.getReturnType(); final Class bret = b.getReturnType(); - if (aret == bret) { - return 0; - } - - // Super type comes last: Integer, Number, Object - if (aret.isAssignableFrom(bret)) { - return 1; - } - if (bret.isAssignableFrom(aret)) { - return -1; - } - return aret.getName().compareTo(bret.getName()); + return aret == bret ? 0 : aret.getName().compareTo(bret.getName()); } static final MethodOrder instance = new MethodOrder(); diff --git a/test/jdk/java/beans/Introspector/MethodOrderException.java b/test/jdk/java/beans/Introspector/MethodOrderException.java index d6c79b5d768..b69981002e6 100644 --- a/test/jdk/java/beans/Introspector/MethodOrderException.java +++ b/test/jdk/java/beans/Introspector/MethodOrderException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,40 +35,1553 @@ import java.util.RandomAccess; /** * @test - * @bug 8211147 + * @bug 8211147 8280132 * @modules java.desktop/com.sun.beans.introspect:open */ public final class MethodOrderException { public static void main(final String[] args) throws Exception { - // Public API, fails rarely - testPublicAPI(); - // Test using internal API, fails always - testPrivateAPI(); + for (Class beanClass : List.of(D.class, X.class, A_258.class)) { + // Public API, fails rarely + testPublicAPI(beanClass); + // Test using internal API, fails always + testPrivateAPI(beanClass); + } } - private static void testPublicAPI() throws Exception { - Introspector.getBeanInfo(X.class); + private static void testPublicAPI(Class beanClass) throws Exception { + Introspector.getBeanInfo(beanClass); } - private static void testPrivateAPI() throws Exception { + private static void testPrivateAPI(Class beanClass) throws Exception { Class name = Class.forName( "com.sun.beans.introspect.MethodInfo$MethodOrder"); Field instance = name.getDeclaredField("instance"); instance.setAccessible(true); Comparator o = (Comparator) instance.get(name); - List methods = List.of(X.class.getDeclaredMethods()); + List methods = List.of(beanClass.getDeclaredMethods()); methods.forEach(m1 -> { methods.forEach(m2 -> { if (o.compare(m1, m2) != -o.compare(m2, m1)) { - System.err.println("Method1 = "+ m1); - System.err.println("Method2 = "+ m2); + System.err.println("Method1 = " + m1); + System.err.println("Method2 = " + m2); throw new RuntimeException("Broken contract!"); } + methods.forEach(m3 -> { + if (o.compare(m1, m2) < 0 && o.compare(m2, m3) < 0) { + if (o.compare(m1, m3) >= 0) { + System.err.println("Method1 = " + m1); + System.err.println("Method2 = " + m2); + System.err.println("Method3 = " + m3); + throw new RuntimeException("Broken contract!"); + } + } + }); }); }); } + interface C1 { + C1 foo0(); + } + interface C2 { + C2 foo0(); + } + interface C3 extends C1 { + C3 foo0(); + } + interface D extends C3, C2, C1 { + D foo0(); + } + public interface A_239 { + } + public interface A_240 { + } + public interface A_000 { + } + public interface A_238 { + } + public interface A_035 extends A_195, A_106, A_240 { + A_035 a_040(); + A_035 a_000(); + A_035 a_018(); + } + public static class A_258 implements A_053, A_196, A_200, A_070, A_106, + A_057, A_094, A_098, A_105, A_107, A_097, A_093, A_214, A_215, + A_210, A_129, A_067, A_180, A_108, A_184, A_110, A_111, A_082, + A_221, A_172, A_171, A_168, A_139, A_143, A_140, A_075, A_081, + A_080, A_163, A_165, A_164, A_159, A_161, A_155, A_158, A_157, + A_156, A_195, A_197, A_114, A_213, A_236, A_220, A_201, A_035, + A_136, A_135, A_226, A_227, A_005, A_054, A_203, A_202, A_071, + A_115, A_113, A_112, A_058, A_095, A_096, A_099, A_100, A_237, + A_091, A_092, A_217, A_218, A_216, A_211, A_130, A_063, A_062, + A_064, A_065, A_066, A_061, A_060, A_181, A_208, A_207, A_209, + A_185, A_186, A_083, A_173, A_176, A_222, A_223, A_174, A_169, + A_153, A_154, A_194, A_190, A_104, A_132, A_141, A_142, A_166, + A_167, A_160, A_162, A_076, A_077, A_078, A_079, A_074, A_085, + A_192, A_188, A_134, A_138, A_137, A_228 { + @Override + public A_258 a_052() { + return null; + } + @Override + public A_258 a_071() { + return null; + } + @Override + public A_258 a_029() { + return null; + } + @Override + public A_258 a_046() { + return null; + } + @Override + public A_258 a_045() { + return null; + } + @Override + public A_258 a_047() { + return null; + } + @Override + public A_258 a_048() { + return null; + } + @Override + public A_258 a_049() { + return null; + } + @Override + public A_258 a_044() { + return null; + } + @Override + public A_258 a_043() { + return null; + } + @Override + public A_258 a_026() { + return null; + } + @Override + public A_258 a_027() { + return null; + } + @Override + public A_258 a_074() { + return null; + } + @Override + public A_258 a_079() { + return null; + } + @Override + public A_258 a_012() { + return null; + } + @Override + public A_258 a_100() { + return null; + } + @Override + public A_258 a_085() { + return null; + } + @Override + public A_258 a_084() { + return null; + } + @Override + public A_258 a_011() { + return null; + } + @Override + public A_258 a_059() { + return null; + } + @Override + public A_258 a_058() { + return null; + } + @Override + public A_258 a_080() { + return null; + } + @Override + public A_258 a_030() { + return null; + } + @Override + public A_258 a_031() { + return null; + } + @Override + public A_258 a_081() { + return null; + } + @Override + public A_258 a_077() { + return null; + } + @Override + public A_258 a_036() { + return null; + } + @Override + public A_258 a_056() { + return null; + } + @Override + public A_258 a_078() { + return null; + } + @Override + public A_258 a_076() { + return null; + } + @Override + public A_258 a_057() { + return null; + } + @Override + public A_258 a_005() { + return null; + } + @Override + public A_258 a_089() { + return null; + } + @Override + public A_258 a_088() { + return null; + } + @Override + public A_258 a_090() { + return null; + } + @Override + public A_258 a_072() { + return null; + } + @Override + public A_258 a_002() { + return null; + } + @Override + public A_258 a_040() { + return null; + } + @Override + public A_258 a_060() { + return null; + } + @Override + public A_258 a_061() { + return null; + } + @Override + public A_258 a_039() { + return null; + } + @Override + public A_258 a_032() { + return null; + } + @Override + public A_258 a_033() { + return null; + } + @Override + public A_258 a_000() { + return null; + } + @Override + public A_258 a_037() { + return null; + } + @Override + public A_258 a_014() { + return null; + } + @Override + public A_258 a_015() { + return null; + } + @Override + public A_258 a_016() { + return null; + } + @Override + public A_258 a_017() { + return null; + } + @Override + public A_258 a_091() { + return null; + } + @Override + public A_258 a_065() { + return null; + } + @Override + public A_258 a_066() { + return null; + } + @Override + public A_258 a_018() { + return null; + } + @Override + public A_258 a_093() { + return null; + } + @Override + public A_258 a_092() { + return null; + } + @Override + public A_258 a_095() { + return null; + } + @Override + public A_258 a_096() { + return null; + } + @Override + public A_258 a_069() { + return null; + } + } + public interface A_250 extends A_239 { + A_250 a_094(); + } + public interface A_253 extends A_239 { + A_253 a_000(); + } + public interface A_256 extends A_239 { + A_256 a_009(); + } + public interface A_248 extends A_239 { + A_248 a_022(); + } + public interface A_255 extends A_239 { + A_255 a_007(); + } + public interface A_241 extends A_248, A_250, A_251, A_249, A_239 { + } + public interface A_254 extends A_239 { + A_254 a_008(); + } + public interface A_251 extends A_239 { + A_251 a_097(); + } + public interface A_252 extends A_241, A_255, A_253, A_257, A_254, A_256, + A_239 { + A_252 a_022(); + A_252 a_094(); + A_252 a_097(); + A_252 a_087(); + } + public interface A_229 extends A_239 { + A_229 a_000(); + } + public interface A_232 extends A_239 { + } + public interface A_249 extends A_239 { + A_249 a_087(); + } + public interface A_230 extends A_239 { + } + public interface A_234 extends A_239 { + A_234 a_026(); + } + public interface A_037 extends A_239 { + A_037 a_013(); + } + public interface A_233 extends A_239 { + A_233 a_018(); + } + public interface A_231 extends A_239 { + A_231 a_007(); + } + public interface A_049 extends A_239 { + A_049 a_068(); + } + public interface A_257 extends A_239 { + A_257 a_018(); + } + public interface A_235 extends A_239 { + } + public interface A_040 extends A_239 { + A_040 a_025(); + } + public interface A_133 extends A_000, A_005, A_134, A_240 { + A_133 a_040(); + A_133 a_057(); + } + public interface A_001 extends A_239 { + A_001 a_020(); + } + public interface A_031 extends A_239 { + } + public interface A_089 extends A_239 { + A_089 a_098(); + } + public interface A_166 extends A_239 { + A_166 a_065(); + } + public interface A_054 extends A_239 { + A_054 a_000(); + } + public interface A_190 extends A_239 { + A_190 a_077(); + } + public interface A_169 extends A_239 { + A_169 a_037(); + } + public interface A_217 extends A_239 { + A_217 a_093(); + } + public interface A_078 extends A_239 { + A_078 a_016(); + } + public interface A_192 extends A_239 { + } + public interface A_222 extends A_239 { + A_222 a_095(); + } + public interface A_112 extends A_239 { + A_112 a_033(); + } + public interface A_066 extends A_239 { + A_066 a_049(); + } + public interface A_074 extends A_239 { + A_074 a_012(); + } + public interface A_003 extends A_239 { + A_003 a_039(); + } + public interface A_083 extends A_239 { + } + public interface A_050 extends A_239 { + A_050 a_070(); + } + public interface A_087 extends A_239 { + } + public interface A_058 extends A_239 { + } + public interface A_128 extends A_239 { + } + public interface A_092 extends A_239 { + } + public interface A_004 extends A_240 { + A_004 a_040(); + } + public interface A_115 extends A_239 { + A_115 a_039(); + } + public interface A_176 extends A_239 { + A_176 a_071(); + } + public interface A_162 extends A_239 { + } + public interface A_132 extends A_239 { + A_132 a_056(); + } + public interface A_064 extends A_239 { + A_064 a_047(); + } + public interface A_021 extends A_239 { + } + public interface A_160 extends A_239 { + } + public interface A_141 extends A_239 { + A_141 a_060(); + } + public interface A_091 extends A_239 { + A_091 a_026(); + } + public interface A_034 extends A_239 { + A_034 a_084(); + } + public interface A_151 extends A_239 { + } + public interface A_026 extends A_239 { + A_026 a_026(); + } + public interface A_130 extends A_239 { + A_130 a_052(); + } + public interface A_242 extends A_239 { + A_242 a_001(); + } + public interface A_205 extends A_239 { + A_205 a_086(); + } + public interface A_048 extends A_239 { + A_048 a_065(); + } + public interface A_044 extends A_240 { + A_044 a_040(); + } + public interface A_023 extends A_239 { + } + public interface A_027 extends A_239 { + } + public interface A_138 extends A_239 { + A_138 a_059(); + } + public interface A_024 extends A_239 { + A_024 a_011(); + } + public interface A_038 extends A_239 { + A_038 a_021(); + } + public interface A_016 extends A_239 { + } + public interface A_118 extends A_239 { + A_118 a_045(); + } + public interface A_071 extends A_239 { + A_071 a_011(); + } + public interface A_203 extends A_239 { + A_203 a_084(); + } + public interface A_137 extends A_239 { + } + public interface A_119 extends A_239 { + A_119 a_046(); + } + public interface A_145 extends A_239 { + } + public interface A_045 extends A_239 { + A_045 a_041(); + } + public interface A_069 extends A_239 { + A_069 a_010(); + } + public interface A_150 extends A_239 { + } + public interface A_047 extends A_239 { + A_047 a_057(); + } + public interface A_179 extends A_239 { + } + public interface A_207 extends A_239 { + A_207 a_088(); + } + public interface A_228 extends A_239 { + A_228 a_100(); + } + public interface A_005 extends A_240 { + A_005 a_040(); + } + public interface A_030 extends A_239 { + A_030 a_039(); + } + public interface A_173 extends A_239 { + A_173 a_069(); + } + public interface A_060 extends A_239 { + A_060 a_043(); + } + public interface A_245 extends A_239 { + A_245 a_009(); + } + public interface A_042 extends A_239 { + A_042 a_035(); + } + public interface A_209 extends A_239 { + A_209 a_090(); + } + public interface A_216 extends A_239 { + } + public interface A_142 extends A_239 { + } + public interface A_246 extends A_239 { + A_246 a_019(); + } + public interface A_223 extends A_239 { + } + public interface A_211 extends A_239 { + A_211 a_091(); + } + public interface A_244 extends A_239 { + A_244 a_008(); + } + public interface A_019 extends A_239 { + A_019 a_050(); + } + public interface A_041 extends A_239 { + A_041 a_034(); + } + public interface A_208 extends A_239 { + A_208 a_089(); + } + public interface A_065 extends A_239 { + } + public interface A_127 extends A_239 { + A_127 a_083(); + } + public interface A_033 extends A_239 { + } + public interface A_153 extends A_239 { + } + public interface A_079 extends A_239 { + } + public interface A_025 extends A_239 { + } + public interface A_046 extends A_239 { + A_046 a_042(); + } + public interface A_002 extends A_239 { + } + public interface A_154 extends A_239 { + } + public interface A_077 extends A_239 { + A_077 a_015(); + } + public interface A_121 extends A_239 { + A_121 a_053(); + } + public interface A_036 extends A_239 { + A_036 a_003(); + } + public interface A_225 extends A_239 { + A_225 a_054(); + } + public interface A_181 extends A_239 { + A_181 a_005(); + } + public interface A_134 extends A_239 { + A_134 a_057(); + } + public interface A_017 extends A_239 { + } + public interface A_194 extends A_239 { + A_194 a_081(); + } + public interface A_243 extends A_239 { + A_243 a_006(); + } + public interface A_015 extends A_239 { + A_015 a_004(); + } + public interface A_028 extends A_239 { + A_028 a_032(); + } + public interface A_218 extends A_239 { + } + public interface A_174 extends A_239 { + } + public interface A_039 extends A_239 { + A_039 a_023(); + } + public interface A_029 extends A_239 { + } + public interface A_095 extends A_239 { + A_095 a_029(); + } + public interface A_096 extends A_239 { + } + public interface A_124 extends A_239 { + A_124 a_028(); + } + public interface A_202 extends A_239 { + A_202 a_085(); + } + public interface A_186 extends A_239 { + } + public interface A_120 extends A_239 { + } + public interface A_076 extends A_239 { + A_076 a_014(); + } + public interface A_052 extends A_239 { + A_052 a_099(); + } + public interface A_056 extends A_239 { + } + public interface A_020 extends A_239 { + A_020 a_062(); + } + public interface A_018 extends A_239 { + A_018 a_045(); + } + public interface A_149 extends A_239 { + A_149 a_051(); + } + public interface A_022 extends A_239 { + A_022 a_075(); + } + public interface A_063 extends A_239 { + A_063 a_046(); + } + public interface A_043 extends A_239 { + A_043 a_038(); + } + public interface A_167 extends A_239 { + } + public interface A_085 extends A_239 { + A_085 a_018(); + } + public interface A_032 extends A_239 { + } + public interface A_188 extends A_239 { + A_188 a_076(); + } + public interface A_126 extends A_239 { + } + public interface A_113 extends A_239 { + A_113 a_032(); + } + public interface A_051 extends A_239 { + A_051 a_082(); + } + public interface A_185 extends A_239 { + A_185 a_074(); + } + public interface A_099 extends A_239 { + } + public interface A_062 extends A_239 { + A_062 a_045(); + } + public interface A_237 extends A_239 { + A_237 a_027(); + } + public interface A_100 extends A_239 { + } + public interface A_189 extends A_000, A_005, A_190, A_240 { + A_189 a_040(); + A_189 a_077(); + } + public interface A_061 extends A_239 { + A_061 a_044(); + } + public interface A_104 extends A_239 { + A_104 a_036(); + } + public interface A_084 extends A_000, A_005, A_085, A_240 { + A_084 a_040(); + A_084 a_018(); + } + public interface A_129 extends A_000, A_005, A_130, A_240 { + A_129 a_040(); + A_129 a_052(); + } + public interface A_086 extends A_000, A_005, A_087, A_089, A_240 { + A_086 a_040(); + A_086 a_024(); + A_086 a_098(); + } + public interface A_125 extends A_239 { + } + public interface A_212 extends A_053, A_084, A_005, A_054, A_085, A_217, + A_218, A_240 { + A_212 a_040(); + A_212 a_000(); + A_212 a_018(); + A_212 a_093(); + } + public interface A_171 extends A_170, A_175, A_005, A_173, A_176, A_174, + A_240 { + A_171 a_040(); + A_171 a_069(); + A_171 a_071(); + A_171 a_072(); + } + public interface A_247 extends A_239 { + } + public interface A_183 extends A_053, A_084, A_005, A_054, A_085, A_185, + A_186, A_240 { + A_183 a_040(); + A_183 a_000(); + A_183 a_018(); + A_183 a_074(); + } + public interface A_198 extends A_053, A_196, A_070, A_131, A_005, A_054, + A_203, A_071, A_132, A_240 { + A_198 a_040(); + A_198 a_000(); + A_198 a_084(); + A_198 a_011(); + A_198 a_056(); + } + public interface A_070 extends A_000, A_005, A_071, A_240 { + A_070 a_040(); + A_070 a_011(); + } + public interface A_109 extends A_106, A_212, A_005, A_115, A_113, A_112, + A_054, A_085, A_217, A_218, A_240 { + A_109 a_040(); + A_109 a_039(); + A_109 a_032(); + A_109 a_033(); + A_109 a_000(); + A_109 a_018(); + A_109 a_093(); + } + public interface A_158 extends A_159, A_161, A_152, A_005, A_054, A_160, + A_162, A_153, A_154, A_240 { + A_158 a_040(); + A_158 a_000(); + A_158 a_079(); + } + public interface A_110 extends A_106, A_212, A_183, A_005, A_054, A_085, + A_115, A_113, A_112, A_217, A_218, A_185, A_186, A_240 { + A_110 a_040(); + A_110 a_000(); + A_110 a_018(); + A_110 a_039(); + A_110 a_032(); + A_110 a_033(); + A_110 a_093(); + A_110 a_074(); + } + public interface A_200 extends A_000, A_005, A_202, A_240 { + A_200 a_040(); + A_200 a_085(); + } + public interface A_161 extends A_053, A_005, A_054, A_162, A_240 { + A_161 a_040(); + A_161 a_000(); + } + public interface A_175 extends A_000, A_005, A_176, A_240 { + A_175 a_040(); + A_175 a_071(); + } + public interface A_103 extends A_000, A_084, A_005, A_085, A_104, A_240 { + A_103 a_040(); + A_103 a_018(); + A_103 a_036(); + } + public interface A_093 extends A_090, A_152, A_005, A_054, A_085, A_091, + A_092, A_153, A_154, A_240 { + A_093 a_040(); + A_093 a_000(); + A_093 a_018(); + A_093 a_026(); + A_093 a_079(); + A_093 a_027(); + } + public interface A_204 extends A_000, A_005, A_205, A_240 { + A_204 a_040(); + A_204 a_086(); + } + public interface A_067 extends A_059, A_152, A_005, A_054, A_085, A_063, + A_062, A_064, A_065, A_066, A_061, A_060, A_153, A_154, A_240 { + A_067 a_040(); + A_067 a_000(); + A_067 a_018(); + A_067 a_046(); + A_067 a_045(); + A_067 a_047(); + A_067 a_049(); + A_067 a_044(); + A_067 a_043(); + A_067 a_079(); + } + public interface A_101 extends A_070, A_005, A_071, A_240 { + A_101 a_040(); + A_101 a_011(); + } + public interface A_224 extends A_000, A_225, A_240 { + A_224 a_054(); + A_224 a_040(); + } + public interface A_156 extends A_053, A_084, A_155, A_059, A_005, A_054, + A_085, A_160, A_162, A_063, A_062, A_064, A_065, A_066, A_061, + A_060, A_240 { + A_156 a_040(); + A_156 a_000(); + A_156 a_018(); + A_156 a_046(); + A_156 a_045(); + A_156 a_047(); + A_156 a_049(); + A_156 a_044(); + A_156 a_043(); + } + public interface A_122 extends A_116, A_152, A_005, A_054, A_085, A_121, + A_119, A_118, A_120, A_153, A_154, A_240 { + A_122 a_040(); + A_122 a_000(); + A_122 a_018(); + A_122 a_053(); + A_122 a_046(); + A_122 a_045(); + A_122 a_048(); + A_122 a_079(); + A_122 a_080(); + } + public interface A_184 extends A_183, A_152, A_005, A_054, A_085, A_185, + A_186, A_153, A_154, A_240 { + A_184 a_040(); + A_184 a_000(); + A_184 a_018(); + A_184 a_074(); + A_184 a_079(); + } + public interface A_180 extends A_000, A_181, A_240 { + A_180 a_005(); + A_180 a_040(); + } + public interface A_191 extends A_000, A_005, A_192, A_240 { + A_191 a_040(); + A_191 a_078(); + } + public interface A_107 extends A_106, A_094, A_005, A_115, A_113, A_112, + A_095, A_096, A_240 { + A_107 a_040(); + A_107 a_039(); + A_107 a_032(); + A_107 a_033(); + A_107 a_029(); + A_107 a_000(); + A_107 a_018(); + } + public interface A_102 extends A_196, A_005, A_203, A_240 { + A_102 a_040(); + A_102 a_084(); + } + public interface A_177 extends A_000, A_005, A_179, A_240 { + A_177 a_040(); + } + public interface A_123 extends A_195, A_005, A_054, A_124, A_127, A_128, + A_126, A_125, A_240 { + A_123 a_040(); + A_123 a_000(); + A_123 a_028(); + A_123 a_083(); + A_123 a_064(); + A_123 a_055(); + A_123 a_018(); + A_123 a_079(); + A_123 a_080(); + A_123 a_081(); + A_123 a_077(); + A_123 a_036(); + A_123 a_056(); + A_123 a_012(); + A_123 a_078(); + A_123 a_076(); + A_123 a_057(); + } + public interface A_088 extends A_106, A_086, A_240 { + A_088 a_040(); + A_088 a_039(); + A_088 a_032(); + A_088 a_033(); + A_088 a_000(); + A_088 a_018(); + A_088 a_024(); + A_088 a_098(); + } + public interface A_094 extends A_084, A_005, A_085, A_095, A_096, A_240 { + A_094 a_040(); + A_094 a_018(); + A_094 a_029(); + } + public interface A_105 extends A_098, A_236, A_005, A_085, A_153, A_074, + A_099, A_100, A_240 { + A_105 a_040(); + A_105 a_018(); + A_105 a_079(); + A_105 a_012(); + A_105 a_030(); + A_105 a_031(); + A_105 a_000(); + A_105 a_081(); + A_105 a_077(); + A_105 a_036(); + A_105 a_056(); + A_105 a_078(); + A_105 a_076(); + A_105 a_057(); + } + public interface A_199 extends A_196, A_090, A_005, A_054, A_085, A_091, + A_092, A_203, A_240 { + A_199 a_040(); + A_199 a_000(); + A_199 a_018(); + A_199 a_026(); + A_199 a_084(); + A_199 a_027(); + } + public interface A_080 extends A_075, A_236, A_005, A_085, A_153, A_074, + A_076, A_077, A_078, A_079, A_240 { + A_080 a_040(); + A_080 a_018(); + A_080 a_079(); + A_080 a_012(); + A_080 a_014(); + A_080 a_015(); + A_080 a_016(); + A_080 a_000(); + A_080 a_080(); + A_080 a_081(); + A_080 a_077(); + A_080 a_036(); + A_080 a_056(); + A_080 a_078(); + A_080 a_076(); + A_080 a_057(); + } + public interface A_172 extends A_170, A_219, A_005, A_054, A_085, A_173, + A_222, A_223, A_174, A_240 { + A_172 a_040(); + A_172 a_000(); + A_172 a_018(); + A_172 a_069(); + A_172 a_095(); + A_172 a_072(); + } + public interface A_108 extends A_106, A_180, A_206, A_005, A_115, A_113, + A_112, A_181, A_208, A_207, A_209, A_240 { + A_108 a_040(); + A_108 a_039(); + A_108 a_032(); + A_108 a_033(); + A_108 a_005(); + A_108 a_089(); + A_108 a_088(); + A_108 a_090(); + A_108 a_000(); + A_108 a_018(); + } + public interface A_195 extends A_053, A_084, A_152, A_193, A_189, A_103, + A_131, A_073, A_191, A_187, A_133, A_005, A_054, A_085, A_153, + A_154, A_194, A_190, A_104, A_132, A_074, A_192, A_188, A_134, + A_240 { + A_195 a_040(); + A_195 a_000(); + A_195 a_018(); + A_195 a_079(); + A_195 a_080(); + A_195 a_081(); + A_195 a_077(); + A_195 a_036(); + A_195 a_056(); + A_195 a_012(); + A_195 a_078(); + A_195 a_076(); + A_195 a_057(); + } + public interface A_220 extends A_219, A_236, A_005, A_085, A_153, A_074, + A_240 { + A_220 a_040(); + A_220 a_018(); + A_220 a_079(); + A_220 a_012(); + A_220 a_000(); + A_220 a_095(); + A_220 a_080(); + A_220 a_081(); + A_220 a_077(); + A_220 a_036(); + A_220 a_056(); + A_220 a_078(); + A_220 a_076(); + A_220 a_057(); + } + public interface A_146 extends A_000, A_005, A_151, A_150, A_149, A_240 { + A_146 a_040(); + A_146 a_073(); + A_146 a_051(); + } + public interface A_090 extends A_000, A_053, A_084, A_005, A_054, A_085, + A_237, A_091, A_092, A_240 { + A_090 a_040(); + A_090 a_000(); + A_090 a_018(); + A_090 a_027(); + A_090 a_026(); + } + public interface A_057 extends A_106, A_058, A_240 { + A_057 a_002(); + A_057 a_040(); + A_057 a_039(); + A_057 a_032(); + A_057 a_033(); + A_057 a_000(); + A_057 a_018(); + } + public interface A_098 extends A_084, A_005, A_085, A_099, A_100, A_240 { + } + public interface A_136 extends A_084, A_005, A_085, A_138, A_137, A_240 { + } + public interface A_116 extends A_053, A_084, A_005, A_054, A_085, A_121, + A_119, A_118, A_120, A_240 { + A_116 a_040(); + A_116 a_000(); + A_116 a_018(); + A_116 a_053(); + A_116 a_046(); + A_116 a_045(); + A_116 a_048(); + } + public interface A_159 extends A_053, A_005, A_054, A_160, A_240 { + A_159 a_040(); + A_159 a_000(); + } + public interface A_140 extends A_139, A_236, A_005, A_085, A_153, A_074, + A_141, A_142, A_240 { + A_140 a_040(); + A_140 a_018(); + A_140 a_079(); + A_140 a_012(); + A_140 a_060(); + A_140 a_061(); + A_140 a_000(); + A_140 a_080(); + A_140 a_081(); + A_140 a_077(); + A_140 a_036(); + A_140 a_056(); + A_140 a_078(); + A_140 a_076(); + A_140 a_057(); + } + public interface A_178 extends A_177, A_144, A_005, A_179, A_145, A_240 { + A_178 a_040(); + } + public interface A_139 extends A_053, A_005, A_054, A_141, A_142, A_240 { + A_139 a_040(); + A_139 a_000(); + A_139 a_060(); + A_139 a_061(); + } + public interface A_165 extends A_163, A_152, A_005, A_054, A_166, A_167, + A_153, A_154, A_240 { + A_165 a_040(); + A_165 a_000(); + A_165 a_065(); + A_165 a_066(); + A_165 a_079(); + A_165 a_080(); + } + public interface A_053 extends A_000, A_238, A_005, A_054, A_240 { + A_053 a_040(); + A_053 a_000(); + } + public interface A_135 extends A_136, A_236, A_005, A_085, A_153, A_074, + A_138, A_137, A_240 { + A_135 a_040(); + A_135 a_018(); + A_135 a_079(); + A_135 a_012(); + A_135 a_059(); + A_135 a_058(); + A_135 a_000(); + A_135 a_081(); + A_135 a_077(); + A_135 a_036(); + A_135 a_056(); + A_135 a_078(); + A_135 a_076(); + A_135 a_057(); + } + public interface A_148 extends A_146, A_236, A_005, A_085, A_153, A_074, + A_240 { + A_148 a_040(); + A_148 a_018(); + A_148 a_079(); + A_148 a_012(); + A_148 a_051(); + A_148 a_000(); + A_148 a_081(); + A_148 a_077(); + A_148 a_036(); + A_148 a_056(); + A_148 a_078(); + A_148 a_076(); + A_148 a_057(); + } + public interface A_206 extends A_000, A_005, A_208, A_207, A_209, A_240 { + A_206 a_040(); + A_206 a_089(); + A_206 a_088(); + A_206 a_090(); + } + public interface A_215 extends A_000, A_005, A_216, A_240 { + A_215 a_040(); + A_215 a_092(); + } + public interface A_117 extends A_116, A_090, A_005, A_054, A_085, A_121, + A_119, A_118, A_120, A_091, A_092, A_240 { + A_117 a_040(); + A_117 a_000(); + A_117 a_018(); + A_117 a_053(); + A_117 a_046(); + A_117 a_045(); + A_117 a_048(); + A_117 a_026(); + A_117 a_027(); + } + public interface A_082 extends A_000, A_005, A_083, A_240 { + A_082 a_040(); + } + public interface A_182 extends A_053, A_084, A_152, A_193, A_189, A_005, + A_054, A_085, A_153, A_154, A_194, A_190, A_240 { + A_182 a_040(); + A_182 a_000(); + A_182 a_018(); + A_182 a_079(); + A_182 a_080(); + A_182 a_081(); + A_182 a_077(); + } + public interface A_055 extends A_000, A_005, A_056, A_240 { + } + public interface A_193 extends A_000, A_005, A_194, A_240 { + A_193 a_040(); + A_193 a_081(); + } + public interface A_214 extends A_212, A_152, A_005, A_054, A_085, A_217, + A_218, A_153, A_154, A_240 { + A_214 a_040(); + A_214 a_000(); + A_214 a_018(); + A_214 a_093(); + A_214 a_079(); + } + public interface A_059 extends A_053, A_084, A_005, A_054, A_085, A_063, + A_062, A_064, A_065, A_066, A_061, A_060, A_240 { + A_059 a_040(); + A_059 a_000(); + A_059 a_018(); + A_059 a_046(); + A_059 a_045(); + A_059 a_047(); + A_059 a_048(); + A_059 a_049(); + A_059 a_044(); + A_059 a_043(); + } + public interface A_226 extends A_000, A_228, A_240 { + A_226 a_100(); + A_226 a_040(); + } + public interface A_210 extends A_053, A_005, A_054, A_211, A_240 { + A_210 a_040(); + A_210 a_000(); + A_210 a_091(); + } + public interface A_073 extends A_000, A_005, A_074, A_240 { + A_073 a_040(); + A_073 a_012(); + } + public interface A_157 extends A_155, A_236, A_005, A_085, A_153, A_074, + A_160, A_162, A_240 { + A_157 a_040(); + A_157 a_018(); + A_157 a_079(); + A_157 a_012(); + A_157 a_000(); + A_157 a_081(); + A_157 a_077(); + A_157 a_036(); + A_157 a_056(); + A_157 a_078(); + A_157 a_076(); + A_157 a_057(); + } + public interface A_131 extends A_053, A_005, A_054, A_132, A_240 { + A_131 a_040(); + A_131 a_000(); + A_131 a_056(); + } + public interface A_152 extends A_053, A_005, A_054, A_153, A_154, A_240 { + A_152 a_040(); + A_152 a_000(); + A_152 a_079(); + } + public interface A_106 extends A_053, A_084, A_005, A_115, A_113, A_112, + A_240 { + A_106 a_040(); + A_106 a_039(); + A_106 a_032(); + A_106 a_033(); + A_106 a_000(); + A_106 a_018(); + } + public interface A_147 extends A_106, A_236, A_005, A_085, A_153, A_074, + A_240 { + A_147 a_040(); + A_147 a_018(); + A_147 a_012(); + A_147 a_039(); + A_147 a_032(); + A_147 a_033(); + A_147 a_000(); + A_147 a_081(); + A_147 a_077(); + A_147 a_036(); + A_147 a_056(); + A_147 a_078(); + A_147 a_076(); + A_147 a_057(); + } + public interface A_081 extends A_075, A_152, A_005, A_054, A_076, A_077, + A_078, A_079, A_153, A_154, A_240 { + A_081 a_040(); + A_081 a_000(); + A_081 a_014(); + A_081 a_015(); + A_081 a_016(); + A_081 a_079(); + A_081 a_080(); + } + public interface A_197 extends A_196, A_070, A_236, A_005, A_085, A_153, + A_074, A_203, A_071, A_240 { + A_197 a_040(); + A_197 a_018(); + A_197 a_079(); + A_197 a_012(); + A_197 a_084(); + A_197 a_011(); + A_197 a_000(); + A_197 a_081(); + A_197 a_077(); + A_197 a_036(); + A_197 a_056(); + A_197 a_078(); + A_197 a_076(); + A_197 a_057(); + } + public interface A_213 extends A_212, A_215, A_236, A_005, A_085, A_153, + A_074, A_240 { + A_213 a_040(); + A_213 a_018(); + A_213 a_079(); + A_213 a_012(); + A_213 a_000(); + A_213 a_093(); + A_213 a_092(); + A_213 a_081(); + A_213 a_077(); + A_213 a_036(); + A_213 a_056(); + A_213 a_078(); + A_213 a_076(); + A_213 a_057(); + } + public interface A_143 extends A_139, A_152, A_005, A_141, A_142, A_153, + A_154, A_240 { + A_143 a_040(); + A_143 a_060(); + A_143 a_061(); + A_143 a_079(); + A_143 a_080(); + A_143 a_000(); + } + public interface A_221 extends A_219, A_152, A_005, A_054, A_085, A_222, + A_223, A_153, A_154, A_240 { + A_221 a_040(); + A_221 a_000(); + A_221 a_018(); + A_221 a_095(); + A_221 a_079(); + A_221 a_080(); + } + public interface A_196 extends A_000, A_005, A_203, A_240 { + A_196 a_040(); + A_196 a_084(); + } + public interface A_155 extends A_159, A_161, A_005, A_054, A_160, A_162, + A_240 { + A_155 a_040(); + A_155 a_000(); + } + public interface A_097 extends A_094, A_152, A_005, A_085, A_095, A_096, + A_153, A_154, A_240 { + A_097 a_040(); + A_097 a_018(); + A_097 a_029(); + A_097 a_079(); + A_097 a_000(); + } + public interface A_219 extends A_053, A_084, A_005, A_054, A_085, A_222, + A_223, A_240 { + A_219 a_040(); + A_219 a_000(); + A_219 a_018(); + A_219 a_095(); + A_219 a_096(); + } + public interface A_068 extends A_053, A_005, A_054, A_069, A_240 { + A_068 a_040(); + A_068 a_000(); + A_068 a_010(); + } + public interface A_114 extends A_106, A_236, A_005, A_085, A_153, A_074, + A_115, A_113, A_240 { + A_114 a_040(); + A_114 a_018(); + A_114 a_079(); + A_114 a_012(); + A_114 a_039(); + A_114 a_032(); + A_114 a_033(); + A_114 a_000(); + A_114 a_080(); + A_114 a_081(); + A_114 a_077(); + A_114 a_036(); + A_114 a_056(); + A_114 a_078(); + A_114 a_076(); + A_114 a_057(); + } + public interface A_163 extends A_053, A_005, A_054, A_166, A_167, A_240 { + A_163 a_040(); + A_163 a_000(); + A_163 a_065(); + A_163 a_066(); + } + public interface A_187 extends A_000, A_005, A_188, A_240 { + A_187 a_040(); + A_187 a_076(); + } + public interface A_144 extends A_000, A_005, A_145, A_240 { + A_144 a_040(); + } + public interface A_111 extends A_106, A_212, A_219, A_170, A_005, A_054, + A_085, A_115, A_113, A_112, A_217, A_218, A_222, A_223, A_173, + A_240 { + A_111 a_040(); + A_111 a_000(); + A_111 a_018(); + A_111 a_039(); + A_111 a_032(); + A_111 a_033(); + A_111 a_093(); + A_111 a_095(); + A_111 a_069(); + } + public interface A_168 extends A_000, A_053, A_005, A_054, A_169, A_240 { + A_168 a_040(); + A_168 a_000(); + A_168 a_037(); + } + public interface A_227 extends A_226, A_236, A_005, A_085, A_153, A_074, + A_228, A_240 { + A_227 a_040(); + A_227 a_018(); + A_227 a_079(); + A_227 a_012(); + A_227 a_100(); + A_227 a_000(); + A_227 a_081(); + A_227 a_077(); + A_227 a_036(); + A_227 a_056(); + A_227 a_078(); + A_227 a_076(); + A_227 a_057(); + } + public interface A_075 extends A_053, A_005, A_054, A_076, A_077, A_078, + A_079, A_240 { + A_075 a_040(); + A_075 a_000(); + A_075 a_014(); + A_075 a_015(); + A_075 a_016(); + A_075 a_017(); + } + public interface A_008 extends A_239 { + A_008 a_040(); + } + public interface A_072 extends A_070, A_090, A_005, A_054, A_085, A_091, + A_092, A_071, A_240 { + A_072 a_040(); + A_072 a_000(); + A_072 a_018(); + A_072 a_026(); + A_072 a_011(); + A_072 a_027(); + } + public interface A_170 extends A_000, A_005, A_173, A_174, A_240 { + A_170 a_040(); + A_170 a_069(); + A_170 a_072(); + } + public interface A_012 extends A_239 { + A_012 a_063(); + } + public interface A_164 extends A_163, A_236, A_005, A_085, A_153, A_074, + A_166, A_167, A_240 { + A_164 a_040(); + A_164 a_018(); + A_164 a_079(); + A_164 a_012(); + A_164 a_065(); + A_164 a_066(); + A_164 a_000(); + A_164 a_080(); + A_164 a_081(); + A_164 a_077(); + A_164 a_036(); + A_164 a_056(); + A_164 a_078(); + A_164 a_076(); + A_164 a_057(); + } + public interface A_006 extends A_239 { + A_006 a_004(); + } + public interface A_007 extends A_239 { + } + public interface A_201 extends A_200, A_236, A_005, A_085, A_153, A_074, + A_240 { + A_201 a_040(); + A_201 a_018(); + A_201 a_079(); + A_201 a_012(); + A_201 a_085(); + A_201 a_000(); + A_201 a_081(); + A_201 a_077(); + A_201 a_036(); + A_201 a_056(); + A_201 a_078(); + A_201 a_076(); + A_201 a_057(); + } + public interface A_011 extends A_239 { + A_011 a_062(); + } + public interface A_014 extends A_239 { + A_014 a_075(); + } + public interface A_009 extends A_239 { + A_009 a_045(); + } + public interface A_010 extends A_239 { + A_010 a_050(); + } + public interface A_013 extends A_239 { + A_013 a_067(); + } + public interface A_236 extends A_195, A_005, A_085, A_153, A_074, A_240 { + A_236 a_040(); + A_236 a_018(); + A_236 a_079(); + A_236 a_012(); + A_236 a_000(); + A_236 a_081(); + A_236 a_077(); + A_236 a_036(); + A_236 a_056(); + A_236 a_078(); + A_236 a_076(); + A_236 a_057(); + } + interface X_1 { AbstractList x_8(); -- GitLab From 13f739d330e393f840d134f5327a025957e1f795 Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Wed, 9 Feb 2022 04:10:37 +0000 Subject: [PATCH 437/564] 8280830: Change NonblockingQueue::try_pop variable named "result" Reviewed-by: dholmes --- .../utilities/nonblockingQueue.inline.hpp | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/hotspot/share/utilities/nonblockingQueue.inline.hpp b/src/hotspot/share/utilities/nonblockingQueue.inline.hpp index e16c8cb57d0..2845822b204 100644 --- a/src/hotspot/share/utilities/nonblockingQueue.inline.hpp +++ b/src/hotspot/share/utilities/nonblockingQueue.inline.hpp @@ -135,36 +135,36 @@ template bool NonblockingQueue::try_pop(T** node_ptr) { // We only need memory_order_consume. Upgrade it to "load_acquire" // as the memory_order_consume API is not ready for use yet. - T* result = Atomic::load_acquire(&_head); - if (result == NULL) { + T* old_head = Atomic::load_acquire(&_head); + if (old_head == NULL) { *node_ptr = NULL; return true; // Queue is empty. } - T* next_node = Atomic::load_acquire(next_ptr(*result)); + T* next_node = Atomic::load_acquire(next_ptr(*old_head)); if (!is_end(next_node)) { // [Clause 1] // There are several cases for next_node. // (1) next_node is the extension of the queue's list. - // (2) next_node is NULL, because a competing try_pop took result. + // (2) next_node is NULL, because a competing try_pop took old_head. // (3) next_node is the extension of some unrelated list, because a - // competing try_pop took result and put it in some other list. + // competing try_pop took old_head and put it in some other list. // - // Attempt to advance the list, replacing result with next_node in + // Attempt to advance the list, replacing old_head with next_node in // _head. The success or failure of that attempt, along with the value // of next_node, are used to partially determine which case we're in and // how to proceed. In particular, advancement will fail for case (3). - if (result != Atomic::cmpxchg(&_head, result, next_node)) { + if (old_head != Atomic::cmpxchg(&_head, old_head, next_node)) { // [Clause 1a] // The cmpxchg to advance the list failed; a concurrent try_pop won - // the race and claimed result. This can happen for any of the + // the race and claimed old_head. This can happen for any of the // next_node cases. return false; } else if (next_node == NULL) { // [Clause 1b] // The cmpxchg to advance the list succeeded, but a concurrent try_pop - // has already claimed result (see [Clause 2] - result was the last - // entry in the list) by nulling result's next field. The advance set + // has already claimed old_head (see [Clause 2] - old_head was the last + // entry in the list) by nulling old_head's next field. The advance set // _head to NULL, "helping" the competing try_pop. _head will remain // NULL until a subsequent push/append. This is a lost race, and we // report it as such for consistency, though we could report the queue @@ -174,17 +174,17 @@ bool NonblockingQueue::try_pop(T** node_ptr) { return false; } else { // [Clause 1c] - // Successfully advanced the list and claimed result. next_node was - // in the extension of the queue's list. Return result after + // Successfully advanced the list and claimed old_head. next_node was + // in the extension of the queue's list. Return old_head after // unlinking it from next_node. - set_next(*result, NULL); - *node_ptr = result; + set_next(*old_head, NULL); + *node_ptr = old_head; return true; } - } else if (is_end(Atomic::cmpxchg(next_ptr(*result), next_node, (T*)NULL))) { + } else if (is_end(Atomic::cmpxchg(next_ptr(*old_head), next_node, (T*)NULL))) { // [Clause 2] - // Result was the last entry and we've claimed it by setting its next + // Old_head was the last entry and we've claimed it by setting its next // value to NULL. However, this leaves the queue in disarray. Fix up // the queue, possibly in conjunction with other concurrent operations. // Any further try_pops will consider the queue empty until a @@ -194,24 +194,24 @@ bool NonblockingQueue::try_pop(T** node_ptr) { // dealing with _head first gives a stronger invariant in append, and is // also consistent with [Clause 1b]. - // Attempt to change the queue head from result to NULL. Failure of the + // Attempt to change the queue head from old_head to NULL. Failure of the // cmpxchg indicates a concurrent operation updated _head first. That // could be either a push/append or a try_pop in [Clause 1b]. - Atomic::cmpxchg(&_head, result, (T*)NULL); + Atomic::cmpxchg(&_head, old_head, (T*)NULL); - // Attempt to change the queue tail from result to NULL. Failure of the + // Attempt to change the queue tail from old_head to NULL. Failure of the // cmpxchg indicates that a concurrent push/append updated _tail first. - // That operation will eventually recognize the old tail (our result) is + // That operation will eventually recognize the old tail (our old_head) is // no longer in the list and update _head from the list being appended. - Atomic::cmpxchg(&_tail, result, (T*)NULL); + Atomic::cmpxchg(&_tail, old_head, (T*)NULL); - // The queue has been restored to order, and we can return the result. - *node_ptr = result; + // The queue has been restored to order, and we can return old_head. + *node_ptr = old_head; return true; } else { // [Clause 3] - // Result was the last entry in the list, but either a concurrent + // Old_head was the last entry in the list, but either a concurrent // try_pop claimed it first or a concurrent push/append extended the // list from it. Either way, we lost the race to claim it. return false; -- GitLab From bce5dd17665d1cdf2901690ca54f84ec200560af Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Wed, 9 Feb 2022 04:38:11 +0000 Subject: [PATCH 438/564] 8280438: Improve BufferNode::Allocator::release to avoid walking pending list Reviewed-by: iwalulya, tschatzl --- src/hotspot/share/gc/shared/ptrQueue.cpp | 93 +++++++++++++++--------- src/hotspot/share/gc/shared/ptrQueue.hpp | 33 +++++++-- 2 files changed, 87 insertions(+), 39 deletions(-) diff --git a/src/hotspot/share/gc/shared/ptrQueue.cpp b/src/hotspot/share/gc/shared/ptrQueue.cpp index 3838b4f37ee..0a95e36de2b 100644 --- a/src/hotspot/share/gc/shared/ptrQueue.cpp +++ b/src/hotspot/share/gc/shared/ptrQueue.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2022, 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 @@ -56,11 +56,38 @@ void BufferNode::deallocate(BufferNode* node) { FREE_C_HEAP_ARRAY(char, node); } +BufferNode::Allocator::PendingList::PendingList() : + _tail(nullptr), _head(nullptr), _count(0) {} + +BufferNode::Allocator::PendingList::~PendingList() { + delete_list(Atomic::load(&_head)); +} + +size_t BufferNode::Allocator::PendingList::add(BufferNode* node) { + assert(node->next() == nullptr, "precondition"); + BufferNode* old_head = Atomic::xchg(&_head, node); + if (old_head != nullptr) { + node->set_next(old_head); + } else { + assert(_tail == nullptr, "invariant"); + _tail = node; + } + return Atomic::add(&_count, size_t(1)); +} + +BufferNodeList BufferNode::Allocator::PendingList::take_all() { + BufferNodeList result{Atomic::load(&_head), _tail, Atomic::load(&_count)}; + Atomic::store(&_head, (BufferNode*)nullptr); + _tail = nullptr; + Atomic::store(&_count, size_t(0)); + return result; +} + BufferNode::Allocator::Allocator(const char* name, size_t buffer_size) : _buffer_size(buffer_size), - _pending_list(), + _pending_lists(), + _active_pending_list(0), _free_list(), - _pending_count(0), _free_count(0), _transfer_lock(false) { @@ -70,7 +97,6 @@ BufferNode::Allocator::Allocator(const char* name, size_t buffer_size) : BufferNode::Allocator::~Allocator() { delete_list(_free_list.pop_all()); - delete_list(_pending_list.pop_all()); } void BufferNode::Allocator::delete_list(BufferNode* list) { @@ -109,14 +135,11 @@ BufferNode* BufferNode::Allocator::allocate() { // pop inside a critical section, and release synchronizes on the // critical sections before adding to the _free_list. But we don't // want to make every release have to do a synchronize. Instead, we -// initially place released nodes on the _pending_list, and transfer +// initially place released nodes on the pending list, and transfer // them to the _free_list in batches. Only one transfer at a time is -// permitted, with a lock bit to control access to that phase. A -// transfer takes all the nodes from the _pending_list, synchronizes on -// the _free_list pops, and then adds the former pending nodes to the -// _free_list. While that's happening, other threads might be adding -// other nodes to the _pending_list, to be dealt with by some later -// transfer. +// permitted, with a lock bit to control access to that phase. While +// a transfer is in progress, other threads might be adding other nodes +// to the pending list, to be dealt with by some later transfer. void BufferNode::Allocator::release(BufferNode* node) { assert(node != NULL, "precondition"); assert(node->next() == NULL, "precondition"); @@ -130,15 +153,20 @@ void BufferNode::Allocator::release(BufferNode* node) { // similar, due to how the buffers are used. const size_t trigger_transfer = 10; - // Add to pending list. Update count first so no underflow in transfer. - size_t pending_count = Atomic::add(&_pending_count, 1u); - _pending_list.push(*node); - if (pending_count > trigger_transfer) { - try_transfer_pending(); + // The pending list is double-buffered. Add node to the currently active + // pending list, within a critical section so a transfer will wait until + // we're done with what might be the pending list to be transferred. + { + GlobalCounter::CriticalSection cs(Thread::current()); + uint index = Atomic::load_acquire(&_active_pending_list); + size_t count = _pending_lists[index].add(node); + if (count <= trigger_transfer) return; } + // Attempt transfer when number pending exceeds the transfer threshold. + try_transfer_pending(); } -// Try to transfer nodes from _pending_list to _free_list, with a +// Try to transfer nodes from the pending list to _free_list, with a // synchronization delay for any in-progress pops from the _free_list, // to solve ABA there. Return true if performed a (possibly empty) // transfer, false if blocked from doing so by some other thread's @@ -151,27 +179,26 @@ bool BufferNode::Allocator::try_transfer_pending() { } // Have the lock; perform the transfer. - // Claim all the pending nodes. - BufferNode* first = _pending_list.pop_all(); - if (first != NULL) { - // Prepare to add the claimed nodes, and update _pending_count. - BufferNode* last = first; - size_t count = 1; - for (BufferNode* next = first->next(); next != NULL; next = next->next()) { - last = next; - ++count; - } - Atomic::sub(&_pending_count, count); + // Change which pending list is active. Don't need an atomic RMW since + // we have the lock and we're the only writer. + uint index = Atomic::load(&_active_pending_list); + uint new_active = (index + 1) % ARRAY_SIZE(_pending_lists); + Atomic::release_store(&_active_pending_list, new_active); - // Wait for any in-progress pops, to avoid ABA for them. - GlobalCounter::write_synchronize(); + // Wait for all critical sections in the buffer life-cycle to complete. + // This includes _free_list pops and adding to the now inactive pending + // list. + GlobalCounter::write_synchronize(); - // Add synchronized nodes to _free_list. + // Transfer the inactive pending list to _free_list. + BufferNodeList transfer_list = _pending_lists[index].take_all(); + size_t count = transfer_list._entry_count; + if (count > 0) { // Update count first so no underflow in allocate(). Atomic::add(&_free_count, count); - _free_list.prepend(*first, *last); + _free_list.prepend(*transfer_list._head, *transfer_list._tail); log_trace(gc, ptrqueue, freelist) - ("Transferred %s pending to free: " SIZE_FORMAT, name(), count); + ("Transferred %s pending to free: %zu", name(), count); } Atomic::release_store(&_transfer_lock, false); return true; diff --git a/src/hotspot/share/gc/shared/ptrQueue.hpp b/src/hotspot/share/gc/shared/ptrQueue.hpp index f1533e5128d..be07f3e58b3 100644 --- a/src/hotspot/share/gc/shared/ptrQueue.hpp +++ b/src/hotspot/share/gc/shared/ptrQueue.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ #ifndef SHARE_GC_SHARED_PTRQUEUE_HPP #define SHARE_GC_SHARED_PTRQUEUE_HPP +#include "gc/shared/bufferNodeList.hpp" #include "memory/padded.hpp" #include "utilities/align.hpp" #include "utilities/debug.hpp" @@ -181,17 +182,37 @@ class BufferNode::Allocator { #define DECLARE_PADDED_MEMBER(Id, Type, Name) \ Type Name; DEFINE_PAD_MINUS_SIZE(Id, DEFAULT_CACHE_LINE_SIZE, sizeof(Type)) + class PendingList { + BufferNode* _tail; + DECLARE_PADDED_MEMBER(1, BufferNode* volatile, _head); + DECLARE_PADDED_MEMBER(2, volatile size_t, _count); + + NONCOPYABLE(PendingList); + + public: + PendingList(); + ~PendingList(); + + // Add node to the list. Returns the number of nodes in the list. + // Thread-safe against concurrent add operations. + size_t add(BufferNode* node); + + // Return the nodes in the list, leaving the list empty. + // Not thread-safe. + BufferNodeList take_all(); + }; + const size_t _buffer_size; char _name[DEFAULT_CACHE_LINE_SIZE - sizeof(size_t)]; // Use name as padding. - DECLARE_PADDED_MEMBER(1, Stack, _pending_list); + PendingList _pending_lists[2]; + DECLARE_PADDED_MEMBER(1, volatile uint, _active_pending_list); DECLARE_PADDED_MEMBER(2, Stack, _free_list); - DECLARE_PADDED_MEMBER(3, volatile size_t, _pending_count); - DECLARE_PADDED_MEMBER(4, volatile size_t, _free_count); - DECLARE_PADDED_MEMBER(5, volatile bool, _transfer_lock); + DECLARE_PADDED_MEMBER(3, volatile size_t, _free_count); + DECLARE_PADDED_MEMBER(4, volatile bool, _transfer_lock); #undef DECLARE_PADDED_MEMBER - void delete_list(BufferNode* list); + static void delete_list(BufferNode* list); bool try_transfer_pending(); NONCOPYABLE(Allocator); -- GitLab From fc77217814eb1a346d7380299abdc2b01a69b4de Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Wed, 9 Feb 2022 06:28:00 +0000 Subject: [PATCH 439/564] 8281168: Micro-optimize VarForm.getMemberName for interpreter Reviewed-by: redestad, vlivanov, mchung --- .../share/classes/java/lang/invoke/VarForm.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/java.base/share/classes/java/lang/invoke/VarForm.java b/src/java.base/share/classes/java/lang/invoke/VarForm.java index 7b118dbe470..1308c48cebb 100644 --- a/src/java.base/share/classes/java/lang/invoke/VarForm.java +++ b/src/java.base/share/classes/java/lang/invoke/VarForm.java @@ -109,9 +109,14 @@ final class VarForm { @ForceInline final MemberName getMemberName(int mode) { - MemberName mn = getMemberNameOrNull(mode); + // Can be simplified by calling getMemberNameOrNull, but written in this + // form to improve interpreter/coldpath performance. + MemberName mn = memberName_table[mode]; if (mn == null) { - throw new UnsupportedOperationException(); + mn = resolveMemberName(mode); + if (mn == null) { + throw new UnsupportedOperationException(); + } } return mn; } -- GitLab From cb2f8caed2de1bf0a85a7ebfd232c36371e06c98 Mon Sep 17 00:00:00 2001 From: Artem Semenov Date: Wed, 9 Feb 2022 06:50:35 +0000 Subject: [PATCH 440/564] 8281338: NSAccessibilityPressAction action for tree node and NSAccessibilityShowMenuAcgtion action not working Reviewed-by: ant, kizune --- .../awt/JavaAccessibilityAction.m | 4 +- .../java/awt/a11y/AccessibleActionsTest.java | 183 ++++++++++++++++++ 2 files changed, 185 insertions(+), 2 deletions(-) create mode 100644 test/jdk/java/awt/a11y/AccessibleActionsTest.java diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityAction.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityAction.m index 06e998ec409..173ad891051 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityAction.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityAction.m @@ -161,8 +161,8 @@ void initializeActions() { [sActions setObject:NSAccessibilityPressAction forKey:@"click"]; [sActions setObject:NSAccessibilityIncrementAction forKey:@"increment"]; [sActions setObject:NSAccessibilityDecrementAction forKey:@"decrement"]; - [sActions setObject:NSAccessibilityShowMenuAction forKey:@"togglePopup"]; - [sActions setObject:NSAccessibilityPressAction forKey:@"toggleExpand"]; + [sActions setObject:NSAccessibilityShowMenuAction forKey:@"toggle popup"]; + [sActions setObject:NSAccessibilityPressAction forKey:@"toggleexpand"]; sActionSelectors = [[NSMutableDictionary alloc] initWithCapacity:actionsCount]; diff --git a/test/jdk/java/awt/a11y/AccessibleActionsTest.java b/test/jdk/java/awt/a11y/AccessibleActionsTest.java new file mode 100644 index 00000000000..b8f6e5d28f9 --- /dev/null +++ b/test/jdk/java/awt/a11y/AccessibleActionsTest.java @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, JetBrains s.r.o.. 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 8281338 + * @summary Test for an element that has more than one Accessibility Action + * @author Artem.Semenov@jetbrains.com + * @run main/manual AccessibleActionsTest + * @requires (os.family == "mac") + */ + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleAction; +import javax.accessibility.AccessibleContext; +import javax.swing.*; +import javax.swing.tree.TreeModel; +import javax.swing.tree.TreePath; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.Hashtable; +import java.util.concurrent.CountDownLatch; + +public class AccessibleActionsTest extends AccessibleComponentTest { + + @Override + public CountDownLatch createCountDownLatch() { + return new CountDownLatch(1); + } + + void createTest() { + INSTRUCTIONS = "INSTRUCTIONS:\n" + + "Check a11y actions.\n\n" + + "Turn screen reader on, and Tab to the label.\n\n" + + "Perform the VO action \"Press\" (VO+space)\n" + + "Perform the VO action \"Show menu\" (VO+m)\n\n" + + "If after the first action the text of the label has changed, and after the second action the menu appears tab further and press PASS, otherwise press FAIL."; + + exceptionString = "AccessibleAction test failed!"; + super.createUI(new AccessibleActionsTestFrame(), "AccessibleActionsTest"); + } + + void createTree() { + INSTRUCTIONS = "INSTRUCTIONS:\n" + + "Check a11y actions.\n\n" + + "Turn screen reader on, and Tab to the label.\n\n" + + "Perform the VO action \"Press\" (VO+space) on tree nodes\n\n" + + "If after press the tree node is expanded tab further and press PASS, otherwise press FAIL."; + + String root = "Root"; + String[] nodes = new String[] {"One node", "Two node"}; + String[][] leafs = new String[][]{{"leaf 1.1", "leaf 1.2", "leaf 1.3", "leaf 1.4"}, + {"leaf 2.1", "leaf 2.2", "leaf 2.3", "leaf 2.4"}}; + + Hashtable data = new Hashtable(); + for (int i = 0; i < nodes.length; i++) { + data.put(nodes[i], leafs[i]); + } + + JTree tree = new JTree(data); + tree.setRootVisible(true); + + JPanel panel = new JPanel(); + panel.setLayout(new FlowLayout()); + JScrollPane scrollPane = new JScrollPane(tree); + panel.add(scrollPane); + panel.setFocusable(false); + + exceptionString = "AccessibleAction test failed!"; + super.createUI(panel, "AccessibleActionsTest"); + } + + public static void main(String[] args) throws Exception { + AccessibleActionsTest test = new AccessibleActionsTest(); + + countDownLatch = test.createCountDownLatch(); + SwingUtilities.invokeLater(test::createTest); + countDownLatch.await(); + + if (!testResult) { + throw new RuntimeException(a11yTest.exceptionString); + } + + countDownLatch = test.createCountDownLatch(); + SwingUtilities.invokeLater(test::createTree); + countDownLatch.await(); + + if (!testResult) { + throw new RuntimeException(a11yTest.exceptionString); + } + } + + private class AccessibleActionsTestFrame extends JPanel { + + public AccessibleActionsTestFrame() { + MyLabel label = new MyLabel("I'm waiting for the push"); + label.setComponentPopupMenu(createPopup()); + label.setFocusable(true); + add(label); + setLayout(new FlowLayout()); + } + + private static class MyLabel extends JLabel { + public MyLabel(String text) { + super(text); + } + + @Override + public AccessibleContext getAccessibleContext() { + if (accessibleContext == null) { + accessibleContext = new MyAccessibleJLabel(); + } + return accessibleContext; + } + + private class MyAccessibleJLabel extends JLabel.AccessibleJLabel { + @Override + public AccessibleAction getAccessibleAction() { + return new AccessibleAction() { + @Override + public int getAccessibleActionCount() { + return 2; + } + + @Override + public String getAccessibleActionDescription(int i) { + if (i == 0) { + return AccessibleAction.CLICK; + } + return AccessibleAction.TOGGLE_POPUP; + } + + @Override + public boolean doAccessibleAction(int i) { + if (i == 0) { + changeText(MyLabel.this, "label is pressed"); + return true; + } + JPopupMenu popup = createPopup(); + popup.show(MyLabel.this, 0, 0); + return true; + } + }; + } + } + } + + private static JPopupMenu createPopup() { + JPopupMenu popup = new JPopupMenu("MENU"); + popup.add("One"); + popup.add("Two"); + popup.add("Three"); + return popup; + } + + private static void changeText(JLabel label, String text) { + label.setText(text); + } + + } +} -- GitLab From 072e7b4da0449ab7c1ab1ba0cfbb3db233823e7c Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Wed, 9 Feb 2022 06:53:09 +0000 Subject: [PATCH 441/564] 8272807: Permit use of memory concurrent with pretouch Reviewed-by: shade, stuefe --- src/hotspot/share/runtime/os.cpp | 30 ++++++++++++++++++++++++------ src/hotspot/share/runtime/os.hpp | 7 +++---- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/src/hotspot/share/runtime/os.cpp b/src/hotspot/share/runtime/os.cpp index 29a3d7622f6..a85be30ec48 100644 --- a/src/hotspot/share/runtime/os.cpp +++ b/src/hotspot/share/runtime/os.cpp @@ -1745,13 +1745,31 @@ void os::print_memory_mappings(outputStream* st) { os::print_memory_mappings(nullptr, (size_t)-1, st); } +// Pretouching must use a store, not just a load. On many OSes loads from +// fresh memory would be satisfied from a single mapped page containing all +// zeros. We need to store something to each page to get them backed by +// their own memory, which is the effect we want here. An atomic add of +// zero is used instead of a simple store, allowing the memory to be used +// while pretouch is in progress, rather than requiring users of the memory +// to wait until the entire range has been touched. This is technically +// a UB data race, but doesn't cause any problems for us. void os::pretouch_memory(void* start, void* end, size_t page_size) { - for (volatile char *p = (char*)start; p < (char*)end; p += page_size) { - // Note: this must be a store, not a load. On many OSes loads from fresh - // memory would be satisfied from a single mapped page containing all zeros. - // We need to store something to each page to get them backed by their own - // memory, which is the effect we want here. - *p = 0; + assert(start <= end, "invalid range: " PTR_FORMAT " -> " PTR_FORMAT, p2i(start), p2i(end)); + assert(is_power_of_2(page_size), "page size misaligned: %zu", page_size); + assert(page_size >= sizeof(int), "page size too small: %zu", page_size); + if (start < end) { + // We're doing concurrent-safe touch and memory state has page + // granularity, so we can touch anywhere in a page. Touch at the + // beginning of each page to simplify iteration. + char* cur = static_cast(align_down(start, page_size)); + void* last = align_down(static_cast(end) - 1, page_size); + assert(cur <= last, "invariant"); + // Iterate from first page through last (inclusive), being careful to + // avoid overflow if the last page abuts the end of the address range. + for ( ; true; cur += page_size) { + Atomic::add(reinterpret_cast(cur), 0, memory_order_relaxed); + if (cur >= last) break; + } } } diff --git a/src/hotspot/share/runtime/os.hpp b/src/hotspot/share/runtime/os.hpp index b63637e3576..1ad15f0d8ea 100644 --- a/src/hotspot/share/runtime/os.hpp +++ b/src/hotspot/share/runtime/os.hpp @@ -365,10 +365,9 @@ class os: AllStatic { // Prints all mappings static void print_memory_mappings(outputStream* st); - // Touch memory pages that cover the memory range from start to end (exclusive) - // to make the OS back the memory range with actual memory. - // Current implementation may not touch the last page if unaligned addresses - // are passed. + // Touch memory pages that cover the memory range from start to end + // (exclusive) to make the OS back the memory range with actual memory. + // Other threads may use the memory range concurrently with pretouch. static void pretouch_memory(void* start, void* end, size_t page_size = vm_page_size()); enum ProtType { MEM_PROT_NONE, MEM_PROT_READ, MEM_PROT_RW, MEM_PROT_RWX }; -- GitLab From f924e50c42c2f9548d2983449a98c45af40b0d35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Jeli=C5=84ski?= Date: Wed, 9 Feb 2022 08:34:47 +0000 Subject: [PATCH 442/564] 8281440: AWT: Conversion from string literal loses const qualifier Reviewed-by: prr, aivanov --- .../windows/native/libawt/windows/WPrinterJob.cpp | 6 +++--- .../windows/native/libawt/windows/awt_Debug.cpp | 2 +- .../libawt/windows/awt_DesktopProperties.cpp | 14 +++++++------- .../native/libawt/windows/awt_DrawingSurface.cpp | 2 +- .../windows/native/libawt/windows/awt_Font.cpp | 6 +++--- .../windows/native/libawt/windows/awt_Font.h | 2 +- .../native/libawt/windows/awt_PrintControl.cpp | 2 +- .../windows/native/libawt/windows/awt_PrintJob.cpp | 6 +++--- .../windows/native/libawt/windows/awt_Toolkit.cpp | 2 +- .../native/libawt/windows/awt_Win32GraphicsEnv.cpp | 2 +- 10 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/java.desktop/windows/native/libawt/windows/WPrinterJob.cpp b/src/java.desktop/windows/native/libawt/windows/WPrinterJob.cpp index 812d0df3bbb..16b20afd030 100644 --- a/src/java.desktop/windows/native/libawt/windows/WPrinterJob.cpp +++ b/src/java.desktop/windows/native/libawt/windows/WPrinterJob.cpp @@ -729,7 +729,7 @@ Java_sun_print_Win32PrintService_getPrinterPort(JNIEnv *env, } jstring jPort; - LPTSTR printerName = NULL, printerPort = TEXT("LPT1"); + LPTSTR printerName = NULL, printerPort = (LPTSTR)TEXT("LPT1"); LPBYTE buffer = NULL; DWORD cbBuf = 0; @@ -745,7 +745,7 @@ Java_sun_print_Win32PrintService_getPrinterPort(JNIEnv *env, } if (printerPort == NULL) { - printerPort = TEXT("LPT1"); + printerPort = (LPTSTR)TEXT("LPT1"); } jPort = JNU_NewStringPlatform(env, printerPort); delete [] buffer; @@ -1110,7 +1110,7 @@ Java_sun_print_Win32PrintJob_startPrintRawData(JNIEnv *env, // Fill in the structure with info about this "document." DocInfo.pDocName = jname; DocInfo.pOutputFile = NULL; - DocInfo.pDatatype = TEXT("RAW"); + DocInfo.pDatatype = (LPTSTR)TEXT("RAW"); // Inform the spooler the document is beginning. if( (::StartDocPrinter(hPrinter, 1, (LPBYTE)&DocInfo)) == 0 ) { diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Debug.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Debug.cpp index 5faa5f3a634..88dc0f17abe 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Debug.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Debug.cpp @@ -193,7 +193,7 @@ void AwtDebugSupport::AssertCallback(const char * expr, const char * file, int l NULL); if (msgBuffer == NULL) { - msgBuffer = ""; + msgBuffer = (LPSTR)""; } // format the assertion message _snprintf(assertMsg, ASSERT_MSG_SIZE, AssertFmt, expr, file, line, lastError, msgBuffer); diff --git a/src/java.desktop/windows/native/libawt/windows/awt_DesktopProperties.cpp b/src/java.desktop/windows/native/libawt/windows/awt_DesktopProperties.cpp index e9d4161c89b..9b3668c1798 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_DesktopProperties.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_DesktopProperties.cpp @@ -138,7 +138,7 @@ void AwtDesktopProperties::GetSystemProperties() { // Note that it uses malloc() and returns the pointer to allocated // memory, so remember to use free() when you are done with its // result. -static LPTSTR resolveShellDialogFont(LPTSTR fontName, HKEY handle) { +static LPTSTR resolveShellDialogFont(LPCTSTR fontName, HKEY handle) { DWORD valueType, valueSize; if (RegQueryValueEx((HKEY)handle, fontName, NULL, &valueType, NULL, &valueSize) != 0) { @@ -164,7 +164,7 @@ static LPTSTR resolveShellDialogFont(LPTSTR fontName, HKEY handle) { // memory, so remember to use free() when you are done with its // result. static LPTSTR resolveShellDialogFont() { - LPTSTR subKey = TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes"); + LPCTSTR subKey = TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes"); HKEY handle; if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, subKey, 0, KEY_READ, &handle) != 0) { @@ -183,7 +183,7 @@ static LPTSTR resolveShellDialogFont() { // Note that it uses malloc() and returns the pointer to allocated // memory, so remember to use free() when you are done with its // result. -static LPTSTR getWindowsPropFromReg(LPTSTR subKey, LPTSTR valueName, DWORD *valueType) { +static LPTSTR getWindowsPropFromReg(LPCTSTR subKey, LPCTSTR valueName, DWORD *valueType) { HKEY handle; if (RegOpenKeyEx(HKEY_CURRENT_USER, subKey, 0, KEY_READ, &handle) != 0) { return NULL; @@ -221,7 +221,7 @@ static LPTSTR getWindowsPropFromReg(LPTSTR subKey, LPTSTR valueName, DWORD *valu } } -static LPTSTR getXPStylePropFromReg(LPTSTR valueName) { +static LPTSTR getXPStylePropFromReg(LPCTSTR valueName) { DWORD valueType; return getWindowsPropFromReg(TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\ThemeManager"), valueName, &valueType); @@ -651,11 +651,11 @@ void AwtDesktopProperties::GetOtherParameters() { throw; } - LPTSTR valueName = TEXT("PlaceN"); + LPCTSTR valueName = TEXT("PlaceN"); LPTSTR valueNameBuf = (LPTSTR)SAFE_SIZE_ARRAY_ALLOC(safe_Malloc, (lstrlen(valueName) + 1), sizeof(TCHAR)); lstrcpy(valueNameBuf, valueName); - LPTSTR propKey = TEXT("win.comdlg.placesBarPlaceN"); + LPCTSTR propKey = TEXT("win.comdlg.placesBarPlaceN"); LPTSTR propKeyBuf; try { @@ -672,7 +672,7 @@ void AwtDesktopProperties::GetOtherParameters() { valueNameBuf[5] = _T('0' + i++); propKeyBuf[25] = valueNameBuf[5]; - LPTSTR key = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\comdlg32\\PlacesBar"); + LPCTSTR key = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\comdlg32\\PlacesBar"); try { value = NULL; if ((value = getWindowsPropFromReg(key, valueNameBuf, &valueType)) != NULL) { diff --git a/src/java.desktop/windows/native/libawt/windows/awt_DrawingSurface.cpp b/src/java.desktop/windows/native/libawt/windows/awt_DrawingSurface.cpp index 019295ac2b5..de7f7fd895c 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_DrawingSurface.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_DrawingSurface.cpp @@ -275,7 +275,7 @@ extern "C" JNIEXPORT void JNICALL DSUnlockAWT(JNIEnv* env) // EmbeddedFrame support -static char *const embeddedClassName = "sun/awt/windows/WEmbeddedFrame"; +static const char *const embeddedClassName = "sun/awt/windows/WEmbeddedFrame"; JNIEXPORT jobject JNICALL awt_CreateEmbeddedFrame (JNIEnv* env, void* platformInfo) diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Font.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Font.cpp index cef2e3d1046..48b78183b20 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Font.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Font.cpp @@ -345,7 +345,7 @@ AwtFont* AwtFont::Create(JNIEnv *env, jobject font, jint angle, jfloat awScale) wName = L"Arial"; } - WCHAR* wEName; + LPCWSTR wEName; if (!wcscmp(wName, L"Helvetica") || !wcscmp(wName, L"SansSerif")) { wEName = L"Arial"; } else if (!wcscmp(wName, L"TimesRoman") || @@ -388,7 +388,7 @@ AwtFont* AwtFont::Create(JNIEnv *env, jobject font, jint angle, jfloat awScale) return awtFont; } -static void strip_tail(wchar_t* text, wchar_t* tail) { // strips tail and any possible whitespace before it from the end of text +static void strip_tail(wchar_t* text, const wchar_t* tail) { // strips tail and any possible whitespace before it from the end of text if (wcslen(text)<=wcslen(tail)) { return; } @@ -495,7 +495,7 @@ static HFONT CreateHFont_sub(LPCWSTR name, int style, int height, return hFont; } -HFONT AwtFont::CreateHFont(WCHAR* name, int style, int height, +HFONT AwtFont::CreateHFont(LPCWSTR name, int style, int height, int angle, float awScale) { WCHAR longName[80]; diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Font.h b/src/java.desktop/windows/native/libawt/windows/awt_Font.h index 3f4d8e6a67d..aa1d7241f10 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Font.h +++ b/src/java.desktop/windows/native/libawt/windows/awt_Font.h @@ -155,7 +155,7 @@ public: */ static AwtFont* Create(JNIEnv *env, jobject font, jint angle = 0, jfloat awScale=1.0f); - static HFONT CreateHFont(WCHAR* name, int style, int height, + static HFONT CreateHFont(LPCWSTR name, int style, int height, int angle = 0, float awScale=1.0f); static void Cleanup(); diff --git a/src/java.desktop/windows/native/libawt/windows/awt_PrintControl.cpp b/src/java.desktop/windows/native/libawt/windows/awt_PrintControl.cpp index c29d4c4e7ac..5064bb4fb45 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_PrintControl.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_PrintControl.cpp @@ -1045,7 +1045,7 @@ BOOL AwtPrintControl::UpdateAttributes(JNIEnv *env, DEVNAMES *devnames = (DEVNAMES*)::GlobalLock(pd.hDevNames); DASSERT(!IsBadReadPtr(devnames, sizeof(DEVNAMES))); LPTSTR lpcNames = (LPTSTR)devnames; - LPTSTR pbuf = (_tcslen(lpcNames + devnames->wDeviceOffset) == 0 ? + LPCTSTR pbuf = (_tcslen(lpcNames + devnames->wDeviceOffset) == 0 ? TEXT("") : lpcNames + devnames->wDeviceOffset); if (pbuf != NULL) { jstring jstr = JNU_NewStringPlatform(env, pbuf); diff --git a/src/java.desktop/windows/native/libawt/windows/awt_PrintJob.cpp b/src/java.desktop/windows/native/libawt/windows/awt_PrintJob.cpp index 9eec4d89b15..874ce94c434 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_PrintJob.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_PrintJob.cpp @@ -64,8 +64,8 @@ extern "C" { /*** Private Constants ***/ -static char *kJavaIntStr = "I"; -static char *kJavaLongStr = "J"; +static const char *kJavaIntStr = "I"; +static const char *kJavaLongStr = "J"; /* 2D printing uses 3 byte BGR pixels in Raster printing */ static int J2DRasterBPP = 3; @@ -1353,7 +1353,7 @@ Java_sun_awt_windows_WPrinterJob__1startDoc(JNIEnv *env, jobject self, } else { destination = VerifyDestination(env, self); } - LPTSTR docname = NULL; + LPCTSTR docname = NULL; if (jobname != NULL) { LPTSTR tmp = (LPTSTR)JNU_GetStringPlatformChars(env, jobname, NULL); if (tmp == NULL) { diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp index 17e69d70b15..687eba5deff 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp @@ -530,7 +530,7 @@ void ToolkitThreadProc(void *param) JNIEnv *env; JavaVMAttachArgs attachArgs; attachArgs.version = JNI_VERSION_1_2; - attachArgs.name = "AWT-Windows"; + attachArgs.name = (char*)"AWT-Windows"; attachArgs.group = data->threadGroup; jint res = jvm->AttachCurrentThreadAsDaemon((void **)&env, &attachArgs); diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsEnv.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsEnv.cpp index bc0d6a939fa..434050215a3 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsEnv.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsEnv.cpp @@ -234,7 +234,7 @@ Java_sun_awt_Win32FontManager_getEUDCFontFile(JNIEnv *env, jclass cl) { unsigned long fontPathLen = MAX_PATH + 1; WCHAR tmpPath[MAX_PATH + 1]; LPWSTR fontPath = fontPathBuf; - LPWSTR eudcKey = NULL; + LPCWSTR eudcKey = NULL; LANGID langID = GetSystemDefaultLangID(); //lookup for encoding ID, EUDC only supported in -- GitLab From f092babafb58563a4044463e157e02c397d8c9bc Mon Sep 17 00:00:00 2001 From: Alexey Pavlyutkin Date: Wed, 9 Feb 2022 09:33:35 +0000 Subject: [PATCH 443/564] 8281195: Mistakenly used logging causes significant overhead in interpreter Reviewed-by: shade, dholmes --- src/hotspot/share/interpreter/oopMapCache.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/hotspot/share/interpreter/oopMapCache.cpp b/src/hotspot/share/interpreter/oopMapCache.cpp index 8799275683a..84bef74bed9 100644 --- a/src/hotspot/share/interpreter/oopMapCache.cpp +++ b/src/hotspot/share/interpreter/oopMapCache.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -276,26 +276,26 @@ bool OopMapCacheEntry::verify_mask(CellTypeState* vars, CellTypeState* stack, in // Check if map is generated correctly // (Use ?: operator to make sure all 'true' & 'false' are represented exactly the same so we can use == afterwards) - Log(interpreter, oopmap) logv; - LogStream st(logv.trace()); + const bool log = log_is_enabled(Trace, interpreter, oopmap); + LogStream st(Log(interpreter, oopmap)::trace()); - st.print("Locals (%d): ", max_locals); + if (log) st.print("Locals (%d): ", max_locals); for(int i = 0; i < max_locals; i++) { bool v1 = is_oop(i) ? true : false; bool v2 = vars[i].is_reference() ? true : false; assert(v1 == v2, "locals oop mask generation error"); - st.print("%d", v1 ? 1 : 0); + if (log) st.print("%d", v1 ? 1 : 0); } - st.cr(); + if (log) st.cr(); - st.print("Stack (%d): ", stack_top); + if (log) st.print("Stack (%d): ", stack_top); for(int j = 0; j < stack_top; j++) { bool v1 = is_oop(max_locals + j) ? true : false; bool v2 = stack[j].is_reference() ? true : false; assert(v1 == v2, "stack oop mask generation error"); - st.print("%d", v1 ? 1 : 0); + if (log) st.print("%d", v1 ? 1 : 0); } - st.cr(); + if (log) st.cr(); return true; } -- GitLab From 69e390a0e86f82eaa7bcdbc3ef509734dbe3b22f Mon Sep 17 00:00:00 2001 From: Roland Westrelin Date: Wed, 9 Feb 2022 10:18:27 +0000 Subject: [PATCH 444/564] 8262721: Add Tests to verify single iteration loops are properly optimized Reviewed-by: neliasso, chagedorn, kvn --- .../irTests/TestFewIterationsCountedLoop.java | 139 ++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 test/hotspot/jtreg/compiler/c2/irTests/TestFewIterationsCountedLoop.java diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestFewIterationsCountedLoop.java b/test/hotspot/jtreg/compiler/c2/irTests/TestFewIterationsCountedLoop.java new file mode 100644 index 00000000000..1d3fed1c87a --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/irTests/TestFewIterationsCountedLoop.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2022, Red Hat, Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package compiler.c2.irTests; + +import compiler.lib.ir_framework.*; + +/* + * @test + * @bug 8262721 + * @summary Add Tests to verify single iteration loops are properly optimized + * @library /test/lib / + * @run driver compiler.c2.irTests.TestFewIterationsCountedLoop + */ + +public class TestFewIterationsCountedLoop { + + public static void main(String[] args) { + TestFramework.runWithFlags("-XX:LoopUnrollLimit=0"); + TestFramework.run(); + } + + static volatile int barrier; + static final Object object = new Object(); + + @Test + @IR(failOn = { IRNode.COUNTEDLOOP, IRNode.LOOP }) + public static void singleIterationFor() { + for (int i = 0; i < 1; i++) { + barrier = 0x42; // something that can't be optimized out + } + } + + @Test + @IR(failOn = { IRNode.COUNTEDLOOP, IRNode.LOOP }) + public static void singleIterationWhile() { + int i = 0; + while (i < 1) { + barrier = 0x42; + i++; + } + } + + @Test + @IR(failOn = { IRNode.COUNTEDLOOP, IRNode.LOOP }) + @Warmup(1) // So C2 can't rely on profile data + public static void singleIterationDoWhile() { + int i = 0; + do { + synchronized(object) {} // so loop head is not cloned by ciTypeFlow + barrier = 0x42; + i++; + } while (i < 1); + } + + @Test + @IR(applyIf = { "LoopUnrollLimit", "0" }, counts = { IRNode.COUNTEDLOOP, "1" }) + @IR(applyIf = { "LoopUnrollLimit", "> 0" }, failOn = { IRNode.COUNTEDLOOP, IRNode.LOOP }) + public static void twoIterationsFor() { + for (int i = 0; i < 2; i++) { + barrier = 0x42; // something that can't be optimized out + } + } + + @Test + @IR(applyIf = { "LoopUnrollLimit", "0" }, counts = { IRNode.COUNTEDLOOP, "1" }) + @IR(applyIf = { "LoopUnrollLimit", "> 0" }, failOn = { IRNode.COUNTEDLOOP, IRNode.LOOP }) + public static void twoIterationsWhile() { + int i = 0; + while (i < 2) { + barrier = 0x42; + i++; + } + } + + @Test + @IR(applyIf = { "LoopUnrollLimit", "0" }, counts = { IRNode.COUNTEDLOOP, "1" }) + @IR(applyIf = { "LoopUnrollLimit", "> 0" }, failOn = { IRNode.COUNTEDLOOP, IRNode.LOOP }) + public static void twoIterationsDoWhile() { + int i = 0; + do { + synchronized(object) {} // so loop head is not cloned by ciTypeFlow + barrier = 0x42; + i++; + } while (i < 2); + } + + @Test + @IR(applyIf = { "LoopUnrollLimit", "0" }, counts = { IRNode.COUNTEDLOOP, "1" }) + @IR(applyIf = { "LoopUnrollLimit", "> 0" }, failOn = { IRNode.COUNTEDLOOP, IRNode.LOOP }) + public static void threadIterationsFor() { + for (int i = 0; i < 2; i++) { + barrier = 0x42; // something that can't be optimized out + } + } + + @Test + @IR(applyIf = { "LoopUnrollLimit", "0" }, counts = { IRNode.COUNTEDLOOP, "1" }) + @IR(applyIf = { "LoopUnrollLimit", "> 0" }, failOn = { IRNode.COUNTEDLOOP, IRNode.LOOP }) + public static void threeIterationsWhile() { + int i = 0; + while (i < 2) { + barrier = 0x42; + i++; + } + } + + @Test + @IR(applyIf = { "LoopUnrollLimit", "0" }, counts = { IRNode.COUNTEDLOOP, "1" }) + @IR(applyIf = { "LoopUnrollLimit", "> 0" }, failOn = { IRNode.COUNTEDLOOP, IRNode.LOOP }) + public static void threeIterationsDoWhile() { + int i = 0; + do { + synchronized(object) {} // so loop head is not cloned by ciTypeFlow + barrier = 0x42; + i++; + } while (i < 2); + } +} -- GitLab From bb2e10ccea0c0b89b06ace034c99253e9999ec47 Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Wed, 9 Feb 2022 11:33:16 +0000 Subject: [PATCH 445/564] 8281274: deal with ActiveProcessorCount in os::Linux::print_container_info Reviewed-by: stuefe, sgehwolf, dholmes, iklam --- src/hotspot/os/linux/os_linux.cpp | 6 +++++- test/hotspot/jtreg/containers/docker/TestMisc.java | 12 +++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index 28477ba8bcb..18b908cfc8f 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -2174,7 +2174,11 @@ bool os::Linux::print_container_info(outputStream* st) { int i = OSContainer::active_processor_count(); st->print("active_processor_count: "); if (i > 0) { - st->print_cr("%d", i); + if (ActiveProcessorCount > 0) { + st->print_cr("%d, but overridden by -XX:ActiveProcessorCount %d", i, ActiveProcessorCount); + } else { + st->print_cr("%d", i); + } } else { st->print_cr("not supported"); } diff --git a/test/hotspot/jtreg/containers/docker/TestMisc.java b/test/hotspot/jtreg/containers/docker/TestMisc.java index e242bdf6632..5625fe828bb 100644 --- a/test/hotspot/jtreg/containers/docker/TestMisc.java +++ b/test/hotspot/jtreg/containers/docker/TestMisc.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022, 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 @@ -56,6 +56,7 @@ public class TestMisc { testMinusContainerSupport(); testIsContainerized(); testPrintContainerInfo(); + testPrintContainerInfoActiveProcessorCount(); } finally { DockerTestUtils.removeDockerImage(imageName); } @@ -92,6 +93,15 @@ public class TestMisc { checkContainerInfo(Common.run(opts)); } + private static void testPrintContainerInfoActiveProcessorCount() throws Exception { + Common.logNewTestCase("Test print_container_info()"); + + DockerRunOptions opts = Common.newOpts(imageName, "PrintContainerInfo").addJavaOpts("-XX:ActiveProcessorCount=2"); + Common.addWhiteBoxOpts(opts); + + OutputAnalyzer out = Common.run(opts); + out.shouldContain("but overridden by -XX:ActiveProcessorCount 2"); + } private static void checkContainerInfo(OutputAnalyzer out) throws Exception { String[] expectedToContain = new String[] { -- GitLab From 8b384b986a0a6a972c29a2f7a4d9fd40dc479b48 Mon Sep 17 00:00:00 2001 From: Christian Stein Date: Wed, 9 Feb 2022 11:34:22 +0000 Subject: [PATCH 446/564] 8281470: tools/jar/CreateMissingParentDirectories.java fails with "Should have failed creating jar file" Reviewed-by: lancea --- test/jdk/ProblemList.txt | 1 - .../jdk/tools/jar/CreateMissingParentDirectories.java | 11 +++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 1d08673243f..6b54c726277 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -765,7 +765,6 @@ javax/swing/JTree/4908142/bug4908142.java 8278348 macosx-all # core_tools tools/jlink/plugins/CompressorPluginTest.java 8247407 generic-all -tools/jar/CreateMissingParentDirectories.java 8281470 generic-all ############################################################################ diff --git a/test/jdk/tools/jar/CreateMissingParentDirectories.java b/test/jdk/tools/jar/CreateMissingParentDirectories.java index 93d6d4ce01d..1f8fa4deb38 100644 --- a/test/jdk/tools/jar/CreateMissingParentDirectories.java +++ b/test/jdk/tools/jar/CreateMissingParentDirectories.java @@ -32,6 +32,7 @@ import java.io.PrintWriter; import java.io.StringWriter; import java.nio.file.Files; import java.nio.file.Path; +import java.util.List; import java.util.spi.ToolProvider; import java.util.stream.Stream; @@ -66,7 +67,6 @@ public class CreateMissingParentDirectories { doHappyPathTest(topDir.resolve("a/test.jar"), entry); doHappyPathTest(topDir.resolve("a/b/test.jar"), entry); - doFailingTest(topDir.toString() + "/a/*/test.jar", entry); Path blocker = Files.writeString(topDir.resolve("blocker.txt"), "Blocked!"); doFailingTest(topDir.resolve("blocker.txt/test.jar").toString(), entry); } finally { @@ -77,7 +77,12 @@ public class CreateMissingParentDirectories { private static void doHappyPathTest(Path jar, Path entry) throws Throwable { String[] jarArgs = new String[]{"cf", jar.toString(), entry.toString()}; if (JAR_TOOL.run(System.out, System.err, jarArgs) != 0) { - fail("Could not create jar file: " + jar); + fail("Could not create jar file: " + List.of(jarArgs)); + return; + } + jarArgs = new String[]{"--create", "--file", jar.toString(), entry.toString()}; + if (JAR_TOOL.run(System.out, System.err, jarArgs) != 0) { + fail("Could not create jar file: " + List.of(jarArgs)); return; } pass(); @@ -92,8 +97,6 @@ public class CreateMissingParentDirectories { fail("Should have failed creating jar file: " + jar); return; } - // non-zero exit code expected, check error message contains jar file's name - check(err.toString().contains(jar)); pass(); } -- GitLab From f823bed043dc38d838baaf8c2024ef24b8a50e9b Mon Sep 17 00:00:00 2001 From: Bhavana Kilambi Date: Wed, 9 Feb 2022 13:18:29 +0000 Subject: [PATCH 447/564] 8280007: Enable Neoverse N1 optimizations for Arm Neoverse V1 & N2 Reviewed-by: phh --- src/hotspot/cpu/aarch64/vm_version_aarch64.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp index 833a6ec9f6d..b0c0c64f6d9 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, 2020, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -197,8 +197,10 @@ void VM_Version::initialize() { } } - // Neoverse N1 - if (_cpu == CPU_ARM && (_model == 0xd0c || _model2 == 0xd0c)) { + // Neoverse N1, N2 and V1 + if (_cpu == CPU_ARM && ((_model == 0xd0c || _model2 == 0xd0c) + || (_model == 0xd49 || _model2 == 0xd49) + || (_model == 0xd40 || _model2 == 0xd40))) { if (FLAG_IS_DEFAULT(UseSIMDForMemoryOps)) { FLAG_SET_DEFAULT(UseSIMDForMemoryOps, true); } -- GitLab From c5c8c0644d9442846de15422285fffeb91c3e0a1 Mon Sep 17 00:00:00 2001 From: Vladimir Ivanov Date: Wed, 9 Feb 2022 13:56:23 +0000 Subject: [PATCH 448/564] 8279822: CI: Constant pool entries in error state are not supported Reviewed-by: kvn, thartmann --- src/hotspot/share/ci/bcEscapeAnalyzer.cpp | 6 +- src/hotspot/share/ci/ciConstant.hpp | 11 + src/hotspot/share/ci/ciEnv.cpp | 40 +-- src/hotspot/share/ci/ciStreams.cpp | 8 + src/hotspot/share/ci/ciStreams.hpp | 19 +- src/hotspot/share/ci/ciTypeFlow.cpp | 19 +- src/hotspot/share/oops/constantPool.cpp | 38 ++- src/hotspot/share/opto/parse2.cpp | 36 +-- src/hotspot/share/utilities/constantTag.hpp | 33 +- .../runtime/TestConstantsInError.java | 283 ++++++++++++++++++ 10 files changed, 403 insertions(+), 90 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/runtime/TestConstantsInError.java diff --git a/src/hotspot/share/ci/bcEscapeAnalyzer.cpp b/src/hotspot/share/ci/bcEscapeAnalyzer.cpp index a10a9d3d551..7fd8b5c04f3 100644 --- a/src/hotspot/share/ci/bcEscapeAnalyzer.cpp +++ b/src/hotspot/share/ci/bcEscapeAnalyzer.cpp @@ -416,11 +416,11 @@ void BCEscapeAnalyzer::iterate_one_block(ciBlock *blk, StateInfo &state, Growabl // Avoid calling get_constant() which will try to allocate // unloaded constant. We need only constant's type. int index = s.get_constant_pool_index(); - constantTag tag = s.get_constant_pool_tag(index); - if (tag.is_long() || tag.is_double()) { + BasicType con_bt = s.get_basic_type_for_constant_at(index); + if (con_bt == T_LONG || con_bt == T_DOUBLE) { // Only longs and doubles use 2 stack slots. state.lpush(); - } else if (tag.basic_type() == T_OBJECT) { + } else if (con_bt == T_OBJECT) { state.apush(unknown_obj); } else { state.spush(); diff --git a/src/hotspot/share/ci/ciConstant.hpp b/src/hotspot/share/ci/ciConstant.hpp index c9351771d17..25591699045 100644 --- a/src/hotspot/share/ci/ciConstant.hpp +++ b/src/hotspot/share/ci/ciConstant.hpp @@ -127,6 +127,17 @@ public: bool is_valid() const { return basic_type() != T_ILLEGAL; } + + bool is_loaded() const { + if (is_valid()) { + if (is_reference_type(basic_type())) { + return as_object()->is_loaded(); + } else { + return true; + } + } + return false; + } // Debugging output void print(); }; diff --git a/src/hotspot/share/ci/ciEnv.cpp b/src/hotspot/share/ci/ciEnv.cpp index 323d67c986f..bdbd86d9018 100644 --- a/src/hotspot/share/ci/ciEnv.cpp +++ b/src/hotspot/share/ci/ciEnv.cpp @@ -503,13 +503,6 @@ ciKlass* ciEnv::get_klass_by_name_impl(ciKlass* accessing_klass, domain = Handle(current, accessing_klass->protection_domain()); } - // setup up the proper type to return on OOM - ciKlass* fail_type; - if (sym->char_at(0) == JVM_SIGNATURE_ARRAY) { - fail_type = _unloaded_ciobjarrayklass; - } else { - fail_type = _unloaded_ciinstance_klass; - } Klass* found_klass; { ttyUnlocker ttyul; // release tty lock to avoid ordering problems @@ -591,7 +584,6 @@ ciKlass* ciEnv::get_klass_by_index_impl(const constantPoolHandle& cpool, int index, bool& is_accessible, ciInstanceKlass* accessor) { - EXCEPTION_CONTEXT; Klass* klass = NULL; Symbol* klass_name = NULL; @@ -599,7 +591,7 @@ ciKlass* ciEnv::get_klass_by_index_impl(const constantPoolHandle& cpool, klass_name = cpool->symbol_at(index); } else { // Check if it's resolved if it's not a symbol constant pool entry. - klass = ConstantPool::klass_at_if_loaded(cpool, index); + klass = ConstantPool::klass_at_if_loaded(cpool, index); // Try to look it up by name. if (klass == NULL) { klass_name = cpool->klass_name_at(index); @@ -666,7 +658,6 @@ ciConstant ciEnv::get_constant_by_index_impl(const constantPoolHandle& cpool, int pool_index, int cache_index, ciInstanceKlass* accessor) { bool ignore_will_link; - EXCEPTION_CONTEXT; int index = pool_index; if (cache_index >= 0) { assert(index < 0, "only one kind of index at a time"); @@ -677,12 +668,14 @@ ciConstant ciEnv::get_constant_by_index_impl(const constantPoolHandle& cpool, return ciConstant(T_OBJECT, get_object(NULL)); } BasicType bt = T_OBJECT; - if (cpool->tag_at(index).is_dynamic_constant()) + if (cpool->tag_at(index).is_dynamic_constant()) { bt = Signature::basic_type(cpool->uncached_signature_ref_at(index)); - if (is_reference_type(bt)) { - } else { + } + if (!is_reference_type(bt)) { // we have to unbox the primitive value - if (!is_java_primitive(bt)) return ciConstant(); + if (!is_java_primitive(bt)) { + return ciConstant(); + } jvalue value; BasicType bt2 = java_lang_boxing_object::get_value(obj, &value); assert(bt2 == bt, ""); @@ -717,6 +710,7 @@ ciConstant ciEnv::get_constant_by_index_impl(const constantPoolHandle& cpool, } else if (tag.is_double()) { return ciConstant((jdouble)cpool->double_at(index)); } else if (tag.is_string()) { + EXCEPTION_CONTEXT; oop string = NULL; assert(cache_index >= 0, "should have a cache index"); string = cpool->string_at(index, cache_index, THREAD); @@ -733,24 +727,18 @@ ciConstant ciEnv::get_constant_by_index_impl(const constantPoolHandle& cpool, return ciConstant(T_OBJECT, constant); } } else if (tag.is_unresolved_klass_in_error()) { - return ciConstant(); + return ciConstant(T_OBJECT, get_unloaded_klass_mirror(NULL)); } else if (tag.is_klass() || tag.is_unresolved_klass()) { - // 4881222: allow ldc to take a class type ciKlass* klass = get_klass_by_index_impl(cpool, index, ignore_will_link, accessor); - if (HAS_PENDING_EXCEPTION) { - CLEAR_PENDING_EXCEPTION; - record_out_of_memory_failure(); - return ciConstant(); - } assert (klass->is_instance_klass() || klass->is_array_klass(), "must be an instance or array klass "); return ciConstant(T_OBJECT, klass->java_mirror()); - } else if (tag.is_method_type()) { + } else if (tag.is_method_type() || tag.is_method_type_in_error()) { // must execute Java code to link this CP entry into cache[i].f1 ciSymbol* signature = get_symbol(cpool->method_type_signature_at(index)); ciObject* ciobj = get_unloaded_method_type_constant(signature); return ciConstant(T_OBJECT, ciobj); - } else if (tag.is_method_handle()) { + } else if (tag.is_method_handle() || tag.is_method_handle_in_error()) { // must execute Java code to link this CP entry into cache[i].f1 int ref_kind = cpool->method_handle_ref_kind_at(index); int callee_index = cpool->method_handle_klass_index_at(index); @@ -759,10 +747,10 @@ ciConstant ciEnv::get_constant_by_index_impl(const constantPoolHandle& cpool, ciSymbol* signature = get_symbol(cpool->method_handle_signature_ref_at(index)); ciObject* ciobj = get_unloaded_method_handle_constant(callee, name, signature, ref_kind); return ciConstant(T_OBJECT, ciobj); - } else if (tag.is_dynamic_constant()) { - return ciConstant(); + } else if (tag.is_dynamic_constant() || tag.is_dynamic_constant_in_error()) { + return ciConstant(); // not supported } else { - ShouldNotReachHere(); + assert(false, "unknown tag: %d (%s)", tag.value(), tag.internal_name()); return ciConstant(); } } diff --git a/src/hotspot/share/ci/ciStreams.cpp b/src/hotspot/share/ci/ciStreams.cpp index a1e6c5bffe8..46f52f19412 100644 --- a/src/hotspot/share/ci/ciStreams.cpp +++ b/src/hotspot/share/ci/ciStreams.cpp @@ -251,6 +251,14 @@ constantTag ciBytecodeStream::get_constant_pool_tag(int index) const { return _method->get_Method()->constants()->constant_tag_at(index); } +// ------------------------------------------------------------------ +// ciBytecodeStream::get_basic_type_for_constant_at +// +BasicType ciBytecodeStream::get_basic_type_for_constant_at(int index) const { + VM_ENTRY_MARK; + return _method->get_Method()->constants()->basic_type_for_constant_at(index); +} + // ------------------------------------------------------------------ // ciBytecodeStream::get_field_index // diff --git a/src/hotspot/share/ci/ciStreams.hpp b/src/hotspot/share/ci/ciStreams.hpp index 8f46510a0d2..e46b2e2bfa2 100644 --- a/src/hotspot/share/ci/ciStreams.hpp +++ b/src/hotspot/share/ci/ciStreams.hpp @@ -140,7 +140,7 @@ public: bool is_wide() const { return ( _pc == _was_wide ); } - // Does this instruction contain an index which refes into the CP cache? + // Does this instruction contain an index which refers into the CP cache? bool has_cache_index() const { return Bytecodes::uses_cp_cache(cur_bc_raw()); } int get_index_u1() const { @@ -226,8 +226,9 @@ public: // constant. Do not attempt to resolve it, since that would require // execution of Java code. If it is not resolved, return an unloaded // object (ciConstant.as_object()->is_loaded() == false). - ciConstant get_constant(); + ciConstant get_constant(); constantTag get_constant_pool_tag(int index) const; + BasicType get_basic_type_for_constant_at(int index) const; // True if the klass-using bytecode points to an unresolved klass bool is_unresolved_klass() const { @@ -235,9 +236,17 @@ public: return tag.is_unresolved_klass(); } - bool is_unresolved_klass_in_error() const { - constantTag tag = get_constant_pool_tag(get_klass_index()); - return tag.is_unresolved_klass_in_error(); + bool is_in_error() const { + assert(cur_bc() == Bytecodes::_ldc || + cur_bc() == Bytecodes::_ldc_w || + cur_bc() == Bytecodes::_ldc2_w, "not supported: %s", Bytecodes::name(cur_bc())); + + int index = get_constant_pool_index(); + constantTag tag = get_constant_pool_tag(index); + return tag.is_unresolved_klass_in_error() || + tag.is_method_handle_in_error() || + tag.is_method_type_in_error() || + tag.is_dynamic_constant_in_error(); } // If this bytecode is one of get_field, get_static, put_field, diff --git a/src/hotspot/share/ci/ciTypeFlow.cpp b/src/hotspot/share/ci/ciTypeFlow.cpp index fc8553aac48..2d7c60356d1 100644 --- a/src/hotspot/share/ci/ciTypeFlow.cpp +++ b/src/hotspot/share/ci/ciTypeFlow.cpp @@ -720,6 +720,11 @@ void ciTypeFlow::StateVector::do_jsr(ciBytecodeStream* str) { // ------------------------------------------------------------------ // ciTypeFlow::StateVector::do_ldc void ciTypeFlow::StateVector::do_ldc(ciBytecodeStream* str) { + if (str->is_in_error()) { + trap(str, NULL, Deoptimization::make_trap_request(Deoptimization::Reason_unhandled, + Deoptimization::Action_none)); + return; + } ciConstant con = str->get_constant(); if (con.is_valid()) { BasicType basic_type = con.basic_type(); @@ -735,14 +740,10 @@ void ciTypeFlow::StateVector::do_ldc(ciBytecodeStream* str) { push_translate(ciType::make(basic_type)); } } else { - if (str->is_unresolved_klass_in_error()) { - trap(str, NULL, Deoptimization::make_trap_request(Deoptimization::Reason_unhandled, - Deoptimization::Action_none)); - } else { - // OutOfMemoryError in the CI while loading constant - push_null(); - outer()->record_failure("ldc did not link"); - } + // OutOfMemoryError in the CI while loading constant. + // Unresolved condy also lands here (not yet supported). + push_null(); + outer()->record_failure("ldc did not link"); } } @@ -2173,7 +2174,7 @@ bool ciTypeFlow::can_trap(ciBytecodeStream& str) { case Bytecodes::_ldc: case Bytecodes::_ldc_w: case Bytecodes::_ldc2_w: - return str.is_unresolved_klass_in_error(); + return str.is_in_error(); case Bytecodes::_aload_0: // These bytecodes can trap for rewriting. We need to assume that diff --git a/src/hotspot/share/oops/constantPool.cpp b/src/hotspot/share/oops/constantPool.cpp index 1ff1abbb57d..d12ccd64cb6 100644 --- a/src/hotspot/share/oops/constantPool.cpp +++ b/src/hotspot/share/oops/constantPool.cpp @@ -885,11 +885,9 @@ void ConstantPool::save_and_throw_exception(const constantPoolHandle& this_cp, i constantTag ConstantPool::constant_tag_at(int which) { constantTag tag = tag_at(which); - if (tag.is_dynamic_constant() || - tag.is_dynamic_constant_in_error()) { + if (tag.is_dynamic_constant()) { BasicType bt = basic_type_for_constant_at(which); - // dynamic constant could return an array, treat as object - return constantTag::ofBasicType(is_reference_type(bt) ? T_OBJECT : bt); + return constantTag(constantTag::type2tag(bt)); } return tag; } @@ -976,7 +974,6 @@ oop ConstantPool::resolve_constant_at_impl(const constantPoolHandle& this_cp, switch (tag.value()) { case JVM_CONSTANT_UnresolvedClass: - case JVM_CONSTANT_UnresolvedClassInError: case JVM_CONSTANT_Class: { assert(cache_index == _no_index_sentinel, "should not have been set"); @@ -1044,14 +1041,6 @@ oop ConstantPool::resolve_constant_at_impl(const constantPoolHandle& this_cp, result_oop = string_at_impl(this_cp, index, cache_index, CHECK_NULL); break; - case JVM_CONSTANT_DynamicInError: - case JVM_CONSTANT_MethodHandleInError: - case JVM_CONSTANT_MethodTypeInError: - { - throw_resolution_error(this_cp, index, CHECK_NULL); - break; - } - case JVM_CONSTANT_MethodHandle: { int ref_kind = this_cp->method_handle_ref_kind_at(index); @@ -1065,11 +1054,14 @@ oop ConstantPool::resolve_constant_at_impl(const constantPoolHandle& this_cp, callee_index, name->as_C_string(), signature->as_C_string()); } - Klass* callee = klass_at_impl(this_cp, callee_index, CHECK_NULL); + Klass* callee = klass_at_impl(this_cp, callee_index, THREAD); + if (HAS_PENDING_EXCEPTION) { + save_and_throw_exception(this_cp, index, tag, CHECK_NULL); + } // Check constant pool method consistency if ((callee->is_interface() && m_tag.is_method()) || - ((!callee->is_interface() && m_tag.is_interface_method()))) { + (!callee->is_interface() && m_tag.is_interface_method())) { ResourceMark rm(THREAD); stringStream ss; ss.print("Inconsistent constant pool data in classfile for class %s. " @@ -1081,17 +1073,18 @@ oop ConstantPool::resolve_constant_at_impl(const constantPoolHandle& this_cp, index, callee->is_interface() ? "CONSTANT_MethodRef" : "CONSTANT_InterfaceMethodRef", callee->is_interface() ? "CONSTANT_InterfaceMethodRef" : "CONSTANT_MethodRef"); - THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), ss.as_string()); + Exceptions::fthrow(THREAD_AND_LOCATION, vmSymbols::java_lang_IncompatibleClassChangeError(), "%s", ss.as_string()); + save_and_throw_exception(this_cp, index, tag, CHECK_NULL); } Klass* klass = this_cp->pool_holder(); Handle value = SystemDictionary::link_method_handle_constant(klass, ref_kind, callee, name, signature, THREAD); - result_oop = value(); if (HAS_PENDING_EXCEPTION) { save_and_throw_exception(this_cp, index, tag, CHECK_NULL); } + result_oop = value(); break; } @@ -1136,10 +1129,15 @@ oop ConstantPool::resolve_constant_at_impl(const constantPoolHandle& this_cp, result_oop = java_lang_boxing_object::create(T_DOUBLE, &prim_value, CHECK_NULL); break; + case JVM_CONSTANT_UnresolvedClassInError: + case JVM_CONSTANT_DynamicInError: + case JVM_CONSTANT_MethodHandleInError: + case JVM_CONSTANT_MethodTypeInError: + throw_resolution_error(this_cp, index, CHECK_NULL); + break; + default: - DEBUG_ONLY( tty->print_cr("*** %p: tag at CP[%d/%d] = %d", - this_cp(), index, cache_index, tag.value())); - assert(false, "unexpected constant tag"); + fatal("unexpected constant tag at CP %p[%d/%d] = %d", this_cp(), index, cache_index, tag.value()); break; } diff --git a/src/hotspot/share/opto/parse2.cpp b/src/hotspot/share/opto/parse2.cpp index 7ad08841476..14cca6cac26 100644 --- a/src/hotspot/share/opto/parse2.cpp +++ b/src/hotspot/share/opto/parse2.cpp @@ -1865,33 +1865,35 @@ void Parse::do_one_bytecode() { case Bytecodes::_bipush: push(intcon(iter().get_constant_u1())); break; case Bytecodes::_sipush: push(intcon(iter().get_constant_u2())); break; case Bytecodes::_aconst_null: push(null()); break; + case Bytecodes::_ldc: case Bytecodes::_ldc_w: - case Bytecodes::_ldc2_w: - // If the constant is unresolved, run this BC once in the interpreter. - { - ciConstant constant = iter().get_constant(); - if (!constant.is_valid() || - (constant.basic_type() == T_OBJECT && - !constant.as_object()->is_loaded())) { - int index = iter().get_constant_pool_index(); - constantTag tag = iter().get_constant_pool_tag(index); - uncommon_trap(Deoptimization::make_trap_request - (Deoptimization::Reason_unloaded, - Deoptimization::Action_reinterpret, - index), - NULL, tag.internal_name()); - break; - } + case Bytecodes::_ldc2_w: { + ciConstant constant = iter().get_constant(); + if (constant.is_loaded()) { assert(constant.basic_type() != T_OBJECT || constant.as_object()->is_instance(), "must be java_mirror of klass"); const Type* con_type = Type::make_from_constant(constant); if (con_type != NULL) { push_node(con_type->basic_type(), makecon(con_type)); } - } + } else { + // If the constant is unresolved or in error state, run this BC in the interpreter. + if (iter().is_in_error()) { + uncommon_trap(Deoptimization::make_trap_request(Deoptimization::Reason_unhandled, + Deoptimization::Action_none), + NULL, "constant in error state", true /* must_throw */); + } else { + int index = iter().get_constant_pool_index(); + uncommon_trap(Deoptimization::make_trap_request(Deoptimization::Reason_unloaded, + Deoptimization::Action_reinterpret, + index), + NULL, "unresolved constant", false /* must_throw */); + } + } break; + } case Bytecodes::_aload_0: push( local(0) ); diff --git a/src/hotspot/share/utilities/constantTag.hpp b/src/hotspot/share/utilities/constantTag.hpp index 4926eafa81c..d826fc0acc0 100644 --- a/src/hotspot/share/utilities/constantTag.hpp +++ b/src/hotspot/share/utilities/constantTag.hpp @@ -86,6 +86,13 @@ class constantTag { return _tag == JVM_CONSTANT_DynamicInError; } + bool is_in_error() const { + return is_unresolved_klass_in_error() || + is_method_handle_in_error() || + is_method_type_in_error() || + is_dynamic_constant_in_error(); + } + bool is_klass_index() const { return _tag == JVM_CONSTANT_ClassIndex; } bool is_string_index() const { return _tag == JVM_CONSTANT_StringIndex; } @@ -121,18 +128,24 @@ class constantTag { _tag = tag; } - static constantTag ofBasicType(BasicType bt) { - if (is_subword_type(bt)) bt = T_INT; + static jbyte type2tag(BasicType bt) { + if (is_subword_type(bt)) { + bt = T_INT; + } + if (bt == T_ARRAY) { + bt = T_OBJECT; + } switch (bt) { - case T_OBJECT: return constantTag(JVM_CONSTANT_String); - case T_INT: return constantTag(JVM_CONSTANT_Integer); - case T_LONG: return constantTag(JVM_CONSTANT_Long); - case T_FLOAT: return constantTag(JVM_CONSTANT_Float); - case T_DOUBLE: return constantTag(JVM_CONSTANT_Double); - default: break; + case T_INT: return JVM_CONSTANT_Integer; + case T_LONG: return JVM_CONSTANT_Long; + case T_FLOAT: return JVM_CONSTANT_Float; + case T_DOUBLE: return JVM_CONSTANT_Double; + case T_OBJECT: return JVM_CONSTANT_String; + + default: + assert(false, "not supported: %s", type2name(bt)); + return JVM_CONSTANT_Invalid; } - assert(false, "bad basic type for tag"); - return constantTag(); } jbyte value() const { return _tag; } diff --git a/test/hotspot/jtreg/compiler/runtime/TestConstantsInError.java b/test/hotspot/jtreg/compiler/runtime/TestConstantsInError.java new file mode 100644 index 00000000000..be5225bee4c --- /dev/null +++ b/test/hotspot/jtreg/compiler/runtime/TestConstantsInError.java @@ -0,0 +1,283 @@ +/* + * Copyright (c) 2022, 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 8279822 + * @requires vm.flagless + * @library /test/lib + * @modules java.base/jdk.internal.org.objectweb.asm + * + * @run main compiler.runtime.TestConstantsInError + */ +package compiler.runtime; + +import jdk.internal.org.objectweb.asm.*; +import jdk.test.lib.Platform; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandleProxies; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.ArrayList; +import java.util.List; + +import static jdk.internal.org.objectweb.asm.ClassWriter.*; +import static jdk.internal.org.objectweb.asm.Opcodes.*; + +interface OutputProcessor { + default void process(OutputAnalyzer output, boolean isC1) {} +} + +public abstract class TestConstantsInError implements OutputProcessor { + static final String TEST_PREFIX = class2desc(TestConstantsInError.class) + "$Test"; + + public interface Test extends Runnable {} + + + interface Generator { + void generate(MethodVisitor mv); + } + + static String class2desc(Class cls) { + return cls.getName().replace('.', '/'); + } + + public static final String PATH = System.getProperty("test.classes", ".") + java.io.File.separator; + + static byte[] generateClassFile(String suffix, Generator g) throws IOException { + var cw = new ClassWriter(COMPUTE_MAXS | COMPUTE_FRAMES); + String name = TEST_PREFIX + "_" + suffix; + cw.visit(V19, ACC_PUBLIC | ACC_SUPER, name, null, "java/lang/Object", null); + + { + var mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "test", "()V", null, null); + mv.visitCode(); + g.generate(mv); + mv.visitInsn(RETURN); + mv.visitMaxs(0, 0); + } + byte[] classFile = cw.toByteArray(); + + try (FileOutputStream fos = new FileOutputStream(PATH + name + ".class")) { + fos.write(classFile); + } + + return classFile; + } + + static Test generate(String suffix, Class expectedError, Generator g) { + try { + byte[] classFile = generateClassFile(suffix, g); + MethodHandles.Lookup testLookup = MethodHandles.lookup().defineHiddenClass(classFile, true); + MethodHandle testMH = testLookup.findStatic(testLookup.lookupClass(), "test", MethodType.methodType(void.class)); + + testMH = MethodHandles.filterReturnValue(testMH, + MethodHandles.insertArguments( + MethodHandles.throwException(void.class, AssertionError.class), + 0, new AssertionError("no exception thrown"))); + + // Install empty handler for linkage exceptions. + testMH = MethodHandles.catchException(testMH, expectedError, + MethodHandles.empty(MethodType.methodType(void.class, expectedError))); + + return MethodHandleProxies.asInterfaceInstance(Test.class, testMH); + } catch (Throwable e) { + throw new InternalError(e); + } + } + + static void run(String name, Class expectedError, Generator g) { + Test test = generate(name, expectedError, g); + for (int i = 0; i < 1000; i++) { + test.run(); + } + } + + static class TestConstantClass extends TestConstantsInError { + public static void main(String[] args) { + run("C1", NoClassDefFoundError.class, mv -> mv.visitLdcInsn(Type.getType("LUnknownClass;"))); // non-existent class + run("C2", IllegalAccessError.class, mv -> mv.visitLdcInsn(Type.getType("Ljava/lang/invoke/LambdaForm;"))); // inaccessible + + // class loader constraints? + } + + public void process(OutputAnalyzer results, boolean isC1) { + results.shouldMatch("Test_C1/.*::test \\(3 bytes\\)$") + .shouldMatch("Test_C2/.*::test \\(3 bytes\\)$"); + + if (isC1 && Platform.isAArch64()) { // no code patching + results.shouldMatch("Test_C1/.*::test \\(3 bytes\\) made not entrant") + .shouldMatch("Test_C2/.*::test \\(3 bytes\\) made not entrant"); + } else { + results.shouldNotContain("made not entrant"); + } + } + + public void processC2(OutputAnalyzer results) { + results.shouldNotContain("made not entrant"); + } + } + + static class TestConstantMethodHandle extends TestConstantsInError { + public static void main(String[] args) { + // Non-existent holder class + run("MH1", NoClassDefFoundError.class, + mv -> mv.visitLdcInsn(new Handle(H_INVOKESTATIC, "UnknownClass", "ignored", "()V", false))); + + // Inaccessible holder class + run("MH2", IllegalAccessError.class, + mv -> mv.visitLdcInsn(new Handle(H_INVOKESTATIC, "java/lang/invoke/LambdaForm", "ignored", "()V", false))); + + // Method vs InterfaceMethod mismatch + run("MH3", IncompatibleClassChangeError.class, + mv -> mv.visitLdcInsn(new Handle(H_INVOKESTATIC, "java/lang/Object", "ignored", "()V", true))); + + // Non-existent method + run("MH4", NoSuchMethodError.class, + mv -> mv.visitLdcInsn(new Handle(H_INVOKESTATIC, "java/lang/Object", "cast", "()V", false))); + } + + public void process(OutputAnalyzer results, boolean isC1) { + results.shouldMatch("Test_MH1/.*::test \\(3 bytes\\)$") + .shouldMatch("Test_MH2/.*::test \\(3 bytes\\)$") + .shouldMatch("Test_MH3/.*::test \\(3 bytes\\)$") + .shouldMatch("Test_MH4/.*::test \\(3 bytes\\)$"); + + if (isC1 && Platform.isAArch64()) { // no code patching + results.shouldMatch("Test_MH1/.*::test \\(3 bytes\\) made not entrant") + .shouldMatch("Test_MH2/.*::test \\(3 bytes\\) made not entrant") + .shouldMatch("Test_MH3/.*::test \\(3 bytes\\) made not entrant") + .shouldMatch("Test_MH4/.*::test \\(3 bytes\\) made not entrant"); + } else { + results.shouldNotContain("made not entrant"); + } + } + } + + static class TestConstantMethodType extends TestConstantsInError { + public static void main(String[] args) { + run("MT1", NoClassDefFoundError.class, + mv -> mv.visitLdcInsn(Type.getMethodType("(LUnknownClass;)V"))); + run("MT2", NoClassDefFoundError.class, + mv -> mv.visitLdcInsn(Type.getMethodType("()LUnknownClass;"))); + } + + public void process(OutputAnalyzer results, boolean isC1) { + results.shouldMatch("Test_MT1/.*::test \\(3 bytes\\)$") + .shouldMatch("Test_MT2/.*::test \\(3 bytes\\)$"); + + if (isC1 && Platform.isAArch64()) { // no code patching + results.shouldMatch("Test_MT1/.*::test \\(3 bytes\\) made not entrant") + .shouldMatch("Test_MT2/.*::test \\(3 bytes\\) made not entrant"); + } else { + results.shouldNotContain("made not entrant"); + } + } + } + + static class TestConstantDynamic extends TestConstantsInError { + static int bsm1() throws Exception { + throw new AssertionError("should not be invoked"); + } + + static int bsm2(MethodHandles.Lookup lookup, String name, Class c) throws Exception { + throw new Exception("expected"); + } + + static final Handle BSM1 = new Handle(H_INVOKESTATIC, class2desc(TestConstantDynamic.class), "bsm1", "()I", false); + static final Handle BSM2 = new Handle(H_INVOKESTATIC, class2desc(TestConstantDynamic.class), "bsm2", + "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;)I", + false); + + public static void main(String[] args) { + run("CD1", NoClassDefFoundError.class, + mv -> { + Handle bsm = new Handle(H_INVOKESTATIC, "UnknownClass", "unknown", "()LUnknownClass;", false); + mv.visitLdcInsn(new ConstantDynamic("tmp", "LUnknownClass;", bsm)); + }); + run("CD2", NoSuchMethodError.class, + mv -> { + Handle bsm = new Handle(H_INVOKESTATIC, class2desc(TestConstantDynamic.class), "unknown", "()I", false); + mv.visitLdcInsn(new ConstantDynamic("tmp", "LUnknownClass;", bsm)); + }); + run("CD3", BootstrapMethodError.class, mv -> mv.visitLdcInsn(new ConstantDynamic("tmp", "I", BSM1))); + run("CD4", BootstrapMethodError.class, mv -> mv.visitLdcInsn(new ConstantDynamic("tmp", "I", BSM2))); + } + + public void process(OutputAnalyzer results, boolean isC1) { + if (isC1) { + results.shouldMatch("Test_CD1.*::test \\(3 bytes\\) COMPILE SKIPPED: could not resolve a constant") + .shouldMatch("Test_CD2.*::test \\(3 bytes\\) COMPILE SKIPPED: could not resolve a constant") + .shouldMatch("Test_CD3.*::test \\(3 bytes\\) COMPILE SKIPPED: could not resolve a constant") + .shouldMatch("Test_CD4.*::test \\(3 bytes\\) COMPILE SKIPPED: could not resolve a constant"); + } else { + results.shouldMatch("Test_CD1.*::test \\(3 bytes\\)$") + .shouldMatch("Test_CD2.*::test \\(3 bytes\\)$") + .shouldMatch("Test_CD3.*::test \\(3 bytes\\)$") + .shouldMatch("Test_CD4.*::test \\(3 bytes\\)$"); + } + } + } + + static void run(TestConstantsInError test) throws Exception { + List commonArgs = List.of( + "--add-exports", "java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED", + "-Xbatch", "-XX:CompileThreshold=100", + "-XX:CompileCommand=quiet", "-XX:CompileCommand=compileonly,*::test", + "-XX:+PrintCompilation", + "-XX:CompileCommand=print,*::test", + "-Dtest.classes=" + System.getProperty("test.classes", "."), + "-XX:+IgnoreUnrecognizedVMOptions", + test.getClass().getName()); + + ArrayList c1Args = new ArrayList<>(); + c1Args.addAll(List.of("-XX:+TieredCompilation", "-XX:TieredStopAtLevel=1", "-XX:+TracePatching")); + c1Args.addAll(commonArgs); + + OutputAnalyzer outputC1 = ProcessTools.executeTestJvm(c1Args) + .shouldHaveExitValue(0); + + test.process(outputC1, true); + + ArrayList c2Args = new ArrayList<>(); + c2Args.add("-XX:-TieredCompilation"); + c2Args.addAll(commonArgs); + + OutputAnalyzer outputC2 = ProcessTools.executeTestJvm(c2Args) + .shouldHaveExitValue(0); + + test.process(outputC2, false); + } + + public static void main(String[] args) throws Exception { + run(new TestConstantClass()); + run(new TestConstantMethodType()); + run(new TestConstantMethodHandle()); + run(new TestConstantDynamic()); + } +} -- GitLab From 178b962e01cc6c150442bf41dc6bd199caff0042 Mon Sep 17 00:00:00 2001 From: Hai-May Chao Date: Wed, 9 Feb 2022 16:53:48 +0000 Subject: [PATCH 449/564] 8265765: DomainKeyStore may stop enumerating aliases if a constituting KeyStore is empty Reviewed-by: weijun --- .../sun/security/provider/DomainKeyStore.java | 16 ++- .../KeyStore/DksWithEmptyKeystore.java | 125 ++++++++++++++++++ 2 files changed, 134 insertions(+), 7 deletions(-) create mode 100644 test/jdk/sun/security/provider/KeyStore/DksWithEmptyKeystore.java diff --git a/src/java.base/share/classes/sun/security/provider/DomainKeyStore.java b/src/java.base/share/classes/sun/security/provider/DomainKeyStore.java index be0e91a55a3..588f2ed78e6 100644 --- a/src/java.base/share/classes/sun/security/provider/DomainKeyStore.java +++ b/src/java.base/share/classes/sun/security/provider/DomainKeyStore.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2022, 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 @@ -419,20 +419,22 @@ abstract class DomainKeyStore extends KeyStoreSpi { if (aliases.hasMoreElements()) { return true; } else { - if (iterator.hasNext()) { + while (iterator.hasNext()) { keystoresEntry = iterator.next(); prefix = keystoresEntry.getKey() + - entryNameSeparator; + entryNameSeparator; aliases = keystoresEntry.getValue().aliases(); - } else { - return false; + if (aliases.hasMoreElements()) { + return true; + } else { + continue; + } } + return false; } } catch (KeyStoreException e) { return false; } - - return aliases.hasMoreElements(); } public String nextElement() { diff --git a/test/jdk/sun/security/provider/KeyStore/DksWithEmptyKeystore.java b/test/jdk/sun/security/provider/KeyStore/DksWithEmptyKeystore.java new file mode 100644 index 00000000000..050c470a3d0 --- /dev/null +++ b/test/jdk/sun/security/provider/KeyStore/DksWithEmptyKeystore.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2022, 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 8265765 + * @summary Test DomainKeyStore with a collection of keystores that has an empty one in between + * based on the test in the bug report + */ + +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.security.DomainLoadStoreParameter; +import java.security.KeyStore; +import java.util.Enumeration; +import java.util.LinkedHashMap; +import java.util.Map; +import javax.crypto.KeyGenerator; + +public class DksWithEmptyKeystore { + private static void write(Path p, KeyStore keystore) throws Exception { + try (OutputStream outputStream = Files.newOutputStream(p)) { + keystore.store(outputStream, new char[] { 'x' }); + } + } + + public static void main(String[] args) throws Exception { + KeyGenerator kg = KeyGenerator.getInstance("AES"); + kg.init(256); + + // Create a keystore with one key + KeyStore nonEmptyKeystore = KeyStore.getInstance("PKCS12"); + nonEmptyKeystore.load(null, null); + + Path nonEmptyPath = Path.of("non_empty.p12"); + nonEmptyKeystore.setKeyEntry("aeskey", kg.generateKey(), new char[] { 'a' }, null); + write(nonEmptyPath, nonEmptyKeystore); + + // Create an empty keystore + KeyStore emptyKeystore = KeyStore.getInstance("PKCS12"); + emptyKeystore.load(null, null); + + Path emptyPath = Path.of("empty.p12"); + write(emptyPath, emptyKeystore); + + // Create a domain keystore with two non-empty keystores + Path dksWithTwoPartsPath = Path.of("two-parts.dks"); + var twoPartsConfiguration = """ + domain Combo { + keystore a keystoreURI="%s"; + keystore b keystoreURI="%s"; + }; + """; + Files.writeString(dksWithTwoPartsPath, String.format(twoPartsConfiguration, + nonEmptyPath.toUri(), nonEmptyPath.toUri())); + Map protectionParameters = new LinkedHashMap<>(); + + KeyStore dksKeystore = KeyStore.getInstance("DKS"); + dksKeystore.load(new DomainLoadStoreParameter(dksWithTwoPartsPath.toUri(), protectionParameters)); + System.out.printf("%s size: %d%n", dksWithTwoPartsPath, dksKeystore.size()); + + int index = 0; + for (Enumeration enumeration = dksKeystore.aliases(); enumeration.hasMoreElements(); ) { + System.out.printf("%d: %s%n", index, enumeration.nextElement()); + index++; + } + + System.out.printf("enumerated aliases from %s: %d%n", dksWithTwoPartsPath, index); + if (index != dksKeystore.size()) { + throw new Exception("Failed to get the number of aliases in the domain keystore " + + "that has two keystores."); + } + + // Create a domain keystore with two non-empty keystores and an empty one in between + Path dksWithThreePartsPath = Path.of("three-parts.dks"); + var threePartsConfiguration = """ + domain Combo { + keystore a keystoreURI="%s"; + keystore b keystoreURI="%s"; + keystore c keystoreURI="%s"; + }; + """; + Files.writeString(dksWithThreePartsPath, String.format(threePartsConfiguration, + nonEmptyPath.toUri(), emptyPath.toUri(), nonEmptyPath.toUri())); + + KeyStore dksKeystore1 = KeyStore.getInstance("DKS"); + dksKeystore1.load(new DomainLoadStoreParameter(dksWithThreePartsPath.toUri(), protectionParameters)); + System.out.printf("%s size: %d%n", dksWithThreePartsPath, dksKeystore1.size()); + + index = 0; + for (Enumeration enumeration = dksKeystore1.aliases(); enumeration.hasMoreElements(); ) { + System.out.printf("%d: %s%n", index, enumeration.nextElement()); + index++; + } + + System.out.printf("enumerated aliases from %s: %d%n", dksWithThreePartsPath, index); + if (index != dksKeystore1.size()) { + throw new Exception("Failed to get the number of aliases in the domain keystore " + + "that has three keystores with an empty one in between."); + } else { + System.out.printf("Test completed successfully"); + } + } +} -- GitLab From fd8a3dcc52dc5d6b62edd83eacef5934f6294e80 Mon Sep 17 00:00:00 2001 From: Alexey Ivanov Date: Wed, 9 Feb 2022 19:12:20 +0000 Subject: [PATCH 450/564] 8280820: Clean up bug8033699 and bug8075609.java tests: regtesthelpers aren't used Reviewed-by: prr --- .../JRadioButton/8033699/bug8033699.java | 63 +++++++++---------- .../JRadioButton/8075609/bug8075609.java | 60 +++++++++--------- 2 files changed, 62 insertions(+), 61 deletions(-) diff --git a/test/jdk/javax/swing/JRadioButton/8033699/bug8033699.java b/test/jdk/javax/swing/JRadioButton/8033699/bug8033699.java index 06622f71819..9365e6ba45b 100644 --- a/test/jdk/javax/swing/JRadioButton/8033699/bug8033699.java +++ b/test/jdk/javax/swing/JRadioButton/8033699/bug8033699.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,11 +21,9 @@ * questions. */ - /* +/* * @test * @key headful - * @library ../../regtesthelpers - * @build Util * @bug 8033699 8154043 8167160 8208640 8226892 * @summary Incorrect radio button behavior when pressing tab key * @run main bug8033699 @@ -34,8 +32,7 @@ import java.awt.KeyboardFocusManager; import java.awt.Robot; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; -import java.util.logging.Level; -import java.util.logging.Logger; + import javax.swing.BorderFactory; import javax.swing.BoxLayout; import javax.swing.ButtonGroup; @@ -45,7 +42,6 @@ import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.SwingUtilities; import javax.swing.UIManager; -import javax.swing.UnsupportedLookAndFeelException; public class bug8033699 { @@ -59,7 +55,7 @@ public class bug8033699 { private static JRadioButton radioBtn3; private static JRadioButton radioBtnSingle; - public static void main(String args[]) throws Throwable { + public static void main(String[] args) throws Throwable { SwingUtilities.invokeAndWait(() -> { changeLAF(); createAndShowGUI(); @@ -67,6 +63,7 @@ public class bug8033699 { robot = new Robot(); Thread.sleep(100); + robot.waitForIdle(); robot.setAutoDelay(100); @@ -76,7 +73,7 @@ public class bug8033699 { // tab key test non-grouped radio button runTest2(); - // shift tab key test grouped and non grouped radio button + // shift tab key test grouped and non-grouped radio button runTest3(); // left/up key test in grouped radio button @@ -152,16 +149,16 @@ public class bug8033699 { mainFrame.setLayout(new BoxLayout(mainFrame.getContentPane(), BoxLayout.Y_AXIS)); mainFrame.setSize(300, 300); - mainFrame.setLocation(200, 200); + mainFrame.setLocationRelativeTo(null); mainFrame.setVisible(true); mainFrame.toFront(); } // Radio button Group as a single component when traversing through tab key private static void runTest1() throws Exception { - hitKey(robot, KeyEvent.VK_TAB); - hitKey(robot, KeyEvent.VK_TAB); - hitKey(robot, KeyEvent.VK_TAB); + hitKey(KeyEvent.VK_TAB); + hitKey(KeyEvent.VK_TAB); + hitKey(KeyEvent.VK_TAB); SwingUtilities.invokeAndWait(() -> { if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() != radioBtnSingle) { @@ -173,7 +170,7 @@ public class bug8033699 { // Non-Grouped Radio button as a single component when traversing through tab key private static void runTest2() throws Exception { - hitKey(robot, KeyEvent.VK_TAB); + hitKey(KeyEvent.VK_TAB); SwingUtilities.invokeAndWait(() -> { if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() != btnEnd) { System.out.println("Non Grouped Radio Button Go To Next Component through Tab Key failed"); @@ -184,9 +181,9 @@ public class bug8033699 { // Non-Grouped Radio button and Group Radio button as a single component when traversing through shift-tab key private static void runTest3() throws Exception { - hitKey(robot, KeyEvent.VK_SHIFT, KeyEvent.VK_TAB); - hitKey(robot, KeyEvent.VK_SHIFT, KeyEvent.VK_TAB); - hitKey(robot, KeyEvent.VK_SHIFT, KeyEvent.VK_TAB); + hitKey(KeyEvent.VK_SHIFT, KeyEvent.VK_TAB); + hitKey(KeyEvent.VK_SHIFT, KeyEvent.VK_TAB); + hitKey(KeyEvent.VK_SHIFT, KeyEvent.VK_TAB); SwingUtilities.invokeAndWait(() -> { if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() != radioBtn1) { System.out.println("Radio button Group/Non Grouped Radio Button SHIFT-Tab Key Test failed"); @@ -197,8 +194,8 @@ public class bug8033699 { // Using arrow key to move focus in radio button group private static void runTest4() throws Exception { - hitKey(robot, KeyEvent.VK_DOWN); - hitKey(robot, KeyEvent.VK_RIGHT); + hitKey(KeyEvent.VK_DOWN); + hitKey(KeyEvent.VK_RIGHT); SwingUtilities.invokeAndWait(() -> { if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() != radioBtn3) { System.out.println("Radio button Group UP/LEFT Arrow Key Move Focus Failed"); @@ -208,8 +205,8 @@ public class bug8033699 { } private static void runTest5() throws Exception { - hitKey(robot, KeyEvent.VK_UP); - hitKey(robot, KeyEvent.VK_LEFT); + hitKey(KeyEvent.VK_UP); + hitKey(KeyEvent.VK_LEFT); SwingUtilities.invokeAndWait(() -> { if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() != radioBtn1) { System.out.println("Radio button Group Left/Up Arrow Key Move Focus Failed"); @@ -219,8 +216,8 @@ public class bug8033699 { } private static void runTest6() throws Exception { - hitKey(robot, KeyEvent.VK_UP); - hitKey(robot, KeyEvent.VK_UP); + hitKey(KeyEvent.VK_UP); + hitKey(KeyEvent.VK_UP); SwingUtilities.invokeAndWait(() -> { if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() != radioBtn2) { System.out.println("Radio button Group Circle Back To First Button Test"); @@ -230,7 +227,7 @@ public class bug8033699 { } private static void runTest7() throws Exception { - hitKey(robot, KeyEvent.VK_TAB); + hitKey(KeyEvent.VK_TAB); SwingUtilities.invokeAndWait(() -> { if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() != btnMiddle) { System.out.println("Separate Component added in button group layout"); @@ -240,7 +237,7 @@ public class bug8033699 { } private static void runTest8() throws Exception { - hitKey(robot, KeyEvent.VK_TAB); + hitKey(KeyEvent.VK_TAB); SwingUtilities.invokeAndWait(() -> { if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() != radioBtnSingle) { System.out.println("Separate Component added in button group layout"); @@ -249,9 +246,9 @@ public class bug8033699 { }); } - private static Boolean actRB1 = false; - private static Boolean actRB2 = false; - private static Boolean actRB3 = false; + private static boolean actRB1 = false; + private static boolean actRB2 = false; + private static boolean actRB3 = false; // JDK-8226892: Verify that ActionListener is called when a RadioButton is selected using arrow key. private static void runTest9() throws Exception { @@ -268,9 +265,9 @@ public class bug8033699 { radioBtn2.addActionListener(actLrRB2); radioBtn3.addActionListener(actLrRB3); - hitKey(robot, KeyEvent.VK_DOWN); - hitKey(robot, KeyEvent.VK_DOWN); - hitKey(robot, KeyEvent.VK_DOWN); + hitKey(KeyEvent.VK_DOWN); + hitKey(KeyEvent.VK_DOWN); + hitKey(KeyEvent.VK_DOWN); String failMessage = "ActionListener not invoked when selected using arrow key."; if (!actRB2) { @@ -288,13 +285,13 @@ public class bug8033699 { radioBtn3.removeActionListener(actLrRB3); } - private static void hitKey(Robot robot, int keycode) { + private static void hitKey(int keycode) { robot.keyPress(keycode); robot.keyRelease(keycode); robot.waitForIdle(); } - private static void hitKey(Robot robot, int mode, int keycode) { + private static void hitKey(int mode, int keycode) { robot.keyPress(mode); robot.keyPress(keycode); robot.keyRelease(keycode); diff --git a/test/jdk/javax/swing/JRadioButton/8075609/bug8075609.java b/test/jdk/javax/swing/JRadioButton/8075609/bug8075609.java index 31c99206b7a..4c29a33ffa0 100644 --- a/test/jdk/javax/swing/JRadioButton/8075609/bug8075609.java +++ b/test/jdk/javax/swing/JRadioButton/8075609/bug8075609.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,44 +21,49 @@ * questions. */ - /* +/* * @test * @key headful - * @library ../../regtesthelpers - * @build Util * @bug 8075609 * @summary IllegalArgumentException when transferring focus from JRadioButton using tab - * @author Vivi An * @run main bug8075609 */ - -import javax.swing.*; -import javax.swing.event.*; -import java.awt.event.*; -import java.awt.*; +import java.awt.BorderLayout; +import java.awt.Robot; +import java.awt.event.KeyEvent; + +import javax.swing.ButtonGroup; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JRadioButton; +import javax.swing.JTextField; +import javax.swing.LayoutFocusTraversalPolicy; +import javax.swing.SwingUtilities; public class bug8075609 { private static Robot robot; private static JTextField textField; private static JFrame mainFrame; - public static void main(String args[]) throws Throwable { + public static void main(String[] args) throws Throwable { try { - SwingUtilities.invokeAndWait(new Runnable() { - public void run() { - createAndShowGUI(); - } - }); + SwingUtilities.invokeAndWait(bug8075609::createAndShowGUI); robot = new Robot(); Thread.sleep(100); + robot.waitForIdle(); robot.setAutoDelay(100); // Radio button group tab key test runTest1(); } finally { - if (mainFrame != null) SwingUtilities.invokeAndWait(() -> mainFrame.dispose()); + SwingUtilities.invokeAndWait(() -> { + if (mainFrame != null) { + mainFrame.dispose(); + } + }); } } @@ -91,26 +96,25 @@ public class bug8075609 { mainFrame.add(rootPanel); mainFrame.pack(); + mainFrame.setLocationRelativeTo(null); mainFrame.setVisible(true); mainFrame.toFront(); } // Radio button Group as a single component when traversing through tab key - private static void runTest1() throws Exception{ - hitKey(robot, KeyEvent.VK_TAB); - - robot.delay(1000 ); - SwingUtilities.invokeAndWait(new Runnable() { - public void run() { - if (!textField.hasFocus()) { - System.out.println("Radio Button Group Go To Next Component through Tab Key failed"); - throw new RuntimeException("Focus is not on textField as Expected"); - } + private static void runTest1() throws Exception { + hitKey(KeyEvent.VK_TAB); + + robot.delay(1000); + SwingUtilities.invokeAndWait(() -> { + if (!textField.hasFocus()) { + System.out.println("Radio Button Group Go To Next Component through Tab Key failed"); + throw new RuntimeException("Focus is not on textField as Expected"); } }); } - private static void hitKey(Robot robot, int keycode) { + private static void hitKey(int keycode) { robot.keyPress(keycode); robot.keyRelease(keycode); robot.waitForIdle(); -- GitLab From 7218d8449bfaa3f121b66088a88a194f77f06753 Mon Sep 17 00:00:00 2001 From: John Jiang Date: Thu, 10 Feb 2022 08:11:08 +0000 Subject: [PATCH 451/564] 8281567: Remove @throws IOException from X509CRLImpl::getExtension docs Reviewed-by: xuelei, jiefu --- src/java.base/share/classes/sun/security/x509/X509CRLImpl.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/java.base/share/classes/sun/security/x509/X509CRLImpl.java b/src/java.base/share/classes/sun/security/x509/X509CRLImpl.java index 1523cde227d..551e38ad31c 100644 --- a/src/java.base/share/classes/sun/security/x509/X509CRLImpl.java +++ b/src/java.base/share/classes/sun/security/x509/X509CRLImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -1047,7 +1047,6 @@ public class X509CRLImpl extends X509CRL implements DerEncoder { * * @param oid ObjectIdentifier of extension desired * @return Object of type {@code } or null, if not found - * @throws IOException on error */ public Object getExtension(ObjectIdentifier oid) { if (extensions == null) -- GitLab From fa0a72c030432f9ea4ad9913a2bb4096324410aa Mon Sep 17 00:00:00 2001 From: Emanuel Peter Date: Thu, 10 Feb 2022 09:29:53 +0000 Subject: [PATCH 452/564] 8252496: C2: Useless code in MergeMemNode::Ideal Reviewed-by: thartmann, chagedorn, vlivanov --- src/hotspot/share/opto/memnode.cpp | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/src/hotspot/share/opto/memnode.cpp b/src/hotspot/share/opto/memnode.cpp index 815cbb2f450..c2e2e939bf3 100644 --- a/src/hotspot/share/opto/memnode.cpp +++ b/src/hotspot/share/opto/memnode.cpp @@ -4752,29 +4752,6 @@ Node *MergeMemNode::Ideal(PhaseGVN *phase, bool can_reshape) { // the base memory might contribute new slices beyond my req() if (old_mbase) grow_to_match(old_mbase); - // Look carefully at the base node if it is a phi. - PhiNode* phi_base; - if (new_base != NULL && new_base->is_Phi()) - phi_base = new_base->as_Phi(); - else - phi_base = NULL; - - Node* phi_reg = NULL; - uint phi_len = (uint)-1; - if (phi_base != NULL) { - phi_reg = phi_base->region(); - phi_len = phi_base->req(); - // see if the phi is unfinished - for (uint i = 1; i < phi_len; i++) { - if (phi_base->in(i) == NULL) { - // incomplete phi; do not look at it yet! - phi_reg = NULL; - phi_len = (uint)-1; - break; - } - } - } - // Note: We do not call verify_sparse on entry, because inputs // can normalize to the base_memory via subsume_node or similar // mechanisms. This method repairs that damage. @@ -4975,7 +4952,6 @@ Node* MergeMemNode::memory_at(uint alias_idx) const { // Otherwise, it is a narrow slice. Node* n = alias_idx < req() ? in(alias_idx) : empty_memory(); - Compile *C = Compile::current(); if (is_empty_memory(n)) { // the array is sparse; empty slots are the "top" node n = base_memory(); -- GitLab From c820d1acb7c6e600a890e4205eef0be8a4c7a791 Mon Sep 17 00:00:00 2001 From: Leo Korinth Date: Thu, 10 Feb 2022 10:34:16 +0000 Subject: [PATCH 453/564] 8281379: Assign package declarations to all jtreg test cases under gc Reviewed-by: kbarrett, tschatzl --- test/hotspot/jtreg/gc/g1/TestG1SkipCompaction.java | 4 +++- test/hotspot/jtreg/gc/g1/numa/TestG1NUMATouchRegions.java | 8 +++++--- test/hotspot/jtreg/gc/z/TestGarbageCollectorMXBean.java | 8 +++++--- test/hotspot/jtreg/gc/z/TestMemoryMXBean.java | 8 +++++--- test/hotspot/jtreg/gc/z/TestMemoryManagerMXBean.java | 6 ++++-- 5 files changed, 22 insertions(+), 12 deletions(-) diff --git a/test/hotspot/jtreg/gc/g1/TestG1SkipCompaction.java b/test/hotspot/jtreg/gc/g1/TestG1SkipCompaction.java index f5fadcbb880..9824186c43c 100644 --- a/test/hotspot/jtreg/gc/g1/TestG1SkipCompaction.java +++ b/test/hotspot/jtreg/gc/g1/TestG1SkipCompaction.java @@ -21,6 +21,8 @@ * questions. */ +package gc.g1; + /* * @test TestG1SkipCompaction * @summary Test for JDK-8262068 Improve G1 Full GC by skipping compaction @@ -29,7 +31,7 @@ * @library /test/lib * @modules java.base/jdk.internal.misc * java.management - * @run main/othervm -Xms256m -Xmx256m TestG1SkipCompaction + * @run main/othervm -Xms256m -Xmx256m gc.g1.TestG1SkipCompaction */ import java.util.regex.Matcher; import java.util.regex.Pattern; diff --git a/test/hotspot/jtreg/gc/g1/numa/TestG1NUMATouchRegions.java b/test/hotspot/jtreg/gc/g1/numa/TestG1NUMATouchRegions.java index 6cdbd2c797a..868e5b185f2 100644 --- a/test/hotspot/jtreg/gc/g1/numa/TestG1NUMATouchRegions.java +++ b/test/hotspot/jtreg/gc/g1/numa/TestG1NUMATouchRegions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,7 +21,7 @@ * questions. */ -package gc.g1; +package gc.g1.numa; /** * @test TestG1NUMATouchRegions @@ -33,7 +33,9 @@ package gc.g1; * java.management * @build sun.hotspot.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox - * @run main/othervm -XX:+UseG1GC -Xbootclasspath/a:. -XX:+UseNUMA -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI gc.g1.TestG1NUMATouchRegions + * @run main/othervm -XX:+UseG1GC -Xbootclasspath/a:. -XX:+UseNUMA + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * gc.g1.numa.TestG1NUMATouchRegions */ import java.util.LinkedList; diff --git a/test/hotspot/jtreg/gc/z/TestGarbageCollectorMXBean.java b/test/hotspot/jtreg/gc/z/TestGarbageCollectorMXBean.java index e29d75b009c..7a011edd8c9 100644 --- a/test/hotspot/jtreg/gc/z/TestGarbageCollectorMXBean.java +++ b/test/hotspot/jtreg/gc/z/TestGarbageCollectorMXBean.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,13 +21,15 @@ * questions. */ +package gc.z; + /** * @test TestGarbageCollectorMXBean * @requires vm.gc.Z * @summary Test ZGC garbage collector MXBean * @modules java.management - * @run main/othervm -XX:+UseZGC -Xms256M -Xmx512M -Xlog:gc TestGarbageCollectorMXBean 256 512 - * @run main/othervm -XX:+UseZGC -Xms512M -Xmx512M -Xlog:gc TestGarbageCollectorMXBean 512 512 + * @run main/othervm -XX:+UseZGC -Xms256M -Xmx512M -Xlog:gc gc.z.TestGarbageCollectorMXBean 256 512 + * @run main/othervm -XX:+UseZGC -Xms512M -Xmx512M -Xlog:gc gc.z.TestGarbageCollectorMXBean 512 512 */ import java.lang.management.ManagementFactory; diff --git a/test/hotspot/jtreg/gc/z/TestMemoryMXBean.java b/test/hotspot/jtreg/gc/z/TestMemoryMXBean.java index 47545d1bcf5..18c18985759 100644 --- a/test/hotspot/jtreg/gc/z/TestMemoryMXBean.java +++ b/test/hotspot/jtreg/gc/z/TestMemoryMXBean.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,13 +21,15 @@ * questions. */ +package gc.z; + /** * @test TestMemoryMXBean * @requires vm.gc.Z * @summary Test ZGC heap memory MXBean * @modules java.management - * @run main/othervm -XX:+UseZGC -Xms128M -Xmx256M -Xlog:gc* TestMemoryMXBean 128 256 - * @run main/othervm -XX:+UseZGC -Xms256M -Xmx256M -Xlog:gc* TestMemoryMXBean 256 256 + * @run main/othervm -XX:+UseZGC -Xms128M -Xmx256M -Xlog:gc* gc.z.TestMemoryMXBean 128 256 + * @run main/othervm -XX:+UseZGC -Xms256M -Xmx256M -Xlog:gc* gc.z.TestMemoryMXBean 256 256 */ import java.lang.management.ManagementFactory; diff --git a/test/hotspot/jtreg/gc/z/TestMemoryManagerMXBean.java b/test/hotspot/jtreg/gc/z/TestMemoryManagerMXBean.java index a5c5c1367e7..803201d576e 100644 --- a/test/hotspot/jtreg/gc/z/TestMemoryManagerMXBean.java +++ b/test/hotspot/jtreg/gc/z/TestMemoryManagerMXBean.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,12 +21,14 @@ * questions. */ +package gc.z; + /** * @test TestMemoryManagerMXBean * @requires vm.gc.Z * @summary Test ZGC memory manager MXBean * @modules java.management - * @run main/othervm -XX:+UseZGC -Xmx128M TestMemoryManagerMXBean + * @run main/othervm -XX:+UseZGC -Xmx128M gc.z.TestMemoryManagerMXBean */ import java.lang.management.ManagementFactory; -- GitLab From d442328bc2f2f4bc35dd054487a78552e3d9a759 Mon Sep 17 00:00:00 2001 From: Maxim Kartashev Date: Thu, 10 Feb 2022 10:46:35 +0000 Subject: [PATCH 454/564] 8281262: Windows builds in different directories are not fully reproducible Co-authored-by: Erik Joelsson Reviewed-by: erikj, ihse --- make/TestImage.gmk | 4 ++-- make/autoconf/flags-cflags.m4 | 4 +--- test/jdk/build/AbsPathsInImage.java | 7 +++++++ 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/make/TestImage.gmk b/make/TestImage.gmk index 26d10f95d3b..b719d6824da 100644 --- a/make/TestImage.gmk +++ b/make/TestImage.gmk @@ -35,8 +35,8 @@ BUILD_INFO_PROPERTIES := $(TEST_IMAGE_DIR)/build-info.properties $(BUILD_INFO_PROPERTIES): $(call MakeTargetDir) $(ECHO) "# Build info properties for JDK tests" > $@ - $(ECHO) "build.workspace.root=$(call FixPath, $(WORKSPACE_ROOT))" >> $@ - $(ECHO) "build.output.root=$(call FixPath, $(OUTPUTDIR))" >> $@ + $(ECHO) 'build.workspace.root=$(call FixPath, $(WORKSPACE_ROOT))' >> $@ + $(ECHO) 'build.output.root=$(call FixPath, $(OUTPUTDIR))' >> $@ README := $(TEST_IMAGE_DIR)/Readme.txt diff --git a/make/autoconf/flags-cflags.m4 b/make/autoconf/flags-cflags.m4 index ba4cb3e9ac7..76724235ec4 100644 --- a/make/autoconf/flags-cflags.m4 +++ b/make/autoconf/flags-cflags.m4 @@ -782,10 +782,8 @@ AC_DEFUN([FLAGS_SETUP_CFLAGS_CPU_DEP], test "x$ENABLE_REPRODUCIBLE_BUILD" = xtrue; then # There is a known issue with the pathmap if the mapping is made to the # empty string. Add a minimal string "s" as prefix to work around this. - workspace_root_win=`$FIXPATH_BASE print "${WORKSPACE_ROOT%/}"` # PATHMAP_FLAGS is also added to LDFLAGS in flags-ldflags.m4. - PATHMAP_FLAGS="-pathmap:${workspace_root_win//\//\\\\}=s \ - -pathmap:${workspace_root_win}=s" + PATHMAP_FLAGS="-pathmap:${WORKSPACE_ROOT}=s" FILE_MACRO_CFLAGS="$PATHMAP_FLAGS" FLAGS_COMPILER_CHECK_ARGUMENTS(ARGUMENT: [${FILE_MACRO_CFLAGS}], PREFIX: $3, diff --git a/test/jdk/build/AbsPathsInImage.java b/test/jdk/build/AbsPathsInImage.java index 3fd7dda239a..0e4b6d8caff 100644 --- a/test/jdk/build/AbsPathsInImage.java +++ b/test/jdk/build/AbsPathsInImage.java @@ -96,6 +96,13 @@ public class AbsPathsInImage { if (buildOutputRoot == null) { throw new Error("Could not find build output root, test cannot run"); } + // Validate the root paths + if (!Paths.get(buildWorkspaceRoot).isAbsolute()) { + throw new Error("Workspace root is not an absolute path: " + buildWorkspaceRoot); + } + if (!Paths.get(buildOutputRoot).isAbsolute()) { + throw new Error("Output root is not an absolute path: " + buildOutputRoot); + } List searchPatterns = new ArrayList<>(); expandPatterns(searchPatterns, buildWorkspaceRoot); -- GitLab From 3ce1c5b6ce02749ef8f9d35409b7bcbf27f47203 Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Thu, 10 Feb 2022 11:28:04 +0000 Subject: [PATCH 455/564] 8280832: Update usage docs for NonblockingQueue Reviewed-by: iwalulya, dholmes --- src/hotspot/share/utilities/nonblockingQueue.hpp | 4 +++- src/hotspot/share/utilities/nonblockingQueue.inline.hpp | 6 ++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/utilities/nonblockingQueue.hpp b/src/hotspot/share/utilities/nonblockingQueue.hpp index 6f8936b019f..a271aaa38d8 100644 --- a/src/hotspot/share/utilities/nonblockingQueue.hpp +++ b/src/hotspot/share/utilities/nonblockingQueue.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022, 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 @@ -96,9 +96,11 @@ public: inline size_t length() const; // Thread-safe add the object to the end of the queue. + // Subject to ABA behavior; callers must ensure usage is safe. inline void push(T& node) { append(node, node); } // Thread-safe add the objects from first to last to the end of the queue. + // Subject to ABA behavior; callers must ensure usage is safe. inline void append(T& first, T& last); // Thread-safe attempt to remove and return the first object in the queue. diff --git a/src/hotspot/share/utilities/nonblockingQueue.inline.hpp b/src/hotspot/share/utilities/nonblockingQueue.inline.hpp index 2845822b204..2ecb1663e45 100644 --- a/src/hotspot/share/utilities/nonblockingQueue.inline.hpp +++ b/src/hotspot/share/utilities/nonblockingQueue.inline.hpp @@ -117,6 +117,12 @@ void NonblockingQueue::append(T& first, T& last) { // other push/append could have competed with us, because we claimed // old_tail for extension. We won any races with try_pop by changing // away from end-marker. So we're done. + // + // Note that ABA is possible here. A concurrent try_pop could take + // old_tail before our update of old_tail's next_ptr, old_tail gets + // recycled and re-added to the end of this queue, and then we + // successfully cmpxchg, making the list in _tail circular. Callers + // must ensure this can't happen. return; } else { // A concurrent try_pop has claimed old_tail, so it is no longer in the -- GitLab From 039313d65d47dc85cb8c91d3e1d2752d365f70f9 Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Thu, 10 Feb 2022 12:02:05 +0000 Subject: [PATCH 456/564] 8054449: Incompatible type in example code in TreePath Reviewed-by: aivanov, dmarkov --- src/java.desktop/share/classes/javax/swing/tree/TreePath.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/java.desktop/share/classes/javax/swing/tree/TreePath.java b/src/java.desktop/share/classes/javax/swing/tree/TreePath.java index e8abb0597df..f55cbe4961b 100644 --- a/src/java.desktop/share/classes/javax/swing/tree/TreePath.java +++ b/src/java.desktop/share/classes/javax/swing/tree/TreePath.java @@ -51,8 +51,8 @@ import java.beans.ConstructorProperties; * ... * TreePath selectedPath = tree.getSelectionPath(); * DefaultMutableTreeNode selectedNode = - * ((DefaultMutableTreeNode)selectedPath.getLastPathComponent()). - * getUserObject(); + * ((DefaultMutableTreeNode)selectedPath.getLastPathComponent()); + * Object myObject= selectedNode.getUserObject(); * * Subclasses typically need override only {@code * getLastPathComponent}, and {@code getParentPath}. As {@code JTree} -- GitLab From 83b6e4bc04db89a846a1b6c2d0666efe139f8f61 Mon Sep 17 00:00:00 2001 From: Paul Sandoz Date: Thu, 10 Feb 2022 18:37:21 +0000 Subject: [PATCH 457/564] 8281294: [vectorapi] FIRST_NONZERO reduction operation throws IllegalArgumentExcept on zero vectors Reviewed-by: jrose --- .../jdk/incubator/vector/ByteVector.java | 36 +---- .../jdk/incubator/vector/DoubleVector.java | 32 +---- .../jdk/incubator/vector/FloatVector.java | 32 +---- .../jdk/incubator/vector/IntVector.java | 36 +---- .../jdk/incubator/vector/LongVector.java | 36 +---- .../jdk/incubator/vector/ShortVector.java | 36 +---- .../incubator/vector/X-Vector.java.template | 40 +----- .../incubator/vector/Byte128VectorTests.java | 127 ++++++++++++++--- .../incubator/vector/Byte256VectorTests.java | 127 ++++++++++++++--- .../incubator/vector/Byte512VectorTests.java | 129 +++++++++++++++--- .../incubator/vector/Byte64VectorTests.java | 127 ++++++++++++++--- .../incubator/vector/ByteMaxVectorTests.java | 129 +++++++++++++++--- .../vector/Double128VectorTests.java | 127 ++++++++++++++--- .../vector/Double256VectorTests.java | 127 ++++++++++++++--- .../vector/Double512VectorTests.java | 127 ++++++++++++++--- .../incubator/vector/Double64VectorTests.java | 127 ++++++++++++++--- .../vector/DoubleMaxVectorTests.java | 127 ++++++++++++++--- .../incubator/vector/Float128VectorTests.java | 127 ++++++++++++++--- .../incubator/vector/Float256VectorTests.java | 127 ++++++++++++++--- .../incubator/vector/Float512VectorTests.java | 127 ++++++++++++++--- .../incubator/vector/Float64VectorTests.java | 127 ++++++++++++++--- .../incubator/vector/FloatMaxVectorTests.java | 127 ++++++++++++++--- .../incubator/vector/Int128VectorTests.java | 127 ++++++++++++++--- .../incubator/vector/Int256VectorTests.java | 127 ++++++++++++++--- .../incubator/vector/Int512VectorTests.java | 127 ++++++++++++++--- .../incubator/vector/Int64VectorTests.java | 127 ++++++++++++++--- .../incubator/vector/IntMaxVectorTests.java | 127 ++++++++++++++--- .../incubator/vector/Long128VectorTests.java | 127 ++++++++++++++--- .../incubator/vector/Long256VectorTests.java | 127 ++++++++++++++--- .../incubator/vector/Long512VectorTests.java | 127 ++++++++++++++--- .../incubator/vector/Long64VectorTests.java | 127 ++++++++++++++--- .../incubator/vector/LongMaxVectorTests.java | 127 ++++++++++++++--- .../incubator/vector/Short128VectorTests.java | 127 ++++++++++++++--- .../incubator/vector/Short256VectorTests.java | 127 ++++++++++++++--- .../incubator/vector/Short512VectorTests.java | 127 ++++++++++++++--- .../incubator/vector/Short64VectorTests.java | 127 ++++++++++++++--- .../incubator/vector/ShortMaxVectorTests.java | 127 ++++++++++++++--- test/jdk/jdk/incubator/vector/gen-template.sh | 36 ++--- .../Kernel-Reduction-Masked-Min-op.template | 21 --- ... Kernel-Reduction-Masked-op-func.template} | 2 +- .../Kernel-Reduction-Min-op.template | 19 --- ...late => Kernel-Reduction-op-func.template} | 2 +- .../Unit-Reduction-Masked-Min-op.template | 6 - ...=> Unit-Reduction-Masked-op-func.template} | 0 .../templates/Unit-Reduction-Min-op.template | 6 - ...it-Reduction-Scalar-Masked-Min-op.template | 19 --- ...-Reduction-Scalar-Masked-op-func.template} | 9 +- .../Unit-Reduction-Scalar-Min-op.template | 17 --- ...=> Unit-Reduction-Scalar-op-func.template} | 6 +- ...mplate => Unit-Reduction-op-func.template} | 0 .../vector/templates/Unit-header.template | 4 + 51 files changed, 3272 insertions(+), 937 deletions(-) delete mode 100644 test/jdk/jdk/incubator/vector/templates/Kernel-Reduction-Masked-Min-op.template rename test/jdk/jdk/incubator/vector/templates/{Kernel-Reduction-Masked-Max-op.template => Kernel-Reduction-Masked-op-func.template} (90%) delete mode 100644 test/jdk/jdk/incubator/vector/templates/Kernel-Reduction-Min-op.template rename test/jdk/jdk/incubator/vector/templates/{Kernel-Reduction-Max-op.template => Kernel-Reduction-op-func.template} (89%) delete mode 100644 test/jdk/jdk/incubator/vector/templates/Unit-Reduction-Masked-Min-op.template rename test/jdk/jdk/incubator/vector/templates/{Unit-Reduction-Masked-Max-op.template => Unit-Reduction-Masked-op-func.template} (100%) delete mode 100644 test/jdk/jdk/incubator/vector/templates/Unit-Reduction-Min-op.template delete mode 100644 test/jdk/jdk/incubator/vector/templates/Unit-Reduction-Scalar-Masked-Min-op.template rename test/jdk/jdk/incubator/vector/templates/{Unit-Reduction-Scalar-Masked-Max-op.template => Unit-Reduction-Scalar-Masked-op-func.template} (60%) delete mode 100644 test/jdk/jdk/incubator/vector/templates/Unit-Reduction-Scalar-Min-op.template rename test/jdk/jdk/incubator/vector/templates/{Unit-Reduction-Scalar-Max-op.template => Unit-Reduction-Scalar-op-func.template} (65%) rename test/jdk/jdk/incubator/vector/templates/{Unit-Reduction-Max-op.template => Unit-Reduction-op-func.template} (100%) diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector.java index 256e1a5700f..d67f86f7985 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector.java @@ -2595,7 +2595,8 @@ public abstract class ByteVector extends AbstractVector { VectorMask m) { m.check(maskClass, this); if (op == FIRST_NONZERO) { - ByteVector v = reduceIdentityVector(op).blend(this, m); + // FIXME: The JIT should handle this. + ByteVector v = broadcast((byte) 0).blend(this, m); return v.reduceLanesTemplate(op); } int opc = opCode(op); @@ -2610,10 +2611,11 @@ public abstract class ByteVector extends AbstractVector { final byte reduceLanesTemplate(VectorOperators.Associative op) { if (op == FIRST_NONZERO) { - // FIXME: The JIT should handle this, and other scan ops alos. + // FIXME: The JIT should handle this. VectorMask thisNZ = this.viewAsIntegralLanes().compare(NE, (byte) 0); - return this.lane(thisNZ.firstTrue()); + int ft = thisNZ.firstTrue(); + return ft < length() ? this.lane(ft) : (byte) 0; } int opc = opCode(op); return fromBits(VectorSupport.reductionCoerced( @@ -2646,34 +2648,6 @@ public abstract class ByteVector extends AbstractVector { } } - private - @ForceInline - ByteVector reduceIdentityVector(VectorOperators.Associative op) { - int opc = opCode(op); - UnaryOperator fn - = REDUCE_ID_IMPL.find(op, opc, (opc_) -> { - switch (opc_) { - case VECTOR_OP_ADD: - case VECTOR_OP_OR: - case VECTOR_OP_XOR: - return v -> v.broadcast(0); - case VECTOR_OP_MUL: - return v -> v.broadcast(1); - case VECTOR_OP_AND: - return v -> v.broadcast(-1); - case VECTOR_OP_MIN: - return v -> v.broadcast(MAX_OR_INF); - case VECTOR_OP_MAX: - return v -> v.broadcast(MIN_OR_INF); - default: return null; - } - }); - return fn.apply(this); - } - private static final - ImplCache> REDUCE_ID_IMPL - = new ImplCache<>(Associative.class, ByteVector.class); - private static final byte MIN_OR_INF = Byte.MIN_VALUE; private static final byte MAX_OR_INF = Byte.MAX_VALUE; diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector.java index 8455e354678..063a4bbb191 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector.java @@ -2419,7 +2419,8 @@ public abstract class DoubleVector extends AbstractVector { VectorMask m) { m.check(maskClass, this); if (op == FIRST_NONZERO) { - DoubleVector v = reduceIdentityVector(op).blend(this, m); + // FIXME: The JIT should handle this. + DoubleVector v = broadcast((double) 0).blend(this, m); return v.reduceLanesTemplate(op); } int opc = opCode(op); @@ -2434,10 +2435,11 @@ public abstract class DoubleVector extends AbstractVector { final double reduceLanesTemplate(VectorOperators.Associative op) { if (op == FIRST_NONZERO) { - // FIXME: The JIT should handle this, and other scan ops alos. + // FIXME: The JIT should handle this. VectorMask thisNZ = this.viewAsIntegralLanes().compare(NE, (long) 0); - return this.lane(thisNZ.firstTrue()); + int ft = thisNZ.firstTrue(); + return ft < length() ? this.lane(ft) : (double) 0; } int opc = opCode(op); return fromBits(VectorSupport.reductionCoerced( @@ -2464,30 +2466,6 @@ public abstract class DoubleVector extends AbstractVector { } } - private - @ForceInline - DoubleVector reduceIdentityVector(VectorOperators.Associative op) { - int opc = opCode(op); - UnaryOperator fn - = REDUCE_ID_IMPL.find(op, opc, (opc_) -> { - switch (opc_) { - case VECTOR_OP_ADD: - return v -> v.broadcast(0); - case VECTOR_OP_MUL: - return v -> v.broadcast(1); - case VECTOR_OP_MIN: - return v -> v.broadcast(MAX_OR_INF); - case VECTOR_OP_MAX: - return v -> v.broadcast(MIN_OR_INF); - default: return null; - } - }); - return fn.apply(this); - } - private static final - ImplCache> REDUCE_ID_IMPL - = new ImplCache<>(Associative.class, DoubleVector.class); - private static final double MIN_OR_INF = Double.NEGATIVE_INFINITY; private static final double MAX_OR_INF = Double.POSITIVE_INFINITY; diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector.java index 1dc63aa1de3..f78d9814514 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector.java @@ -2439,7 +2439,8 @@ public abstract class FloatVector extends AbstractVector { VectorMask m) { m.check(maskClass, this); if (op == FIRST_NONZERO) { - FloatVector v = reduceIdentityVector(op).blend(this, m); + // FIXME: The JIT should handle this. + FloatVector v = broadcast((float) 0).blend(this, m); return v.reduceLanesTemplate(op); } int opc = opCode(op); @@ -2454,10 +2455,11 @@ public abstract class FloatVector extends AbstractVector { final float reduceLanesTemplate(VectorOperators.Associative op) { if (op == FIRST_NONZERO) { - // FIXME: The JIT should handle this, and other scan ops alos. + // FIXME: The JIT should handle this. VectorMask thisNZ = this.viewAsIntegralLanes().compare(NE, (int) 0); - return this.lane(thisNZ.firstTrue()); + int ft = thisNZ.firstTrue(); + return ft < length() ? this.lane(ft) : (float) 0; } int opc = opCode(op); return fromBits(VectorSupport.reductionCoerced( @@ -2484,30 +2486,6 @@ public abstract class FloatVector extends AbstractVector { } } - private - @ForceInline - FloatVector reduceIdentityVector(VectorOperators.Associative op) { - int opc = opCode(op); - UnaryOperator fn - = REDUCE_ID_IMPL.find(op, opc, (opc_) -> { - switch (opc_) { - case VECTOR_OP_ADD: - return v -> v.broadcast(0); - case VECTOR_OP_MUL: - return v -> v.broadcast(1); - case VECTOR_OP_MIN: - return v -> v.broadcast(MAX_OR_INF); - case VECTOR_OP_MAX: - return v -> v.broadcast(MIN_OR_INF); - default: return null; - } - }); - return fn.apply(this); - } - private static final - ImplCache> REDUCE_ID_IMPL - = new ImplCache<>(Associative.class, FloatVector.class); - private static final float MIN_OR_INF = Float.NEGATIVE_INFINITY; private static final float MAX_OR_INF = Float.POSITIVE_INFINITY; diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector.java index 29dbfe5a796..c80b61cb7a2 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector.java @@ -2594,7 +2594,8 @@ public abstract class IntVector extends AbstractVector { VectorMask m) { m.check(maskClass, this); if (op == FIRST_NONZERO) { - IntVector v = reduceIdentityVector(op).blend(this, m); + // FIXME: The JIT should handle this. + IntVector v = broadcast((int) 0).blend(this, m); return v.reduceLanesTemplate(op); } int opc = opCode(op); @@ -2609,10 +2610,11 @@ public abstract class IntVector extends AbstractVector { final int reduceLanesTemplate(VectorOperators.Associative op) { if (op == FIRST_NONZERO) { - // FIXME: The JIT should handle this, and other scan ops alos. + // FIXME: The JIT should handle this. VectorMask thisNZ = this.viewAsIntegralLanes().compare(NE, (int) 0); - return this.lane(thisNZ.firstTrue()); + int ft = thisNZ.firstTrue(); + return ft < length() ? this.lane(ft) : (int) 0; } int opc = opCode(op); return fromBits(VectorSupport.reductionCoerced( @@ -2645,34 +2647,6 @@ public abstract class IntVector extends AbstractVector { } } - private - @ForceInline - IntVector reduceIdentityVector(VectorOperators.Associative op) { - int opc = opCode(op); - UnaryOperator fn - = REDUCE_ID_IMPL.find(op, opc, (opc_) -> { - switch (opc_) { - case VECTOR_OP_ADD: - case VECTOR_OP_OR: - case VECTOR_OP_XOR: - return v -> v.broadcast(0); - case VECTOR_OP_MUL: - return v -> v.broadcast(1); - case VECTOR_OP_AND: - return v -> v.broadcast(-1); - case VECTOR_OP_MIN: - return v -> v.broadcast(MAX_OR_INF); - case VECTOR_OP_MAX: - return v -> v.broadcast(MIN_OR_INF); - default: return null; - } - }); - return fn.apply(this); - } - private static final - ImplCache> REDUCE_ID_IMPL - = new ImplCache<>(Associative.class, IntVector.class); - private static final int MIN_OR_INF = Integer.MIN_VALUE; private static final int MAX_OR_INF = Integer.MAX_VALUE; diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector.java index 365740c90c2..6934469b213 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector.java @@ -2460,7 +2460,8 @@ public abstract class LongVector extends AbstractVector { VectorMask m) { m.check(maskClass, this); if (op == FIRST_NONZERO) { - LongVector v = reduceIdentityVector(op).blend(this, m); + // FIXME: The JIT should handle this. + LongVector v = broadcast((long) 0).blend(this, m); return v.reduceLanesTemplate(op); } int opc = opCode(op); @@ -2475,10 +2476,11 @@ public abstract class LongVector extends AbstractVector { final long reduceLanesTemplate(VectorOperators.Associative op) { if (op == FIRST_NONZERO) { - // FIXME: The JIT should handle this, and other scan ops alos. + // FIXME: The JIT should handle this. VectorMask thisNZ = this.viewAsIntegralLanes().compare(NE, (long) 0); - return this.lane(thisNZ.firstTrue()); + int ft = thisNZ.firstTrue(); + return ft < length() ? this.lane(ft) : (long) 0; } int opc = opCode(op); return fromBits(VectorSupport.reductionCoerced( @@ -2511,34 +2513,6 @@ public abstract class LongVector extends AbstractVector { } } - private - @ForceInline - LongVector reduceIdentityVector(VectorOperators.Associative op) { - int opc = opCode(op); - UnaryOperator fn - = REDUCE_ID_IMPL.find(op, opc, (opc_) -> { - switch (opc_) { - case VECTOR_OP_ADD: - case VECTOR_OP_OR: - case VECTOR_OP_XOR: - return v -> v.broadcast(0); - case VECTOR_OP_MUL: - return v -> v.broadcast(1); - case VECTOR_OP_AND: - return v -> v.broadcast(-1); - case VECTOR_OP_MIN: - return v -> v.broadcast(MAX_OR_INF); - case VECTOR_OP_MAX: - return v -> v.broadcast(MIN_OR_INF); - default: return null; - } - }); - return fn.apply(this); - } - private static final - ImplCache> REDUCE_ID_IMPL - = new ImplCache<>(Associative.class, LongVector.class); - private static final long MIN_OR_INF = Long.MIN_VALUE; private static final long MAX_OR_INF = Long.MAX_VALUE; diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector.java index d527500bb1a..b3c89e87cc4 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector.java @@ -2595,7 +2595,8 @@ public abstract class ShortVector extends AbstractVector { VectorMask m) { m.check(maskClass, this); if (op == FIRST_NONZERO) { - ShortVector v = reduceIdentityVector(op).blend(this, m); + // FIXME: The JIT should handle this. + ShortVector v = broadcast((short) 0).blend(this, m); return v.reduceLanesTemplate(op); } int opc = opCode(op); @@ -2610,10 +2611,11 @@ public abstract class ShortVector extends AbstractVector { final short reduceLanesTemplate(VectorOperators.Associative op) { if (op == FIRST_NONZERO) { - // FIXME: The JIT should handle this, and other scan ops alos. + // FIXME: The JIT should handle this. VectorMask thisNZ = this.viewAsIntegralLanes().compare(NE, (short) 0); - return this.lane(thisNZ.firstTrue()); + int ft = thisNZ.firstTrue(); + return ft < length() ? this.lane(ft) : (short) 0; } int opc = opCode(op); return fromBits(VectorSupport.reductionCoerced( @@ -2646,34 +2648,6 @@ public abstract class ShortVector extends AbstractVector { } } - private - @ForceInline - ShortVector reduceIdentityVector(VectorOperators.Associative op) { - int opc = opCode(op); - UnaryOperator fn - = REDUCE_ID_IMPL.find(op, opc, (opc_) -> { - switch (opc_) { - case VECTOR_OP_ADD: - case VECTOR_OP_OR: - case VECTOR_OP_XOR: - return v -> v.broadcast(0); - case VECTOR_OP_MUL: - return v -> v.broadcast(1); - case VECTOR_OP_AND: - return v -> v.broadcast(-1); - case VECTOR_OP_MIN: - return v -> v.broadcast(MAX_OR_INF); - case VECTOR_OP_MAX: - return v -> v.broadcast(MIN_OR_INF); - default: return null; - } - }); - return fn.apply(this); - } - private static final - ImplCache> REDUCE_ID_IMPL - = new ImplCache<>(Associative.class, ShortVector.class); - private static final short MIN_OR_INF = Short.MIN_VALUE; private static final short MAX_OR_INF = Short.MAX_VALUE; diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template index ae12e5fecff..1cd50a11b8b 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template @@ -3021,7 +3021,8 @@ public abstract class $abstractvectortype$ extends AbstractVector<$Boxtype$> { VectorMask<$Boxtype$> m) { m.check(maskClass, this); if (op == FIRST_NONZERO) { - $abstractvectortype$ v = reduceIdentityVector(op).blend(this, m); + // FIXME: The JIT should handle this. + $abstractvectortype$ v = broadcast(($type$) 0).blend(this, m); return v.reduceLanesTemplate(op); } int opc = opCode(op); @@ -3036,10 +3037,11 @@ public abstract class $abstractvectortype$ extends AbstractVector<$Boxtype$> { final $type$ reduceLanesTemplate(VectorOperators.Associative op) { if (op == FIRST_NONZERO) { - // FIXME: The JIT should handle this, and other scan ops alos. + // FIXME: The JIT should handle this. VectorMask<$Boxbitstype$> thisNZ = this.viewAsIntegralLanes().compare(NE, ($bitstype$) 0); - return this.lane(thisNZ.firstTrue()); + int ft = thisNZ.firstTrue(); + return ft < length() ? this.lane(ft) : ($type$) 0; } int opc = opCode(op); return fromBits(VectorSupport.reductionCoerced( @@ -3074,38 +3076,6 @@ public abstract class $abstractvectortype$ extends AbstractVector<$Boxtype$> { } } - private - @ForceInline - $abstractvectortype$ reduceIdentityVector(VectorOperators.Associative op) { - int opc = opCode(op); - UnaryOperator<$abstractvectortype$> fn - = REDUCE_ID_IMPL.find(op, opc, (opc_) -> { - switch (opc_) { - case VECTOR_OP_ADD: -#if[BITWISE] - case VECTOR_OP_OR: - case VECTOR_OP_XOR: -#end[BITWISE] - return v -> v.broadcast(0); - case VECTOR_OP_MUL: - return v -> v.broadcast(1); -#if[BITWISE] - case VECTOR_OP_AND: - return v -> v.broadcast(-1); -#end[BITWISE] - case VECTOR_OP_MIN: - return v -> v.broadcast(MAX_OR_INF); - case VECTOR_OP_MAX: - return v -> v.broadcast(MIN_OR_INF); - default: return null; - } - }); - return fn.apply(this); - } - private static final - ImplCache> REDUCE_ID_IMPL - = new ImplCache<>(Associative.class, $Type$Vector.class); - #if[FP] private static final $type$ MIN_OR_INF = $Boxtype$.NEGATIVE_INFINITY; private static final $type$ MAX_OR_INF = $Boxtype$.POSITIVE_INFINITY; diff --git a/test/jdk/jdk/incubator/vector/Byte128VectorTests.java b/test/jdk/jdk/incubator/vector/Byte128VectorTests.java index df3e773388a..22e07e05a06 100644 --- a/test/jdk/jdk/incubator/vector/Byte128VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Byte128VectorTests.java @@ -1201,6 +1201,10 @@ public class Byte128VectorTests extends AbstractVectorTest { return Byte.compareUnsigned(a, b) >= 0; } + static byte firstNonZero(byte a, byte b) { + return Byte.compare(a, (byte) 0) != 0 ? a : b; + } + @Test static void smokeTest1() { ByteVector three = ByteVector.broadcast(SPECIES, (byte)-3); @@ -3216,7 +3220,7 @@ public class Byte128VectorTests extends AbstractVectorTest { static byte MINReduce(byte[] a, int idx) { byte res = Byte.MAX_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (byte)Math.min(res, a[i]); + res = (byte) Math.min(res, a[i]); } return res; @@ -3224,8 +3228,8 @@ public class Byte128VectorTests extends AbstractVectorTest { static byte MINReduceAll(byte[] a) { byte res = Byte.MAX_VALUE; - for (int i = 0; i < a.length; i++) { - res = (byte)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (byte) Math.min(res, MINReduce(a, i)); } return res; @@ -3247,7 +3251,7 @@ public class Byte128VectorTests extends AbstractVectorTest { ra = Byte.MAX_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { ByteVector av = ByteVector.fromArray(SPECIES, a, i); - ra = (byte)Math.min(ra, av.reduceLanes(VectorOperators.MIN)); + ra = (byte) Math.min(ra, av.reduceLanes(VectorOperators.MIN)); } } @@ -3257,8 +3261,8 @@ public class Byte128VectorTests extends AbstractVectorTest { static byte MINReduceMasked(byte[] a, int idx, boolean[] mask) { byte res = Byte.MAX_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (byte)Math.min(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (byte) Math.min(res, a[i]); } return res; @@ -3266,9 +3270,8 @@ public class Byte128VectorTests extends AbstractVectorTest { static byte MINReduceAllMasked(byte[] a, boolean[] mask) { byte res = Byte.MAX_VALUE; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (byte)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (byte) Math.min(res, MINReduceMasked(a, i, mask)); } return res; @@ -3292,7 +3295,7 @@ public class Byte128VectorTests extends AbstractVectorTest { ra = Byte.MAX_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { ByteVector av = ByteVector.fromArray(SPECIES, a, i); - ra = (byte)Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); + ra = (byte) Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); } } @@ -3302,7 +3305,7 @@ public class Byte128VectorTests extends AbstractVectorTest { static byte MAXReduce(byte[] a, int idx) { byte res = Byte.MIN_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (byte)Math.max(res, a[i]); + res = (byte) Math.max(res, a[i]); } return res; @@ -3310,8 +3313,8 @@ public class Byte128VectorTests extends AbstractVectorTest { static byte MAXReduceAll(byte[] a) { byte res = Byte.MIN_VALUE; - for (int i = 0; i < a.length; i++) { - res = (byte)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (byte) Math.max(res, MAXReduce(a, i)); } return res; @@ -3333,7 +3336,7 @@ public class Byte128VectorTests extends AbstractVectorTest { ra = Byte.MIN_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { ByteVector av = ByteVector.fromArray(SPECIES, a, i); - ra = (byte)Math.max(ra, av.reduceLanes(VectorOperators.MAX)); + ra = (byte) Math.max(ra, av.reduceLanes(VectorOperators.MAX)); } } @@ -3343,8 +3346,8 @@ public class Byte128VectorTests extends AbstractVectorTest { static byte MAXReduceMasked(byte[] a, int idx, boolean[] mask) { byte res = Byte.MIN_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (byte)Math.max(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (byte) Math.max(res, a[i]); } return res; @@ -3352,9 +3355,8 @@ public class Byte128VectorTests extends AbstractVectorTest { static byte MAXReduceAllMasked(byte[] a, boolean[] mask) { byte res = Byte.MIN_VALUE; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (byte)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (byte) Math.max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -3378,13 +3380,98 @@ public class Byte128VectorTests extends AbstractVectorTest { ra = Byte.MIN_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { ByteVector av = ByteVector.fromArray(SPECIES, a, i); - ra = (byte)Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); + ra = (byte) Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); } } assertReductionArraysEqualsMasked(r, ra, a, mask, Byte128VectorTests::MAXReduceMasked, Byte128VectorTests::MAXReduceAllMasked); } + static byte FIRST_NONZEROReduce(byte[] a, int idx) { + byte res = (byte) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = firstNonZero(res, a[i]); + } + + return res; + } + + static byte FIRST_NONZEROReduceAll(byte[] a) { + byte res = (byte) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduce(a, i)); + } + + return res; + } + @Test(dataProvider = "byteUnaryOpProvider") + static void FIRST_NONZEROReduceByte128VectorTests(IntFunction fa) { + byte[] a = fa.apply(SPECIES.length()); + byte[] r = fr.apply(SPECIES.length()); + byte ra = (byte) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (byte) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO)); + } + } + + assertReductionArraysEquals(r, ra, a, + Byte128VectorTests::FIRST_NONZEROReduce, Byte128VectorTests::FIRST_NONZEROReduceAll); + } + static byte FIRST_NONZEROReduceMasked(byte[] a, int idx, boolean[] mask) { + byte res = (byte) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = firstNonZero(res, a[i]); + } + + return res; + } + + static byte FIRST_NONZEROReduceAllMasked(byte[] a, boolean[] mask) { + byte res = (byte) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduceMasked(a, i, mask)); + } + + return res; + } + @Test(dataProvider = "byteUnaryOpMaskProvider") + static void FIRST_NONZEROReduceByte128VectorTestsMasked(IntFunction fa, IntFunction fm) { + byte[] a = fa.apply(SPECIES.length()); + byte[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + byte ra = (byte) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (byte) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Byte128VectorTests::FIRST_NONZEROReduceMasked, Byte128VectorTests::FIRST_NONZEROReduceAllMasked); + } static boolean anyTrue(boolean[] a, int idx) { boolean res = false; diff --git a/test/jdk/jdk/incubator/vector/Byte256VectorTests.java b/test/jdk/jdk/incubator/vector/Byte256VectorTests.java index 85da0f82e81..9a631c47993 100644 --- a/test/jdk/jdk/incubator/vector/Byte256VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Byte256VectorTests.java @@ -1201,6 +1201,10 @@ public class Byte256VectorTests extends AbstractVectorTest { return Byte.compareUnsigned(a, b) >= 0; } + static byte firstNonZero(byte a, byte b) { + return Byte.compare(a, (byte) 0) != 0 ? a : b; + } + @Test static void smokeTest1() { ByteVector three = ByteVector.broadcast(SPECIES, (byte)-3); @@ -3216,7 +3220,7 @@ public class Byte256VectorTests extends AbstractVectorTest { static byte MINReduce(byte[] a, int idx) { byte res = Byte.MAX_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (byte)Math.min(res, a[i]); + res = (byte) Math.min(res, a[i]); } return res; @@ -3224,8 +3228,8 @@ public class Byte256VectorTests extends AbstractVectorTest { static byte MINReduceAll(byte[] a) { byte res = Byte.MAX_VALUE; - for (int i = 0; i < a.length; i++) { - res = (byte)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (byte) Math.min(res, MINReduce(a, i)); } return res; @@ -3247,7 +3251,7 @@ public class Byte256VectorTests extends AbstractVectorTest { ra = Byte.MAX_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { ByteVector av = ByteVector.fromArray(SPECIES, a, i); - ra = (byte)Math.min(ra, av.reduceLanes(VectorOperators.MIN)); + ra = (byte) Math.min(ra, av.reduceLanes(VectorOperators.MIN)); } } @@ -3257,8 +3261,8 @@ public class Byte256VectorTests extends AbstractVectorTest { static byte MINReduceMasked(byte[] a, int idx, boolean[] mask) { byte res = Byte.MAX_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (byte)Math.min(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (byte) Math.min(res, a[i]); } return res; @@ -3266,9 +3270,8 @@ public class Byte256VectorTests extends AbstractVectorTest { static byte MINReduceAllMasked(byte[] a, boolean[] mask) { byte res = Byte.MAX_VALUE; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (byte)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (byte) Math.min(res, MINReduceMasked(a, i, mask)); } return res; @@ -3292,7 +3295,7 @@ public class Byte256VectorTests extends AbstractVectorTest { ra = Byte.MAX_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { ByteVector av = ByteVector.fromArray(SPECIES, a, i); - ra = (byte)Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); + ra = (byte) Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); } } @@ -3302,7 +3305,7 @@ public class Byte256VectorTests extends AbstractVectorTest { static byte MAXReduce(byte[] a, int idx) { byte res = Byte.MIN_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (byte)Math.max(res, a[i]); + res = (byte) Math.max(res, a[i]); } return res; @@ -3310,8 +3313,8 @@ public class Byte256VectorTests extends AbstractVectorTest { static byte MAXReduceAll(byte[] a) { byte res = Byte.MIN_VALUE; - for (int i = 0; i < a.length; i++) { - res = (byte)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (byte) Math.max(res, MAXReduce(a, i)); } return res; @@ -3333,7 +3336,7 @@ public class Byte256VectorTests extends AbstractVectorTest { ra = Byte.MIN_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { ByteVector av = ByteVector.fromArray(SPECIES, a, i); - ra = (byte)Math.max(ra, av.reduceLanes(VectorOperators.MAX)); + ra = (byte) Math.max(ra, av.reduceLanes(VectorOperators.MAX)); } } @@ -3343,8 +3346,8 @@ public class Byte256VectorTests extends AbstractVectorTest { static byte MAXReduceMasked(byte[] a, int idx, boolean[] mask) { byte res = Byte.MIN_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (byte)Math.max(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (byte) Math.max(res, a[i]); } return res; @@ -3352,9 +3355,8 @@ public class Byte256VectorTests extends AbstractVectorTest { static byte MAXReduceAllMasked(byte[] a, boolean[] mask) { byte res = Byte.MIN_VALUE; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (byte)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (byte) Math.max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -3378,13 +3380,98 @@ public class Byte256VectorTests extends AbstractVectorTest { ra = Byte.MIN_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { ByteVector av = ByteVector.fromArray(SPECIES, a, i); - ra = (byte)Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); + ra = (byte) Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); } } assertReductionArraysEqualsMasked(r, ra, a, mask, Byte256VectorTests::MAXReduceMasked, Byte256VectorTests::MAXReduceAllMasked); } + static byte FIRST_NONZEROReduce(byte[] a, int idx) { + byte res = (byte) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = firstNonZero(res, a[i]); + } + + return res; + } + + static byte FIRST_NONZEROReduceAll(byte[] a) { + byte res = (byte) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduce(a, i)); + } + + return res; + } + @Test(dataProvider = "byteUnaryOpProvider") + static void FIRST_NONZEROReduceByte256VectorTests(IntFunction fa) { + byte[] a = fa.apply(SPECIES.length()); + byte[] r = fr.apply(SPECIES.length()); + byte ra = (byte) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (byte) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO)); + } + } + + assertReductionArraysEquals(r, ra, a, + Byte256VectorTests::FIRST_NONZEROReduce, Byte256VectorTests::FIRST_NONZEROReduceAll); + } + static byte FIRST_NONZEROReduceMasked(byte[] a, int idx, boolean[] mask) { + byte res = (byte) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = firstNonZero(res, a[i]); + } + + return res; + } + + static byte FIRST_NONZEROReduceAllMasked(byte[] a, boolean[] mask) { + byte res = (byte) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduceMasked(a, i, mask)); + } + + return res; + } + @Test(dataProvider = "byteUnaryOpMaskProvider") + static void FIRST_NONZEROReduceByte256VectorTestsMasked(IntFunction fa, IntFunction fm) { + byte[] a = fa.apply(SPECIES.length()); + byte[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + byte ra = (byte) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (byte) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Byte256VectorTests::FIRST_NONZEROReduceMasked, Byte256VectorTests::FIRST_NONZEROReduceAllMasked); + } static boolean anyTrue(boolean[] a, int idx) { boolean res = false; diff --git a/test/jdk/jdk/incubator/vector/Byte512VectorTests.java b/test/jdk/jdk/incubator/vector/Byte512VectorTests.java index d7659d86871..203f233e4e8 100644 --- a/test/jdk/jdk/incubator/vector/Byte512VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Byte512VectorTests.java @@ -24,7 +24,7 @@ /* * @test * @modules jdk.incubator.vector - * @run testng/othervm/timeout=240 -ea -esa -Xbatch -XX:-TieredCompilation Byte512VectorTests + * @run testng/othervm -ea -esa -Xbatch -XX:-TieredCompilation Byte512VectorTests */ // -- This file was mechanically generated: Do not edit! -- // @@ -1201,6 +1201,10 @@ public class Byte512VectorTests extends AbstractVectorTest { return Byte.compareUnsigned(a, b) >= 0; } + static byte firstNonZero(byte a, byte b) { + return Byte.compare(a, (byte) 0) != 0 ? a : b; + } + @Test static void smokeTest1() { ByteVector three = ByteVector.broadcast(SPECIES, (byte)-3); @@ -3216,7 +3220,7 @@ public class Byte512VectorTests extends AbstractVectorTest { static byte MINReduce(byte[] a, int idx) { byte res = Byte.MAX_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (byte)Math.min(res, a[i]); + res = (byte) Math.min(res, a[i]); } return res; @@ -3224,8 +3228,8 @@ public class Byte512VectorTests extends AbstractVectorTest { static byte MINReduceAll(byte[] a) { byte res = Byte.MAX_VALUE; - for (int i = 0; i < a.length; i++) { - res = (byte)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (byte) Math.min(res, MINReduce(a, i)); } return res; @@ -3247,7 +3251,7 @@ public class Byte512VectorTests extends AbstractVectorTest { ra = Byte.MAX_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { ByteVector av = ByteVector.fromArray(SPECIES, a, i); - ra = (byte)Math.min(ra, av.reduceLanes(VectorOperators.MIN)); + ra = (byte) Math.min(ra, av.reduceLanes(VectorOperators.MIN)); } } @@ -3257,8 +3261,8 @@ public class Byte512VectorTests extends AbstractVectorTest { static byte MINReduceMasked(byte[] a, int idx, boolean[] mask) { byte res = Byte.MAX_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (byte)Math.min(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (byte) Math.min(res, a[i]); } return res; @@ -3266,9 +3270,8 @@ public class Byte512VectorTests extends AbstractVectorTest { static byte MINReduceAllMasked(byte[] a, boolean[] mask) { byte res = Byte.MAX_VALUE; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (byte)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (byte) Math.min(res, MINReduceMasked(a, i, mask)); } return res; @@ -3292,7 +3295,7 @@ public class Byte512VectorTests extends AbstractVectorTest { ra = Byte.MAX_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { ByteVector av = ByteVector.fromArray(SPECIES, a, i); - ra = (byte)Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); + ra = (byte) Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); } } @@ -3302,7 +3305,7 @@ public class Byte512VectorTests extends AbstractVectorTest { static byte MAXReduce(byte[] a, int idx) { byte res = Byte.MIN_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (byte)Math.max(res, a[i]); + res = (byte) Math.max(res, a[i]); } return res; @@ -3310,8 +3313,8 @@ public class Byte512VectorTests extends AbstractVectorTest { static byte MAXReduceAll(byte[] a) { byte res = Byte.MIN_VALUE; - for (int i = 0; i < a.length; i++) { - res = (byte)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (byte) Math.max(res, MAXReduce(a, i)); } return res; @@ -3333,7 +3336,7 @@ public class Byte512VectorTests extends AbstractVectorTest { ra = Byte.MIN_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { ByteVector av = ByteVector.fromArray(SPECIES, a, i); - ra = (byte)Math.max(ra, av.reduceLanes(VectorOperators.MAX)); + ra = (byte) Math.max(ra, av.reduceLanes(VectorOperators.MAX)); } } @@ -3343,8 +3346,8 @@ public class Byte512VectorTests extends AbstractVectorTest { static byte MAXReduceMasked(byte[] a, int idx, boolean[] mask) { byte res = Byte.MIN_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (byte)Math.max(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (byte) Math.max(res, a[i]); } return res; @@ -3352,9 +3355,8 @@ public class Byte512VectorTests extends AbstractVectorTest { static byte MAXReduceAllMasked(byte[] a, boolean[] mask) { byte res = Byte.MIN_VALUE; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (byte)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (byte) Math.max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -3378,13 +3380,98 @@ public class Byte512VectorTests extends AbstractVectorTest { ra = Byte.MIN_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { ByteVector av = ByteVector.fromArray(SPECIES, a, i); - ra = (byte)Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); + ra = (byte) Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); } } assertReductionArraysEqualsMasked(r, ra, a, mask, Byte512VectorTests::MAXReduceMasked, Byte512VectorTests::MAXReduceAllMasked); } + static byte FIRST_NONZEROReduce(byte[] a, int idx) { + byte res = (byte) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = firstNonZero(res, a[i]); + } + + return res; + } + + static byte FIRST_NONZEROReduceAll(byte[] a) { + byte res = (byte) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduce(a, i)); + } + + return res; + } + @Test(dataProvider = "byteUnaryOpProvider") + static void FIRST_NONZEROReduceByte512VectorTests(IntFunction fa) { + byte[] a = fa.apply(SPECIES.length()); + byte[] r = fr.apply(SPECIES.length()); + byte ra = (byte) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (byte) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO)); + } + } + + assertReductionArraysEquals(r, ra, a, + Byte512VectorTests::FIRST_NONZEROReduce, Byte512VectorTests::FIRST_NONZEROReduceAll); + } + static byte FIRST_NONZEROReduceMasked(byte[] a, int idx, boolean[] mask) { + byte res = (byte) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = firstNonZero(res, a[i]); + } + + return res; + } + + static byte FIRST_NONZEROReduceAllMasked(byte[] a, boolean[] mask) { + byte res = (byte) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduceMasked(a, i, mask)); + } + + return res; + } + @Test(dataProvider = "byteUnaryOpMaskProvider") + static void FIRST_NONZEROReduceByte512VectorTestsMasked(IntFunction fa, IntFunction fm) { + byte[] a = fa.apply(SPECIES.length()); + byte[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + byte ra = (byte) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (byte) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Byte512VectorTests::FIRST_NONZEROReduceMasked, Byte512VectorTests::FIRST_NONZEROReduceAllMasked); + } static boolean anyTrue(boolean[] a, int idx) { boolean res = false; diff --git a/test/jdk/jdk/incubator/vector/Byte64VectorTests.java b/test/jdk/jdk/incubator/vector/Byte64VectorTests.java index cc8c2e1c24c..110e741ea43 100644 --- a/test/jdk/jdk/incubator/vector/Byte64VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Byte64VectorTests.java @@ -1201,6 +1201,10 @@ public class Byte64VectorTests extends AbstractVectorTest { return Byte.compareUnsigned(a, b) >= 0; } + static byte firstNonZero(byte a, byte b) { + return Byte.compare(a, (byte) 0) != 0 ? a : b; + } + @Test static void smokeTest1() { ByteVector three = ByteVector.broadcast(SPECIES, (byte)-3); @@ -3216,7 +3220,7 @@ public class Byte64VectorTests extends AbstractVectorTest { static byte MINReduce(byte[] a, int idx) { byte res = Byte.MAX_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (byte)Math.min(res, a[i]); + res = (byte) Math.min(res, a[i]); } return res; @@ -3224,8 +3228,8 @@ public class Byte64VectorTests extends AbstractVectorTest { static byte MINReduceAll(byte[] a) { byte res = Byte.MAX_VALUE; - for (int i = 0; i < a.length; i++) { - res = (byte)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (byte) Math.min(res, MINReduce(a, i)); } return res; @@ -3247,7 +3251,7 @@ public class Byte64VectorTests extends AbstractVectorTest { ra = Byte.MAX_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { ByteVector av = ByteVector.fromArray(SPECIES, a, i); - ra = (byte)Math.min(ra, av.reduceLanes(VectorOperators.MIN)); + ra = (byte) Math.min(ra, av.reduceLanes(VectorOperators.MIN)); } } @@ -3257,8 +3261,8 @@ public class Byte64VectorTests extends AbstractVectorTest { static byte MINReduceMasked(byte[] a, int idx, boolean[] mask) { byte res = Byte.MAX_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (byte)Math.min(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (byte) Math.min(res, a[i]); } return res; @@ -3266,9 +3270,8 @@ public class Byte64VectorTests extends AbstractVectorTest { static byte MINReduceAllMasked(byte[] a, boolean[] mask) { byte res = Byte.MAX_VALUE; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (byte)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (byte) Math.min(res, MINReduceMasked(a, i, mask)); } return res; @@ -3292,7 +3295,7 @@ public class Byte64VectorTests extends AbstractVectorTest { ra = Byte.MAX_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { ByteVector av = ByteVector.fromArray(SPECIES, a, i); - ra = (byte)Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); + ra = (byte) Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); } } @@ -3302,7 +3305,7 @@ public class Byte64VectorTests extends AbstractVectorTest { static byte MAXReduce(byte[] a, int idx) { byte res = Byte.MIN_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (byte)Math.max(res, a[i]); + res = (byte) Math.max(res, a[i]); } return res; @@ -3310,8 +3313,8 @@ public class Byte64VectorTests extends AbstractVectorTest { static byte MAXReduceAll(byte[] a) { byte res = Byte.MIN_VALUE; - for (int i = 0; i < a.length; i++) { - res = (byte)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (byte) Math.max(res, MAXReduce(a, i)); } return res; @@ -3333,7 +3336,7 @@ public class Byte64VectorTests extends AbstractVectorTest { ra = Byte.MIN_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { ByteVector av = ByteVector.fromArray(SPECIES, a, i); - ra = (byte)Math.max(ra, av.reduceLanes(VectorOperators.MAX)); + ra = (byte) Math.max(ra, av.reduceLanes(VectorOperators.MAX)); } } @@ -3343,8 +3346,8 @@ public class Byte64VectorTests extends AbstractVectorTest { static byte MAXReduceMasked(byte[] a, int idx, boolean[] mask) { byte res = Byte.MIN_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (byte)Math.max(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (byte) Math.max(res, a[i]); } return res; @@ -3352,9 +3355,8 @@ public class Byte64VectorTests extends AbstractVectorTest { static byte MAXReduceAllMasked(byte[] a, boolean[] mask) { byte res = Byte.MIN_VALUE; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (byte)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (byte) Math.max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -3378,13 +3380,98 @@ public class Byte64VectorTests extends AbstractVectorTest { ra = Byte.MIN_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { ByteVector av = ByteVector.fromArray(SPECIES, a, i); - ra = (byte)Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); + ra = (byte) Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); } } assertReductionArraysEqualsMasked(r, ra, a, mask, Byte64VectorTests::MAXReduceMasked, Byte64VectorTests::MAXReduceAllMasked); } + static byte FIRST_NONZEROReduce(byte[] a, int idx) { + byte res = (byte) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = firstNonZero(res, a[i]); + } + + return res; + } + + static byte FIRST_NONZEROReduceAll(byte[] a) { + byte res = (byte) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduce(a, i)); + } + + return res; + } + @Test(dataProvider = "byteUnaryOpProvider") + static void FIRST_NONZEROReduceByte64VectorTests(IntFunction fa) { + byte[] a = fa.apply(SPECIES.length()); + byte[] r = fr.apply(SPECIES.length()); + byte ra = (byte) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (byte) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO)); + } + } + + assertReductionArraysEquals(r, ra, a, + Byte64VectorTests::FIRST_NONZEROReduce, Byte64VectorTests::FIRST_NONZEROReduceAll); + } + static byte FIRST_NONZEROReduceMasked(byte[] a, int idx, boolean[] mask) { + byte res = (byte) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = firstNonZero(res, a[i]); + } + + return res; + } + + static byte FIRST_NONZEROReduceAllMasked(byte[] a, boolean[] mask) { + byte res = (byte) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduceMasked(a, i, mask)); + } + + return res; + } + @Test(dataProvider = "byteUnaryOpMaskProvider") + static void FIRST_NONZEROReduceByte64VectorTestsMasked(IntFunction fa, IntFunction fm) { + byte[] a = fa.apply(SPECIES.length()); + byte[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + byte ra = (byte) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (byte) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Byte64VectorTests::FIRST_NONZEROReduceMasked, Byte64VectorTests::FIRST_NONZEROReduceAllMasked); + } static boolean anyTrue(boolean[] a, int idx) { boolean res = false; diff --git a/test/jdk/jdk/incubator/vector/ByteMaxVectorTests.java b/test/jdk/jdk/incubator/vector/ByteMaxVectorTests.java index eb438cb2042..e4a9ebf19f5 100644 --- a/test/jdk/jdk/incubator/vector/ByteMaxVectorTests.java +++ b/test/jdk/jdk/incubator/vector/ByteMaxVectorTests.java @@ -24,7 +24,7 @@ /* * @test * @modules jdk.incubator.vector - * @run testng/othervm/timeout=240 -ea -esa -Xbatch -XX:-TieredCompilation ByteMaxVectorTests + * @run testng/othervm -ea -esa -Xbatch -XX:-TieredCompilation ByteMaxVectorTests */ // -- This file was mechanically generated: Do not edit! -- // @@ -1206,6 +1206,10 @@ public class ByteMaxVectorTests extends AbstractVectorTest { return Byte.compareUnsigned(a, b) >= 0; } + static byte firstNonZero(byte a, byte b) { + return Byte.compare(a, (byte) 0) != 0 ? a : b; + } + @Test static void smokeTest1() { ByteVector three = ByteVector.broadcast(SPECIES, (byte)-3); @@ -3221,7 +3225,7 @@ public class ByteMaxVectorTests extends AbstractVectorTest { static byte MINReduce(byte[] a, int idx) { byte res = Byte.MAX_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (byte)Math.min(res, a[i]); + res = (byte) Math.min(res, a[i]); } return res; @@ -3229,8 +3233,8 @@ public class ByteMaxVectorTests extends AbstractVectorTest { static byte MINReduceAll(byte[] a) { byte res = Byte.MAX_VALUE; - for (int i = 0; i < a.length; i++) { - res = (byte)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (byte) Math.min(res, MINReduce(a, i)); } return res; @@ -3252,7 +3256,7 @@ public class ByteMaxVectorTests extends AbstractVectorTest { ra = Byte.MAX_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { ByteVector av = ByteVector.fromArray(SPECIES, a, i); - ra = (byte)Math.min(ra, av.reduceLanes(VectorOperators.MIN)); + ra = (byte) Math.min(ra, av.reduceLanes(VectorOperators.MIN)); } } @@ -3262,8 +3266,8 @@ public class ByteMaxVectorTests extends AbstractVectorTest { static byte MINReduceMasked(byte[] a, int idx, boolean[] mask) { byte res = Byte.MAX_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (byte)Math.min(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (byte) Math.min(res, a[i]); } return res; @@ -3271,9 +3275,8 @@ public class ByteMaxVectorTests extends AbstractVectorTest { static byte MINReduceAllMasked(byte[] a, boolean[] mask) { byte res = Byte.MAX_VALUE; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (byte)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (byte) Math.min(res, MINReduceMasked(a, i, mask)); } return res; @@ -3297,7 +3300,7 @@ public class ByteMaxVectorTests extends AbstractVectorTest { ra = Byte.MAX_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { ByteVector av = ByteVector.fromArray(SPECIES, a, i); - ra = (byte)Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); + ra = (byte) Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); } } @@ -3307,7 +3310,7 @@ public class ByteMaxVectorTests extends AbstractVectorTest { static byte MAXReduce(byte[] a, int idx) { byte res = Byte.MIN_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (byte)Math.max(res, a[i]); + res = (byte) Math.max(res, a[i]); } return res; @@ -3315,8 +3318,8 @@ public class ByteMaxVectorTests extends AbstractVectorTest { static byte MAXReduceAll(byte[] a) { byte res = Byte.MIN_VALUE; - for (int i = 0; i < a.length; i++) { - res = (byte)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (byte) Math.max(res, MAXReduce(a, i)); } return res; @@ -3338,7 +3341,7 @@ public class ByteMaxVectorTests extends AbstractVectorTest { ra = Byte.MIN_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { ByteVector av = ByteVector.fromArray(SPECIES, a, i); - ra = (byte)Math.max(ra, av.reduceLanes(VectorOperators.MAX)); + ra = (byte) Math.max(ra, av.reduceLanes(VectorOperators.MAX)); } } @@ -3348,8 +3351,8 @@ public class ByteMaxVectorTests extends AbstractVectorTest { static byte MAXReduceMasked(byte[] a, int idx, boolean[] mask) { byte res = Byte.MIN_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (byte)Math.max(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (byte) Math.max(res, a[i]); } return res; @@ -3357,9 +3360,8 @@ public class ByteMaxVectorTests extends AbstractVectorTest { static byte MAXReduceAllMasked(byte[] a, boolean[] mask) { byte res = Byte.MIN_VALUE; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (byte)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (byte) Math.max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -3383,13 +3385,98 @@ public class ByteMaxVectorTests extends AbstractVectorTest { ra = Byte.MIN_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { ByteVector av = ByteVector.fromArray(SPECIES, a, i); - ra = (byte)Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); + ra = (byte) Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); } } assertReductionArraysEqualsMasked(r, ra, a, mask, ByteMaxVectorTests::MAXReduceMasked, ByteMaxVectorTests::MAXReduceAllMasked); } + static byte FIRST_NONZEROReduce(byte[] a, int idx) { + byte res = (byte) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = firstNonZero(res, a[i]); + } + + return res; + } + + static byte FIRST_NONZEROReduceAll(byte[] a) { + byte res = (byte) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduce(a, i)); + } + + return res; + } + @Test(dataProvider = "byteUnaryOpProvider") + static void FIRST_NONZEROReduceByteMaxVectorTests(IntFunction fa) { + byte[] a = fa.apply(SPECIES.length()); + byte[] r = fr.apply(SPECIES.length()); + byte ra = (byte) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (byte) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO)); + } + } + + assertReductionArraysEquals(r, ra, a, + ByteMaxVectorTests::FIRST_NONZEROReduce, ByteMaxVectorTests::FIRST_NONZEROReduceAll); + } + static byte FIRST_NONZEROReduceMasked(byte[] a, int idx, boolean[] mask) { + byte res = (byte) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = firstNonZero(res, a[i]); + } + + return res; + } + + static byte FIRST_NONZEROReduceAllMasked(byte[] a, boolean[] mask) { + byte res = (byte) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduceMasked(a, i, mask)); + } + + return res; + } + @Test(dataProvider = "byteUnaryOpMaskProvider") + static void FIRST_NONZEROReduceByteMaxVectorTestsMasked(IntFunction fa, IntFunction fm) { + byte[] a = fa.apply(SPECIES.length()); + byte[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + byte ra = (byte) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (byte) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + ByteMaxVectorTests::FIRST_NONZEROReduceMasked, ByteMaxVectorTests::FIRST_NONZEROReduceAllMasked); + } static boolean anyTrue(boolean[] a, int idx) { boolean res = false; diff --git a/test/jdk/jdk/incubator/vector/Double128VectorTests.java b/test/jdk/jdk/incubator/vector/Double128VectorTests.java index 646570f3752..c79b1e2f4ef 100644 --- a/test/jdk/jdk/incubator/vector/Double128VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Double128VectorTests.java @@ -1299,6 +1299,10 @@ public class Double128VectorTests extends AbstractVectorTest { } + static double firstNonZero(double a, double b) { + return Double.compare(a, (double) 0) != 0 ? a : b; + } + @Test static void smokeTest1() { DoubleVector three = DoubleVector.broadcast(SPECIES, (byte)-3); @@ -2277,7 +2281,7 @@ public class Double128VectorTests extends AbstractVectorTest { static double MINReduce(double[] a, int idx) { double res = Double.POSITIVE_INFINITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (double)Math.min(res, a[i]); + res = (double) Math.min(res, a[i]); } return res; @@ -2285,8 +2289,8 @@ public class Double128VectorTests extends AbstractVectorTest { static double MINReduceAll(double[] a) { double res = Double.POSITIVE_INFINITY; - for (int i = 0; i < a.length; i++) { - res = (double)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (double) Math.min(res, MINReduce(a, i)); } return res; @@ -2308,7 +2312,7 @@ public class Double128VectorTests extends AbstractVectorTest { ra = Double.POSITIVE_INFINITY; for (int i = 0; i < a.length; i += SPECIES.length()) { DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); - ra = (double)Math.min(ra, av.reduceLanes(VectorOperators.MIN)); + ra = (double) Math.min(ra, av.reduceLanes(VectorOperators.MIN)); } } @@ -2318,8 +2322,8 @@ public class Double128VectorTests extends AbstractVectorTest { static double MINReduceMasked(double[] a, int idx, boolean[] mask) { double res = Double.POSITIVE_INFINITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (double)Math.min(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (double) Math.min(res, a[i]); } return res; @@ -2327,9 +2331,8 @@ public class Double128VectorTests extends AbstractVectorTest { static double MINReduceAllMasked(double[] a, boolean[] mask) { double res = Double.POSITIVE_INFINITY; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (double)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (double) Math.min(res, MINReduceMasked(a, i, mask)); } return res; @@ -2353,7 +2356,7 @@ public class Double128VectorTests extends AbstractVectorTest { ra = Double.POSITIVE_INFINITY; for (int i = 0; i < a.length; i += SPECIES.length()) { DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); - ra = (double)Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); + ra = (double) Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); } } @@ -2363,7 +2366,7 @@ public class Double128VectorTests extends AbstractVectorTest { static double MAXReduce(double[] a, int idx) { double res = Double.NEGATIVE_INFINITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (double)Math.max(res, a[i]); + res = (double) Math.max(res, a[i]); } return res; @@ -2371,8 +2374,8 @@ public class Double128VectorTests extends AbstractVectorTest { static double MAXReduceAll(double[] a) { double res = Double.NEGATIVE_INFINITY; - for (int i = 0; i < a.length; i++) { - res = (double)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (double) Math.max(res, MAXReduce(a, i)); } return res; @@ -2394,7 +2397,7 @@ public class Double128VectorTests extends AbstractVectorTest { ra = Double.NEGATIVE_INFINITY; for (int i = 0; i < a.length; i += SPECIES.length()) { DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); - ra = (double)Math.max(ra, av.reduceLanes(VectorOperators.MAX)); + ra = (double) Math.max(ra, av.reduceLanes(VectorOperators.MAX)); } } @@ -2404,8 +2407,8 @@ public class Double128VectorTests extends AbstractVectorTest { static double MAXReduceMasked(double[] a, int idx, boolean[] mask) { double res = Double.NEGATIVE_INFINITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (double)Math.max(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (double) Math.max(res, a[i]); } return res; @@ -2413,9 +2416,8 @@ public class Double128VectorTests extends AbstractVectorTest { static double MAXReduceAllMasked(double[] a, boolean[] mask) { double res = Double.NEGATIVE_INFINITY; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (double)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (double) Math.max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -2439,13 +2441,98 @@ public class Double128VectorTests extends AbstractVectorTest { ra = Double.NEGATIVE_INFINITY; for (int i = 0; i < a.length; i += SPECIES.length()) { DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); - ra = (double)Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); + ra = (double) Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); } } assertReductionArraysEqualsMasked(r, ra, a, mask, Double128VectorTests::MAXReduceMasked, Double128VectorTests::MAXReduceAllMasked); } + static double FIRST_NONZEROReduce(double[] a, int idx) { + double res = (double) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = firstNonZero(res, a[i]); + } + + return res; + } + + static double FIRST_NONZEROReduceAll(double[] a) { + double res = (double) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduce(a, i)); + } + + return res; + } + @Test(dataProvider = "doubleUnaryOpProvider") + static void FIRST_NONZEROReduceDouble128VectorTests(IntFunction fa) { + double[] a = fa.apply(SPECIES.length()); + double[] r = fr.apply(SPECIES.length()); + double ra = (double) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (double) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO)); + } + } + + assertReductionArraysEquals(r, ra, a, + Double128VectorTests::FIRST_NONZEROReduce, Double128VectorTests::FIRST_NONZEROReduceAll); + } + static double FIRST_NONZEROReduceMasked(double[] a, int idx, boolean[] mask) { + double res = (double) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = firstNonZero(res, a[i]); + } + + return res; + } + + static double FIRST_NONZEROReduceAllMasked(double[] a, boolean[] mask) { + double res = (double) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduceMasked(a, i, mask)); + } + + return res; + } + @Test(dataProvider = "doubleUnaryOpMaskProvider") + static void FIRST_NONZEROReduceDouble128VectorTestsMasked(IntFunction fa, IntFunction fm) { + double[] a = fa.apply(SPECIES.length()); + double[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + double ra = (double) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (double) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Double128VectorTests::FIRST_NONZEROReduceMasked, Double128VectorTests::FIRST_NONZEROReduceAllMasked); + } diff --git a/test/jdk/jdk/incubator/vector/Double256VectorTests.java b/test/jdk/jdk/incubator/vector/Double256VectorTests.java index a7d0a2c0b9f..6d459901d13 100644 --- a/test/jdk/jdk/incubator/vector/Double256VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Double256VectorTests.java @@ -1299,6 +1299,10 @@ public class Double256VectorTests extends AbstractVectorTest { } + static double firstNonZero(double a, double b) { + return Double.compare(a, (double) 0) != 0 ? a : b; + } + @Test static void smokeTest1() { DoubleVector three = DoubleVector.broadcast(SPECIES, (byte)-3); @@ -2277,7 +2281,7 @@ public class Double256VectorTests extends AbstractVectorTest { static double MINReduce(double[] a, int idx) { double res = Double.POSITIVE_INFINITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (double)Math.min(res, a[i]); + res = (double) Math.min(res, a[i]); } return res; @@ -2285,8 +2289,8 @@ public class Double256VectorTests extends AbstractVectorTest { static double MINReduceAll(double[] a) { double res = Double.POSITIVE_INFINITY; - for (int i = 0; i < a.length; i++) { - res = (double)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (double) Math.min(res, MINReduce(a, i)); } return res; @@ -2308,7 +2312,7 @@ public class Double256VectorTests extends AbstractVectorTest { ra = Double.POSITIVE_INFINITY; for (int i = 0; i < a.length; i += SPECIES.length()) { DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); - ra = (double)Math.min(ra, av.reduceLanes(VectorOperators.MIN)); + ra = (double) Math.min(ra, av.reduceLanes(VectorOperators.MIN)); } } @@ -2318,8 +2322,8 @@ public class Double256VectorTests extends AbstractVectorTest { static double MINReduceMasked(double[] a, int idx, boolean[] mask) { double res = Double.POSITIVE_INFINITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (double)Math.min(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (double) Math.min(res, a[i]); } return res; @@ -2327,9 +2331,8 @@ public class Double256VectorTests extends AbstractVectorTest { static double MINReduceAllMasked(double[] a, boolean[] mask) { double res = Double.POSITIVE_INFINITY; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (double)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (double) Math.min(res, MINReduceMasked(a, i, mask)); } return res; @@ -2353,7 +2356,7 @@ public class Double256VectorTests extends AbstractVectorTest { ra = Double.POSITIVE_INFINITY; for (int i = 0; i < a.length; i += SPECIES.length()) { DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); - ra = (double)Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); + ra = (double) Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); } } @@ -2363,7 +2366,7 @@ public class Double256VectorTests extends AbstractVectorTest { static double MAXReduce(double[] a, int idx) { double res = Double.NEGATIVE_INFINITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (double)Math.max(res, a[i]); + res = (double) Math.max(res, a[i]); } return res; @@ -2371,8 +2374,8 @@ public class Double256VectorTests extends AbstractVectorTest { static double MAXReduceAll(double[] a) { double res = Double.NEGATIVE_INFINITY; - for (int i = 0; i < a.length; i++) { - res = (double)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (double) Math.max(res, MAXReduce(a, i)); } return res; @@ -2394,7 +2397,7 @@ public class Double256VectorTests extends AbstractVectorTest { ra = Double.NEGATIVE_INFINITY; for (int i = 0; i < a.length; i += SPECIES.length()) { DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); - ra = (double)Math.max(ra, av.reduceLanes(VectorOperators.MAX)); + ra = (double) Math.max(ra, av.reduceLanes(VectorOperators.MAX)); } } @@ -2404,8 +2407,8 @@ public class Double256VectorTests extends AbstractVectorTest { static double MAXReduceMasked(double[] a, int idx, boolean[] mask) { double res = Double.NEGATIVE_INFINITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (double)Math.max(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (double) Math.max(res, a[i]); } return res; @@ -2413,9 +2416,8 @@ public class Double256VectorTests extends AbstractVectorTest { static double MAXReduceAllMasked(double[] a, boolean[] mask) { double res = Double.NEGATIVE_INFINITY; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (double)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (double) Math.max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -2439,13 +2441,98 @@ public class Double256VectorTests extends AbstractVectorTest { ra = Double.NEGATIVE_INFINITY; for (int i = 0; i < a.length; i += SPECIES.length()) { DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); - ra = (double)Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); + ra = (double) Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); } } assertReductionArraysEqualsMasked(r, ra, a, mask, Double256VectorTests::MAXReduceMasked, Double256VectorTests::MAXReduceAllMasked); } + static double FIRST_NONZEROReduce(double[] a, int idx) { + double res = (double) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = firstNonZero(res, a[i]); + } + + return res; + } + + static double FIRST_NONZEROReduceAll(double[] a) { + double res = (double) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduce(a, i)); + } + + return res; + } + @Test(dataProvider = "doubleUnaryOpProvider") + static void FIRST_NONZEROReduceDouble256VectorTests(IntFunction fa) { + double[] a = fa.apply(SPECIES.length()); + double[] r = fr.apply(SPECIES.length()); + double ra = (double) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (double) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO)); + } + } + + assertReductionArraysEquals(r, ra, a, + Double256VectorTests::FIRST_NONZEROReduce, Double256VectorTests::FIRST_NONZEROReduceAll); + } + static double FIRST_NONZEROReduceMasked(double[] a, int idx, boolean[] mask) { + double res = (double) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = firstNonZero(res, a[i]); + } + + return res; + } + + static double FIRST_NONZEROReduceAllMasked(double[] a, boolean[] mask) { + double res = (double) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduceMasked(a, i, mask)); + } + + return res; + } + @Test(dataProvider = "doubleUnaryOpMaskProvider") + static void FIRST_NONZEROReduceDouble256VectorTestsMasked(IntFunction fa, IntFunction fm) { + double[] a = fa.apply(SPECIES.length()); + double[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + double ra = (double) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (double) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Double256VectorTests::FIRST_NONZEROReduceMasked, Double256VectorTests::FIRST_NONZEROReduceAllMasked); + } diff --git a/test/jdk/jdk/incubator/vector/Double512VectorTests.java b/test/jdk/jdk/incubator/vector/Double512VectorTests.java index 26a699454bc..82299753e65 100644 --- a/test/jdk/jdk/incubator/vector/Double512VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Double512VectorTests.java @@ -1299,6 +1299,10 @@ public class Double512VectorTests extends AbstractVectorTest { } + static double firstNonZero(double a, double b) { + return Double.compare(a, (double) 0) != 0 ? a : b; + } + @Test static void smokeTest1() { DoubleVector three = DoubleVector.broadcast(SPECIES, (byte)-3); @@ -2277,7 +2281,7 @@ public class Double512VectorTests extends AbstractVectorTest { static double MINReduce(double[] a, int idx) { double res = Double.POSITIVE_INFINITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (double)Math.min(res, a[i]); + res = (double) Math.min(res, a[i]); } return res; @@ -2285,8 +2289,8 @@ public class Double512VectorTests extends AbstractVectorTest { static double MINReduceAll(double[] a) { double res = Double.POSITIVE_INFINITY; - for (int i = 0; i < a.length; i++) { - res = (double)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (double) Math.min(res, MINReduce(a, i)); } return res; @@ -2308,7 +2312,7 @@ public class Double512VectorTests extends AbstractVectorTest { ra = Double.POSITIVE_INFINITY; for (int i = 0; i < a.length; i += SPECIES.length()) { DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); - ra = (double)Math.min(ra, av.reduceLanes(VectorOperators.MIN)); + ra = (double) Math.min(ra, av.reduceLanes(VectorOperators.MIN)); } } @@ -2318,8 +2322,8 @@ public class Double512VectorTests extends AbstractVectorTest { static double MINReduceMasked(double[] a, int idx, boolean[] mask) { double res = Double.POSITIVE_INFINITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (double)Math.min(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (double) Math.min(res, a[i]); } return res; @@ -2327,9 +2331,8 @@ public class Double512VectorTests extends AbstractVectorTest { static double MINReduceAllMasked(double[] a, boolean[] mask) { double res = Double.POSITIVE_INFINITY; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (double)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (double) Math.min(res, MINReduceMasked(a, i, mask)); } return res; @@ -2353,7 +2356,7 @@ public class Double512VectorTests extends AbstractVectorTest { ra = Double.POSITIVE_INFINITY; for (int i = 0; i < a.length; i += SPECIES.length()) { DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); - ra = (double)Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); + ra = (double) Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); } } @@ -2363,7 +2366,7 @@ public class Double512VectorTests extends AbstractVectorTest { static double MAXReduce(double[] a, int idx) { double res = Double.NEGATIVE_INFINITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (double)Math.max(res, a[i]); + res = (double) Math.max(res, a[i]); } return res; @@ -2371,8 +2374,8 @@ public class Double512VectorTests extends AbstractVectorTest { static double MAXReduceAll(double[] a) { double res = Double.NEGATIVE_INFINITY; - for (int i = 0; i < a.length; i++) { - res = (double)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (double) Math.max(res, MAXReduce(a, i)); } return res; @@ -2394,7 +2397,7 @@ public class Double512VectorTests extends AbstractVectorTest { ra = Double.NEGATIVE_INFINITY; for (int i = 0; i < a.length; i += SPECIES.length()) { DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); - ra = (double)Math.max(ra, av.reduceLanes(VectorOperators.MAX)); + ra = (double) Math.max(ra, av.reduceLanes(VectorOperators.MAX)); } } @@ -2404,8 +2407,8 @@ public class Double512VectorTests extends AbstractVectorTest { static double MAXReduceMasked(double[] a, int idx, boolean[] mask) { double res = Double.NEGATIVE_INFINITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (double)Math.max(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (double) Math.max(res, a[i]); } return res; @@ -2413,9 +2416,8 @@ public class Double512VectorTests extends AbstractVectorTest { static double MAXReduceAllMasked(double[] a, boolean[] mask) { double res = Double.NEGATIVE_INFINITY; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (double)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (double) Math.max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -2439,13 +2441,98 @@ public class Double512VectorTests extends AbstractVectorTest { ra = Double.NEGATIVE_INFINITY; for (int i = 0; i < a.length; i += SPECIES.length()) { DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); - ra = (double)Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); + ra = (double) Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); } } assertReductionArraysEqualsMasked(r, ra, a, mask, Double512VectorTests::MAXReduceMasked, Double512VectorTests::MAXReduceAllMasked); } + static double FIRST_NONZEROReduce(double[] a, int idx) { + double res = (double) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = firstNonZero(res, a[i]); + } + + return res; + } + + static double FIRST_NONZEROReduceAll(double[] a) { + double res = (double) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduce(a, i)); + } + + return res; + } + @Test(dataProvider = "doubleUnaryOpProvider") + static void FIRST_NONZEROReduceDouble512VectorTests(IntFunction fa) { + double[] a = fa.apply(SPECIES.length()); + double[] r = fr.apply(SPECIES.length()); + double ra = (double) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (double) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO)); + } + } + + assertReductionArraysEquals(r, ra, a, + Double512VectorTests::FIRST_NONZEROReduce, Double512VectorTests::FIRST_NONZEROReduceAll); + } + static double FIRST_NONZEROReduceMasked(double[] a, int idx, boolean[] mask) { + double res = (double) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = firstNonZero(res, a[i]); + } + + return res; + } + + static double FIRST_NONZEROReduceAllMasked(double[] a, boolean[] mask) { + double res = (double) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduceMasked(a, i, mask)); + } + + return res; + } + @Test(dataProvider = "doubleUnaryOpMaskProvider") + static void FIRST_NONZEROReduceDouble512VectorTestsMasked(IntFunction fa, IntFunction fm) { + double[] a = fa.apply(SPECIES.length()); + double[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + double ra = (double) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (double) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Double512VectorTests::FIRST_NONZEROReduceMasked, Double512VectorTests::FIRST_NONZEROReduceAllMasked); + } diff --git a/test/jdk/jdk/incubator/vector/Double64VectorTests.java b/test/jdk/jdk/incubator/vector/Double64VectorTests.java index 017889f8b9a..82fd826ffcb 100644 --- a/test/jdk/jdk/incubator/vector/Double64VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Double64VectorTests.java @@ -1299,6 +1299,10 @@ public class Double64VectorTests extends AbstractVectorTest { } + static double firstNonZero(double a, double b) { + return Double.compare(a, (double) 0) != 0 ? a : b; + } + @Test static void smokeTest1() { DoubleVector three = DoubleVector.broadcast(SPECIES, (byte)-3); @@ -2277,7 +2281,7 @@ public class Double64VectorTests extends AbstractVectorTest { static double MINReduce(double[] a, int idx) { double res = Double.POSITIVE_INFINITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (double)Math.min(res, a[i]); + res = (double) Math.min(res, a[i]); } return res; @@ -2285,8 +2289,8 @@ public class Double64VectorTests extends AbstractVectorTest { static double MINReduceAll(double[] a) { double res = Double.POSITIVE_INFINITY; - for (int i = 0; i < a.length; i++) { - res = (double)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (double) Math.min(res, MINReduce(a, i)); } return res; @@ -2308,7 +2312,7 @@ public class Double64VectorTests extends AbstractVectorTest { ra = Double.POSITIVE_INFINITY; for (int i = 0; i < a.length; i += SPECIES.length()) { DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); - ra = (double)Math.min(ra, av.reduceLanes(VectorOperators.MIN)); + ra = (double) Math.min(ra, av.reduceLanes(VectorOperators.MIN)); } } @@ -2318,8 +2322,8 @@ public class Double64VectorTests extends AbstractVectorTest { static double MINReduceMasked(double[] a, int idx, boolean[] mask) { double res = Double.POSITIVE_INFINITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (double)Math.min(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (double) Math.min(res, a[i]); } return res; @@ -2327,9 +2331,8 @@ public class Double64VectorTests extends AbstractVectorTest { static double MINReduceAllMasked(double[] a, boolean[] mask) { double res = Double.POSITIVE_INFINITY; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (double)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (double) Math.min(res, MINReduceMasked(a, i, mask)); } return res; @@ -2353,7 +2356,7 @@ public class Double64VectorTests extends AbstractVectorTest { ra = Double.POSITIVE_INFINITY; for (int i = 0; i < a.length; i += SPECIES.length()) { DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); - ra = (double)Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); + ra = (double) Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); } } @@ -2363,7 +2366,7 @@ public class Double64VectorTests extends AbstractVectorTest { static double MAXReduce(double[] a, int idx) { double res = Double.NEGATIVE_INFINITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (double)Math.max(res, a[i]); + res = (double) Math.max(res, a[i]); } return res; @@ -2371,8 +2374,8 @@ public class Double64VectorTests extends AbstractVectorTest { static double MAXReduceAll(double[] a) { double res = Double.NEGATIVE_INFINITY; - for (int i = 0; i < a.length; i++) { - res = (double)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (double) Math.max(res, MAXReduce(a, i)); } return res; @@ -2394,7 +2397,7 @@ public class Double64VectorTests extends AbstractVectorTest { ra = Double.NEGATIVE_INFINITY; for (int i = 0; i < a.length; i += SPECIES.length()) { DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); - ra = (double)Math.max(ra, av.reduceLanes(VectorOperators.MAX)); + ra = (double) Math.max(ra, av.reduceLanes(VectorOperators.MAX)); } } @@ -2404,8 +2407,8 @@ public class Double64VectorTests extends AbstractVectorTest { static double MAXReduceMasked(double[] a, int idx, boolean[] mask) { double res = Double.NEGATIVE_INFINITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (double)Math.max(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (double) Math.max(res, a[i]); } return res; @@ -2413,9 +2416,8 @@ public class Double64VectorTests extends AbstractVectorTest { static double MAXReduceAllMasked(double[] a, boolean[] mask) { double res = Double.NEGATIVE_INFINITY; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (double)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (double) Math.max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -2439,13 +2441,98 @@ public class Double64VectorTests extends AbstractVectorTest { ra = Double.NEGATIVE_INFINITY; for (int i = 0; i < a.length; i += SPECIES.length()) { DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); - ra = (double)Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); + ra = (double) Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); } } assertReductionArraysEqualsMasked(r, ra, a, mask, Double64VectorTests::MAXReduceMasked, Double64VectorTests::MAXReduceAllMasked); } + static double FIRST_NONZEROReduce(double[] a, int idx) { + double res = (double) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = firstNonZero(res, a[i]); + } + + return res; + } + + static double FIRST_NONZEROReduceAll(double[] a) { + double res = (double) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduce(a, i)); + } + + return res; + } + @Test(dataProvider = "doubleUnaryOpProvider") + static void FIRST_NONZEROReduceDouble64VectorTests(IntFunction fa) { + double[] a = fa.apply(SPECIES.length()); + double[] r = fr.apply(SPECIES.length()); + double ra = (double) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (double) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO)); + } + } + + assertReductionArraysEquals(r, ra, a, + Double64VectorTests::FIRST_NONZEROReduce, Double64VectorTests::FIRST_NONZEROReduceAll); + } + static double FIRST_NONZEROReduceMasked(double[] a, int idx, boolean[] mask) { + double res = (double) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = firstNonZero(res, a[i]); + } + + return res; + } + + static double FIRST_NONZEROReduceAllMasked(double[] a, boolean[] mask) { + double res = (double) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduceMasked(a, i, mask)); + } + + return res; + } + @Test(dataProvider = "doubleUnaryOpMaskProvider") + static void FIRST_NONZEROReduceDouble64VectorTestsMasked(IntFunction fa, IntFunction fm) { + double[] a = fa.apply(SPECIES.length()); + double[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + double ra = (double) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (double) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Double64VectorTests::FIRST_NONZEROReduceMasked, Double64VectorTests::FIRST_NONZEROReduceAllMasked); + } diff --git a/test/jdk/jdk/incubator/vector/DoubleMaxVectorTests.java b/test/jdk/jdk/incubator/vector/DoubleMaxVectorTests.java index c4eb2b2182b..af9054efbb0 100644 --- a/test/jdk/jdk/incubator/vector/DoubleMaxVectorTests.java +++ b/test/jdk/jdk/incubator/vector/DoubleMaxVectorTests.java @@ -1304,6 +1304,10 @@ public class DoubleMaxVectorTests extends AbstractVectorTest { } + static double firstNonZero(double a, double b) { + return Double.compare(a, (double) 0) != 0 ? a : b; + } + @Test static void smokeTest1() { DoubleVector three = DoubleVector.broadcast(SPECIES, (byte)-3); @@ -2282,7 +2286,7 @@ public class DoubleMaxVectorTests extends AbstractVectorTest { static double MINReduce(double[] a, int idx) { double res = Double.POSITIVE_INFINITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (double)Math.min(res, a[i]); + res = (double) Math.min(res, a[i]); } return res; @@ -2290,8 +2294,8 @@ public class DoubleMaxVectorTests extends AbstractVectorTest { static double MINReduceAll(double[] a) { double res = Double.POSITIVE_INFINITY; - for (int i = 0; i < a.length; i++) { - res = (double)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (double) Math.min(res, MINReduce(a, i)); } return res; @@ -2313,7 +2317,7 @@ public class DoubleMaxVectorTests extends AbstractVectorTest { ra = Double.POSITIVE_INFINITY; for (int i = 0; i < a.length; i += SPECIES.length()) { DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); - ra = (double)Math.min(ra, av.reduceLanes(VectorOperators.MIN)); + ra = (double) Math.min(ra, av.reduceLanes(VectorOperators.MIN)); } } @@ -2323,8 +2327,8 @@ public class DoubleMaxVectorTests extends AbstractVectorTest { static double MINReduceMasked(double[] a, int idx, boolean[] mask) { double res = Double.POSITIVE_INFINITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (double)Math.min(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (double) Math.min(res, a[i]); } return res; @@ -2332,9 +2336,8 @@ public class DoubleMaxVectorTests extends AbstractVectorTest { static double MINReduceAllMasked(double[] a, boolean[] mask) { double res = Double.POSITIVE_INFINITY; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (double)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (double) Math.min(res, MINReduceMasked(a, i, mask)); } return res; @@ -2358,7 +2361,7 @@ public class DoubleMaxVectorTests extends AbstractVectorTest { ra = Double.POSITIVE_INFINITY; for (int i = 0; i < a.length; i += SPECIES.length()) { DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); - ra = (double)Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); + ra = (double) Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); } } @@ -2368,7 +2371,7 @@ public class DoubleMaxVectorTests extends AbstractVectorTest { static double MAXReduce(double[] a, int idx) { double res = Double.NEGATIVE_INFINITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (double)Math.max(res, a[i]); + res = (double) Math.max(res, a[i]); } return res; @@ -2376,8 +2379,8 @@ public class DoubleMaxVectorTests extends AbstractVectorTest { static double MAXReduceAll(double[] a) { double res = Double.NEGATIVE_INFINITY; - for (int i = 0; i < a.length; i++) { - res = (double)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (double) Math.max(res, MAXReduce(a, i)); } return res; @@ -2399,7 +2402,7 @@ public class DoubleMaxVectorTests extends AbstractVectorTest { ra = Double.NEGATIVE_INFINITY; for (int i = 0; i < a.length; i += SPECIES.length()) { DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); - ra = (double)Math.max(ra, av.reduceLanes(VectorOperators.MAX)); + ra = (double) Math.max(ra, av.reduceLanes(VectorOperators.MAX)); } } @@ -2409,8 +2412,8 @@ public class DoubleMaxVectorTests extends AbstractVectorTest { static double MAXReduceMasked(double[] a, int idx, boolean[] mask) { double res = Double.NEGATIVE_INFINITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (double)Math.max(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (double) Math.max(res, a[i]); } return res; @@ -2418,9 +2421,8 @@ public class DoubleMaxVectorTests extends AbstractVectorTest { static double MAXReduceAllMasked(double[] a, boolean[] mask) { double res = Double.NEGATIVE_INFINITY; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (double)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (double) Math.max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -2444,13 +2446,98 @@ public class DoubleMaxVectorTests extends AbstractVectorTest { ra = Double.NEGATIVE_INFINITY; for (int i = 0; i < a.length; i += SPECIES.length()) { DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); - ra = (double)Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); + ra = (double) Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); } } assertReductionArraysEqualsMasked(r, ra, a, mask, DoubleMaxVectorTests::MAXReduceMasked, DoubleMaxVectorTests::MAXReduceAllMasked); } + static double FIRST_NONZEROReduce(double[] a, int idx) { + double res = (double) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = firstNonZero(res, a[i]); + } + + return res; + } + + static double FIRST_NONZEROReduceAll(double[] a) { + double res = (double) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduce(a, i)); + } + + return res; + } + @Test(dataProvider = "doubleUnaryOpProvider") + static void FIRST_NONZEROReduceDoubleMaxVectorTests(IntFunction fa) { + double[] a = fa.apply(SPECIES.length()); + double[] r = fr.apply(SPECIES.length()); + double ra = (double) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (double) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO)); + } + } + + assertReductionArraysEquals(r, ra, a, + DoubleMaxVectorTests::FIRST_NONZEROReduce, DoubleMaxVectorTests::FIRST_NONZEROReduceAll); + } + static double FIRST_NONZEROReduceMasked(double[] a, int idx, boolean[] mask) { + double res = (double) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = firstNonZero(res, a[i]); + } + + return res; + } + + static double FIRST_NONZEROReduceAllMasked(double[] a, boolean[] mask) { + double res = (double) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduceMasked(a, i, mask)); + } + + return res; + } + @Test(dataProvider = "doubleUnaryOpMaskProvider") + static void FIRST_NONZEROReduceDoubleMaxVectorTestsMasked(IntFunction fa, IntFunction fm) { + double[] a = fa.apply(SPECIES.length()); + double[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + double ra = (double) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (double) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + DoubleMaxVectorTests::FIRST_NONZEROReduceMasked, DoubleMaxVectorTests::FIRST_NONZEROReduceAllMasked); + } diff --git a/test/jdk/jdk/incubator/vector/Float128VectorTests.java b/test/jdk/jdk/incubator/vector/Float128VectorTests.java index b3e7b05d2a2..c793515b6c6 100644 --- a/test/jdk/jdk/incubator/vector/Float128VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Float128VectorTests.java @@ -1309,6 +1309,10 @@ public class Float128VectorTests extends AbstractVectorTest { } + static float firstNonZero(float a, float b) { + return Float.compare(a, (float) 0) != 0 ? a : b; + } + @Test static void smokeTest1() { FloatVector three = FloatVector.broadcast(SPECIES, (byte)-3); @@ -2287,7 +2291,7 @@ public class Float128VectorTests extends AbstractVectorTest { static float MINReduce(float[] a, int idx) { float res = Float.POSITIVE_INFINITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (float)Math.min(res, a[i]); + res = (float) Math.min(res, a[i]); } return res; @@ -2295,8 +2299,8 @@ public class Float128VectorTests extends AbstractVectorTest { static float MINReduceAll(float[] a) { float res = Float.POSITIVE_INFINITY; - for (int i = 0; i < a.length; i++) { - res = (float)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (float) Math.min(res, MINReduce(a, i)); } return res; @@ -2318,7 +2322,7 @@ public class Float128VectorTests extends AbstractVectorTest { ra = Float.POSITIVE_INFINITY; for (int i = 0; i < a.length; i += SPECIES.length()) { FloatVector av = FloatVector.fromArray(SPECIES, a, i); - ra = (float)Math.min(ra, av.reduceLanes(VectorOperators.MIN)); + ra = (float) Math.min(ra, av.reduceLanes(VectorOperators.MIN)); } } @@ -2328,8 +2332,8 @@ public class Float128VectorTests extends AbstractVectorTest { static float MINReduceMasked(float[] a, int idx, boolean[] mask) { float res = Float.POSITIVE_INFINITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (float)Math.min(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (float) Math.min(res, a[i]); } return res; @@ -2337,9 +2341,8 @@ public class Float128VectorTests extends AbstractVectorTest { static float MINReduceAllMasked(float[] a, boolean[] mask) { float res = Float.POSITIVE_INFINITY; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (float)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (float) Math.min(res, MINReduceMasked(a, i, mask)); } return res; @@ -2363,7 +2366,7 @@ public class Float128VectorTests extends AbstractVectorTest { ra = Float.POSITIVE_INFINITY; for (int i = 0; i < a.length; i += SPECIES.length()) { FloatVector av = FloatVector.fromArray(SPECIES, a, i); - ra = (float)Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); + ra = (float) Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); } } @@ -2373,7 +2376,7 @@ public class Float128VectorTests extends AbstractVectorTest { static float MAXReduce(float[] a, int idx) { float res = Float.NEGATIVE_INFINITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (float)Math.max(res, a[i]); + res = (float) Math.max(res, a[i]); } return res; @@ -2381,8 +2384,8 @@ public class Float128VectorTests extends AbstractVectorTest { static float MAXReduceAll(float[] a) { float res = Float.NEGATIVE_INFINITY; - for (int i = 0; i < a.length; i++) { - res = (float)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (float) Math.max(res, MAXReduce(a, i)); } return res; @@ -2404,7 +2407,7 @@ public class Float128VectorTests extends AbstractVectorTest { ra = Float.NEGATIVE_INFINITY; for (int i = 0; i < a.length; i += SPECIES.length()) { FloatVector av = FloatVector.fromArray(SPECIES, a, i); - ra = (float)Math.max(ra, av.reduceLanes(VectorOperators.MAX)); + ra = (float) Math.max(ra, av.reduceLanes(VectorOperators.MAX)); } } @@ -2414,8 +2417,8 @@ public class Float128VectorTests extends AbstractVectorTest { static float MAXReduceMasked(float[] a, int idx, boolean[] mask) { float res = Float.NEGATIVE_INFINITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (float)Math.max(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (float) Math.max(res, a[i]); } return res; @@ -2423,9 +2426,8 @@ public class Float128VectorTests extends AbstractVectorTest { static float MAXReduceAllMasked(float[] a, boolean[] mask) { float res = Float.NEGATIVE_INFINITY; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (float)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (float) Math.max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -2449,13 +2451,98 @@ public class Float128VectorTests extends AbstractVectorTest { ra = Float.NEGATIVE_INFINITY; for (int i = 0; i < a.length; i += SPECIES.length()) { FloatVector av = FloatVector.fromArray(SPECIES, a, i); - ra = (float)Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); + ra = (float) Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); } } assertReductionArraysEqualsMasked(r, ra, a, mask, Float128VectorTests::MAXReduceMasked, Float128VectorTests::MAXReduceAllMasked); } + static float FIRST_NONZEROReduce(float[] a, int idx) { + float res = (float) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = firstNonZero(res, a[i]); + } + + return res; + } + + static float FIRST_NONZEROReduceAll(float[] a) { + float res = (float) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduce(a, i)); + } + + return res; + } + @Test(dataProvider = "floatUnaryOpProvider") + static void FIRST_NONZEROReduceFloat128VectorTests(IntFunction fa) { + float[] a = fa.apply(SPECIES.length()); + float[] r = fr.apply(SPECIES.length()); + float ra = (float) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + FloatVector av = FloatVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (float) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + FloatVector av = FloatVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO)); + } + } + + assertReductionArraysEquals(r, ra, a, + Float128VectorTests::FIRST_NONZEROReduce, Float128VectorTests::FIRST_NONZEROReduceAll); + } + static float FIRST_NONZEROReduceMasked(float[] a, int idx, boolean[] mask) { + float res = (float) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = firstNonZero(res, a[i]); + } + + return res; + } + + static float FIRST_NONZEROReduceAllMasked(float[] a, boolean[] mask) { + float res = (float) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduceMasked(a, i, mask)); + } + + return res; + } + @Test(dataProvider = "floatUnaryOpMaskProvider") + static void FIRST_NONZEROReduceFloat128VectorTestsMasked(IntFunction fa, IntFunction fm) { + float[] a = fa.apply(SPECIES.length()); + float[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + float ra = (float) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + FloatVector av = FloatVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (float) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + FloatVector av = FloatVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Float128VectorTests::FIRST_NONZEROReduceMasked, Float128VectorTests::FIRST_NONZEROReduceAllMasked); + } diff --git a/test/jdk/jdk/incubator/vector/Float256VectorTests.java b/test/jdk/jdk/incubator/vector/Float256VectorTests.java index 120fc4cabd2..61593a8c23a 100644 --- a/test/jdk/jdk/incubator/vector/Float256VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Float256VectorTests.java @@ -1309,6 +1309,10 @@ public class Float256VectorTests extends AbstractVectorTest { } + static float firstNonZero(float a, float b) { + return Float.compare(a, (float) 0) != 0 ? a : b; + } + @Test static void smokeTest1() { FloatVector three = FloatVector.broadcast(SPECIES, (byte)-3); @@ -2287,7 +2291,7 @@ public class Float256VectorTests extends AbstractVectorTest { static float MINReduce(float[] a, int idx) { float res = Float.POSITIVE_INFINITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (float)Math.min(res, a[i]); + res = (float) Math.min(res, a[i]); } return res; @@ -2295,8 +2299,8 @@ public class Float256VectorTests extends AbstractVectorTest { static float MINReduceAll(float[] a) { float res = Float.POSITIVE_INFINITY; - for (int i = 0; i < a.length; i++) { - res = (float)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (float) Math.min(res, MINReduce(a, i)); } return res; @@ -2318,7 +2322,7 @@ public class Float256VectorTests extends AbstractVectorTest { ra = Float.POSITIVE_INFINITY; for (int i = 0; i < a.length; i += SPECIES.length()) { FloatVector av = FloatVector.fromArray(SPECIES, a, i); - ra = (float)Math.min(ra, av.reduceLanes(VectorOperators.MIN)); + ra = (float) Math.min(ra, av.reduceLanes(VectorOperators.MIN)); } } @@ -2328,8 +2332,8 @@ public class Float256VectorTests extends AbstractVectorTest { static float MINReduceMasked(float[] a, int idx, boolean[] mask) { float res = Float.POSITIVE_INFINITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (float)Math.min(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (float) Math.min(res, a[i]); } return res; @@ -2337,9 +2341,8 @@ public class Float256VectorTests extends AbstractVectorTest { static float MINReduceAllMasked(float[] a, boolean[] mask) { float res = Float.POSITIVE_INFINITY; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (float)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (float) Math.min(res, MINReduceMasked(a, i, mask)); } return res; @@ -2363,7 +2366,7 @@ public class Float256VectorTests extends AbstractVectorTest { ra = Float.POSITIVE_INFINITY; for (int i = 0; i < a.length; i += SPECIES.length()) { FloatVector av = FloatVector.fromArray(SPECIES, a, i); - ra = (float)Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); + ra = (float) Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); } } @@ -2373,7 +2376,7 @@ public class Float256VectorTests extends AbstractVectorTest { static float MAXReduce(float[] a, int idx) { float res = Float.NEGATIVE_INFINITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (float)Math.max(res, a[i]); + res = (float) Math.max(res, a[i]); } return res; @@ -2381,8 +2384,8 @@ public class Float256VectorTests extends AbstractVectorTest { static float MAXReduceAll(float[] a) { float res = Float.NEGATIVE_INFINITY; - for (int i = 0; i < a.length; i++) { - res = (float)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (float) Math.max(res, MAXReduce(a, i)); } return res; @@ -2404,7 +2407,7 @@ public class Float256VectorTests extends AbstractVectorTest { ra = Float.NEGATIVE_INFINITY; for (int i = 0; i < a.length; i += SPECIES.length()) { FloatVector av = FloatVector.fromArray(SPECIES, a, i); - ra = (float)Math.max(ra, av.reduceLanes(VectorOperators.MAX)); + ra = (float) Math.max(ra, av.reduceLanes(VectorOperators.MAX)); } } @@ -2414,8 +2417,8 @@ public class Float256VectorTests extends AbstractVectorTest { static float MAXReduceMasked(float[] a, int idx, boolean[] mask) { float res = Float.NEGATIVE_INFINITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (float)Math.max(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (float) Math.max(res, a[i]); } return res; @@ -2423,9 +2426,8 @@ public class Float256VectorTests extends AbstractVectorTest { static float MAXReduceAllMasked(float[] a, boolean[] mask) { float res = Float.NEGATIVE_INFINITY; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (float)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (float) Math.max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -2449,13 +2451,98 @@ public class Float256VectorTests extends AbstractVectorTest { ra = Float.NEGATIVE_INFINITY; for (int i = 0; i < a.length; i += SPECIES.length()) { FloatVector av = FloatVector.fromArray(SPECIES, a, i); - ra = (float)Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); + ra = (float) Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); } } assertReductionArraysEqualsMasked(r, ra, a, mask, Float256VectorTests::MAXReduceMasked, Float256VectorTests::MAXReduceAllMasked); } + static float FIRST_NONZEROReduce(float[] a, int idx) { + float res = (float) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = firstNonZero(res, a[i]); + } + + return res; + } + + static float FIRST_NONZEROReduceAll(float[] a) { + float res = (float) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduce(a, i)); + } + + return res; + } + @Test(dataProvider = "floatUnaryOpProvider") + static void FIRST_NONZEROReduceFloat256VectorTests(IntFunction fa) { + float[] a = fa.apply(SPECIES.length()); + float[] r = fr.apply(SPECIES.length()); + float ra = (float) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + FloatVector av = FloatVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (float) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + FloatVector av = FloatVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO)); + } + } + + assertReductionArraysEquals(r, ra, a, + Float256VectorTests::FIRST_NONZEROReduce, Float256VectorTests::FIRST_NONZEROReduceAll); + } + static float FIRST_NONZEROReduceMasked(float[] a, int idx, boolean[] mask) { + float res = (float) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = firstNonZero(res, a[i]); + } + + return res; + } + + static float FIRST_NONZEROReduceAllMasked(float[] a, boolean[] mask) { + float res = (float) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduceMasked(a, i, mask)); + } + + return res; + } + @Test(dataProvider = "floatUnaryOpMaskProvider") + static void FIRST_NONZEROReduceFloat256VectorTestsMasked(IntFunction fa, IntFunction fm) { + float[] a = fa.apply(SPECIES.length()); + float[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + float ra = (float) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + FloatVector av = FloatVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (float) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + FloatVector av = FloatVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Float256VectorTests::FIRST_NONZEROReduceMasked, Float256VectorTests::FIRST_NONZEROReduceAllMasked); + } diff --git a/test/jdk/jdk/incubator/vector/Float512VectorTests.java b/test/jdk/jdk/incubator/vector/Float512VectorTests.java index 75fbccaed27..421338f053c 100644 --- a/test/jdk/jdk/incubator/vector/Float512VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Float512VectorTests.java @@ -1309,6 +1309,10 @@ public class Float512VectorTests extends AbstractVectorTest { } + static float firstNonZero(float a, float b) { + return Float.compare(a, (float) 0) != 0 ? a : b; + } + @Test static void smokeTest1() { FloatVector three = FloatVector.broadcast(SPECIES, (byte)-3); @@ -2287,7 +2291,7 @@ public class Float512VectorTests extends AbstractVectorTest { static float MINReduce(float[] a, int idx) { float res = Float.POSITIVE_INFINITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (float)Math.min(res, a[i]); + res = (float) Math.min(res, a[i]); } return res; @@ -2295,8 +2299,8 @@ public class Float512VectorTests extends AbstractVectorTest { static float MINReduceAll(float[] a) { float res = Float.POSITIVE_INFINITY; - for (int i = 0; i < a.length; i++) { - res = (float)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (float) Math.min(res, MINReduce(a, i)); } return res; @@ -2318,7 +2322,7 @@ public class Float512VectorTests extends AbstractVectorTest { ra = Float.POSITIVE_INFINITY; for (int i = 0; i < a.length; i += SPECIES.length()) { FloatVector av = FloatVector.fromArray(SPECIES, a, i); - ra = (float)Math.min(ra, av.reduceLanes(VectorOperators.MIN)); + ra = (float) Math.min(ra, av.reduceLanes(VectorOperators.MIN)); } } @@ -2328,8 +2332,8 @@ public class Float512VectorTests extends AbstractVectorTest { static float MINReduceMasked(float[] a, int idx, boolean[] mask) { float res = Float.POSITIVE_INFINITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (float)Math.min(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (float) Math.min(res, a[i]); } return res; @@ -2337,9 +2341,8 @@ public class Float512VectorTests extends AbstractVectorTest { static float MINReduceAllMasked(float[] a, boolean[] mask) { float res = Float.POSITIVE_INFINITY; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (float)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (float) Math.min(res, MINReduceMasked(a, i, mask)); } return res; @@ -2363,7 +2366,7 @@ public class Float512VectorTests extends AbstractVectorTest { ra = Float.POSITIVE_INFINITY; for (int i = 0; i < a.length; i += SPECIES.length()) { FloatVector av = FloatVector.fromArray(SPECIES, a, i); - ra = (float)Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); + ra = (float) Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); } } @@ -2373,7 +2376,7 @@ public class Float512VectorTests extends AbstractVectorTest { static float MAXReduce(float[] a, int idx) { float res = Float.NEGATIVE_INFINITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (float)Math.max(res, a[i]); + res = (float) Math.max(res, a[i]); } return res; @@ -2381,8 +2384,8 @@ public class Float512VectorTests extends AbstractVectorTest { static float MAXReduceAll(float[] a) { float res = Float.NEGATIVE_INFINITY; - for (int i = 0; i < a.length; i++) { - res = (float)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (float) Math.max(res, MAXReduce(a, i)); } return res; @@ -2404,7 +2407,7 @@ public class Float512VectorTests extends AbstractVectorTest { ra = Float.NEGATIVE_INFINITY; for (int i = 0; i < a.length; i += SPECIES.length()) { FloatVector av = FloatVector.fromArray(SPECIES, a, i); - ra = (float)Math.max(ra, av.reduceLanes(VectorOperators.MAX)); + ra = (float) Math.max(ra, av.reduceLanes(VectorOperators.MAX)); } } @@ -2414,8 +2417,8 @@ public class Float512VectorTests extends AbstractVectorTest { static float MAXReduceMasked(float[] a, int idx, boolean[] mask) { float res = Float.NEGATIVE_INFINITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (float)Math.max(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (float) Math.max(res, a[i]); } return res; @@ -2423,9 +2426,8 @@ public class Float512VectorTests extends AbstractVectorTest { static float MAXReduceAllMasked(float[] a, boolean[] mask) { float res = Float.NEGATIVE_INFINITY; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (float)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (float) Math.max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -2449,13 +2451,98 @@ public class Float512VectorTests extends AbstractVectorTest { ra = Float.NEGATIVE_INFINITY; for (int i = 0; i < a.length; i += SPECIES.length()) { FloatVector av = FloatVector.fromArray(SPECIES, a, i); - ra = (float)Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); + ra = (float) Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); } } assertReductionArraysEqualsMasked(r, ra, a, mask, Float512VectorTests::MAXReduceMasked, Float512VectorTests::MAXReduceAllMasked); } + static float FIRST_NONZEROReduce(float[] a, int idx) { + float res = (float) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = firstNonZero(res, a[i]); + } + + return res; + } + + static float FIRST_NONZEROReduceAll(float[] a) { + float res = (float) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduce(a, i)); + } + + return res; + } + @Test(dataProvider = "floatUnaryOpProvider") + static void FIRST_NONZEROReduceFloat512VectorTests(IntFunction fa) { + float[] a = fa.apply(SPECIES.length()); + float[] r = fr.apply(SPECIES.length()); + float ra = (float) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + FloatVector av = FloatVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (float) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + FloatVector av = FloatVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO)); + } + } + + assertReductionArraysEquals(r, ra, a, + Float512VectorTests::FIRST_NONZEROReduce, Float512VectorTests::FIRST_NONZEROReduceAll); + } + static float FIRST_NONZEROReduceMasked(float[] a, int idx, boolean[] mask) { + float res = (float) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = firstNonZero(res, a[i]); + } + + return res; + } + + static float FIRST_NONZEROReduceAllMasked(float[] a, boolean[] mask) { + float res = (float) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduceMasked(a, i, mask)); + } + + return res; + } + @Test(dataProvider = "floatUnaryOpMaskProvider") + static void FIRST_NONZEROReduceFloat512VectorTestsMasked(IntFunction fa, IntFunction fm) { + float[] a = fa.apply(SPECIES.length()); + float[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + float ra = (float) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + FloatVector av = FloatVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (float) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + FloatVector av = FloatVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Float512VectorTests::FIRST_NONZEROReduceMasked, Float512VectorTests::FIRST_NONZEROReduceAllMasked); + } diff --git a/test/jdk/jdk/incubator/vector/Float64VectorTests.java b/test/jdk/jdk/incubator/vector/Float64VectorTests.java index dbe87867b9a..cbe82a7e22d 100644 --- a/test/jdk/jdk/incubator/vector/Float64VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Float64VectorTests.java @@ -1309,6 +1309,10 @@ public class Float64VectorTests extends AbstractVectorTest { } + static float firstNonZero(float a, float b) { + return Float.compare(a, (float) 0) != 0 ? a : b; + } + @Test static void smokeTest1() { FloatVector three = FloatVector.broadcast(SPECIES, (byte)-3); @@ -2287,7 +2291,7 @@ public class Float64VectorTests extends AbstractVectorTest { static float MINReduce(float[] a, int idx) { float res = Float.POSITIVE_INFINITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (float)Math.min(res, a[i]); + res = (float) Math.min(res, a[i]); } return res; @@ -2295,8 +2299,8 @@ public class Float64VectorTests extends AbstractVectorTest { static float MINReduceAll(float[] a) { float res = Float.POSITIVE_INFINITY; - for (int i = 0; i < a.length; i++) { - res = (float)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (float) Math.min(res, MINReduce(a, i)); } return res; @@ -2318,7 +2322,7 @@ public class Float64VectorTests extends AbstractVectorTest { ra = Float.POSITIVE_INFINITY; for (int i = 0; i < a.length; i += SPECIES.length()) { FloatVector av = FloatVector.fromArray(SPECIES, a, i); - ra = (float)Math.min(ra, av.reduceLanes(VectorOperators.MIN)); + ra = (float) Math.min(ra, av.reduceLanes(VectorOperators.MIN)); } } @@ -2328,8 +2332,8 @@ public class Float64VectorTests extends AbstractVectorTest { static float MINReduceMasked(float[] a, int idx, boolean[] mask) { float res = Float.POSITIVE_INFINITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (float)Math.min(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (float) Math.min(res, a[i]); } return res; @@ -2337,9 +2341,8 @@ public class Float64VectorTests extends AbstractVectorTest { static float MINReduceAllMasked(float[] a, boolean[] mask) { float res = Float.POSITIVE_INFINITY; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (float)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (float) Math.min(res, MINReduceMasked(a, i, mask)); } return res; @@ -2363,7 +2366,7 @@ public class Float64VectorTests extends AbstractVectorTest { ra = Float.POSITIVE_INFINITY; for (int i = 0; i < a.length; i += SPECIES.length()) { FloatVector av = FloatVector.fromArray(SPECIES, a, i); - ra = (float)Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); + ra = (float) Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); } } @@ -2373,7 +2376,7 @@ public class Float64VectorTests extends AbstractVectorTest { static float MAXReduce(float[] a, int idx) { float res = Float.NEGATIVE_INFINITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (float)Math.max(res, a[i]); + res = (float) Math.max(res, a[i]); } return res; @@ -2381,8 +2384,8 @@ public class Float64VectorTests extends AbstractVectorTest { static float MAXReduceAll(float[] a) { float res = Float.NEGATIVE_INFINITY; - for (int i = 0; i < a.length; i++) { - res = (float)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (float) Math.max(res, MAXReduce(a, i)); } return res; @@ -2404,7 +2407,7 @@ public class Float64VectorTests extends AbstractVectorTest { ra = Float.NEGATIVE_INFINITY; for (int i = 0; i < a.length; i += SPECIES.length()) { FloatVector av = FloatVector.fromArray(SPECIES, a, i); - ra = (float)Math.max(ra, av.reduceLanes(VectorOperators.MAX)); + ra = (float) Math.max(ra, av.reduceLanes(VectorOperators.MAX)); } } @@ -2414,8 +2417,8 @@ public class Float64VectorTests extends AbstractVectorTest { static float MAXReduceMasked(float[] a, int idx, boolean[] mask) { float res = Float.NEGATIVE_INFINITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (float)Math.max(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (float) Math.max(res, a[i]); } return res; @@ -2423,9 +2426,8 @@ public class Float64VectorTests extends AbstractVectorTest { static float MAXReduceAllMasked(float[] a, boolean[] mask) { float res = Float.NEGATIVE_INFINITY; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (float)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (float) Math.max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -2449,13 +2451,98 @@ public class Float64VectorTests extends AbstractVectorTest { ra = Float.NEGATIVE_INFINITY; for (int i = 0; i < a.length; i += SPECIES.length()) { FloatVector av = FloatVector.fromArray(SPECIES, a, i); - ra = (float)Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); + ra = (float) Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); } } assertReductionArraysEqualsMasked(r, ra, a, mask, Float64VectorTests::MAXReduceMasked, Float64VectorTests::MAXReduceAllMasked); } + static float FIRST_NONZEROReduce(float[] a, int idx) { + float res = (float) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = firstNonZero(res, a[i]); + } + + return res; + } + + static float FIRST_NONZEROReduceAll(float[] a) { + float res = (float) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduce(a, i)); + } + + return res; + } + @Test(dataProvider = "floatUnaryOpProvider") + static void FIRST_NONZEROReduceFloat64VectorTests(IntFunction fa) { + float[] a = fa.apply(SPECIES.length()); + float[] r = fr.apply(SPECIES.length()); + float ra = (float) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + FloatVector av = FloatVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (float) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + FloatVector av = FloatVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO)); + } + } + + assertReductionArraysEquals(r, ra, a, + Float64VectorTests::FIRST_NONZEROReduce, Float64VectorTests::FIRST_NONZEROReduceAll); + } + static float FIRST_NONZEROReduceMasked(float[] a, int idx, boolean[] mask) { + float res = (float) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = firstNonZero(res, a[i]); + } + + return res; + } + + static float FIRST_NONZEROReduceAllMasked(float[] a, boolean[] mask) { + float res = (float) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduceMasked(a, i, mask)); + } + + return res; + } + @Test(dataProvider = "floatUnaryOpMaskProvider") + static void FIRST_NONZEROReduceFloat64VectorTestsMasked(IntFunction fa, IntFunction fm) { + float[] a = fa.apply(SPECIES.length()); + float[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + float ra = (float) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + FloatVector av = FloatVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (float) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + FloatVector av = FloatVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Float64VectorTests::FIRST_NONZEROReduceMasked, Float64VectorTests::FIRST_NONZEROReduceAllMasked); + } diff --git a/test/jdk/jdk/incubator/vector/FloatMaxVectorTests.java b/test/jdk/jdk/incubator/vector/FloatMaxVectorTests.java index 5d3e65b765b..e8680eb1d94 100644 --- a/test/jdk/jdk/incubator/vector/FloatMaxVectorTests.java +++ b/test/jdk/jdk/incubator/vector/FloatMaxVectorTests.java @@ -1314,6 +1314,10 @@ public class FloatMaxVectorTests extends AbstractVectorTest { } + static float firstNonZero(float a, float b) { + return Float.compare(a, (float) 0) != 0 ? a : b; + } + @Test static void smokeTest1() { FloatVector three = FloatVector.broadcast(SPECIES, (byte)-3); @@ -2292,7 +2296,7 @@ public class FloatMaxVectorTests extends AbstractVectorTest { static float MINReduce(float[] a, int idx) { float res = Float.POSITIVE_INFINITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (float)Math.min(res, a[i]); + res = (float) Math.min(res, a[i]); } return res; @@ -2300,8 +2304,8 @@ public class FloatMaxVectorTests extends AbstractVectorTest { static float MINReduceAll(float[] a) { float res = Float.POSITIVE_INFINITY; - for (int i = 0; i < a.length; i++) { - res = (float)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (float) Math.min(res, MINReduce(a, i)); } return res; @@ -2323,7 +2327,7 @@ public class FloatMaxVectorTests extends AbstractVectorTest { ra = Float.POSITIVE_INFINITY; for (int i = 0; i < a.length; i += SPECIES.length()) { FloatVector av = FloatVector.fromArray(SPECIES, a, i); - ra = (float)Math.min(ra, av.reduceLanes(VectorOperators.MIN)); + ra = (float) Math.min(ra, av.reduceLanes(VectorOperators.MIN)); } } @@ -2333,8 +2337,8 @@ public class FloatMaxVectorTests extends AbstractVectorTest { static float MINReduceMasked(float[] a, int idx, boolean[] mask) { float res = Float.POSITIVE_INFINITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (float)Math.min(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (float) Math.min(res, a[i]); } return res; @@ -2342,9 +2346,8 @@ public class FloatMaxVectorTests extends AbstractVectorTest { static float MINReduceAllMasked(float[] a, boolean[] mask) { float res = Float.POSITIVE_INFINITY; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (float)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (float) Math.min(res, MINReduceMasked(a, i, mask)); } return res; @@ -2368,7 +2371,7 @@ public class FloatMaxVectorTests extends AbstractVectorTest { ra = Float.POSITIVE_INFINITY; for (int i = 0; i < a.length; i += SPECIES.length()) { FloatVector av = FloatVector.fromArray(SPECIES, a, i); - ra = (float)Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); + ra = (float) Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); } } @@ -2378,7 +2381,7 @@ public class FloatMaxVectorTests extends AbstractVectorTest { static float MAXReduce(float[] a, int idx) { float res = Float.NEGATIVE_INFINITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (float)Math.max(res, a[i]); + res = (float) Math.max(res, a[i]); } return res; @@ -2386,8 +2389,8 @@ public class FloatMaxVectorTests extends AbstractVectorTest { static float MAXReduceAll(float[] a) { float res = Float.NEGATIVE_INFINITY; - for (int i = 0; i < a.length; i++) { - res = (float)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (float) Math.max(res, MAXReduce(a, i)); } return res; @@ -2409,7 +2412,7 @@ public class FloatMaxVectorTests extends AbstractVectorTest { ra = Float.NEGATIVE_INFINITY; for (int i = 0; i < a.length; i += SPECIES.length()) { FloatVector av = FloatVector.fromArray(SPECIES, a, i); - ra = (float)Math.max(ra, av.reduceLanes(VectorOperators.MAX)); + ra = (float) Math.max(ra, av.reduceLanes(VectorOperators.MAX)); } } @@ -2419,8 +2422,8 @@ public class FloatMaxVectorTests extends AbstractVectorTest { static float MAXReduceMasked(float[] a, int idx, boolean[] mask) { float res = Float.NEGATIVE_INFINITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (float)Math.max(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (float) Math.max(res, a[i]); } return res; @@ -2428,9 +2431,8 @@ public class FloatMaxVectorTests extends AbstractVectorTest { static float MAXReduceAllMasked(float[] a, boolean[] mask) { float res = Float.NEGATIVE_INFINITY; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (float)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (float) Math.max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -2454,13 +2456,98 @@ public class FloatMaxVectorTests extends AbstractVectorTest { ra = Float.NEGATIVE_INFINITY; for (int i = 0; i < a.length; i += SPECIES.length()) { FloatVector av = FloatVector.fromArray(SPECIES, a, i); - ra = (float)Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); + ra = (float) Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); } } assertReductionArraysEqualsMasked(r, ra, a, mask, FloatMaxVectorTests::MAXReduceMasked, FloatMaxVectorTests::MAXReduceAllMasked); } + static float FIRST_NONZEROReduce(float[] a, int idx) { + float res = (float) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = firstNonZero(res, a[i]); + } + + return res; + } + + static float FIRST_NONZEROReduceAll(float[] a) { + float res = (float) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduce(a, i)); + } + + return res; + } + @Test(dataProvider = "floatUnaryOpProvider") + static void FIRST_NONZEROReduceFloatMaxVectorTests(IntFunction fa) { + float[] a = fa.apply(SPECIES.length()); + float[] r = fr.apply(SPECIES.length()); + float ra = (float) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + FloatVector av = FloatVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (float) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + FloatVector av = FloatVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO)); + } + } + + assertReductionArraysEquals(r, ra, a, + FloatMaxVectorTests::FIRST_NONZEROReduce, FloatMaxVectorTests::FIRST_NONZEROReduceAll); + } + static float FIRST_NONZEROReduceMasked(float[] a, int idx, boolean[] mask) { + float res = (float) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = firstNonZero(res, a[i]); + } + + return res; + } + + static float FIRST_NONZEROReduceAllMasked(float[] a, boolean[] mask) { + float res = (float) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduceMasked(a, i, mask)); + } + + return res; + } + @Test(dataProvider = "floatUnaryOpMaskProvider") + static void FIRST_NONZEROReduceFloatMaxVectorTestsMasked(IntFunction fa, IntFunction fm) { + float[] a = fa.apply(SPECIES.length()); + float[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + float ra = (float) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + FloatVector av = FloatVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (float) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + FloatVector av = FloatVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + FloatMaxVectorTests::FIRST_NONZEROReduceMasked, FloatMaxVectorTests::FIRST_NONZEROReduceAllMasked); + } diff --git a/test/jdk/jdk/incubator/vector/Int128VectorTests.java b/test/jdk/jdk/incubator/vector/Int128VectorTests.java index d23295f5b4e..99bc02b8239 100644 --- a/test/jdk/jdk/incubator/vector/Int128VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Int128VectorTests.java @@ -1161,6 +1161,10 @@ public class Int128VectorTests extends AbstractVectorTest { return Integer.compareUnsigned(a, b) >= 0; } + static int firstNonZero(int a, int b) { + return Integer.compare(a, (int) 0) != 0 ? a : b; + } + @Test static void smokeTest1() { IntVector three = IntVector.broadcast(SPECIES, (byte)-3); @@ -3181,7 +3185,7 @@ public class Int128VectorTests extends AbstractVectorTest { static int MINReduce(int[] a, int idx) { int res = Integer.MAX_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (int)Math.min(res, a[i]); + res = (int) Math.min(res, a[i]); } return res; @@ -3189,8 +3193,8 @@ public class Int128VectorTests extends AbstractVectorTest { static int MINReduceAll(int[] a) { int res = Integer.MAX_VALUE; - for (int i = 0; i < a.length; i++) { - res = (int)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (int) Math.min(res, MINReduce(a, i)); } return res; @@ -3212,7 +3216,7 @@ public class Int128VectorTests extends AbstractVectorTest { ra = Integer.MAX_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { IntVector av = IntVector.fromArray(SPECIES, a, i); - ra = (int)Math.min(ra, av.reduceLanes(VectorOperators.MIN)); + ra = (int) Math.min(ra, av.reduceLanes(VectorOperators.MIN)); } } @@ -3222,8 +3226,8 @@ public class Int128VectorTests extends AbstractVectorTest { static int MINReduceMasked(int[] a, int idx, boolean[] mask) { int res = Integer.MAX_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (int)Math.min(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (int) Math.min(res, a[i]); } return res; @@ -3231,9 +3235,8 @@ public class Int128VectorTests extends AbstractVectorTest { static int MINReduceAllMasked(int[] a, boolean[] mask) { int res = Integer.MAX_VALUE; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (int)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (int) Math.min(res, MINReduceMasked(a, i, mask)); } return res; @@ -3257,7 +3260,7 @@ public class Int128VectorTests extends AbstractVectorTest { ra = Integer.MAX_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { IntVector av = IntVector.fromArray(SPECIES, a, i); - ra = (int)Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); + ra = (int) Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); } } @@ -3267,7 +3270,7 @@ public class Int128VectorTests extends AbstractVectorTest { static int MAXReduce(int[] a, int idx) { int res = Integer.MIN_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (int)Math.max(res, a[i]); + res = (int) Math.max(res, a[i]); } return res; @@ -3275,8 +3278,8 @@ public class Int128VectorTests extends AbstractVectorTest { static int MAXReduceAll(int[] a) { int res = Integer.MIN_VALUE; - for (int i = 0; i < a.length; i++) { - res = (int)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (int) Math.max(res, MAXReduce(a, i)); } return res; @@ -3298,7 +3301,7 @@ public class Int128VectorTests extends AbstractVectorTest { ra = Integer.MIN_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { IntVector av = IntVector.fromArray(SPECIES, a, i); - ra = (int)Math.max(ra, av.reduceLanes(VectorOperators.MAX)); + ra = (int) Math.max(ra, av.reduceLanes(VectorOperators.MAX)); } } @@ -3308,8 +3311,8 @@ public class Int128VectorTests extends AbstractVectorTest { static int MAXReduceMasked(int[] a, int idx, boolean[] mask) { int res = Integer.MIN_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (int)Math.max(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (int) Math.max(res, a[i]); } return res; @@ -3317,9 +3320,8 @@ public class Int128VectorTests extends AbstractVectorTest { static int MAXReduceAllMasked(int[] a, boolean[] mask) { int res = Integer.MIN_VALUE; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (int)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (int) Math.max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -3343,13 +3345,98 @@ public class Int128VectorTests extends AbstractVectorTest { ra = Integer.MIN_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { IntVector av = IntVector.fromArray(SPECIES, a, i); - ra = (int)Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); + ra = (int) Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); } } assertReductionArraysEqualsMasked(r, ra, a, mask, Int128VectorTests::MAXReduceMasked, Int128VectorTests::MAXReduceAllMasked); } + static int FIRST_NONZEROReduce(int[] a, int idx) { + int res = (int) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = firstNonZero(res, a[i]); + } + + return res; + } + + static int FIRST_NONZEROReduceAll(int[] a) { + int res = (int) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduce(a, i)); + } + + return res; + } + @Test(dataProvider = "intUnaryOpProvider") + static void FIRST_NONZEROReduceInt128VectorTests(IntFunction fa) { + int[] a = fa.apply(SPECIES.length()); + int[] r = fr.apply(SPECIES.length()); + int ra = (int) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (int) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO)); + } + } + + assertReductionArraysEquals(r, ra, a, + Int128VectorTests::FIRST_NONZEROReduce, Int128VectorTests::FIRST_NONZEROReduceAll); + } + static int FIRST_NONZEROReduceMasked(int[] a, int idx, boolean[] mask) { + int res = (int) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = firstNonZero(res, a[i]); + } + + return res; + } + + static int FIRST_NONZEROReduceAllMasked(int[] a, boolean[] mask) { + int res = (int) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduceMasked(a, i, mask)); + } + + return res; + } + @Test(dataProvider = "intUnaryOpMaskProvider") + static void FIRST_NONZEROReduceInt128VectorTestsMasked(IntFunction fa, IntFunction fm) { + int[] a = fa.apply(SPECIES.length()); + int[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + int ra = (int) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (int) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Int128VectorTests::FIRST_NONZEROReduceMasked, Int128VectorTests::FIRST_NONZEROReduceAllMasked); + } static boolean anyTrue(boolean[] a, int idx) { boolean res = false; diff --git a/test/jdk/jdk/incubator/vector/Int256VectorTests.java b/test/jdk/jdk/incubator/vector/Int256VectorTests.java index f6bc1f7fd4c..e4b3f491e31 100644 --- a/test/jdk/jdk/incubator/vector/Int256VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Int256VectorTests.java @@ -1161,6 +1161,10 @@ public class Int256VectorTests extends AbstractVectorTest { return Integer.compareUnsigned(a, b) >= 0; } + static int firstNonZero(int a, int b) { + return Integer.compare(a, (int) 0) != 0 ? a : b; + } + @Test static void smokeTest1() { IntVector three = IntVector.broadcast(SPECIES, (byte)-3); @@ -3181,7 +3185,7 @@ public class Int256VectorTests extends AbstractVectorTest { static int MINReduce(int[] a, int idx) { int res = Integer.MAX_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (int)Math.min(res, a[i]); + res = (int) Math.min(res, a[i]); } return res; @@ -3189,8 +3193,8 @@ public class Int256VectorTests extends AbstractVectorTest { static int MINReduceAll(int[] a) { int res = Integer.MAX_VALUE; - for (int i = 0; i < a.length; i++) { - res = (int)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (int) Math.min(res, MINReduce(a, i)); } return res; @@ -3212,7 +3216,7 @@ public class Int256VectorTests extends AbstractVectorTest { ra = Integer.MAX_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { IntVector av = IntVector.fromArray(SPECIES, a, i); - ra = (int)Math.min(ra, av.reduceLanes(VectorOperators.MIN)); + ra = (int) Math.min(ra, av.reduceLanes(VectorOperators.MIN)); } } @@ -3222,8 +3226,8 @@ public class Int256VectorTests extends AbstractVectorTest { static int MINReduceMasked(int[] a, int idx, boolean[] mask) { int res = Integer.MAX_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (int)Math.min(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (int) Math.min(res, a[i]); } return res; @@ -3231,9 +3235,8 @@ public class Int256VectorTests extends AbstractVectorTest { static int MINReduceAllMasked(int[] a, boolean[] mask) { int res = Integer.MAX_VALUE; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (int)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (int) Math.min(res, MINReduceMasked(a, i, mask)); } return res; @@ -3257,7 +3260,7 @@ public class Int256VectorTests extends AbstractVectorTest { ra = Integer.MAX_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { IntVector av = IntVector.fromArray(SPECIES, a, i); - ra = (int)Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); + ra = (int) Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); } } @@ -3267,7 +3270,7 @@ public class Int256VectorTests extends AbstractVectorTest { static int MAXReduce(int[] a, int idx) { int res = Integer.MIN_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (int)Math.max(res, a[i]); + res = (int) Math.max(res, a[i]); } return res; @@ -3275,8 +3278,8 @@ public class Int256VectorTests extends AbstractVectorTest { static int MAXReduceAll(int[] a) { int res = Integer.MIN_VALUE; - for (int i = 0; i < a.length; i++) { - res = (int)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (int) Math.max(res, MAXReduce(a, i)); } return res; @@ -3298,7 +3301,7 @@ public class Int256VectorTests extends AbstractVectorTest { ra = Integer.MIN_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { IntVector av = IntVector.fromArray(SPECIES, a, i); - ra = (int)Math.max(ra, av.reduceLanes(VectorOperators.MAX)); + ra = (int) Math.max(ra, av.reduceLanes(VectorOperators.MAX)); } } @@ -3308,8 +3311,8 @@ public class Int256VectorTests extends AbstractVectorTest { static int MAXReduceMasked(int[] a, int idx, boolean[] mask) { int res = Integer.MIN_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (int)Math.max(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (int) Math.max(res, a[i]); } return res; @@ -3317,9 +3320,8 @@ public class Int256VectorTests extends AbstractVectorTest { static int MAXReduceAllMasked(int[] a, boolean[] mask) { int res = Integer.MIN_VALUE; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (int)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (int) Math.max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -3343,13 +3345,98 @@ public class Int256VectorTests extends AbstractVectorTest { ra = Integer.MIN_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { IntVector av = IntVector.fromArray(SPECIES, a, i); - ra = (int)Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); + ra = (int) Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); } } assertReductionArraysEqualsMasked(r, ra, a, mask, Int256VectorTests::MAXReduceMasked, Int256VectorTests::MAXReduceAllMasked); } + static int FIRST_NONZEROReduce(int[] a, int idx) { + int res = (int) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = firstNonZero(res, a[i]); + } + + return res; + } + + static int FIRST_NONZEROReduceAll(int[] a) { + int res = (int) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduce(a, i)); + } + + return res; + } + @Test(dataProvider = "intUnaryOpProvider") + static void FIRST_NONZEROReduceInt256VectorTests(IntFunction fa) { + int[] a = fa.apply(SPECIES.length()); + int[] r = fr.apply(SPECIES.length()); + int ra = (int) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (int) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO)); + } + } + + assertReductionArraysEquals(r, ra, a, + Int256VectorTests::FIRST_NONZEROReduce, Int256VectorTests::FIRST_NONZEROReduceAll); + } + static int FIRST_NONZEROReduceMasked(int[] a, int idx, boolean[] mask) { + int res = (int) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = firstNonZero(res, a[i]); + } + + return res; + } + + static int FIRST_NONZEROReduceAllMasked(int[] a, boolean[] mask) { + int res = (int) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduceMasked(a, i, mask)); + } + + return res; + } + @Test(dataProvider = "intUnaryOpMaskProvider") + static void FIRST_NONZEROReduceInt256VectorTestsMasked(IntFunction fa, IntFunction fm) { + int[] a = fa.apply(SPECIES.length()); + int[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + int ra = (int) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (int) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Int256VectorTests::FIRST_NONZEROReduceMasked, Int256VectorTests::FIRST_NONZEROReduceAllMasked); + } static boolean anyTrue(boolean[] a, int idx) { boolean res = false; diff --git a/test/jdk/jdk/incubator/vector/Int512VectorTests.java b/test/jdk/jdk/incubator/vector/Int512VectorTests.java index 7f5ce407da6..503d24ab05c 100644 --- a/test/jdk/jdk/incubator/vector/Int512VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Int512VectorTests.java @@ -1161,6 +1161,10 @@ public class Int512VectorTests extends AbstractVectorTest { return Integer.compareUnsigned(a, b) >= 0; } + static int firstNonZero(int a, int b) { + return Integer.compare(a, (int) 0) != 0 ? a : b; + } + @Test static void smokeTest1() { IntVector three = IntVector.broadcast(SPECIES, (byte)-3); @@ -3181,7 +3185,7 @@ public class Int512VectorTests extends AbstractVectorTest { static int MINReduce(int[] a, int idx) { int res = Integer.MAX_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (int)Math.min(res, a[i]); + res = (int) Math.min(res, a[i]); } return res; @@ -3189,8 +3193,8 @@ public class Int512VectorTests extends AbstractVectorTest { static int MINReduceAll(int[] a) { int res = Integer.MAX_VALUE; - for (int i = 0; i < a.length; i++) { - res = (int)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (int) Math.min(res, MINReduce(a, i)); } return res; @@ -3212,7 +3216,7 @@ public class Int512VectorTests extends AbstractVectorTest { ra = Integer.MAX_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { IntVector av = IntVector.fromArray(SPECIES, a, i); - ra = (int)Math.min(ra, av.reduceLanes(VectorOperators.MIN)); + ra = (int) Math.min(ra, av.reduceLanes(VectorOperators.MIN)); } } @@ -3222,8 +3226,8 @@ public class Int512VectorTests extends AbstractVectorTest { static int MINReduceMasked(int[] a, int idx, boolean[] mask) { int res = Integer.MAX_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (int)Math.min(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (int) Math.min(res, a[i]); } return res; @@ -3231,9 +3235,8 @@ public class Int512VectorTests extends AbstractVectorTest { static int MINReduceAllMasked(int[] a, boolean[] mask) { int res = Integer.MAX_VALUE; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (int)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (int) Math.min(res, MINReduceMasked(a, i, mask)); } return res; @@ -3257,7 +3260,7 @@ public class Int512VectorTests extends AbstractVectorTest { ra = Integer.MAX_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { IntVector av = IntVector.fromArray(SPECIES, a, i); - ra = (int)Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); + ra = (int) Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); } } @@ -3267,7 +3270,7 @@ public class Int512VectorTests extends AbstractVectorTest { static int MAXReduce(int[] a, int idx) { int res = Integer.MIN_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (int)Math.max(res, a[i]); + res = (int) Math.max(res, a[i]); } return res; @@ -3275,8 +3278,8 @@ public class Int512VectorTests extends AbstractVectorTest { static int MAXReduceAll(int[] a) { int res = Integer.MIN_VALUE; - for (int i = 0; i < a.length; i++) { - res = (int)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (int) Math.max(res, MAXReduce(a, i)); } return res; @@ -3298,7 +3301,7 @@ public class Int512VectorTests extends AbstractVectorTest { ra = Integer.MIN_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { IntVector av = IntVector.fromArray(SPECIES, a, i); - ra = (int)Math.max(ra, av.reduceLanes(VectorOperators.MAX)); + ra = (int) Math.max(ra, av.reduceLanes(VectorOperators.MAX)); } } @@ -3308,8 +3311,8 @@ public class Int512VectorTests extends AbstractVectorTest { static int MAXReduceMasked(int[] a, int idx, boolean[] mask) { int res = Integer.MIN_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (int)Math.max(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (int) Math.max(res, a[i]); } return res; @@ -3317,9 +3320,8 @@ public class Int512VectorTests extends AbstractVectorTest { static int MAXReduceAllMasked(int[] a, boolean[] mask) { int res = Integer.MIN_VALUE; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (int)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (int) Math.max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -3343,13 +3345,98 @@ public class Int512VectorTests extends AbstractVectorTest { ra = Integer.MIN_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { IntVector av = IntVector.fromArray(SPECIES, a, i); - ra = (int)Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); + ra = (int) Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); } } assertReductionArraysEqualsMasked(r, ra, a, mask, Int512VectorTests::MAXReduceMasked, Int512VectorTests::MAXReduceAllMasked); } + static int FIRST_NONZEROReduce(int[] a, int idx) { + int res = (int) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = firstNonZero(res, a[i]); + } + + return res; + } + + static int FIRST_NONZEROReduceAll(int[] a) { + int res = (int) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduce(a, i)); + } + + return res; + } + @Test(dataProvider = "intUnaryOpProvider") + static void FIRST_NONZEROReduceInt512VectorTests(IntFunction fa) { + int[] a = fa.apply(SPECIES.length()); + int[] r = fr.apply(SPECIES.length()); + int ra = (int) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (int) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO)); + } + } + + assertReductionArraysEquals(r, ra, a, + Int512VectorTests::FIRST_NONZEROReduce, Int512VectorTests::FIRST_NONZEROReduceAll); + } + static int FIRST_NONZEROReduceMasked(int[] a, int idx, boolean[] mask) { + int res = (int) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = firstNonZero(res, a[i]); + } + + return res; + } + + static int FIRST_NONZEROReduceAllMasked(int[] a, boolean[] mask) { + int res = (int) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduceMasked(a, i, mask)); + } + + return res; + } + @Test(dataProvider = "intUnaryOpMaskProvider") + static void FIRST_NONZEROReduceInt512VectorTestsMasked(IntFunction fa, IntFunction fm) { + int[] a = fa.apply(SPECIES.length()); + int[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + int ra = (int) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (int) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Int512VectorTests::FIRST_NONZEROReduceMasked, Int512VectorTests::FIRST_NONZEROReduceAllMasked); + } static boolean anyTrue(boolean[] a, int idx) { boolean res = false; diff --git a/test/jdk/jdk/incubator/vector/Int64VectorTests.java b/test/jdk/jdk/incubator/vector/Int64VectorTests.java index 6da8ecf04e4..2bebc06d0e2 100644 --- a/test/jdk/jdk/incubator/vector/Int64VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Int64VectorTests.java @@ -1161,6 +1161,10 @@ public class Int64VectorTests extends AbstractVectorTest { return Integer.compareUnsigned(a, b) >= 0; } + static int firstNonZero(int a, int b) { + return Integer.compare(a, (int) 0) != 0 ? a : b; + } + @Test static void smokeTest1() { IntVector three = IntVector.broadcast(SPECIES, (byte)-3); @@ -3181,7 +3185,7 @@ public class Int64VectorTests extends AbstractVectorTest { static int MINReduce(int[] a, int idx) { int res = Integer.MAX_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (int)Math.min(res, a[i]); + res = (int) Math.min(res, a[i]); } return res; @@ -3189,8 +3193,8 @@ public class Int64VectorTests extends AbstractVectorTest { static int MINReduceAll(int[] a) { int res = Integer.MAX_VALUE; - for (int i = 0; i < a.length; i++) { - res = (int)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (int) Math.min(res, MINReduce(a, i)); } return res; @@ -3212,7 +3216,7 @@ public class Int64VectorTests extends AbstractVectorTest { ra = Integer.MAX_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { IntVector av = IntVector.fromArray(SPECIES, a, i); - ra = (int)Math.min(ra, av.reduceLanes(VectorOperators.MIN)); + ra = (int) Math.min(ra, av.reduceLanes(VectorOperators.MIN)); } } @@ -3222,8 +3226,8 @@ public class Int64VectorTests extends AbstractVectorTest { static int MINReduceMasked(int[] a, int idx, boolean[] mask) { int res = Integer.MAX_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (int)Math.min(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (int) Math.min(res, a[i]); } return res; @@ -3231,9 +3235,8 @@ public class Int64VectorTests extends AbstractVectorTest { static int MINReduceAllMasked(int[] a, boolean[] mask) { int res = Integer.MAX_VALUE; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (int)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (int) Math.min(res, MINReduceMasked(a, i, mask)); } return res; @@ -3257,7 +3260,7 @@ public class Int64VectorTests extends AbstractVectorTest { ra = Integer.MAX_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { IntVector av = IntVector.fromArray(SPECIES, a, i); - ra = (int)Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); + ra = (int) Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); } } @@ -3267,7 +3270,7 @@ public class Int64VectorTests extends AbstractVectorTest { static int MAXReduce(int[] a, int idx) { int res = Integer.MIN_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (int)Math.max(res, a[i]); + res = (int) Math.max(res, a[i]); } return res; @@ -3275,8 +3278,8 @@ public class Int64VectorTests extends AbstractVectorTest { static int MAXReduceAll(int[] a) { int res = Integer.MIN_VALUE; - for (int i = 0; i < a.length; i++) { - res = (int)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (int) Math.max(res, MAXReduce(a, i)); } return res; @@ -3298,7 +3301,7 @@ public class Int64VectorTests extends AbstractVectorTest { ra = Integer.MIN_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { IntVector av = IntVector.fromArray(SPECIES, a, i); - ra = (int)Math.max(ra, av.reduceLanes(VectorOperators.MAX)); + ra = (int) Math.max(ra, av.reduceLanes(VectorOperators.MAX)); } } @@ -3308,8 +3311,8 @@ public class Int64VectorTests extends AbstractVectorTest { static int MAXReduceMasked(int[] a, int idx, boolean[] mask) { int res = Integer.MIN_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (int)Math.max(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (int) Math.max(res, a[i]); } return res; @@ -3317,9 +3320,8 @@ public class Int64VectorTests extends AbstractVectorTest { static int MAXReduceAllMasked(int[] a, boolean[] mask) { int res = Integer.MIN_VALUE; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (int)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (int) Math.max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -3343,13 +3345,98 @@ public class Int64VectorTests extends AbstractVectorTest { ra = Integer.MIN_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { IntVector av = IntVector.fromArray(SPECIES, a, i); - ra = (int)Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); + ra = (int) Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); } } assertReductionArraysEqualsMasked(r, ra, a, mask, Int64VectorTests::MAXReduceMasked, Int64VectorTests::MAXReduceAllMasked); } + static int FIRST_NONZEROReduce(int[] a, int idx) { + int res = (int) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = firstNonZero(res, a[i]); + } + + return res; + } + + static int FIRST_NONZEROReduceAll(int[] a) { + int res = (int) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduce(a, i)); + } + + return res; + } + @Test(dataProvider = "intUnaryOpProvider") + static void FIRST_NONZEROReduceInt64VectorTests(IntFunction fa) { + int[] a = fa.apply(SPECIES.length()); + int[] r = fr.apply(SPECIES.length()); + int ra = (int) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (int) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO)); + } + } + + assertReductionArraysEquals(r, ra, a, + Int64VectorTests::FIRST_NONZEROReduce, Int64VectorTests::FIRST_NONZEROReduceAll); + } + static int FIRST_NONZEROReduceMasked(int[] a, int idx, boolean[] mask) { + int res = (int) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = firstNonZero(res, a[i]); + } + + return res; + } + + static int FIRST_NONZEROReduceAllMasked(int[] a, boolean[] mask) { + int res = (int) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduceMasked(a, i, mask)); + } + + return res; + } + @Test(dataProvider = "intUnaryOpMaskProvider") + static void FIRST_NONZEROReduceInt64VectorTestsMasked(IntFunction fa, IntFunction fm) { + int[] a = fa.apply(SPECIES.length()); + int[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + int ra = (int) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (int) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Int64VectorTests::FIRST_NONZEROReduceMasked, Int64VectorTests::FIRST_NONZEROReduceAllMasked); + } static boolean anyTrue(boolean[] a, int idx) { boolean res = false; diff --git a/test/jdk/jdk/incubator/vector/IntMaxVectorTests.java b/test/jdk/jdk/incubator/vector/IntMaxVectorTests.java index 0e59f7f0ed5..faf232e2985 100644 --- a/test/jdk/jdk/incubator/vector/IntMaxVectorTests.java +++ b/test/jdk/jdk/incubator/vector/IntMaxVectorTests.java @@ -1166,6 +1166,10 @@ public class IntMaxVectorTests extends AbstractVectorTest { return Integer.compareUnsigned(a, b) >= 0; } + static int firstNonZero(int a, int b) { + return Integer.compare(a, (int) 0) != 0 ? a : b; + } + @Test static void smokeTest1() { IntVector three = IntVector.broadcast(SPECIES, (byte)-3); @@ -3186,7 +3190,7 @@ public class IntMaxVectorTests extends AbstractVectorTest { static int MINReduce(int[] a, int idx) { int res = Integer.MAX_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (int)Math.min(res, a[i]); + res = (int) Math.min(res, a[i]); } return res; @@ -3194,8 +3198,8 @@ public class IntMaxVectorTests extends AbstractVectorTest { static int MINReduceAll(int[] a) { int res = Integer.MAX_VALUE; - for (int i = 0; i < a.length; i++) { - res = (int)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (int) Math.min(res, MINReduce(a, i)); } return res; @@ -3217,7 +3221,7 @@ public class IntMaxVectorTests extends AbstractVectorTest { ra = Integer.MAX_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { IntVector av = IntVector.fromArray(SPECIES, a, i); - ra = (int)Math.min(ra, av.reduceLanes(VectorOperators.MIN)); + ra = (int) Math.min(ra, av.reduceLanes(VectorOperators.MIN)); } } @@ -3227,8 +3231,8 @@ public class IntMaxVectorTests extends AbstractVectorTest { static int MINReduceMasked(int[] a, int idx, boolean[] mask) { int res = Integer.MAX_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (int)Math.min(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (int) Math.min(res, a[i]); } return res; @@ -3236,9 +3240,8 @@ public class IntMaxVectorTests extends AbstractVectorTest { static int MINReduceAllMasked(int[] a, boolean[] mask) { int res = Integer.MAX_VALUE; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (int)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (int) Math.min(res, MINReduceMasked(a, i, mask)); } return res; @@ -3262,7 +3265,7 @@ public class IntMaxVectorTests extends AbstractVectorTest { ra = Integer.MAX_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { IntVector av = IntVector.fromArray(SPECIES, a, i); - ra = (int)Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); + ra = (int) Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); } } @@ -3272,7 +3275,7 @@ public class IntMaxVectorTests extends AbstractVectorTest { static int MAXReduce(int[] a, int idx) { int res = Integer.MIN_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (int)Math.max(res, a[i]); + res = (int) Math.max(res, a[i]); } return res; @@ -3280,8 +3283,8 @@ public class IntMaxVectorTests extends AbstractVectorTest { static int MAXReduceAll(int[] a) { int res = Integer.MIN_VALUE; - for (int i = 0; i < a.length; i++) { - res = (int)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (int) Math.max(res, MAXReduce(a, i)); } return res; @@ -3303,7 +3306,7 @@ public class IntMaxVectorTests extends AbstractVectorTest { ra = Integer.MIN_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { IntVector av = IntVector.fromArray(SPECIES, a, i); - ra = (int)Math.max(ra, av.reduceLanes(VectorOperators.MAX)); + ra = (int) Math.max(ra, av.reduceLanes(VectorOperators.MAX)); } } @@ -3313,8 +3316,8 @@ public class IntMaxVectorTests extends AbstractVectorTest { static int MAXReduceMasked(int[] a, int idx, boolean[] mask) { int res = Integer.MIN_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (int)Math.max(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (int) Math.max(res, a[i]); } return res; @@ -3322,9 +3325,8 @@ public class IntMaxVectorTests extends AbstractVectorTest { static int MAXReduceAllMasked(int[] a, boolean[] mask) { int res = Integer.MIN_VALUE; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (int)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (int) Math.max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -3348,13 +3350,98 @@ public class IntMaxVectorTests extends AbstractVectorTest { ra = Integer.MIN_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { IntVector av = IntVector.fromArray(SPECIES, a, i); - ra = (int)Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); + ra = (int) Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); } } assertReductionArraysEqualsMasked(r, ra, a, mask, IntMaxVectorTests::MAXReduceMasked, IntMaxVectorTests::MAXReduceAllMasked); } + static int FIRST_NONZEROReduce(int[] a, int idx) { + int res = (int) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = firstNonZero(res, a[i]); + } + + return res; + } + + static int FIRST_NONZEROReduceAll(int[] a) { + int res = (int) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduce(a, i)); + } + + return res; + } + @Test(dataProvider = "intUnaryOpProvider") + static void FIRST_NONZEROReduceIntMaxVectorTests(IntFunction fa) { + int[] a = fa.apply(SPECIES.length()); + int[] r = fr.apply(SPECIES.length()); + int ra = (int) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (int) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO)); + } + } + + assertReductionArraysEquals(r, ra, a, + IntMaxVectorTests::FIRST_NONZEROReduce, IntMaxVectorTests::FIRST_NONZEROReduceAll); + } + static int FIRST_NONZEROReduceMasked(int[] a, int idx, boolean[] mask) { + int res = (int) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = firstNonZero(res, a[i]); + } + + return res; + } + + static int FIRST_NONZEROReduceAllMasked(int[] a, boolean[] mask) { + int res = (int) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduceMasked(a, i, mask)); + } + + return res; + } + @Test(dataProvider = "intUnaryOpMaskProvider") + static void FIRST_NONZEROReduceIntMaxVectorTestsMasked(IntFunction fa, IntFunction fm) { + int[] a = fa.apply(SPECIES.length()); + int[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + int ra = (int) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (int) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + IntMaxVectorTests::FIRST_NONZEROReduceMasked, IntMaxVectorTests::FIRST_NONZEROReduceAllMasked); + } static boolean anyTrue(boolean[] a, int idx) { boolean res = false; diff --git a/test/jdk/jdk/incubator/vector/Long128VectorTests.java b/test/jdk/jdk/incubator/vector/Long128VectorTests.java index ebd7acb104d..74d251476b2 100644 --- a/test/jdk/jdk/incubator/vector/Long128VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Long128VectorTests.java @@ -1183,6 +1183,10 @@ public class Long128VectorTests extends AbstractVectorTest { return Long.compareUnsigned(a, b) >= 0; } + static long firstNonZero(long a, long b) { + return Long.compare(a, (long) 0) != 0 ? a : b; + } + @Test static void smokeTest1() { LongVector three = LongVector.broadcast(SPECIES, (byte)-3); @@ -3203,7 +3207,7 @@ public class Long128VectorTests extends AbstractVectorTest { static long MINReduce(long[] a, int idx) { long res = Long.MAX_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (long)Math.min(res, a[i]); + res = (long) Math.min(res, a[i]); } return res; @@ -3211,8 +3215,8 @@ public class Long128VectorTests extends AbstractVectorTest { static long MINReduceAll(long[] a) { long res = Long.MAX_VALUE; - for (int i = 0; i < a.length; i++) { - res = (long)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (long) Math.min(res, MINReduce(a, i)); } return res; @@ -3234,7 +3238,7 @@ public class Long128VectorTests extends AbstractVectorTest { ra = Long.MAX_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { LongVector av = LongVector.fromArray(SPECIES, a, i); - ra = (long)Math.min(ra, av.reduceLanes(VectorOperators.MIN)); + ra = (long) Math.min(ra, av.reduceLanes(VectorOperators.MIN)); } } @@ -3244,8 +3248,8 @@ public class Long128VectorTests extends AbstractVectorTest { static long MINReduceMasked(long[] a, int idx, boolean[] mask) { long res = Long.MAX_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (long)Math.min(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (long) Math.min(res, a[i]); } return res; @@ -3253,9 +3257,8 @@ public class Long128VectorTests extends AbstractVectorTest { static long MINReduceAllMasked(long[] a, boolean[] mask) { long res = Long.MAX_VALUE; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (long)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (long) Math.min(res, MINReduceMasked(a, i, mask)); } return res; @@ -3279,7 +3282,7 @@ public class Long128VectorTests extends AbstractVectorTest { ra = Long.MAX_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { LongVector av = LongVector.fromArray(SPECIES, a, i); - ra = (long)Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); + ra = (long) Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); } } @@ -3289,7 +3292,7 @@ public class Long128VectorTests extends AbstractVectorTest { static long MAXReduce(long[] a, int idx) { long res = Long.MIN_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (long)Math.max(res, a[i]); + res = (long) Math.max(res, a[i]); } return res; @@ -3297,8 +3300,8 @@ public class Long128VectorTests extends AbstractVectorTest { static long MAXReduceAll(long[] a) { long res = Long.MIN_VALUE; - for (int i = 0; i < a.length; i++) { - res = (long)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (long) Math.max(res, MAXReduce(a, i)); } return res; @@ -3320,7 +3323,7 @@ public class Long128VectorTests extends AbstractVectorTest { ra = Long.MIN_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { LongVector av = LongVector.fromArray(SPECIES, a, i); - ra = (long)Math.max(ra, av.reduceLanes(VectorOperators.MAX)); + ra = (long) Math.max(ra, av.reduceLanes(VectorOperators.MAX)); } } @@ -3330,8 +3333,8 @@ public class Long128VectorTests extends AbstractVectorTest { static long MAXReduceMasked(long[] a, int idx, boolean[] mask) { long res = Long.MIN_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (long)Math.max(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (long) Math.max(res, a[i]); } return res; @@ -3339,9 +3342,8 @@ public class Long128VectorTests extends AbstractVectorTest { static long MAXReduceAllMasked(long[] a, boolean[] mask) { long res = Long.MIN_VALUE; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (long)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (long) Math.max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -3365,13 +3367,98 @@ public class Long128VectorTests extends AbstractVectorTest { ra = Long.MIN_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { LongVector av = LongVector.fromArray(SPECIES, a, i); - ra = (long)Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); + ra = (long) Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); } } assertReductionArraysEqualsMasked(r, ra, a, mask, Long128VectorTests::MAXReduceMasked, Long128VectorTests::MAXReduceAllMasked); } + static long FIRST_NONZEROReduce(long[] a, int idx) { + long res = (long) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = firstNonZero(res, a[i]); + } + + return res; + } + + static long FIRST_NONZEROReduceAll(long[] a) { + long res = (long) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduce(a, i)); + } + + return res; + } + @Test(dataProvider = "longUnaryOpProvider") + static void FIRST_NONZEROReduceLong128VectorTests(IntFunction fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = fr.apply(SPECIES.length()); + long ra = (long) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (long) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO)); + } + } + + assertReductionArraysEquals(r, ra, a, + Long128VectorTests::FIRST_NONZEROReduce, Long128VectorTests::FIRST_NONZEROReduceAll); + } + static long FIRST_NONZEROReduceMasked(long[] a, int idx, boolean[] mask) { + long res = (long) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = firstNonZero(res, a[i]); + } + + return res; + } + + static long FIRST_NONZEROReduceAllMasked(long[] a, boolean[] mask) { + long res = (long) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduceMasked(a, i, mask)); + } + + return res; + } + @Test(dataProvider = "longUnaryOpMaskProvider") + static void FIRST_NONZEROReduceLong128VectorTestsMasked(IntFunction fa, IntFunction fm) { + long[] a = fa.apply(SPECIES.length()); + long[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + long ra = (long) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (long) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Long128VectorTests::FIRST_NONZEROReduceMasked, Long128VectorTests::FIRST_NONZEROReduceAllMasked); + } static boolean anyTrue(boolean[] a, int idx) { boolean res = false; diff --git a/test/jdk/jdk/incubator/vector/Long256VectorTests.java b/test/jdk/jdk/incubator/vector/Long256VectorTests.java index 5065745e5f8..4d2acbddd86 100644 --- a/test/jdk/jdk/incubator/vector/Long256VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Long256VectorTests.java @@ -1183,6 +1183,10 @@ public class Long256VectorTests extends AbstractVectorTest { return Long.compareUnsigned(a, b) >= 0; } + static long firstNonZero(long a, long b) { + return Long.compare(a, (long) 0) != 0 ? a : b; + } + @Test static void smokeTest1() { LongVector three = LongVector.broadcast(SPECIES, (byte)-3); @@ -3203,7 +3207,7 @@ public class Long256VectorTests extends AbstractVectorTest { static long MINReduce(long[] a, int idx) { long res = Long.MAX_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (long)Math.min(res, a[i]); + res = (long) Math.min(res, a[i]); } return res; @@ -3211,8 +3215,8 @@ public class Long256VectorTests extends AbstractVectorTest { static long MINReduceAll(long[] a) { long res = Long.MAX_VALUE; - for (int i = 0; i < a.length; i++) { - res = (long)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (long) Math.min(res, MINReduce(a, i)); } return res; @@ -3234,7 +3238,7 @@ public class Long256VectorTests extends AbstractVectorTest { ra = Long.MAX_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { LongVector av = LongVector.fromArray(SPECIES, a, i); - ra = (long)Math.min(ra, av.reduceLanes(VectorOperators.MIN)); + ra = (long) Math.min(ra, av.reduceLanes(VectorOperators.MIN)); } } @@ -3244,8 +3248,8 @@ public class Long256VectorTests extends AbstractVectorTest { static long MINReduceMasked(long[] a, int idx, boolean[] mask) { long res = Long.MAX_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (long)Math.min(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (long) Math.min(res, a[i]); } return res; @@ -3253,9 +3257,8 @@ public class Long256VectorTests extends AbstractVectorTest { static long MINReduceAllMasked(long[] a, boolean[] mask) { long res = Long.MAX_VALUE; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (long)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (long) Math.min(res, MINReduceMasked(a, i, mask)); } return res; @@ -3279,7 +3282,7 @@ public class Long256VectorTests extends AbstractVectorTest { ra = Long.MAX_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { LongVector av = LongVector.fromArray(SPECIES, a, i); - ra = (long)Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); + ra = (long) Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); } } @@ -3289,7 +3292,7 @@ public class Long256VectorTests extends AbstractVectorTest { static long MAXReduce(long[] a, int idx) { long res = Long.MIN_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (long)Math.max(res, a[i]); + res = (long) Math.max(res, a[i]); } return res; @@ -3297,8 +3300,8 @@ public class Long256VectorTests extends AbstractVectorTest { static long MAXReduceAll(long[] a) { long res = Long.MIN_VALUE; - for (int i = 0; i < a.length; i++) { - res = (long)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (long) Math.max(res, MAXReduce(a, i)); } return res; @@ -3320,7 +3323,7 @@ public class Long256VectorTests extends AbstractVectorTest { ra = Long.MIN_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { LongVector av = LongVector.fromArray(SPECIES, a, i); - ra = (long)Math.max(ra, av.reduceLanes(VectorOperators.MAX)); + ra = (long) Math.max(ra, av.reduceLanes(VectorOperators.MAX)); } } @@ -3330,8 +3333,8 @@ public class Long256VectorTests extends AbstractVectorTest { static long MAXReduceMasked(long[] a, int idx, boolean[] mask) { long res = Long.MIN_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (long)Math.max(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (long) Math.max(res, a[i]); } return res; @@ -3339,9 +3342,8 @@ public class Long256VectorTests extends AbstractVectorTest { static long MAXReduceAllMasked(long[] a, boolean[] mask) { long res = Long.MIN_VALUE; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (long)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (long) Math.max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -3365,13 +3367,98 @@ public class Long256VectorTests extends AbstractVectorTest { ra = Long.MIN_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { LongVector av = LongVector.fromArray(SPECIES, a, i); - ra = (long)Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); + ra = (long) Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); } } assertReductionArraysEqualsMasked(r, ra, a, mask, Long256VectorTests::MAXReduceMasked, Long256VectorTests::MAXReduceAllMasked); } + static long FIRST_NONZEROReduce(long[] a, int idx) { + long res = (long) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = firstNonZero(res, a[i]); + } + + return res; + } + + static long FIRST_NONZEROReduceAll(long[] a) { + long res = (long) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduce(a, i)); + } + + return res; + } + @Test(dataProvider = "longUnaryOpProvider") + static void FIRST_NONZEROReduceLong256VectorTests(IntFunction fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = fr.apply(SPECIES.length()); + long ra = (long) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (long) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO)); + } + } + + assertReductionArraysEquals(r, ra, a, + Long256VectorTests::FIRST_NONZEROReduce, Long256VectorTests::FIRST_NONZEROReduceAll); + } + static long FIRST_NONZEROReduceMasked(long[] a, int idx, boolean[] mask) { + long res = (long) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = firstNonZero(res, a[i]); + } + + return res; + } + + static long FIRST_NONZEROReduceAllMasked(long[] a, boolean[] mask) { + long res = (long) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduceMasked(a, i, mask)); + } + + return res; + } + @Test(dataProvider = "longUnaryOpMaskProvider") + static void FIRST_NONZEROReduceLong256VectorTestsMasked(IntFunction fa, IntFunction fm) { + long[] a = fa.apply(SPECIES.length()); + long[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + long ra = (long) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (long) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Long256VectorTests::FIRST_NONZEROReduceMasked, Long256VectorTests::FIRST_NONZEROReduceAllMasked); + } static boolean anyTrue(boolean[] a, int idx) { boolean res = false; diff --git a/test/jdk/jdk/incubator/vector/Long512VectorTests.java b/test/jdk/jdk/incubator/vector/Long512VectorTests.java index dd0c71e1dbc..9bb6f568fca 100644 --- a/test/jdk/jdk/incubator/vector/Long512VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Long512VectorTests.java @@ -1183,6 +1183,10 @@ public class Long512VectorTests extends AbstractVectorTest { return Long.compareUnsigned(a, b) >= 0; } + static long firstNonZero(long a, long b) { + return Long.compare(a, (long) 0) != 0 ? a : b; + } + @Test static void smokeTest1() { LongVector three = LongVector.broadcast(SPECIES, (byte)-3); @@ -3203,7 +3207,7 @@ public class Long512VectorTests extends AbstractVectorTest { static long MINReduce(long[] a, int idx) { long res = Long.MAX_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (long)Math.min(res, a[i]); + res = (long) Math.min(res, a[i]); } return res; @@ -3211,8 +3215,8 @@ public class Long512VectorTests extends AbstractVectorTest { static long MINReduceAll(long[] a) { long res = Long.MAX_VALUE; - for (int i = 0; i < a.length; i++) { - res = (long)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (long) Math.min(res, MINReduce(a, i)); } return res; @@ -3234,7 +3238,7 @@ public class Long512VectorTests extends AbstractVectorTest { ra = Long.MAX_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { LongVector av = LongVector.fromArray(SPECIES, a, i); - ra = (long)Math.min(ra, av.reduceLanes(VectorOperators.MIN)); + ra = (long) Math.min(ra, av.reduceLanes(VectorOperators.MIN)); } } @@ -3244,8 +3248,8 @@ public class Long512VectorTests extends AbstractVectorTest { static long MINReduceMasked(long[] a, int idx, boolean[] mask) { long res = Long.MAX_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (long)Math.min(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (long) Math.min(res, a[i]); } return res; @@ -3253,9 +3257,8 @@ public class Long512VectorTests extends AbstractVectorTest { static long MINReduceAllMasked(long[] a, boolean[] mask) { long res = Long.MAX_VALUE; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (long)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (long) Math.min(res, MINReduceMasked(a, i, mask)); } return res; @@ -3279,7 +3282,7 @@ public class Long512VectorTests extends AbstractVectorTest { ra = Long.MAX_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { LongVector av = LongVector.fromArray(SPECIES, a, i); - ra = (long)Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); + ra = (long) Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); } } @@ -3289,7 +3292,7 @@ public class Long512VectorTests extends AbstractVectorTest { static long MAXReduce(long[] a, int idx) { long res = Long.MIN_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (long)Math.max(res, a[i]); + res = (long) Math.max(res, a[i]); } return res; @@ -3297,8 +3300,8 @@ public class Long512VectorTests extends AbstractVectorTest { static long MAXReduceAll(long[] a) { long res = Long.MIN_VALUE; - for (int i = 0; i < a.length; i++) { - res = (long)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (long) Math.max(res, MAXReduce(a, i)); } return res; @@ -3320,7 +3323,7 @@ public class Long512VectorTests extends AbstractVectorTest { ra = Long.MIN_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { LongVector av = LongVector.fromArray(SPECIES, a, i); - ra = (long)Math.max(ra, av.reduceLanes(VectorOperators.MAX)); + ra = (long) Math.max(ra, av.reduceLanes(VectorOperators.MAX)); } } @@ -3330,8 +3333,8 @@ public class Long512VectorTests extends AbstractVectorTest { static long MAXReduceMasked(long[] a, int idx, boolean[] mask) { long res = Long.MIN_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (long)Math.max(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (long) Math.max(res, a[i]); } return res; @@ -3339,9 +3342,8 @@ public class Long512VectorTests extends AbstractVectorTest { static long MAXReduceAllMasked(long[] a, boolean[] mask) { long res = Long.MIN_VALUE; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (long)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (long) Math.max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -3365,13 +3367,98 @@ public class Long512VectorTests extends AbstractVectorTest { ra = Long.MIN_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { LongVector av = LongVector.fromArray(SPECIES, a, i); - ra = (long)Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); + ra = (long) Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); } } assertReductionArraysEqualsMasked(r, ra, a, mask, Long512VectorTests::MAXReduceMasked, Long512VectorTests::MAXReduceAllMasked); } + static long FIRST_NONZEROReduce(long[] a, int idx) { + long res = (long) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = firstNonZero(res, a[i]); + } + + return res; + } + + static long FIRST_NONZEROReduceAll(long[] a) { + long res = (long) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduce(a, i)); + } + + return res; + } + @Test(dataProvider = "longUnaryOpProvider") + static void FIRST_NONZEROReduceLong512VectorTests(IntFunction fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = fr.apply(SPECIES.length()); + long ra = (long) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (long) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO)); + } + } + + assertReductionArraysEquals(r, ra, a, + Long512VectorTests::FIRST_NONZEROReduce, Long512VectorTests::FIRST_NONZEROReduceAll); + } + static long FIRST_NONZEROReduceMasked(long[] a, int idx, boolean[] mask) { + long res = (long) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = firstNonZero(res, a[i]); + } + + return res; + } + + static long FIRST_NONZEROReduceAllMasked(long[] a, boolean[] mask) { + long res = (long) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduceMasked(a, i, mask)); + } + + return res; + } + @Test(dataProvider = "longUnaryOpMaskProvider") + static void FIRST_NONZEROReduceLong512VectorTestsMasked(IntFunction fa, IntFunction fm) { + long[] a = fa.apply(SPECIES.length()); + long[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + long ra = (long) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (long) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Long512VectorTests::FIRST_NONZEROReduceMasked, Long512VectorTests::FIRST_NONZEROReduceAllMasked); + } static boolean anyTrue(boolean[] a, int idx) { boolean res = false; diff --git a/test/jdk/jdk/incubator/vector/Long64VectorTests.java b/test/jdk/jdk/incubator/vector/Long64VectorTests.java index 919f6ef0f6a..50976531dac 100644 --- a/test/jdk/jdk/incubator/vector/Long64VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Long64VectorTests.java @@ -1183,6 +1183,10 @@ public class Long64VectorTests extends AbstractVectorTest { return Long.compareUnsigned(a, b) >= 0; } + static long firstNonZero(long a, long b) { + return Long.compare(a, (long) 0) != 0 ? a : b; + } + @Test static void smokeTest1() { LongVector three = LongVector.broadcast(SPECIES, (byte)-3); @@ -3203,7 +3207,7 @@ public class Long64VectorTests extends AbstractVectorTest { static long MINReduce(long[] a, int idx) { long res = Long.MAX_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (long)Math.min(res, a[i]); + res = (long) Math.min(res, a[i]); } return res; @@ -3211,8 +3215,8 @@ public class Long64VectorTests extends AbstractVectorTest { static long MINReduceAll(long[] a) { long res = Long.MAX_VALUE; - for (int i = 0; i < a.length; i++) { - res = (long)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (long) Math.min(res, MINReduce(a, i)); } return res; @@ -3234,7 +3238,7 @@ public class Long64VectorTests extends AbstractVectorTest { ra = Long.MAX_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { LongVector av = LongVector.fromArray(SPECIES, a, i); - ra = (long)Math.min(ra, av.reduceLanes(VectorOperators.MIN)); + ra = (long) Math.min(ra, av.reduceLanes(VectorOperators.MIN)); } } @@ -3244,8 +3248,8 @@ public class Long64VectorTests extends AbstractVectorTest { static long MINReduceMasked(long[] a, int idx, boolean[] mask) { long res = Long.MAX_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (long)Math.min(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (long) Math.min(res, a[i]); } return res; @@ -3253,9 +3257,8 @@ public class Long64VectorTests extends AbstractVectorTest { static long MINReduceAllMasked(long[] a, boolean[] mask) { long res = Long.MAX_VALUE; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (long)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (long) Math.min(res, MINReduceMasked(a, i, mask)); } return res; @@ -3279,7 +3282,7 @@ public class Long64VectorTests extends AbstractVectorTest { ra = Long.MAX_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { LongVector av = LongVector.fromArray(SPECIES, a, i); - ra = (long)Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); + ra = (long) Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); } } @@ -3289,7 +3292,7 @@ public class Long64VectorTests extends AbstractVectorTest { static long MAXReduce(long[] a, int idx) { long res = Long.MIN_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (long)Math.max(res, a[i]); + res = (long) Math.max(res, a[i]); } return res; @@ -3297,8 +3300,8 @@ public class Long64VectorTests extends AbstractVectorTest { static long MAXReduceAll(long[] a) { long res = Long.MIN_VALUE; - for (int i = 0; i < a.length; i++) { - res = (long)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (long) Math.max(res, MAXReduce(a, i)); } return res; @@ -3320,7 +3323,7 @@ public class Long64VectorTests extends AbstractVectorTest { ra = Long.MIN_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { LongVector av = LongVector.fromArray(SPECIES, a, i); - ra = (long)Math.max(ra, av.reduceLanes(VectorOperators.MAX)); + ra = (long) Math.max(ra, av.reduceLanes(VectorOperators.MAX)); } } @@ -3330,8 +3333,8 @@ public class Long64VectorTests extends AbstractVectorTest { static long MAXReduceMasked(long[] a, int idx, boolean[] mask) { long res = Long.MIN_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (long)Math.max(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (long) Math.max(res, a[i]); } return res; @@ -3339,9 +3342,8 @@ public class Long64VectorTests extends AbstractVectorTest { static long MAXReduceAllMasked(long[] a, boolean[] mask) { long res = Long.MIN_VALUE; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (long)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (long) Math.max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -3365,13 +3367,98 @@ public class Long64VectorTests extends AbstractVectorTest { ra = Long.MIN_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { LongVector av = LongVector.fromArray(SPECIES, a, i); - ra = (long)Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); + ra = (long) Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); } } assertReductionArraysEqualsMasked(r, ra, a, mask, Long64VectorTests::MAXReduceMasked, Long64VectorTests::MAXReduceAllMasked); } + static long FIRST_NONZEROReduce(long[] a, int idx) { + long res = (long) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = firstNonZero(res, a[i]); + } + + return res; + } + + static long FIRST_NONZEROReduceAll(long[] a) { + long res = (long) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduce(a, i)); + } + + return res; + } + @Test(dataProvider = "longUnaryOpProvider") + static void FIRST_NONZEROReduceLong64VectorTests(IntFunction fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = fr.apply(SPECIES.length()); + long ra = (long) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (long) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO)); + } + } + + assertReductionArraysEquals(r, ra, a, + Long64VectorTests::FIRST_NONZEROReduce, Long64VectorTests::FIRST_NONZEROReduceAll); + } + static long FIRST_NONZEROReduceMasked(long[] a, int idx, boolean[] mask) { + long res = (long) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = firstNonZero(res, a[i]); + } + + return res; + } + + static long FIRST_NONZEROReduceAllMasked(long[] a, boolean[] mask) { + long res = (long) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduceMasked(a, i, mask)); + } + + return res; + } + @Test(dataProvider = "longUnaryOpMaskProvider") + static void FIRST_NONZEROReduceLong64VectorTestsMasked(IntFunction fa, IntFunction fm) { + long[] a = fa.apply(SPECIES.length()); + long[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + long ra = (long) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (long) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Long64VectorTests::FIRST_NONZEROReduceMasked, Long64VectorTests::FIRST_NONZEROReduceAllMasked); + } static boolean anyTrue(boolean[] a, int idx) { boolean res = false; diff --git a/test/jdk/jdk/incubator/vector/LongMaxVectorTests.java b/test/jdk/jdk/incubator/vector/LongMaxVectorTests.java index 443de01cdb4..eb16136a0d6 100644 --- a/test/jdk/jdk/incubator/vector/LongMaxVectorTests.java +++ b/test/jdk/jdk/incubator/vector/LongMaxVectorTests.java @@ -1188,6 +1188,10 @@ public class LongMaxVectorTests extends AbstractVectorTest { return Long.compareUnsigned(a, b) >= 0; } + static long firstNonZero(long a, long b) { + return Long.compare(a, (long) 0) != 0 ? a : b; + } + @Test static void smokeTest1() { LongVector three = LongVector.broadcast(SPECIES, (byte)-3); @@ -3208,7 +3212,7 @@ public class LongMaxVectorTests extends AbstractVectorTest { static long MINReduce(long[] a, int idx) { long res = Long.MAX_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (long)Math.min(res, a[i]); + res = (long) Math.min(res, a[i]); } return res; @@ -3216,8 +3220,8 @@ public class LongMaxVectorTests extends AbstractVectorTest { static long MINReduceAll(long[] a) { long res = Long.MAX_VALUE; - for (int i = 0; i < a.length; i++) { - res = (long)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (long) Math.min(res, MINReduce(a, i)); } return res; @@ -3239,7 +3243,7 @@ public class LongMaxVectorTests extends AbstractVectorTest { ra = Long.MAX_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { LongVector av = LongVector.fromArray(SPECIES, a, i); - ra = (long)Math.min(ra, av.reduceLanes(VectorOperators.MIN)); + ra = (long) Math.min(ra, av.reduceLanes(VectorOperators.MIN)); } } @@ -3249,8 +3253,8 @@ public class LongMaxVectorTests extends AbstractVectorTest { static long MINReduceMasked(long[] a, int idx, boolean[] mask) { long res = Long.MAX_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (long)Math.min(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (long) Math.min(res, a[i]); } return res; @@ -3258,9 +3262,8 @@ public class LongMaxVectorTests extends AbstractVectorTest { static long MINReduceAllMasked(long[] a, boolean[] mask) { long res = Long.MAX_VALUE; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (long)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (long) Math.min(res, MINReduceMasked(a, i, mask)); } return res; @@ -3284,7 +3287,7 @@ public class LongMaxVectorTests extends AbstractVectorTest { ra = Long.MAX_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { LongVector av = LongVector.fromArray(SPECIES, a, i); - ra = (long)Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); + ra = (long) Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); } } @@ -3294,7 +3297,7 @@ public class LongMaxVectorTests extends AbstractVectorTest { static long MAXReduce(long[] a, int idx) { long res = Long.MIN_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (long)Math.max(res, a[i]); + res = (long) Math.max(res, a[i]); } return res; @@ -3302,8 +3305,8 @@ public class LongMaxVectorTests extends AbstractVectorTest { static long MAXReduceAll(long[] a) { long res = Long.MIN_VALUE; - for (int i = 0; i < a.length; i++) { - res = (long)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (long) Math.max(res, MAXReduce(a, i)); } return res; @@ -3325,7 +3328,7 @@ public class LongMaxVectorTests extends AbstractVectorTest { ra = Long.MIN_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { LongVector av = LongVector.fromArray(SPECIES, a, i); - ra = (long)Math.max(ra, av.reduceLanes(VectorOperators.MAX)); + ra = (long) Math.max(ra, av.reduceLanes(VectorOperators.MAX)); } } @@ -3335,8 +3338,8 @@ public class LongMaxVectorTests extends AbstractVectorTest { static long MAXReduceMasked(long[] a, int idx, boolean[] mask) { long res = Long.MIN_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (long)Math.max(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (long) Math.max(res, a[i]); } return res; @@ -3344,9 +3347,8 @@ public class LongMaxVectorTests extends AbstractVectorTest { static long MAXReduceAllMasked(long[] a, boolean[] mask) { long res = Long.MIN_VALUE; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (long)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (long) Math.max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -3370,13 +3372,98 @@ public class LongMaxVectorTests extends AbstractVectorTest { ra = Long.MIN_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { LongVector av = LongVector.fromArray(SPECIES, a, i); - ra = (long)Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); + ra = (long) Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); } } assertReductionArraysEqualsMasked(r, ra, a, mask, LongMaxVectorTests::MAXReduceMasked, LongMaxVectorTests::MAXReduceAllMasked); } + static long FIRST_NONZEROReduce(long[] a, int idx) { + long res = (long) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = firstNonZero(res, a[i]); + } + + return res; + } + + static long FIRST_NONZEROReduceAll(long[] a) { + long res = (long) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduce(a, i)); + } + + return res; + } + @Test(dataProvider = "longUnaryOpProvider") + static void FIRST_NONZEROReduceLongMaxVectorTests(IntFunction fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = fr.apply(SPECIES.length()); + long ra = (long) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (long) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO)); + } + } + + assertReductionArraysEquals(r, ra, a, + LongMaxVectorTests::FIRST_NONZEROReduce, LongMaxVectorTests::FIRST_NONZEROReduceAll); + } + static long FIRST_NONZEROReduceMasked(long[] a, int idx, boolean[] mask) { + long res = (long) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = firstNonZero(res, a[i]); + } + + return res; + } + + static long FIRST_NONZEROReduceAllMasked(long[] a, boolean[] mask) { + long res = (long) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduceMasked(a, i, mask)); + } + + return res; + } + @Test(dataProvider = "longUnaryOpMaskProvider") + static void FIRST_NONZEROReduceLongMaxVectorTestsMasked(IntFunction fa, IntFunction fm) { + long[] a = fa.apply(SPECIES.length()); + long[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + long ra = (long) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (long) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + LongMaxVectorTests::FIRST_NONZEROReduceMasked, LongMaxVectorTests::FIRST_NONZEROReduceAllMasked); + } static boolean anyTrue(boolean[] a, int idx) { boolean res = false; diff --git a/test/jdk/jdk/incubator/vector/Short128VectorTests.java b/test/jdk/jdk/incubator/vector/Short128VectorTests.java index 2e50b940b0e..2a060c354cd 100644 --- a/test/jdk/jdk/incubator/vector/Short128VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Short128VectorTests.java @@ -1191,6 +1191,10 @@ public class Short128VectorTests extends AbstractVectorTest { return Short.compareUnsigned(a, b) >= 0; } + static short firstNonZero(short a, short b) { + return Short.compare(a, (short) 0) != 0 ? a : b; + } + @Test static void smokeTest1() { ShortVector three = ShortVector.broadcast(SPECIES, (byte)-3); @@ -3206,7 +3210,7 @@ public class Short128VectorTests extends AbstractVectorTest { static short MINReduce(short[] a, int idx) { short res = Short.MAX_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (short)Math.min(res, a[i]); + res = (short) Math.min(res, a[i]); } return res; @@ -3214,8 +3218,8 @@ public class Short128VectorTests extends AbstractVectorTest { static short MINReduceAll(short[] a) { short res = Short.MAX_VALUE; - for (int i = 0; i < a.length; i++) { - res = (short)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (short) Math.min(res, MINReduce(a, i)); } return res; @@ -3237,7 +3241,7 @@ public class Short128VectorTests extends AbstractVectorTest { ra = Short.MAX_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { ShortVector av = ShortVector.fromArray(SPECIES, a, i); - ra = (short)Math.min(ra, av.reduceLanes(VectorOperators.MIN)); + ra = (short) Math.min(ra, av.reduceLanes(VectorOperators.MIN)); } } @@ -3247,8 +3251,8 @@ public class Short128VectorTests extends AbstractVectorTest { static short MINReduceMasked(short[] a, int idx, boolean[] mask) { short res = Short.MAX_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (short)Math.min(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (short) Math.min(res, a[i]); } return res; @@ -3256,9 +3260,8 @@ public class Short128VectorTests extends AbstractVectorTest { static short MINReduceAllMasked(short[] a, boolean[] mask) { short res = Short.MAX_VALUE; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (short)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (short) Math.min(res, MINReduceMasked(a, i, mask)); } return res; @@ -3282,7 +3285,7 @@ public class Short128VectorTests extends AbstractVectorTest { ra = Short.MAX_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { ShortVector av = ShortVector.fromArray(SPECIES, a, i); - ra = (short)Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); + ra = (short) Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); } } @@ -3292,7 +3295,7 @@ public class Short128VectorTests extends AbstractVectorTest { static short MAXReduce(short[] a, int idx) { short res = Short.MIN_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (short)Math.max(res, a[i]); + res = (short) Math.max(res, a[i]); } return res; @@ -3300,8 +3303,8 @@ public class Short128VectorTests extends AbstractVectorTest { static short MAXReduceAll(short[] a) { short res = Short.MIN_VALUE; - for (int i = 0; i < a.length; i++) { - res = (short)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (short) Math.max(res, MAXReduce(a, i)); } return res; @@ -3323,7 +3326,7 @@ public class Short128VectorTests extends AbstractVectorTest { ra = Short.MIN_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { ShortVector av = ShortVector.fromArray(SPECIES, a, i); - ra = (short)Math.max(ra, av.reduceLanes(VectorOperators.MAX)); + ra = (short) Math.max(ra, av.reduceLanes(VectorOperators.MAX)); } } @@ -3333,8 +3336,8 @@ public class Short128VectorTests extends AbstractVectorTest { static short MAXReduceMasked(short[] a, int idx, boolean[] mask) { short res = Short.MIN_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (short)Math.max(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (short) Math.max(res, a[i]); } return res; @@ -3342,9 +3345,8 @@ public class Short128VectorTests extends AbstractVectorTest { static short MAXReduceAllMasked(short[] a, boolean[] mask) { short res = Short.MIN_VALUE; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (short)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (short) Math.max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -3368,13 +3370,98 @@ public class Short128VectorTests extends AbstractVectorTest { ra = Short.MIN_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { ShortVector av = ShortVector.fromArray(SPECIES, a, i); - ra = (short)Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); + ra = (short) Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); } } assertReductionArraysEqualsMasked(r, ra, a, mask, Short128VectorTests::MAXReduceMasked, Short128VectorTests::MAXReduceAllMasked); } + static short FIRST_NONZEROReduce(short[] a, int idx) { + short res = (short) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = firstNonZero(res, a[i]); + } + + return res; + } + + static short FIRST_NONZEROReduceAll(short[] a) { + short res = (short) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduce(a, i)); + } + + return res; + } + @Test(dataProvider = "shortUnaryOpProvider") + static void FIRST_NONZEROReduceShort128VectorTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + short ra = (short) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (short) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO)); + } + } + + assertReductionArraysEquals(r, ra, a, + Short128VectorTests::FIRST_NONZEROReduce, Short128VectorTests::FIRST_NONZEROReduceAll); + } + static short FIRST_NONZEROReduceMasked(short[] a, int idx, boolean[] mask) { + short res = (short) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = firstNonZero(res, a[i]); + } + + return res; + } + + static short FIRST_NONZEROReduceAllMasked(short[] a, boolean[] mask) { + short res = (short) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduceMasked(a, i, mask)); + } + + return res; + } + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void FIRST_NONZEROReduceShort128VectorTestsMasked(IntFunction fa, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + short ra = (short) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (short) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Short128VectorTests::FIRST_NONZEROReduceMasked, Short128VectorTests::FIRST_NONZEROReduceAllMasked); + } static boolean anyTrue(boolean[] a, int idx) { boolean res = false; diff --git a/test/jdk/jdk/incubator/vector/Short256VectorTests.java b/test/jdk/jdk/incubator/vector/Short256VectorTests.java index 67fc08c6194..46626d63aaf 100644 --- a/test/jdk/jdk/incubator/vector/Short256VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Short256VectorTests.java @@ -1191,6 +1191,10 @@ public class Short256VectorTests extends AbstractVectorTest { return Short.compareUnsigned(a, b) >= 0; } + static short firstNonZero(short a, short b) { + return Short.compare(a, (short) 0) != 0 ? a : b; + } + @Test static void smokeTest1() { ShortVector three = ShortVector.broadcast(SPECIES, (byte)-3); @@ -3206,7 +3210,7 @@ public class Short256VectorTests extends AbstractVectorTest { static short MINReduce(short[] a, int idx) { short res = Short.MAX_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (short)Math.min(res, a[i]); + res = (short) Math.min(res, a[i]); } return res; @@ -3214,8 +3218,8 @@ public class Short256VectorTests extends AbstractVectorTest { static short MINReduceAll(short[] a) { short res = Short.MAX_VALUE; - for (int i = 0; i < a.length; i++) { - res = (short)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (short) Math.min(res, MINReduce(a, i)); } return res; @@ -3237,7 +3241,7 @@ public class Short256VectorTests extends AbstractVectorTest { ra = Short.MAX_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { ShortVector av = ShortVector.fromArray(SPECIES, a, i); - ra = (short)Math.min(ra, av.reduceLanes(VectorOperators.MIN)); + ra = (short) Math.min(ra, av.reduceLanes(VectorOperators.MIN)); } } @@ -3247,8 +3251,8 @@ public class Short256VectorTests extends AbstractVectorTest { static short MINReduceMasked(short[] a, int idx, boolean[] mask) { short res = Short.MAX_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (short)Math.min(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (short) Math.min(res, a[i]); } return res; @@ -3256,9 +3260,8 @@ public class Short256VectorTests extends AbstractVectorTest { static short MINReduceAllMasked(short[] a, boolean[] mask) { short res = Short.MAX_VALUE; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (short)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (short) Math.min(res, MINReduceMasked(a, i, mask)); } return res; @@ -3282,7 +3285,7 @@ public class Short256VectorTests extends AbstractVectorTest { ra = Short.MAX_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { ShortVector av = ShortVector.fromArray(SPECIES, a, i); - ra = (short)Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); + ra = (short) Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); } } @@ -3292,7 +3295,7 @@ public class Short256VectorTests extends AbstractVectorTest { static short MAXReduce(short[] a, int idx) { short res = Short.MIN_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (short)Math.max(res, a[i]); + res = (short) Math.max(res, a[i]); } return res; @@ -3300,8 +3303,8 @@ public class Short256VectorTests extends AbstractVectorTest { static short MAXReduceAll(short[] a) { short res = Short.MIN_VALUE; - for (int i = 0; i < a.length; i++) { - res = (short)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (short) Math.max(res, MAXReduce(a, i)); } return res; @@ -3323,7 +3326,7 @@ public class Short256VectorTests extends AbstractVectorTest { ra = Short.MIN_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { ShortVector av = ShortVector.fromArray(SPECIES, a, i); - ra = (short)Math.max(ra, av.reduceLanes(VectorOperators.MAX)); + ra = (short) Math.max(ra, av.reduceLanes(VectorOperators.MAX)); } } @@ -3333,8 +3336,8 @@ public class Short256VectorTests extends AbstractVectorTest { static short MAXReduceMasked(short[] a, int idx, boolean[] mask) { short res = Short.MIN_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (short)Math.max(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (short) Math.max(res, a[i]); } return res; @@ -3342,9 +3345,8 @@ public class Short256VectorTests extends AbstractVectorTest { static short MAXReduceAllMasked(short[] a, boolean[] mask) { short res = Short.MIN_VALUE; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (short)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (short) Math.max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -3368,13 +3370,98 @@ public class Short256VectorTests extends AbstractVectorTest { ra = Short.MIN_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { ShortVector av = ShortVector.fromArray(SPECIES, a, i); - ra = (short)Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); + ra = (short) Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); } } assertReductionArraysEqualsMasked(r, ra, a, mask, Short256VectorTests::MAXReduceMasked, Short256VectorTests::MAXReduceAllMasked); } + static short FIRST_NONZEROReduce(short[] a, int idx) { + short res = (short) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = firstNonZero(res, a[i]); + } + + return res; + } + + static short FIRST_NONZEROReduceAll(short[] a) { + short res = (short) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduce(a, i)); + } + + return res; + } + @Test(dataProvider = "shortUnaryOpProvider") + static void FIRST_NONZEROReduceShort256VectorTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + short ra = (short) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (short) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO)); + } + } + + assertReductionArraysEquals(r, ra, a, + Short256VectorTests::FIRST_NONZEROReduce, Short256VectorTests::FIRST_NONZEROReduceAll); + } + static short FIRST_NONZEROReduceMasked(short[] a, int idx, boolean[] mask) { + short res = (short) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = firstNonZero(res, a[i]); + } + + return res; + } + + static short FIRST_NONZEROReduceAllMasked(short[] a, boolean[] mask) { + short res = (short) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduceMasked(a, i, mask)); + } + + return res; + } + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void FIRST_NONZEROReduceShort256VectorTestsMasked(IntFunction fa, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + short ra = (short) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (short) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Short256VectorTests::FIRST_NONZEROReduceMasked, Short256VectorTests::FIRST_NONZEROReduceAllMasked); + } static boolean anyTrue(boolean[] a, int idx) { boolean res = false; diff --git a/test/jdk/jdk/incubator/vector/Short512VectorTests.java b/test/jdk/jdk/incubator/vector/Short512VectorTests.java index 63bc3709481..2cff4a4802a 100644 --- a/test/jdk/jdk/incubator/vector/Short512VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Short512VectorTests.java @@ -1191,6 +1191,10 @@ public class Short512VectorTests extends AbstractVectorTest { return Short.compareUnsigned(a, b) >= 0; } + static short firstNonZero(short a, short b) { + return Short.compare(a, (short) 0) != 0 ? a : b; + } + @Test static void smokeTest1() { ShortVector three = ShortVector.broadcast(SPECIES, (byte)-3); @@ -3206,7 +3210,7 @@ public class Short512VectorTests extends AbstractVectorTest { static short MINReduce(short[] a, int idx) { short res = Short.MAX_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (short)Math.min(res, a[i]); + res = (short) Math.min(res, a[i]); } return res; @@ -3214,8 +3218,8 @@ public class Short512VectorTests extends AbstractVectorTest { static short MINReduceAll(short[] a) { short res = Short.MAX_VALUE; - for (int i = 0; i < a.length; i++) { - res = (short)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (short) Math.min(res, MINReduce(a, i)); } return res; @@ -3237,7 +3241,7 @@ public class Short512VectorTests extends AbstractVectorTest { ra = Short.MAX_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { ShortVector av = ShortVector.fromArray(SPECIES, a, i); - ra = (short)Math.min(ra, av.reduceLanes(VectorOperators.MIN)); + ra = (short) Math.min(ra, av.reduceLanes(VectorOperators.MIN)); } } @@ -3247,8 +3251,8 @@ public class Short512VectorTests extends AbstractVectorTest { static short MINReduceMasked(short[] a, int idx, boolean[] mask) { short res = Short.MAX_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (short)Math.min(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (short) Math.min(res, a[i]); } return res; @@ -3256,9 +3260,8 @@ public class Short512VectorTests extends AbstractVectorTest { static short MINReduceAllMasked(short[] a, boolean[] mask) { short res = Short.MAX_VALUE; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (short)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (short) Math.min(res, MINReduceMasked(a, i, mask)); } return res; @@ -3282,7 +3285,7 @@ public class Short512VectorTests extends AbstractVectorTest { ra = Short.MAX_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { ShortVector av = ShortVector.fromArray(SPECIES, a, i); - ra = (short)Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); + ra = (short) Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); } } @@ -3292,7 +3295,7 @@ public class Short512VectorTests extends AbstractVectorTest { static short MAXReduce(short[] a, int idx) { short res = Short.MIN_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (short)Math.max(res, a[i]); + res = (short) Math.max(res, a[i]); } return res; @@ -3300,8 +3303,8 @@ public class Short512VectorTests extends AbstractVectorTest { static short MAXReduceAll(short[] a) { short res = Short.MIN_VALUE; - for (int i = 0; i < a.length; i++) { - res = (short)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (short) Math.max(res, MAXReduce(a, i)); } return res; @@ -3323,7 +3326,7 @@ public class Short512VectorTests extends AbstractVectorTest { ra = Short.MIN_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { ShortVector av = ShortVector.fromArray(SPECIES, a, i); - ra = (short)Math.max(ra, av.reduceLanes(VectorOperators.MAX)); + ra = (short) Math.max(ra, av.reduceLanes(VectorOperators.MAX)); } } @@ -3333,8 +3336,8 @@ public class Short512VectorTests extends AbstractVectorTest { static short MAXReduceMasked(short[] a, int idx, boolean[] mask) { short res = Short.MIN_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (short)Math.max(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (short) Math.max(res, a[i]); } return res; @@ -3342,9 +3345,8 @@ public class Short512VectorTests extends AbstractVectorTest { static short MAXReduceAllMasked(short[] a, boolean[] mask) { short res = Short.MIN_VALUE; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (short)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (short) Math.max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -3368,13 +3370,98 @@ public class Short512VectorTests extends AbstractVectorTest { ra = Short.MIN_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { ShortVector av = ShortVector.fromArray(SPECIES, a, i); - ra = (short)Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); + ra = (short) Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); } } assertReductionArraysEqualsMasked(r, ra, a, mask, Short512VectorTests::MAXReduceMasked, Short512VectorTests::MAXReduceAllMasked); } + static short FIRST_NONZEROReduce(short[] a, int idx) { + short res = (short) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = firstNonZero(res, a[i]); + } + + return res; + } + + static short FIRST_NONZEROReduceAll(short[] a) { + short res = (short) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduce(a, i)); + } + + return res; + } + @Test(dataProvider = "shortUnaryOpProvider") + static void FIRST_NONZEROReduceShort512VectorTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + short ra = (short) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (short) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO)); + } + } + + assertReductionArraysEquals(r, ra, a, + Short512VectorTests::FIRST_NONZEROReduce, Short512VectorTests::FIRST_NONZEROReduceAll); + } + static short FIRST_NONZEROReduceMasked(short[] a, int idx, boolean[] mask) { + short res = (short) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = firstNonZero(res, a[i]); + } + + return res; + } + + static short FIRST_NONZEROReduceAllMasked(short[] a, boolean[] mask) { + short res = (short) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduceMasked(a, i, mask)); + } + + return res; + } + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void FIRST_NONZEROReduceShort512VectorTestsMasked(IntFunction fa, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + short ra = (short) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (short) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Short512VectorTests::FIRST_NONZEROReduceMasked, Short512VectorTests::FIRST_NONZEROReduceAllMasked); + } static boolean anyTrue(boolean[] a, int idx) { boolean res = false; diff --git a/test/jdk/jdk/incubator/vector/Short64VectorTests.java b/test/jdk/jdk/incubator/vector/Short64VectorTests.java index 8c05159737d..481081b75da 100644 --- a/test/jdk/jdk/incubator/vector/Short64VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Short64VectorTests.java @@ -1191,6 +1191,10 @@ public class Short64VectorTests extends AbstractVectorTest { return Short.compareUnsigned(a, b) >= 0; } + static short firstNonZero(short a, short b) { + return Short.compare(a, (short) 0) != 0 ? a : b; + } + @Test static void smokeTest1() { ShortVector three = ShortVector.broadcast(SPECIES, (byte)-3); @@ -3206,7 +3210,7 @@ public class Short64VectorTests extends AbstractVectorTest { static short MINReduce(short[] a, int idx) { short res = Short.MAX_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (short)Math.min(res, a[i]); + res = (short) Math.min(res, a[i]); } return res; @@ -3214,8 +3218,8 @@ public class Short64VectorTests extends AbstractVectorTest { static short MINReduceAll(short[] a) { short res = Short.MAX_VALUE; - for (int i = 0; i < a.length; i++) { - res = (short)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (short) Math.min(res, MINReduce(a, i)); } return res; @@ -3237,7 +3241,7 @@ public class Short64VectorTests extends AbstractVectorTest { ra = Short.MAX_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { ShortVector av = ShortVector.fromArray(SPECIES, a, i); - ra = (short)Math.min(ra, av.reduceLanes(VectorOperators.MIN)); + ra = (short) Math.min(ra, av.reduceLanes(VectorOperators.MIN)); } } @@ -3247,8 +3251,8 @@ public class Short64VectorTests extends AbstractVectorTest { static short MINReduceMasked(short[] a, int idx, boolean[] mask) { short res = Short.MAX_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (short)Math.min(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (short) Math.min(res, a[i]); } return res; @@ -3256,9 +3260,8 @@ public class Short64VectorTests extends AbstractVectorTest { static short MINReduceAllMasked(short[] a, boolean[] mask) { short res = Short.MAX_VALUE; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (short)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (short) Math.min(res, MINReduceMasked(a, i, mask)); } return res; @@ -3282,7 +3285,7 @@ public class Short64VectorTests extends AbstractVectorTest { ra = Short.MAX_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { ShortVector av = ShortVector.fromArray(SPECIES, a, i); - ra = (short)Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); + ra = (short) Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); } } @@ -3292,7 +3295,7 @@ public class Short64VectorTests extends AbstractVectorTest { static short MAXReduce(short[] a, int idx) { short res = Short.MIN_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (short)Math.max(res, a[i]); + res = (short) Math.max(res, a[i]); } return res; @@ -3300,8 +3303,8 @@ public class Short64VectorTests extends AbstractVectorTest { static short MAXReduceAll(short[] a) { short res = Short.MIN_VALUE; - for (int i = 0; i < a.length; i++) { - res = (short)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (short) Math.max(res, MAXReduce(a, i)); } return res; @@ -3323,7 +3326,7 @@ public class Short64VectorTests extends AbstractVectorTest { ra = Short.MIN_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { ShortVector av = ShortVector.fromArray(SPECIES, a, i); - ra = (short)Math.max(ra, av.reduceLanes(VectorOperators.MAX)); + ra = (short) Math.max(ra, av.reduceLanes(VectorOperators.MAX)); } } @@ -3333,8 +3336,8 @@ public class Short64VectorTests extends AbstractVectorTest { static short MAXReduceMasked(short[] a, int idx, boolean[] mask) { short res = Short.MIN_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (short)Math.max(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (short) Math.max(res, a[i]); } return res; @@ -3342,9 +3345,8 @@ public class Short64VectorTests extends AbstractVectorTest { static short MAXReduceAllMasked(short[] a, boolean[] mask) { short res = Short.MIN_VALUE; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (short)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (short) Math.max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -3368,13 +3370,98 @@ public class Short64VectorTests extends AbstractVectorTest { ra = Short.MIN_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { ShortVector av = ShortVector.fromArray(SPECIES, a, i); - ra = (short)Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); + ra = (short) Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); } } assertReductionArraysEqualsMasked(r, ra, a, mask, Short64VectorTests::MAXReduceMasked, Short64VectorTests::MAXReduceAllMasked); } + static short FIRST_NONZEROReduce(short[] a, int idx) { + short res = (short) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = firstNonZero(res, a[i]); + } + + return res; + } + + static short FIRST_NONZEROReduceAll(short[] a) { + short res = (short) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduce(a, i)); + } + + return res; + } + @Test(dataProvider = "shortUnaryOpProvider") + static void FIRST_NONZEROReduceShort64VectorTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + short ra = (short) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (short) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO)); + } + } + + assertReductionArraysEquals(r, ra, a, + Short64VectorTests::FIRST_NONZEROReduce, Short64VectorTests::FIRST_NONZEROReduceAll); + } + static short FIRST_NONZEROReduceMasked(short[] a, int idx, boolean[] mask) { + short res = (short) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = firstNonZero(res, a[i]); + } + + return res; + } + + static short FIRST_NONZEROReduceAllMasked(short[] a, boolean[] mask) { + short res = (short) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduceMasked(a, i, mask)); + } + + return res; + } + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void FIRST_NONZEROReduceShort64VectorTestsMasked(IntFunction fa, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + short ra = (short) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (short) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Short64VectorTests::FIRST_NONZEROReduceMasked, Short64VectorTests::FIRST_NONZEROReduceAllMasked); + } static boolean anyTrue(boolean[] a, int idx) { boolean res = false; diff --git a/test/jdk/jdk/incubator/vector/ShortMaxVectorTests.java b/test/jdk/jdk/incubator/vector/ShortMaxVectorTests.java index b196aad5218..00d99484a13 100644 --- a/test/jdk/jdk/incubator/vector/ShortMaxVectorTests.java +++ b/test/jdk/jdk/incubator/vector/ShortMaxVectorTests.java @@ -1196,6 +1196,10 @@ public class ShortMaxVectorTests extends AbstractVectorTest { return Short.compareUnsigned(a, b) >= 0; } + static short firstNonZero(short a, short b) { + return Short.compare(a, (short) 0) != 0 ? a : b; + } + @Test static void smokeTest1() { ShortVector three = ShortVector.broadcast(SPECIES, (byte)-3); @@ -3211,7 +3215,7 @@ public class ShortMaxVectorTests extends AbstractVectorTest { static short MINReduce(short[] a, int idx) { short res = Short.MAX_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (short)Math.min(res, a[i]); + res = (short) Math.min(res, a[i]); } return res; @@ -3219,8 +3223,8 @@ public class ShortMaxVectorTests extends AbstractVectorTest { static short MINReduceAll(short[] a) { short res = Short.MAX_VALUE; - for (int i = 0; i < a.length; i++) { - res = (short)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (short) Math.min(res, MINReduce(a, i)); } return res; @@ -3242,7 +3246,7 @@ public class ShortMaxVectorTests extends AbstractVectorTest { ra = Short.MAX_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { ShortVector av = ShortVector.fromArray(SPECIES, a, i); - ra = (short)Math.min(ra, av.reduceLanes(VectorOperators.MIN)); + ra = (short) Math.min(ra, av.reduceLanes(VectorOperators.MIN)); } } @@ -3252,8 +3256,8 @@ public class ShortMaxVectorTests extends AbstractVectorTest { static short MINReduceMasked(short[] a, int idx, boolean[] mask) { short res = Short.MAX_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (short)Math.min(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (short) Math.min(res, a[i]); } return res; @@ -3261,9 +3265,8 @@ public class ShortMaxVectorTests extends AbstractVectorTest { static short MINReduceAllMasked(short[] a, boolean[] mask) { short res = Short.MAX_VALUE; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (short)Math.min(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (short) Math.min(res, MINReduceMasked(a, i, mask)); } return res; @@ -3287,7 +3290,7 @@ public class ShortMaxVectorTests extends AbstractVectorTest { ra = Short.MAX_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { ShortVector av = ShortVector.fromArray(SPECIES, a, i); - ra = (short)Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); + ra = (short) Math.min(ra, av.reduceLanes(VectorOperators.MIN, vmask)); } } @@ -3297,7 +3300,7 @@ public class ShortMaxVectorTests extends AbstractVectorTest { static short MAXReduce(short[] a, int idx) { short res = Short.MIN_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (short)Math.max(res, a[i]); + res = (short) Math.max(res, a[i]); } return res; @@ -3305,8 +3308,8 @@ public class ShortMaxVectorTests extends AbstractVectorTest { static short MAXReduceAll(short[] a) { short res = Short.MIN_VALUE; - for (int i = 0; i < a.length; i++) { - res = (short)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (short) Math.max(res, MAXReduce(a, i)); } return res; @@ -3328,7 +3331,7 @@ public class ShortMaxVectorTests extends AbstractVectorTest { ra = Short.MIN_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { ShortVector av = ShortVector.fromArray(SPECIES, a, i); - ra = (short)Math.max(ra, av.reduceLanes(VectorOperators.MAX)); + ra = (short) Math.max(ra, av.reduceLanes(VectorOperators.MAX)); } } @@ -3338,8 +3341,8 @@ public class ShortMaxVectorTests extends AbstractVectorTest { static short MAXReduceMasked(short[] a, int idx, boolean[] mask) { short res = Short.MIN_VALUE; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = (short)Math.max(res, a[i]); + if (mask[i % SPECIES.length()]) + res = (short) Math.max(res, a[i]); } return res; @@ -3347,9 +3350,8 @@ public class ShortMaxVectorTests extends AbstractVectorTest { static short MAXReduceAllMasked(short[] a, boolean[] mask) { short res = Short.MIN_VALUE; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = (short)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (short) Math.max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -3373,13 +3375,98 @@ public class ShortMaxVectorTests extends AbstractVectorTest { ra = Short.MIN_VALUE; for (int i = 0; i < a.length; i += SPECIES.length()) { ShortVector av = ShortVector.fromArray(SPECIES, a, i); - ra = (short)Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); + ra = (short) Math.max(ra, av.reduceLanes(VectorOperators.MAX, vmask)); } } assertReductionArraysEqualsMasked(r, ra, a, mask, ShortMaxVectorTests::MAXReduceMasked, ShortMaxVectorTests::MAXReduceAllMasked); } + static short FIRST_NONZEROReduce(short[] a, int idx) { + short res = (short) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = firstNonZero(res, a[i]); + } + + return res; + } + + static short FIRST_NONZEROReduceAll(short[] a) { + short res = (short) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduce(a, i)); + } + + return res; + } + @Test(dataProvider = "shortUnaryOpProvider") + static void FIRST_NONZEROReduceShortMaxVectorTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + short ra = (short) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (short) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO)); + } + } + + assertReductionArraysEquals(r, ra, a, + ShortMaxVectorTests::FIRST_NONZEROReduce, ShortMaxVectorTests::FIRST_NONZEROReduceAll); + } + static short FIRST_NONZEROReduceMasked(short[] a, int idx, boolean[] mask) { + short res = (short) 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = firstNonZero(res, a[i]); + } + + return res; + } + + static short FIRST_NONZEROReduceAllMasked(short[] a, boolean[] mask) { + short res = (short) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduceMasked(a, i, mask)); + } + + return res; + } + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void FIRST_NONZEROReduceShortMaxVectorTestsMasked(IntFunction fa, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + short ra = (short) 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = (short) 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + ra = firstNonZero(ra, av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + ShortMaxVectorTests::FIRST_NONZEROReduceMasked, ShortMaxVectorTests::FIRST_NONZEROReduceAllMasked); + } static boolean anyTrue(boolean[] a, int idx) { boolean res = false; diff --git a/test/jdk/jdk/incubator/vector/gen-template.sh b/test/jdk/jdk/incubator/vector/gen-template.sh index 544cd0dc317..51fb155fd84 100644 --- a/test/jdk/jdk/incubator/vector/gen-template.sh +++ b/test/jdk/jdk/incubator/vector/gen-template.sh @@ -55,17 +55,13 @@ compare_template="Compare" compare_masked_template="Compare-Masked" compare_broadcast_template="Compare-Broadcast" reduction_scalar="Reduction-Scalar-op" -reduction_scalar_min="Reduction-Scalar-Min-op" -reduction_scalar_max="Reduction-Scalar-Max-op" +reduction_scalar_func="Reduction-Scalar-op-func" reduction_scalar_masked="Reduction-Scalar-Masked-op" -reduction_scalar_min_masked="Reduction-Scalar-Masked-Min-op" -reduction_scalar_max_masked="Reduction-Scalar-Masked-Max-op" +reduction_scalar_masked_func="Reduction-Scalar-Masked-op-func" reduction_op="Reduction-op" -reduction_op_min="Reduction-Min-op" -reduction_op_max="Reduction-Max-op" +reduction_op_func="Reduction-op-func" reduction_op_masked="Reduction-Masked-op" -reduction_op_min_masked="Reduction-Masked-Min-op" -reduction_op_max_masked="Reduction-Masked-Max-op" +reduction_op_masked_func="Reduction-Masked-op-func" unary_math_template="Unary-op-math" binary_math_template="Binary-op-math" binary_math_broadcast_template="Binary-Broadcast-op-math" @@ -337,20 +333,12 @@ function gen_reduction_op { gen_op_tmpl $reduction_op_masked "$@" } -function gen_reduction_op_min { +function gen_reduction_op_func { echo "Generating reduction op $1 ($2)..." - gen_op_tmpl $reduction_scalar_min "$@" - gen_op_tmpl $reduction_op_min "$@" - gen_op_tmpl $reduction_scalar_min_masked "$@" - gen_op_tmpl $reduction_op_min_masked "$@" -} - -function gen_reduction_op_max { - echo "Generating reduction op $1 ($2)..." - gen_op_tmpl $reduction_scalar_max "$@" - gen_op_tmpl $reduction_op_max "$@" - gen_op_tmpl $reduction_scalar_max_masked "$@" - gen_op_tmpl $reduction_op_max_masked "$@" + gen_op_tmpl $reduction_scalar_func "$@" + gen_op_tmpl $reduction_op_func "$@" + gen_op_tmpl $reduction_scalar_masked_func "$@" + gen_op_tmpl $reduction_op_masked_func "$@" } function gen_bool_reduction_op { @@ -462,9 +450,9 @@ gen_reduction_op "OR" "|" "BITWISE" "0" gen_reduction_op "XOR" "^" "BITWISE" "0" gen_reduction_op "ADD" "+" "" "0" gen_reduction_op "MUL" "*" "" "1" -gen_reduction_op_min "MIN" "" "" "\$Wideboxtype\$.\$MaxValue\$" -gen_reduction_op_max "MAX" "" "" "\$Wideboxtype\$.\$MinValue\$" -#gen_reduction_op "reduce_FIRST_NONZERO" "lanewise_FIRST_NONZERO" "{#if[FP]?Double.doubleToLongBits}(a)=0?a:b" "" "1" +gen_reduction_op_func "MIN" "(\$type\$) Math.min" "" "\$Wideboxtype\$.\$MaxValue\$" +gen_reduction_op_func "MAX" "(\$type\$) Math.max" "" "\$Wideboxtype\$.\$MinValue\$" +gen_reduction_op_func "FIRST_NONZERO" "firstNonZero" "" "(\$type\$) 0" # Boolean reductions. gen_bool_reduction_op "anyTrue" "|" "BITWISE" "false" diff --git a/test/jdk/jdk/incubator/vector/templates/Kernel-Reduction-Masked-Min-op.template b/test/jdk/jdk/incubator/vector/templates/Kernel-Reduction-Masked-Min-op.template deleted file mode 100644 index 041b61da0e1..00000000000 --- a/test/jdk/jdk/incubator/vector/templates/Kernel-Reduction-Masked-Min-op.template +++ /dev/null @@ -1,21 +0,0 @@ - $type$[] a = fa.apply(SPECIES.length()); - $type$[] r = fr.apply(SPECIES.length()); - boolean[] mask = fm.apply(SPECIES.length()); - VectorMask<$Wideboxtype$> vmask = VectorMask.fromArray(SPECIES, mask, 0); - $type$ ra = [[TEST_INIT]]; - - for (int ic = 0; ic < INVOC_COUNT; ic++) { - for (int i = 0; i < a.length; i += SPECIES.length()) { - $abstractvectortype$ av = $abstractvectortype$.fromArray(SPECIES, a, i); - r[i] = av.reduceLanes(VectorOperators.[[TEST]], vmask); - } - } - - for (int ic = 0; ic < INVOC_COUNT; ic++) { - ra = [[TEST_INIT]]; - for (int i = 0; i < a.length; i += SPECIES.length()) { - $abstractvectortype$ av = $abstractvectortype$.fromArray(SPECIES, a, i); - ra = ($type$)Math.min(ra, av.reduceLanes(VectorOperators.[[TEST]], vmask)); - } - } - diff --git a/test/jdk/jdk/incubator/vector/templates/Kernel-Reduction-Masked-Max-op.template b/test/jdk/jdk/incubator/vector/templates/Kernel-Reduction-Masked-op-func.template similarity index 90% rename from test/jdk/jdk/incubator/vector/templates/Kernel-Reduction-Masked-Max-op.template rename to test/jdk/jdk/incubator/vector/templates/Kernel-Reduction-Masked-op-func.template index d317aaf4f8a..bf03a4d0430 100644 --- a/test/jdk/jdk/incubator/vector/templates/Kernel-Reduction-Masked-Max-op.template +++ b/test/jdk/jdk/incubator/vector/templates/Kernel-Reduction-Masked-op-func.template @@ -15,7 +15,7 @@ ra = [[TEST_INIT]]; for (int i = 0; i < a.length; i += SPECIES.length()) { $abstractvectortype$ av = $abstractvectortype$.fromArray(SPECIES, a, i); - ra = ($type$)Math.max(ra, av.reduceLanes(VectorOperators.[[TEST]], vmask)); + ra = [[TEST_OP]](ra, av.reduceLanes(VectorOperators.[[TEST]], vmask)); } } diff --git a/test/jdk/jdk/incubator/vector/templates/Kernel-Reduction-Min-op.template b/test/jdk/jdk/incubator/vector/templates/Kernel-Reduction-Min-op.template deleted file mode 100644 index d6d53e4ef21..00000000000 --- a/test/jdk/jdk/incubator/vector/templates/Kernel-Reduction-Min-op.template +++ /dev/null @@ -1,19 +0,0 @@ - $type$[] a = fa.apply(SPECIES.length()); - $type$[] r = fr.apply(SPECIES.length()); - $type$ ra = [[TEST_INIT]]; - - for (int ic = 0; ic < INVOC_COUNT; ic++) { - for (int i = 0; i < a.length; i += SPECIES.length()) { - $abstractvectortype$ av = $abstractvectortype$.fromArray(SPECIES, a, i); - r[i] = av.reduceLanes(VectorOperators.[[TEST]]); - } - } - - for (int ic = 0; ic < INVOC_COUNT; ic++) { - ra = [[TEST_INIT]]; - for (int i = 0; i < a.length; i += SPECIES.length()) { - $abstractvectortype$ av = $abstractvectortype$.fromArray(SPECIES, a, i); - ra = ($type$)Math.min(ra, av.reduceLanes(VectorOperators.[[TEST]])); - } - } - diff --git a/test/jdk/jdk/incubator/vector/templates/Kernel-Reduction-Max-op.template b/test/jdk/jdk/incubator/vector/templates/Kernel-Reduction-op-func.template similarity index 89% rename from test/jdk/jdk/incubator/vector/templates/Kernel-Reduction-Max-op.template rename to test/jdk/jdk/incubator/vector/templates/Kernel-Reduction-op-func.template index 3af5b8cfde9..7082ff0795e 100644 --- a/test/jdk/jdk/incubator/vector/templates/Kernel-Reduction-Max-op.template +++ b/test/jdk/jdk/incubator/vector/templates/Kernel-Reduction-op-func.template @@ -13,7 +13,7 @@ ra = [[TEST_INIT]]; for (int i = 0; i < a.length; i += SPECIES.length()) { $abstractvectortype$ av = $abstractvectortype$.fromArray(SPECIES, a, i); - ra = ($type$)Math.max(ra, av.reduceLanes(VectorOperators.[[TEST]])); + ra = [[TEST_OP]](ra, av.reduceLanes(VectorOperators.[[TEST]])); } } diff --git a/test/jdk/jdk/incubator/vector/templates/Unit-Reduction-Masked-Min-op.template b/test/jdk/jdk/incubator/vector/templates/Unit-Reduction-Masked-Min-op.template deleted file mode 100644 index 70ffa79bf6f..00000000000 --- a/test/jdk/jdk/incubator/vector/templates/Unit-Reduction-Masked-Min-op.template +++ /dev/null @@ -1,6 +0,0 @@ - @Test(dataProvider = "$type$UnaryOpMaskProvider") - static void [[TEST]]Reduce$vectorteststype$Masked(IntFunction<$type$[]> fa, IntFunction fm) { -[[KERNEL]] - assertReductionArraysEqualsMasked(r, ra, a, mask, - $vectorteststype$::[[TEST]]ReduceMasked, $vectorteststype$::[[TEST]]ReduceAllMasked); - } diff --git a/test/jdk/jdk/incubator/vector/templates/Unit-Reduction-Masked-Max-op.template b/test/jdk/jdk/incubator/vector/templates/Unit-Reduction-Masked-op-func.template similarity index 100% rename from test/jdk/jdk/incubator/vector/templates/Unit-Reduction-Masked-Max-op.template rename to test/jdk/jdk/incubator/vector/templates/Unit-Reduction-Masked-op-func.template diff --git a/test/jdk/jdk/incubator/vector/templates/Unit-Reduction-Min-op.template b/test/jdk/jdk/incubator/vector/templates/Unit-Reduction-Min-op.template deleted file mode 100644 index b86248f3f09..00000000000 --- a/test/jdk/jdk/incubator/vector/templates/Unit-Reduction-Min-op.template +++ /dev/null @@ -1,6 +0,0 @@ - @Test(dataProvider = "$type$UnaryOpProvider") - static void [[TEST]]Reduce$vectorteststype$(IntFunction<$type$[]> fa) { -[[KERNEL]] - assertReductionArraysEquals(r, ra, a, - $vectorteststype$::[[TEST]]Reduce, $vectorteststype$::[[TEST]]ReduceAll); - } diff --git a/test/jdk/jdk/incubator/vector/templates/Unit-Reduction-Scalar-Masked-Min-op.template b/test/jdk/jdk/incubator/vector/templates/Unit-Reduction-Scalar-Masked-Min-op.template deleted file mode 100644 index 6a491c05734..00000000000 --- a/test/jdk/jdk/incubator/vector/templates/Unit-Reduction-Scalar-Masked-Min-op.template +++ /dev/null @@ -1,19 +0,0 @@ - static $type$ [[TEST]]ReduceMasked($type$[] a, int idx, boolean[] mask) { - $type$ res = [[TEST_INIT]]; - for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = ($type$)Math.min(res, a[i]); - } - - return res; - } - - static $type$ [[TEST]]ReduceAllMasked($type$[] a, boolean[] mask) { - $type$ res = [[TEST_INIT]]; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = ($type$)Math.min(res, a[i]); - } - - return res; - } diff --git a/test/jdk/jdk/incubator/vector/templates/Unit-Reduction-Scalar-Masked-Max-op.template b/test/jdk/jdk/incubator/vector/templates/Unit-Reduction-Scalar-Masked-op-func.template similarity index 60% rename from test/jdk/jdk/incubator/vector/templates/Unit-Reduction-Scalar-Masked-Max-op.template rename to test/jdk/jdk/incubator/vector/templates/Unit-Reduction-Scalar-Masked-op-func.template index b4a2c764b84..00b8ed390bc 100644 --- a/test/jdk/jdk/incubator/vector/templates/Unit-Reduction-Scalar-Masked-Max-op.template +++ b/test/jdk/jdk/incubator/vector/templates/Unit-Reduction-Scalar-Masked-op-func.template @@ -1,8 +1,8 @@ static $type$ [[TEST]]ReduceMasked($type$[] a, int idx, boolean[] mask) { $type$ res = [[TEST_INIT]]; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res = ($type$)Math.max(res, a[i]); + if (mask[i % SPECIES.length()]) + res = [[TEST_OP]](res, a[i]); } return res; @@ -10,9 +10,8 @@ static $type$ [[TEST]]ReduceAllMasked($type$[] a, boolean[] mask) { $type$ res = [[TEST_INIT]]; - for (int i = 0; i < a.length; i++) { - if(mask[i % SPECIES.length()]) - res = ($type$)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = [[TEST_OP]](res, [[TEST]]ReduceMasked(a, i, mask)); } return res; diff --git a/test/jdk/jdk/incubator/vector/templates/Unit-Reduction-Scalar-Min-op.template b/test/jdk/jdk/incubator/vector/templates/Unit-Reduction-Scalar-Min-op.template deleted file mode 100644 index 9e84bd13034..00000000000 --- a/test/jdk/jdk/incubator/vector/templates/Unit-Reduction-Scalar-Min-op.template +++ /dev/null @@ -1,17 +0,0 @@ - static $type$ [[TEST]]Reduce($type$[] a, int idx) { - $type$ res = [[TEST_INIT]]; - for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = ($type$)Math.min(res, a[i]); - } - - return res; - } - - static $type$ [[TEST]]ReduceAll($type$[] a) { - $type$ res = [[TEST_INIT]]; - for (int i = 0; i < a.length; i++) { - res = ($type$)Math.min(res, a[i]); - } - - return res; - } diff --git a/test/jdk/jdk/incubator/vector/templates/Unit-Reduction-Scalar-Max-op.template b/test/jdk/jdk/incubator/vector/templates/Unit-Reduction-Scalar-op-func.template similarity index 65% rename from test/jdk/jdk/incubator/vector/templates/Unit-Reduction-Scalar-Max-op.template rename to test/jdk/jdk/incubator/vector/templates/Unit-Reduction-Scalar-op-func.template index 528f4ddb5f3..2abdcd295b4 100644 --- a/test/jdk/jdk/incubator/vector/templates/Unit-Reduction-Scalar-Max-op.template +++ b/test/jdk/jdk/incubator/vector/templates/Unit-Reduction-Scalar-op-func.template @@ -1,7 +1,7 @@ static $type$ [[TEST]]Reduce($type$[] a, int idx) { $type$ res = [[TEST_INIT]]; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = ($type$)Math.max(res, a[i]); + res = [[TEST_OP]](res, a[i]); } return res; @@ -9,8 +9,8 @@ static $type$ [[TEST]]ReduceAll($type$[] a) { $type$ res = [[TEST_INIT]]; - for (int i = 0; i < a.length; i++) { - res = ($type$)Math.max(res, a[i]); + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = [[TEST_OP]](res, [[TEST]]Reduce(a, i)); } return res; diff --git a/test/jdk/jdk/incubator/vector/templates/Unit-Reduction-Max-op.template b/test/jdk/jdk/incubator/vector/templates/Unit-Reduction-op-func.template similarity index 100% rename from test/jdk/jdk/incubator/vector/templates/Unit-Reduction-Max-op.template rename to test/jdk/jdk/incubator/vector/templates/Unit-Reduction-op-func.template diff --git a/test/jdk/jdk/incubator/vector/templates/Unit-header.template b/test/jdk/jdk/incubator/vector/templates/Unit-header.template index f73d697e2a7..239596bf433 100644 --- a/test/jdk/jdk/incubator/vector/templates/Unit-header.template +++ b/test/jdk/jdk/incubator/vector/templates/Unit-header.template @@ -1451,6 +1451,10 @@ public class $vectorteststype$ extends AbstractVectorTest { } #end[!FP] + static $type$ firstNonZero($type$ a, $type$ b) { + return $Boxtype$.compare(a, ($type$) 0) != 0 ? a : b; + } + @Test static void smokeTest1() { $abstractvectortype$ three = $abstractvectortype$.broadcast(SPECIES, (byte)-3); -- GitLab From 58c2bd315836b9c4fbffa212497fd84c8f589c17 Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Thu, 10 Feb 2022 22:51:39 +0000 Subject: [PATCH 458/564] 8281536: JFR: Improve jdk.jfr.ContentType documentation Reviewed-by: mgronlun --- .../share/classes/jdk/jfr/ContentType.java | 16 ++++ .../jdk/jfr/snippet-files/Snippets.java | 82 +++++++++++++++++++ 2 files changed, 98 insertions(+) diff --git a/src/jdk.jfr/share/classes/jdk/jfr/ContentType.java b/src/jdk.jfr/share/classes/jdk/jfr/ContentType.java index 13a5ae226ba..3580997ad24 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/ContentType.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/ContentType.java @@ -33,6 +33,22 @@ import java.lang.annotation.Target; /** * Meta annotation, specifies that an annotation represents a content type, such * as a time span or a frequency. + *

    + * The following example shows how a temperature content type can be created and + * used. + *

    + * First declare a temperature annotation using the {@code ContentType} + * annotation: + * + * {@snippet class="Snippets" region="ContentTypeDeclaration"} + * + * Then declare an event, annotate a field and commit the data: + * + * {@snippet class="Snippets" region="ContentTypeEvent"} + * + * Finally, inspect the annotation when displaying event data: + * + * {@snippet class="Snippets" region="ContentTypeConsumption"} * * @since 9 */ diff --git a/src/jdk.jfr/share/classes/jdk/jfr/snippet-files/Snippets.java b/src/jdk.jfr/share/classes/jdk/jfr/snippet-files/Snippets.java index b2d4fff29de..ef95e2ffb35 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/snippet-files/Snippets.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/snippet-files/Snippets.java @@ -32,7 +32,10 @@ import jdk.jfr.Name; import jdk.jfr.Label; import jdk.jfr.Description; import jdk.jfr.Category; +import jdk.jfr.ContentType; +import jdk.jfr.Period; import jdk.jfr.Recording; +import jdk.jfr.StackTrace; import jdk.jfr.MetadataDefinition; import jdk.jfr.Relational; import jdk.jfr.consumer.RecordingFile; @@ -40,6 +43,7 @@ import jdk.jfr.Configuration; import jdk.jfr.SettingDefinition; import jdk.jfr.SettingControl; import jdk.jfr.FlightRecorder; +import jdk.jfr.consumer.RecordedEvent; import java.io.IOException; import java.nio.file.Files; @@ -78,6 +82,84 @@ public class Snippets { // @end } + record CPU(String id, float temperature) { + } + + private static List listCPUs() { + return List.of(); + } + + // @start region="ContentTypeDeclaration" + @MetadataDefinition + @ContentType + @Name("com.example.Temperature") + @Label("Temperature") + @Target(ElementType.FIELD) + @Retention(RetentionPolicy.RUNTIME) + public @interface Temperature { + public final static String KELVIN = "KELVIN"; + public final static String CELSIUS = "CELSIUS"; + public final static String FAHRENEHIT = "FAHRENHEIT"; + + String value() default CELSIUS; + } + // @end + + // @start region="ContentTypeEvent" + @Name("com.example.CPU") + @Label("CPU") + @Category({ "Hardware", "CPU" }) + @Period("1 s") + @StackTrace(false) + static public class CPUEvent extends Event { + @Label("ID") + String id; + + @Temperature(Temperature.KELVIN) + @Label("Temperature") + float temperature; + } + + public static void main(String... args) throws InterruptedException { + FlightRecorder.addPeriodicEvent(CPUEvent.class, () -> { + for (var cpu : listCPUs()) { + CPUEvent event = new CPUEvent(); + event.id = cpu.id(); + event.temperature = cpu.temperature(); // in Kelvin + event.commit(); + } + }); + Thread.sleep(10_000); + } + // @end + + // @start region="ContentTypeConsumption" + void printTemperaturesInCelsius(Path file) throws IOException { + for (RecordedEvent event : RecordingFile.readAllEvents(file)) { + for (ValueDescriptor field : event.getEventType().getFields()) { + for (AnnotationElement ae : field.getAnnotationElements()) { + ContentType type = ae.getAnnotation(ContentType.class); + if (type != null) { + if (ae.getTypeName().equals("com.example.Temperature")) { + double value = event.getDouble(field.getName()); + String unit = (String) ae.getValue("value"); + double celsius = switch (unit) { + case "CELSIUS" -> value; + case "KELVIN" -> value - 273.15; + case "FAHRENHEIT" -> (value - 32) / 1.8; + default -> throw new IllegalStateException("Unknown temperature unit '" + unit + "'"); + }; + System.out.println(celsius + " C"); + } else { + System.err.println("Can't format content type " + ae.getTypeName() + " for field " + field.getName()); + } + } + } + } + } + } + // @end + // @start region="EventOverview" public class Example { -- GitLab From 84868e39be4522ba87e603beea0f8da9efa43b6d Mon Sep 17 00:00:00 2001 From: David Holmes Date: Thu, 10 Feb 2022 23:23:48 +0000 Subject: [PATCH 459/564] 8281275: Upgrading from 8 to 11 no longer accepts '/' as filepath separator in gc paths Reviewed-by: shade, dcubed --- .../share/logging/logConfiguration.cpp | 8 +++--- .../gtest/logging/test_logConfiguration.cpp | 25 ++++++++++++++++++- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/hotspot/share/logging/logConfiguration.cpp b/src/hotspot/share/logging/logConfiguration.cpp index a46af599215..518e7979ef8 100644 --- a/src/hotspot/share/logging/logConfiguration.cpp +++ b/src/hotspot/share/logging/logConfiguration.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, 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,9 +365,9 @@ bool LogConfiguration::parse_command_line_arguments(const char* opts) { // Find the next colon or quote char* next = strpbrk(str, ":\""); #ifdef _WINDOWS - // Skip over Windows paths such as "C:\..." - // Handle both C:\... and file=C:\..." - if (next != NULL && next[0] == ':' && next[1] == '\\') { + // Skip over Windows paths such as "C:\..." and "C:/...". + // Handles both "C:\..." and "file=C:\...". + if (next != NULL && next[0] == ':' && (next[1] == '\\' || next[1] == '/')) { if (next == str + 1 || (strncmp(str, "file=", 5) == 0)) { next = strpbrk(next + 1, ":\""); } diff --git a/test/hotspot/gtest/logging/test_logConfiguration.cpp b/test/hotspot/gtest/logging/test_logConfiguration.cpp index 0d092dc0d75..38997af68cb 100644 --- a/test/hotspot/gtest/logging/test_logConfiguration.cpp +++ b/test/hotspot/gtest/logging/test_logConfiguration.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, 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 @@ -359,6 +359,29 @@ TEST_VM_F(LogConfigurationTest, parse_command_line_arguments) { ret = jio_snprintf(buf, sizeof(buf), ":%s", TestLogFileName); ASSERT_NE(-1, ret); EXPECT_TRUE(LogConfiguration::parse_command_line_arguments(buf)); + +#ifdef _WINDOWS + // We need to test the special-case parsing for drive letters in + // log file paths e.g. c:\log.txt and c:/log.txt. Our temp directory + // based TestLogFileName should already be the \ format (we print it + // below to visually verify) so we only need to convert to /. + printf("Checked: %s\n", buf); + // First disable logging so the current log file will be closed and we + // can delete it, so that UL won't try to perform log file rotation. + // The rotated file would not be auto-deleted. + set_log_config(TestLogFileName, "all=off"); + delete_file(TestLogFileName); + + // now convert \ to / + char* current_pos = strchr(buf,'\\'); + while (current_pos != nullptr) { + *current_pos = '/'; + current_pos = strchr(current_pos + 1, '\\'); + } + printf("Checking: %s\n", buf); + EXPECT_TRUE(LogConfiguration::parse_command_line_arguments(buf)); +#endif + } // Test split up log configuration arguments -- GitLab From eee6a5622dca683d4d6a701daa48e09e8d17b54e Mon Sep 17 00:00:00 2001 From: Thomas Stuefe Date: Fri, 11 Feb 2022 05:34:27 +0000 Subject: [PATCH 460/564] 8281522: Rename ADLC classes which have the same name as hotspot variants Reviewed-by: neliasso, kvn --- .../share/adlc/{arena.cpp => adlArena.cpp} | 94 +++++++++---------- .../share/adlc/{arena.hpp => adlArena.hpp} | 56 +++++------ src/hotspot/share/adlc/adlc.hpp | 2 +- src/hotspot/share/adlc/adlparse.cpp | 16 ++-- src/hotspot/share/adlc/dfa.cpp | 6 +- src/hotspot/share/adlc/dict2.cpp | 4 +- src/hotspot/share/adlc/dict2.hpp | 6 +- src/hotspot/share/adlc/forms.cpp | 14 +-- src/hotspot/share/adlc/forms.hpp | 10 +- src/hotspot/share/adlc/formsopt.cpp | 4 +- src/hotspot/share/adlc/formssel.cpp | 6 +- 11 files changed, 109 insertions(+), 109 deletions(-) rename src/hotspot/share/adlc/{arena.cpp => adlArena.cpp} (66%) rename src/hotspot/share/adlc/{arena.hpp => adlArena.hpp} (73%) diff --git a/src/hotspot/share/adlc/arena.cpp b/src/hotspot/share/adlc/adlArena.cpp similarity index 66% rename from src/hotspot/share/adlc/arena.cpp rename to src/hotspot/share/adlc/adlArena.cpp index 60a546e7961..7c6e9419d4f 100644 --- a/src/hotspot/share/adlc/arena.cpp +++ b/src/hotspot/share/adlc/adlArena.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ #include "adlc.hpp" -void* AllocateHeap(size_t size) { +void* AdlAllocateHeap(size_t size) { unsigned char* ptr = (unsigned char*) malloc(size); if (ptr == NULL && size != 0) { fprintf(stderr, "Error: Out of memory in ADLC\n"); // logging can cause crash! @@ -34,7 +34,7 @@ void* AllocateHeap(size_t size) { return ptr; } -void* ReAllocateHeap(void* old_ptr, size_t size) { +void* AdlReAllocateHeap(void* old_ptr, size_t size) { unsigned char* ptr = (unsigned char*) realloc(old_ptr, size); if (ptr == NULL && size != 0) { fprintf(stderr, "Error: Out of memory in ADLC\n"); // logging can cause crash! @@ -44,24 +44,24 @@ void* ReAllocateHeap(void* old_ptr, size_t size) { return ptr; } -void* Chunk::operator new(size_t requested_size, size_t length) throw() { - return CHeapObj::operator new(requested_size + length); +void* AdlChunk::operator new(size_t requested_size, size_t length) throw() { + return AdlCHeapObj::operator new(requested_size + length); } -void Chunk::operator delete(void* p, size_t length) { - CHeapObj::operator delete(p); +void AdlChunk::operator delete(void* p, size_t length) { + AdlCHeapObj::operator delete(p); } -Chunk::Chunk(size_t length) { +AdlChunk::AdlChunk(size_t length) { _next = NULL; // Chain on the linked list _len = length; // Save actual size } //------------------------------chop------------------------------------------- -void Chunk::chop() { - Chunk *k = this; +void AdlChunk::chop() { + AdlChunk *k = this; while( k ) { - Chunk *tmp = k->_next; + AdlChunk *tmp = k->_next; // clear out this chunk (to detect allocation bugs) memset(k, 0xBE, k->_len); free(k); // Free chunk (was malloc'd) @@ -69,52 +69,52 @@ void Chunk::chop() { } } -void Chunk::next_chop() { +void AdlChunk::next_chop() { _next->chop(); _next = NULL; } -//------------------------------Arena------------------------------------------ -Arena::Arena( size_t init_size ) { +//------------------------------AdlArena------------------------------------------ +AdlArena::AdlArena( size_t init_size ) { init_size = (init_size+3) & ~3; - _first = _chunk = new (init_size) Chunk(init_size); + _first = _chunk = new (init_size) AdlChunk(init_size); _hwm = _chunk->bottom(); // Save the cached hwm, max _max = _chunk->top(); set_size_in_bytes(init_size); } -Arena::Arena() { - _first = _chunk = new (Chunk::init_size) Chunk(Chunk::init_size); +AdlArena::AdlArena() { + _first = _chunk = new (AdlChunk::init_size) AdlChunk(AdlChunk::init_size); _hwm = _chunk->bottom(); // Save the cached hwm, max _max = _chunk->top(); - set_size_in_bytes(Chunk::init_size); + set_size_in_bytes(AdlChunk::init_size); } -Arena::Arena( Arena *a ) +AdlArena::AdlArena( AdlArena *a ) : _chunk(a->_chunk), _hwm(a->_hwm), _max(a->_max), _first(a->_first) { set_size_in_bytes(a->size_in_bytes()); } //------------------------------used------------------------------------------- -// Total of all Chunks in arena -size_t Arena::used() const { - size_t sum = _chunk->_len - (_max-_hwm); // Size leftover in this Chunk - Chunk *k = _first; - while( k != _chunk) { // Whilst have Chunks in a row - sum += k->_len; // Total size of this Chunk - k = k->_next; // Bump along to next Chunk +// Total of all AdlChunks in arena +size_t AdlArena::used() const { + size_t sum = _chunk->_len - (_max-_hwm); // Size leftover in this AdlChunk + AdlChunk *k = _first; + while( k != _chunk) { // Whilst have AdlChunks in a row + sum += k->_len; // Total size of this AdlChunk + k = k->_next; // Bump along to next AdlChunk } return sum; // Return total consumed space. } //------------------------------grow------------------------------------------- -// Grow a new Chunk -void* Arena::grow( size_t x ) { +// Grow a new AdlChunk +void* AdlArena::grow( size_t x ) { // Get minimal required size. Either real big, or even bigger for giant objs - size_t len = max(x, Chunk::size); + size_t len = max(x, AdlChunk::size); - Chunk *k = _chunk; // Get filled-up chunk address - _chunk = new (len) Chunk(len); + AdlChunk *k = _chunk; // Get filled-up chunk address + _chunk = new (len) AdlChunk(len); if( k ) k->_next = _chunk; // Append new chunk to end of linked list else _first = _chunk; @@ -127,8 +127,8 @@ void* Arena::grow( size_t x ) { } //------------------------------calloc----------------------------------------- -// Allocate zeroed storage in Arena -void *Arena::Acalloc( size_t items, size_t x ) { +// Allocate zeroed storage in AdlArena +void *AdlArena::Acalloc( size_t items, size_t x ) { size_t z = items*x; // Total size needed void *ptr = Amalloc(z); // Get space memset( ptr, 0, z ); // Zap space @@ -136,8 +136,8 @@ void *Arena::Acalloc( size_t items, size_t x ) { } //------------------------------realloc---------------------------------------- -// Reallocate storage in Arena. -void *Arena::Arealloc( void *old_ptr, size_t old_size, size_t new_size ) { +// Reallocate storage in AdlArena. +void *AdlArena::Arealloc( void *old_ptr, size_t old_size, size_t new_size ) { char *c_old = (char*)old_ptr; // Handy name // Stupid fast special case if( new_size <= old_size ) { // Shrink in-place @@ -161,32 +161,32 @@ void *Arena::Arealloc( void *old_ptr, size_t old_size, size_t new_size ) { } //------------------------------reset------------------------------------------ -// Reset this Arena to empty, and return this Arenas guts in a new Arena. -Arena *Arena::reset(void) { - Arena *a = new Arena(this); // New empty arena +// Reset this AdlArena to empty, and return this AdlArenas guts in a new AdlArena. +AdlArena *AdlArena::reset(void) { + AdlArena *a = new AdlArena(this); // New empty arena _first = _chunk = NULL; // Normal, new-arena initialization _hwm = _max = NULL; - return a; // Return Arena with guts + return a; // Return AdlArena with guts } //------------------------------contains--------------------------------------- -// Determine if pointer belongs to this Arena or not. -bool Arena::contains( const void *ptr ) const { +// Determine if pointer belongs to this AdlArena or not. +bool AdlArena::contains( const void *ptr ) const { if( (void*)_chunk->bottom() <= ptr && ptr < (void*)_hwm ) return true; // Check for in this chunk - for( Chunk *c = _first; c; c = c->_next ) + for( AdlChunk *c = _first; c; c = c->_next ) if( (void*)c->bottom() <= ptr && ptr < (void*)c->top()) - return true; // Check for every chunk in Arena - return false; // Not in any Chunk, so not in Arena + return true; // Check for every chunk in AdlArena + return false; // Not in any AdlChunk, so not in AdlArena } //----------------------------------------------------------------------------- // CHeapObj -void* CHeapObj::operator new(size_t size) throw() { - return (void *) AllocateHeap(size); +void* AdlCHeapObj::operator new(size_t size) throw() { + return (void *) AdlAllocateHeap(size); } -void CHeapObj::operator delete(void* p){ +void AdlCHeapObj::operator delete(void* p){ free(p); } diff --git a/src/hotspot/share/adlc/arena.hpp b/src/hotspot/share/adlc/adlArena.hpp similarity index 73% rename from src/hotspot/share/adlc/arena.hpp rename to src/hotspot/share/adlc/adlArena.hpp index 1fa99ed0e24..254f414f707 100644 --- a/src/hotspot/share/adlc/arena.hpp +++ b/src/hotspot/share/adlc/adlArena.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,11 +22,11 @@ * */ -#ifndef SHARE_ADLC_ARENA_HPP -#define SHARE_ADLC_ARENA_HPP +#ifndef SHARE_ADLC_ADLARENA_HPP +#define SHARE_ADLC_ADLARENA_HPP -void* AllocateHeap(size_t size); -void* ReAllocateHeap(void* old_ptr, size_t size); +void* AdlAllocateHeap(size_t size); +void* AdlReAllocateHeap(void* old_ptr, size_t size); // All classes in adlc may be derived // from one of the following allocation classes: @@ -35,10 +35,10 @@ void* ReAllocateHeap(void* old_ptr, size_t size); // - CHeapObj // // For classes used as name spaces. -// - AllStatic +// - AdlAllStatic // -class CHeapObj { +class AdlCHeapObj { public: void* operator new(size_t size) throw(); void operator delete(void* p); @@ -47,16 +47,16 @@ class CHeapObj { // Base class for classes that constitute name spaces. -class AllStatic { +class AdlAllStatic { public: void* operator new(size_t size) throw(); void operator delete(void* p); }; -//------------------------------Chunk------------------------------------------ +//------------------------------AdlChunk------------------------------------------ // Linked list of raw memory chunks -class Chunk: public CHeapObj { +class AdlChunk: public AdlCHeapObj { private: // This ordinary operator delete is needed even though not used, so the // below two-argument operator delete will be treated as a placement @@ -65,41 +65,41 @@ class Chunk: public CHeapObj { public: void* operator new(size_t size, size_t length) throw(); void operator delete(void* p, size_t length); - Chunk(size_t length); + AdlChunk(size_t length); enum { init_size = 1*1024, // Size of first chunk - size = 32*1024 // Default size of an Arena chunk (following the first) + size = 32*1024 // Default size of an AdlArena chunk (following the first) }; - Chunk* _next; // Next Chunk in list - size_t _len; // Size of this Chunk + AdlChunk* _next; // Next AdlChunk in list + size_t _len; // Size of this AdlChunk void chop(); // Chop this chunk void next_chop(); // Chop next chunk // Boundaries of data area (possibly unused) - char* bottom() const { return ((char*) this) + sizeof(Chunk); } + char* bottom() const { return ((char*) this) + sizeof(AdlChunk); } char* top() const { return bottom() + _len; } }; -//------------------------------Arena------------------------------------------ +//------------------------------AdlArena------------------------------------------ // Fast allocation of memory -class Arena: public CHeapObj { +class AdlArena: public AdlCHeapObj { protected: friend class ResourceMark; friend class HandleMark; friend class NoHandleMark; - Chunk *_first; // First chunk - Chunk *_chunk; // current chunk + AdlChunk *_first; // First chunk + AdlChunk *_chunk; // current chunk char *_hwm, *_max; // High water mark and max in current chunk - void* grow(size_t x); // Get a new Chunk of at least size x + void* grow(size_t x); // Get a new AdlChunk of at least size x size_t _size_in_bytes; // Size of arena (used for memory usage tracing) public: - Arena(); - Arena(size_t init_size); - Arena(Arena *old); - ~Arena() { _first->chop(); } + AdlArena(); + AdlArena(size_t init_size); + AdlArena(AdlArena *old); + ~AdlArena() { _first->chop(); } char* hwm() const { return _hwm; } // Fast allocate in the arena. Common case is: pointer test + increment. @@ -137,10 +137,10 @@ public: void *Acalloc( size_t items, size_t x ); void *Arealloc( void *old_ptr, size_t old_size, size_t new_size ); - // Reset this Arena to empty, and return this Arenas guts in a new Arena. - Arena *reset(void); + // Reset this AdlArena to empty, and return this AdlArenas guts in a new AdlArena. + AdlArena *reset(void); - // Determine if pointer belongs to this Arena or not. + // Determine if pointer belongs to this AdlArena or not. bool contains( const void *ptr ) const; // Total of all chunks in use (not thread-safe) @@ -151,4 +151,4 @@ public: void set_size_in_bytes(size_t size) { _size_in_bytes = size; } }; -#endif // SHARE_ADLC_ARENA_HPP +#endif // SHARE_ADLC_ADLARENA_HPP diff --git a/src/hotspot/share/adlc/adlc.hpp b/src/hotspot/share/adlc/adlc.hpp index 297d5cb0133..19567f05d40 100644 --- a/src/hotspot/share/adlc/adlc.hpp +++ b/src/hotspot/share/adlc/adlc.hpp @@ -93,7 +93,7 @@ typedef unsigned int uintptr_t; #define max(a, b) (((a)>(b)) ? (a) : (b)) // ADLC components -#include "arena.hpp" +#include "adlArena.hpp" #include "opto/adlcVMDeps.hpp" #include "filebuff.hpp" #include "dict2.hpp" diff --git a/src/hotspot/share/adlc/adlparse.cpp b/src/hotspot/share/adlc/adlparse.cpp index ecb722c56b2..283713bb1f8 100644 --- a/src/hotspot/share/adlc/adlparse.cpp +++ b/src/hotspot/share/adlc/adlparse.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -211,7 +211,7 @@ void ADLParser::instr_parse(void) { return; } assert(match_rules_cnt < 100," too many match rule clones"); - char* buf = (char*) AllocateHeap(strlen(instr->_ident) + 4); + char* buf = (char*) AdlAllocateHeap(strlen(instr->_ident) + 4); sprintf(buf, "%s_%d", instr->_ident, match_rules_cnt++); rule->_result = buf; // Check for commutative operations with tree operands. @@ -2805,7 +2805,7 @@ void ADLParser::ins_encode_parse_block(InstructForm& inst) { // Create a new encoding name based on the name of the instruction // definition, which should be unique. const char* prefix = "__ins_encode_"; - char* ec_name = (char*) AllocateHeap(strlen(inst._ident) + strlen(prefix) + 1); + char* ec_name = (char*) AdlAllocateHeap(strlen(inst._ident) + strlen(prefix) + 1); sprintf(ec_name, "%s%s", prefix, inst._ident); assert(_AD._encode->encClass(ec_name) == NULL, "shouldn't already exist"); @@ -3276,7 +3276,7 @@ void ADLParser::constant_parse(InstructForm& inst) { // Create a new encoding name based on the name of the instruction // definition, which should be unique. const char* prefix = "__constant_"; - char* ec_name = (char*) AllocateHeap(strlen(inst._ident) + strlen(prefix) + 1); + char* ec_name = (char*) AdlAllocateHeap(strlen(inst._ident) + strlen(prefix) + 1); sprintf(ec_name, "%s%s", prefix, inst._ident); assert(_AD._encode->encClass(ec_name) == NULL, "shouldn't already exist"); @@ -4409,7 +4409,7 @@ char* ADLParser::find_cpp_block(const char* description) { if (_AD._adlocation_debug) { char* location = get_line_string(line); char* end_loc = end_line_marker(); - char* result = (char *)AllocateHeap(strlen(location) + strlen(cppBlock) + strlen(end_loc) + 1); + char* result = (char *)AdlAllocateHeap(strlen(location) + strlen(cppBlock) + strlen(end_loc) + 1); strcpy(result, location); strcat(result, cppBlock); strcat(result, end_loc); @@ -4498,7 +4498,7 @@ char *ADLParser::get_paren_expr(const char *description, bool include_location) // Prepend location descriptor, for debugging. char* location = get_line_string(line); char* end_loc = end_line_marker(); - char* result = (char *)AllocateHeap(strlen(location) + strlen(token2) + strlen(end_loc) + 1); + char* result = (char *)AdlAllocateHeap(strlen(location) + strlen(token2) + strlen(end_loc) + 1); strcpy(result, location); strcat(result, token2); strcat(result, end_loc); @@ -4596,7 +4596,7 @@ char *ADLParser::get_ident_or_literal_constant(const char* description) { // Grab a constant expression. param = get_paren_expr(description); if (param[0] != '(') { - char* buf = (char*) AllocateHeap(strlen(param) + 3); + char* buf = (char*) AdlAllocateHeap(strlen(param) + 3); sprintf(buf, "(%s)", param); param = buf; } @@ -5204,7 +5204,7 @@ void ADLParser::next_line() { char* ADLParser::get_line_string(int linenum) { const char* file = _AD._ADL_file._name; int line = linenum ? linenum : this->linenum(); - char* location = (char *)AllocateHeap(strlen(file) + 100); + char* location = (char *)AdlAllocateHeap(strlen(file) + 100); sprintf(location, "\n#line %d \"%s\"\n", line, file); return location; } diff --git a/src/hotspot/share/adlc/dfa.cpp b/src/hotspot/share/adlc/dfa.cpp index b1556ab5f5e..5abc4365297 100644 --- a/src/hotspot/share/adlc/dfa.cpp +++ b/src/hotspot/share/adlc/dfa.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -72,7 +72,7 @@ private: public: // cmpstr does string comparisions. hashstr computes a key. - ProductionState(Arena *arena) : _production(cmpstr, hashstr, arena) { initialize(); }; + ProductionState(AdlArena *arena) : _production(cmpstr, hashstr, arena) { initialize(); }; ~ProductionState() { }; void initialize(); // reset local and dictionary state @@ -817,7 +817,7 @@ bool Expr::check_buffers() { //------------------------------ExprDict--------------------------------------- // Constructor -ExprDict::ExprDict( CmpKey cmp, Hash hash, Arena *arena ) +ExprDict::ExprDict( CmpKey cmp, Hash hash, AdlArena *arena ) : _expr(cmp, hash, arena), _defines() { } ExprDict::~ExprDict() { diff --git a/src/hotspot/share/adlc/dict2.cpp b/src/hotspot/share/adlc/dict2.cpp index 4f3e33dd626..9fd22572855 100644 --- a/src/hotspot/share/adlc/dict2.cpp +++ b/src/hotspot/share/adlc/dict2.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2022, 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 @@ -56,7 +56,7 @@ Dict::Dict(CmpKey initcmp, Hash inithash) : _hash(inithash), _cmp(initcmp), _are init(); } -Dict::Dict(CmpKey initcmp, Hash inithash, Arena *arena) : _hash(inithash), _cmp(initcmp), _arena(arena) { +Dict::Dict(CmpKey initcmp, Hash inithash, AdlArena *arena) : _hash(inithash), _cmp(initcmp), _arena(arena) { init(); } diff --git a/src/hotspot/share/adlc/dict2.hpp b/src/hotspot/share/adlc/dict2.hpp index a9790088dfb..c6b7da3368a 100644 --- a/src/hotspot/share/adlc/dict2.hpp +++ b/src/hotspot/share/adlc/dict2.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2022, 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 @@ -43,7 +43,7 @@ typedef void (*FuncDict)(const void *key, const void *val, Dict *d); class Dict { // Dictionary structure private: - class Arena *_arena; // Where to draw storage from + class AdlArena *_arena; // Where to draw storage from class bucket *_bin; // Hash table is array of buckets int _size; // Size (# of slots) in hash table int _cnt; // Number of key-value pairs in hash table @@ -56,7 +56,7 @@ class Dict { // Dictionary structure // cmp is a key comparision routine. hash is a routine to hash a key. Dict( CmpKey cmp, Hash hash ); - Dict( CmpKey cmp, Hash hash, Arena *arena ); + Dict( CmpKey cmp, Hash hash, AdlArena *arena ); void init(); ~Dict(); diff --git a/src/hotspot/share/adlc/forms.cpp b/src/hotspot/share/adlc/forms.cpp index 3a246285b3a..9580d81484d 100644 --- a/src/hotspot/share/adlc/forms.cpp +++ b/src/hotspot/share/adlc/forms.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,9 +27,9 @@ //------------------------------Static Initializers---------------------------- // allocate arena used by forms -Arena *Form::arena = Form::generate_arena(); // = Form::generate_arena(); -Arena *Form::generate_arena() { - return (new Arena); +AdlArena *Form::arena = Form::generate_arena(); // = Form::generate_arena(); +AdlArena *Form::generate_arena() { + return (new AdlArena); } //------------------------------NameList--------------------------------------- @@ -40,7 +40,7 @@ const char *NameList::_signal3 = "$$SIGNAL3$$"; // Constructor and Destructor NameList::NameList() : _cur(0), _max(4), _iter(0), _justReset(true) { - _names = (const char**) AllocateHeap(_max*sizeof(char*)); + _names = (const char**) AdlAllocateHeap(_max*sizeof(char*)); } NameList::~NameList() { // The following free is a double-free, and crashes the program: @@ -49,7 +49,7 @@ NameList::~NameList() { void NameList::addName(const char *name) { if (_cur == _max) { - _names = (const char**) ReAllocateHeap(_names, (_max *=2)*sizeof(char*)); + _names = (const char**) AdlReAllocateHeap(_names, (_max *=2)*sizeof(char*)); } _names[_cur++] = name; } @@ -312,7 +312,7 @@ FormList::~FormList() { //------------------------------FormDict--------------------------------------- // Constructor -FormDict::FormDict( CmpKey cmp, Hash hash, Arena *arena ) +FormDict::FormDict( CmpKey cmp, Hash hash, AdlArena *arena ) : _form(cmp, hash, arena) { } FormDict::~FormDict() { diff --git a/src/hotspot/share/adlc/forms.hpp b/src/hotspot/share/adlc/forms.hpp index b4e115229c3..6586ea88311 100644 --- a/src/hotspot/share/adlc/forms.hpp +++ b/src/hotspot/share/adlc/forms.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -97,7 +97,7 @@ private: public: // cmp is a key comparision routine. hash is a routine to hash a key. // FormDict( CmpKey cmp, Hash hash ); - FormDict( CmpKey cmp, Hash hash, Arena *arena ); + FormDict( CmpKey cmp, Hash hash, AdlArena *arena ); FormDict( const FormDict & fd ); // Deep-copy guts ~FormDict(); @@ -119,9 +119,9 @@ public: //------------------------------Form------------------------------------------- class Form { public: - static Arena *arena; // arena used by forms + static AdlArena *arena; // arena used by forms private: - static Arena *generate_arena(); // allocate arena used by forms + static AdlArena *generate_arena(); // allocate arena used by forms protected: int _ftype; // Indicator for derived class type @@ -573,7 +573,7 @@ private: public: // cmp is a key comparision routine. hash is a routine to hash a key. - ExprDict( CmpKey cmp, Hash hash, Arena *arena ); + ExprDict( CmpKey cmp, Hash hash, AdlArena *arena ); ~ExprDict(); // Return # of key-value pairs in dict diff --git a/src/hotspot/share/adlc/formsopt.cpp b/src/hotspot/share/adlc/formsopt.cpp index 351904bbb29..6f1a5997511 100644 --- a/src/hotspot/share/adlc/formsopt.cpp +++ b/src/hotspot/share/adlc/formsopt.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2022, 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 @@ -206,7 +206,7 @@ RegDef::RegDef(char *regname, char *callconv, char *c_conv, char * idealtype, ch _concrete(concrete), _register_num(0) { - // Chunk and register mask are determined by the register number + // AdlChunk and register mask are determined by the register number // _register_num is set when registers are added to an allocation class } RegDef::~RegDef() { // Destructor diff --git a/src/hotspot/share/adlc/formssel.cpp b/src/hotspot/share/adlc/formssel.cpp index f7ff8ccf40b..67c49459db9 100644 --- a/src/hotspot/share/adlc/formssel.cpp +++ b/src/hotspot/share/adlc/formssel.cpp @@ -1366,7 +1366,7 @@ void InstructForm::set_unique_opnds() { // component back to an index and any DEF always goes at 0 so the // length of the array has to be the number of components + 1. _uniq_idx_length = _components.count() + 1; - uniq_idx = (uint*) AllocateHeap(sizeof(uint) * _uniq_idx_length); + uniq_idx = (uint*) AdlAllocateHeap(sizeof(uint) * _uniq_idx_length); for (i = 0; i < _uniq_idx_length; i++) { uniq_idx[i] = i; } @@ -3476,7 +3476,7 @@ void MatchNode::build_internalop( ) { rstr = (_rChild) ? ((_rChild->_internalop) ? _rChild->_internalop : _rChild->_opType) : ""; len += (int)strlen(lstr) + (int)strlen(rstr); - subtree = (char *)AllocateHeap(len); + subtree = (char *)AdlAllocateHeap(len); sprintf(subtree,"_%s_%s_%s", _opType, lstr, rstr); // Hash the subtree string in _internalOps; if a name exists, use it iop = (char *)_AD._internalOps[subtree]; @@ -3926,7 +3926,7 @@ void MatchRule::matchrule_swap_commutative_op(const char* instr_ident, int count MatchRule* clone = new MatchRule(_AD, this); // Swap operands of commutative operation ((MatchNode*)clone)->swap_commutative_op(true, count); - char* buf = (char*) AllocateHeap(strlen(instr_ident) + 4); + char* buf = (char*) AdlAllocateHeap(strlen(instr_ident) + 4); sprintf(buf, "%s_%d", instr_ident, match_rules_cnt++); clone->_result = buf; -- GitLab From 65831eb294b6f1f5f99988836c00005d41c27fd3 Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Fri, 11 Feb 2022 06:45:13 +0000 Subject: [PATCH 461/564] 8281318: Improve jfr/event/allocation tests reliability Reviewed-by: mgronlun --- .../TestObjectAllocationInNewTLABEvent.java | 30 +++++++++++++------ .../TestObjectAllocationOutsideTLABEvent.java | 28 ++++++++++++----- ...ObjectAllocationSampleEventThrottling.java | 17 ++++++++--- 3 files changed, 54 insertions(+), 21 deletions(-) diff --git a/test/jdk/jdk/jfr/event/allocation/TestObjectAllocationInNewTLABEvent.java b/test/jdk/jdk/jfr/event/allocation/TestObjectAllocationInNewTLABEvent.java index d4078a65ecd..cb70c0ba324 100644 --- a/test/jdk/jdk/jfr/event/allocation/TestObjectAllocationInNewTLABEvent.java +++ b/test/jdk/jdk/jfr/event/allocation/TestObjectAllocationInNewTLABEvent.java @@ -30,6 +30,8 @@ import jdk.jfr.consumer.RecordedEvent; import jdk.test.lib.jfr.EventNames; import jdk.test.lib.jfr.Events; import jdk.test.lib.Asserts; +import jdk.test.lib.Platform; +import sun.hotspot.WhiteBox; /** * @test @@ -37,8 +39,16 @@ import jdk.test.lib.Asserts; * @key jfr * @requires vm.hasJFR * @library /test/lib - * @run main/othervm -XX:+UseTLAB -XX:TLABSize=100k -XX:-ResizeTLAB -XX:TLABRefillWasteFraction=1 jdk.jfr.event.allocation.TestObjectAllocationInNewTLABEvent - * @run main/othervm -XX:+UseTLAB -XX:TLABSize=100k -XX:-ResizeTLAB -XX:TLABRefillWasteFraction=1 -Xint jdk.jfr.event.allocation.TestObjectAllocationInNewTLABEvent + * @build sun.hotspot.WhiteBox + * + * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -XX:+WhiteBoxAPI -Xbootclasspath/a:. + * -XX:+UseTLAB -XX:TLABSize=100k -XX:-ResizeTLAB -XX:TLABRefillWasteFraction=1 + * jdk.jfr.event.allocation.TestObjectAllocationInNewTLABEvent + * @run main/othervm -XX:+WhiteBoxAPI -Xbootclasspath/a:. + * -XX:+UseTLAB -XX:TLABSize=100k -XX:-ResizeTLAB -XX:TLABRefillWasteFraction=1 + * -Xint + * jdk.jfr.event.allocation.TestObjectAllocationInNewTLABEvent */ /** @@ -46,17 +56,19 @@ import jdk.test.lib.Asserts; * an event will be triggered. The test is done for default and interpreted mode (-Xint). * * To force objects to be allocated in a new TLAB: - * the size of TLAB is set to 100k (-XX:TLABSize=100k); - * the size of allocated objects is set to 100k minus 16 bytes overhead; + * the initial size of TLAB is set to 100k (-XX:TLABSize=100k); + * the size of allocated objects is set to 128k; * max TLAB waste at refill is set to minimum (-XX:TLABRefillWasteFraction=1), * to provoke a new TLAB creation. */ public class TestObjectAllocationInNewTLABEvent { private final static String EVENT_NAME = EventNames.ObjectAllocationInNewTLAB; - private static final int BYTE_ARRAY_OVERHEAD = 16; // Extra bytes used by a byte array. - private static final int OBJECT_SIZE = 100 * 1024; - private static final int OBJECT_SIZE_ALT = OBJECT_SIZE + 8; // Object size in case of disabled CompressedOops. + private static final Boolean COMPRESSED_CLASS_PTRS = WhiteBox.getWhiteBox().getBooleanVMFlag("UseCompressedClassPointers"); + + private static final int BYTE_ARRAY_OVERHEAD = (Platform.is64bit() && !COMPRESSED_CLASS_PTRS) ? 24 : 16; + private static final int OBJECT_SIZE = 128 * 1024; + private static final int OBJECTS_TO_ALLOCATE = 100; private static final String BYTE_ARRAY_CLASS_NAME = new byte[0].getClass().getName(); private static final int INITIAL_TLAB_SIZE = 100 * 1024; @@ -112,9 +124,9 @@ public class TestObjectAllocationInNewTLABEvent { long allocationSize = Events.assertField(event, "allocationSize").atLeast(1L).getValue(); long tlabSize = Events.assertField(event, "tlabSize").atLeast(allocationSize).getValue(); String className = Events.assertField(event, "objectClass.name").notEmpty().getValue(); - if (className.equals(BYTE_ARRAY_CLASS_NAME) && (allocationSize == OBJECT_SIZE || allocationSize == OBJECT_SIZE_ALT)) { + if (className.equals(BYTE_ARRAY_CLASS_NAME) && (allocationSize == OBJECT_SIZE)) { countAllTlabs++; - if (tlabSize == INITIAL_TLAB_SIZE + OBJECT_SIZE || tlabSize == INITIAL_TLAB_SIZE + OBJECT_SIZE_ALT) { + if (tlabSize == INITIAL_TLAB_SIZE + OBJECT_SIZE) { countFullTlabs++; } } diff --git a/test/jdk/jdk/jfr/event/allocation/TestObjectAllocationOutsideTLABEvent.java b/test/jdk/jdk/jfr/event/allocation/TestObjectAllocationOutsideTLABEvent.java index 466a0062ac9..70bf4518f08 100644 --- a/test/jdk/jdk/jfr/event/allocation/TestObjectAllocationOutsideTLABEvent.java +++ b/test/jdk/jdk/jfr/event/allocation/TestObjectAllocationOutsideTLABEvent.java @@ -30,6 +30,8 @@ import jdk.jfr.consumer.RecordedEvent; import jdk.test.lib.jfr.EventNames; import jdk.test.lib.jfr.Events; import jdk.test.lib.Asserts; +import jdk.test.lib.Platform; +import sun.hotspot.WhiteBox; /** * @test @@ -37,8 +39,16 @@ import jdk.test.lib.Asserts; * @key jfr * @requires vm.hasJFR * @library /test/lib - * @run main/othervm -XX:+UseTLAB -XX:TLABSize=90k -XX:-ResizeTLAB -XX:TLABRefillWasteFraction=256 jdk.jfr.event.allocation.TestObjectAllocationOutsideTLABEvent - * @run main/othervm -XX:+UseTLAB -XX:TLABSize=90k -XX:-ResizeTLAB -XX:TLABRefillWasteFraction=256 -Xint jdk.jfr.event.allocation.TestObjectAllocationOutsideTLABEvent + * @build sun.hotspot.WhiteBox + * + * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -XX:+WhiteBoxAPI -Xbootclasspath/a:. + * -XX:+UseTLAB -XX:TLABSize=90k -XX:-ResizeTLAB -XX:TLABRefillWasteFraction=256 + * jdk.jfr.event.allocation.TestObjectAllocationOutsideTLABEvent + * @run main/othervm -XX:+WhiteBoxAPI -Xbootclasspath/a:. + * -XX:+UseTLAB -XX:TLABSize=90k -XX:-ResizeTLAB -XX:TLABRefillWasteFraction=256 + * -Xint + * jdk.jfr.event.allocation.TestObjectAllocationOutsideTLABEvent */ /** @@ -46,17 +56,19 @@ import jdk.test.lib.Asserts; * Thread Local Allocation Buffer (TLAB). The test is done for default interpreted mode (-Xint). * * To force objects to be allocated outside TLAB: - * the size of TLAB is set to 90k (-XX:TLABSize=90k); - * the size of allocated objects is set to 100k. + * the initial size of TLAB is set to 90k (-XX:TLABSize=90k); + * the size of allocated objects is set to 128k; * max TLAB waste at refill is set to 256 (-XX:TLABRefillWasteFraction=256), * to prevent a new TLAB creation. */ public class TestObjectAllocationOutsideTLABEvent { private static final String EVENT_NAME = EventNames.ObjectAllocationOutsideTLAB; - private static final int BYTE_ARRAY_OVERHEAD = 16; // Extra bytes used by a byte array - private static final int OBJECT_SIZE = 100 * 1024; - private static final int OBJECT_SIZE_ALT = OBJECT_SIZE + 8; // Object size in case of disabled CompressedOops + private static final Boolean COMPRESSED_CLASS_PTRS = WhiteBox.getWhiteBox().getBooleanVMFlag("UseCompressedClassPointers"); + + private static final int BYTE_ARRAY_OVERHEAD = (Platform.is64bit() && !COMPRESSED_CLASS_PTRS) ? 24 : 16; + private static final int OBJECT_SIZE = 128 * 1024; + private static final int OBJECTS_TO_ALLOCATE = 100; private static final String BYTE_ARRAY_CLASS_NAME = new byte[0].getClass().getName(); private static int eventCount; @@ -94,7 +106,7 @@ public class TestObjectAllocationOutsideTLABEvent { } long allocationSize = Events.assertField(event, "allocationSize").atLeast(1L).getValue(); String className = Events.assertField(event, "objectClass.name").notEmpty().getValue(); - if (className.equals(BYTE_ARRAY_CLASS_NAME) && (allocationSize == OBJECT_SIZE || allocationSize == OBJECT_SIZE_ALT)) { + if (className.equals(BYTE_ARRAY_CLASS_NAME) && (allocationSize == OBJECT_SIZE)) { ++eventCount; } } diff --git a/test/jdk/jdk/jfr/event/allocation/TestObjectAllocationSampleEventThrottling.java b/test/jdk/jdk/jfr/event/allocation/TestObjectAllocationSampleEventThrottling.java index 22d03ce57ba..a10b6e2b56a 100644 --- a/test/jdk/jdk/jfr/event/allocation/TestObjectAllocationSampleEventThrottling.java +++ b/test/jdk/jdk/jfr/event/allocation/TestObjectAllocationSampleEventThrottling.java @@ -32,6 +32,8 @@ import jdk.jfr.consumer.RecordedEvent; import jdk.test.lib.jfr.EventNames; import jdk.test.lib.jfr.Events; import jdk.test.lib.Asserts; +import jdk.test.lib.Platform; +import sun.hotspot.WhiteBox; /** * @test @@ -39,15 +41,22 @@ import jdk.test.lib.Asserts; * @key jfr * @requires vm.hasJFR * @library /test/lib -* @run main/othervm -XX:+UseTLAB -XX:TLABSize=2k -XX:-ResizeTLAB jdk.jfr.event.allocation.TestObjectAllocationSampleEventThrottling + * @build sun.hotspot.WhiteBox + * + * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -XX:+WhiteBoxAPI -Xbootclasspath/a:. + * -XX:+UseTLAB -XX:TLABSize=2k -XX:-ResizeTLAB + * jdk.jfr.event.allocation.TestObjectAllocationSampleEventThrottling */ public class TestObjectAllocationSampleEventThrottling { private static final String EVENT_NAME = EventNames.ObjectAllocationSample; - private static final int BYTE_ARRAY_OVERHEAD = 16; // Extra bytes used by a byte array - private static final int OBJECT_SIZE = 100 * 1024; - private static final int OBJECT_SIZE_ALT = OBJECT_SIZE + 8; // Object size in case of disabled CompressedOops + private static final Boolean COMPRESSED_CLASS_PTRS = WhiteBox.getWhiteBox().getBooleanVMFlag("UseCompressedClassPointers"); + + private static final int BYTE_ARRAY_OVERHEAD = (Platform.is64bit() && !COMPRESSED_CLASS_PTRS) ? 24 : 16; + private static final int OBJECT_SIZE = 128 * 1024; + private static final int OBJECTS_TO_ALLOCATE = 100; private static final String BYTE_ARRAY_CLASS_NAME = new byte[0].getClass().getName(); private static int eventCount; -- GitLab From a037b3c35831f029d23a88bdd49e7f2c2d951631 Mon Sep 17 00:00:00 2001 From: Thomas Stuefe Date: Fri, 11 Feb 2022 07:21:04 +0000 Subject: [PATCH 462/564] 8281460: Let ObjectMonitor have its own NMT category Reviewed-by: dholmes, dcubed, shade --- src/hotspot/share/memory/allocation.hpp | 1 + src/hotspot/share/runtime/objectMonitor.hpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/memory/allocation.hpp b/src/hotspot/share/memory/allocation.hpp index 8503942f21f..ec7f78b9fa4 100644 --- a/src/hotspot/share/memory/allocation.hpp +++ b/src/hotspot/share/memory/allocation.hpp @@ -146,6 +146,7 @@ class AllocatedObj { f(mtServiceability, "Serviceability") \ f(mtMetaspace, "Metaspace") \ f(mtStringDedup, "String Deduplication") \ + f(mtObjectMonitor, "Object Monitors") \ f(mtNone, "Unknown") \ //end diff --git a/src/hotspot/share/runtime/objectMonitor.hpp b/src/hotspot/share/runtime/objectMonitor.hpp index 4ca4cc28c86..889a844fa50 100644 --- a/src/hotspot/share/runtime/objectMonitor.hpp +++ b/src/hotspot/share/runtime/objectMonitor.hpp @@ -127,7 +127,7 @@ class ObjectWaiter : public StackObj { #define OM_CACHE_LINE_SIZE DEFAULT_CACHE_LINE_SIZE #endif -class ObjectMonitor : public CHeapObj { +class ObjectMonitor : public CHeapObj { friend class ObjectSynchronizer; friend class ObjectWaiter; friend class VMStructs; -- GitLab From 8441d51e71e143250b44eea74114a624cf00cc3e Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Fri, 11 Feb 2022 07:41:18 +0000 Subject: [PATCH 463/564] 8281419: The source data for the color conversion can be discarded Reviewed-by: prr, aivanov --- src/java.desktop/share/native/liblcms/LCMS.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/java.desktop/share/native/liblcms/LCMS.c b/src/java.desktop/share/native/liblcms/LCMS.c index 4bbd6e100c3..27c23c6d92f 100644 --- a/src/java.desktop/share/native/liblcms/LCMS.c +++ b/src/java.desktop/share/native/liblcms/LCMS.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2022, 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 @@ -496,19 +496,20 @@ static void *getILData(JNIEnv *env, jobject data, jint type) { } } -static void releaseILData(JNIEnv *env, void *pData, jint type, jobject data) { +static void releaseILData(JNIEnv *env, void *pData, jint type, jobject data, + jint mode) { switch (type) { case DT_BYTE: - (*env)->ReleaseByteArrayElements(env, data, (jbyte *) pData, 0); + (*env)->ReleaseByteArrayElements(env, data, (jbyte *) pData, mode); break; case DT_SHORT: - (*env)->ReleaseShortArrayElements(env, data, (jshort *) pData, 0); + (*env)->ReleaseShortArrayElements(env, data, (jshort *) pData, mode); break; case DT_INT: - (*env)->ReleaseIntArrayElements(env, data, (jint *) pData, 0); + (*env)->ReleaseIntArrayElements(env, data, (jint *) pData, mode); break; case DT_DOUBLE: - (*env)->ReleaseDoubleArrayElements(env, data, (jdouble *) pData, 0); + (*env)->ReleaseDoubleArrayElements(env, data, (jdouble *) pData, mode); break; } } @@ -542,7 +543,7 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_colorConvert void *outputBuffer = getILData(env, dstData, dstDType); if (outputBuffer == NULL) { - releaseILData(env, inputBuffer, srcDType, srcData); + releaseILData(env, inputBuffer, srcDType, srcData, JNI_ABORT); // An exception should have already been thrown. return; } @@ -560,8 +561,8 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_colorConvert } } - releaseILData(env, inputBuffer, srcDType, srcData); - releaseILData(env, outputBuffer, dstDType, dstData); + releaseILData(env, inputBuffer, srcDType, srcData, JNI_ABORT); + releaseILData(env, outputBuffer, dstDType, dstData, 0); } /* -- GitLab From 3a13425bc9088cbb6d95e1a46248d7eba27fb1a6 Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Fri, 11 Feb 2022 08:46:55 +0000 Subject: [PATCH 464/564] 8072070: Improve interpreter stack banging Reviewed-by: xliu, coleenp, mdoerr --- .../x86/templateInterpreterGenerator_x86.cpp | 56 ++++++-- src/hotspot/share/runtime/javaCalls.cpp | 4 +- src/hotspot/share/runtime/os.cpp | 6 +- src/hotspot/share/runtime/stackOverflow.hpp | 123 +++++++++++++++++- src/hotspot/share/runtime/thread.hpp | 6 + 5 files changed, 173 insertions(+), 22 deletions(-) diff --git a/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp b/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp index a4e86ff4202..cc365f70426 100644 --- a/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp +++ b/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, 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 @@ -713,23 +713,59 @@ address TemplateInterpreterGenerator::generate_Reference_get_entry(void) { } void TemplateInterpreterGenerator::bang_stack_shadow_pages(bool native_call) { - // Quick & dirty stack overflow checking: bang the stack & handle trap. + // See more discussion in stackOverflow.hpp. + // Note that we do the banging after the frame is setup, since the exception // handling code expects to find a valid interpreter frame on the stack. // Doing the banging earlier fails if the caller frame is not an interpreter // frame. // (Also, the exception throwing code expects to unlock any synchronized - // method receiever, so do the banging after locking the receiver.) + // method receiver, so do the banging after locking the receiver.) - // Bang each page in the shadow zone. We can't assume it's been done for - // an interpreter frame with greater than a page of locals, so each page - // needs to be checked. Only true for non-native. + const int shadow_zone_size = checked_cast(StackOverflow::stack_shadow_zone_size()); const int page_size = os::vm_page_size(); - const int n_shadow_pages = ((int)StackOverflow::stack_shadow_zone_size()) / page_size; - const int start_page = native_call ? n_shadow_pages : 1; - for (int pages = start_page; pages <= n_shadow_pages; pages++) { - __ bang_stack_with_offset(pages*page_size); + const int n_shadow_pages = shadow_zone_size / page_size; + + const Register thread = NOT_LP64(rsi) LP64_ONLY(r15_thread); +#ifndef _LP64 + __ push(thread); + __ get_thread(thread); +#endif + +#ifdef ASSERT + Label L_good_limit; + __ cmpptr(Address(thread, JavaThread::shadow_zone_safe_limit()), (int32_t)NULL_WORD); + __ jcc(Assembler::notEqual, L_good_limit); + __ stop("shadow zone safe limit is not initialized"); + __ bind(L_good_limit); + + Label L_good_watermark; + __ cmpptr(Address(thread, JavaThread::shadow_zone_growth_watermark()), (int32_t)NULL_WORD); + __ jcc(Assembler::notEqual, L_good_watermark); + __ stop("shadow zone growth watermark is not initialized"); + __ bind(L_good_watermark); +#endif + + Label L_done; + + __ cmpptr(rsp, Address(thread, JavaThread::shadow_zone_growth_watermark())); + __ jcc(Assembler::above, L_done); + + for (int p = 1; p <= n_shadow_pages; p++) { + __ bang_stack_with_offset(p*page_size); } + + // Record a new watermark, unless the update is above the safe limit. + // Otherwise, the next time around a check above would pass the safe limit. + __ cmpptr(rsp, Address(thread, JavaThread::shadow_zone_safe_limit())); + __ jccb(Assembler::belowEqual, L_done); + __ movptr(Address(thread, JavaThread::shadow_zone_growth_watermark()), rsp); + + __ bind(L_done); + +#ifndef _LP64 + __ pop(thread); +#endif } // Interpreter stub for calling a native method. (asm interpreter) diff --git a/src/hotspot/share/runtime/javaCalls.cpp b/src/hotspot/share/runtime/javaCalls.cpp index 5390c5f6eaf..978fd20e0dd 100644 --- a/src/hotspot/share/runtime/javaCalls.cpp +++ b/src/hotspot/share/runtime/javaCalls.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2021, Azul Systems, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -380,7 +380,7 @@ void JavaCalls::call_helper(JavaValue* result, const methodHandle& method, JavaC // Check that there are shadow pages available before changing thread state // to Java. Calculate current_stack_pointer here to make sure - // stack_shadow_pages_available() and bang_stack_shadow_pages() use the same sp. + // stack_shadow_pages_available() and map_stack_shadow_pages() use the same sp. address sp = os::current_stack_pointer(); if (!os::stack_shadow_pages_available(THREAD, method, sp)) { // Throw stack overflow exception with preinitialized exception. diff --git a/src/hotspot/share/runtime/os.cpp b/src/hotspot/share/runtime/os.cpp index a85be30ec48..f86396beada 100644 --- a/src/hotspot/share/runtime/os.cpp +++ b/src/hotspot/share/runtime/os.cpp @@ -1384,7 +1384,7 @@ char** os::split_path(const char* path, size_t* elements, size_t file_name_lengt // pages, false otherwise. bool os::stack_shadow_pages_available(Thread *thread, const methodHandle& method, address sp) { if (!thread->is_Java_thread()) return false; - // Check if we have StackShadowPages above the yellow zone. This parameter + // Check if we have StackShadowPages above the guard zone. This parameter // is dependent on the depth of the maximum VM call stack possible from // the handler for stack overflow. 'instanceof' in the stack overflow // handler or a println uses at least 8k stack of VM and native code @@ -1392,9 +1392,7 @@ bool os::stack_shadow_pages_available(Thread *thread, const methodHandle& method const int framesize_in_bytes = Interpreter::size_top_interpreter_activation(method()) * wordSize; - address limit = JavaThread::cast(thread)->stack_end() + - (StackOverflow::stack_guard_zone_size() + StackOverflow::stack_shadow_zone_size()); - + address limit = JavaThread::cast(thread)->stack_overflow_state()->shadow_zone_safe_limit(); return sp > (limit + framesize_in_bytes); } diff --git a/src/hotspot/share/runtime/stackOverflow.hpp b/src/hotspot/share/runtime/stackOverflow.hpp index c8e4249ab25..5a8a88c4fcd 100644 --- a/src/hotspot/share/runtime/stackOverflow.hpp +++ b/src/hotspot/share/runtime/stackOverflow.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, 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 @@ -51,6 +51,8 @@ class StackOverflow { _stack_guard_state(stack_guard_unused), _stack_overflow_limit(nullptr), _reserved_stack_activation(nullptr), // stack base not known yet + _shadow_zone_safe_limit(nullptr), + _shadow_zone_growth_watermark(nullptr), _stack_base(nullptr), _stack_end(nullptr) {} // Initialization after thread is started. @@ -58,6 +60,7 @@ class StackOverflow { _stack_base = base; _stack_end = end; set_stack_overflow_limit(); + set_shadow_zone_limits(); set_reserved_stack_activation(base); } private: @@ -68,6 +71,8 @@ class StackOverflow { // We load it from here to simplify the stack overflow check in assembly. address _stack_overflow_limit; address _reserved_stack_activation; + address _shadow_zone_safe_limit; + address _shadow_zone_growth_watermark; // Support for stack overflow handling, copied down from thread. address _stack_base; @@ -77,6 +82,9 @@ class StackOverflow { address stack_base() const { assert(_stack_base != nullptr, "Sanity check"); return _stack_base; } // Stack overflow support + // -------------------------------------------------------------------------------- + // + // The Java thread stack is structured as follows: // // (low addresses) // @@ -95,11 +103,24 @@ class StackOverflow { // | | // | reserved zone | // | | - // -- <-- stack_reserved_zone_base() --- --- - // /|\ shadow <-- stack_overflow_limit() (somewhere in here) - // | zone - // \|/ size - // some untouched memory --- + // -- <-- stack_reserved_zone_base() --- --- + // ^ + // | <-- stack_overflow_limit() [somewhere in here] + // | shadow + // | zone + // | size + // v + // --- <-- shadow_zone_safe_limit() + // (Here and below: not yet touched stack) + // + // + // (Here and below: touched at least once) --- + // ^ + // | shadow + // | zone + // | size + // v + // --- <-- shadow_zone_growth_watermark() // // // -- @@ -120,6 +141,84 @@ class StackOverflow { // // (high addresses) // + // + // The stack overflow mechanism detects overflows by touching ("banging") the stack + // ahead of current stack pointer (SP). The entirety of guard zone is memory protected, + // therefore such access would trap when touching the guard zone, and one of the following + // things would happen. + // + // Access in the red zone: unrecoverable stack overflow. Crash the VM, generate a report, + // crash dump, and other diagnostics. + // + // Access in the yellow zone: recoverable, reportable stack overflow. Create and throw + // a StackOverflowError, remove the protection of yellow zone temporarily to let exception + // handlers run. If exception handlers themselves run out of stack, they will crash VM due + // to access to red zone. + // + // Access in the reserved zone: recoverable, reportable, transparent for privileged methods + // stack overflow. Perform a stack walk to check if there's a method annotated with + // @ReservedStackAccess on the call stack. If such method is found, remove the protection of + // reserved zone temporarily, and let the method run. If not, handle the access like a yellow + // zone trap. + // + // The banging itself happens within the "shadow zone" that extends from the current SP. + // + // The goals for properly implemented shadow zone banging are: + // + // a) Allow native/VM methods to run without stack overflow checks within some reasonable + // headroom. Default shadow zone size should accommodate the largest normally expected + // native/VM stack use. + // b) Guarantee the stack overflow checks work even if SP is dangerously close to guard zone. + // If SP is very low, banging at the edge of shadow zone (SP+shadow-zone-size) can slip + // into adjacent thread stack, or even into other readable memory. This would potentially + // pass the check by accident. + // c) Allow for incremental stack growth on some OSes. This is enabled by handling traps + // from not yet committed thread stacks, even outside the guard zone. The banging should + // not allow uncommitted "gaps" on thread stack. See for example the uses of + // os::map_stack_shadow_pages(). + // d) Make sure the stack overflow trap happens in the code that is known to runtime, so + // the traps can be reasonably handled: handling a spurious trap from executing Java code + // is hard, while properly handling the trap from VM/native code is nearly impossible. + // + // The simplest code that satisfies all these requirements is banging the shadow zone + // page by page at every Java/native method entry. + // + // While that code is sufficient, it comes with the large performance cost. This performance + // cost can be reduced by several *optional* techniques: + // + // 1. Guarantee that stack would not take another page. If so, the current bang was + // enough to verify we are not near the guard zone. This kind of insight is usually only + // available for compilers that can know the size of the frame exactly. + // + // Examples: PhaseOutput::need_stack_bang. + // + // 2. Check the current SP in relation to shadow zone safe limit. + // + // Define "safe limit" as the highest SP where banging would not touch the guard zone. + // Then, do the page-by-page bang only if current SP is above that safe limit, OR some + // OS-es need it to get the stack mapped. + // + // Examples: AbstractAssembler::generate_stack_overflow_check, JavaCalls::call_helper, + // os::stack_shadow_pages_available, os::map_stack_shadow_pages and their uses. + // + // 3. Check the current SP in relation to the shadow zone growth watermark. + // + // Define "shadow zone growth watermark" as the highest SP where we banged already. + // Invariant: growth watermark is always above the safe limit, which allows testing + // for watermark and safe limit at the same time in the most frequent case. + // + // Easy and overwhelmingly frequent case: SP is above the growth watermark, and + // by extension above the safe limit. In this case, we know that the guard zone is far away + // (safe limit), and that the stack was banged before for stack growth (growth watermark). + // Therefore, we can skip the banging altogether. + // + // Harder cases: SP is below the growth watermark. In might be due to two things: + // we have not banged the stack for growth (below growth watermark only), or we are + // close to guard zone (also below safe limit). Do the full banging. Once done, we + // can adjust the growth watermark, thus recording the bang for stack growth had + // happened. + // + // Examples: TemplateInterpreterGenerator::bang_stack_shadow_pages on x86 and others. private: // These values are derived from flags StackRedPages, StackYellowPages, @@ -189,6 +288,11 @@ class StackOverflow { return _stack_shadow_zone_size; } + address shadow_zone_safe_limit() const { + assert(_shadow_zone_safe_limit != nullptr, "Don't call this before the field is initialized."); + return _shadow_zone_safe_limit; + } + void create_stack_guard_pages(); void remove_stack_guard_pages(); @@ -242,6 +346,13 @@ class StackOverflow { _stack_overflow_limit = stack_end() + MAX2(stack_guard_zone_size(), stack_shadow_zone_size()); } + + void set_shadow_zone_limits() { + _shadow_zone_safe_limit = + stack_end() + stack_guard_zone_size() + stack_shadow_zone_size(); + _shadow_zone_growth_watermark = + stack_base(); + } }; #endif // SHARE_RUNTIME_STACKOVERFLOW_HPP diff --git a/src/hotspot/share/runtime/thread.hpp b/src/hotspot/share/runtime/thread.hpp index 9ceb17f7af1..151d487355a 100644 --- a/src/hotspot/share/runtime/thread.hpp +++ b/src/hotspot/share/runtime/thread.hpp @@ -1299,6 +1299,12 @@ class JavaThread: public Thread { static ByteSize reserved_stack_activation_offset() { return byte_offset_of(JavaThread, _stack_overflow_state._reserved_stack_activation); } + static ByteSize shadow_zone_safe_limit() { + return byte_offset_of(JavaThread, _stack_overflow_state._shadow_zone_safe_limit); + } + static ByteSize shadow_zone_growth_watermark() { + return byte_offset_of(JavaThread, _stack_overflow_state._shadow_zone_growth_watermark); + } static ByteSize suspend_flags_offset() { return byte_offset_of(JavaThread, _suspend_flags); } -- GitLab From 90939cb80193c671cae635b7a4e41bd2e6bcdbd5 Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Fri, 11 Feb 2022 09:05:50 +0000 Subject: [PATCH 465/564] 8281626: NonblockingQueue should use nullptr Reviewed-by: shade, dholmes --- .../share/utilities/nonblockingQueue.hpp | 10 +-- .../utilities/nonblockingQueue.inline.hpp | 68 +++++++++---------- 2 files changed, 39 insertions(+), 39 deletions(-) diff --git a/src/hotspot/share/utilities/nonblockingQueue.hpp b/src/hotspot/share/utilities/nonblockingQueue.hpp index a271aaa38d8..7ba4c80cfd6 100644 --- a/src/hotspot/share/utilities/nonblockingQueue.hpp +++ b/src/hotspot/share/utilities/nonblockingQueue.hpp @@ -45,7 +45,7 @@ // // A queue may temporarily appear to be empty even though elements have been // added and not removed. For example, after running the following program, -// the value of r may be NULL. +// the value of r may be nullptr. // // thread1: q.push(a); r = q.pop(); // thread2: q.push(b); @@ -105,15 +105,15 @@ public: // Thread-safe attempt to remove and return the first object in the queue. // Returns true if successful. If successful then *node_ptr is the former - // first object, or NULL if the queue was empty. If unsuccessful, because + // first object, or nullptr if the queue was empty. If unsuccessful, because // of contention with a concurrent modification, then returns false with // the value of *node_ptr unspecified. Subject to ABA behavior; callers // must ensure usage is safe. inline bool try_pop(T** node_ptr); - // Thread-safe remove and return the first object in the queue, or NULL if - // the queue was empty. This just iterates on try_pop() until it - // succeeds, returning the (possibly NULL) element obtained from that. + // Thread-safe remove and return the first object in the queue, or nullptr + // if the queue was empty. This just iterates on try_pop() until it + // succeeds, returning the (possibly nullptr) element obtained from that. // Subject to ABA behavior; callers must ensure usage is safe. inline T* pop(); diff --git a/src/hotspot/share/utilities/nonblockingQueue.inline.hpp b/src/hotspot/share/utilities/nonblockingQueue.inline.hpp index 2ecb1663e45..f4e86c6fe65 100644 --- a/src/hotspot/share/utilities/nonblockingQueue.inline.hpp +++ b/src/hotspot/share/utilities/nonblockingQueue.inline.hpp @@ -40,13 +40,13 @@ void NonblockingQueue::set_next(T& node, T* new_next) { } template -NonblockingQueue::NonblockingQueue() : _head(NULL), _tail(NULL) {} +NonblockingQueue::NonblockingQueue() : _head(nullptr), _tail(nullptr) {} #ifdef ASSERT template NonblockingQueue::~NonblockingQueue() { - assert(_head == NULL, "precondition"); - assert(_tail == NULL, "precondition"); + assert(_head == nullptr, "precondition"); + assert(_tail == nullptr, "precondition"); } #endif @@ -61,7 +61,7 @@ T* NonblockingQueue::end_marker() const { template T* NonblockingQueue::first() const { T* head = Atomic::load(&_head); - return head == NULL ? end_marker() : head; + return head == nullptr ? end_marker() : head; } template @@ -71,7 +71,7 @@ bool NonblockingQueue::is_end(const T* entry) const { template bool NonblockingQueue::empty() const { - return Atomic::load(&_head) == NULL; + return Atomic::load(&_head) == nullptr; } template @@ -85,8 +85,8 @@ size_t NonblockingQueue::length() const { // An append operation atomically exchanges the new tail with the queue tail. // It then sets the "next" value of the old tail to the head of the list being -// appended. If the old tail is NULL then the queue was empty, then the head -// of the list being appended is instead stored in the queue head. +// appended. If the old tail is nullptr then the queue was empty, then the +// head of the list being appended is instead stored in the queue head. // // This means there is a period between the exchange and the old tail update // where the queue sequence is split into two parts, the list from the queue @@ -100,17 +100,17 @@ size_t NonblockingQueue::length() const { // is both the head and the tail of the list being appended. template void NonblockingQueue::append(T& first, T& last) { - assert(next(last) == NULL, "precondition"); + assert(next(last) == nullptr, "precondition"); // Make last the new end of the queue. Any further push/appends will // extend after last. We will try to extend from the previous end of // queue. set_next(last, end_marker()); T* old_tail = Atomic::xchg(&_tail, &last); - if (old_tail == NULL) { - // If old_tail is NULL then the queue was empty, and _head must also be - // NULL. The correctness of this assertion depends on try_pop clearing + if (old_tail == nullptr) { + // If old_tail is nullptr then the queue was empty, and _head must also be + // nullptr. The correctness of this assertion depends on try_pop clearing // first _head then _tail when taking the last entry. - assert(Atomic::load(&_head) == NULL, "invariant"); + assert(Atomic::load(&_head) == nullptr, "invariant"); // Fall through to common update of _head. } else if (is_end(Atomic::cmpxchg(next_ptr(*old_tail), end_marker(), &first))) { // Successfully extended the queue list from old_tail to first. No @@ -126,10 +126,10 @@ void NonblockingQueue::append(T& first, T& last) { return; } else { // A concurrent try_pop has claimed old_tail, so it is no longer in the - // list. The queue was logically empty. _head is either NULL or + // list. The queue was logically empty. _head is either nullptr or // old_tail, depending on how far try_pop operations have progressed. DEBUG_ONLY(T* old_head = Atomic::load(&_head);) - assert((old_head == NULL) || (old_head == old_tail), "invariant"); + assert((old_head == nullptr) || (old_head == old_tail), "invariant"); // Fall through to common update of _head. } // The queue was empty, and first should become the new _head. The queue @@ -142,8 +142,8 @@ bool NonblockingQueue::try_pop(T** node_ptr) { // We only need memory_order_consume. Upgrade it to "load_acquire" // as the memory_order_consume API is not ready for use yet. T* old_head = Atomic::load_acquire(&_head); - if (old_head == NULL) { - *node_ptr = NULL; + if (old_head == nullptr) { + *node_ptr = nullptr; return true; // Queue is empty. } @@ -152,7 +152,7 @@ bool NonblockingQueue::try_pop(T** node_ptr) { // [Clause 1] // There are several cases for next_node. // (1) next_node is the extension of the queue's list. - // (2) next_node is NULL, because a competing try_pop took old_head. + // (2) next_node is nullptr, because a competing try_pop took old_head. // (3) next_node is the extension of some unrelated list, because a // competing try_pop took old_head and put it in some other list. // @@ -166,16 +166,16 @@ bool NonblockingQueue::try_pop(T** node_ptr) { // the race and claimed old_head. This can happen for any of the // next_node cases. return false; - } else if (next_node == NULL) { + } else if (next_node == nullptr) { // [Clause 1b] // The cmpxchg to advance the list succeeded, but a concurrent try_pop // has already claimed old_head (see [Clause 2] - old_head was the last // entry in the list) by nulling old_head's next field. The advance set - // _head to NULL, "helping" the competing try_pop. _head will remain - // NULL until a subsequent push/append. This is a lost race, and we + // _head to nullptr, "helping" the competing try_pop. _head will remain + // nullptr until a subsequent push/append. This is a lost race, and we // report it as such for consistency, though we could report the queue // was empty. We don't attempt to further help [Clause 2] by also - // trying to set _tail to NULL, as that would just ensure that one or + // trying to set _tail to nullptr, as that would just ensure that one or // the other cmpxchg is a wasted failure. return false; } else { @@ -183,15 +183,15 @@ bool NonblockingQueue::try_pop(T** node_ptr) { // Successfully advanced the list and claimed old_head. next_node was // in the extension of the queue's list. Return old_head after // unlinking it from next_node. - set_next(*old_head, NULL); + set_next(*old_head, nullptr); *node_ptr = old_head; return true; } - } else if (is_end(Atomic::cmpxchg(next_ptr(*old_head), next_node, (T*)NULL))) { + } else if (is_end(Atomic::cmpxchg(next_ptr(*old_head), next_node, (T*)nullptr))) { // [Clause 2] // Old_head was the last entry and we've claimed it by setting its next - // value to NULL. However, this leaves the queue in disarray. Fix up + // value to nullptr. However, this leaves the queue in disarray. Fix up // the queue, possibly in conjunction with other concurrent operations. // Any further try_pops will consider the queue empty until a // push/append completes by installing a new head. @@ -200,16 +200,16 @@ bool NonblockingQueue::try_pop(T** node_ptr) { // dealing with _head first gives a stronger invariant in append, and is // also consistent with [Clause 1b]. - // Attempt to change the queue head from old_head to NULL. Failure of the - // cmpxchg indicates a concurrent operation updated _head first. That + // Attempt to change the queue head from old_head to nullptr. Failure of + // the cmpxchg indicates a concurrent operation updated _head first. That // could be either a push/append or a try_pop in [Clause 1b]. - Atomic::cmpxchg(&_head, old_head, (T*)NULL); + Atomic::cmpxchg(&_head, old_head, (T*)nullptr); - // Attempt to change the queue tail from old_head to NULL. Failure of the - // cmpxchg indicates that a concurrent push/append updated _tail first. + // Attempt to change the queue tail from old_head to nullptr. Failure of + // the cmpxchg indicates that a concurrent push/append updated _tail first. // That operation will eventually recognize the old tail (our old_head) is // no longer in the list and update _head from the list being appended. - Atomic::cmpxchg(&_tail, old_head, (T*)NULL); + Atomic::cmpxchg(&_tail, old_head, (T*)nullptr); // The queue has been restored to order, and we can return old_head. *node_ptr = old_head; @@ -226,7 +226,7 @@ bool NonblockingQueue::try_pop(T** node_ptr) { template T* NonblockingQueue::pop() { - T* result = NULL; + T* result = nullptr; // Typically try_pop() will succeed without retrying many times, thus we // omit SpinPause in the loop body. SpinPause or yield may be worthwhile // in rare, highly contended cases, and client code could implement such @@ -238,10 +238,10 @@ T* NonblockingQueue::pop() { template Pair NonblockingQueue::take_all() { T* tail = Atomic::load(&_tail); - if (tail != NULL) set_next(*tail, NULL); // Clear end marker. + if (tail != nullptr) set_next(*tail, nullptr); // Clear end marker. Pair result(Atomic::load(&_head), tail); - Atomic::store(&_head, (T*)NULL); - Atomic::store(&_tail, (T*)NULL); + Atomic::store(&_head, (T*)nullptr); + Atomic::store(&_tail, (T*)nullptr); return result; } -- GitLab From 4d64076058a4ec5df101b06572195ed5fdee6f64 Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Fri, 11 Feb 2022 09:39:10 +0000 Subject: [PATCH 466/564] 8047749: javadoc for getPathBounds() in TreeUI and BasicTreeUI is incorrect Reviewed-by: aivanov --- src/java.desktop/share/classes/javax/swing/plaf/TreeUI.java | 2 +- .../share/classes/javax/swing/plaf/basic/BasicTreeUI.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/java.desktop/share/classes/javax/swing/plaf/TreeUI.java b/src/java.desktop/share/classes/javax/swing/plaf/TreeUI.java index 22e8a10052b..40b575f1b2c 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/TreeUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/TreeUI.java @@ -45,7 +45,7 @@ public abstract class TreeUI extends ComponentUI /** * Returns the Rectangle enclosing the label portion that the * last item in path will be drawn into. Will return null if - * any component in path is currently valid. + * any component in path is currently invalid. * * @param tree the {@code JTree} for {@code path} * @param path the {@code TreePath} identifying the node diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTreeUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTreeUI.java index 2626b1c9585..d02a53315af 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTreeUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTreeUI.java @@ -665,7 +665,7 @@ public class BasicTreeUI extends TreeUI /** * Returns the Rectangle enclosing the label portion that the * last item in path will be drawn into. Will return null if - * any component in path is currently valid. + * any component in path is currently invalid. */ public Rectangle getPathBounds(JTree tree, TreePath path) { if(tree != null && treeState != null) { -- GitLab From d254cf28c5e72bd9b8de863b831015237640ca25 Mon Sep 17 00:00:00 2001 From: Jie Fu Date: Fri, 11 Feb 2022 11:39:54 +0000 Subject: [PATCH 467/564] 8281638: jfr/event/allocation tests fail with release VMs after JDK-8281318 due to lack of -XX:+UnlockDiagnosticVMOptions Reviewed-by: shade --- .../allocation/TestObjectAllocationInNewTLABEvent.java | 6 +++--- .../allocation/TestObjectAllocationOutsideTLABEvent.java | 6 +++--- .../TestObjectAllocationSampleEventThrottling.java | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/test/jdk/jdk/jfr/event/allocation/TestObjectAllocationInNewTLABEvent.java b/test/jdk/jdk/jfr/event/allocation/TestObjectAllocationInNewTLABEvent.java index cb70c0ba324..6dbd51b1386 100644 --- a/test/jdk/jdk/jfr/event/allocation/TestObjectAllocationInNewTLABEvent.java +++ b/test/jdk/jdk/jfr/event/allocation/TestObjectAllocationInNewTLABEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2022, 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 @@ -42,10 +42,10 @@ import sun.hotspot.WhiteBox; * @build sun.hotspot.WhiteBox * * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox - * @run main/othervm -XX:+WhiteBoxAPI -Xbootclasspath/a:. + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. * -XX:+UseTLAB -XX:TLABSize=100k -XX:-ResizeTLAB -XX:TLABRefillWasteFraction=1 * jdk.jfr.event.allocation.TestObjectAllocationInNewTLABEvent - * @run main/othervm -XX:+WhiteBoxAPI -Xbootclasspath/a:. + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. * -XX:+UseTLAB -XX:TLABSize=100k -XX:-ResizeTLAB -XX:TLABRefillWasteFraction=1 * -Xint * jdk.jfr.event.allocation.TestObjectAllocationInNewTLABEvent diff --git a/test/jdk/jdk/jfr/event/allocation/TestObjectAllocationOutsideTLABEvent.java b/test/jdk/jdk/jfr/event/allocation/TestObjectAllocationOutsideTLABEvent.java index 70bf4518f08..87c3b29af42 100644 --- a/test/jdk/jdk/jfr/event/allocation/TestObjectAllocationOutsideTLABEvent.java +++ b/test/jdk/jdk/jfr/event/allocation/TestObjectAllocationOutsideTLABEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2022, 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 @@ -42,10 +42,10 @@ import sun.hotspot.WhiteBox; * @build sun.hotspot.WhiteBox * * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox - * @run main/othervm -XX:+WhiteBoxAPI -Xbootclasspath/a:. + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. * -XX:+UseTLAB -XX:TLABSize=90k -XX:-ResizeTLAB -XX:TLABRefillWasteFraction=256 * jdk.jfr.event.allocation.TestObjectAllocationOutsideTLABEvent - * @run main/othervm -XX:+WhiteBoxAPI -Xbootclasspath/a:. + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. * -XX:+UseTLAB -XX:TLABSize=90k -XX:-ResizeTLAB -XX:TLABRefillWasteFraction=256 * -Xint * jdk.jfr.event.allocation.TestObjectAllocationOutsideTLABEvent diff --git a/test/jdk/jdk/jfr/event/allocation/TestObjectAllocationSampleEventThrottling.java b/test/jdk/jdk/jfr/event/allocation/TestObjectAllocationSampleEventThrottling.java index a10b6e2b56a..5049acc229c 100644 --- a/test/jdk/jdk/jfr/event/allocation/TestObjectAllocationSampleEventThrottling.java +++ b/test/jdk/jdk/jfr/event/allocation/TestObjectAllocationSampleEventThrottling.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,7 +44,7 @@ import sun.hotspot.WhiteBox; * @build sun.hotspot.WhiteBox * * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox - * @run main/othervm -XX:+WhiteBoxAPI -Xbootclasspath/a:. + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. * -XX:+UseTLAB -XX:TLABSize=2k -XX:-ResizeTLAB * jdk.jfr.event.allocation.TestObjectAllocationSampleEventThrottling */ -- GitLab From 4ff5824f5bc13826d2eae1c83094acfcccdb7b8f Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Fri, 11 Feb 2022 12:11:29 +0000 Subject: [PATCH 468/564] 8281100: Spurious "variable might not have been initialized" with sealed class switch Reviewed-by: vromero --- .../com/sun/tools/javac/comp/Flow.java | 32 ++++---- .../com/sun/tools/javac/tree/JCTree.java | 2 + .../com/sun/tools/javac/tree/TreeInfo.java | 6 ++ .../tools/javac/patterns/Exhaustiveness.java | 81 ++++++++++++++++++- 4 files changed, 104 insertions(+), 17 deletions(-) diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java index 1346d141bb7..db64097c02d 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java @@ -664,10 +664,7 @@ public class Flow { ListBuffer prevPendingExits = pendingExits; pendingExits = new ListBuffer<>(); scan(tree.selector); - boolean exhaustiveSwitch = tree.patternSwitch || - tree.cases.stream() - .flatMap(c -> c.labels.stream()) - .anyMatch(l -> TreeInfo.isNull(l)); + boolean exhaustiveSwitch = TreeInfo.expectedExhaustive(tree); Set constants = exhaustiveSwitch ? new HashSet<>() : null; for (List l = tree.cases; l.nonEmpty(); l = l.tail) { alive = Liveness.ALIVE; @@ -689,10 +686,13 @@ public class Flow { l.tail.head.pos(), Warnings.PossibleFallThroughIntoCase); } - if (!tree.hasTotalPattern && exhaustiveSwitch && - !TreeInfo.isErrorEnumSwitch(tree.selector, tree.cases) && - (constants == null || !isExhaustive(tree.selector.pos(), tree.selector.type, constants))) { - log.error(tree, Errors.NotExhaustiveStatement); + tree.isExhaustive = tree.hasTotalPattern || + TreeInfo.isErrorEnumSwitch(tree.selector, tree.cases); + if (exhaustiveSwitch) { + tree.isExhaustive |= isExhaustive(tree.selector.pos(), tree.selector.type, constants); + if (!tree.isExhaustive) { + log.error(tree, Errors.NotExhaustiveStatement); + } } if (!tree.hasTotalPattern) { alive = Liveness.ALIVE; @@ -725,8 +725,10 @@ public class Flow { } } } - if (!tree.hasTotalPattern && !TreeInfo.isErrorEnumSwitch(tree.selector, tree.cases) && - !isExhaustive(tree.selector.pos(), tree.selector.type, constants)) { + tree.isExhaustive = tree.hasTotalPattern || + TreeInfo.isErrorEnumSwitch(tree.selector, tree.cases) || + isExhaustive(tree.selector.pos(), tree.selector.type, constants); + if (!tree.isExhaustive) { log.error(tree, Errors.NotExhaustive); } alive = prevAlive; @@ -2432,15 +2434,15 @@ public class Flow { } public void visitSwitch(JCSwitch tree) { - handleSwitch(tree, tree.selector, tree.cases, tree.hasTotalPattern); + handleSwitch(tree, tree.selector, tree.cases, tree.isExhaustive); } public void visitSwitchExpression(JCSwitchExpression tree) { - handleSwitch(tree, tree.selector, tree.cases, tree.hasTotalPattern); + handleSwitch(tree, tree.selector, tree.cases, tree.isExhaustive); } private void handleSwitch(JCTree tree, JCExpression selector, - List cases, boolean hasTotalPattern) { + List cases, boolean isExhaustive) { ListBuffer prevPendingExits = pendingExits; pendingExits = new ListBuffer<>(); int nextadrPrev = nextadr; @@ -2478,10 +2480,10 @@ public class Flow { addVars(c.stats, initsSwitch, uninitsSwitch); // Warn about fall-through if lint switch fallthrough enabled. } - if (!hasTotalPattern) { + if (!isExhaustive) { if (tree.hasTag(SWITCH_EXPRESSION)) { markDead(); - } else { + } else if (tree.hasTag(SWITCH) && !TreeInfo.expectedExhaustive((JCSwitch) tree)) { inits.assign(initsSwitch); uninits.assign(uninits.andSet(uninitsSwitch)); } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java index a6d3de24e3c..cc66127baa4 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java @@ -1285,6 +1285,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { /** Position of closing brace, optional. */ public int endpos = Position.NOPOS; public boolean hasTotalPattern; + public boolean isExhaustive; public boolean patternSwitch; protected JCSwitch(JCExpression selector, List cases) { this.selector = selector; @@ -1371,6 +1372,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { /** Position of closing brace, optional. */ public int endpos = Position.NOPOS; public boolean hasTotalPattern; + public boolean isExhaustive; public boolean patternSwitch; protected JCSwitchExpression(JCExpression selector, List cases) { this.selector = selector; diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java index ee25802ca86..355e19c8826 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java @@ -1384,4 +1384,10 @@ public class TreeInfo { public record PatternPrimaryType(Type type, boolean unconditional) {} + public static boolean expectedExhaustive(JCSwitch tree) { + return tree.patternSwitch || + tree.cases.stream() + .flatMap(c -> c.labels.stream()) + .anyMatch(l -> TreeInfo.isNull(l)); + } } diff --git a/test/langtools/tools/javac/patterns/Exhaustiveness.java b/test/langtools/tools/javac/patterns/Exhaustiveness.java index b7db66c3231..75121a97eca 100644 --- a/test/langtools/tools/javac/patterns/Exhaustiveness.java +++ b/test/langtools/tools/javac/patterns/Exhaustiveness.java @@ -23,7 +23,7 @@ /** * @test - * @bug 8262891 8268871 8274363 + * @bug 8262891 8268871 8274363 8281100 * @summary Check exhaustiveness of switches over sealed types. * @library /tools/lib * @modules jdk.compiler/com.sun.tools.javac.api @@ -791,6 +791,82 @@ public class Exhaustiveness extends TestRunner { } } + @Test + public void testDefiniteAssignment(Path base) throws Exception { + doTest(base, + new String[]{""" + package lib; + public sealed interface S permits A, B {} + """, + """ + package lib; + public final class A implements S {} + """, + """ + package lib; + public final class B implements S {} + """}, + """ + package test; + import lib.*; + public class Test { + private void testStatement(S obj) { + int data; + switch (obj) { + case A a -> data = 0; + case B b -> data = 0; + }; + System.err.println(data); + } + private void testExpression(S obj) { + int data; + int v = switch (obj) { + case A a -> data = 0; + case B b -> data = 0; + }; + System.err.println(data); + } + private void testStatementNotExhaustive(S obj) { + int data; + switch (obj) { + case A a -> data = 0; + }; + System.err.println(data); + } + private void testExpressionNotExhaustive(S obj) { + int data; + int v = switch (obj) { + case A a -> data = 0; + }; + System.err.println(data); + } + private void testStatementErrorEnum(E e) { //"E" is intentionally unresolvable + int data; + switch (e) { + case A -> data = 0; + case B -> data = 0; + }; + System.err.println(data); + } + private void testExpressionErrorEnum(E e) { //"E" is intentionally unresolvable + int data; + int v = switch (e) { + case A -> data = 0; + case B -> data = 0; + }; + System.err.println(data); + } + } + """, + "Test.java:34:41: compiler.err.cant.resolve.location: kindname.class, E, , , (compiler.misc.location: kindname.class, test.Test, null)", + "Test.java:42:42: compiler.err.cant.resolve.location: kindname.class, E, , , (compiler.misc.location: kindname.class, test.Test, null)", + "Test.java:22:9: compiler.err.not.exhaustive.statement", + "Test.java:29:17: compiler.err.not.exhaustive", + "- compiler.note.preview.filename: Test.java, DEFAULT", + "- compiler.note.preview.recompile", + "4 errors"); + } + private void doTest(Path base, String[] libraryCode, String testCode, String... expectedErrors) throws IOException { Path current = base.resolve("."); Path libClasses = current.resolve("libClasses"); @@ -825,7 +901,8 @@ public class Exhaustiveness extends TestRunner { "-source", JAVA_VERSION, "-XDrawDiagnostics", "-Xlint:-preview", - "--class-path", libClasses.toString()) + "--class-path", libClasses.toString(), + "-XDshould-stop.at=FLOW") .outdir(classes) .files(tb.findJavaFiles(src)) .run(expectedErrors.length > 0 ? Task.Expect.FAIL : Task.Expect.SUCCESS) -- GitLab From f399ae558eabdce8960d339ef0758c023aeb89cc Mon Sep 17 00:00:00 2001 From: "lawrence.andrews" Date: Fri, 11 Feb 2022 15:33:17 +0000 Subject: [PATCH 469/564] 8202836: [macosx] test java/awt/Graphics/TextAAHintsTest.java fails Reviewed-by: prr, aivanov --- .../java/awt/Graphics/TextAAHintsTest.java | 132 +++++++++++++++--- 1 file changed, 110 insertions(+), 22 deletions(-) diff --git a/test/jdk/java/awt/Graphics/TextAAHintsTest.java b/test/jdk/java/awt/Graphics/TextAAHintsTest.java index 46fa6c28c9b..15fd5a63464 100644 --- a/test/jdk/java/awt/Graphics/TextAAHintsTest.java +++ b/test/jdk/java/awt/Graphics/TextAAHintsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,21 +21,44 @@ * questions. */ -/** +/* * @test * @bug 6263951 * @summary Text should be B&W, grayscale, and LCD. - * @run main/manual=yesno TextAAHintsTest + * @requires (os.family != "mac") + * @run main/manual TextAAHintsTest */ -import java.awt.*; -import java.awt.geom.*; -import java.awt.image.*; + +import java.awt.AWTException; +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dialog; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.ImageCapabilities; +import java.awt.Panel; +import java.awt.RenderingHints; +import java.awt.TextArea; +import java.awt.image.BufferedImage; +import java.awt.image.VolatileImage; +import java.lang.reflect.InvocationTargetException; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; public class TextAAHintsTest extends Component { - String black = "This text should be solid black"; - String gray = "This text should be gray scale anti-aliased"; - String lcd = "This text should be LCD sub-pixel text (coloured)."; + private static final String black = "This text should be solid black"; + private static final String gray = "This text should be gray scale anti-aliased"; + private static final String lcd = "This text should be LCD sub-pixel text (coloured)."; + private static final CountDownLatch countDownLatch = new CountDownLatch(1); + private static volatile String failureReason; + private static volatile boolean testPassed = false; + private static Frame frame; public void paint(Graphics g) { @@ -63,28 +86,24 @@ public class TextAAHintsTest extends Component { RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); g2d.drawString(black, 10, 20); - g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, - RenderingHints.VALUE_TEXT_ANTIALIAS_GASP); - g2d.drawString(black, 10, 35); - g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT); - g2d.drawString(gray, 10, 50); + g2d.drawString(gray, 10, 35); g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); - g2d.drawString(gray, 10, 65); + g2d.drawString(gray, 10, 50); /* For visual comparison, render grayscale with graphics AA off */ g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); - g2d.drawString(gray, 10, 80); + g2d.drawString(gray, 10, 65); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB); - g2d.drawString(lcd, 10, 95); + g2d.drawString(lcd, 10, 80); } public void bufferedImageText(Graphics g) { @@ -139,11 +158,80 @@ public class TextAAHintsTest extends Component { return new Dimension(500,300); } - public static void main(String[] args) throws Exception { + public static void createTestUI() { + frame = new Frame("Composite and Text Test"); + TextAAHintsTest textAAHintsTestObject = new TextAAHintsTest(); + frame.add(textAAHintsTestObject, BorderLayout.NORTH); + + String instructions = """ + Note: Texts are rendered with different TEXT_ANTIALIASING & + VALUE_TEXT_ANTIALIAS. Text should be B&W, grayscale, and LCD. + Note: The results may be visually the same. + 1. Verify that first set of text are rendered correctly. + 2. Second set of text are created using BufferedImage of the first text. + 3. Third set of text are created using VolatileImage of the first text. + """; + TextArea instructionTextArea = new TextArea(instructions, 8, 50); + instructionTextArea.setEditable(false); + frame.add(instructionTextArea, BorderLayout.CENTER); + + Panel controlPanel = new Panel(); + Button passButton = new Button("Pass"); + passButton.addActionListener(e -> { + testPassed = true; + countDownLatch.countDown(); + frame.dispose(); + }); + Button failButton = new Button("Fail"); + failButton.addActionListener(e -> { + getFailureReason(); + testPassed = false; + countDownLatch.countDown(); + frame.dispose(); + }); + controlPanel.add(passButton); + controlPanel.add(failButton); + frame.add(controlPanel, BorderLayout.SOUTH); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + public static void getFailureReason() { + // Show dialog to read why the testcase was failed and append the + // testcase failure reason to the output + final Dialog dialog = new Dialog(frame, "TestCase" + + " failure reason", true); + TextArea textArea = new TextArea("", 5, 60, TextArea.SCROLLBARS_BOTH); + dialog.add(textArea, BorderLayout.CENTER); + + Button okButton = new Button("OK"); + okButton.addActionListener(e1 -> { + failureReason = textArea.getText(); + dialog.dispose(); + }); + Panel ctlPanel = new Panel(); + ctlPanel.add(okButton); + dialog.add(ctlPanel, BorderLayout.SOUTH); + dialog.setLocationRelativeTo(null); + dialog.pack(); + dialog.setVisible(true); + } + + public static void main(String[] args) throws InterruptedException, InvocationTargetException { + EventQueue.invokeAndWait(TextAAHintsTest::createTestUI); + if (!countDownLatch.await(2, TimeUnit.MINUTES)) { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + throw new RuntimeException("Timeout : No action was taken on the test."); + } - Frame f = new Frame("Composite and Text Test"); - f.add(new TextAAHintsTest(), BorderLayout.CENTER); - f.pack(); - f.setVisible(true); + if (!testPassed) { + throw new RuntimeException("Test failed : Reason : " + failureReason); + } } } + -- GitLab From e73ee0ca10b644600ee3747b901e5f69104d03df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Jeli=C5=84ski?= Date: Fri, 11 Feb 2022 16:24:43 +0000 Subject: [PATCH 470/564] 8281259: MutableBigInteger subtraction could be simplified Reviewed-by: bpb --- .../share/classes/java/math/MutableBigInteger.java | 10 +++++----- .../org/openjdk/bench/java/math/BigIntegers.java | 11 +++++++++++ 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/java.base/share/classes/java/math/MutableBigInteger.java b/src/java.base/share/classes/java/math/MutableBigInteger.java index 7d0ccbf1e09..91f710d67b8 100644 --- a/src/java.base/share/classes/java/math/MutableBigInteger.java +++ b/src/java.base/share/classes/java/math/MutableBigInteger.java @@ -945,13 +945,13 @@ class MutableBigInteger { x--; y--; diff = (a.value[x+a.offset] & LONG_MASK) - - (b.value[y+b.offset] & LONG_MASK) - ((int)-(diff>>32)); + (b.value[y+b.offset] & LONG_MASK) + (diff >> 32); result[rstart--] = (int)diff; } // Subtract remainder of longer number while (x > 0) { x--; - diff = (a.value[x+a.offset] & LONG_MASK) - ((int)-(diff>>32)); + diff = (a.value[x+a.offset] & LONG_MASK) + (diff >> 32); result[rstart--] = (int)diff; } @@ -986,13 +986,13 @@ class MutableBigInteger { while (y > 0) { x--; y--; diff = (a.value[a.offset+ x] & LONG_MASK) - - (b.value[b.offset+ y] & LONG_MASK) - ((int)-(diff>>32)); + (b.value[b.offset+ y] & LONG_MASK) + (diff >> 32); a.value[a.offset+x] = (int)diff; } // Subtract remainder of longer number - while (x > 0) { + while (diff < 0 && x > 0) { x--; - diff = (a.value[a.offset+ x] & LONG_MASK) - ((int)-(diff>>32)); + diff = (a.value[a.offset+ x] & LONG_MASK) + (diff >> 32); a.value[a.offset+x] = (int)diff; } diff --git a/test/micro/org/openjdk/bench/java/math/BigIntegers.java b/test/micro/org/openjdk/bench/java/math/BigIntegers.java index e2d563d8306..54056e2c5d4 100644 --- a/test/micro/org/openjdk/bench/java/math/BigIntegers.java +++ b/test/micro/org/openjdk/bench/java/math/BigIntegers.java @@ -207,4 +207,15 @@ public class BigIntegers { bh.consume(tmp); } } + + /** Invokes the gcd method of BigInteger with different values. */ + @Benchmark + @OperationsPerInvocation(TESTSIZE) + public void testGcd(Blackhole bh) { + for (int i = 0; i < TESTSIZE; i++) { + BigInteger i1 = shiftArray[TESTSIZE - i - 1]; + BigInteger i2 = shiftArray[i]; + bh.consume(i2.gcd(i1)); + } + } } -- GitLab From e75e8cd708ed478eda08c4a5c724e7e82f57d36e Mon Sep 17 00:00:00 2001 From: Yumin Qi Date: Fri, 11 Feb 2022 16:42:07 +0000 Subject: [PATCH 471/564] 8279997: check_for_dynamic_dump should not exit vm Reviewed-by: ccheung, iklam --- src/hotspot/share/cds/dynamicArchive.cpp | 5 +- src/hotspot/share/runtime/arguments.cpp | 4 ++ .../dynamicArchive/ArchiveConsistency.java | 27 ++++++++++- .../SharedArchiveFileOption.java | 48 ++++++++----------- 4 files changed, 54 insertions(+), 30 deletions(-) diff --git a/src/hotspot/share/cds/dynamicArchive.cpp b/src/hotspot/share/cds/dynamicArchive.cpp index 0ff6a017fed..00d586ffc4f 100644 --- a/src/hotspot/share/cds/dynamicArchive.cpp +++ b/src/hotspot/share/cds/dynamicArchive.cpp @@ -375,9 +375,10 @@ void DynamicArchive::check_for_dynamic_dump() { vm_exit_during_initialization("-XX:+RecordDynamicDumpInfo" __THEMSG, NULL); } else { assert(ArchiveClassesAtExit != nullptr, "sanity"); - vm_exit_during_initialization("-XX:ArchiveClassesAtExit" __THEMSG, NULL); -#undef __THEMSG + warning("-XX:ArchiveClassesAtExit" __THEMSG); } +#undef __THEMSG + DynamicDumpSharedSpaces = false; } } diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index c0f78eaaccf..7d0f1ddd4d3 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -3576,6 +3576,10 @@ void Arguments::init_shared_archive_paths() { SharedArchivePath = get_default_shared_archive_path(); SharedArchiveFile = nullptr; } else { + if (AutoCreateSharedArchive) { + warning("-XX:+AutoCreateSharedArchive is unsupported when base CDS archive is not loaded. Run with -Xlog:cds for more info."); + AutoCreateSharedArchive = false; + } no_shared_spaces("invalid archive"); } } else if (base_archive_path == NULL) { diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/ArchiveConsistency.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/ArchiveConsistency.java index 33bfc2ef99e..0dcc0e3d7b0 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/ArchiveConsistency.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/ArchiveConsistency.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, 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 @@ -202,5 +202,30 @@ public class ArchiveConsistency extends DynamicArchiveTestBase { runTwo(nonExistBase, nonExistTop, appJar, mainClass, isAuto ? 0 : 1, "Specified shared archive not found (" + nonExistBase + ")"); + + // following two tests: + // -Xshare:auto -XX:SharedArchiveFile=top.jsa, but base does not exist. + + new File(baseArchiveName).delete(); + + startTest("10. -XX:+AutoCreateSharedArchive -XX:SharedArchiveFile=" + topArchiveName); + run(topArchiveName, + "-Xshare:auto", + "-XX:+AutoCreateSharedArchive", + "-cp", + appJar, mainClass) + .assertNormalExit(output -> { + output.shouldContain("warning: -XX:+AutoCreateSharedArchive is unsupported when base CDS archive is not loaded"); + }); + + startTest("11. -XX:SharedArchiveFile=" + topArchiveName + " -XX:ArchiveClassesAtExit=" + getNewArchiveName("top3")); + run(topArchiveName, + "-Xshare:auto", + "-XX:ArchiveClassesAtExit=" + getNewArchiveName("top3"), + "-cp", + appJar, mainClass) + .assertNormalExit(output -> { + output.shouldContain("VM warning: -XX:ArchiveClassesAtExit is unsupported when base CDS archive is not loaded"); + }); } } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/SharedArchiveFileOption.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/SharedArchiveFileOption.java index 1dd12b2b55d..d06bb8ef106 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/SharedArchiveFileOption.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/SharedArchiveFileOption.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, 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 @@ -64,17 +64,6 @@ public class SharedArchiveFileOption extends DynamicArchiveTestBase { public void run() throws Exception; } - private static void mustSkipWith(String expectedMsg, MyRunnable r) throws Exception { - try { - r.run(); - } catch (SkippedException e) { - System.out.println("Got SkippedException: " + e); - Asserts.assertTrue(e.getMessage().contains(expectedMsg), "SkippedException must have message " + expectedMsg); - return; - } - Asserts.fail("SkippedException should have been thrown"); - } - private static void doTest(String baseArchiveName, String topArchiveName) throws Exception { String appJar = ClassFileInstaller.getJarPath("hello.jar"); String mainClass = "Hello"; @@ -205,25 +194,30 @@ public class SharedArchiveFileOption extends DynamicArchiveTestBase { output.shouldNotMatch("\\[cds,dynamic"); }); - { + { String ERROR = "-XX:ArchiveClassesAtExit is unsupported when base CDS archive is not loaded"; testcase("-XX:ArchiveClassesAtExit with CDS disabled (-Xshare:off)"); - mustSkipWith(ERROR, () -> { - dump2(baseArchiveName, - topArchiveName, - "-Xshare:off", - "-cp", appJar, mainClass); - }); + dump2(baseArchiveName, + topArchiveName, + "-Xshare:off", + "-Xlog:cds", + "-cp", appJar, mainClass) + .assertNormalExit(output -> { + output.shouldNotMatch("\\[cds,dynamic"); + output.shouldContain(ERROR); + }); testcase("-XX:ArchiveClassesAtExit with CDS disabled (Base archive cannot be mapped -- doesn't exist"); - mustSkipWith(ERROR, () -> { - dump2(baseArchiveName + ".notExist", - topArchiveName, - "-Xlog:cds", - "-Xshare:auto", - "-cp", appJar, mainClass); - }); + dump2(baseArchiveName + ".notExist", + topArchiveName, + "-Xlog:cds", + "-Xshare:auto", + "-cp", appJar, mainClass) + .assertNormalExit(output -> { + output.shouldNotMatch("\\[cds,dynamic"); + output.shouldContain(ERROR); + }); testcase("-XX:ArchiveClassesAtExit with CDS disabled (incompatible VM options)"); dump2(baseArchiveName, @@ -233,7 +227,7 @@ public class SharedArchiveFileOption extends DynamicArchiveTestBase { "-Xshare:auto", "-Xlog:cds", "-cp", appJar, mainClass) - .assertAbnormalExit("Cannot use the following option when dumping the shared archive: --patch-module"); + .assertAbnormalExit("Cannot use the following option when dumping the shared archive: --patch-module"); } { -- GitLab From 8886839779094f8a13c16be79f88052b2c79eeea Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Fri, 11 Feb 2022 17:15:04 +0000 Subject: [PATCH 472/564] 8281622: JFR: Improve documentation of jdk.jfr.Relational Reviewed-by: jbachorik --- .../share/classes/jdk/jfr/Relational.java | 9 ++++- .../jdk/jfr/snippet-files/Snippets.java | 40 +++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/src/jdk.jfr/share/classes/jdk/jfr/Relational.java b/src/jdk.jfr/share/classes/jdk/jfr/Relational.java index f195d6ac67b..153346a19ac 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/Relational.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/Relational.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,6 +32,13 @@ import java.lang.annotation.Target; /** * Meta annotation for relational annotations, to be used on an annotation. + *

    + * The following example shows how a relational annotation can be created and + * used. The {@code Orderid} annotation indicates there is a relation between + * {@code OrderEvent} and {@code OrderLineEvent}. if they have the same ID, + * the order line belongs to the order. + * + * {@snippet class="Snippets" region="RelationalOverview"} * * @since 9 */ diff --git a/src/jdk.jfr/share/classes/jdk/jfr/snippet-files/Snippets.java b/src/jdk.jfr/share/classes/jdk/jfr/snippet-files/Snippets.java index ef95e2ffb35..ef2ff2f3670 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/snippet-files/Snippets.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/snippet-files/Snippets.java @@ -42,6 +42,7 @@ import jdk.jfr.consumer.RecordingFile; import jdk.jfr.Configuration; import jdk.jfr.SettingDefinition; import jdk.jfr.SettingControl; +import jdk.jfr.Timestamp; import jdk.jfr.FlightRecorder; import jdk.jfr.consumer.RecordedEvent; @@ -260,6 +261,45 @@ public class Snippets { } // @end + // @start region="RelationalOverview" + @MetadataDefinition + @Relational + @Name("com.example.OrderId") + @Label("Order ID") + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.FIELD) + public @interface OrderId { + } + + @Name("com.example.Order") + @Label("Order") + @Category("Orders") + class OrderEvent extends Event { + @Label("Order ID") + @OrderId + long orderId; + + @Label("Order Date") + @Timestamp + long orderDate; + } + + @Name("com.example.OrderLine") + @Label("Order Line") + @Category("Orders") + class OrderLineEvent extends Event { + @Label("Order ID") + @OrderId + long orderId; + + @Label("Quantity") + long quantity; + + @Label("Product") + String product; + } + // @end + void RecordingnOverview() throws Exception { // @start region="RecordingOverview" Configuration c = Configuration.getConfiguration("default"); -- GitLab From c5ff6e45dee41b5703138d323a04c2c7973a08b9 Mon Sep 17 00:00:00 2001 From: Calvin Cheung Date: Fri, 11 Feb 2022 17:39:20 +0000 Subject: [PATCH 473/564] 8223077: module path support for dynamic CDS archive Reviewed-by: iklam, minqi --- src/hotspot/share/cds/filemap.cpp | 19 ++- src/hotspot/share/cds/filemap.hpp | 1 + src/hotspot/share/runtime/arguments.hpp | 2 +- .../jtreg/runtime/cds/appcds/TestCommon.java | 15 +- .../cds/appcds/dynamicArchive/ModulePath.java | 131 ++++++++++++++++++ .../UnsupportedBaseArchive.java | 23 +-- 6 files changed, 175 insertions(+), 16 deletions(-) create mode 100644 test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/ModulePath.java diff --git a/src/hotspot/share/cds/filemap.cpp b/src/hotspot/share/cds/filemap.cpp index 5128565803b..63ba7fb2893 100644 --- a/src/hotspot/share/cds/filemap.cpp +++ b/src/hotspot/share/cds/filemap.cpp @@ -963,6 +963,17 @@ void FileMapInfo::log_paths(const char* msg, int start_idx, int end_idx) { } } +bool FileMapInfo::check_module_paths() { + const char* rp = Arguments::get_property("jdk.module.path"); + int num_paths = Arguments::num_archives(rp); + if (num_paths != header()->num_module_paths()) { + return false; + } + ResourceMark rm; + GrowableArray* rp_array = create_path_array(rp); + return check_paths(header()->app_module_paths_start_index(), num_paths, rp_array); +} + bool FileMapInfo::validate_shared_path_table() { assert(UseSharedSpaces, "runtime only"); @@ -985,9 +996,11 @@ bool FileMapInfo::validate_shared_path_table() { "Dynamic archiving is disabled because base layer archive has appended boot classpath"); } if (header()->num_module_paths() > 0) { - DynamicDumpSharedSpaces = false; - warning( - "Dynamic archiving is disabled because base layer archive has module path"); + if (!check_module_paths()) { + DynamicDumpSharedSpaces = false; + warning( + "Dynamic archiving is disabled because base layer archive has a different module path"); + } } } diff --git a/src/hotspot/share/cds/filemap.hpp b/src/hotspot/share/cds/filemap.hpp index e6655858187..f34fb4d7211 100644 --- a/src/hotspot/share/cds/filemap.hpp +++ b/src/hotspot/share/cds/filemap.hpp @@ -491,6 +491,7 @@ public: static void clone_shared_path_table(TRAPS); static int add_shared_classpaths(int i, const char* which, ClassPathEntry *cpe, TRAPS); static void check_nonempty_dir_in_shared_path_table(); + bool check_module_paths(); bool validate_shared_path_table(); void validate_non_existent_class_paths(); static void set_shared_path_table(FileMapInfo* info) { diff --git a/src/hotspot/share/runtime/arguments.hpp b/src/hotspot/share/runtime/arguments.hpp index 19bb12196e3..de6cf1a4d23 100644 --- a/src/hotspot/share/runtime/arguments.hpp +++ b/src/hotspot/share/runtime/arguments.hpp @@ -470,12 +470,12 @@ class Arguments : AllStatic { static char* SharedArchivePath; static char* SharedDynamicArchivePath; static size_t _default_SharedBaseAddress; // The default value specified in globals.hpp - static int num_archives(const char* archive_path) NOT_CDS_RETURN_(0); static void extract_shared_archive_paths(const char* archive_path, char** base_archive_path, char** top_archive_path) NOT_CDS_RETURN; public: + static int num_archives(const char* archive_path) NOT_CDS_RETURN_(0); // Parses the arguments, first phase static jint parse(const JavaVMInitArgs* args); // Parse a string for a unsigned integer. Returns true if value diff --git a/test/hotspot/jtreg/runtime/cds/appcds/TestCommon.java b/test/hotspot/jtreg/runtime/cds/appcds/TestCommon.java index a90512f73fb..959d43173d0 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/TestCommon.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/TestCommon.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2022, 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 @@ -153,6 +153,19 @@ public class TestCommon extends CDSTestUtils { return out; } + public static OutputAnalyzer dumpBaseArchive(String baseArchiveName, String classList[], String ... cmdLineSuffix) + throws Exception + { + CDSOptions opts = new CDSOptions(); + opts.setArchiveName(baseArchiveName); + opts.setClassList(classList); + opts.addSuffix(cmdLineSuffix); + opts.addSuffix("-Djava.class.path="); + OutputAnalyzer out = CDSTestUtils.createArchive(opts); + CDSTestUtils.checkBaseDump(out); + return out; + } + // Create AppCDS archive using most common args - convenience method public static OutputAnalyzer createArchive(String appJar, String classList[], String... suffix) throws Exception { diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/ModulePath.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/ModulePath.java new file mode 100644 index 00000000000..2672225ee05 --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/ModulePath.java @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2022, 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.io.File; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import jdk.test.lib.cds.CDSTestUtils; + +/* + * @test + * @summary Dyanmic archive with module path + * @requires vm.cds + * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds /test/hotspot/jtreg/runtime/cds/appcds/test-classes + * @compile ../test-classes/Hello.java + * @build sun.hotspot.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar WhiteBox.jar sun.hotspot.WhiteBox + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:./WhiteBox.jar ModulePath + */ + +public class ModulePath extends DynamicArchiveTestBase { + private static final Path USER_DIR = Paths.get(CDSTestUtils.getOutputDir()); + + private static final String FS = File.separator; + private static final String TEST_SRC = System.getProperty("test.src") + + FS + ".." + FS + "jigsaw" + FS + "modulepath"; + + private static final Path SRC_DIR = Paths.get(TEST_SRC, "src"); + private static final Path MODS_DIR = Paths.get("mods"); + + // the module name of the test module + private static final String TEST_MODULE = "com.simple"; + + // the module main class + private static final String MAIN_CLASS = "com.simple.Main"; + + private static Path moduleDir = null; + private static Path srcJar = null; + + public static void buildTestModule() throws Exception { + + // javac -d mods/$TESTMODULE --module-path MOD_DIR src/$TESTMODULE/** + JarBuilder.compileModule(SRC_DIR.resolve(TEST_MODULE), + MODS_DIR.resolve(TEST_MODULE), + MODS_DIR.toString()); + + + moduleDir = Files.createTempDirectory(USER_DIR, "mlib"); + srcJar = moduleDir.resolve(TEST_MODULE + ".jar"); + String classes = MODS_DIR.resolve(TEST_MODULE).toString(); + JarBuilder.createModularJar(srcJar.toString(), classes, MAIN_CLASS); + } + + public static void main(String[] args) throws Exception { + runTest(ModulePath::test); + } + + static void test(String args[]) throws Exception { + String topArchiveName = getNewArchiveName("top"); + String baseArchiveName = getNewArchiveName("base"); + + String appJar = JarBuilder.getOrCreateHelloJar(); + String mainClass = "Hello"; + + // create a base archive with the --module-path option + buildTestModule(); + baseArchiveName = getNewArchiveName("base-with-module"); + String appClasses[] = {mainClass}; + TestCommon.dumpBaseArchive(baseArchiveName, + appClasses, + "-Xlog:class+load", + "-cp", appJar, + "--module-path", moduleDir.toString(), + "-m", TEST_MODULE); + + // Dumping of dynamic archive should be successful if the specified + // --module-path is the same as for the base archive. + topArchiveName = getNewArchiveName("top-with-module"); + dump2(baseArchiveName, topArchiveName, + "-Xlog:cds*", + "-Xlog:cds+dynamic=debug", + "-Xlog:class+path=info,class+load", + "-cp", appJar, + "--module-path", moduleDir.toString(), + "-m", TEST_MODULE, MAIN_CLASS) + .assertNormalExit(); + + // Load the Hello class from the base archive. + run2(baseArchiveName, topArchiveName, + "-Xlog:class+load", + "-Xlog:cds+dynamic=debug,cds=debug", + "-cp", appJar, mainClass) + .assertNormalExit(output -> { + output.shouldContain("Hello source: shared objects file") + .shouldHaveExitValue(0); + }); + + // Load the com.simple.Main class from the dynamic archive. + run2(baseArchiveName, topArchiveName, + "-Xlog:class+load", + "-Xlog:cds+dynamic=debug,cds=debug", + "-cp", appJar, + "--module-path", moduleDir.toString(), + "-m", TEST_MODULE, MAIN_CLASS) + .assertNormalExit(output -> { + output.shouldContain("com.simple.Main source: shared objects file (top)") + .shouldHaveExitValue(0); + }); + } +} diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/UnsupportedBaseArchive.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/UnsupportedBaseArchive.java index a6027354e25..6a34bcc3192 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/UnsupportedBaseArchive.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/UnsupportedBaseArchive.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, 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 @@ -62,7 +62,7 @@ public class UnsupportedBaseArchive extends DynamicArchiveTestBase { "Dynamic archiving is disabled because base layer archive has appended boot classpath"; private static final String warningModulePath = - "Dynamic archiving is disabled because base layer archive has module path"; + "Dynamic archiving is disabled because base layer archive has a different module path"; public static void buildTestModule() throws Exception { @@ -104,22 +104,23 @@ public class UnsupportedBaseArchive extends DynamicArchiveTestBase { // create a base archive with the --module-path option buildTestModule(); baseArchiveName = getNewArchiveName("base-with-module"); + String appClasses[] = {mainClass}; TestCommon.dumpBaseArchive(baseArchiveName, - "-cp", srcJar.toString(), + appClasses, + "-Xlog:class+load", + "-cp", appJar, "--module-path", moduleDir.toString(), "-m", TEST_MODULE); - // dumping of dynamic archive should be disabled with a warning message - // if the base archive contains --module-path entries. - topArchiveName = getNewArchiveName("top-with-module"); + // Try to create a dynamic archive without specifying module path, + // dumping should fail. + topArchiveName = getNewArchiveName("top-with-module-failed"); dump2(baseArchiveName, topArchiveName, "-Xlog:cds*", "-Xlog:cds+dynamic=debug", - "-Xlog:class+path=info", - "-cp", srcJar.toString(), - "--module-path", moduleDir.toString(), - "-m", TEST_MODULE) + "-Xlog:class+path=info,class+load", + "-cp", appJar, + mainClass) .assertNormalExit(warningModulePath); - } } -- GitLab From 0786ddb4712296c90df2c9e97c76c203a4de4612 Mon Sep 17 00:00:00 2001 From: Manukumar V S Date: Fri, 11 Feb 2022 17:40:25 +0000 Subject: [PATCH 474/564] 8281535: Create a regression test for JDK-4670051 Reviewed-by: aivanov --- .../4670051/DateFieldUnderCursorTest.java | 282 ++++++++++++++++++ 1 file changed, 282 insertions(+) create mode 100644 test/jdk/javax/swing/JSpinner/4670051/DateFieldUnderCursorTest.java diff --git a/test/jdk/javax/swing/JSpinner/4670051/DateFieldUnderCursorTest.java b/test/jdk/javax/swing/JSpinner/4670051/DateFieldUnderCursorTest.java new file mode 100644 index 00000000000..c0346700699 --- /dev/null +++ b/test/jdk/javax/swing/JSpinner/4670051/DateFieldUnderCursorTest.java @@ -0,0 +1,282 @@ +/* + * Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.ComponentOrientation; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Date; +import java.util.List; +import java.util.stream.Collectors; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JSpinner; +import javax.swing.SpinnerDateModel; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; + +import static javax.swing.UIManager.getInstalledLookAndFeels; + +/* + * @test + * @key headful + * @bug 4670051 + * @summary Checks whether JSpinner with a SpinnerDateModel + * spins the field where cursor is located. + * @run main DateFieldUnderCursorTest + */ +public class DateFieldUnderCursorTest { + + private static final Calendar expected = Calendar.getInstance(); + private static final Calendar actual = Calendar.getInstance(); + private static Robot robot; + private static JSpinner spinner; + private static Date initValue; + private static Date upValue; + private static Date downValue; + private static JFrame frame; + private static boolean passed = true; + private static volatile Point spinnerUpButtonCenter; + private static volatile Point spinnerDownButtonCenter; + private static volatile Date spinnerValue; + + public static void main(String[] s) throws Exception { + runTest(); + } + + public static void runTest() throws Exception { + robot = new Robot(); + robot.setAutoWaitForIdle(true); + robot.setAutoDelay(100); + List lafs = Arrays.stream(getInstalledLookAndFeels()) + .map(UIManager.LookAndFeelInfo::getClassName) + .collect(Collectors.toList()); + for (final String laf : lafs) { + try { + SwingUtilities.invokeAndWait(() -> { + setLookAndFeel(laf); + createUI(); + }); + SwingUtilities.invokeAndWait(() -> { + Point loc = spinner.getLocationOnScreen(); + int editorWidth = spinner.getEditor().getWidth(); + int buttonWidth = spinner.getWidth() - editorWidth; + int quarterHeight = spinner.getHeight() / 4; + + spinnerUpButtonCenter = new Point(loc.x + editorWidth + + (buttonWidth / 2), + loc.y + quarterHeight); + spinnerDownButtonCenter = new Point(spinnerUpButtonCenter.x, + loc.y + (3 * quarterHeight)); + }); + + // Cursor at Day field. + // Increment Day + initValue = getSpinnerValue(); + mousePressOnUpButton(); + upValue = getSpinnerValue(); + verifyDayIncrement(); + // Decrement Day + initValue = getSpinnerValue(); + mousePressOnDownButton(); + downValue = getSpinnerValue(); + verifyDayDecrement(); + + // Cursor at Month Field + pressRightArrowKey(); + // Increment Month + initValue = getSpinnerValue(); + mousePressOnUpButton(); + upValue = getSpinnerValue(); + verifyMonthIncrement(); + // Decrement Month + initValue = getSpinnerValue(); + mousePressOnDownButton(); + downValue = getSpinnerValue(); + verifyMonthDecrement(); + + // Cursor at Year Field + pressRightArrowKey(); + // Increment Year + initValue = getSpinnerValue(); + mousePressOnUpButton(); + upValue = getSpinnerValue(); + verifyYearIncrement(); + // Decrement Year + initValue = getSpinnerValue(); + mousePressOnDownButton(); + downValue = getSpinnerValue(); + verifyYearDecrement(); + + if (passed) { + System.out.println("Test Passed"); + } else { + throw new RuntimeException("Test Failed as one or more cases failed"); + } + } finally { + SwingUtilities.invokeAndWait(DateFieldUnderCursorTest::disposeFrame); + } + } + } + + private static Date getSpinnerValue() throws Exception { + SwingUtilities.invokeAndWait(() -> spinnerValue = (Date) spinner.getValue()); + return spinnerValue; + } + + public static void pressRightArrowKey() { + robot.keyPress(KeyEvent.VK_RIGHT); + robot.keyRelease(KeyEvent.VK_RIGHT); + } + + public static void mousePressOnUpButton() { + robot.mouseMove(spinnerUpButtonCenter.x, spinnerUpButtonCenter.y); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + } + + public static void mousePressOnDownButton() { + robot.mouseMove(spinnerDownButtonCenter.x, spinnerDownButtonCenter.y); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + } + + + public static boolean compareDates() { + return (expected.get(Calendar.DATE) == actual.get(Calendar.DATE)) + && (expected.get(Calendar.MONTH) == actual.get(Calendar.MONTH)) + && (expected.get(Calendar.YEAR) == actual.get(Calendar.YEAR)); + } + + private static void checkResult() { + if (compareDates()) { + System.out.println(" Case Passed"); + } else { + passed = false; + System.out.println(" Case Failed because the expected: " + expected.getTime() + + " and actual: " + actual.getTime() + " outputs do not match."); + } + } + + private static void updateCalendarObjects(Date finalValue) { + expected.setTime(initValue); + actual.setTime(finalValue); + } + + /** + * Verifying that JSpinner increments the date field when cursor is on date field + */ + private static void verifyDayIncrement() { + System.out.print("verifyDateIncrement"); + updateCalendarObjects(upValue); + expected.add(Calendar.DATE, 1); + checkResult(); + } + + /** + * Verifying that JSpinner decrements the date field when cursor is on date field + */ + private static void verifyDayDecrement() { + System.out.print("verifyDateDecrement"); + updateCalendarObjects(downValue); + expected.add(Calendar.DATE, -1); + checkResult(); + } + + /** + * Verifying that JSpinner increments the month field when cursor is on month field + */ + private static void verifyMonthIncrement() { + System.out.print("verifyMonthIncrement"); + updateCalendarObjects(upValue); + expected.add(Calendar.MONTH, 1); + checkResult(); + } + + /** + * Verifying that JSpinner decrements the month field when cursor is on month field + */ + private static void verifyMonthDecrement() { + System.out.print("verifyMonthDecrement"); + updateCalendarObjects(downValue); + expected.add(Calendar.MONTH, -1); + checkResult(); + } + + /** + * Verifying that, JSpinner decrements the year field when the cursor is on year field. + */ + private static void verifyYearDecrement() { + System.out.print("verifyYearDecrement"); + updateCalendarObjects(downValue); + expected.add(Calendar.YEAR, -1); + checkResult(); + } + + /** + * Verifying that JSpinner increments the year field when cursor is on year field + */ + private static void verifyYearIncrement() { + System.out.print("verifyYearIncrement"); + updateCalendarObjects(upValue); + expected.add(Calendar.YEAR, 1); + checkResult(); + } + + private static void createUI() { + frame = new JFrame(); + JPanel panel = new JPanel(); + spinner = new JSpinner(new SpinnerDateModel()); + JSpinner.DateEditor editor = new JSpinner.DateEditor(spinner, " dd/MM/yy "); + spinner.setEditor(editor); + spinner.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT); + panel.add(spinner); + + frame.add(panel); + frame.setUndecorated(true); + frame.pack(); + frame.setAlwaysOnTop(true); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + private static void setLookAndFeel(final String laf) { + try { + UIManager.setLookAndFeel(laf); + System.out.println("LookAndFeel: " + laf); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private static void disposeFrame() { + if (frame != null) { + frame.dispose(); + frame = null; + } + } + +} -- GitLab From 83ffbd2e7aed8a9c788395ccbe920ddff221ae16 Mon Sep 17 00:00:00 2001 From: "Dr Heinz M. Kabutz" Date: Fri, 11 Feb 2022 18:49:04 +0000 Subject: [PATCH 475/564] 8277175: Add a parallel multiply method to BigInteger Reviewed-by: psandoz --- .../share/classes/java/math/BigInteger.java | 155 +++++++-- .../BigIntegerParallelMultiplyTest.java | 82 +++++ .../math/BigIntegerMersennePrimeMultiply.java | 322 ++++++++++++++++++ .../java/math/BigIntegerParallelMultiply.java | 61 ++++ 4 files changed, 601 insertions(+), 19 deletions(-) create mode 100644 test/jdk/java/math/BigInteger/BigIntegerParallelMultiplyTest.java create mode 100644 test/micro/org/openjdk/bench/java/math/BigIntegerMersennePrimeMultiply.java create mode 100644 test/micro/org/openjdk/bench/java/math/BigIntegerParallelMultiply.java diff --git a/src/java.base/share/classes/java/math/BigInteger.java b/src/java.base/share/classes/java/math/BigInteger.java index 34f1953d003..81d9a9cf248 100644 --- a/src/java.base/share/classes/java/math/BigInteger.java +++ b/src/java.base/share/classes/java/math/BigInteger.java @@ -36,6 +36,9 @@ import java.io.ObjectStreamField; import java.util.Arrays; import java.util.Objects; import java.util.Random; +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.ForkJoinWorkerThread; +import java.util.concurrent.RecursiveTask; import java.util.concurrent.ThreadLocalRandom; import jdk.internal.math.DoubleConsts; @@ -1581,7 +1584,30 @@ public class BigInteger extends Number implements Comparable { * @return {@code this * val} */ public BigInteger multiply(BigInteger val) { - return multiply(val, false); + return multiply(val, false, false, 0); + } + + /** + * Returns a BigInteger whose value is {@code (this * val)}. + * When both {@code this} and {@code val} are large, typically + * in the thousands of bits, parallel multiply might be used. + * This method returns the exact same mathematical result as + * {@link #multiply}. + * + * @implNote This implementation may offer better algorithmic + * performance when {@code val == this}. + * + * @implNote Compared to {@link #multiply}, an implementation's + * parallel multiplication algorithm would typically use more + * CPU resources to compute the result faster, and may do so + * with a slight increase in memory consumption. + * + * @param val value to be multiplied by this BigInteger. + * @return {@code this * val} + * @see #multiply + */ + public BigInteger parallelMultiply(BigInteger val) { + return multiply(val, false, true, 0); } /** @@ -1590,16 +1616,17 @@ public class BigInteger extends Number implements Comparable { * * @param val value to be multiplied by this BigInteger. * @param isRecursion whether this is a recursive invocation + * @param parallel whether the multiply should be done in parallel * @return {@code this * val} */ - private BigInteger multiply(BigInteger val, boolean isRecursion) { + private BigInteger multiply(BigInteger val, boolean isRecursion, boolean parallel, int depth) { if (val.signum == 0 || signum == 0) return ZERO; int xlen = mag.length; if (val == this && xlen > MULTIPLY_SQUARE_THRESHOLD) { - return square(); + return square(true, parallel, depth); } int ylen = val.mag.length; @@ -1677,7 +1704,7 @@ public class BigInteger extends Number implements Comparable { } } - return multiplyToomCook3(this, val); + return multiplyToomCook3(this, val, parallel, depth); } } } @@ -1844,6 +1871,88 @@ public class BigInteger extends Number implements Comparable { } } + @SuppressWarnings("serial") + private abstract static sealed class RecursiveOp extends RecursiveTask { + /** + * The threshold until when we should continue forking recursive ops + * if parallel is true. This threshold is only relevant for Toom Cook 3 + * multiply and square. + */ + private static final int PARALLEL_FORK_DEPTH_THRESHOLD = + calculateMaximumDepth(ForkJoinPool.getCommonPoolParallelism()); + + private static final int calculateMaximumDepth(int parallelism) { + return 32 - Integer.numberOfLeadingZeros(parallelism); + } + + final boolean parallel; + /** + * The current recursing depth. Since it is a logarithmic algorithm, + * we do not need an int to hold the number. + */ + final byte depth; + + private RecursiveOp(boolean parallel, int depth) { + this.parallel = parallel; + this.depth = (byte) depth; + } + + private static int getParallelForkDepthThreshold() { + if (Thread.currentThread() instanceof ForkJoinWorkerThread fjwt) { + return calculateMaximumDepth(fjwt.getPool().getParallelism()); + } + else { + return PARALLEL_FORK_DEPTH_THRESHOLD; + } + } + + protected RecursiveTask forkOrInvoke() { + if (parallel && depth <= getParallelForkDepthThreshold()) fork(); + else invoke(); + return this; + } + + @SuppressWarnings("serial") + private static final class RecursiveMultiply extends RecursiveOp { + private final BigInteger a; + private final BigInteger b; + + public RecursiveMultiply(BigInteger a, BigInteger b, boolean parallel, int depth) { + super(parallel, depth); + this.a = a; + this.b = b; + } + + @Override + public BigInteger compute() { + return a.multiply(b, true, parallel, depth); + } + } + + @SuppressWarnings("serial") + private static final class RecursiveSquare extends RecursiveOp { + private final BigInteger a; + + public RecursiveSquare(BigInteger a, boolean parallel, int depth) { + super(parallel, depth); + this.a = a; + } + + @Override + public BigInteger compute() { + return a.square(true, parallel, depth); + } + } + + private static RecursiveTask multiply(BigInteger a, BigInteger b, boolean parallel, int depth) { + return new RecursiveMultiply(a, b, parallel, depth).forkOrInvoke(); + } + + private static RecursiveTask square(BigInteger a, boolean parallel, int depth) { + return new RecursiveSquare(a, parallel, depth).forkOrInvoke(); + } + } + /** * Multiplies two BigIntegers using a 3-way Toom-Cook multiplication * algorithm. This is a recursive divide-and-conquer algorithm which is @@ -1872,7 +1981,7 @@ public class BigInteger extends Number implements Comparable { * LNCS #4547. Springer, Madrid, Spain, June 21-22, 2007. * */ - private static BigInteger multiplyToomCook3(BigInteger a, BigInteger b) { + private static BigInteger multiplyToomCook3(BigInteger a, BigInteger b, boolean parallel, int depth) { int alen = a.mag.length; int blen = b.mag.length; @@ -1896,16 +2005,20 @@ public class BigInteger extends Number implements Comparable { BigInteger v0, v1, v2, vm1, vinf, t1, t2, tm1, da1, db1; - v0 = a0.multiply(b0, true); + depth++; + var v0_task = RecursiveOp.multiply(a0, b0, parallel, depth); da1 = a2.add(a0); db1 = b2.add(b0); - vm1 = da1.subtract(a1).multiply(db1.subtract(b1), true); + var vm1_task = RecursiveOp.multiply(da1.subtract(a1), db1.subtract(b1), parallel, depth); da1 = da1.add(a1); db1 = db1.add(b1); - v1 = da1.multiply(db1, true); + var v1_task = RecursiveOp.multiply(da1, db1, parallel, depth); v2 = da1.add(a2).shiftLeft(1).subtract(a0).multiply( - db1.add(b2).shiftLeft(1).subtract(b0), true); - vinf = a2.multiply(b2, true); + db1.add(b2).shiftLeft(1).subtract(b0), true, parallel, depth); + vinf = a2.multiply(b2, true, parallel, depth); + v0 = v0_task.join(); + vm1 = vm1_task.join(); + v1 = v1_task.join(); // The algorithm requires two divisions by 2 and one by 3. // All divisions are known to be exact, that is, they do not produce @@ -2071,7 +2184,7 @@ public class BigInteger extends Number implements Comparable { * @return this2 */ private BigInteger square() { - return square(false); + return square(false, false, 0); } /** @@ -2081,7 +2194,7 @@ public class BigInteger extends Number implements Comparable { * @param isRecursion whether this is a recursive invocation * @return this2 */ - private BigInteger square(boolean isRecursion) { + private BigInteger square(boolean isRecursion, boolean parallel, int depth) { if (signum == 0) { return ZERO; } @@ -2103,7 +2216,7 @@ public class BigInteger extends Number implements Comparable { } } - return squareToomCook3(); + return squareToomCook3(parallel, depth); } } } @@ -2237,7 +2350,7 @@ public class BigInteger extends Number implements Comparable { * that has better asymptotic performance than the algorithm used in * squareToLen or squareKaratsuba. */ - private BigInteger squareToomCook3() { + private BigInteger squareToomCook3(boolean parallel, int depth) { int len = mag.length; // k is the size (in ints) of the lower-order slices. @@ -2254,13 +2367,17 @@ public class BigInteger extends Number implements Comparable { a0 = getToomSlice(k, r, 2, len); BigInteger v0, v1, v2, vm1, vinf, t1, t2, tm1, da1; - v0 = a0.square(true); + depth++; + var v0_fork = RecursiveOp.square(a0, parallel, depth); da1 = a2.add(a0); - vm1 = da1.subtract(a1).square(true); + var vm1_fork = RecursiveOp.square(da1.subtract(a1), parallel, depth); da1 = da1.add(a1); - v1 = da1.square(true); - vinf = a2.square(true); - v2 = da1.add(a2).shiftLeft(1).subtract(a0).square(true); + var v1_fork = RecursiveOp.square(da1, parallel, depth); + vinf = a2.square(true, parallel, depth); + v2 = da1.add(a2).shiftLeft(1).subtract(a0).square(true, parallel, depth); + v0 = v0_fork.join(); + vm1 = vm1_fork.join(); + v1 = v1_fork.join(); // The algorithm requires two divisions by 2 and one by 3. // All divisions are known to be exact, that is, they do not produce diff --git a/test/jdk/java/math/BigInteger/BigIntegerParallelMultiplyTest.java b/test/jdk/java/math/BigInteger/BigIntegerParallelMultiplyTest.java new file mode 100644 index 00000000000..1396ae06d96 --- /dev/null +++ b/test/jdk/java/math/BigInteger/BigIntegerParallelMultiplyTest.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @run main BigIntegerParallelMultiplyTest + * @summary tests parallelMultiply() method in BigInteger + * @author Heinz Kabutz heinz@javaspecialists.eu + */ + +import java.math.BigInteger; +import java.util.function.BinaryOperator; + +/** + * This is a simple test class created to ensure that the results + * of multiply() are the same as multiplyParallel(). We calculate + * the Fibonacci numbers using Dijkstra's sum of squares to get + * very large numbers (hundreds of thousands of bits). + * + * @author Heinz Kabutz, heinz@javaspecialists.eu + */ +public class BigIntegerParallelMultiplyTest { + public static BigInteger fibonacci(int n, BinaryOperator multiplyOperator) { + if (n == 0) return BigInteger.ZERO; + if (n == 1) return BigInteger.ONE; + + int half = (n + 1) / 2; + BigInteger f0 = fibonacci(half - 1, multiplyOperator); + BigInteger f1 = fibonacci(half, multiplyOperator); + if (n % 2 == 1) { + BigInteger b0 = multiplyOperator.apply(f0, f0); + BigInteger b1 = multiplyOperator.apply(f1, f1); + return b0.add(b1); + } else { + BigInteger b0 = f0.shiftLeft(1).add(f1); + return multiplyOperator.apply(b0, f1); + } + } + + public static void main(String[] args) throws Exception { + compare(1000, 324); + compare(10_000, 3473); + compare(100_000, 34883); + compare(1_000_000, 347084); + } + + private static void compare(int n, int expectedBitCount) { + BigInteger multiplyResult = fibonacci(n, BigInteger::multiply); + BigInteger parallelMultiplyResult = fibonacci(n, BigInteger::parallelMultiply); + checkBitCount(n, expectedBitCount, multiplyResult); + checkBitCount(n, expectedBitCount, parallelMultiplyResult); + if (!multiplyResult.equals(parallelMultiplyResult)) + throw new AssertionError("multiply() and parallelMultiply() give different results"); + } + + private static void checkBitCount(int n, int expectedBitCount, BigInteger number) { + if (number.bitCount() != expectedBitCount) + throw new AssertionError( + "bitCount of fibonacci(" + n + ") was expected to be " + expectedBitCount + + " but was " + number.bitCount()); + } +} diff --git a/test/micro/org/openjdk/bench/java/math/BigIntegerMersennePrimeMultiply.java b/test/micro/org/openjdk/bench/java/math/BigIntegerMersennePrimeMultiply.java new file mode 100644 index 00000000000..7ac4cf54dc2 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/math/BigIntegerMersennePrimeMultiply.java @@ -0,0 +1,322 @@ +package org.openjdk.bench.java.math; + +import javax.management.MBeanServer; +import javax.management.MalformedObjectNameException; +import javax.management.ObjectName; +import java.lang.management.ManagementFactory; +import java.lang.management.ThreadMXBean; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.math.BigInteger; +import java.util.Arrays; +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Locale; +import java.util.LongSummaryStatistics; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.ForkJoinWorkerThread; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicLong; +import java.util.function.BinaryOperator; +import java.util.function.LongUnaryOperator; +import java.util.stream.Collectors; + +import static java.util.concurrent.ForkJoinPool.defaultForkJoinWorkerThreadFactory; + +/** + * Benchmark for checking performance difference between sequential and parallel + * multiply of very large Mersenne primes using BigInteger. We want to measure + * real time, user time, system time and the amount of memory allocated. To + * calculate this, we create our own thread factory for the common ForkJoinPool + * and then use that to measure user time, cpu time and bytes allocated. + *

    + * We use reflection to discover all methods that match "*ultiply", and use them + * to multiply two very large Mersenne primes together. + *

    + *

    Results on a 1-6-2 machine running Ubuntu linux

    + *

    + * Memory allocation increased from 83.9GB to 84GB, for both the sequential and + * parallel versions. This is an increase of just 0.1%. On this machine, the + * parallel version was 3.8x faster in latency (real time), but it used 2.7x + * more CPU resources. + *

    + * Testing multiplying Mersenne primes of 2^57885161-1 and 2^82589933-1 + *

    + *

    + * openjdk version "18-internal" 2022-03-15
    + * BigInteger.parallelMultiply()
    + * real  0m6.288s
    + * user  1m3.010s
    + * sys   0m0.027s
    + * mem   84.0GB
    + * BigInteger.multiply()
    + * real  0m23.682s
    + * user  0m23.530s
    + * sys   0m0.004s
    + * mem   84.0GB
    + *
    + * openjdk version "1.8.0_302"
    + * BigInteger.multiply()
    + * real  0m25.657s
    + * user  0m25.390s
    + * sys   0m0.001s
    + * mem   83.9GB
    + *
    + * openjdk version "9.0.7.1"
    + * BigInteger.multiply()
    + * real  0m24.907s
    + * user  0m24.700s
    + * sys   0m0.001s
    + * mem   83.9GB
    + *
    + * openjdk version "10.0.2" 2018-07-17
    + * BigInteger.multiply()
    + * real  0m24.632s
    + * user  0m24.380s
    + * sys   0m0.004s
    + * mem   83.9GB
    + *
    + * openjdk version "11.0.12" 2021-07-20 LTS
    + * BigInteger.multiply()
    + * real  0m22.114s
    + * user  0m21.930s
    + * sys   0m0.001s
    + * mem   83.9GB
    + *
    + * openjdk version "12.0.2" 2019-07-16
    + * BigInteger.multiply()
    + * real  0m23.015s
    + * user  0m22.830s
    + * sys   0m0.000s
    + * mem   83.9GB
    + *
    + * openjdk version "13.0.9" 2021-10-19
    + * BigInteger.multiply()
    + * real  0m23.548s
    + * user  0m23.350s
    + * sys   0m0.005s
    + * mem   83.9GB
    + *
    + * openjdk version "14.0.2" 2020-07-14
    + * BigInteger.multiply()
    + * real  0m22.918s
    + * user  0m22.530s
    + * sys   0m0.131s
    + * mem   83.9GB
    + *
    + * openjdk version "15.0.5" 2021-10-19
    + * BigInteger.multiply()
    + * real  0m22.038s
    + * user  0m21.750s
    + * sys   0m0.003s
    + * mem   83.9GB
    + *
    + * openjdk version "16.0.2" 2021-07-20
    + * BigInteger.multiply()
    + * real  0m23.049s
    + * user  0m22.760s
    + * sys   0m0.006s
    + * mem   83.9GB
    + *
    + * openjdk version "17" 2021-09-14
    + * BigInteger.multiply()
    + * real  0m22.580s
    + * user  0m22.310s
    + * sys   0m0.001s
    + * mem   83.9GB
    + *
    + * + * @author Heinz Kabutz, heinz@javaspecialists.eu + */ +public class BigIntegerMersennePrimeMultiply implements ForkJoinPool.ForkJoinWorkerThreadFactory { + // Large Mersenne prime discovered by Curtis Cooper in 2013 + private static final int EXPONENT_1 = 57885161; + private static final BigInteger MERSENNE_1 = + BigInteger.ONE.shiftLeft(EXPONENT_1).subtract(BigInteger.ONE); + // Largest Mersenne prime number discovered by Patrick Laroche in 2018 + private static final int EXPONENT_2 = 82589933; + private static final BigInteger MERSENNE_2 = + BigInteger.ONE.shiftLeft(EXPONENT_2).subtract(BigInteger.ONE); + private static boolean DEBUG = false; + + public static void main(String... args) { + System.setProperty("java.util.concurrent.ForkJoinPool.common.threadFactory", + BigIntegerMersennePrimeMultiply.class.getName()); + System.out.println("Testing multiplying Mersenne primes of " + + "2^" + EXPONENT_1 + "-1 and 2^" + EXPONENT_2 + "-1"); + addCounters(Thread.currentThread()); + System.out.println("Using the following multiply methods:"); + List methods = Arrays.stream(BigInteger.class.getMethods()) + .filter(method -> method.getName().endsWith("ultiply") && + method.getParameterCount() == 1 && + method.getParameterTypes()[0] == BigInteger.class) + .peek(method -> System.out.println(" " + method)) + .collect(Collectors.toList()); + + for (int i = 0; i < 3; i++) { + System.out.println(); + methods.forEach(BigIntegerMersennePrimeMultiply::test); + } + } + + private static void test(Method method) { + BinaryOperator multiplyOperator = (a, b) -> { + try { + return (BigInteger) method.invoke(a, b); + } catch (IllegalAccessException e) { + throw new AssertionError(e); + } catch (InvocationTargetException e) { + throw new AssertionError(e.getCause()); + } + }; + test(method.getName(), multiplyOperator); + } + + private static void test(String description, + BinaryOperator multiplyOperator) { + System.out.println("BigInteger." + description + "()"); + resetAllCounters(); + long elapsedTimeInNanos = System.nanoTime(); + try { + BigInteger result1 = multiplyOperator.apply(MERSENNE_1, MERSENNE_2); + BigInteger result2 = multiplyOperator.apply(MERSENNE_2, MERSENNE_1); + if (result1.bitLength() != 140475094) + throw new AssertionError("Expected bitLength: 140475094, " + + "but was " + result1.bitLength()); + if (result2.bitLength() != 140475094) + throw new AssertionError("Expected bitLength: 140475094, " + + "but was " + result1.bitLength()); + } finally { + elapsedTimeInNanos = System.nanoTime() - elapsedTimeInNanos; + } + + LongSummaryStatistics userTimeStatistics = getStatistics(userTime); + LongSummaryStatistics cpuTimeStatistics = getStatistics(cpuTime); + LongSummaryStatistics memoryAllocationStatistics = getStatistics(bytes); + System.out.println("real " + formatTime(elapsedTimeInNanos)); + System.out.println("user " + formatTime(userTimeStatistics.getSum())); + System.out.println("sys " + + formatTime(cpuTimeStatistics.getSum() - userTimeStatistics.getSum())); + System.out.println("mem " + formatMemory(memoryAllocationStatistics.getSum(), 1)); + } + + private static LongSummaryStatistics getStatistics(Map timeMap) { + return timeMap.entrySet() + .stream() + .peek(entry -> { + long timeInMs = (counterExtractorMap.get(timeMap) + .applyAsLong(entry.getKey().getId()) + - entry.getValue().get()); + entry.getValue().set(timeInMs); + }) + .peek(BigIntegerMersennePrimeMultiply::printTime) + .map(Map.Entry::getValue) + .mapToLong(AtomicLong::get) + .summaryStatistics(); + } + + private static void printTime(Map.Entry threadCounter) { + if (DEBUG) + System.out.printf("%s %d%n", threadCounter.getKey(), threadCounter.getValue() + .get()); + } + + private static void addCounters(Thread thread) { + counterExtractorMap.forEach((map, timeExtractor) -> add(map, thread, timeExtractor)); + } + + private static void add(Map time, Thread thread, + LongUnaryOperator timeExtractor) { + time.put(thread, new AtomicLong(timeExtractor.applyAsLong(thread.getId()))); + } + + private static void resetAllCounters() { + counterExtractorMap.forEach(BigIntegerMersennePrimeMultiply::resetTimes); + } + + private static void resetTimes(Map timeMap, LongUnaryOperator timeMethod) { + timeMap.forEach((thread, time) -> + time.set(timeMethod.applyAsLong(thread.getId()))); + } + + private static final Map userTime = + new ConcurrentHashMap<>(); + private static final Map cpuTime = + new ConcurrentHashMap<>(); + private static final Map bytes = + new ConcurrentHashMap<>(); + private static final ThreadMXBean tmb = ManagementFactory.getThreadMXBean(); + + private static final Map, LongUnaryOperator> counterExtractorMap = + new IdentityHashMap<>(); + + static { + counterExtractorMap.put(userTime, tmb::getThreadUserTime); + counterExtractorMap.put(cpuTime, tmb::getThreadCpuTime); + counterExtractorMap.put(bytes, BigIntegerMersennePrimeMultiply::threadAllocatedBytes); + } + + public final ForkJoinWorkerThread newThread(ForkJoinPool pool) { + ForkJoinWorkerThread thread = defaultForkJoinWorkerThreadFactory.newThread(pool); + addCounters(thread); + return thread; + } + + private static final String[] SIGNATURE = new String[]{long.class.getName()}; + private static final MBeanServer mBeanServer; + private static final ObjectName name; + + static { + try { + name = new ObjectName(ManagementFactory.THREAD_MXBEAN_NAME); + mBeanServer = ManagementFactory.getPlatformMBeanServer(); + } catch (MalformedObjectNameException e) { + throw new ExceptionInInitializerError(e); + } + } + + public static long threadAllocatedBytes(long threadId) { + try { + return (long) mBeanServer.invoke( + name, + "getThreadAllocatedBytes", + new Object[]{threadId}, + SIGNATURE + ); + } catch (Exception e) { + throw new IllegalArgumentException(e); + } + } + + public static String formatMemory(double bytes, int decimals) { + double val; + String unitStr; + if (bytes < 1024) { + val = bytes; + unitStr = "B"; + } else if (bytes < 1024 * 1024) { + val = bytes / 1024; + unitStr = "KB"; + } else if (bytes < 1024 * 1024 * 1024) { + val = bytes / (1024 * 1024); + unitStr = "MB"; + } else if (bytes < 1024 * 1024 * 1024 * 1024L) { + val = bytes / (1024 * 1024 * 1024L); + unitStr = "GB"; + } else { + val = bytes / (1024 * 1024 * 1024 * 1024L); + unitStr = "TB"; + } + return String.format(Locale.US, "%." + decimals + "f%s", val, unitStr); + } + + public static String formatTime(long nanos) { + if (nanos < 0) nanos = 0; + long timeInMs = TimeUnit.NANOSECONDS.toMillis(nanos); + long minutes = timeInMs / 60_000; + double remainingMs = (timeInMs % 60_000) / 1000.0; + return String.format(Locale.US, "%dm%.3fs", minutes, remainingMs); + } +} \ No newline at end of file diff --git a/test/micro/org/openjdk/bench/java/math/BigIntegerParallelMultiply.java b/test/micro/org/openjdk/bench/java/math/BigIntegerParallelMultiply.java new file mode 100644 index 00000000000..92a1c5a8237 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/math/BigIntegerParallelMultiply.java @@ -0,0 +1,61 @@ +package org.openjdk.bench.java.math; + +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.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +import java.math.BigInteger; +import java.util.concurrent.TimeUnit; +import java.util.function.BinaryOperator; + +/** + * Benchmark for checking performance difference between + * sequential and parallel multiply methods in BigInteger, + * using a large Fibonacci calculation of up to n = 100 million. + * + * @author Heinz Kabutz, heinz@javaspecialists.eu + */ +@BenchmarkMode(Mode.SingleShotTime) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@Fork(value = 2) +@Warmup(iterations = 2) +@Measurement(iterations = 2) // only 2 iterations because each one takes very long +@State(Scope.Thread) +public class BigIntegerParallelMultiply { + private static BigInteger fibonacci(int n, BinaryOperator multiplyOperator) { + if (n == 0) return BigInteger.ZERO; + if (n == 1) return BigInteger.ONE; + + int half = (n + 1) / 2; + BigInteger f0 = fibonacci(half - 1, multiplyOperator); + BigInteger f1 = fibonacci(half, multiplyOperator); + if (n % 2 == 1) { + BigInteger b0 = multiplyOperator.apply(f0, f0); + BigInteger b1 = multiplyOperator.apply(f1, f1); + return b0.add(b1); + } else { + BigInteger b0 = f0.shiftLeft(1).add(f1); + return multiplyOperator.apply(b0, f1); + } + } + + @Param({"1000000", "10000000", "100000000"}) + private int n; + + @Benchmark + public void multiply() { + fibonacci(n, BigInteger::multiply); + } + + @Benchmark + public void parallelMultiply() { + fibonacci(n, BigInteger::parallelMultiply); + } +} \ No newline at end of file -- GitLab From 4032fe76dccb6da85927361aee7ceedcdb758e89 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Fri, 11 Feb 2022 21:52:16 +0000 Subject: [PATCH 476/564] 8281238: TYPE_USE annotations not printed in correct position in toString output Reviewed-by: vromero --- .../share/classes/com/sun/tools/javac/code/Type.java | 12 ++++++++++-- test/langtools/tools/javac/patterns/Annotations.java | 10 +++++----- .../tools/javac/tree/ArrayTypeToString.java | 6 +++--- .../langtools/tools/javac/tree/ArrayTypeToString.out | 2 +- 4 files changed, 19 insertions(+), 11 deletions(-) diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java index 3cf34052300..86851fa8cb6 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java @@ -1038,8 +1038,16 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons appendAnnotationsString(buf); buf.append(className(tsym, false)); } else { - appendAnnotationsString(buf); - buf.append(className(tsym, true)); + if (isAnnotated()) { + if (!tsym.packge().isUnnamed()) { + buf.append(tsym.packge()); + buf.append("."); + } + appendAnnotationsString(buf); + buf.append(tsym.name); + } else { + buf.append(className(tsym, true)); + } } if (getTypeArguments().nonEmpty()) { diff --git a/test/langtools/tools/javac/patterns/Annotations.java b/test/langtools/tools/javac/patterns/Annotations.java index 8c9062fa427..324f07945dd 100644 --- a/test/langtools/tools/javac/patterns/Annotations.java +++ b/test/langtools/tools/javac/patterns/Annotations.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, 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 8256266 + * @bug 8256266 8281238 * @summary Verify annotations work correctly on binding variables * @library /tools/javac/lib * @modules java.compiler @@ -114,11 +114,11 @@ public class Annotations extends JavacTestingAbstractProcessor { } case "dta" -> { expectedDeclAnnos = "@Annotations.DTA"; - expectedType = "@Annotations.DTA java.lang.String"; + expectedType = "java.lang.@Annotations.DTA String"; } case "ta" -> { expectedDeclAnnos = ""; - expectedType = "@Annotations.TA java.lang.String"; + expectedType = "java.lang.@Annotations.TA String"; } default -> { throw new AssertionError("Unexpected variable: " + var); @@ -133,7 +133,7 @@ public class Annotations extends JavacTestingAbstractProcessor { String type = varType.toString(); if (!expectedType.equals(type)) { throw new AssertionError("Unexpected type: " + type + - " for: " + var.getName()); + " for: " + var.getName() + " expected " + expectedType); } return super.visitInstanceOf(node, p); } diff --git a/test/langtools/tools/javac/tree/ArrayTypeToString.java b/test/langtools/tools/javac/tree/ArrayTypeToString.java index 9d2275ab26f..eac8f345bef 100644 --- a/test/langtools/tools/javac/tree/ArrayTypeToString.java +++ b/test/langtools/tools/javac/tree/ArrayTypeToString.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, 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 8068737 + * @bug 8068737 8281238 * @summary Tests ArrayType.toString with type annotations present * @modules jdk.compiler/com.sun.tools.javac.code * @library /tools/javac/lib @@ -66,7 +66,7 @@ public class ArrayTypeToString extends JavacTestingAbstractProcessor { // Normalize output by removing whitespace s = s.replaceAll("\\s", ""); - // Expected: "@Foo(0)java.lang.String@Foo(3)[]@Foo(2)[]@Foo(1)[]" + // Expected: "java.lang.@Foo(0)String@Foo(1)[]@Foo(2)[]@Foo(3)[]" processingEnv.getMessager().printNote(s); } } diff --git a/test/langtools/tools/javac/tree/ArrayTypeToString.out b/test/langtools/tools/javac/tree/ArrayTypeToString.out index 375a6f28949..ca3db541c2d 100644 --- a/test/langtools/tools/javac/tree/ArrayTypeToString.out +++ b/test/langtools/tools/javac/tree/ArrayTypeToString.out @@ -1 +1 @@ -- compiler.note.proc.messager: @Foo(0)java.lang.String@Foo(1)[]@Foo(2)[]@Foo(3)[] +- compiler.note.proc.messager: java.lang.@Foo(0)String@Foo(1)[]@Foo(2)[]@Foo(3)[] -- GitLab From c3179a8760019b5954e344bf0d2775e1e1968f32 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Fri, 11 Feb 2022 23:24:08 +0000 Subject: [PATCH 477/564] 8281462: Annotation toString output for enum not reusable for source input Reviewed-by: mchung --- .../AnnotationInvocationHandler.java | 30 ++++++++++------ .../annotation/AnnotationToStringTest.java | 21 +++++++++--- .../EnumTypeMismatchTest.java | 4 +-- .../TestConstructorParameterAnnotations.java | 34 +++++++++---------- .../GetAnnotatedNestedSuperclass.java | 12 +++---- ...stConstructorParameterTypeAnnotations.java | 18 +++++----- .../typeAnnotations/TestObjectMethods.java | 4 +-- .../reflect/records/RecordReflectionTest.java | 6 ++-- 8 files changed, 74 insertions(+), 55 deletions(-) diff --git a/src/java.base/share/classes/sun/reflect/annotation/AnnotationInvocationHandler.java b/src/java.base/share/classes/sun/reflect/annotation/AnnotationInvocationHandler.java index c4cc4ccdec7..74eec629b3e 100644 --- a/src/java.base/share/classes/sun/reflect/annotation/AnnotationInvocationHandler.java +++ b/src/java.base/share/classes/sun/reflect/annotation/AnnotationInvocationHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -145,7 +145,9 @@ class AnnotationInvocationHandler implements InvocationHandler, Serializable { private String toStringImpl() { StringBuilder result = new StringBuilder(128); result.append('@'); - result.append(type.getName()); + // Guard against null canonical name; shouldn't happen + result.append(Objects.toString(type.getCanonicalName(), + "")); result.append('('); boolean firstMember = true; Set> entries = memberValues.entrySet(); @@ -189,6 +191,10 @@ class AnnotationInvocationHandler implements InvocationHandler, Serializable { return toSourceString((long) value); else if (type == Byte.class) return toSourceString((byte) value); + else if (value instanceof Enum v) + // Predicate above covers enum constants, including + // those with specialized class bodies. + return toSourceString(v); else return value.toString(); } else { @@ -219,6 +225,10 @@ class AnnotationInvocationHandler implements InvocationHandler, Serializable { stringStream = Arrays.stream((String[])value). map(AnnotationInvocationHandler::toSourceString); + else if (type.getComponentType().isEnum()) + stringStream = + Arrays.stream((Enum[])value). + map(AnnotationInvocationHandler::toSourceString); else stringStream = Arrays.stream((Object[])value).map(Objects::toString); @@ -231,15 +241,9 @@ class AnnotationInvocationHandler implements InvocationHandler, Serializable { * string representation of an annotation. */ private static String toSourceString(Class clazz) { - Class finalComponent = clazz; - StringBuilder arrayBrackets = new StringBuilder(); - - while(finalComponent.isArray()) { - finalComponent = finalComponent.getComponentType(); - arrayBrackets.append("[]"); - } - - return finalComponent.getName() + arrayBrackets.toString() + ".class"; + // Guard against null canonical name; shouldn't happen + return Objects.toString(clazz.getCanonicalName(), + "") + ".class"; } private static String toSourceString(float f) { @@ -307,6 +311,10 @@ class AnnotationInvocationHandler implements InvocationHandler, Serializable { return String.valueOf(ell) + "L"; } + private static String toSourceString(Enum enumConstant) { + return enumConstant.name(); + } + /** * Return a string suitable for use in the string representation * of an annotation. diff --git a/test/jdk/java/lang/annotation/AnnotationToStringTest.java b/test/jdk/java/lang/annotation/AnnotationToStringTest.java index e9fcf57014e..71551193a3f 100644 --- a/test/jdk/java/lang/annotation/AnnotationToStringTest.java +++ b/test/jdk/java/lang/annotation/AnnotationToStringTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, 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,7 +31,8 @@ // test/langtools/tools/javac/processing/model/element/AnnotationToStringTest.java import java.lang.annotation.*; -import java.lang.reflect.*; +import java.lang.reflect.Field; +import javax.lang.model.element.Modifier; import java.util.*; /** @@ -160,6 +161,11 @@ public class AnnotationToStringTest { } static class ArrayAnnotationHost { + @ExpectedString( + "@EnumValue(NON_SEALED)") // toString and name differ + @EnumValue(Modifier.NON_SEALED) + public int f00; + @ExpectedString( "@BooleanArray({true, false, true})") @BooleanArray({true, false, true}) @@ -213,8 +219,8 @@ public class AnnotationToStringTest { public Class[] f9; @ExpectedString( - "@EnumArray({SOURCE})") - @EnumArray({RetentionPolicy.SOURCE}) + "@EnumArray({SEALED, NON_SEALED, PUBLIC})") + @EnumArray({Modifier.SEALED, Modifier.NON_SEALED, Modifier.PUBLIC}) public RetentionPolicy[] f10; } } @@ -223,6 +229,11 @@ public class AnnotationToStringTest { class Obj {} +@Retention(RetentionPolicy.RUNTIME) +@interface EnumValue { + Modifier value(); +} + @Retention(RetentionPolicy.RUNTIME) @interface ExpectedString { String value(); @@ -285,7 +296,7 @@ class Obj {} @Retention(RetentionPolicy.RUNTIME) @interface EnumArray { - RetentionPolicy[] value(); + Modifier[] value(); } @Retention(RetentionPolicy.RUNTIME) diff --git a/test/jdk/java/lang/annotation/AnnotationTypeMismatchException/EnumTypeMismatchTest.java b/test/jdk/java/lang/annotation/AnnotationTypeMismatchException/EnumTypeMismatchTest.java index dd787e727b4..5000aa0ee65 100644 --- a/test/jdk/java/lang/annotation/AnnotationTypeMismatchException/EnumTypeMismatchTest.java +++ b/test/jdk/java/lang/annotation/AnnotationTypeMismatchException/EnumTypeMismatchTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, 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 @@ -61,7 +61,7 @@ public class EnumTypeMismatchTest { } catch (AnnotationTypeMismatchException e) { if (!e.element().getName().equals("value")) { throw new IllegalStateException("Unexpected element: " + e.element()); - } else if (!e.foundType().equals("@" + AnAnnotation.class.getName() + "(" + AnEnum.VALUE.name() + ")")) { + } else if (!e.foundType().equals("@" + AnAnnotation.class.getCanonicalName() + "(" + AnEnum.VALUE.name() + ")")) { throw new IllegalStateException("Unexpected type: " + e.foundType()); } } diff --git a/test/jdk/java/lang/annotation/TestConstructorParameterAnnotations.java b/test/jdk/java/lang/annotation/TestConstructorParameterAnnotations.java index f36474ef3b7..3e39cdb6e8d 100644 --- a/test/jdk/java/lang/annotation/TestConstructorParameterAnnotations.java +++ b/test/jdk/java/lang/annotation/TestConstructorParameterAnnotations.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022, 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 @@ -129,21 +129,21 @@ public class TestConstructorParameterAnnotations { @ExpectedGetParameterAnnotations( "[[], " + - "[@TestConstructorParameterAnnotations$MarkerAnnotation(1)]]") + "[@TestConstructorParameterAnnotations.MarkerAnnotation(1)]]") @ExpectedParameterAnnotations({ "null", - "@TestConstructorParameterAnnotations$MarkerAnnotation(1)"}) + "@TestConstructorParameterAnnotations.MarkerAnnotation(1)"}) public class NestedClass1 { public NestedClass1(@MarkerAnnotation(1) int parameter) {} } @ExpectedGetParameterAnnotations( "[[], " + - "[@TestConstructorParameterAnnotations$MarkerAnnotation(2)], " + + "[@TestConstructorParameterAnnotations.MarkerAnnotation(2)], " + "[]]") @ExpectedParameterAnnotations({ "null", - "@TestConstructorParameterAnnotations$MarkerAnnotation(2)", + "@TestConstructorParameterAnnotations.MarkerAnnotation(2)", "null"}) public class NestedClass2 { public NestedClass2(@MarkerAnnotation(2) int parameter1, @@ -152,11 +152,11 @@ public class TestConstructorParameterAnnotations { @ExpectedGetParameterAnnotations( "[[], " + - "[@TestConstructorParameterAnnotations$MarkerAnnotation(3)], " + + "[@TestConstructorParameterAnnotations.MarkerAnnotation(3)], " + "[]]") @ExpectedParameterAnnotations({ "null", - "@TestConstructorParameterAnnotations$MarkerAnnotation(3)", + "@TestConstructorParameterAnnotations.MarkerAnnotation(3)", "null"}) public class NestedClass3 { public

    NestedClass3(@MarkerAnnotation(3) P parameter1, @@ -165,11 +165,11 @@ public class TestConstructorParameterAnnotations { @ExpectedGetParameterAnnotations( "[[], " + - "[@TestConstructorParameterAnnotations$MarkerAnnotation(4)], " + + "[@TestConstructorParameterAnnotations.MarkerAnnotation(4)], " + "[]]") @ExpectedParameterAnnotations({ "null", - "@TestConstructorParameterAnnotations$MarkerAnnotation(4)", + "@TestConstructorParameterAnnotations.MarkerAnnotation(4)", "null"}) public class NestedClass4 { public NestedClass4(@MarkerAnnotation(4) P parameter1, @@ -183,18 +183,18 @@ public class TestConstructorParameterAnnotations { } @ExpectedGetParameterAnnotations( - "[[@TestConstructorParameterAnnotations$MarkerAnnotation(1)]]") + "[[@TestConstructorParameterAnnotations.MarkerAnnotation(1)]]") @ExpectedParameterAnnotations({ - "@TestConstructorParameterAnnotations$MarkerAnnotation(1)"}) + "@TestConstructorParameterAnnotations.MarkerAnnotation(1)"}) public static class StaticNestedClass1 { public StaticNestedClass1(@MarkerAnnotation(1) int parameter) {} } @ExpectedGetParameterAnnotations( - "[[@TestConstructorParameterAnnotations$MarkerAnnotation(2)], " + + "[[@TestConstructorParameterAnnotations.MarkerAnnotation(2)], " + "[]]") @ExpectedParameterAnnotations({ - "@TestConstructorParameterAnnotations$MarkerAnnotation(2)", + "@TestConstructorParameterAnnotations.MarkerAnnotation(2)", "null"}) public static class StaticNestedClass2 { public StaticNestedClass2(@MarkerAnnotation(2) int parameter1, @@ -202,10 +202,10 @@ public class TestConstructorParameterAnnotations { } @ExpectedGetParameterAnnotations( - "[[@TestConstructorParameterAnnotations$MarkerAnnotation(3)], " + + "[[@TestConstructorParameterAnnotations.MarkerAnnotation(3)], " + "[]]") @ExpectedParameterAnnotations({ - "@TestConstructorParameterAnnotations$MarkerAnnotation(3)", + "@TestConstructorParameterAnnotations.MarkerAnnotation(3)", "null"}) public static class StaticNestedClass3 { public

    StaticNestedClass3(@MarkerAnnotation(3) P parameter1, @@ -213,10 +213,10 @@ public class TestConstructorParameterAnnotations { } @ExpectedGetParameterAnnotations( - "[[@TestConstructorParameterAnnotations$MarkerAnnotation(4)], " + + "[[@TestConstructorParameterAnnotations.MarkerAnnotation(4)], " + "[]]") @ExpectedParameterAnnotations({ - "@TestConstructorParameterAnnotations$MarkerAnnotation(4)", + "@TestConstructorParameterAnnotations.MarkerAnnotation(4)", "null"}) public static class StaticNestedClass4 { public StaticNestedClass4(@MarkerAnnotation(4) P parameter1, diff --git a/test/jdk/java/lang/annotation/typeAnnotations/GetAnnotatedNestedSuperclass.java b/test/jdk/java/lang/annotation/typeAnnotations/GetAnnotatedNestedSuperclass.java index a667a2e2c23..8603b7f9f19 100644 --- a/test/jdk/java/lang/annotation/typeAnnotations/GetAnnotatedNestedSuperclass.java +++ b/test/jdk/java/lang/annotation/typeAnnotations/GetAnnotatedNestedSuperclass.java @@ -64,31 +64,31 @@ public class GetAnnotatedNestedSuperclass { public static void main(String[] args) throws Exception { AnnotatedType x = Y.class.getAnnotatedSuperclass(); - assertEquals(Arrays.toString(x.getAnnotations()), "[@GetAnnotatedNestedSuperclass$A()]"); + assertEquals(Arrays.toString(x.getAnnotations()), "[@GetAnnotatedNestedSuperclass.A()]"); AnnotatedParameterizedType xpt = (AnnotatedParameterizedType) x; { AnnotatedType arg = xpt.getAnnotatedActualTypeArguments()[0]; assertEquals( - Arrays.toString(arg.getAnnotations()), "[@GetAnnotatedNestedSuperclass$B()]"); + Arrays.toString(arg.getAnnotations()), "[@GetAnnotatedNestedSuperclass.B()]"); } { AnnotatedType arg = xpt.getAnnotatedActualTypeArguments()[1]; assertEquals( - Arrays.toString(arg.getAnnotations()), "[@GetAnnotatedNestedSuperclass$C()]"); + Arrays.toString(arg.getAnnotations()), "[@GetAnnotatedNestedSuperclass.C()]"); } { AnnotatedType arg = xpt.getAnnotatedActualTypeArguments()[2]; assertEquals( - Arrays.toString(arg.getAnnotations()), "[@GetAnnotatedNestedSuperclass$D()]"); + Arrays.toString(arg.getAnnotations()), "[@GetAnnotatedNestedSuperclass.D()]"); AnnotatedType nestedArg = ((AnnotatedParameterizedType) arg).getAnnotatedActualTypeArguments()[0]; assertEquals( Arrays.toString(nestedArg.getAnnotations()), - "[@GetAnnotatedNestedSuperclass$E()]"); + "[@GetAnnotatedNestedSuperclass.E()]"); } } - private static void assertEquals(Object expected, Object actual) { + private static void assertEquals(Object actual, Object expected) { if (!Objects.equals(expected, actual)) { throw new AssertionError("expected: " + expected + "; actual=" + actual); } diff --git a/test/jdk/java/lang/annotation/typeAnnotations/TestConstructorParameterTypeAnnotations.java b/test/jdk/java/lang/annotation/typeAnnotations/TestConstructorParameterTypeAnnotations.java index 21934b3247d..a90aa36ba09 100644 --- a/test/jdk/java/lang/annotation/typeAnnotations/TestConstructorParameterTypeAnnotations.java +++ b/test/jdk/java/lang/annotation/typeAnnotations/TestConstructorParameterTypeAnnotations.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022, 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 @@ -128,7 +128,7 @@ public class TestConstructorParameterTypeAnnotations { @ExpectedGetParameterAnnotations("[[], []]") @ExpectedParameterTypeAnnotations({ "null", - "@TestConstructorParameterTypeAnnotations$MarkerTypeAnnotation(1)"}) + "@TestConstructorParameterTypeAnnotations.MarkerTypeAnnotation(1)"}) public class NestedClass1 { public NestedClass1(@MarkerTypeAnnotation(1) int parameter) {} } @@ -136,7 +136,7 @@ public class TestConstructorParameterTypeAnnotations { @ExpectedGetParameterAnnotations("[[], [], []]") @ExpectedParameterTypeAnnotations({ "null", - "@TestConstructorParameterTypeAnnotations$MarkerTypeAnnotation(2)", + "@TestConstructorParameterTypeAnnotations.MarkerTypeAnnotation(2)", "null"}) public class NestedClass2 { public NestedClass2(@MarkerTypeAnnotation(2) int parameter1, @@ -146,7 +146,7 @@ public class TestConstructorParameterTypeAnnotations { @ExpectedGetParameterAnnotations("[[], [], []]") @ExpectedParameterTypeAnnotations({ "null", - "@TestConstructorParameterTypeAnnotations$MarkerTypeAnnotation(3)", + "@TestConstructorParameterTypeAnnotations.MarkerTypeAnnotation(3)", "null"}) public class NestedClass3 { public

    NestedClass3(@MarkerTypeAnnotation(3) P parameter1, @@ -156,7 +156,7 @@ public class TestConstructorParameterTypeAnnotations { @ExpectedGetParameterAnnotations("[[], [], []]") @ExpectedParameterTypeAnnotations({ "null", - "@TestConstructorParameterTypeAnnotations$MarkerTypeAnnotation(4)", + "@TestConstructorParameterTypeAnnotations.MarkerTypeAnnotation(4)", "null"}) public class NestedClass4 { public NestedClass4(@MarkerTypeAnnotation(4) P parameter1, @@ -171,14 +171,14 @@ public class TestConstructorParameterTypeAnnotations { @ExpectedGetParameterAnnotations("[[]]") @ExpectedParameterTypeAnnotations({ - "@TestConstructorParameterTypeAnnotations$MarkerTypeAnnotation(1)"}) + "@TestConstructorParameterTypeAnnotations.MarkerTypeAnnotation(1)"}) public static class StaticNestedClass1 { public StaticNestedClass1(@MarkerTypeAnnotation(1) int parameter) {} } @ExpectedGetParameterAnnotations("[[], []]") @ExpectedParameterTypeAnnotations({ - "@TestConstructorParameterTypeAnnotations$MarkerTypeAnnotation(2)", + "@TestConstructorParameterTypeAnnotations.MarkerTypeAnnotation(2)", "null"}) public static class StaticNestedClass2 { public StaticNestedClass2(@MarkerTypeAnnotation(2) int parameter1, @@ -187,7 +187,7 @@ public class TestConstructorParameterTypeAnnotations { @ExpectedGetParameterAnnotations("[[], []]") @ExpectedParameterTypeAnnotations({ - "@TestConstructorParameterTypeAnnotations$MarkerTypeAnnotation(3)", + "@TestConstructorParameterTypeAnnotations.MarkerTypeAnnotation(3)", "null"}) public static class StaticNestedClass3 { public

    StaticNestedClass3(@MarkerTypeAnnotation(3) P parameter1, @@ -196,7 +196,7 @@ public class TestConstructorParameterTypeAnnotations { @ExpectedGetParameterAnnotations("[[], []]") @ExpectedParameterTypeAnnotations({ - "@TestConstructorParameterTypeAnnotations$MarkerTypeAnnotation(4)", + "@TestConstructorParameterTypeAnnotations.MarkerTypeAnnotation(4)", "null"}) public static class StaticNestedClass4 { public StaticNestedClass4(@MarkerTypeAnnotation(4) P parameter1, diff --git a/test/jdk/java/lang/annotation/typeAnnotations/TestObjectMethods.java b/test/jdk/java/lang/annotation/typeAnnotations/TestObjectMethods.java index dea8f42db6a..8349d48af72 100644 --- a/test/jdk/java/lang/annotation/typeAnnotations/TestObjectMethods.java +++ b/test/jdk/java/lang/annotation/typeAnnotations/TestObjectMethods.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -177,7 +177,7 @@ public class TestObjectMethods { } } - private static final Pattern annotationRegex = Pattern.compile("@TestObjectMethods\\$AnnotType\\((\\p{Digit})+\\)"); + private static final Pattern annotationRegex = Pattern.compile("@TestObjectMethods\\.AnnotType\\((\\p{Digit})+\\)"); static void testGetAnnotations(Class clazz, boolean annotationsExpectedOnMethods) { System.err.println("Testing getAnnotations on methods of class " + clazz.getName()); diff --git a/test/jdk/java/lang/reflect/records/RecordReflectionTest.java b/test/jdk/java/lang/reflect/records/RecordReflectionTest.java index 5968b4813ea..23b707663a9 100644 --- a/test/jdk/java/lang/reflect/records/RecordReflectionTest.java +++ b/test/jdk/java/lang/reflect/records/RecordReflectionTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, 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 @@ -162,7 +162,7 @@ public class RecordReflectionTest { RecordComponent rc = recordClass.getRecordComponents()[0]; Annotation[] annos = rc.getAnnotations(); assertEquals(annos.length, 1); - assertEquals(annos[0].toString(), "@RecordReflectionTest$RCA()"); + assertEquals(annos[0].toString(), "@RecordReflectionTest.RCA()"); Field f = recordClass.getDeclaredField("i"); assertEquals(f.getAnnotations().length, 1); @@ -181,7 +181,7 @@ public class RecordReflectionTest { AnnotatedType at = rc.getAnnotatedType(); Annotation[] annos = at.getAnnotations(); assertEquals(annos.length, 1); - assertEquals(annos[0].toString(), "@RecordReflectionTest$TYPE_USE()"); + assertEquals(annos[0].toString(), "@RecordReflectionTest.TYPE_USE()"); Field f = recordClass.getDeclaredField("i"); assertEquals(f.getAnnotatedType().getAnnotations().length, 1); -- GitLab From 6fdfe0458df989a7946b4f52a3023e8a39fb3bbb Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Sat, 12 Feb 2022 01:33:41 +0000 Subject: [PATCH 478/564] 8281674: tools/javac/annotations/typeAnnotations/classfile/AnonymousExtendsTest.java fails with AssertionError Reviewed-by: vromero --- .../typeAnnotations/classfile/AnonymousExtendsTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/langtools/tools/javac/annotations/typeAnnotations/classfile/AnonymousExtendsTest.java b/test/langtools/tools/javac/annotations/typeAnnotations/classfile/AnonymousExtendsTest.java index 063afbf43f3..0a99008c643 100644 --- a/test/langtools/tools/javac/annotations/typeAnnotations/classfile/AnonymousExtendsTest.java +++ b/test/langtools/tools/javac/annotations/typeAnnotations/classfile/AnonymousExtendsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, 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 8146167 + * @bug 8146167 8281674 * @summary Anonymous type declarations drop supertype type parameter annotations * @run main AnonymousExtendsTest */ @@ -52,10 +52,10 @@ public class AnonymousExtendsTest { public void testIt() { checkAnnotations(TestClass.class.getAnnotatedSuperclass(), - "[@AnonymousExtendsTest$TA(1)],[@AnonymousExtendsTest$TA(2)]"); + "[@AnonymousExtendsTest.TA(1)],[@AnonymousExtendsTest.TA(2)]"); checkAnnotations(new @TA(3) ArrayList<@TA(4) List>() { }.getClass().getAnnotatedSuperclass(), - "[@AnonymousExtendsTest$TA(3)],[@AnonymousExtendsTest$TA(4)]"); + "[@AnonymousExtendsTest.TA(3)],[@AnonymousExtendsTest.TA(4)]"); } public void checkAnnotations(AnnotatedType type, String expected) { -- GitLab From aa918a6ec4cd1356efd481c6f6fa94959f94f7b3 Mon Sep 17 00:00:00 2001 From: Alexander Zuev Date: Sat, 12 Feb 2022 09:26:47 +0000 Subject: [PATCH 479/564] 8281033: Improve ImageCheckboxTest to test all available LaF Reviewed-by: serb --- .../ImageCheckboxFocus/ImageCheckboxTest.java | 59 +++++++++++++++---- 1 file changed, 48 insertions(+), 11 deletions(-) diff --git a/test/jdk/javax/swing/JCheckBox/ImageCheckboxFocus/ImageCheckboxTest.java b/test/jdk/javax/swing/JCheckBox/ImageCheckboxFocus/ImageCheckboxTest.java index c93715d8087..844692bf454 100644 --- a/test/jdk/javax/swing/JCheckBox/ImageCheckboxFocus/ImageCheckboxTest.java +++ b/test/jdk/javax/swing/JCheckBox/ImageCheckboxFocus/ImageCheckboxTest.java @@ -23,13 +23,14 @@ import java.awt.Color; import java.awt.Component; -import java.awt.Dimension; import java.awt.Graphics; import java.awt.image.BufferedImage; import java.io.File; import javax.imageio.ImageIO; import javax.swing.Icon; import javax.swing.JCheckBox; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; /* * @test @@ -43,18 +44,43 @@ import javax.swing.JCheckBox; public class ImageCheckboxTest { public static void main(String[] args) throws Exception { - new ImageCheckboxTest().performTest(); + ImageCheckboxTest test = new ImageCheckboxTest(); + boolean passed = true; + // There are bugs found in various LaFs that needs to be fixed + // to enable testing there + String[] skip = { + "GTK+", // JDK-8281580 + "Nimbus" // JDK-8281581 + }; + testloop: + for (UIManager.LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels()) { + for (String s : skip) { + if (s.equals(laf.getName())) { + continue testloop; + } + } + passed = passed && test.performTest(laf); + } + + if(!passed) { + throw new RuntimeException("Test failed"); + } } - public void performTest() throws Exception { + public boolean performTest(UIManager.LookAndFeelInfo laf) throws Exception { BufferedImage imageNoFocus = new BufferedImage(100, 50, BufferedImage.TYPE_INT_ARGB); BufferedImage imageFocus = new BufferedImage(100, 50, BufferedImage.TYPE_INT_ARGB); BufferedImage imageFocusNotPainted = new BufferedImage(100, 50, BufferedImage.TYPE_INT_ARGB); + boolean success = true; - + try { + UIManager.setLookAndFeel(laf.getClassName()); + } catch (UnsupportedLookAndFeelException ulaf) { + return true; + } CustomCheckBox checkbox = new CustomCheckBox("Test", new MyIcon(Color.GREEN)); checkbox.setFocusPainted(true); checkbox.setSize(100, 50); @@ -64,21 +90,32 @@ public class ImageCheckboxTest { checkbox.paint(imageFocus.createGraphics()); if (Util.compareBufferedImages(imageFocus, imageNoFocus)) { - ImageIO.write(imageFocus, "png", new File("imageFocus.png")); - ImageIO.write(imageNoFocus, "png", new File("imageNoFocus.png")); - throw new Exception("Changing focus is not visualized"); + File folder = new File(laf.getName()); + if (!folder.exists()) { + folder.mkdir(); + } + ImageIO.write(imageFocus, "png", new File(folder, "/imageFocus.png")); + ImageIO.write(imageNoFocus, "png", new File(folder, "/imageNoFocus.png")); + System.err.println(laf.getName() + ": Changing of focus is not visualized"); + success = false; } checkbox.setFocusPainted(false); checkbox.paint(imageFocusNotPainted.createGraphics()); if (!Util.compareBufferedImages(imageFocusNotPainted, imageNoFocus)) { + File folder = new File(laf.getName()); + if (!folder.exists()) { + folder.mkdir(); + } ImageIO.write(imageFocusNotPainted, "png", - new File("imageFocusNotPainted.png")); - ImageIO.write(imageFocus, "png", new File("imageFocus.png")); - ImageIO.write(imageNoFocus, "png", new File("imageNoFocus.png")); - throw new Exception("setFocusPainted(false) is ignored"); + new File(folder,"imageFocusNotPainted.png")); + ImageIO.write(imageFocus, "png", new File(folder, "imageFocus.png")); + ImageIO.write(imageNoFocus, "png", new File(folder, "imageNoFocus.png")); + System.err.println(laf.getName() + ": setFocusPainted(false) is ignored"); + success = false; } + return success; } class MyIcon implements Icon { -- GitLab From 58dae60da0711c4ae0cb23f8ce2328e051d603b2 Mon Sep 17 00:00:00 2001 From: Alexey Bakhtin Date: Sat, 12 Feb 2022 11:54:22 +0000 Subject: [PATCH 480/564] 8274524: SSLSocket.close() hangs if it is called during the ssl handshake Reviewed-by: xuelei --- .../sun/security/ssl/SSLSocketImpl.java | 17 +++ .../SSLSocketImpl/ClientSocketCloseHang.java | 134 ++++++++++++++++++ 2 files changed, 151 insertions(+) create mode 100644 test/jdk/sun/security/ssl/SSLSocketImpl/ClientSocketCloseHang.java diff --git a/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java b/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java index e55419d70ee..842cef11911 100644 --- a/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java +++ b/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java @@ -107,6 +107,11 @@ public final class SSLSocketImpl private static final boolean trustNameService = Utilities.getBooleanProperty("jdk.tls.trustNameService", false); + /* + * Default timeout to skip bytes from the open socket + */ + private static final int DEFAULT_SKIP_TIMEOUT = 1; + /** * Package-private constructor used to instantiate an unconnected * socket. @@ -1781,9 +1786,21 @@ public final class SSLSocketImpl if (conContext.inputRecord instanceof SSLSocketInputRecord inputRecord && isConnected) { if (appInput.readLock.tryLock()) { + int soTimeout = getSoTimeout(); try { + // deplete could hang on the skip operation + // in case of infinite socket read timeout. + // Change read timeout to avoid deadlock. + // This workaround could be replaced later + // with the right synchronization + if (soTimeout == 0) + setSoTimeout(DEFAULT_SKIP_TIMEOUT); inputRecord.deplete(false); + } catch (java.net.SocketTimeoutException stEx) { + // skip timeout exception during deplete } finally { + if (soTimeout == 0) + setSoTimeout(soTimeout); appInput.readLock.unlock(); } } diff --git a/test/jdk/sun/security/ssl/SSLSocketImpl/ClientSocketCloseHang.java b/test/jdk/sun/security/ssl/SSLSocketImpl/ClientSocketCloseHang.java new file mode 100644 index 00000000000..249aab13291 --- /dev/null +++ b/test/jdk/sun/security/ssl/SSLSocketImpl/ClientSocketCloseHang.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2021, 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 8274524 + * @summary 8274524: SSLSocket.close() hangs if it is called during the ssl handshake + * @library /javax/net/ssl/templates + * @run main/othervm ClientSocketCloseHang TLSv1.2 + * @run main/othervm ClientSocketCloseHang TLSv1.3 + */ + + +import javax.net.ssl.*; +import java.net.InetAddress; + +public class ClientSocketCloseHang implements SSLContextTemplate { + + public static void main(String[] args) throws Exception { + System.setProperty("jdk.tls.client.protocols", args[0]); + for (int i = 0; i<= 20; i++) { + System.err.println("==================================="); + System.err.println("loop " + i); + System.err.println("==================================="); + new ClientSocketCloseHang().test(); + } + } + + private void test() throws Exception { + SSLServerSocket listenSocket = null; + SSLSocket serverSocket = null; + ClientSocket clientSocket = null; + try { + SSLServerSocketFactory serversocketfactory = + createServerSSLContext().getServerSocketFactory(); + listenSocket = + (SSLServerSocket)serversocketfactory.createServerSocket(0); + listenSocket.setNeedClientAuth(false); + listenSocket.setEnableSessionCreation(true); + listenSocket.setUseClientMode(false); + + + System.err.println("Starting client"); + clientSocket = new ClientSocket(listenSocket.getLocalPort()); + clientSocket.start(); + + System.err.println("Accepting client requests"); + serverSocket = (SSLSocket) listenSocket.accept(); + + serverSocket.startHandshake(); + } finally { + if (clientSocket != null) { + clientSocket.close(); + } + if (listenSocket != null) { + listenSocket.close(); + } + + if (serverSocket != null) { + serverSocket.close(); + } + } + } + + private class ClientSocket extends Thread{ + int serverPort = 0; + SSLSocket clientSocket = null; + + public ClientSocket(int serverPort) { + this.serverPort = serverPort; + } + + @Override + public void run() { + try { + System.err.println( + "Connecting to server at port " + serverPort); + SSLSocketFactory sslSocketFactory = + createClientSSLContext().getSocketFactory(); + clientSocket = (SSLSocket)sslSocketFactory.createSocket( + InetAddress.getLocalHost(), serverPort); + clientSocket.setSoLinger(true, 3); + clientSocket.startHandshake(); + } catch (Exception e) { + } + } + + public void close() { + Thread t = new Thread() { + @Override + public void run() { + try { + if (clientSocket != null) { + clientSocket.close(); + } + } catch (Exception ex) { + } + } + }; + try { + // Close client connection + t.start(); + t.join(2000); // 2 sec + } catch (InterruptedException ex) { + return; + } + + if (t.isAlive()) { + throw new RuntimeException("SSL Client hangs on close"); + } + } + } +} + -- GitLab From 67077a04307b512219a46b6c4c274ce308ee46de Mon Sep 17 00:00:00 2001 From: Emanuel Peter Date: Sat, 12 Feb 2022 13:08:39 +0000 Subject: [PATCH 481/564] 8278423: ExtendedDTraceProbes should be deprecated Reviewed-by: dholmes, hseigel, kvn, thartmann --- src/hotspot/share/runtime/arguments.cpp | 3 ++ src/hotspot/share/runtime/globals.hpp | 10 ++++--- src/java.base/share/man/java.1 | 28 +++++++++++++++---- .../CommandLine/VMDeprecatedOptions.java | 1 + .../7170638/SDTProbesGNULinuxTest.java | 4 ++- 5 files changed, 36 insertions(+), 10 deletions(-) diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index 7d0f1ddd4d3..952b96f537e 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -537,6 +537,7 @@ static SpecialFlag const special_jvm_flags[] = { #ifdef PRODUCT { "UseHeavyMonitors", JDK_Version::jdk(18), JDK_Version::jdk(19), JDK_Version::jdk(20) }, #endif + { "ExtendedDTraceProbes", JDK_Version::jdk(19), JDK_Version::jdk(20), JDK_Version::jdk(21) }, // --- Deprecated alias flags (see also aliased_jvm_flags) - sorted by obsolete_in then expired_in: { "DefaultMaxRAMFraction", JDK_Version::jdk(8), JDK_Version::undefined(), JDK_Version::undefined() }, @@ -2886,6 +2887,8 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, bool* patch_m } } else if (match_option(option, "-XX:+ExtendedDTraceProbes")) { #if defined(DTRACE_ENABLED) + warning("Option ExtendedDTraceProbes was deprecated in version 19 and will likely be removed in a future release."); + warning("Use the combination of -XX:+DTraceMethodProbes, -XX:+DTraceAllocProbes and -XX:+DTraceMonitorProbes instead."); if (FLAG_SET_CMDLINE(ExtendedDTraceProbes, true) != JVMFlag::SUCCESS) { return JNI_EINVAL; } diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index bc80a2eb45f..f45d259fd21 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -1858,16 +1858,18 @@ const intx ObjectAlignmentInBytes = 8; "Pause and wait for keypress on exit if a debugger is attached") \ \ product(bool, ExtendedDTraceProbes, false, \ - "Enable performance-impacting dtrace probes") \ + "(Deprecated) Enable performance-impacting dtrace probes. " \ + "Use the combination of -XX:+DTraceMethodProbes, " \ + "-XX:+DTraceAllocProbes and -XX:+DTraceMonitorProbes instead.") \ \ product(bool, DTraceMethodProbes, false, \ - "Enable dtrace probes for method-entry and method-exit") \ + "Enable dtrace tool probes for method-entry and method-exit") \ \ product(bool, DTraceAllocProbes, false, \ - "Enable dtrace probes for object allocation") \ + "Enable dtrace tool probes for object allocation") \ \ product(bool, DTraceMonitorProbes, false, \ - "Enable dtrace probes for monitor events") \ + "Enable dtrace tool probes for monitor events") \ \ product(bool, RelaxAccessControlCheck, false, \ "Relax the access control checks in the verifier") \ diff --git a/src/java.base/share/man/java.1 b/src/java.base/share/man/java.1 index 6a1532a8981..ea7edb8ef99 100644 --- a/src/java.base/share/man/java.1 +++ b/src/java.base/share/man/java.1 @@ -2977,11 +2977,19 @@ different JDK version. .RE .RE .TP -.B \f[CB]\-XX:+ExtendedDTraceProbes\f[R] -\f[B]Linux and macOS:\f[R] Enables additional \f[CB]dtrace\f[R] tool probes -that affect the performance. -By default, this option is disabled and \f[CB]dtrace\f[R] performs only -standard probes. +.B \f[CB]\-XX:+DTraceAllocProbes\f[R] +\f[B]Linux and macOS:\f[R] Enable \f[CB]dtrace\f[R] tool probes for object allocation. +.RS +.RE +.TP +.B \f[CB]\-XX:+DTraceMethodProbes\f[R] +\f[B]Linux and macOS:\f[R] Enable \f[CB]dtrace\f[R] tool probes for method-entry +and method-exit. +.RS +.RE +.TP +.B \f[CB]\-XX:+DTraceMonitorProbes\f[R] +\f[B]Linux and macOS:\f[R] Enable \f[CB]dtrace\f[R] tool probes for monitor events. .RS .RE .TP @@ -4008,6 +4016,16 @@ Example: \f[CB]\-Xlog:gc:garbage\-collection.log\f[R] .RE .TP +.B \f[CB]\-XX:+ExtendedDTraceProbes\f[R] +\f[B]Linux and macOS:\f[R] Enables additional \f[CB]dtrace\f[R] tool probes +that affect performance. +By default, this option is disabled and \f[CB]dtrace\f[R] performs only +standard probes. +Use the combination of these flags instead: \f[CB]\-XX:+DTraceMethodProbes\f[R], +\f[CB]\-XX:+DTraceAllocProbes\f[R], \f[CB]\-XX:+DTraceMonitorProbes\f[R]. +.RS +.RE +.TP .B \f[CB]\-XX:+FlightRecorder\f[R] Enables the use of Java Flight Recorder (JFR) during the runtime of the application. diff --git a/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java b/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java index e9ccac08793..86bd3e9d2e2 100644 --- a/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java +++ b/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java @@ -54,6 +54,7 @@ public class VMDeprecatedOptions { {"InitialRAMFraction", "64"}, {"TLABStats", "false"}, {"AllowRedefinitionToAddDeleteMethods", "true"}, + {"ExtendedDTraceProbes", "true"}, // deprecated alias flags (see also aliased_jvm_flags): {"DefaultMaxRAMFraction", "4"}, diff --git a/test/hotspot/jtreg/serviceability/7170638/SDTProbesGNULinuxTest.java b/test/hotspot/jtreg/serviceability/7170638/SDTProbesGNULinuxTest.java index 9ad10282d1b..36759433112 100644 --- a/test/hotspot/jtreg/serviceability/7170638/SDTProbesGNULinuxTest.java +++ b/test/hotspot/jtreg/serviceability/7170638/SDTProbesGNULinuxTest.java @@ -46,7 +46,9 @@ public class SDTProbesGNULinuxTest { public static void main(String[] args) throws Throwable { { var pb = ProcessTools.createJavaProcessBuilder( - "-XX:+ExtendedDTraceProbes", + "-XX:+DTraceMethodProbes", + "-XX:+DTraceAllocProbes", + "-XX:+DTraceMonitorProbes", "-version"); var oa = new OutputAnalyzer(pb.start()); // This test only matters when build with DTRACE_ENABLED. -- GitLab From 8acfbc2e21063c3dc088c25c1574bcefa94e5a24 Mon Sep 17 00:00:00 2001 From: David Holmes Date: Sat, 12 Feb 2022 14:12:42 +0000 Subject: [PATCH 482/564] 8281675: VMDeprecatedOptions test fails after JDK-8278423 Reviewed-by: dcubed --- .../hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java b/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java index 86bd3e9d2e2..a8b5bb31194 100644 --- a/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java +++ b/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, 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 @@ -54,7 +54,6 @@ public class VMDeprecatedOptions { {"InitialRAMFraction", "64"}, {"TLABStats", "false"}, {"AllowRedefinitionToAddDeleteMethods", "true"}, - {"ExtendedDTraceProbes", "true"}, // deprecated alias flags (see also aliased_jvm_flags): {"DefaultMaxRAMFraction", "4"}, -- GitLab From eff5dafba9f72bd0612357712ffa472ce1c9166a Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Sat, 12 Feb 2022 22:10:11 +0000 Subject: [PATCH 483/564] 8274939: Incorrect size of the pixel storage is used by the robot on macOS Reviewed-by: aivanov, prr --- .../macosx/classes/sun/lwawt/macosx/CRobot.java | 8 ++++---- src/java.desktop/macosx/native/libawt_lwawt/awt/CRobot.m | 7 ++++++- .../awt/Robot/CheckCommonColors/CheckCommonColors.java | 2 ++ 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CRobot.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CRobot.java index 49125443b2e..5dba06cb612 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CRobot.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CRobot.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2022, 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 @@ -168,9 +168,9 @@ final class CRobot implements RobotPeer { */ @Override public int getRGBPixel(int x, int y) { - int[] c = new int[1]; - double scale = fDevice.getScaleFactor(); - getScreenPixels(new Rectangle(x, y, (int) scale, (int) scale), c); + int scale = fDevice.getScaleFactor(); + int[] c = new int[scale * scale]; + getScreenPixels(new Rectangle(x, y, scale, scale), c); return c[0]; } diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/CRobot.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/CRobot.m index 9d90086677d..55df129960f 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/CRobot.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/CRobot.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, 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 @@ -321,6 +321,11 @@ Java_sun_lwawt_macosx_CRobot_nativeGetScreenPixels jint picY = y; jint picWidth = width; jint picHeight = height; + jsize size = (*env)->GetArrayLength(env, pixels); + if (size < (long) picWidth * picHeight || picWidth < 0 || picHeight < 0) { + JNU_ThrowInternalError(env, "Invalid arguments to get screen pixels"); + return; + } CGRect screenRect = CGRectMake(picX / scale, picY / scale, picWidth / scale, picHeight / scale); diff --git a/test/jdk/java/awt/Robot/CheckCommonColors/CheckCommonColors.java b/test/jdk/java/awt/Robot/CheckCommonColors/CheckCommonColors.java index 57419b0ac5a..55d9b4358af 100644 --- a/test/jdk/java/awt/Robot/CheckCommonColors/CheckCommonColors.java +++ b/test/jdk/java/awt/Robot/CheckCommonColors/CheckCommonColors.java @@ -42,6 +42,8 @@ import javax.imageio.ImageIO; * @key headful * @bug 8215105 8211999 * @summary tests that Robot can capture the common colors without artifacts + * @run main/othervm CheckCommonColors + * @run main/othervm -Xcheck:jni CheckCommonColors */ public final class CheckCommonColors { -- GitLab From adbe0661029f12a36a44af52b83b189384d33a27 Mon Sep 17 00:00:00 2001 From: Bhavana Kilambi Date: Mon, 14 Feb 2022 01:33:20 +0000 Subject: [PATCH 484/564] 8239927: Product variable PrefetchFieldsAhead is unused and should be removed Reviewed-by: njian, dholmes --- src/hotspot/cpu/x86/vm_version_x86.cpp | 8 +------- src/hotspot/share/gc/shared/gc_globals.hpp | 6 +----- src/hotspot/share/runtime/arguments.cpp | 1 + 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/src/hotspot/cpu/x86/vm_version_x86.cpp b/src/hotspot/cpu/x86/vm_version_x86.cpp index 93613850a5e..c09785b969a 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.cpp +++ b/src/hotspot/cpu/x86/vm_version_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -1818,9 +1818,6 @@ void VM_Version::get_processor_features() { if (FLAG_IS_DEFAULT(PrefetchScanIntervalInBytes)) { FLAG_SET_DEFAULT(PrefetchScanIntervalInBytes, 576); } - if (FLAG_IS_DEFAULT(PrefetchFieldsAhead)) { - FLAG_SET_DEFAULT(PrefetchFieldsAhead, 1); - } #endif if (FLAG_IS_DEFAULT(ContendedPaddingWidth) && @@ -1883,9 +1880,6 @@ void VM_Version::get_processor_features() { if (PrefetchScanIntervalInBytes > 0) { log->print_cr("PrefetchScanIntervalInBytes %d", (int) PrefetchScanIntervalInBytes); } - if (PrefetchFieldsAhead > 0) { - log->print_cr("PrefetchFieldsAhead %d", (int) PrefetchFieldsAhead); - } if (ContendedPaddingWidth > 0) { log->print_cr("ContendedPaddingWidth %d", (int) ContendedPaddingWidth); } diff --git a/src/hotspot/share/gc/shared/gc_globals.hpp b/src/hotspot/share/gc/shared/gc_globals.hpp index 555170a091a..d9380b2af71 100644 --- a/src/hotspot/share/gc/shared/gc_globals.hpp +++ b/src/hotspot/share/gc/shared/gc_globals.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -503,10 +503,6 @@ "How far ahead to prefetch scan area (<= 0 means off)") \ range(-1, max_jint) \ \ - product(intx, PrefetchFieldsAhead, -1, \ - "How many fields ahead to prefetch in oop scan (<= 0 means off)") \ - range(-1, max_jint) \ - \ product(bool, VerifyDuringStartup, false, DIAGNOSTIC, \ "Verify memory system before executing any Java code " \ "during VM initialization") \ diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index 952b96f537e..fed6faa0ccd 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -548,6 +548,7 @@ static SpecialFlag const special_jvm_flags[] = { { "FilterSpuriousWakeups", JDK_Version::jdk(18), JDK_Version::jdk(19), JDK_Version::jdk(20) }, { "MinInliningThreshold", JDK_Version::jdk(18), JDK_Version::jdk(19), JDK_Version::jdk(20) }, + { "PrefetchFieldsAhead", JDK_Version::undefined(), JDK_Version::jdk(19), JDK_Version::jdk(20) }, #ifdef ASSERT { "DummyObsoleteTestFlag", JDK_Version::undefined(), JDK_Version::jdk(18), JDK_Version::undefined() }, #endif -- GitLab From 483d4b97e0ae4ab7b0d87058901f57688a0f0811 Mon Sep 17 00:00:00 2001 From: Nils Eliasson Date: Mon, 14 Feb 2022 08:27:21 +0000 Subject: [PATCH 485/564] 8281505: Add CompileCommand PrintIdealPhase Reviewed-by: kvn, thartmann, chagedorn --- src/hotspot/share/compiler/compileBroker.cpp | 3 +- .../share/compiler/compilerDirectives.cpp | 20 ++ .../share/compiler/compilerDirectives.hpp | 6 +- src/hotspot/share/compiler/compilerOracle.cpp | 16 ++ src/hotspot/share/compiler/compilerOracle.hpp | 7 +- .../share/compiler/directivesParser.cpp | 10 + src/hotspot/share/opto/compile.cpp | 15 +- src/hotspot/share/opto/compile.hpp | 1 + src/hotspot/share/opto/phasetype.hpp | 248 +++++++++++------- .../compiler/oracle/PrintIdealPhaseTest.java | 153 +++++++++++ 10 files changed, 377 insertions(+), 102 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/oracle/PrintIdealPhaseTest.java diff --git a/src/hotspot/share/compiler/compileBroker.cpp b/src/hotspot/share/compiler/compileBroker.cpp index 4ae7bc21ce6..1c8656044b5 100644 --- a/src/hotspot/share/compiler/compileBroker.cpp +++ b/src/hotspot/share/compiler/compileBroker.cpp @@ -614,9 +614,8 @@ void register_jfr_phasetype_serializer(CompilerType compiler_type) { #ifdef COMPILER2 } else if (compiler_type == compiler_c2) { assert(first_registration, "invariant"); // c2 must be registered first. - GrowableArray* c2_phase_names = new GrowableArray(PHASE_NUM_TYPES); for (int i = 0; i < PHASE_NUM_TYPES; i++) { - const char* phase_name = CompilerPhaseTypeHelper::to_string((CompilerPhaseType) i); + const char* phase_name = CompilerPhaseTypeHelper::to_description((CompilerPhaseType) i); CompilerEvent::PhaseEvent::get_phase_id(phase_name, false, false, false); } first_registration = false; diff --git a/src/hotspot/share/compiler/compilerDirectives.cpp b/src/hotspot/share/compiler/compilerDirectives.cpp index 6d864072d1b..5fe84827195 100644 --- a/src/hotspot/share/compiler/compilerDirectives.cpp +++ b/src/hotspot/share/compiler/compilerDirectives.cpp @@ -30,6 +30,7 @@ #include "compiler/compilerOracle.hpp" #include "memory/allocation.inline.hpp" #include "memory/resourceArea.hpp" +#include "opto/phasetype.hpp" #include "runtime/globals_extension.hpp" CompilerDirectives::CompilerDirectives() : _next(NULL), _match(NULL), _ref_count(0) { @@ -262,6 +263,7 @@ void DirectiveSet::init_control_intrinsic() { DirectiveSet::DirectiveSet(CompilerDirectives* d) :_inlinematchers(NULL), _directive(d) { #define init_defaults_definition(name, type, dvalue, compiler) this->name##Option = dvalue; + _ideal_phase_name_mask = 0; compilerdirectives_common_flags(init_defaults_definition) compilerdirectives_c2_flags(init_defaults_definition) compilerdirectives_c1_flags(init_defaults_definition) @@ -381,6 +383,24 @@ DirectiveSet* DirectiveSet::compilecommand_compatibility_init(const methodHandle compilerdirectives_c2_flags(init_default_cc) compilerdirectives_c1_flags(init_default_cc) + // Parse PrintIdealPhaseName and create an efficient lookup mask +#ifndef PRODUCT +#ifdef COMPILER2 + if (!_modified[PrintIdealPhaseIndex]) { + // Parse ccstr and create mask + ccstrlist option; + if (CompilerOracle::has_option_value(method, CompileCommand::PrintIdealPhase, option)) { + uint64_t mask = 0; + PhaseNameValidator validator(option, mask); + if (validator.is_valid()) { + assert(mask != 0, "Must be set"); + set.cloned()->_ideal_phase_name_mask = mask; + } + } + } +#endif +#endif + // Canonicalize DisableIntrinsic to contain only ',' as a separator. ccstrlist option_value; bool need_reset = true; // if Control/DisableIntrinsic redefined, only need to reset control_words once diff --git a/src/hotspot/share/compiler/compilerDirectives.hpp b/src/hotspot/share/compiler/compilerDirectives.hpp index 7daa034a8d0..8e3ba2db005 100644 --- a/src/hotspot/share/compiler/compilerDirectives.hpp +++ b/src/hotspot/share/compiler/compilerDirectives.hpp @@ -67,6 +67,7 @@ NOT_PRODUCT(cflags(TraceOptoPipelining, bool, TraceOptoPipelining, TraceOptoPipelining)) \ NOT_PRODUCT(cflags(TraceOptoOutput, bool, TraceOptoOutput, TraceOptoOutput)) \ NOT_PRODUCT(cflags(PrintIdeal, bool, PrintIdeal, PrintIdeal)) \ +NOT_PRODUCT(cflags(PrintIdealPhase, ccstrlist, "", PrintIdealPhase)) \ NOT_PRODUCT(cflags(PrintIdealLevel, uintx, PrintIdealLevel, PrintIdealLevel)) \ cflags(TraceSpilling, bool, TraceSpilling, TraceSpilling) \ cflags(Vectorize, bool, false, Vectorize) \ @@ -108,6 +109,7 @@ private: InlineMatcher* _inlinematchers; CompilerDirectives* _directive; TriBoolArray<(size_t)vmIntrinsics::number_of_intrinsics(), int> _intrinsic_control_words; + uint64_t _ideal_phase_name_mask; public: DirectiveSet(CompilerDirectives* directive); @@ -137,7 +139,6 @@ public: private: bool _modified[number_of_flags]; // Records what options where set by a directive - public: #define flag_store_definition(name, type, dvalue, cc_flag) type name##Option; compilerdirectives_common_flags(flag_store_definition) @@ -150,6 +151,9 @@ public: compilerdirectives_c2_flags(set_function_definition) compilerdirectives_c1_flags(set_function_definition) + void set_ideal_phase_mask(uint64_t mask) { _ideal_phase_name_mask = mask; }; + uint64_t ideal_phase_mask() { return _ideal_phase_name_mask; }; + void print_intx(outputStream* st, ccstr n, intx v, bool mod) { if (mod) { st->print("%s:" INTX_FORMAT " ", n, v); } } void print_uintx(outputStream* st, ccstr n, intx v, bool mod) { if (mod) { st->print("%s:" UINTX_FORMAT " ", n, v); } } void print_bool(outputStream* st, ccstr n, bool v, bool mod) { if (mod) { st->print("%s:%s ", n, v ? "true" : "false"); } } diff --git a/src/hotspot/share/compiler/compilerOracle.cpp b/src/hotspot/share/compiler/compilerOracle.cpp index 7d58a28d272..7d8b7179d0c 100644 --- a/src/hotspot/share/compiler/compilerOracle.cpp +++ b/src/hotspot/share/compiler/compilerOracle.cpp @@ -34,6 +34,7 @@ #include "oops/klass.hpp" #include "oops/method.inline.hpp" #include "oops/symbol.hpp" +#include "opto/phasetype.hpp" #include "runtime/globals_extension.hpp" #include "runtime/handles.inline.hpp" #include "runtime/jniHandles.hpp" @@ -683,6 +684,21 @@ static void scan_value(enum OptionType type, char* line, int& total_bytes_read, jio_snprintf(errorbuf, buf_size, "Unrecognized intrinsic detected in %s: %s", option2name(option), validator.what()); } } +#ifndef PRODUCT + else if (option == CompileCommand::PrintIdealPhase) { + uint64_t mask = 0; + PhaseNameValidator validator(value, mask); + + if (!validator.is_valid()) { + jio_snprintf(errorbuf, buf_size, "Unrecognized phase name in %s: %s", option2name(option), validator.what()); + } + } else if (option == CompileCommand::TestOptionList) { + // all values are ok + } +#endif + else { + assert(false, "Ccstrlist type option missing validator"); + } register_command(matcher, option, (ccstr) value); return; diff --git a/src/hotspot/share/compiler/compilerOracle.hpp b/src/hotspot/share/compiler/compilerOracle.hpp index f2fc0e8251d..24ed40b7ef2 100644 --- a/src/hotspot/share/compiler/compilerOracle.hpp +++ b/src/hotspot/share/compiler/compilerOracle.hpp @@ -79,9 +79,10 @@ class methodHandle; option(TraceOptoPipelining, "TraceOptoPipelining", Bool) \ option(TraceOptoOutput, "TraceOptoOutput", Bool) \ option(TraceSpilling, "TraceSpilling", Bool) \ - option(PrintIdeal, "PrintIdeal", Bool) \ - option(PrintIdealLevel, "PrintIdealLevel", Uintx) \ - option(IGVPrintLevel, "IGVPrintLevel", Intx) \ +NOT_PRODUCT(option(PrintIdeal, "PrintIdeal", Bool)) \ +NOT_PRODUCT(option(PrintIdealLevel, "PrintIdealLevel", Uintx)) \ +NOT_PRODUCT(option(PrintIdealPhase, "PrintIdealPhase", Ccstrlist)) \ +NOT_PRODUCT(option(IGVPrintLevel, "IGVPrintLevel", Intx)) \ option(Vectorize, "Vectorize", Bool) \ option(VectorizeDebug, "VectorizeDebug", Uintx) \ option(CloneMapDebug, "CloneMapDebug", Bool) \ diff --git a/src/hotspot/share/compiler/directivesParser.cpp b/src/hotspot/share/compiler/directivesParser.cpp index b4ce9a3877c..e48ac58b31c 100644 --- a/src/hotspot/share/compiler/directivesParser.cpp +++ b/src/hotspot/share/compiler/directivesParser.cpp @@ -27,6 +27,7 @@ #include "compiler/directivesParser.hpp" #include "memory/allocation.inline.hpp" #include "memory/resourceArea.hpp" +#include "opto/phasetype.hpp" #include "runtime/os.hpp" #include @@ -334,6 +335,15 @@ bool DirectivesParser::set_option_flag(JSON_TYPE t, JSON_VAL* v, const key* opti error(VALUE_ERROR, "Unrecognized intrinsic detected in DisableIntrinsic: %s", validator.what()); return false; } + } else if (strncmp(option_key->name, "PrintIdealPhase", 15) == 0) { + uint64_t mask = 0; + PhaseNameValidator validator(s, mask); + + if (!validator.is_valid()) { + error(VALUE_ERROR, "Unrecognized phase name detected in PrintIdealPhase: %s", validator.what()); + return false; + } + set->set_ideal_phase_mask(mask); } } break; diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index 1296a3ff8b8..44456772321 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -4833,7 +4833,7 @@ void Compile::print_method(CompilerPhaseType cpt, int level, Node* n) { #ifndef PRODUCT ResourceMark rm; stringStream ss; - ss.print_raw(CompilerPhaseTypeHelper::to_string(cpt)); + ss.print_raw(CompilerPhaseTypeHelper::to_name(cpt)); if (n != nullptr) { ss.print(": %d %s ", n->_idx, NodeClassNames[n->Opcode()]); } @@ -4842,8 +4842,8 @@ void Compile::print_method(CompilerPhaseType cpt, int level, Node* n) { if (should_print_igv(level)) { _igv_printer->print_method(name, level); } - if (should_print_ideal(level)) { - print_ideal_ir(name); + if (should_print_ideal(level) || should_print_phase(cpt)) { + print_ideal_ir(CompilerPhaseTypeHelper::to_name(cpt)); } #endif C->_latest_stage_start_counter.stamp(); @@ -4873,6 +4873,15 @@ void Compile::end_method() { #endif } +bool Compile::should_print_phase(CompilerPhaseType cpt) { +#ifndef PRODUCT + if ((_directive->ideal_phase_mask() & CompilerPhaseTypeHelper::to_bitmask(cpt)) != 0) { + return true; + } +#endif + return false; +} + bool Compile::should_print_igv(int level) { #ifndef PRODUCT if (PrintIdealGraphLevel < 0) { // disabled by the user diff --git a/src/hotspot/share/opto/compile.hpp b/src/hotspot/share/opto/compile.hpp index 70480b0d06e..0d74c9e5f9a 100644 --- a/src/hotspot/share/opto/compile.hpp +++ b/src/hotspot/share/opto/compile.hpp @@ -654,6 +654,7 @@ class Compile : public Phase { void begin_method(); void end_method(); bool should_print_igv(int level); + bool should_print_phase(CompilerPhaseType cpt); void print_method(CompilerPhaseType cpt, int level, Node* n = nullptr); diff --git a/src/hotspot/share/opto/phasetype.hpp b/src/hotspot/share/opto/phasetype.hpp index 2aa55a65553..d56a7b13197 100644 --- a/src/hotspot/share/opto/phasetype.hpp +++ b/src/hotspot/share/opto/phasetype.hpp @@ -25,105 +25,167 @@ #ifndef SHARE_OPTO_PHASETYPE_HPP #define SHARE_OPTO_PHASETYPE_HPP +#define COMPILER_PHASES(flags) \ + flags(BEFORE_STRINGOPTS, "Before StringOpts") \ + flags(AFTER_STRINGOPTS, "After StringOpts") \ + flags(BEFORE_REMOVEUSELESS, "Before RemoveUseless") \ + flags(AFTER_PARSING, "After Parsing") \ + flags(ITER_GVN1, "Iter GVN 1") \ + flags(EXPAND_VUNBOX, "Expand VectorUnbox") \ + flags(SCALARIZE_VBOX, "Scalarize VectorBox") \ + flags(INLINE_VECTOR_REBOX, "Inline Vector Rebox Calls") \ + flags(EXPAND_VBOX, "Expand VectorBox") \ + flags(ELIMINATE_VBOX_ALLOC, "Eliminate VectorBoxAllocate") \ + flags(PHASEIDEAL_BEFORE_EA, "PhaseIdealLoop before EA") \ + flags(ITER_GVN_AFTER_VECTOR, "Iter GVN after vector box elimination") \ + flags(ITER_GVN_BEFORE_EA, "Iter GVN before EA") \ + flags(ITER_GVN_AFTER_EA, "Iter GVN after EA") \ + flags(ITER_GVN_AFTER_ELIMINATION, "Iter GVN after eliminating allocations and locks") \ + flags(PHASEIDEALLOOP1, "PhaseIdealLoop 1") \ + flags(PHASEIDEALLOOP2, "PhaseIdealLoop 2") \ + flags(PHASEIDEALLOOP3, "PhaseIdealLoop 3") \ + flags(CCP1, "PhaseCCP 1") \ + flags(ITER_GVN2, "Iter GVN 2") \ + flags(PHASEIDEALLOOP_ITERATIONS, "PhaseIdealLoop iterations") \ + flags(OPTIMIZE_FINISHED, "Optimize finished") \ + flags(GLOBAL_CODE_MOTION, "Global code motion") \ + flags(FINAL_CODE, "Final Code") \ + flags(AFTER_EA, "After Escape Analysis") \ + flags(BEFORE_CLOOPS, "Before CountedLoop") \ + flags(AFTER_CLOOPS, "After CountedLoop") \ + flags(BEFORE_BEAUTIFY_LOOPS, "Before beautify loops") \ + flags(AFTER_BEAUTIFY_LOOPS, "After beautify loops") \ + flags(BEFORE_MATCHING, "Before matching") \ + flags(MATCHING, "After matching") \ + flags(INCREMENTAL_INLINE, "Incremental Inline") \ + flags(INCREMENTAL_INLINE_STEP, "Incremental Inline Step") \ + flags(INCREMENTAL_INLINE_CLEANUP, "Incremental Inline Cleanup") \ + flags(INCREMENTAL_BOXING_INLINE, "Incremental Boxing Inline") \ + flags(CALL_CATCH_CLEANUP, "Call catch cleanup") \ + flags(MACRO_EXPANSION, "Macro expand") \ + flags(BARRIER_EXPANSION, "Barrier expand") \ + flags(END, "End") \ + flags(FAILURE, "Failure") \ + flags(DEBUG, "Debug") + +#define table_entry(name, description) PHASE_##name, enum CompilerPhaseType { - PHASE_BEFORE_STRINGOPTS, - PHASE_AFTER_STRINGOPTS, - PHASE_BEFORE_REMOVEUSELESS, - PHASE_AFTER_PARSING, - PHASE_ITER_GVN1, - PHASE_EXPAND_VUNBOX, - PHASE_SCALARIZE_VBOX, - PHASE_INLINE_VECTOR_REBOX, - PHASE_EXPAND_VBOX, - PHASE_ELIMINATE_VBOX_ALLOC, - PHASE_PHASEIDEAL_BEFORE_EA, - PHASE_ITER_GVN_AFTER_VECTOR, - PHASE_ITER_GVN_BEFORE_EA, - PHASE_ITER_GVN_AFTER_EA, - PHASE_ITER_GVN_AFTER_ELIMINATION, - PHASE_PHASEIDEALLOOP1, - PHASE_PHASEIDEALLOOP2, - PHASE_PHASEIDEALLOOP3, - PHASE_CCP1, - PHASE_ITER_GVN2, - PHASE_PHASEIDEALLOOP_ITERATIONS, - PHASE_OPTIMIZE_FINISHED, - PHASE_GLOBAL_CODE_MOTION, - PHASE_FINAL_CODE, - PHASE_AFTER_EA, - PHASE_BEFORE_CLOOPS, - PHASE_AFTER_CLOOPS, - PHASE_BEFORE_BEAUTIFY_LOOPS, - PHASE_AFTER_BEAUTIFY_LOOPS, - PHASE_BEFORE_MATCHING, - PHASE_MATCHING, - PHASE_INCREMENTAL_INLINE, - PHASE_INCREMENTAL_INLINE_STEP, - PHASE_INCREMENTAL_INLINE_CLEANUP, - PHASE_INCREMENTAL_BOXING_INLINE, - PHASE_CALL_CATCH_CLEANUP, - PHASE_INSERT_BARRIER, - PHASE_MACRO_EXPANSION, - PHASE_BARRIER_EXPANSION, - PHASE_ADD_UNSAFE_BARRIER, - PHASE_END, - PHASE_FAILURE, - PHASE_DEBUG, - - PHASE_NUM_TYPES + COMPILER_PHASES(table_entry) + PHASE_NUM_TYPES, + PHASE_NONE +}; +#undef table_entry + +static const char* phase_descriptions[] = { +#define array_of_labels(name, description) description, + COMPILER_PHASES(array_of_labels) +#undef array_of_labels +}; + +static const char* phase_names[] = { +#define array_of_labels(name, description) #name, + COMPILER_PHASES(array_of_labels) +#undef array_of_labels }; class CompilerPhaseTypeHelper { public: - static const char* to_string(CompilerPhaseType cpt) { - switch (cpt) { - case PHASE_BEFORE_STRINGOPTS: return "Before StringOpts"; - case PHASE_AFTER_STRINGOPTS: return "After StringOpts"; - case PHASE_BEFORE_REMOVEUSELESS: return "Before RemoveUseless"; - case PHASE_AFTER_PARSING: return "After Parsing"; - case PHASE_ITER_GVN1: return "Iter GVN 1"; - case PHASE_EXPAND_VUNBOX: return "Expand VectorUnbox"; - case PHASE_SCALARIZE_VBOX: return "Scalarize VectorBox"; - case PHASE_INLINE_VECTOR_REBOX: return "Inline Vector Rebox Calls"; - case PHASE_EXPAND_VBOX: return "Expand VectorBox"; - case PHASE_ELIMINATE_VBOX_ALLOC: return "Eliminate VectorBoxAllocate"; - case PHASE_PHASEIDEAL_BEFORE_EA: return "PhaseIdealLoop before EA"; - case PHASE_ITER_GVN_AFTER_VECTOR: return "Iter GVN after vector box elimination"; - case PHASE_ITER_GVN_BEFORE_EA: return "Iter GVN before EA"; - case PHASE_ITER_GVN_AFTER_EA: return "Iter GVN after EA"; - case PHASE_ITER_GVN_AFTER_ELIMINATION: return "Iter GVN after eliminating allocations and locks"; - case PHASE_PHASEIDEALLOOP1: return "PhaseIdealLoop 1"; - case PHASE_PHASEIDEALLOOP2: return "PhaseIdealLoop 2"; - case PHASE_PHASEIDEALLOOP3: return "PhaseIdealLoop 3"; - case PHASE_CCP1: return "PhaseCCP 1"; - case PHASE_ITER_GVN2: return "Iter GVN 2"; - case PHASE_PHASEIDEALLOOP_ITERATIONS: return "PhaseIdealLoop iterations"; - case PHASE_OPTIMIZE_FINISHED: return "Optimize finished"; - case PHASE_GLOBAL_CODE_MOTION: return "Global code motion"; - case PHASE_FINAL_CODE: return "Final Code"; - case PHASE_AFTER_EA: return "After Escape Analysis"; - case PHASE_BEFORE_CLOOPS: return "Before CountedLoop"; - case PHASE_AFTER_CLOOPS: return "After CountedLoop"; - case PHASE_BEFORE_BEAUTIFY_LOOPS: return "Before beautify loops"; - case PHASE_AFTER_BEAUTIFY_LOOPS: return "After beautify loops"; - case PHASE_BEFORE_MATCHING: return "Before matching"; - case PHASE_MATCHING: return "After matching"; - case PHASE_INCREMENTAL_INLINE: return "Incremental Inline"; - case PHASE_INCREMENTAL_INLINE_STEP: return "Incremental Inline Step"; - case PHASE_INCREMENTAL_INLINE_CLEANUP: return "Incremental Inline Cleanup"; - case PHASE_INCREMENTAL_BOXING_INLINE: return "Incremental Boxing Inline"; - case PHASE_CALL_CATCH_CLEANUP: return "Call catch cleanup"; - case PHASE_INSERT_BARRIER: return "Insert barrier"; - case PHASE_MACRO_EXPANSION: return "Macro expand"; - case PHASE_BARRIER_EXPANSION: return "Barrier expand"; - case PHASE_ADD_UNSAFE_BARRIER: return "Add barrier to unsafe op"; - case PHASE_END: return "End"; - case PHASE_FAILURE: return "Failure"; - case PHASE_DEBUG: return "Debug"; - default: - ShouldNotReachHere(); - return NULL; + static const char* to_name(CompilerPhaseType cpt) { + return phase_names[cpt]; + } + static const char* to_description(CompilerPhaseType cpt) { + return phase_descriptions[cpt]; + } + static int to_bitmask(CompilerPhaseType cpt) { + return (1 << cpt); + } +}; + +static CompilerPhaseType find_phase(const char* str) { + for (int i = 0; i < PHASE_NUM_TYPES; i++) { + if (strcmp(phase_names[i], str) == 0) { + return (CompilerPhaseType)i; + } + } + return PHASE_NONE; +} + +class PhaseNameIter { + private: + char* _token; + char* _saved_ptr; + char* _list; + + public: + PhaseNameIter(ccstrlist option) { + _list = (char*) canonicalize(option); + _saved_ptr = _list; + _token = strtok_r(_saved_ptr, ",", &_saved_ptr); + } + + ~PhaseNameIter() { + FREE_C_HEAP_ARRAY(char, _list); + } + + const char* operator*() const { return _token; } + + PhaseNameIter& operator++() { + _token = strtok_r(NULL, ",", &_saved_ptr); + return *this; + } + + ccstrlist canonicalize(ccstrlist option_value) { + char* canonicalized_list = NEW_C_HEAP_ARRAY(char, strlen(option_value) + 1, mtCompiler); + int i = 0; + char current; + while ((current = option_value[i]) != '\0') { + if (current == '\n' || current == ' ') { + canonicalized_list[i] = ','; + } else { + canonicalized_list[i] = current; + } + i++; } + canonicalized_list[i] = '\0'; + return canonicalized_list; + } +}; + +class PhaseNameValidator { + private: + bool _valid; + char* _bad; + + public: + PhaseNameValidator(ccstrlist option, uint64_t& mask) : _valid(true), _bad(nullptr) { + for (PhaseNameIter iter(option); *iter != NULL && _valid; ++iter) { + + CompilerPhaseType cpt = find_phase(*iter); + if (PHASE_NONE == cpt) { + const size_t len = MIN2(strlen(*iter), 63) + 1; // cap len to a value we know is enough for all phase descriptions + _bad = NEW_C_HEAP_ARRAY(char, len, mtCompiler); + // strncpy always writes len characters. If the source string is shorter, the function fills the remaining bytes with NULLs. + strncpy(_bad, *iter, len); + _valid = false; + } else { + assert(cpt < 64, "out of bounds"); + mask |= CompilerPhaseTypeHelper::to_bitmask(cpt); + } + } + } + + ~PhaseNameValidator() { + if (_bad != NULL) { + FREE_C_HEAP_ARRAY(char, _bad); + } + } + + bool is_valid() const { + return _valid; + } + + const char* what() const { + return _bad; } }; diff --git a/test/hotspot/jtreg/compiler/oracle/PrintIdealPhaseTest.java b/test/hotspot/jtreg/compiler/oracle/PrintIdealPhaseTest.java new file mode 100644 index 00000000000..f07d7264482 --- /dev/null +++ b/test/hotspot/jtreg/compiler/oracle/PrintIdealPhaseTest.java @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2022, 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 PrintIdealPhaseTest + * @summary Checks that -XX:CompileCommand=PrintIdealPhase,... works + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * @requires vm.debug == true & vm.compiler2.enabled + * @run driver compiler.oracle.PrintIdealPhaseTest + */ + +package compiler.oracle; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import jdk.test.lib.Asserts; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +public class PrintIdealPhaseTest { + + public static void main(String[] args) throws Exception { + new PrintIdealPhaseTest(); + } + + PrintIdealPhaseTest() throws Exception { + // The Phases specified here will be exchanged for the enum Phase in compiler.lib.ir_framework when it's done + + // Test -XX:CompileCommand=PrintIdealPhase,*::test,CCP1 + List expectedPhases = new ArrayList(); + expectedPhases.add("CCP1"); + runTest("CCP1", expectedPhases, "hotspot_log_1.log", true); + runTest("FISH", expectedPhases, "hotspot_log_1f.log", false); + + // Test -XX:CompileCommand=PrintIdealPhase,*::test,MATCHING + expectedPhases.clear(); + expectedPhases.add("MATCHING"); + runTest("MATCHING", expectedPhases, "hotspot_log_2.log", true); + + // Test -XX:CompileCommand=PrintIdealPhase,*::test,CCP_1,AFTER_MATCHING + expectedPhases.add("CCP1"); + runTest("MATCHING,CCP1", expectedPhases, "hotspot_log_3.log", true); + } + + private void runTest(String cmdPhases, List expectedPhases, String logFile, boolean valid) throws Exception { + List options = new ArrayList(); + options.add("-Xbatch"); + options.add("-XX:+PrintCompilation"); + options.add("-XX:LogFile="+logFile); + options.add("-XX:+IgnoreUnrecognizedVMOptions"); + options.add("-XX:CompileCommand=PrintIdealPhase," + getTestClass() + "::test," + cmdPhases); + options.add(getTestClass()); + + OutputAnalyzer oa = ProcessTools.executeTestJvm(options); + if (valid) { + oa.shouldHaveExitValue(0) + .shouldContain("CompileCommand: PrintIdealPhase compiler/oracle/PrintIdealPhaseTest$TestMain.test const char* PrintIdealPhase = '"+cmdPhases.replace(',', ' ')+"'") + .shouldNotContain("CompileCommand: An error occurred during parsing") + .shouldNotContain("Error: Unrecognized phase name in PrintIdealPhase:") + .shouldNotContain("# A fatal error has been detected by the Java Runtime Environment"); + + // Check that all the expected phases matches what can be found in the compilation log file + HashSet loggedPhases = parseLogFile(logFile); + System.out.println("Logged phases:"); + for (String loggedPhase : loggedPhases) { + System.out.println("loggedPhase: "+ loggedPhase); + } + for (String expectedPhase : expectedPhases) { + System.out.println("Looking for phase: " + expectedPhase); + + Asserts.assertTrue(loggedPhases.contains(expectedPhase), "Must find specified phase: " + expectedPhase); + loggedPhases.remove(expectedPhase); + } + Asserts.assertTrue(loggedPhases.isEmpty(), "Expect no other phases"); + } else { + // Check that we don't pass even though bad phase names where given + oa.shouldHaveExitValue(0) + .shouldContain("CompileCommand: An error occurred during parsing") + .shouldContain("Error: Unrecognized phase name in PrintIdealPhase:"); + } + } + + private HashSet parseLogFile(String logFile) { + String printIdealTag = " phasesFound = new HashSet<>(); + + try (var br = Files.newBufferedReader(Paths.get(logFile))) { + String line; + while ((line = br.readLine()) != null) { + if (line.startsWith(printIdealTag)) { + Matcher matcher = compilePhasePattern.matcher(line); + if (matcher.find()) { + phasesFound.add(matcher.group(1)); + } else { + throw new Error("Failed to match compile_phase in file: " + logFile); + } + } + } + } catch (IOException e) { + throw new Error("Failed to read " + logFile + " data: " + e, e); + } + return phasesFound; + } + + // Test class that is invoked by the sub process + public String getTestClass() { + return TestMain.class.getName(); + } + + public static class TestMain { + public static void main(String[] args) { + for (int i = 0; i < 20_000; i++) { + test(i); + } + } + + static void test(int i) { + if ((i % 1000) == 0) { + System.out.println("Hello World!"); + } + } + } +} -- GitLab From 1ef45c5bbdeb4e1ca65c6d8f3ac1568a6951f3a7 Mon Sep 17 00:00:00 2001 From: Roland Westrelin Date: Mon, 14 Feb 2022 08:35:53 +0000 Subject: [PATCH 486/564] =?UTF-8?q?8280799:=20=D0=A12:=20assert(false)=20f?= =?UTF-8?q?ailed:=20cyclic=20dependency=20prevents=20range=20check=20elimi?= =?UTF-8?q?nation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: thartmann, kvn --- src/hotspot/share/opto/loopnode.cpp | 59 ++-- src/hotspot/share/opto/split_if.cpp | 18 ++ .../TestPredicateInputBelowLoopPredicate.java | 268 ++++++++++++++++++ 3 files changed, 319 insertions(+), 26 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/loopopts/TestPredicateInputBelowLoopPredicate.java diff --git a/src/hotspot/share/opto/loopnode.cpp b/src/hotspot/share/opto/loopnode.cpp index e2b01f61d49..ceb2327edb5 100644 --- a/src/hotspot/share/opto/loopnode.cpp +++ b/src/hotspot/share/opto/loopnode.cpp @@ -5725,38 +5725,45 @@ void PhaseIdealLoop::build_loop_late_post_work(Node *n, bool pinned) { } assert(early == legal || legal != C->root(), "bad dominance of inputs"); + if (least != early) { + // Move the node above predicates as far up as possible so a + // following pass of loop predication doesn't hoist a predicate + // that depends on it above that node. + Node* new_ctrl = least; + for (;;) { + if (!new_ctrl->is_Proj()) { + break; + } + CallStaticJavaNode* call = new_ctrl->as_Proj()->is_uncommon_trap_if_pattern(Deoptimization::Reason_none); + if (call == NULL) { + break; + } + int req = call->uncommon_trap_request(); + Deoptimization::DeoptReason trap_reason = Deoptimization::trap_request_reason(req); + if (trap_reason != Deoptimization::Reason_loop_limit_check && + trap_reason != Deoptimization::Reason_predicate && + trap_reason != Deoptimization::Reason_profile_predicate) { + break; + } + Node* c = new_ctrl->in(0)->in(0); + if (is_dominator(c, early) && c != early) { + break; + } + new_ctrl = c; + } + least = new_ctrl; + } // Try not to place code on a loop entry projection // which can inhibit range check elimination. if (least != early) { Node* ctrl_out = least->unique_ctrl_out(); if (ctrl_out && ctrl_out->is_Loop() && - least == ctrl_out->in(LoopNode::EntryControl)) { - // Move the node above predicates as far up as possible so a - // following pass of loop predication doesn't hoist a predicate - // that depends on it above that node. - Node* new_ctrl = least; - for (;;) { - if (!new_ctrl->is_Proj()) { - break; - } - CallStaticJavaNode* call = new_ctrl->as_Proj()->is_uncommon_trap_if_pattern(Deoptimization::Reason_none); - if (call == NULL) { - break; - } - int req = call->uncommon_trap_request(); - Deoptimization::DeoptReason trap_reason = Deoptimization::trap_request_reason(req); - if (trap_reason != Deoptimization::Reason_loop_limit_check && - trap_reason != Deoptimization::Reason_predicate && - trap_reason != Deoptimization::Reason_profile_predicate) { - break; - } - Node* c = new_ctrl->in(0)->in(0); - if (is_dominator(c, early) && c != early) { - break; - } - new_ctrl = c; + least == ctrl_out->in(LoopNode::EntryControl) && + (ctrl_out->is_CountedLoop() || ctrl_out->is_OuterStripMinedLoop())) { + Node* least_dom = idom(least); + if (get_loop(least_dom)->is_member(get_loop(least))) { + least = least_dom; } - least = new_ctrl; } } diff --git a/src/hotspot/share/opto/split_if.cpp b/src/hotspot/share/opto/split_if.cpp index 05babc625c6..f85f3996ca5 100644 --- a/src/hotspot/share/opto/split_if.cpp +++ b/src/hotspot/share/opto/split_if.cpp @@ -201,6 +201,24 @@ bool PhaseIdealLoop::split_up( Node *n, Node *blk1, Node *blk2 ) { return true; } } + if (n->Opcode() == Op_OpaqueLoopStride || n->Opcode() == Op_OpaqueLoopInit) { + Unique_Node_List wq; + wq.push(n); + for (uint i = 0; i < wq.size(); i++) { + Node* m = wq.at(i); + if (m->is_If()) { + assert(skeleton_predicate_has_opaque(m->as_If()), "opaque node not reachable from if?"); + Node* bol = clone_skeleton_predicate_bool(m, NULL, NULL, m->in(0)); + _igvn.replace_input_of(m, 1, bol); + } else { + assert(!m->is_CFG(), "not CFG expected"); + for (DUIterator_Fast jmax, j = m->fast_outs(jmax); j < jmax; j++) { + Node* u = m->fast_out(j); + wq.push(u); + } + } + } + } // See if splitting-up a Store. Any anti-dep loads must go up as // well. An anti-dep load might be in the wrong block, because in diff --git a/test/hotspot/jtreg/compiler/loopopts/TestPredicateInputBelowLoopPredicate.java b/test/hotspot/jtreg/compiler/loopopts/TestPredicateInputBelowLoopPredicate.java new file mode 100644 index 00000000000..8ffa476ff26 --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/TestPredicateInputBelowLoopPredicate.java @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2022, Red Hat, Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * bug 8280799 + * @summary С2: assert(false) failed: cyclic dependency prevents range check elimination + * @run main/othervm -XX:-BackgroundCompilation -XX:-UseCountedLoopSafepoints TestPredicateInputBelowLoopPredicate + */ + +public class TestPredicateInputBelowLoopPredicate { + private static final Object object = new Object(); + private static int fieldStop = 100; + private static int[] array = new int[200]; + private static int[] array2 = new int[200]; + private static int fieldStart = 0; + + public static void main(String[] args) { + for (int i = 0; i < 20_000; i++) { + test(true); + test(false); + } + } + + private static void test(boolean flag) { + if (array == null) { + } + int start = fieldStart; + int i = start; + for(;;) { + int j; + for (j = -10; j < 0; j++) { + } + int stop = fieldStop; + // bound check becomes candidate for predication once + // loop above is optimized out + array[stop - i + j] = 0; + + // A bunch of stuff to grow loop body size and prevent peeling: + array2[0] = 0; + array2[1] = 0; + array2[2] = 0; + array2[3] = 0; + array2[4] = 0; + array2[5] = 0; + array2[6] = 0; + array2[7] = 0; + array2[8] = 0; + array2[9] = 0; + array2[10] = 0; + array2[11] = 0; + array2[12] = 0; + array2[13] = 0; + array2[14] = 0; + array2[15] = 0; + array2[16] = 0; + array2[17] = 0; + array2[18] = 0; + array2[19] = 0; + array2[20] = 0; + array2[21] = 0; + array2[22] = 0; + array2[23] = 0; + array2[24] = 0; + array2[25] = 0; + array2[26] = 0; + array2[27] = 0; + array2[28] = 0; + array2[29] = 0; + array2[30] = 0; + array2[31] = 0; + array2[32] = 0; + array2[33] = 0; + array2[34] = 0; + array2[35] = 0; + array2[36] = 0; + array2[37] = 0; + array2[38] = 0; + array2[39] = 0; + array2[40] = 0; + array2[41] = 0; + array2[42] = 0; + array2[43] = 0; + array2[44] = 0; + array2[45] = 0; + array2[46] = 0; + array2[47] = 0; + array2[48] = 0; + array2[49] = 0; + array2[50] = 0; + array2[51] = 0; + array2[52] = 0; + array2[53] = 0; + array2[54] = 0; + array2[55] = 0; + array2[56] = 0; + array2[57] = 0; + array2[58] = 0; + array2[59] = 0; + array2[60] = 0; + array2[61] = 0; + array2[62] = 0; + array2[63] = 0; + array2[64] = 0; + array2[65] = 0; + array2[66] = 0; + array2[67] = 0; + array2[68] = 0; + array2[69] = 0; + array2[70] = 0; + array2[71] = 0; + array2[72] = 0; + array2[73] = 0; + array2[74] = 0; + array2[75] = 0; + array2[76] = 0; + array2[77] = 0; + array2[78] = 0; + array2[79] = 0; + array2[80] = 0; + array2[81] = 0; + array2[82] = 0; + array2[83] = 0; + array2[84] = 0; + array2[85] = 0; + array2[86] = 0; + array2[87] = 0; + array2[88] = 0; + array2[89] = 0; + array2[90] = 0; + array2[91] = 0; + array2[92] = 0; + array2[93] = 0; + array2[94] = 0; + array2[95] = 0; + array2[96] = 0; + array2[97] = 0; + array2[98] = 0; + array2[99] = 0; + + array2[100] = 0; + array2[101] = 0; + array2[102] = 0; + array2[103] = 0; + array2[104] = 0; + array2[105] = 0; + array2[106] = 0; + array2[107] = 0; + array2[108] = 0; + array2[109] = 0; + array2[110] = 0; + array2[111] = 0; + array2[112] = 0; + array2[113] = 0; + array2[114] = 0; + array2[115] = 0; + array2[116] = 0; + array2[117] = 0; + array2[118] = 0; + array2[119] = 0; + array2[120] = 0; + array2[121] = 0; + array2[122] = 0; + array2[123] = 0; + array2[124] = 0; + array2[125] = 0; + array2[126] = 0; + array2[127] = 0; + array2[128] = 0; + array2[129] = 0; + array2[130] = 0; + array2[131] = 0; + array2[132] = 0; + array2[133] = 0; + array2[134] = 0; + array2[135] = 0; + array2[136] = 0; + array2[137] = 0; + array2[138] = 0; + array2[139] = 0; + array2[140] = 0; + array2[141] = 0; + array2[142] = 0; + array2[143] = 0; + array2[144] = 0; + array2[145] = 0; + array2[146] = 0; + array2[147] = 0; + array2[148] = 0; + array2[149] = 0; + array2[150] = 0; + array2[151] = 0; + array2[152] = 0; + array2[153] = 0; + array2[154] = 0; + array2[155] = 0; + array2[156] = 0; + array2[157] = 0; + array2[158] = 0; + array2[159] = 0; + array2[160] = 0; + array2[161] = 0; + array2[162] = 0; + array2[163] = 0; + array2[164] = 0; + array2[165] = 0; + array2[166] = 0; + array2[167] = 0; + array2[168] = 0; + array2[169] = 0; + array2[170] = 0; + array2[171] = 0; + array2[172] = 0; + array2[173] = 0; + array2[174] = 0; + array2[175] = 0; + array2[176] = 0; + array2[177] = 0; + array2[178] = 0; + array2[179] = 0; + array2[180] = 0; + array2[181] = 0; + array2[182] = 0; + array2[183] = 0; + array2[184] = 0; + array2[185] = 0; + array2[186] = 0; + array2[187] = 0; + array2[188] = 0; + array2[189] = 0; + array2[190] = 0; + array2[191] = 0; + array2[192] = 0; + array2[193] = 0; + array2[194] = 0; + array2[195] = 0; + array2[196] = 0; + array2[197] = 0; + array2[198] = 0; + array2[199] = 0; + i++; + + if (i == stop) { // requires a loop limit predicate + break; + } + } + } +} -- GitLab From 46f522962f1b2bbb2513823821e332db1093994b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20Casta=C3=B1eda=20Lozano?= Date: Mon, 14 Feb 2022 08:37:31 +0000 Subject: [PATCH 487/564] 8281539: IGV: schedule approximation computes immediate dominators wrongly Replace custom dominator computation with one from the WALA libraries. Reviewed-by: neliasso, chagedorn --- .../ServerCompiler/pom.xml | 7 +- .../ServerCompilerScheduler.java | 173 ++---------------- src/utils/IdealGraphVisualizer/pom.xml | 3 +- 3 files changed, 26 insertions(+), 157 deletions(-) diff --git a/src/utils/IdealGraphVisualizer/ServerCompiler/pom.xml b/src/utils/IdealGraphVisualizer/ServerCompiler/pom.xml index b43145fa974..79209514ebc 100644 --- a/src/utils/IdealGraphVisualizer/ServerCompiler/pom.xml +++ b/src/utils/IdealGraphVisualizer/ServerCompiler/pom.xml @@ -1,6 +1,6 @@ server // client <--- 401 ---- server try (Socket s = ss.accept()) { - new MessageHeader().parseHeader(s.getInputStream()); + new HttpHeaderParser().parse(s.getInputStream()); s.getOutputStream().write(reply.getBytes("US-ASCII")); } @@ -171,10 +171,10 @@ public class NoNTLM { // client <--- 200 ---- server String auth; try (Socket s = ss.accept()) { - MessageHeader mh = new MessageHeader(); - mh.parseHeader(s.getInputStream()); + HttpHeaderParser mh = new HttpHeaderParser(); + mh.parse(s.getInputStream()); s.getOutputStream().write(OKAY.getBytes("US-ASCII")); - auth = mh.findValue("Authorization"); + auth = mh.getHeaderValue("Authorization").get(0); } // check Authorization header @@ -208,7 +208,7 @@ public class NoNTLM { // client ---- GET ---> server // client <--- 401 ---- client try (Socket s = ss.accept()) { - new MessageHeader().parseHeader(s.getInputStream()); + new HttpHeaderParser().parse(s.getInputStream()); s.getOutputStream().write(reply.getBytes("US-ASCII")); } diff --git a/test/jdk/sun/net/www/protocol/http/RetryUponTimeout.java b/test/jdk/sun/net/www/protocol/http/RetryUponTimeout.java index bfda1663259..b2214780c2e 100644 --- a/test/jdk/sun/net/www/protocol/http/RetryUponTimeout.java +++ b/test/jdk/sun/net/www/protocol/http/RetryUponTimeout.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,13 +26,13 @@ * @bug 4772077 * @library /test/lib * @summary using defaultReadTimeout appear to retry request upon timeout - * @modules java.base/sun.net.www */ import java.net.*; import java.io.*; + +import jdk.test.lib.net.HttpHeaderParser; import jdk.test.lib.net.URIBuilder; -import sun.net.www.*; public class RetryUponTimeout implements Runnable { // run server @@ -42,7 +42,7 @@ public class RetryUponTimeout implements Runnable { for (int i = 0; i < 2; i++) { socket = server.accept(); InputStream is = socket.getInputStream (); - MessageHeader header = new MessageHeader (is); + HttpHeaderParser header = new HttpHeaderParser (is); count++; } } catch (Exception ex) { diff --git a/test/jdk/sun/net/www/protocol/http/UserAgent.java b/test/jdk/sun/net/www/protocol/http/UserAgent.java index 7db84882488..40ff5d3106f 100644 --- a/test/jdk/sun/net/www/protocol/http/UserAgent.java +++ b/test/jdk/sun/net/www/protocol/http/UserAgent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 4512200 * @library /test/lib - * @modules java.base/sun.net.www * @run main/othervm -Dhttp.agent=foo UserAgent * @run main/othervm -Dhttp.agent=foo -Djava.net.preferIPv6Addresses=true UserAgent * @summary HTTP header "User-Agent" format incorrect @@ -34,8 +33,9 @@ import java.io.*; import java.util.*; import java.net.*; + +import jdk.test.lib.net.HttpHeaderParser; import jdk.test.lib.net.URIBuilder; -import sun.net.www.MessageHeader; class Server extends Thread { Server (ServerSocket server) { @@ -46,8 +46,8 @@ class Server extends Thread { String version = System.getProperty ("java.version"); String expected = "foo Java/"+version; Socket s = server.accept (); - MessageHeader header = new MessageHeader (s.getInputStream()); - String v = header.findValue ("User-Agent"); + HttpHeaderParser header = new HttpHeaderParser (s.getInputStream()); + String v = header.getHeaderValue ("User-Agent").get(0); if (!expected.equals (v)) { error ("Got unexpected User-Agent: " + v); } else { diff --git a/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/B6226610.java b/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/B6226610.java index ec75bcc3e11..9fca12c9958 100644 --- a/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/B6226610.java +++ b/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/B6226610.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2022, 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 6226610 6973030 * @summary HTTP tunnel connections send user headers to proxy - * @modules java.base/sun.net.www + * @library /test/lib * @run main/othervm B6226610 */ @@ -37,7 +37,9 @@ import java.io.*; import java.net.*; -import sun.net.www.MessageHeader; + +import jdk.test.lib.net.HttpHeaderParser; + public class B6226610 { static HeaderCheckerProxyTunnelServer proxy; @@ -138,21 +140,21 @@ class HeaderCheckerProxyTunnelServer extends Thread private void processRequests() throws IOException { InputStream in = clientSocket.getInputStream(); - MessageHeader mheader = new MessageHeader(in); - String statusLine = mheader.getValue(0); + HttpHeaderParser mheader = new HttpHeaderParser(in); + String statusLine = mheader.getRequestDetails(); if (statusLine.startsWith("CONNECT")) { // retrieve the host and port info from the status-line retrieveConnectInfo(statusLine); - if (mheader.findValue("X-TestHeader") != null) { + if (mheader.getHeaderValue("X-TestHeader") != null) { System.out.println("Proxy should not receive user defined headers for tunneled requests"); failed = true; } // 6973030 String value; - if ((value = mheader.findValue("Proxy-Connection")) == null || + if ((value = mheader.getHeaderValue("Proxy-Connection").get(0)) == null || !value.equals("keep-alive")) { System.out.println("Proxy-Connection:keep-alive not being sent"); failed = true; diff --git a/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/TunnelProxy.java b/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/TunnelProxy.java index 9573543fde1..979e8be9acd 100644 --- a/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/TunnelProxy.java +++ b/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/TunnelProxy.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2022, 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 @@ -45,7 +45,8 @@ import java.util.HashMap; import java.util.Iterator; import java.util.Set; -import sun.net.www.MessageHeader; +import jdk.test.lib.net.HttpHeaderParser; + public class TunnelProxy { @@ -261,7 +262,7 @@ public class TunnelProxy { try { InputStream is = new BufferedInputStream (new NioInputStream (chan)); String requestline = readLine (is); - MessageHeader mhead = new MessageHeader (is); + HttpHeaderParser mhead = new HttpHeaderParser (is); String[] req = requestline.split (" "); if (req.length < 2) { /* invalid request line */ diff --git a/test/lib/jdk/test/lib/net/HttpHeaderParser.java b/test/lib/jdk/test/lib/net/HttpHeaderParser.java new file mode 100644 index 00000000000..71b3a84fdaa --- /dev/null +++ b/test/lib/jdk/test/lib/net/HttpHeaderParser.java @@ -0,0 +1,390 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.net; + +import java.io.IOException; +import java.io.InputStream; +import java.net.ProtocolException; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import static java.util.Objects.requireNonNull; + +public class HttpHeaderParser { + private static final char CR = '\r'; + private static final char LF = '\n'; + private static final char HT = '\t'; + private static final char SP = ' '; + // ABNF primitives defined in RFC 7230 + private static boolean[] tchar = new boolean[256]; + private static boolean[] fieldvchar = new boolean[256]; + + static { + char[] allowedTokenChars = + ("!#$%&'*+-.^_`|~0123456789" + + "abcdefghijklmnopqrstuvwxyz" + + "ABCDEFGHIJKLMNOPQRSTUVWXYZ").toCharArray(); + for (char c : allowedTokenChars) { + tchar[c] = true; + } + for (char c = 0x21; c <= 0xFF; c++) { + fieldvchar[c] = true; + } + fieldvchar[0x7F] = false; // a little hole (DEL) in the range + } + + private StringBuilder sb = new StringBuilder(); + + private Map > headerMap = new LinkedHashMap<>(); + private List keyList = new ArrayList<>(); + private String requestOrStatusLine; + private int responseCode; + private boolean eof; + + + + enum State { INITIAL, + STATUS_OR_REQUEST_LINE, + STATUS_OR_REQUEST_LINE_FOUND_CR, + STATUS_OR_REQUEST_LINE_FOUND_LF, + STATUS_OR_REQUEST_LINE_END, + STATUS_OR_REQUEST_LINE_END_CR, + STATUS_OR_REQUEST_LINE_END_LF, + HEADER, + HEADER_FOUND_CR, + HEADER_FOUND_LF, + HEADER_FOUND_CR_LF, + HEADER_FOUND_CR_LF_CR, + FINISHED } + + private HttpHeaderParser.State state = HttpHeaderParser.State.INITIAL; + + public HttpHeaderParser() { + } + + + public HttpHeaderParser(InputStream is) throws IOException, ProtocolException { + parse(is); + } + + public Map> getHeaderMap() { + return headerMap; + } + + public List getHeaderValue(String key) { + if(headerMap.containsKey(key.toLowerCase(Locale.ROOT))) { + return headerMap.get(key.toLowerCase(Locale.ROOT)); + } + return null; + } + public List getValue(int id) { + String key = keyList.get(id); + return headerMap.get(key); + } + + public String getRequestDetails() { + return requestOrStatusLine; + } + + /** + * Parses HTTP/1.X status-line or request-line and headers from the given input stream. + * @param input Containing the input stream of bytes representing request or response header data + * @return true if the end of the headers block has been reached + */ + public boolean parse(InputStream input) throws IOException { + requireNonNull(input, "null input"); + while (canContinueParsing()) { + switch (state) { + case INITIAL -> state = HttpHeaderParser.State.STATUS_OR_REQUEST_LINE; + case STATUS_OR_REQUEST_LINE -> readResumeStatusLine(input); + case STATUS_OR_REQUEST_LINE_FOUND_CR, STATUS_OR_REQUEST_LINE_FOUND_LF -> readStatusLineFeed(input); + case STATUS_OR_REQUEST_LINE_END -> maybeStartHeaders(input); + case STATUS_OR_REQUEST_LINE_END_CR, STATUS_OR_REQUEST_LINE_END_LF -> maybeEndHeaders(input); + case HEADER -> readResumeHeader(input); + case HEADER_FOUND_CR, HEADER_FOUND_LF -> resumeOrLF(input); + case HEADER_FOUND_CR_LF -> resumeOrSecondCR(input); + case HEADER_FOUND_CR_LF_CR -> resumeOrEndHeaders(input); + default -> throw new InternalError("Unexpected state: " + state); + } + } + return state == HttpHeaderParser.State.FINISHED; + } + + private boolean canContinueParsing() { + // some states don't require any input to transition + // to the next state. + return switch (state) { + case FINISHED -> false; + case STATUS_OR_REQUEST_LINE_FOUND_LF, STATUS_OR_REQUEST_LINE_END_LF, HEADER_FOUND_LF -> true; + default -> !eof; + }; + } + + /** + * Returns a character (char) corresponding to the next byte in the + * input, interpreted as an ISO-8859-1 encoded character. + *

    + * The ISO-8859-1 encoding is a 8-bit character coding that + * corresponds to the first 256 Unicode characters - from U+0000 to + * U+00FF. UTF-16 is backward compatible with ISO-8859-1 - which + * means each byte in the input should be interpreted as an unsigned + * value from [0, 255] representing the character code. + * + * @param input a {@code InputStream} containing input stream of Bytes. + * @return the next byte in the input, interpreted as an ISO-8859-1 + * encoded char + * @throws IOException + * if an I/O error occurs. + */ + private char get(InputStream input) throws IOException { + int c = input.read(); + if(c < 0) + eof = true; + return (char)(c & 0xFF); + } + + private void readResumeStatusLine(InputStream input) throws IOException { + char c; + while ((c = get(input)) != CR && !eof) { + if (c == LF) break; + sb.append(c); + } + if (c == CR) { + state = HttpHeaderParser.State.STATUS_OR_REQUEST_LINE_FOUND_CR; + } else if (c == LF) { + state = HttpHeaderParser.State.STATUS_OR_REQUEST_LINE_FOUND_LF; + } + } + + private void readStatusLineFeed(InputStream input) throws IOException { + char c = state == HttpHeaderParser.State.STATUS_OR_REQUEST_LINE_FOUND_LF ? LF : get(input); + if (c != LF) { + throw protocolException("Bad trailing char, \"%s\", when parsing status line, \"%s\"", + c, sb.toString()); + } + requestOrStatusLine = sb.toString(); + sb = new StringBuilder(); + if (!requestOrStatusLine.startsWith("HTTP/1.")) { + if(!requestOrStatusLine.startsWith("GET") && !requestOrStatusLine.startsWith("POST") && + !requestOrStatusLine.startsWith("PUT") && !requestOrStatusLine.startsWith("DELETE") && + !requestOrStatusLine.startsWith("OPTIONS") && !requestOrStatusLine.startsWith("HEAD") && + !requestOrStatusLine.startsWith("PATCH") && !requestOrStatusLine.startsWith("CONNECT")) { + throw protocolException("Invalid request Or Status line: \"%s\"", requestOrStatusLine); + } else { //This is request + System.out.println("Request is :"+requestOrStatusLine); + } + } else { //This is response + if (requestOrStatusLine.length() < 12) { + throw protocolException("Invalid status line: \"%s\"", requestOrStatusLine); + } + try { + responseCode = Integer.parseInt(requestOrStatusLine.substring(9, 12)); + } catch (NumberFormatException nfe) { + throw protocolException("Invalid status line: \"%s\"", requestOrStatusLine); + } + // response code expected to be a 3-digit integer (RFC-2616, section 6.1.1) + if (responseCode < 100) { + throw protocolException("Invalid status line: \"%s\"", requestOrStatusLine); + } + } + state = HttpHeaderParser.State.STATUS_OR_REQUEST_LINE_END; + } + + private void maybeStartHeaders(InputStream input) throws IOException { + assert state == HttpHeaderParser.State.STATUS_OR_REQUEST_LINE_END; + assert sb.length() == 0; + char c = get(input); + if(!eof) { + if (c == CR) { + state = HttpHeaderParser.State.STATUS_OR_REQUEST_LINE_END_CR; + } else if (c == LF) { + state = HttpHeaderParser.State.STATUS_OR_REQUEST_LINE_END_LF; + } else { + sb.append(c); + state = HttpHeaderParser.State.HEADER; + } + } + } + + private void maybeEndHeaders(InputStream input) throws IOException { + assert state == HttpHeaderParser.State.STATUS_OR_REQUEST_LINE_END_CR || state == HttpHeaderParser.State.STATUS_OR_REQUEST_LINE_END_LF; + assert sb.length() == 0; + char c = state == HttpHeaderParser.State.STATUS_OR_REQUEST_LINE_END_LF ? LF : get(input); + if (c == LF) { + state = HttpHeaderParser.State.FINISHED; // no headers + } else { + throw protocolException("Unexpected \"%s\", after status line CR", c); + } + } + + private void readResumeHeader(InputStream input) throws IOException { + assert state == HttpHeaderParser.State.HEADER; + assert !eof; + char c = get(input); + while (!eof) { + if (c == CR) { + state = HttpHeaderParser.State.HEADER_FOUND_CR; + break; + } else if (c == LF) { + state = HttpHeaderParser.State.HEADER_FOUND_LF; + break; + } + if (c == HT) + c = SP; + sb.append(c); + c = get(input); + } + } + + private void addHeaderFromString(String headerString) throws ProtocolException { + assert sb.length() == 0; + int idx = headerString.indexOf(':'); + if (idx == -1) + return; + String name = headerString.substring(0, idx); + + // compatibility with HttpURLConnection; + if (name.isEmpty()) return; + + if (!isValidName(name)) { + throw protocolException("Invalid header name \"%s\"", name); + } + String value = headerString.substring(idx + 1).trim(); + if (!isValidValue(value)) { + throw protocolException("Invalid header value \"%s: %s\"", name, value); + } + + keyList.add(name); + headerMap.computeIfAbsent(name.toLowerCase(Locale.US), + k -> new ArrayList<>()).add(value); + } + + private void resumeOrLF(InputStream input) throws IOException { + assert state == HttpHeaderParser.State.HEADER_FOUND_CR || state == HttpHeaderParser.State.HEADER_FOUND_LF; + char c = state == HttpHeaderParser.State.HEADER_FOUND_LF ? LF : get(input); + if (!eof) { + if (c == LF) { + state = HttpHeaderParser.State.HEADER_FOUND_CR_LF; + } else if (c == SP || c == HT) { + sb.append(SP); // parity with MessageHeaders + state = HttpHeaderParser.State.HEADER; + } else { + sb = new StringBuilder(); + sb.append(c); + state = HttpHeaderParser.State.HEADER; + } + } + } + + private void resumeOrSecondCR(InputStream input) throws IOException { + assert state == HttpHeaderParser.State.HEADER_FOUND_CR_LF; + char c = get(input); + if (!eof) { + if (c == CR || c == LF) { + if (sb.length() > 0) { + // no continuation line - flush + // previous header value. + String headerString = sb.toString(); + sb = new StringBuilder(); + addHeaderFromString(headerString); + } + if (c == CR) { + state = HttpHeaderParser.State.HEADER_FOUND_CR_LF_CR; + } else { + state = HttpHeaderParser.State.FINISHED; + } + } else if (c == SP || c == HT) { + assert sb.length() != 0; + sb.append(SP); // continuation line + state = HttpHeaderParser.State.HEADER; + } else { + if (sb.length() > 0) { + // no continuation line - flush + // previous header value. + String headerString = sb.toString(); + sb = new StringBuilder(); + addHeaderFromString(headerString); + } + sb.append(c); + state = HttpHeaderParser.State.HEADER; + } + } + } + + private void resumeOrEndHeaders(InputStream input) throws IOException { + assert state == HttpHeaderParser.State.HEADER_FOUND_CR_LF_CR; + char c = get(input); + if (!eof) { + if (c == LF) { + state = HttpHeaderParser.State.FINISHED; + } else { + throw protocolException("Unexpected \"%s\", after CR LF CR", c); + } + } + } + + private ProtocolException protocolException(String format, Object ... args) { + return new ProtocolException(String.format(format, args)); + } + + /* + * Validates a RFC 7230 field-name. + */ + public boolean isValidName(String token) { + for (int i = 0; i < token.length(); i++) { + char c = token.charAt(i); + if (c > 255 || !tchar[c]) { + return false; + } + } + return !token.isEmpty(); + } + + /* + * Validates a RFC 7230 field-value. + * + * "Obsolete line folding" rule + * + * obs-fold = CRLF 1*( SP / HTAB ) + * + * is not permitted! + */ + public boolean isValidValue(String token) { + for (int i = 0; i < token.length(); i++) { + char c = token.charAt(i); + if (c > 255) { + return false; + } + if (c == ' ' || c == '\t') { + continue; + } else if (!fieldvchar[c]) { + return false; // forbidden byte + } + } + return true; + } +} -- GitLab From 9b74c3f2e74a4efdec1c1488e96ab5939a408df0 Mon Sep 17 00:00:00 2001 From: Naoto Sato Date: Wed, 16 Feb 2022 16:54:53 +0000 Subject: [PATCH 525/564] 8176706: Additional Date-Time Formats Reviewed-by: joehw, rriggs --- .../build/tools/cldrconverter/Bundle.java | 82 ++++-- .../tools/cldrconverter/CLDRConverter.java | 20 +- .../tools/cldrconverter/LDMLParseHandler.java | 12 +- .../SupplementDataParseHandler.java | 52 ++-- .../java/time/format/DateTimeFormatter.java | 54 +++- .../time/format/DateTimeFormatterBuilder.java | 204 ++++++++++++--- .../spi/JavaTimeDateTimePatternProvider.java | 27 +- .../provider/JavaTimeDateTimePatternImpl.java | 22 +- .../util/locale/provider/LocaleResources.java | 233 +++++++++++++++++- .../time/format/Skeletons_en_US.properties | 51 ++++ .../java/time/format/Skeletons_ja.properties | 43 ++++ .../time/format/TestLocalizedPattern.java | 105 ++++++++ 12 files changed, 809 insertions(+), 96 deletions(-) create mode 100644 test/jdk/java/time/test/java/time/format/Skeletons_en_US.properties create mode 100644 test/jdk/java/time/test/java/time/format/Skeletons_ja.properties create mode 100644 test/jdk/java/time/test/java/time/format/TestLocalizedPattern.java diff --git a/make/jdk/src/classes/build/tools/cldrconverter/Bundle.java b/make/jdk/src/classes/build/tools/cldrconverter/Bundle.java index 9f262fa0106..952e28fd43b 100644 --- a/make/jdk/src/classes/build/tools/cldrconverter/Bundle.java +++ b/make/jdk/src/classes/build/tools/cldrconverter/Bundle.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,9 @@ package build.tools.cldrconverter; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; import java.util.EnumSet; @@ -34,6 +37,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; +import java.util.stream.Collectors; import java.util.stream.IntStream; class Bundle { @@ -47,21 +51,21 @@ class Bundle { FORMATDATA); } - private final static Map bundles = new HashMap<>(); + private static final Map bundles = new HashMap<>(); - private final static String[] NUMBER_PATTERN_KEYS = { + private static final String[] NUMBER_PATTERN_KEYS = { "NumberPatterns/decimal", "NumberPatterns/currency", "NumberPatterns/percent", "NumberPatterns/accounting" }; - private final static String[] COMPACT_NUMBER_PATTERN_KEYS = { - "short.CompactNumberPatterns", - "long.CompactNumberPatterns" + private static final String[] COMPACT_NUMBER_PATTERN_KEYS = { + "short.CompactNumberPatterns", + "long.CompactNumberPatterns" }; - private final static String[] NUMBER_ELEMENT_KEYS = { + private static final String[] NUMBER_ELEMENT_KEYS = { "NumberElements/decimal", "NumberElements/group", "NumberElements/list", @@ -77,41 +81,45 @@ class Bundle { "NumberElements/currencyGroup", }; - private final static String[] TIME_PATTERN_KEYS = { + private static final String[] TIME_PATTERN_KEYS = { "DateTimePatterns/full-time", "DateTimePatterns/long-time", "DateTimePatterns/medium-time", "DateTimePatterns/short-time", }; - private final static String[] DATE_PATTERN_KEYS = { + private static final String[] DATE_PATTERN_KEYS = { "DateTimePatterns/full-date", "DateTimePatterns/long-date", "DateTimePatterns/medium-date", "DateTimePatterns/short-date", }; - private final static String[] DATETIME_PATTERN_KEYS = { + private static final String[] DATETIME_PATTERN_KEYS = { "DateTimePatterns/full-dateTime", "DateTimePatterns/long-dateTime", "DateTimePatterns/medium-dateTime", "DateTimePatterns/short-dateTime", }; - private final static String[] ERA_KEYS = { + private static final String[] ERA_KEYS = { "long.Eras", "Eras", "narrow.Eras" }; + // DateFormatItem prefix + static final String DATEFORMATITEM_KEY_PREFIX = "DateFormatItem."; + static final String DATEFORMATITEM_INPUT_REGIONS_PREFIX = "DateFormatItemInputRegions."; + // Keys for individual time zone names - private final static String TZ_GEN_LONG_KEY = "timezone.displayname.generic.long"; - private final static String TZ_GEN_SHORT_KEY = "timezone.displayname.generic.short"; - private final static String TZ_STD_LONG_KEY = "timezone.displayname.standard.long"; - private final static String TZ_STD_SHORT_KEY = "timezone.displayname.standard.short"; - private final static String TZ_DST_LONG_KEY = "timezone.displayname.daylight.long"; - private final static String TZ_DST_SHORT_KEY = "timezone.displayname.daylight.short"; - private final static String[] ZONE_NAME_KEYS = { + private static final String TZ_GEN_LONG_KEY = "timezone.displayname.generic.long"; + private static final String TZ_GEN_SHORT_KEY = "timezone.displayname.generic.short"; + private static final String TZ_STD_LONG_KEY = "timezone.displayname.standard.long"; + private static final String TZ_STD_SHORT_KEY = "timezone.displayname.standard.short"; + private static final String TZ_DST_LONG_KEY = "timezone.displayname.daylight.long"; + private static final String TZ_DST_SHORT_KEY = "timezone.displayname.daylight.short"; + private static final String[] ZONE_NAME_KEYS = { TZ_STD_LONG_KEY, TZ_STD_SHORT_KEY, TZ_DST_LONG_KEY, @@ -262,7 +270,7 @@ class Bundle { CLDRConverter.handleAliases(myMap); // another hack: parentsMap is not used for date-time resources. - if ("root".equals(id)) { + if (isRoot()) { parentsMap = null; } @@ -287,6 +295,14 @@ class Bundle { handleDateTimeFormatPatterns(TIME_PATTERN_KEYS, myMap, parentsMap, calendarType, "TimePatterns"); handleDateTimeFormatPatterns(DATE_PATTERN_KEYS, myMap, parentsMap, calendarType, "DatePatterns"); handleDateTimeFormatPatterns(DATETIME_PATTERN_KEYS, myMap, parentsMap, calendarType, "DateTimePatterns"); + + // Skeleton + handleSkeletonPatterns(myMap, calendarType); + } + + // Skeleton input regions + if (isRoot()) { + skeletonInputRegions(myMap); } // First, weed out any empty timezone or metazone names from myMap. @@ -647,8 +663,9 @@ class Bundle { private void convertDateTimePatternLetter(CalendarType calendarType, char cldrLetter, int count, StringBuilder sb) { switch (cldrLetter) { case 'u': - // Change cldr letter 'u' to 'y', as 'u' is interpreted as - // "Extended year (numeric)" in CLDR/LDML, + case 'U': + // Change cldr letter 'u'/'U' to 'y', as 'u' is interpreted as + // "Extended year (numeric)", and 'U' as "Cyclic year" in CLDR/LDML, // which is not supported in SimpleDateFormat and // j.t.f.DateTimeFormatter, so it is replaced with 'y' // as the best approximation @@ -742,6 +759,19 @@ class Bundle { return false; } + private void handleSkeletonPatterns(Map myMap, CalendarType calendarType) { + String calendarPrefix = calendarType.keyElementName(); + myMap.putAll(myMap.entrySet().stream() + .filter(e -> e.getKey().startsWith(Bundle.DATEFORMATITEM_KEY_PREFIX)) + .collect(Collectors.toMap( + e -> calendarPrefix + e.getKey(), + e -> translateDateFormatLetters(calendarType, + (String)e.getValue(), + this::convertDateTimePatternLetter) + )) + ); + } + @FunctionalInterface private interface ConvertDateTimeLetters { void convert(CalendarType calendarType, char cldrLetter, int count, StringBuilder sb); @@ -790,4 +820,14 @@ class Bundle { } return numArray; } + + private static void skeletonInputRegions(Map myMap) { + myMap.putAll(myMap.entrySet().stream() + .filter(e -> e.getKey().startsWith(Bundle.DATEFORMATITEM_INPUT_REGIONS_PREFIX)) + .collect(Collectors.toMap( + e -> e.getKey(), + e -> ((String)e.getValue()).trim() + )) + ); + } } diff --git a/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java b/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java index 267f93e733b..abf1be64306 100644 --- a/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java +++ b/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022, 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 @@ -847,20 +847,19 @@ public class CLDRConverter { "DateTimePatternChars", "PluralRules", "DayPeriodRules", + "DateFormatItem", }; private static Map extractFormatData(Map map, String id) { Map formatData = new LinkedHashMap<>(); for (CalendarType calendarType : CalendarType.values()) { - if (calendarType == CalendarType.GENERIC) { - continue; - } String prefix = calendarType.keyElementName(); - for (String element : FORMAT_DATA_ELEMENTS) { - String key = prefix + element; - copyIfPresent(map, "java.time." + key, formatData); - copyIfPresent(map, key, formatData); - } + Arrays.stream(FORMAT_DATA_ELEMENTS) + .flatMap(elem -> map.keySet().stream().filter(k -> k.startsWith(prefix + elem))) + .forEach(key -> { + copyIfPresent(map, "java.time." + key, formatData); + copyIfPresent(map, key, formatData); + }); } for (String key : map.keySet()) { @@ -868,9 +867,6 @@ public class CLDRConverter { if (key.startsWith(CLDRConverter.LOCALE_TYPE_PREFIX_CA)) { String type = key.substring(CLDRConverter.LOCALE_TYPE_PREFIX_CA.length()); for (CalendarType calendarType : CalendarType.values()) { - if (calendarType == CalendarType.GENERIC) { - continue; - } if (type.equals(calendarType.lname())) { Object value = map.get(key); String dataKey = key.replace(LOCALE_TYPE_PREFIX_CA, diff --git a/make/jdk/src/classes/build/tools/cldrconverter/LDMLParseHandler.java b/make/jdk/src/classes/build/tools/cldrconverter/LDMLParseHandler.java index 745796d96cf..668c187c383 100644 --- a/make/jdk/src/classes/build/tools/cldrconverter/LDMLParseHandler.java +++ b/make/jdk/src/classes/build/tools/cldrconverter/LDMLParseHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022, 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 @@ -756,6 +756,14 @@ class LDMLParseHandler extends AbstractLDMLHandler { pushStringEntry(qName, attributes, prefix + "DateTimePatterns/" + attributes.getValue("type") + "-dateTime"); } break; + case "dateFormatItem": + { + // for FormatData + String prefix = (currentCalendarType == null) ? "" : currentCalendarType.keyElementName(); + pushStringEntry(qName, attributes, + prefix + Bundle.DATEFORMATITEM_KEY_PREFIX + attributes.getValue("id")); + } + break; case "localizedPatternChars": { // for FormatData @@ -1113,7 +1121,7 @@ class LDMLParseHandler extends AbstractLDMLHandler { if (id.equals("root") && key.startsWith("MonthNames")) { value = new DateFormatSymbols(Locale.US).getShortMonths(); } - return put(entry.getKey(), value); + return put(key, value); } } return null; diff --git a/make/jdk/src/classes/build/tools/cldrconverter/SupplementDataParseHandler.java b/make/jdk/src/classes/build/tools/cldrconverter/SupplementDataParseHandler.java index fdc8a977766..11547ccb38e 100644 --- a/make/jdk/src/classes/build/tools/cldrconverter/SupplementDataParseHandler.java +++ b/make/jdk/src/classes/build/tools/cldrconverter/SupplementDataParseHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,8 +27,12 @@ package build.tools.cldrconverter; import java.io.File; import java.io.IOException; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; +import java.util.SortedSet; +import java.util.TreeSet; +import java.util.stream.Collectors; import org.xml.sax.Attributes; import org.xml.sax.InputSource; import org.xml.sax.SAXException; @@ -62,10 +66,15 @@ class SupplementDataParseHandler extends AbstractLDMLHandler { // parentLocale.=(" ")+ private final Map parentLocalesMap; + // Input Skeleton map for "preferred" and "allowed" + // Map<"preferred"/"allowed", Map<"skeleton", SortedSet<"regions">>> + private final Map>> inputSkeletonMap; + SupplementDataParseHandler() { firstDayMap = new HashMap<>(); minDaysMap = new HashMap<>(); parentLocalesMap = new HashMap<>(); + inputSkeletonMap = new HashMap<>(); } /** @@ -76,22 +85,25 @@ class SupplementDataParseHandler extends AbstractLDMLHandler { * It returns null when there is no firstDay and minDays for the country * although this should not happen because supplementalData.xml includes * default value for the world ("001") for firstDay and minDays. + * + * This method also returns Maps for "preferred" and "allowed" skeletons, + * which are grouped by regions. E.g, "h:XX YY ZZ;" which means 'h' pattern + * is "preferred"/"allowed" in "XX", "YY", and "ZZ" regions. */ Map getData(String id) { Map values = new HashMap<>(); if ("root".equals(id)) { - parentLocalesMap.keySet().forEach(key -> { - values.put(CLDRConverter.PARENT_LOCALE_PREFIX+key, - parentLocalesMap.get(key)); - }); - firstDayMap.keySet().forEach(key -> { - values.put(CLDRConverter.CALENDAR_FIRSTDAY_PREFIX+firstDayMap.get(key), - key); - }); - minDaysMap.keySet().forEach(key -> { - values.put(CLDRConverter.CALENDAR_MINDAYS_PREFIX+minDaysMap.get(key), - key); - }); + parentLocalesMap.forEach((k, v) -> values.put(CLDRConverter.PARENT_LOCALE_PREFIX + k, v)); + firstDayMap.forEach((k, v) -> values.put(CLDRConverter.CALENDAR_FIRSTDAY_PREFIX + v, k)); + minDaysMap.forEach((k, v) -> values.put(CLDRConverter.CALENDAR_MINDAYS_PREFIX + v, k)); + inputSkeletonMap.get("preferred").forEach((k, v) -> + values.merge(Bundle.DATEFORMATITEM_INPUT_REGIONS_PREFIX + "preferred", + k + ":" + v.stream().collect(Collectors.joining(" ")) + ";", + (old, newVal) -> old + (String)newVal)); + inputSkeletonMap.get("allowed").forEach((k, v) -> + values.merge(Bundle.DATEFORMATITEM_INPUT_REGIONS_PREFIX + "allowed", + k + ":" + v.stream().collect(Collectors.joining(" ")) + ";", + (old, newVal) -> old + (String)newVal)); } return values.isEmpty() ? null : values; } @@ -158,11 +170,23 @@ class SupplementDataParseHandler extends AbstractLDMLHandler { attributes.getValue("locales").replaceAll("_", "-")); } break; + case "hours": + if (!isIgnored(attributes)) { + var preferred = attributes.getValue("preferred"); + var allowed = attributes.getValue("allowed").replaceFirst(" .*", "").replaceFirst("b", "B"); // take only the first one, "b" -> "B" + var regions = Arrays.stream(attributes.getValue("regions").split(" ")) + .map(r -> r.replaceAll("_", "-")) + .collect(Collectors.toSet()); + var pmap = inputSkeletonMap.computeIfAbsent("preferred", k -> new HashMap<>()); + var amap = inputSkeletonMap.computeIfAbsent("allowed", k -> new HashMap<>()); + pmap.computeIfAbsent(preferred, k -> new TreeSet<>()).addAll(regions); + amap.computeIfAbsent(allowed, k -> new TreeSet<>()).addAll(regions); + } + break; default: // treat anything else as a container pushContainer(qName, attributes); break; } } - } diff --git a/src/java.base/share/classes/java/time/format/DateTimeFormatter.java b/src/java.base/share/classes/java/time/format/DateTimeFormatter.java index 063b6e14a00..0a67e22c0f3 100644 --- a/src/java.base/share/classes/java/time/format/DateTimeFormatter.java +++ b/src/java.base/share/classes/java/time/format/DateTimeFormatter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -81,7 +81,6 @@ import java.time.Period; import java.time.ZoneId; import java.time.ZoneOffset; import java.time.chrono.ChronoLocalDateTime; -import java.time.chrono.ChronoZonedDateTime; import java.time.chrono.Chronology; import java.time.chrono.IsoChronology; import java.time.format.DateTimeFormatterBuilder.CompositePrinterParser; @@ -718,6 +717,57 @@ public final class DateTimeFormatter { .toFormatter(ResolverStyle.SMART, IsoChronology.INSTANCE); } + //----------------------------------------------------------------------- + /** + * Creates a locale specific formatter derived from the requested template for + * the ISO chronology. The requested template is a series of typical pattern + * symbols in canonical order from the largest date or time unit to the smallest, + * which can be expressed with the following regular expression: + * {@snippet : + * "G{0,5}" + // Era + * "y*" + // Year + * "Q{0,5}" + // Quarter + * "M{0,5}" + // Month + * "w*" + // Week of Week Based Year + * "E{0,5}" + // Day of Week + * "d{0,2}" + // Day of Month + * "B{0,5}" + // Period/AmPm of Day + * "[hHjC]{0,2}" + // Hour of Day/AmPm (refer to LDML for 'j' and 'C') + * "m{0,2}" + // Minute of Hour + * "s{0,2}" + // Second of Minute + * "[vz]{0,4}" // Zone + * } + * All pattern symbols are optional, and each pattern symbol represents a field, + * for example, 'M' represents the Month field. The number of the pattern symbol letters follows the + * same presentation, such as "number" or "text" as in the Patterns for + * Formatting and Parsing section. Other pattern symbols in the requested template are + * invalid. + *

    + * The mapping of the requested template to the closest of the available localized formats + * is defined by the + * + * Unicode LDML specification. For example, the formatter created from the requested template + * {@code yMMM} will format the date '2020-06-16' to 'Jun 2020' in the {@link Locale#US US locale}. + *

    + * The locale is determined from the formatter. The formatter returned directly by + * this method uses the {@link Locale#getDefault() default FORMAT locale}. + * The locale can be controlled using {@link DateTimeFormatter#withLocale(Locale) withLocale(Locale)} + * on the result of this method. + *

    + * The returned formatter has no override zone. + * It uses {@link ResolverStyle#SMART SMART} resolver style. + * + * @param requestedTemplate the requested template, not null + * @return the formatter based on the {@code requestedTemplate} pattern, not null + * @throws IllegalArgumentException if {@code requestedTemplate} is invalid + * @see #ofPattern(String) + * @since 19 + */ + public static DateTimeFormatter ofLocalizedPattern(String requestedTemplate) { + return new DateTimeFormatterBuilder().appendLocalized(requestedTemplate) + .toFormatter(ResolverStyle.SMART, IsoChronology.INSTANCE); + } + //----------------------------------------------------------------------- /** * The ISO date formatter that formats or parses a date without an diff --git a/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java b/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java index 40c0de53d3f..62ea488ede7 100644 --- a/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java +++ b/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022, 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 @@ -227,6 +227,42 @@ public final class DateTimeFormatterBuilder { CalendarDataUtility.findRegionOverride(locale)); } + /** + * Returns the formatting pattern for the requested template for a locale and chronology. + * The locale and chronology are used to lookup the locale specific format + * for the requested template. + *

    + * If the locale contains the "rg" (region override) + * Unicode extensions, + * the formatting pattern is overridden with the one appropriate for the region. + *

    + * Refer to {@link #appendLocalized(String)} for the detail of {@code requestedTemplate} + * argument. + * + * @param requestedTemplate the requested template, not null + * @param chrono the Chronology, non-null + * @param locale the locale, non-null + * @return the locale and Chronology specific formatting pattern + * @throws IllegalArgumentException if {@code requestedTemplate} does not match + * the regular expression syntax described in {@link #appendLocalized(String)}. + * @throws DateTimeException if a match for the localized pattern for + * {@code requestedTemplate} is not available + * @see #appendLocalized(String) + * @since 19 + */ + public static String getLocalizedDateTimePattern(String requestedTemplate, + Chronology chrono, Locale locale) { + Objects.requireNonNull(requestedTemplate, "requestedTemplate"); + Objects.requireNonNull(chrono, "chrono"); + Objects.requireNonNull(locale, "locale"); + Locale override = CalendarDataUtility.findRegionOverride(locale); + LocaleProviderAdapter adapter = LocaleProviderAdapter.getAdapter(JavaTimeDateTimePatternProvider.class, override); + JavaTimeDateTimePatternProvider provider = adapter.getJavaTimeDateTimePatternProvider(); + return provider.getJavaTimeDateTimePattern(requestedTemplate, + chrono.getCalendarType(), + override); + } + /** * Converts the given FormatStyle to the java.text.DateFormat style. * @@ -1423,6 +1459,84 @@ public final class DateTimeFormatterBuilder { return this; } + //----------------------------------------------------------------------- + // RegEx pattern for skeleton validity checking + private static final Pattern VALID_TEMPLATE_PATTERN = Pattern.compile( + "G{0,5}" + // Era + "y*" + // Year + "Q{0,5}" + // Quarter + "M{0,5}" + // Month + "w*" + // Week of Week Based Year + "E{0,5}" + // Day of Week + "d{0,2}" + // Day of Month + "B{0,5}" + // Period/AmPm of Day + "[hHjC]{0,2}" + // Hour of Day/AmPm + "m{0,2}" + // Minute of Hour + "s{0,2}" + // Second of Minute + "[vz]{0,4}"); // Zone + /** + * Appends a localized pattern to the formatter using the requested template. + *

    + * This appends a localized section to the builder, suitable for outputting + * a date, time or date-time combination. The format of the localized + * section is lazily looked up based on three items: + *

      + *
    • the {@code requestedTemplate} specified to this method + *
    • the {@code Locale} of the {@code DateTimeFormatter} + *
    • the {@code Chronology} of the {@code DateTimeFormatter} unless overridden + *
    + * During formatting, the chronology is obtained from the temporal object + * being formatted, which may have been overridden by + * {@link DateTimeFormatter#withChronology(Chronology)}. + *

    + * During parsing, if a chronology has already been parsed, then it is used. + * Otherwise the default from {@code DateTimeFormatter.withChronology(Chronology)} + * is used, with {@code IsoChronology} as the fallback. + *

    + * The requested template is a series of typical pattern + * symbols in canonical order from the largest date or time unit to the smallest, + * which can be expressed with the following regular expression: + * {@snippet : + * "G{0,5}" + // Era + * "y*" + // Year + * "Q{0,5}" + // Quarter + * "M{0,5}" + // Month + * "w*" + // Week of Week Based Year + * "E{0,5}" + // Day of Week + * "d{0,2}" + // Day of Month + * "B{0,5}" + // Period/AmPm of Day + * "[hHjC]{0,2}" + // Hour of Day/AmPm (refer to LDML for 'j' and 'C') + * "m{0,2}" + // Minute of Hour + * "s{0,2}" + // Second of Minute + * "[vz]{0,4}" // Zone + * } + * All pattern symbols are optional, and each pattern symbol represents a field, + * for example, 'M' represents the Month field. The number of the pattern symbol letters follows the + * same presentation, such as "number" or "text" as in the + * Patterns for Formatting and Parsing section. + * Other pattern symbols in the requested template are invalid. + *

    + * The mapping of the requested template to the closest of the available localized formats + * is defined by the + * + * Unicode LDML specification. For example, the formatter created from the requested template + * {@code yMMM} will format the date '2020-06-16' to 'Jun 2020' in the {@link Locale#US US locale}. + * + * @param requestedTemplate the requested template to use, not null + * @return this, for chaining, not null + * @throws IllegalArgumentException if {@code requestedTemplate} is invalid + * @see #appendPattern(String) + * @since 19 + */ + public DateTimeFormatterBuilder appendLocalized(String requestedTemplate) { + Objects.requireNonNull(requestedTemplate, "requestedTemplate"); + if (!VALID_TEMPLATE_PATTERN.matcher(requestedTemplate).matches()) { + throw new IllegalArgumentException("Requested template is invalid: " + requestedTemplate); + } + appendInternal(new LocalizedPrinterParser(requestedTemplate)); + return this; + } + //----------------------------------------------------------------------- /** * Appends a character literal to the formatter. @@ -2378,11 +2492,11 @@ public final class DateTimeFormatterBuilder { private final DateTimePrinterParser[] printerParsers; private final boolean optional; - CompositePrinterParser(List printerParsers, boolean optional) { + private CompositePrinterParser(List printerParsers, boolean optional) { this(printerParsers.toArray(new DateTimePrinterParser[0]), optional); } - CompositePrinterParser(DateTimePrinterParser[] printerParsers, boolean optional) { + private CompositePrinterParser(DateTimePrinterParser[] printerParsers, boolean optional) { this.printerParsers = printerParsers; this.optional = optional; } @@ -2476,7 +2590,7 @@ public final class DateTimeFormatterBuilder { * @param padWidth the width to pad to, 1 or greater * @param padChar the pad character */ - PadPrinterParserDecorator(DateTimePrinterParser printerParser, int padWidth, char padChar) { + private PadPrinterParserDecorator(DateTimePrinterParser printerParser, int padWidth, char padChar) { // input checked by DateTimeFormatterBuilder this.printerParser = printerParser; this.padWidth = padWidth; @@ -2584,7 +2698,7 @@ public final class DateTimeFormatterBuilder { private final TemporalField field; private final long value; - DefaultValueParser(TemporalField field, long value) { + private DefaultValueParser(TemporalField field, long value) { this.field = field; this.value = value; } @@ -2608,7 +2722,7 @@ public final class DateTimeFormatterBuilder { static final class CharLiteralPrinterParser implements DateTimePrinterParser { private final char literal; - CharLiteralPrinterParser(char literal) { + private CharLiteralPrinterParser(char literal) { this.literal = literal; } @@ -2651,7 +2765,7 @@ public final class DateTimeFormatterBuilder { static final class StringLiteralPrinterParser implements DateTimePrinterParser { private final String literal; - StringLiteralPrinterParser(String literal) { + private StringLiteralPrinterParser(String literal) { this.literal = literal; // validated by caller } @@ -2717,7 +2831,7 @@ public final class DateTimeFormatterBuilder { * @param maxWidth the maximum field width, from minWidth to 19 * @param signStyle the positive/negative sign style, not null */ - NumberPrinterParser(TemporalField field, int minWidth, int maxWidth, SignStyle signStyle) { + private NumberPrinterParser(TemporalField field, int minWidth, int maxWidth, SignStyle signStyle) { // validated by caller this.field = field; this.minWidth = minWidth; @@ -3008,7 +3122,7 @@ public final class DateTimeFormatterBuilder { * @param baseValue the base value * @param baseDate the base date */ - ReducedPrinterParser(TemporalField field, int minWidth, int maxWidth, + private ReducedPrinterParser(TemporalField field, int minWidth, int maxWidth, int baseValue, ChronoLocalDate baseDate) { this(field, minWidth, maxWidth, baseValue, baseDate, 0); if (minWidth < 1 || minWidth > 10) { @@ -3161,7 +3275,7 @@ public final class DateTimeFormatterBuilder { * @param maxWidth the maximum width to output, from 0 to 9 * @param decimalPoint whether to output the localized decimal point symbol */ - NanosPrinterParser(int minWidth, int maxWidth, boolean decimalPoint) { + private NanosPrinterParser(int minWidth, int maxWidth, boolean decimalPoint) { this(minWidth, maxWidth, decimalPoint, 0); if (minWidth < 0 || minWidth > 9) { throw new IllegalArgumentException("Minimum width must be from 0 to 9 inclusive but was " + minWidth); @@ -3183,7 +3297,7 @@ public final class DateTimeFormatterBuilder { * @param decimalPoint whether to output the localized decimal point symbol * @param subsequentWidth the subsequentWidth for this instance */ - NanosPrinterParser(int minWidth, int maxWidth, boolean decimalPoint, int subsequentWidth) { + private NanosPrinterParser(int minWidth, int maxWidth, boolean decimalPoint, int subsequentWidth) { super(NANO_OF_SECOND, minWidth, maxWidth, SignStyle.NOT_NEGATIVE, subsequentWidth); this.decimalPoint = decimalPoint; } @@ -3366,7 +3480,7 @@ public final class DateTimeFormatterBuilder { * @param maxWidth the maximum width to output, from 0 to 9 * @param decimalPoint whether to output the localized decimal point symbol */ - FractionPrinterParser(TemporalField field, int minWidth, int maxWidth, boolean decimalPoint) { + private FractionPrinterParser(TemporalField field, int minWidth, int maxWidth, boolean decimalPoint) { this(field, minWidth, maxWidth, decimalPoint, 0); Objects.requireNonNull(field, "field"); if (field.range().isFixed() == false) { @@ -3393,7 +3507,7 @@ public final class DateTimeFormatterBuilder { * @param decimalPoint whether to output the localized decimal point symbol * @param subsequentWidth the subsequentWidth for this instance */ - FractionPrinterParser(TemporalField field, int minWidth, int maxWidth, boolean decimalPoint, int subsequentWidth) { + private FractionPrinterParser(TemporalField field, int minWidth, int maxWidth, boolean decimalPoint, int subsequentWidth) { super(field, minWidth, maxWidth, SignStyle.NOT_NEGATIVE, subsequentWidth); this.decimalPoint = decimalPoint; ValueRange range = field.range(); @@ -3583,7 +3697,7 @@ public final class DateTimeFormatterBuilder { * @param textStyle the text style, not null * @param provider the text provider, not null */ - TextPrinterParser(TemporalField field, TextStyle textStyle, DateTimeTextProvider provider) { + private TextPrinterParser(TemporalField field, TextStyle textStyle, DateTimeTextProvider provider) { // validated by caller this.field = field; this.textStyle = textStyle; @@ -3681,7 +3795,7 @@ public final class DateTimeFormatterBuilder { private static final long SECONDS_0000_TO_1970 = ((146097L * 5L) - (30L * 365L + 7L)) * 86400L; private final int fractionalDigits; - InstantPrinterParser(int fractionalDigits) { + private InstantPrinterParser(int fractionalDigits) { this.fractionalDigits = fractionalDigits; } @@ -3830,7 +3944,7 @@ public final class DateTimeFormatterBuilder { * @param pattern the pattern * @param noOffsetText the text to use for UTC, not null */ - OffsetIdPrinterParser(String pattern, String noOffsetText) { + private OffsetIdPrinterParser(String pattern, String noOffsetText) { Objects.requireNonNull(pattern, "pattern"); Objects.requireNonNull(noOffsetText, "noOffsetText"); this.type = checkPattern(pattern); @@ -4312,7 +4426,7 @@ public final class DateTimeFormatterBuilder { /** Display in generic time-zone format. True in case of pattern letter 'v' */ private final boolean isGeneric; - ZoneTextPrinterParser(TextStyle textStyle, Set preferredZones, boolean isGeneric) { + private ZoneTextPrinterParser(TextStyle textStyle, Set preferredZones, boolean isGeneric) { super(TemporalQueries.zone(), "ZoneText(" + textStyle + ")"); this.textStyle = Objects.requireNonNull(textStyle, "textStyle"); this.isGeneric = isGeneric; @@ -4484,7 +4598,7 @@ public final class DateTimeFormatterBuilder { private final TemporalQuery query; private final String description; - ZoneIdPrinterParser(TemporalQuery query, String description) { + private ZoneIdPrinterParser(TemporalQuery query, String description) { this.query = query; this.description = description; } @@ -4903,7 +5017,7 @@ public final class DateTimeFormatterBuilder { /** The text style to output, null means the ID. */ private final TextStyle textStyle; - ChronoPrinterParser(TextStyle textStyle) { + private ChronoPrinterParser(TextStyle textStyle) { // validated by caller this.textStyle = textStyle; } @@ -4978,6 +5092,7 @@ public final class DateTimeFormatterBuilder { private final FormatStyle dateStyle; private final FormatStyle timeStyle; + private final String requestedTemplate; /** * Constructor. @@ -4985,10 +5100,23 @@ public final class DateTimeFormatterBuilder { * @param dateStyle the date style to use, may be null * @param timeStyle the time style to use, may be null */ - LocalizedPrinterParser(FormatStyle dateStyle, FormatStyle timeStyle) { - // validated by caller + private LocalizedPrinterParser(FormatStyle dateStyle, FormatStyle timeStyle) { + // params validated by caller this.dateStyle = dateStyle; this.timeStyle = timeStyle; + this.requestedTemplate = null; + } + + /** + * Constructor. + * + * @param requestedTemplate the requested template to use, not null + */ + private LocalizedPrinterParser(String requestedTemplate) { + // param validated by caller + this.dateStyle = null; + this.timeStyle = null; + this.requestedTemplate = requestedTemplate; } @Override @@ -5006,7 +5134,8 @@ public final class DateTimeFormatterBuilder { /** * Gets the formatter to use. *

    - * The formatter will be the most appropriate to use for the date and time style in the locale. + * The formatter will be the most appropriate to use for the date and time style, or + * the requested template for the locale. * For example, some locales will use the month name while others will use the number. * * @param locale the locale to use, not null @@ -5015,23 +5144,22 @@ public final class DateTimeFormatterBuilder { * @throws IllegalArgumentException if the formatter cannot be found */ private DateTimeFormatter formatter(Locale locale, Chronology chrono) { - String key = chrono.getId() + '|' + locale.toString() + '|' + dateStyle + timeStyle; - DateTimeFormatter formatter = FORMATTER_CACHE.get(key); - if (formatter == null) { - String pattern = getLocalizedDateTimePattern(dateStyle, timeStyle, chrono, locale); - formatter = new DateTimeFormatterBuilder().appendPattern(pattern).toFormatter(locale); - DateTimeFormatter old = FORMATTER_CACHE.putIfAbsent(key, formatter); - if (old != null) { - formatter = old; - } - } - return formatter; + String key = chrono.getId() + '|' + locale.toString() + '|' + + (requestedTemplate != null ? requestedTemplate : Objects.toString(dateStyle) + timeStyle); + + return FORMATTER_CACHE.computeIfAbsent(key, k -> + new DateTimeFormatterBuilder() + .appendPattern(requestedTemplate != null ? + getLocalizedDateTimePattern(requestedTemplate, chrono, locale) : + getLocalizedDateTimePattern(dateStyle, timeStyle, chrono, locale)) + .toFormatter(locale)); } @Override public String toString() { - return "Localized(" + (dateStyle != null ? dateStyle : "") + "," + - (timeStyle != null ? timeStyle : "") + ")"; + return "Localized(" + (requestedTemplate != null ? requestedTemplate : + (dateStyle != null ? dateStyle : "") + "," + + (timeStyle != null ? timeStyle : "")) + ")"; } } @@ -5056,7 +5184,7 @@ public final class DateTimeFormatterBuilder { * @param minWidth the minimum field width, from 1 to 19 * @param maxWidth the maximum field width, from minWidth to 19 */ - WeekBasedFieldPrinterParser(char chr, int count, int minWidth, int maxWidth) { + private WeekBasedFieldPrinterParser(char chr, int count, int minWidth, int maxWidth) { this(chr, count, minWidth, maxWidth, 0); } @@ -5070,7 +5198,7 @@ public final class DateTimeFormatterBuilder { * @param subsequentWidth the width of subsequent non-negative numbers, 0 or greater, * -1 if fixed width due to active adjacent parsing */ - WeekBasedFieldPrinterParser(char chr, int count, int minWidth, int maxWidth, + private WeekBasedFieldPrinterParser(char chr, int count, int minWidth, int maxWidth, int subsequentWidth) { super(null, minWidth, maxWidth, SignStyle.NOT_NEGATIVE, subsequentWidth); this.chr = chr; @@ -5201,7 +5329,7 @@ public final class DateTimeFormatterBuilder { * * @param textStyle the text style, not null */ - DayPeriodPrinterParser(TextStyle textStyle) { + private DayPeriodPrinterParser(TextStyle textStyle) { // validated by caller this.textStyle = textStyle; } diff --git a/src/java.base/share/classes/sun/text/spi/JavaTimeDateTimePatternProvider.java b/src/java.base/share/classes/sun/text/spi/JavaTimeDateTimePatternProvider.java index a3835c6ac82..58235c9dff0 100644 --- a/src/java.base/share/classes/sun/text/spi/JavaTimeDateTimePatternProvider.java +++ b/src/java.base/share/classes/sun/text/spi/JavaTimeDateTimePatternProvider.java @@ -27,6 +27,7 @@ package sun.text.spi; +import java.time.DateTimeException; import java.util.Locale; import java.util.spi.LocaleServiceProvider; @@ -41,10 +42,10 @@ public abstract class JavaTimeDateTimePatternProvider extends LocaleServiceProvi } /** - * Gets the formatting pattern for a timeStyle + * Returns the formatting pattern for a timeStyle * dateStyle, calendarType and locale. * Concrete implementation of this method will retrieve - * a java.time specific dateTime Pattern from selected Locale Provider. + * a java.time specific dateTime Pattern from the selected Locale Provider. * * @param timeStyle an {@code int} value, representing FormatStyle constant, -1 * for date-only pattern @@ -58,4 +59,26 @@ public abstract class JavaTimeDateTimePatternProvider extends LocaleServiceProvi * @since 9 */ public abstract String getJavaTimeDateTimePattern(int timeStyle, int dateStyle, String calType, Locale locale); + + /** + * Returns the formatting pattern for the requested template, calendarType, and locale. + * Concrete implementation of this method will retrieve + * a java.time specific pattern from selected Locale Provider. + * + * @param requestedTemplate the requested template, not null + * @param calType a {@code String}, non-null representing CalendarType such as "japanese", + * "iso8601" + * @param locale {@code locale}, non-null + * @throws IllegalArgumentException if {@code requestedTemplate} does not match + * the regular expression syntax described in + * {@link java.time.format.DateTimeFormatterBuilder#appendLocalized(String)}. + * @throws DateTimeException if a match for the formatting pattern for + * {@code requestedTemplate} is not available + * @return formatting pattern {@code String} + * @since 19 + */ + public String getJavaTimeDateTimePattern(String requestedTemplate, String calType, Locale locale) { + // default implementation throws exception + throw new DateTimeException("Formatting pattern is not available for the requested template: " + requestedTemplate); + } } diff --git a/src/java.base/share/classes/sun/util/locale/provider/JavaTimeDateTimePatternImpl.java b/src/java.base/share/classes/sun/util/locale/provider/JavaTimeDateTimePatternImpl.java index 41de2dd7f65..c39cea799b3 100644 --- a/src/java.base/share/classes/sun/util/locale/provider/JavaTimeDateTimePatternImpl.java +++ b/src/java.base/share/classes/sun/util/locale/provider/JavaTimeDateTimePatternImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,10 @@ */ package sun.util.locale.provider; +import java.time.DateTimeException; import java.util.Locale; +import java.util.Objects; +import java.util.Optional; import java.util.Set; import sun.text.spi.JavaTimeDateTimePatternProvider; @@ -63,10 +66,21 @@ public class JavaTimeDateTimePatternImpl extends JavaTimeDateTimePatternProvider @Override public String getJavaTimeDateTimePattern(int timeStyle, int dateStyle, String calType, Locale locale) { LocaleResources lr = LocaleProviderAdapter.getResourceBundleBased().getLocaleResources(locale); - String pattern = lr.getJavaTimeDateTimePattern( - timeStyle, dateStyle, calType); - return pattern; + return lr.getJavaTimeDateTimePattern(timeStyle, dateStyle, calType); + } + @Override + public String getJavaTimeDateTimePattern(String requestedTemplate, String calType, Locale locale) { + LocaleProviderAdapter lpa = LocaleProviderAdapter.getResourceBundleBased(); + return ((ResourceBundleBasedAdapter)lpa).getCandidateLocales("", locale).stream() + .map(lpa::getLocaleResources) + .map(lr -> lr.getLocalizedPattern(requestedTemplate, calType)) + .filter(Objects::nonNull) + .findFirst() + .or(() -> calType.equals("generic") ? Optional.empty(): + Optional.of(getJavaTimeDateTimePattern(requestedTemplate, "generic", locale))) + .orElseThrow(() -> new DateTimeException("Requested template \"" + requestedTemplate + + "\" cannot be resolved in the locale \"" + locale + "\"")); } @Override diff --git a/src/java.base/share/classes/sun/util/locale/provider/LocaleResources.java b/src/java.base/share/classes/sun/util/locale/provider/LocaleResources.java index fe84b66b167..aa991359c68 100644 --- a/src/java.base/share/classes/sun/util/locale/provider/LocaleResources.java +++ b/src/java.base/share/classes/sun/util/locale/provider/LocaleResources.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022, 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 @@ -46,15 +46,21 @@ import java.text.MessageFormat; import java.text.NumberFormat; import java.util.Arrays; import java.util.Calendar; +import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashSet; +import java.util.List; import java.util.Locale; +import java.util.Map; import java.util.Objects; import java.util.ResourceBundle; import java.util.Set; import java.util.TimeZone; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import java.util.regex.Pattern; +import java.util.stream.Stream; + import sun.security.action.GetPropertyAction; import sun.util.resources.LocaleData; import sun.util.resources.OpenListResourceBundle; @@ -91,6 +97,10 @@ public class LocaleResources { private static final String COMPACT_NUMBER_PATTERNS_CACHEKEY = "CNP"; private static final String DATE_TIME_PATTERN = "DTP."; private static final String RULES_CACHEKEY = "RULE"; + private static final String SKELETON_PATTERN = "SP."; + + // ResourceBundle key names for skeletons + private static final String SKELETON_INPUT_REGIONS_KEY = "DateFormatItemInputRegions"; // TimeZoneNamesBundle exemplar city prefix private static final String TZNB_EXCITY_PREFIX = "timezone.excity."; @@ -98,6 +108,31 @@ public class LocaleResources { // null singleton cache value private static final Object NULLOBJECT = new Object(); + // RegEx pattern for skeleton validity checking + private static final Pattern VALID_SKELETON_PATTERN = Pattern.compile( + "(?" + + "G{0,5}" + // Era + "y*" + // Year + "Q{0,5}" + // Quarter + "M{0,5}" + // Month + "w*" + // Week of Week Based Year + "E{0,5}" + // Day of Week + "d{0,2})" + // Day of Month + "(?

    * This method is caller sensitive, which means that it may return different * values to different callers. + * In cases where {@code MethodHandles.lookup} is called from a context where + * there is no caller frame on the stack (e.g. when called directly + * from a JNI attached thread), {@code IllegalCallerException} is thrown. + * To obtain a {@link Lookup lookup object} in such a context, use an auxiliary class that will + * implicitly be identified as the caller, or use {@link MethodHandles#publicLookup()} + * to obtain a low-privileged lookup instead. * @return a lookup object for the caller of this method, with * {@linkplain Lookup#ORIGINAL original} and * {@linkplain Lookup#hasFullPrivilegeAccess() full privilege access}. + * @throws IllegalCallerException if there is no caller frame on the stack. */ @CallerSensitive @ForceInline // to ensure Reflection.getCallerClass optimization public static Lookup lookup() { - return new Lookup(Reflection.getCallerClass()); + final Class c = Reflection.getCallerClass(); + if (c == null) { + throw new IllegalCallerException("no caller frame"); + } + return new Lookup(c); } /** diff --git a/test/jdk/java/lang/invoke/MethodHandles/exeNullCallerLookup/NullCallerLookupTest.java b/test/jdk/java/lang/invoke/MethodHandles/exeNullCallerLookup/NullCallerLookupTest.java new file mode 100644 index 00000000000..cda0b2bc7af --- /dev/null +++ b/test/jdk/java/lang/invoke/MethodHandles/exeNullCallerLookup/NullCallerLookupTest.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2022, 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 8281003 + * @summary Test uses custom launcher that starts VM using JNI that verifies + * MethodHandles::lookup with null caller class throws an IllegalCallerException. + * @library /test/lib + * @requires os.family != "aix" + * @run main/native NullCallerLookupTest + */ + +// Test disabled on AIX since we cannot invoke the JVM on the primordial thread. + +import java.io.File; +import java.util.Map; +import jdk.test.lib.Platform; +import jdk.test.lib.process.OutputAnalyzer; + +import java.io.IOException; +import java.nio.file.Path; + +public class NullCallerLookupTest { + public static void main(String[] args) throws IOException { + Path launcher = Path.of(System.getProperty("test.nativepath"), "NullCallerLookupTest"); + ProcessBuilder pb = new ProcessBuilder(launcher.toString()); + Map env = pb.environment(); + + String libDir = Platform.libDir().toString(); + String vmDir = Platform.jvmLibDir().toString(); + + // set up shared library path + String sharedLibraryPathEnvName = Platform.sharedLibraryPathVariableName(); + env.compute(sharedLibraryPathEnvName, + (k, v) -> (v == null) ? libDir : v + File.pathSeparator + libDir); + env.compute(sharedLibraryPathEnvName, + (k, v) -> (v == null) ? vmDir : v + File.pathSeparator + vmDir); + + System.out.println("Launching: " + launcher + " shared library path: " + + env.get(sharedLibraryPathEnvName)); + new OutputAnalyzer(pb.start()) + .outputTo(System.out) + .errorTo(System.err) + .shouldHaveExitValue(0); + } +} + diff --git a/test/jdk/java/lang/invoke/MethodHandles/exeNullCallerLookup/exeNullCallerLookupTest.c b/test/jdk/java/lang/invoke/MethodHandles/exeNullCallerLookup/exeNullCallerLookupTest.c new file mode 100644 index 00000000000..3abe15ce96c --- /dev/null +++ b/test/jdk/java/lang/invoke/MethodHandles/exeNullCallerLookup/exeNullCallerLookupTest.c @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include +#include + +#include "jni.h" +#include "assert.h" + +static jclass class_IllegalCallerException; + +int checkAndClearIllegalCallerExceptionThrown(JNIEnv *env) { + jthrowable t = (*env)->ExceptionOccurred(env); + if ((*env)->IsInstanceOf(env, t, class_IllegalCallerException) == JNI_TRUE) { + (*env)->ExceptionClear(env); + return JNI_TRUE; + } + return JNI_FALSE; +} + +int main(int argc, char** args) { + JavaVM *jvm; + JNIEnv *env; + JavaVMInitArgs vm_args; + JavaVMOption options[1]; + jint rc; + + + vm_args.version = JNI_VERSION_1_2; + vm_args.nOptions = 0; + vm_args.options = options; + + if ((rc = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args)) != JNI_OK) { + printf("ERROR: cannot create VM.\n"); + exit(-1); + } + class_IllegalCallerException = (*env)->FindClass(env, "java/lang/IllegalCallerException"); + assert (class_IllegalCallerException != NULL); + + // call MethodHandles.lookup() + jclass methodHandlesClass = (*env)->FindClass(env, "java/lang/invoke/MethodHandles"); + assert(methodHandlesClass != NULL); + jmethodID mid_MethodHandles_lookup = (*env)->GetStaticMethodID(env, methodHandlesClass, "lookup", "()Ljava/lang/invoke/MethodHandles$Lookup;" ); + assert(mid_MethodHandles_lookup != NULL); + jobject l = (*env)->CallStaticObjectMethod(env, methodHandlesClass, mid_MethodHandles_lookup ); + if ((rc = checkAndClearIllegalCallerExceptionThrown(env)) != JNI_TRUE) { + printf("ERROR: Didn't get the expected IllegalCallerException.\n"); + exit(-1); + } + + printf("Expected IllegalCallerException was thrown\n"); + + (*jvm)->DestroyJavaVM(jvm); + return 0; +} + -- GitLab From 48f6e93079f377a621ca769b820fa221062ceab1 Mon Sep 17 00:00:00 2001 From: Daniel Fuchs Date: Wed, 16 Feb 2022 21:38:48 +0000 Subject: [PATCH 531/564] 8282020: ProblemList sun/net/www/protocol/https/HttpsURLConnection/B6216082.java until JDK-8282017 is fixed Reviewed-by: michaelm, naoto --- test/jdk/ProblemList.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 6b54c726277..8e00e12f1ba 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -597,6 +597,7 @@ java/net/MulticastSocket/SetGetNetworkInterfaceTest.java 8219083 windows- java/net/ServerSocket/AcceptInheritHandle.java 8211854 aix-ppc64 +sun/net/www/protocol/https/HttpsURLConnection/B6216082.java 8282017 generic-all ############################################################################ -- GitLab From 9ba0760cf85f9e843f3383b725017c9ffac350df Mon Sep 17 00:00:00 2001 From: Martin Desruisseaux Date: Wed, 16 Feb 2022 22:01:01 +0000 Subject: [PATCH 532/564] 8275345: RasterFormatException when drawing a tiled image made of non-writable rasters Reviewed-by: prr, aivanov --- .../classes/sun/java2d/SunGraphics2D.java | 18 +- .../java/awt/image/DrawImage/TiledImage.java | 225 ++++++++++++++++++ 2 files changed, 234 insertions(+), 9 deletions(-) create mode 100644 test/jdk/java/awt/image/DrawImage/TiledImage.java diff --git a/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java b/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java index b5b5225938b..193a8a38587 100644 --- a/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java +++ b/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java @@ -2838,23 +2838,23 @@ public final class SunGraphics2D WritableRaster wRaster = null; if (raster instanceof WritableRaster) { wRaster = (WritableRaster)raster; + + // Translate wRaster to start at (0, 0) and to contain + // only the relevent portion of the tile + wRaster = wRaster.createWritableChild(tileRect.x, tileRect.y, + tileRect.width, + tileRect.height, + 0, 0, + null); } else { // Create a WritableRaster in the same coordinate system - // as the original raster. + // as the original raster, except origin which is (0,0). wRaster = Raster.createWritableRaster(raster.getSampleModel(), raster.getDataBuffer(), null); } - // Translate wRaster to start at (0, 0) and to contain - // only the relevent portion of the tile - wRaster = wRaster.createWritableChild(tileRect.x, tileRect.y, - tileRect.width, - tileRect.height, - 0, 0, - null); - // Wrap wRaster in a BufferedImage BufferedImage bufImg = new BufferedImage(colorModel, diff --git a/test/jdk/java/awt/image/DrawImage/TiledImage.java b/test/jdk/java/awt/image/DrawImage/TiledImage.java new file mode 100644 index 00000000000..8faca3aec6a --- /dev/null +++ b/test/jdk/java/awt/image/DrawImage/TiledImage.java @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.geom.AffineTransform; +import java.awt.image.BandedSampleModel; +import java.awt.image.BufferedImage; +import java.awt.image.Raster; +import java.awt.image.ColorModel; +import java.awt.image.DataBuffer; +import java.awt.image.DataBufferByte; +import java.awt.image.RenderedImage; +import java.awt.image.SampleModel; +import java.awt.image.WritableRaster; +import java.util.Objects; +import java.util.Vector; + + +/** + * @test + * @bug 8275345 + * @summary RasterFormatException when drawing a tiled image made of non-writable rasters. + * + * Test drawing a tiled image made of non-writable {@link Raster} tiles. + * Drawing works when tiles are instances of {@link WritableRaster}. + * But if tiles are instances of {@link Raster} only, then the following + * exception is thrown: + * + * Exception in thread "main" java.awt.image.RasterFormatException: (parentX + width) is outside raster + * at java.desktop/java.awt.image.WritableRaster.createWritableChild(WritableRaster.java:228) + * at java.desktop/sun.java2d.SunGraphics2D.drawTranslatedRenderedImage(SunGraphics2D.java:2852) + * at java.desktop/sun.java2d.SunGraphics2D.drawRenderedImage(SunGraphics2D.java:2711) + * + * The bug is demonstrated by drawing the same image twice: + * once with {@link WritableRaster} tiles (which succeed), + * then the same operation but with {@link Raster} tiles. + * + * The bug is caused by the following code in {@code SunGraphics2D}: + * + * // Create a WritableRaster containing the tile + * WritableRaster wRaster = null; + * if (raster instanceof WritableRaster) { + * wRaster = (WritableRaster)raster; + * } else { + * // Create a WritableRaster in the same coordinate system + * // as the original raster. + * wRaster = + * Raster.createWritableRaster(raster.getSampleModel(), + * raster.getDataBuffer(), + * null); + * } + * // Translate wRaster to start at (0, 0) and to contain + * // only the relevant portion of the tile + * wRaster = wRaster.createWritableChild(tileRect.x, tileRect.y, + * tileRect.width, + * tileRect.height, + * 0, 0, + * null); + * + * If {@code raster} is not an instance of {@link WritableRaster}, + * then a new {@link WritableRaster} is created wrapping the same + * buffer but with a location of (0,0), because + * the {@code location} argument of {@code createWritableRaster} + * is null. Consequently the call to {@code createWritableChild} + * shall not be done in that case, because the raster is already + * translated. The current code applies translation twice. + * + * This bug is largely unnoticed because most {@code Raster.create} + * methods actually create {@link WritableRaster} instances, even + * when the user did not asked for writable raster. To make this + * bug apparent, we need to invoke {@code Raster.createRaster(…)} + * with a sample model for which no optimization is provided. + */ +public class TiledImage implements RenderedImage { + /** + * Run the test using writable tiles first, then read-only tiles. + */ + public static void main(String[] args) { + draw(true); // Pass. + draw(false); // Fail if 8275345 is not fixed. + } + + private static final int NUM_X_TILES = 2, NUM_Y_TILES = 3; + + private static final int TILE_WIDTH = 16, TILE_HEIGHT = 12; + + /** + * Tests rendering a tiled image. + * + * @param writable whether the image shall use writable raster. + */ + private static void draw(final boolean writable) { + final BufferedImage target = new BufferedImage( + TILE_WIDTH * NUM_X_TILES, + TILE_HEIGHT * NUM_Y_TILES, + BufferedImage.TYPE_BYTE_GRAY); + + final RenderedImage source = new TiledImage(writable, + target.getColorModel()); + + Graphics2D g = target.createGraphics(); + g.drawRenderedImage(source, new AffineTransform()); + g.dispose(); + } + + private final ColorModel colorModel; + + private final Raster[] tiles; + + /** + * Creates a tiled image. The image is empty, + * but pixel values are not the purpose of this test. + * + * @param writable whether the image shall use writable raster. + */ + private TiledImage(boolean writable, ColorModel cm) { + /* + * We need a sample model class for which Raster.createRaster + * do not provide a special case. That method has optimizations + * for most SampleModel sub-types, except BandedSampleModel. + */ + SampleModel sm = new BandedSampleModel(DataBuffer.TYPE_BYTE, TILE_WIDTH, TILE_HEIGHT, 1); + tiles = new Raster[NUM_X_TILES * NUM_Y_TILES]; + final Point location = new Point(); + for (int tileY = 0; tileY < NUM_Y_TILES; tileY++) { + for (int tileX = 0; tileX < NUM_X_TILES; tileX++) { + location.x = tileX * TILE_WIDTH; + location.y = tileY * TILE_HEIGHT; + DataBufferByte db = new DataBufferByte(TILE_WIDTH * TILE_HEIGHT); + Raster r; + if (writable) { + r = Raster.createWritableRaster(sm, db, location); + } else { + // Case causing RasterFormatException later. + r = Raster.createRaster(sm, db, location); + } + tiles[tileX + tileY * NUM_X_TILES] = r; + } + } + colorModel = cm; + } + + @Override + public ColorModel getColorModel() { + return colorModel; + } + + @Override + public SampleModel getSampleModel() { + return tiles[0].getSampleModel(); + } + + @Override + public Vector getSources() { + return new Vector<>(); + } + + @Override + public Object getProperty(String key) { + return Image.UndefinedProperty; + } + + @Override + public String[] getPropertyNames() { + return null; + } + + @Override public int getMinX() {return 0;} + @Override public int getMinY() {return 0;} + @Override public int getMinTileX() {return 0;} + @Override public int getMinTileY() {return 0;} + @Override public int getTileGridXOffset() {return 0;} + @Override public int getTileGridYOffset() {return 0;} + @Override public int getNumXTiles() {return NUM_X_TILES;} + @Override public int getNumYTiles() {return NUM_Y_TILES;} + @Override public int getTileWidth() {return TILE_WIDTH;} + @Override public int getTileHeight() {return TILE_HEIGHT;} + @Override public int getWidth() {return TILE_WIDTH * NUM_X_TILES;} + @Override public int getHeight() {return TILE_HEIGHT * NUM_Y_TILES;} + + @Override + public Raster getTile(final int tileX, final int tileY) { + Objects.checkIndex(tileX, NUM_X_TILES); + Objects.checkIndex(tileY, NUM_Y_TILES); + return tiles[tileX + tileY * NUM_X_TILES]; + } + + @Override + public Raster getData() { + throw new UnsupportedOperationException("Not needed for this test."); + } + + @Override + public Raster getData(Rectangle rect) { + throw new UnsupportedOperationException("Not needed for this test."); + } + + @Override + public WritableRaster copyData(WritableRaster raster) { + throw new UnsupportedOperationException("Not needed for this test."); + } +} -- GitLab From 5ec7898dbf1ebe261e5e25939cad42134611ff12 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Wed, 16 Feb 2022 22:02:55 +0000 Subject: [PATCH 533/564] 8281671: Class.getCanonicalName spec should explicitly cover array classes Reviewed-by: mchung --- .../share/classes/java/lang/Class.java | 10 ++ test/jdk/java/lang/Class/NameTest.java | 101 ++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 test/jdk/java/lang/Class/NameTest.java diff --git a/src/java.base/share/classes/java/lang/Class.java b/src/java.base/share/classes/java/lang/Class.java index fb936b14989..fce7793fbcf 100644 --- a/src/java.base/share/classes/java/lang/Class.java +++ b/src/java.base/share/classes/java/lang/Class.java @@ -1732,8 +1732,18 @@ public final class Class implements java.io.Serializable, *

  • an array whose component type does not have a canonical name
  • * * + * The canonical name for a primitive class is the keyword for the + * corresponding primitive type ({@code byte}, {@code short}, + * {@code char}, {@code int}, and so on). + * + *

    An array type has a canonical name if and only if its + * component type has a canonical name. When an array type has a + * canonical name, it is equal to the canonical name of the + * component type followed by "{@code []}". + * * @return the canonical name of the underlying class if it exists, and * {@code null} otherwise. + * @jls 6.7 Fully Qualified Names and Canonical Names * @since 1.5 */ public String getCanonicalName() { diff --git a/test/jdk/java/lang/Class/NameTest.java b/test/jdk/java/lang/Class/NameTest.java new file mode 100644 index 00000000000..b8d6e2125b8 --- /dev/null +++ b/test/jdk/java/lang/Class/NameTest.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2022, 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 8281671 + * @summary Checks on various "getFooName" methods of java.lang.Class + */ + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +public class NameTest { + public static void main(String... args) { + testCanonicalName(); + testSimpleName(); + } + + private static void testCanonicalName() { + class LocalClass {} // Local class; no canonical name + Object o = new Object() {}; // Anonymous class; no canonical name + Object[] objectArray = {}; + + Map, String> expectedCanonicalName = new HashMap<>(); + + expectedCanonicalName.put(LocalClass.class, null); + expectedCanonicalName.put(o.getClass(), null); + + // If a component type doesn't have a canonical name, neither + // does an array of that type. + expectedCanonicalName.put(LocalClass.class.arrayType(), null); + expectedCanonicalName.put(o.getClass().arrayType(), null); + + expectedCanonicalName.put(int.class, "int"); + expectedCanonicalName.put(Object.class, "java.lang.Object"); + expectedCanonicalName.put(objectArray.getClass(), "java.lang.Object[]"); + + for (var entry : expectedCanonicalName.entrySet()) { + var key = entry.getKey(); + var expectedName = entry.getValue(); + String canonicalName = key.getCanonicalName(); + if (!Objects.equals(canonicalName, expectedName)) { + System.err.println("Unexpected canonical name '" + + canonicalName + "' found for " + + key + ", expected " + expectedName); + throw new RuntimeException(); + } + } + } + + private static void testSimpleName() { + class ALocalClass {} // Local class + Object o = new Object() {}; // Anonymous class, empty simple name + Object[] objectArray = {}; + + Map, String> expectedSimpleName = new HashMap<>(); + + expectedSimpleName.put(ALocalClass.class, "ALocalClass"); + expectedSimpleName.put(o.getClass(), ""); + + expectedSimpleName.put(ALocalClass.class.arrayType(), "ALocalClass[]"); + expectedSimpleName.put(o.getClass().arrayType(), "[]"); + + expectedSimpleName.put(int.class, "int"); + expectedSimpleName.put(Object.class, "Object"); + expectedSimpleName.put(objectArray.getClass(), "Object[]"); + + for (var entry : expectedSimpleName.entrySet()) { + var key = entry.getKey(); + var expectedName = entry.getValue(); + String simpleName = key.getSimpleName(); + if (!Objects.equals(simpleName, expectedName)) { + System.err.println("Unexpected simple name '" + + simpleName + "' found for " + + key + ", expected " + expectedName); + throw new RuntimeException(); + } + } + } +} -- GitLab From 0b00ce17cd6b530d9394e79ac8b07208cd4b92f5 Mon Sep 17 00:00:00 2001 From: Alexey Semenyuk Date: Wed, 16 Feb 2022 23:23:57 +0000 Subject: [PATCH 534/564] 8282011: test/jdk/tools/jpackage/windows/WinL10nTest.java test fails if light.exe is not in %PATH% Reviewed-by: almatvee --- test/jdk/tools/jpackage/windows/WinL10nTest.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/test/jdk/tools/jpackage/windows/WinL10nTest.java b/test/jdk/tools/jpackage/windows/WinL10nTest.java index 4171da208a4..4f7e726a3af 100644 --- a/test/jdk/tools/jpackage/windows/WinL10nTest.java +++ b/test/jdk/tools/jpackage/windows/WinL10nTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, 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 @@ -94,8 +94,11 @@ public class WinL10nTest { private final static Stream getLightCommandLine( Executor.Result result) { - return result.getOutput().stream() - .filter(s -> s.trim().startsWith("light.exe")); + return result.getOutput().stream().filter(s -> { + s = s.trim(); + return s.startsWith("light.exe") || ((s.contains("\\light.exe ") + && s.contains(" -out "))); + }); } @Test -- GitLab From cd234f5dbebd18ebf0c78dfdf533318cdc627971 Mon Sep 17 00:00:00 2001 From: Alexey Semenyuk Date: Thu, 17 Feb 2022 05:27:41 +0000 Subject: [PATCH 535/564] 8282007: Assorted enhancements to jpackage testing framework Reviewed-by: almatvee --- test/jdk/tools/jpackage/apps/Hello.java | 19 +- .../jdk/jpackage/test/AdditionalLauncher.java | 137 ++++++++++--- .../helpers/jdk/jpackage/test/CfgFile.java | 6 +- .../helpers/jdk/jpackage/test/Executor.java | 8 +- .../helpers/jdk/jpackage/test/HelloApp.java | 21 +- .../jdk/jpackage/test/JPackageCommand.java | 67 +++++- .../helpers/jdk/jpackage/test/JavaTool.java | 6 +- .../jdk/jpackage/test/LinuxHelper.java | 44 ++-- .../helpers/jdk/jpackage/test/MacHelper.java | 93 +++++---- .../jdk/jpackage/test/PackageTest.java | 190 ++++++++++++------ .../jpackage/test/RunnablePackageTest.java | 16 +- .../helpers/jdk/jpackage/test/TKit.java | 2 +- .../jdk/jpackage/test/WindowsHelper.java | 109 ++++++---- test/jdk/tools/jpackage/run_tests.sh | 62 ++++-- .../share/MultiLauncherTwoPhaseTest.java | 4 +- test/jdk/tools/jpackage/test_jpackage.sh | 100 --------- .../jpackage/windows/WinUpgradeUUIDTest.java | 4 +- 17 files changed, 562 insertions(+), 326 deletions(-) delete mode 100644 test/jdk/tools/jpackage/test_jpackage.sh diff --git a/test/jdk/tools/jpackage/apps/Hello.java b/test/jdk/tools/jpackage/apps/Hello.java index dd6f114a421..000573c933f 100644 --- a/test/jdk/tools/jpackage/apps/Hello.java +++ b/test/jdk/tools/jpackage/apps/Hello.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,6 +37,7 @@ import java.util.List; import java.util.ArrayList; import java.util.stream.Stream; import java.util.Collections; +import java.util.Optional; public class Hello implements OpenFilesHandler { @@ -60,6 +61,15 @@ public class Hello implements OpenFilesHandler { var outputFile = getOutputFile(args); trace(String.format("Output file: [%s]", outputFile)); Files.write(outputFile, lines); + + if (Optional.ofNullable(System.getProperty("jpackage.test.noexit")).map( + Boolean::parseBoolean).orElse(false)) { + trace("noexit"); + var lock = new Object(); + synchronized (lock) { + lock.wait(); + } + } } private static List printArgs(String[] args) { @@ -87,7 +97,8 @@ public class Hello implements OpenFilesHandler { } private static Path getOutputFile(String[] args) { - Path outputFilePath = Path.of("appOutput.txt"); + Path outputFilePath = Path.of(Optional.ofNullable(System.getProperty( + "jpackage.test.appOutput")).orElse("appOutput.txt")); // If first arg is a file (most likely from fa), then put output in the same folder as // the file from fa. @@ -101,7 +112,7 @@ public class Hello implements OpenFilesHandler { try { // Try writing in the default output file. Files.write(outputFilePath, Collections.emptyList()); - return outputFilePath; + return outputFilePath.toAbsolutePath(); } catch (IOException ex) { // Log reason of a failure. StringWriter errors = new StringWriter(); @@ -109,7 +120,7 @@ public class Hello implements OpenFilesHandler { Stream.of(errors.toString().split("\\R")).forEachOrdered(Hello::trace); } - return Path.of(System.getProperty("user.home")).resolve(outputFilePath); + return Path.of(System.getProperty("user.home")).resolve(outputFilePath).toAbsolutePath(); } @Override diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/AdditionalLauncher.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/AdditionalLauncher.java index 10033db4802..44d75d98ec9 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/AdditionalLauncher.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/AdditionalLauncher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,13 +29,17 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.function.BiConsumer; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; import java.util.stream.Stream; -import jdk.jpackage.internal.ApplicationLayout; import jdk.jpackage.test.Functional.ThrowingBiConsumer; +import static jdk.jpackage.test.Functional.ThrowingFunction.toFunction; -public final class AdditionalLauncher { +public class AdditionalLauncher { public AdditionalLauncher(String name) { this.name = name; @@ -43,12 +47,12 @@ public final class AdditionalLauncher { setPersistenceHandler(null); } - public AdditionalLauncher setDefaultArguments(String... v) { + final public AdditionalLauncher setDefaultArguments(String... v) { defaultArguments = new ArrayList<>(List.of(v)); return this; } - public AdditionalLauncher addDefaultArguments(String... v) { + final public AdditionalLauncher addDefaultArguments(String... v) { if (defaultArguments == null) { return setDefaultArguments(v); } @@ -57,12 +61,12 @@ public final class AdditionalLauncher { return this; } - public AdditionalLauncher setJavaOptions(String... v) { + final public AdditionalLauncher setJavaOptions(String... v) { javaOptions = new ArrayList<>(List.of(v)); return this; } - public AdditionalLauncher addJavaOptions(String... v) { + final public AdditionalLauncher addJavaOptions(String... v) { if (javaOptions == null) { return setJavaOptions(v); } @@ -71,23 +75,24 @@ public final class AdditionalLauncher { return this; } - public AdditionalLauncher addRawProperties(Map.Entry... v) { + final public AdditionalLauncher addRawProperties( + Map.Entry... v) { return addRawProperties(List.of(v)); } - public AdditionalLauncher addRawProperties( + final public AdditionalLauncher addRawProperties( Collection> v) { rawProperties.addAll(v); return this; } - public AdditionalLauncher setShortcuts(boolean menu, boolean shortcut) { + final public AdditionalLauncher setShortcuts(boolean menu, boolean shortcut) { withMenuShortcut = menu; withShortcut = shortcut; return this; } - public AdditionalLauncher setIcon(Path iconPath) { + final public AdditionalLauncher setIcon(Path iconPath) { if (iconPath == NO_ICON) { throw new IllegalArgumentException(); } @@ -96,12 +101,12 @@ public final class AdditionalLauncher { return this; } - public AdditionalLauncher setNoIcon() { + final public AdditionalLauncher setNoIcon() { icon = NO_ICON; return this; } - public AdditionalLauncher setPersistenceHandler( + final public AdditionalLauncher setPersistenceHandler( ThrowingBiConsumer>> handler) { if (handler != null) { createFileHandler = ThrowingBiConsumer.toBiConsumer(handler); @@ -111,19 +116,53 @@ public final class AdditionalLauncher { return this; } - public void applyTo(JPackageCommand cmd) { + final public void applyTo(JPackageCommand cmd) { cmd.addPrerequisiteAction(this::initialize); cmd.addVerifyAction(this::verify); } - public void applyTo(PackageTest test) { - test.addLauncherName(name); + final public void applyTo(PackageTest test) { test.addInitializer(this::initialize); test.addInstallVerifier(this::verify); } + static void forEachAdditionalLauncher(JPackageCommand cmd, + BiConsumer consumer) { + var argIt = cmd.getAllArguments().iterator(); + while (argIt.hasNext()) { + if ("--add-launcher".equals(argIt.next())) { + // = + var arg = argIt.next(); + var items = arg.split("=", 2); + consumer.accept(items[0], Path.of(items[1])); + } + } + } + + static PropertyFile getAdditionalLauncherProperties( + JPackageCommand cmd, String launcherName) { + PropertyFile shell[] = new PropertyFile[1]; + forEachAdditionalLauncher(cmd, (name, propertiesFilePath) -> { + if (name.equals(launcherName)) { + shell[0] = toFunction(PropertyFile::new).apply( + propertiesFilePath); + } + }); + return Optional.of(shell[0]).get(); + } + private void initialize(JPackageCommand cmd) { - final Path propsFile = TKit.workDir().resolve(name + ".properties"); + Path propsFile = TKit.workDir().resolve(name + ".properties"); + if (Files.exists(propsFile)) { + // File with the given name exists, pick another name that + // will not reference existing file. + try { + propsFile = TKit.createTempFile(propsFile); + TKit.deleteIfExists(propsFile); + } catch (IOException ex) { + Functional.rethrowUnchecked(ex); + } + } cmd.addArguments("--add-launcher", String.format("%s=%s", name, propsFile)); @@ -242,7 +281,7 @@ public final class AdditionalLauncher { } } - private void verify(JPackageCommand cmd) throws IOException { + protected void verify(JPackageCommand cmd) throws IOException { verifyIcon(cmd); verifyShortcuts(cmd); @@ -255,14 +294,60 @@ public final class AdditionalLauncher { return; } - HelloApp.assertApp(launcherPath) - .addDefaultArguments(Optional - .ofNullable(defaultArguments) - .orElseGet(() -> List.of(cmd.getAllArgumentValues("--arguments")))) - .addJavaOptions(Optional - .ofNullable(javaOptions) - .orElseGet(() -> List.of(cmd.getAllArgumentValues("--java-options")))) - .executeAndVerifyOutput(); + var appVerifier = HelloApp.assertApp(launcherPath) + .addDefaultArguments(Optional + .ofNullable(defaultArguments) + .orElseGet(() -> List.of(cmd.getAllArgumentValues("--arguments")))) + .addJavaOptions(Optional + .ofNullable(javaOptions) + .orElseGet(() -> List.of(cmd.getAllArgumentValues( + "--java-options"))).stream().map( + str -> resolveVariables(cmd, str)).toList()); + + appVerifier.executeAndVerifyOutput(); + } + + public static final class PropertyFile { + + PropertyFile(Path path) throws IOException { + data = Files.readAllLines(path).stream().map(str -> { + return str.split("=", 2); + }).collect( + Collectors.toMap(tokens -> tokens[0], tokens -> tokens[1], + (oldValue, newValue) -> { + return newValue; + })); + } + + public boolean isPropertySet(String name) { + Objects.requireNonNull(name); + return data.containsKey(name); + } + + public Optional getPropertyValue(String name) { + Objects.requireNonNull(name); + return Optional.of(data.get(name)); + } + + public Optional getPropertyBooleanValue(String name) { + Objects.requireNonNull(name); + return Optional.ofNullable(data.get(name)).map(Boolean::parseBoolean); + } + + private final Map data; + } + + private static String resolveVariables(JPackageCommand cmd, String str) { + var map = Map.of( + "$APPDIR", cmd.appLayout().appDirectory(), + "$ROOTDIR", + cmd.isImagePackageType() ? cmd.outputBundle() : cmd.appInstallationDirectory(), + "$BINDIR", cmd.appLayout().launchersDirectory()); + for (var e : map.entrySet()) { + str = str.replaceAll(Pattern.quote(e.getKey()), + Matcher.quoteReplacement(e.getValue().toString())); + } + return str; } private List javaOptions; diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/CfgFile.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/CfgFile.java index e2a380366e8..31bf0520a31 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/CfgFile.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/CfgFile.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Objects; +import java.util.Optional; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -85,7 +86,8 @@ public final class CfgFile { } if (!currentSection.isEmpty()) { - result.put("", Collections.unmodifiableMap(currentSection)); + result.put(Optional.ofNullable(currentSectionName).orElse(""), + Collections.unmodifiableMap(currentSection)); } return new CfgFile(Collections.unmodifiableMap(result), path.toString()); diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Executor.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Executor.java index d65fe4e667b..3fed83ddb36 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Executor.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Executor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, 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 @@ -90,8 +90,10 @@ public final class Executor extends CommandArguments { } public Executor setWindowsTmpDir(String tmp) { - TKit.assertTrue(TKit.isWindows(), - "setWindowsTmpDir is only valid on Windows platform"); + if (!TKit.isWindows()) { + throw new UnsupportedOperationException( + "setWindowsTmpDir is only valid on Windows platform"); + } winTmpDir = tmp; return this; } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/HelloApp.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/HelloApp.java index 71561a51cf3..2d0d23dae26 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/HelloApp.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/HelloApp.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, 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 @@ -351,6 +351,7 @@ public final class HelloApp { public final static class AppOutputVerifier { AppOutputVerifier(Path helloAppLauncher) { this.launcherPath = helloAppLauncher; + this.outputFilePath = TKit.workDir().resolve(OUTPUT_FILENAME); this.params = new HashMap<>(); this.defaultLauncherArgs = new ArrayList<>(); } @@ -367,6 +368,8 @@ public final class HelloApp { public AppOutputVerifier addParam(String name, String value) { if (name.startsWith("param")) { params.put(name, value); + } else if ("jpackage.test.appOutput".equals(name)) { + outputFilePath = Path.of(value); } return this; } @@ -397,6 +400,18 @@ public final class HelloApp { .collect(Collectors.toList())); } + public void verifyOutput(String... args) { + final List launcherArgs = List.of(args); + final List appArgs; + if (launcherArgs.isEmpty()) { + appArgs = defaultLauncherArgs; + } else { + appArgs = launcherArgs; + } + + verifyOutputFile(outputFilePath, appArgs, params); + } + public void executeAndVerifyOutput(String... args) { executeAndVerifyOutput(false, args); } @@ -408,8 +423,7 @@ public final class HelloApp { getExecutor(launcherArgs.toArray(new String[0])).dumpOutput().setRemovePath( removePath).executeAndRepeatUntilExitCode(0, attempts, waitBetweenAttemptsSeconds); - Path outputFile = TKit.workDir().resolve(OUTPUT_FILENAME); - verifyOutputFile(outputFile, appArgs, params); + verifyOutputFile(outputFilePath, appArgs, params); } public void executeAndVerifyOutput(boolean removePath, String... args) { @@ -453,6 +467,7 @@ public final class HelloApp { } private final Path launcherPath; + private Path outputFilePath; private final List defaultLauncherArgs; private final Map params; } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java index b68fe08bd1e..d30f96ff786 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, 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,6 +47,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import jdk.jpackage.internal.AppImageFile; import jdk.jpackage.internal.ApplicationLayout; +import static jdk.jpackage.test.AdditionalLauncher.forEachAdditionalLauncher; import jdk.jpackage.test.Functional.ThrowingConsumer; import jdk.jpackage.test.Functional.ThrowingFunction; import jdk.jpackage.test.Functional.ThrowingSupplier; @@ -242,6 +243,17 @@ public final class JPackageCommand extends CommandArguments { return this; } + public JPackageCommand setInputToEmptyDirectory() { + if (Files.exists(inputDir())) { + try { + setArgumentValue("--input", TKit.createTempDirectory("input")); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + return this; + } + public JPackageCommand setFakeRuntime() { verifyMutable(); @@ -414,6 +426,28 @@ public final class JPackageCommand extends CommandArguments { return unpackDir.resolve(TKit.removeRootFromAbsolutePath(path)); } + /** + * Returns path to package file from the path in unpacked package directory + * or the given path if the package is not unpacked. + */ + public Path pathToPackageFile(Path path) { + Path unpackDir = unpackedPackageDirectory(); + if (unpackDir == null) { + if (!path.isAbsolute()) { + throw new IllegalArgumentException(String.format( + "Path [%s] is not absolute", path)); + } + return path; + } + + if (!path.startsWith(unpackDir)) { + throw new IllegalArgumentException(String.format( + "Path [%s] doesn't start with [%s] path", path, unpackDir)); + } + + return Path.of("/").resolve(unpackDir.relativize(path)); + } + Path unpackedPackageDirectory() { verifyIsOfType(PackageType.NATIVE); return getArgumentValue(UNPACKED_PATH_ARGNAME, () -> null, Path::of); @@ -497,6 +531,18 @@ public final class JPackageCommand extends CommandArguments { return appLauncherPath(null); } + /** + * Returns names of all additional launchers or empty list if none + * configured. + */ + public List addLauncherNames() { + List names = new ArrayList<>(); + forEachAdditionalLauncher(this, (launcherName, propFile) -> { + names.add(launcherName); + }); + return names; + } + private void verifyNotRuntime() { if (isRuntime()) { throw new IllegalArgumentException("Java runtime packaging"); @@ -537,9 +583,9 @@ public final class JPackageCommand extends CommandArguments { throw TKit.throwUnknownPlatformError(); } - if (criticalRuntimeFiles.stream().filter( - v -> runtimeDir.resolve(v).toFile().exists()).findFirst().orElse( - null) == null) { + if (!criticalRuntimeFiles.stream().anyMatch(v -> { + return runtimeDir.resolve(v).toFile().exists(); + })) { // Fake runtime TKit.trace(String.format( "%s because application runtime directory [%s] is incomplete", @@ -738,7 +784,7 @@ public final class JPackageCommand extends CommandArguments { appImageFileName)); } } - } else if (TKit.isOSX()) { + } else if (TKit.isOSX() && !isRuntime()) { TKit.assertFileExists(AppImageFile.getPathInAppImage( appInstallationDirectory())); } else { @@ -763,7 +809,11 @@ public final class JPackageCommand extends CommandArguments { JPackageCommand setUnpackedPackageLocation(Path path) { verifyIsOfType(PackageType.NATIVE); - setArgumentValue(UNPACKED_PATH_ARGNAME, path); + if (path != null) { + setArgumentValue(UNPACKED_PATH_ARGNAME, path); + } else { + removeArgumentWithValue(UNPACKED_PATH_ARGNAME); + } return this; } @@ -788,6 +838,11 @@ public final class JPackageCommand extends CommandArguments { return createExecutor().getPrintableCommandLine(); } + @Override + public String toString() { + return getPrintableCommandLine(); + } + public void verifyIsOfType(Collection types) { verifyIsOfType(types.toArray(PackageType[]::new)); } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JavaTool.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JavaTool.java index de5a4e4d8e4..7b217b2431c 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JavaTool.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JavaTool.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,7 +40,7 @@ public enum JavaTool { } } - Path getPath() { + public Path getPath() { return path; } @@ -48,7 +48,7 @@ public enum JavaTool { return ToolProvider.findFirst(toolName()).orElse(null); } - Path relativePathInJavaHome() { + private Path relativePathInJavaHome() { Path path = Path.of("bin", toolName()); if (TKit.isWindows()) { path = path.getParent().resolve(path.getFileName().toString() + ".exe"); diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LinuxHelper.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LinuxHelper.java index 5b91b829457..4d096198c9d 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LinuxHelper.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LinuxHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, 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 @@ -42,8 +42,7 @@ import jdk.jpackage.internal.IOUtils; import jdk.jpackage.test.PackageTest.PackageHandlers; - -public class LinuxHelper { +public final class LinuxHelper { private static String getReleaseSuffix(JPackageCommand cmd) { String value = null; final PackageType packageType = cmd.packageType(); @@ -183,7 +182,10 @@ public class LinuxHelper { }; deb.uninstallHandler = cmd -> { cmd.verifyIsOfType(PackageType.LINUX_DEB); - Executor.of("sudo", "dpkg", "-r", getPackageName(cmd)).execute(); + var packageName = getPackageName(cmd); + String script = String.format("! dpkg -s %s || sudo dpkg -r %s", + packageName, packageName); + Executor.of("sh", "-c", script).execute(); }; deb.unpackHandler = (cmd, destinationDir) -> { cmd.verifyIsOfType(PackageType.LINUX_DEB); @@ -200,13 +202,16 @@ public class LinuxHelper { PackageHandlers rpm = new PackageHandlers(); rpm.installHandler = cmd -> { cmd.verifyIsOfType(PackageType.LINUX_RPM); - Executor.of("sudo", "rpm", "-i") + Executor.of("sudo", "rpm", "-U") .addArgument(cmd.outputBundle()) .execute(); }; rpm.uninstallHandler = cmd -> { cmd.verifyIsOfType(PackageType.LINUX_RPM); - Executor.of("sudo", "rpm", "-e", getPackageName(cmd)).execute(); + var packageName = getPackageName(cmd); + String script = String.format("! rpm -q %s || sudo rpm -e %s", + packageName, packageName); + Executor.of("sh", "-c", script).execute(); }; rpm.unpackHandler = (cmd, destinationDir) -> { cmd.verifyIsOfType(PackageType.LINUX_RPM); @@ -363,10 +368,10 @@ public class LinuxHelper { test.addInstallVerifier(cmd -> { // Verify .desktop files. - try (var files = Files.walk(cmd.appLayout().destktopIntegrationDirectory(), 1)) { + try (var files = Files.list(cmd.appLayout().destktopIntegrationDirectory())) { List desktopFiles = files .filter(path -> path.getFileName().toString().endsWith(".desktop")) - .collect(Collectors.toList()); + .toList(); if (!integrated) { TKit.assertStringListEquals(List.of(), desktopFiles.stream().map(Path::toString).collect( @@ -470,23 +475,18 @@ public class LinuxHelper { String desktopFileName = queryMimeTypeDefaultHandler(mimeType); - Path desktopFile = getSystemDesktopFilesFolder().resolve( + Path systemDesktopFile = getSystemDesktopFilesFolder().resolve( + desktopFileName); + Path appDesktopFile = cmd.appLayout().destktopIntegrationDirectory().resolve( desktopFileName); - TKit.assertFileExists(desktopFile); - - TKit.trace(String.format("Reading [%s] file...", desktopFile)); - String mimeHandler = Files.readAllLines(desktopFile).stream().peek( - v -> TKit.trace(v)).filter( - v -> v.startsWith("Exec=")).map( - v -> v.split("=", 2)[1]).findFirst().orElseThrow(); - - TKit.trace(String.format("Done")); - - TKit.assertEquals(cmd.appLauncherPath().toString(), - mimeHandler, String.format( - "Check mime type handler is the main application launcher")); + TKit.assertFileExists(systemDesktopFile); + TKit.assertFileExists(appDesktopFile); + TKit.assertStringListEquals(Files.readAllLines(appDesktopFile), + Files.readAllLines(systemDesktopFile), String.format( + "Check [%s] file is a copy of [%s] file", + systemDesktopFile, appDesktopFile)); }); }); diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacHelper.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacHelper.java index 9b6457ccc58..7f5887f0ac3 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacHelper.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,6 +39,7 @@ import javax.xml.parsers.ParserConfigurationException; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathFactory; +import jdk.jpackage.internal.IOUtils; import jdk.jpackage.test.Functional.ThrowingConsumer; import jdk.jpackage.test.Functional.ThrowingSupplier; import jdk.jpackage.test.PackageTest.PackageHandlers; @@ -46,7 +47,7 @@ import jdk.jpackage.internal.RetryExecutor; import org.xml.sax.SAXException; import org.w3c.dom.NodeList; -public class MacHelper { +public final class MacHelper { public static void withExplodedDmg(JPackageCommand cmd, ThrowingConsumer consumer) { @@ -172,41 +173,62 @@ public class MacHelper { pkg.installHandler = cmd -> { cmd.verifyIsOfType(PackageType.MAC_PKG); Executor.of("sudo", "/usr/sbin/installer", "-allowUntrusted", "-pkg") - .addArgument(cmd.outputBundle()) - .addArguments("-target", "/") - .execute(); + .addArgument(cmd.outputBundle()) + .addArguments("-target", "/") + .execute(); }; pkg.unpackHandler = (cmd, destinationDir) -> { cmd.verifyIsOfType(PackageType.MAC_PKG); + + var dataDir = destinationDir.resolve("data"); + Executor.of("pkgutil", "--expand") - .addArgument(cmd.outputBundle()) - .addArgument(destinationDir.resolve("data")) // We need non-existing folder - .execute(); + .addArgument(cmd.outputBundle()) + .addArgument(dataDir) // We need non-existing folder + .execute(); final Path unpackRoot = destinationDir.resolve("unpacked"); - Path installDir = TKit.removeRootFromAbsolutePath( - getInstallationDirectory(cmd)).getParent(); - final Path unpackDir = unpackRoot.resolve(installDir); - try { - Files.createDirectories(unpackDir); + // Unpack all ".pkg" files from $dataDir folder in $unpackDir folder + try (var dataListing = Files.list(dataDir)) { + dataListing.filter(file -> { + return ".pkg".equals(IOUtils.getSuffix(file.getFileName())); + }).forEach(ThrowingConsumer.toConsumer(pkgDir -> { + // Installation root of the package is stored in + // /pkg-info@install-location attribute in $pkgDir/PackageInfo xml file + var doc = createDocumentBuilder().parse( + new ByteArrayInputStream(Files.readAllBytes( + pkgDir.resolve("PackageInfo")))); + var xPath = XPathFactory.newInstance().newXPath(); + + final String installRoot = (String) xPath.evaluate( + "/pkg-info/@install-location", doc, + XPathConstants.STRING); + + final Path unpackDir = unpackRoot.resolve( + TKit.removeRootFromAbsolutePath(Path.of(installRoot))); + + Files.createDirectories(unpackDir); + + Executor.of("tar", "-C") + .addArgument(unpackDir) + .addArgument("-xvf") + .addArgument(pkgDir.resolve("Payload")) + .execute(); + })); } catch (IOException ex) { throw new RuntimeException(ex); } - Executor.of("tar", "-C") - .addArgument(unpackDir) - .addArgument("-xvf") - .addArgument(Path.of(destinationDir.toString(), "data", - cmd.name() + "-app.pkg", "Payload")) - .execute(); return unpackRoot; }; pkg.uninstallHandler = cmd -> { cmd.verifyIsOfType(PackageType.MAC_PKG); + Executor.of("sudo", "rm", "-rf") - .addArgument(cmd.appInstallationDirectory()) - .execute(); + .addArgument(cmd.appInstallationDirectory()) + .execute(); + }; return pkg; @@ -220,13 +242,13 @@ public class MacHelper { static Path getInstallationDirectory(JPackageCommand cmd) { cmd.verifyIsOfType(PackageType.MAC); - return Path.of(cmd.getArgumentValue("--install-dir", () -> "/Applications")) - .resolve(cmd.name() + (cmd.isRuntime() ? "" : ".app")); + return Path.of(cmd.getArgumentValue("--install-dir", + () -> cmd.isRuntime() ? "/Library/Java/JavaVirtualMachines" : "/Applications")).resolve( + cmd.name() + (cmd.isRuntime() ? "" : ".app")); } private static String getPackageName(JPackageCommand cmd) { - return cmd.getArgumentValue("--mac-package-name", - () -> cmd.installerName()); + return cmd.getArgumentValue("--mac-package-name", cmd::installerName); } public static final class PListWrapper { @@ -274,25 +296,24 @@ public class MacHelper { return values; } - PListWrapper(String xml) throws ParserConfigurationException, + private PListWrapper(String xml) throws ParserConfigurationException, SAXException, IOException { doc = createDocumentBuilder().parse(new ByteArrayInputStream( xml.getBytes(StandardCharsets.UTF_8))); } - private static DocumentBuilder createDocumentBuilder() throws - ParserConfigurationException { - DocumentBuilderFactory dbf = DocumentBuilderFactory.newDefaultInstance(); - dbf.setFeature( - "http://apache.org/xml/features/nonvalidating/load-external-dtd", - false); - return dbf.newDocumentBuilder(); - } - private final org.w3c.dom.Document doc; } + private static DocumentBuilder createDocumentBuilder() throws + ParserConfigurationException { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newDefaultInstance(); + dbf.setFeature( + "http://apache.org/xml/features/nonvalidating/load-external-dtd", + false); + return dbf.newDocumentBuilder(); + } + static final Set CRITICAL_RUNTIME_FILES = Set.of(Path.of( "Contents/Home/lib/server/libjvm.dylib")); - } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageTest.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageTest.java index f81fb1c170c..0884b41dc55 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageTest.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ package jdk.jpackage.test; import java.awt.Desktop; import java.awt.GraphicsEnvironment; import java.io.File; +import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; @@ -36,19 +37,32 @@ import java.util.List; import java.util.ListIterator; import java.util.Map; import java.util.Objects; +import java.util.Optional; import java.util.Set; import java.util.function.BiConsumer; import java.util.function.BiFunction; import java.util.function.Consumer; import java.util.function.Predicate; +import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.Stream; -import jdk.jpackage.internal.AppImageFile; import jdk.jpackage.internal.ApplicationLayout; import jdk.jpackage.test.Functional.ThrowingBiConsumer; +import static jdk.jpackage.test.Functional.ThrowingBiConsumer.toBiConsumer; import jdk.jpackage.test.Functional.ThrowingConsumer; +import static jdk.jpackage.test.Functional.ThrowingConsumer.toConsumer; import jdk.jpackage.test.Functional.ThrowingRunnable; - +import static jdk.jpackage.test.Functional.ThrowingSupplier.toSupplier; +import static jdk.jpackage.test.Functional.rethrowUnchecked; +import static jdk.jpackage.test.PackageType.LINUX; +import static jdk.jpackage.test.PackageType.LINUX_DEB; +import static jdk.jpackage.test.PackageType.LINUX_RPM; +import static jdk.jpackage.test.PackageType.MAC_DMG; +import static jdk.jpackage.test.PackageType.MAC_PKG; +import static jdk.jpackage.test.PackageType.NATIVE; +import static jdk.jpackage.test.PackageType.WINDOWS; +import static jdk.jpackage.test.PackageType.WIN_EXE; +import static jdk.jpackage.test.PackageType.WIN_MSI; /** @@ -82,7 +96,7 @@ public final class PackageTest extends RunnablePackageTest { public PackageTest forTypes(PackageType... types) { Collection newTypes; if (types == null || types.length == 0) { - newTypes = PackageType.NATIVE; + newTypes = NATIVE; } else { newTypes = Stream.of(types).collect(Collectors.toSet()); } @@ -122,7 +136,7 @@ public final class PackageTest extends RunnablePackageTest { namedInitializers.add(id); } currentTypes.forEach(type -> handlers.get(type).addInitializer( - ThrowingConsumer.toConsumer(v))); + toConsumer(v))); return this; } @@ -151,13 +165,12 @@ public final class PackageTest extends RunnablePackageTest { public PackageTest addBundleVerifier( ThrowingBiConsumer v) { currentTypes.forEach(type -> handlers.get(type).addBundleVerifier( - ThrowingBiConsumer.toBiConsumer(v))); + toBiConsumer(v))); return this; } public PackageTest addBundleVerifier(ThrowingConsumer v) { - return addBundleVerifier( - (cmd, unused) -> ThrowingConsumer.toConsumer(v).accept(cmd)); + return addBundleVerifier((cmd, unused) -> toConsumer(v).accept(cmd)); } public PackageTest addBundlePropertyVerifier(String propertyName, @@ -184,7 +197,7 @@ public final class PackageTest extends RunnablePackageTest { } public PackageTest addBundleDesktopIntegrationVerifier(boolean integrated) { - forTypes(PackageType.LINUX, () -> { + forTypes(LINUX, () -> { LinuxHelper.addBundleDesktopIntegrationVerifier(this, integrated); }); return this; @@ -192,31 +205,25 @@ public final class PackageTest extends RunnablePackageTest { public PackageTest addInstallVerifier(ThrowingConsumer v) { currentTypes.forEach(type -> handlers.get(type).addInstallVerifier( - ThrowingConsumer.toConsumer(v))); + toConsumer(v))); return this; } public PackageTest addUninstallVerifier(ThrowingConsumer v) { currentTypes.forEach(type -> handlers.get(type).addUninstallVerifier( - ThrowingConsumer.toConsumer(v))); + toConsumer(v))); return this; } - public PackageTest setPackageInstaller(Consumer v) { + public PackageTest disablePackageInstaller() { currentTypes.forEach( - type -> packageHandlers.get(type).installHandler = v); - return this; - } - - public PackageTest setPackageUnpacker( - BiFunction v) { - currentTypes.forEach(type -> packageHandlers.get(type).unpackHandler = v); + type -> packageHandlers.get(type).installHandler = cmd -> {}); return this; } - public PackageTest setPackageUninstaller(Consumer v) { + public PackageTest disablePackageUninstaller() { currentTypes.forEach( - type -> packageHandlers.get(type).uninstallHandler = v); + type -> packageHandlers.get(type).uninstallHandler = cmd -> {}); return this; } @@ -238,7 +245,7 @@ public final class PackageTest extends RunnablePackageTest { // running check of type of environment. addHelloAppInitializer(null); - forTypes(PackageType.LINUX, () -> { + forTypes(LINUX, () -> { LinuxHelper.addFileAssociationsVerifier(this, fa); }); @@ -317,11 +324,6 @@ public final class PackageTest extends RunnablePackageTest { return this; } - public PackageTest addLauncherName(String name) { - launcherNames.add(name); - return this; - } - public final static class Group extends RunnablePackageTest { public Group(PackageTest... tests) { handlers = Stream.of(tests) @@ -372,7 +374,7 @@ public final class PackageTest extends RunnablePackageTest { } private List> createPackageTypeHandlers() { - return PackageType.NATIVE.stream() + return NATIVE.stream() .map(type -> { Handler handler = handlers.entrySet().stream() .filter(entry -> !entry.getValue().isVoid()) @@ -393,29 +395,39 @@ public final class PackageTest extends RunnablePackageTest { private Consumer createPackageTypeHandler( PackageType type, Handler handler) { - return ThrowingConsumer.toConsumer(new ThrowingConsumer() { + return toConsumer(new ThrowingConsumer() { @Override public void accept(Action action) throws Throwable { + if (terminated) { + throw new IllegalStateException(); + } + if (action == Action.FINALIZE) { - if (unpackDir != null && Files.isDirectory(unpackDir) - && !unpackDir.startsWith(TKit.workDir())) { - TKit.deleteDirectoryRecursive(unpackDir); + if (unpackDir != null) { + if (Files.isDirectory(unpackDir) + && !unpackDir.startsWith(TKit.workDir())) { + TKit.deleteDirectoryRecursive(unpackDir); + } + unpackDir = null; } + terminated = true; } if (aborted) { return; } - final JPackageCommand curCmd; - if (Set.of(Action.INITIALIZE, Action.CREATE).contains(action)) { - curCmd = cmd; - } else { - curCmd = cmd.createImmutableCopy(); - } + final Supplier curCmd = () -> { + if (Set.of(Action.INITIALIZE, Action.CREATE).contains(action)) { + return cmd; + } else { + return cmd.createImmutableCopy(); + } + }; switch (action) { case UNPACK: { + cmd.setUnpackedPackageLocation(null); var handler = packageHandlers.get(type).unpackHandler; if (!(aborted = (handler == null))) { unpackDir = TKit.createTempDirectory( @@ -428,9 +440,10 @@ public final class PackageTest extends RunnablePackageTest { } case INSTALL: { + cmd.setUnpackedPackageLocation(null); var handler = packageHandlers.get(type).installHandler; if (!(aborted = (handler == null))) { - handler.accept(curCmd); + handler.accept(curCmd.get()); } break; } @@ -438,18 +451,19 @@ public final class PackageTest extends RunnablePackageTest { case UNINSTALL: { var handler = packageHandlers.get(type).uninstallHandler; if (!(aborted = (handler == null))) { - handler.accept(curCmd); + handler.accept(curCmd.get()); } break; } case CREATE: - handler.accept(action, curCmd); + cmd.setUnpackedPackageLocation(null); + handler.accept(action, curCmd.get()); aborted = (expectedJPackageExitCode != 0); return; default: - handler.accept(action, curCmd); + handler.accept(action, curCmd.get()); break; } @@ -462,6 +476,7 @@ public final class PackageTest extends RunnablePackageTest { private Path unpackDir; private boolean aborted; + private boolean terminated; private final JPackageCommand cmd = Functional.identity(() -> { JPackageCommand result = new JPackageCommand(); result.setDefaultInputOutput().setDefaultAppName(); @@ -535,13 +550,23 @@ public final class PackageTest extends RunnablePackageTest { verifyPackageUninstalled(cmd); } break; + + case PURGE: + if (expectedJPackageExitCode == 0) { + var bundle = cmd.outputBundle(); + if (toSupplier(() -> TKit.deleteIfExists(bundle)).get()) { + TKit.trace(String.format("Deleted [%s] package", + bundle)); + } + } + break; } } private void verifyPackageBundle(JPackageCommand cmd, Executor.Result result) { if (expectedJPackageExitCode == 0) { - if (PackageType.LINUX.contains(cmd.packageType())) { + if (LINUX.contains(cmd.packageType())) { LinuxHelper.verifyPackageBundleEssential(cmd); } } @@ -557,35 +582,85 @@ public final class PackageTest extends RunnablePackageTest { } TKit.trace(String.format(formatString, cmd.getPrintableCommandLine())); + Optional.ofNullable(cmd.unpackedPackageDirectory()).ifPresent( + unpackedDir -> { + verifyRootCountInUnpackedPackage(cmd, unpackedDir); + }); + if (!cmd.isRuntime()) { - if (PackageType.WINDOWS.contains(cmd.packageType()) + if (WINDOWS.contains(cmd.packageType()) && !cmd.isPackageUnpacked( "Not verifying desktop integration")) { // Check main launcher - new WindowsHelper.DesktopIntegrationVerifier(cmd, null); + WindowsHelper.verifyDesktopIntegration(cmd, null); // Check additional launchers - launcherNames.forEach(name -> { - new WindowsHelper.DesktopIntegrationVerifier(cmd, name); + cmd.addLauncherNames().forEach(name -> { + WindowsHelper.verifyDesktopIntegration(cmd, name); }); } } + cmd.assertAppLayout(); installVerifiers.forEach(v -> v.accept(cmd)); } + private void verifyRootCountInUnpackedPackage(JPackageCommand cmd, + Path unpackedDir) { + + final long expectedRootCount; + if (WINDOWS.contains(cmd.packageType())) { + // On Windows it is always two entries: + // installation home directory and MSI file + expectedRootCount = 2; + } else if (LINUX.contains(cmd.packageType())) { + Set roots = new HashSet<>(); + roots.add(Path.of("/").resolve(Path.of(cmd.getArgumentValue( + "--install-dir", () -> "/opt")).getName(0))); + if (cmd.hasArgument("--license-file")) { + switch (cmd.packageType()) { + case LINUX_RPM -> { + // License file is in /usr/share/licenses subtree + roots.add(Path.of("/usr")); + } + + case LINUX_DEB -> { + Path installDir = cmd.appInstallationDirectory(); + if (installDir.equals(Path.of("/")) + || installDir.startsWith("/usr")) { + // License file is in /usr/share/doc subtree + roots.add(Path.of("/usr")); + } + } + } + } + expectedRootCount = roots.size(); + } else { + expectedRootCount = 1; + } + + try ( var files = Files.list(unpackedDir)) { + TKit.assertEquals(expectedRootCount, files.count(), + String.format( + "Check the package has %d top installation directories", + expectedRootCount)); + } catch (IOException ex) { + rethrowUnchecked(ex); + } + } + private void verifyPackageUninstalled(JPackageCommand cmd) { TKit.trace(String.format("Verify uninstalled: %s", cmd.getPrintableCommandLine())); if (!cmd.isRuntime()) { TKit.assertPathExists(cmd.appLauncherPath(), false); - if (PackageType.WINDOWS.contains(cmd.packageType())) { + if (WINDOWS.contains(cmd.packageType())) { // Check main launcher - new WindowsHelper.DesktopIntegrationVerifier(cmd, null); + WindowsHelper.verifyDesktopIntegration(cmd, null); // Check additional launchers - launcherNames.forEach(name -> { - new WindowsHelper.DesktopIntegrationVerifier(cmd, name); + cmd.addLauncherNames().forEach(name -> { + WindowsHelper.verifyDesktopIntegration(cmd, name); }); } } @@ -610,18 +685,18 @@ public final class PackageTest extends RunnablePackageTest { private static Map createDefaultPackageHandlers() { HashMap handlers = new HashMap<>(); if (TKit.isLinux()) { - handlers.put(PackageType.LINUX_DEB, LinuxHelper.createDebPackageHandlers()); - handlers.put(PackageType.LINUX_RPM, LinuxHelper.createRpmPackageHandlers()); + handlers.put(LINUX_DEB, LinuxHelper.createDebPackageHandlers()); + handlers.put(LINUX_RPM, LinuxHelper.createRpmPackageHandlers()); } if (TKit.isWindows()) { - handlers.put(PackageType.WIN_MSI, WindowsHelper.createMsiPackageHandlers()); - handlers.put(PackageType.WIN_EXE, WindowsHelper.createExePackageHandlers()); + handlers.put(WIN_MSI, WindowsHelper.createMsiPackageHandlers()); + handlers.put(WIN_EXE, WindowsHelper.createExePackageHandlers()); } if (TKit.isOSX()) { - handlers.put(PackageType.MAC_DMG, MacHelper.createDmgPackageHandlers()); - handlers.put(PackageType.MAC_PKG, MacHelper.createPkgPackageHandlers()); + handlers.put(MAC_DMG, MacHelper.createDmgPackageHandlers()); + handlers.put(MAC_PKG, MacHelper.createPkgPackageHandlers()); } return handlers; @@ -633,7 +708,6 @@ public final class PackageTest extends RunnablePackageTest { private Map handlers; private Set namedInitializers; private Map packageHandlers; - private final List launcherNames = new ArrayList(); private final static File BUNDLE_OUTPUT_DIR; diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/RunnablePackageTest.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/RunnablePackageTest.java index 6f98cfc234d..a5cedc5c34e 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/RunnablePackageTest.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/RunnablePackageTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,6 +41,12 @@ public abstract class RunnablePackageTest { .filter(Predicate.not(Action.INITIALIZE::equals)) .filter(Predicate.not(Action.FINALIZE::equals)) .collect(Collectors.toList())); + if (hasAction(Action.PURGE) && !actionList.contains(Action.PURGE)) { + // Default action list contains "purge" action meaning + // packages are not needed for further processing. + // Copy this behavior in custom action list. + actionList.add(Action.PURGE); + } } actionList.add(Action.FINALIZE); @@ -51,6 +57,10 @@ public abstract class RunnablePackageTest { runActions(actionGroups); } + public static boolean hasAction(Action a) { + return DEFAULT_ACTIONS.contains(a); + } + protected void runActions(List actions) { actions.forEach(this::runAction); } @@ -89,6 +99,10 @@ public abstract class RunnablePackageTest { * Uninstall package. */ UNINSTALL, + /** + * Purge package. + */ + PURGE, /** * Finalize test. */ diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java index fb88d4cd21d..1907c074504 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, 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 diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WindowsHelper.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WindowsHelper.java index 528973bea22..a3f67e01d46 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WindowsHelper.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WindowsHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -58,7 +58,7 @@ public class WindowsHelper { private static Path getInstallationSubDirectory(JPackageCommand cmd) { cmd.verifyIsOfType(PackageType.WINDOWS); - return Path.of(cmd.getArgumentValue("--install-dir", () -> cmd.name())); + return Path.of(cmd.getArgumentValue("--install-dir", cmd::name)); } private static void runMsiexecWithRetries(Executor misexec) { @@ -66,7 +66,13 @@ public class WindowsHelper { for (int attempt = 0; attempt < 8; ++attempt) { result = misexec.executeWithoutExitCodeCheck(); - // The given Executor may either be of an msiexe command or an + if (result.exitCode == 1605) { + // ERROR_UNKNOWN_PRODUCT, attempt to uninstall not installed + // package + return; + } + + // The given Executor may either be of an msiexec command or an // unpack.bat script containing the msiexec command. In the later // case, when misexec returns 1618, the unpack.bat may return 1603 if ((result.exitCode == 1618) || (result.exitCode == 1603)) { @@ -91,16 +97,25 @@ public class WindowsHelper { PackageHandlers msi = new PackageHandlers(); msi.installHandler = cmd -> installMsi.accept(cmd, true); - msi.uninstallHandler = cmd -> installMsi.accept(cmd, false); + msi.uninstallHandler = cmd -> { + if (Files.exists(cmd.outputBundle())) { + installMsi.accept(cmd, false); + } + }; msi.unpackHandler = (cmd, destinationDir) -> { cmd.verifyIsOfType(PackageType.WIN_MSI); final Path unpackBat = destinationDir.resolve("unpack.bat"); final Path unpackDir = destinationDir.resolve( TKit.removeRootFromAbsolutePath( getInstallationRootDirectory(cmd))); + // Put msiexec in .bat file because can't pass value of TARGETDIR // property containing spaces through ProcessBuilder properly. - TKit.createTextFile(unpackBat, List.of(String.join(" ", List.of( + // Set folder permissions to allow msiexec unpack msi bundle. + TKit.createTextFile(unpackBat, List.of( + String.format("icacls \"%s\" /inheritance:e /grant Users:M", + destinationDir), + String.join(" ", List.of( "msiexec", "/a", String.format("\"%s\"", cmd.outputBundle().normalize()), @@ -125,10 +140,19 @@ public class WindowsHelper { PackageHandlers exe = new PackageHandlers(); exe.installHandler = cmd -> installExe.accept(cmd, true); - exe.uninstallHandler = cmd -> installExe.accept(cmd, false); + exe.uninstallHandler = cmd -> { + if (Files.exists(cmd.outputBundle())) { + installExe.accept(cmd, false); + } + }; return exe; } + static void verifyDesktopIntegration(JPackageCommand cmd, + String launcherName) { + new DesktopIntegrationVerifier(cmd, launcherName); + } + public static String getMsiProperty(JPackageCommand cmd, String propertyName) { cmd.verifyIsOfType(PackageType.WIN_MSI); return Executor.of("cscript.exe", "//Nologo") @@ -143,21 +167,45 @@ public class WindowsHelper { return cmd.hasArgument("--win-per-user-install"); } - static class DesktopIntegrationVerifier { + private static class DesktopIntegrationVerifier { - DesktopIntegrationVerifier(JPackageCommand cmd, String name) { + DesktopIntegrationVerifier(JPackageCommand cmd, String launcherName) { cmd.verifyIsOfType(PackageType.WINDOWS); - this.cmd = cmd; - this.name = (name == null ? cmd.name() : name); + + name = Optional.ofNullable(launcherName).orElseGet(cmd::name); + + isUserLocalInstall = isUserLocalInstall(cmd); + + appInstalled = cmd.appLauncherPath(launcherName).toFile().exists(); + + desktopShortcutPath = Path.of(name + ".lnk"); + + startMenuShortcutPath = Path.of(cmd.getArgumentValue( + "--win-menu-group", () -> "Unknown"), name + ".lnk"); + + if (name.equals(cmd.name())) { + isWinMenu = cmd.hasArgument("--win-menu"); + isDesktop = cmd.hasArgument("--win-shortcut"); + } else { + var props = AdditionalLauncher.getAdditionalLauncherProperties(cmd, + launcherName); + isWinMenu = props.getPropertyBooleanValue("win-menu").orElseGet( + () -> cmd.hasArgument("--win-menu")); + isDesktop = props.getPropertyBooleanValue("win-shortcut").orElseGet( + () -> cmd.hasArgument("--win-shortcut")); + } + verifyStartMenuShortcut(); + verifyDesktopShortcut(); - verifyFileAssociationsRegistry(); + + Stream.of(cmd.getAllArgumentValues("--file-associations")).map( + Path::of).forEach(this::verifyFileAssociationsRegistry); } private void verifyDesktopShortcut() { - boolean appInstalled = cmd.appLauncherPath(name).toFile().exists(); - if (cmd.hasArgument("--win-shortcut")) { - if (isUserLocalInstall(cmd)) { + if (isDesktop) { + if (isUserLocalInstall) { verifyUserLocalDesktopShortcut(appInstalled); verifySystemDesktopShortcut(false); } else { @@ -170,10 +218,6 @@ public class WindowsHelper { } } - private Path desktopShortcutPath() { - return Path.of(name + ".lnk"); - } - private void verifyShortcut(Path path, boolean exists) { if (exists) { TKit.assertFileExists(path); @@ -185,19 +229,18 @@ public class WindowsHelper { private void verifySystemDesktopShortcut(boolean exists) { Path dir = Path.of(queryRegistryValueCache( SYSTEM_SHELL_FOLDERS_REGKEY, "Common Desktop")); - verifyShortcut(dir.resolve(desktopShortcutPath()), exists); + verifyShortcut(dir.resolve(desktopShortcutPath), exists); } private void verifyUserLocalDesktopShortcut(boolean exists) { Path dir = Path.of( queryRegistryValueCache(USER_SHELL_FOLDERS_REGKEY, "Desktop")); - verifyShortcut(dir.resolve(desktopShortcutPath()), exists); + verifyShortcut(dir.resolve(desktopShortcutPath), exists); } private void verifyStartMenuShortcut() { - boolean appInstalled = cmd.appLauncherPath(name).toFile().exists(); - if (cmd.hasArgument("--win-menu")) { - if (isUserLocalInstall(cmd)) { + if (isWinMenu) { + if (isUserLocalInstall) { verifyUserLocalStartMenuShortcut(appInstalled); verifySystemStartMenuShortcut(false); } else { @@ -210,13 +253,8 @@ public class WindowsHelper { } } - private Path startMenuShortcutPath() { - return Path.of(cmd.getArgumentValue("--win-menu-group", - () -> "Unknown"), name + ".lnk"); - } - private void verifyStartMenuShortcut(Path shortcutsRoot, boolean exists) { - Path shortcutPath = shortcutsRoot.resolve(startMenuShortcutPath()); + Path shortcutPath = shortcutsRoot.resolve(startMenuShortcutPath); verifyShortcut(shortcutPath, exists); if (!exists) { TKit.assertPathNotEmptyDirectory(shortcutPath.getParent()); @@ -234,13 +272,7 @@ public class WindowsHelper { USER_SHELL_FOLDERS_REGKEY, "Programs")), exists); } - private void verifyFileAssociationsRegistry() { - Stream.of(cmd.getAllArgumentValues("--file-associations")).map( - Path::of).forEach(this::verifyFileAssociationsRegistry); - } - private void verifyFileAssociationsRegistry(Path faFile) { - boolean appInstalled = cmd.appLauncherPath(name).toFile().exists(); try { TKit.trace(String.format( "Get file association properties from [%s] file", @@ -290,7 +322,12 @@ public class WindowsHelper { } } - private final JPackageCommand cmd; + private final Path desktopShortcutPath; + private final Path startMenuShortcutPath; + private final boolean isUserLocalInstall; + private final boolean appInstalled; + private final boolean isWinMenu; + private final boolean isDesktop; private final String name; } diff --git a/test/jdk/tools/jpackage/run_tests.sh b/test/jdk/tools/jpackage/run_tests.sh index a5cb03fc3aa..2639f38cd68 100644 --- a/test/jdk/tools/jpackage/run_tests.sh +++ b/test/jdk/tools/jpackage/run_tests.sh @@ -1,6 +1,6 @@ #!/bin/bash -# Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2020, 2022, 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 @@ -78,15 +78,25 @@ help_usage () echo " Optional, for jtreg tests debug purposes only." echo ' -l - value for `jpackage.test.logfile` property.' echo " Optional, for jtreg tests debug purposes only." - echo " -m - mode to run jtreg tests." - echo ' Should be one of `create`, `update` or `print-default-tests`.' - echo ' Optional, default mode is `update`.' + echo " -m - mode to run jtreg tests. Supported values:" echo ' - `create`' echo ' Remove all package bundles from the output directory before running jtreg tests.' echo ' - `update`' echo ' Run jtreg tests and overrite existing package bundles in the output directory.' echo ' - `print-default-tests`' echo ' Print default list of packaging tests and exit.' + echo ' - `create-small-runtime`' + echo ' Create small Java runtime using /bin/jlink command in the output directory.' + echo ' - `create-packages`' + echo ' Create packages.' + echo ' The script will set `jpackage.test.action` property.' + echo ' - `test-packages`' + echo ' Create and fully test packages. Will create, unpack, install, and uninstall packages.' + echo ' The script will set `jpackage.test.action` property.' + echo ' - `do-packages`' + echo " Create, unpack and verify packages." + echo ' The script will not set `jpackage.test.action` property.' + echo ' Optional, defaults are `update` and `create-packages`.' } error () @@ -133,8 +143,6 @@ exec_command () test_jdk= # Path to local copy of open jdk repo with jpackage jtreg tests -# hg clone http://hg.openjdk.java.net/jdk/sandbox -# cd sandbox; hg update -r JDK-8200758-branch open_jdk_with_jpackage_jtreg_tests=$(dirname $0)/../../../../ # Directory where to save artifacts for testing. @@ -152,12 +160,27 @@ mode=update # jtreg extra arguments declare -a jtreg_args -# Create packages only -jtreg_args+=("-Djpackage.test.action=create") - # run all tests run_all_tests= +test_actions= + +set_mode () +{ + case "$1" in + create-packages) test_actions='-Djpackage.test.action=create';; + test-packages) test_actions='-Djpackage.test.action=uninstall,create,unpack,verify-install,install,verify-install,uninstall,verify-uninstall,purge';; + do-packages) test_actions=;; + create-small-runtime) mode=$1;; + print-default-tests) mode=$1;; + create) mode=$1;; + update) mode=$1;; + *) fatal_with_help_usage 'Invalid value of -m option:' [$1];; + esac +} + +set_mode 'create-packages' + mapfile -t tests < <(find_all_packaging_tests) while getopts "vahdct:j:o:r:m:l:" argname; do @@ -171,7 +194,7 @@ while getopts "vahdct:j:o:r:m:l:" argname; do o) output_dir="$OPTARG";; r) runtime_dir="$OPTARG";; l) logfile="$OPTARG";; - m) mode="$OPTARG";; + m) set_mode "$OPTARG";; h) help_usage; exit 0;; ?) help_usage; exit 1;; esac @@ -201,6 +224,11 @@ if [ ! -e "$JAVA_HOME/bin/java" ]; then fatal JAVA_HOME variable is set to [$JAVA_HOME] value, but $JAVA_HOME/bin/java not found. fi +if [ "$mode" = "create-small-runtime" ]; then + exec_command "$test_jdk/bin/jlink" --add-modules java.base,java.datatransfer,java.xml,java.prefs,java.desktop --compress=2 --no-header-files --no-man-pages --strip-debug --output "$output_dir" + exit +fi + if [ -z "$JT_HOME" ]; then if [ -z "$JT_BUNDLE_URL" ]; then fatal 'JT_HOME or JT_BUNDLE_URL environment variable is not set. Link to JTREG bundle can be found at https://openjdk.java.net/jtreg/'. @@ -222,18 +250,12 @@ if [ -n "$logfile" ]; then jtreg_args+=("-Djpackage.test.logfile=$(to_native_path "$logfile")") fi -if [ "$mode" = create ]; then - true -elif [ "$mode" = update ]; then - true -else - fatal_with_help_usage 'Invalid value of -m option:' [$mode] -fi - if [ -z "$run_all_tests" ]; then jtreg_args+=(-Djpackage.test.SQETest=yes) fi +jtreg_args+=("$test_actions") + # Drop arguments separator [ "$1" != "--" ] || shift @@ -249,10 +271,10 @@ installJtreg () if [ ! -f "$jtreg_jar" ]; then exec_command mkdir -p "$workdir" if [[ ${jtreg_bundle: -7} == ".tar.gz" ]]; then - exec_command "(" cd "$workdir" "&&" wget "$jtreg_bundle" "&&" tar -xzf "$(basename $jtreg_bundle)" ";" rm -f "$(basename $jtreg_bundle)" ")" + exec_command "(" cd "$workdir" "&&" wget --no-check-certificate "$jtreg_bundle" "&&" tar -xzf "$(basename $jtreg_bundle)" ";" rm -f "$(basename $jtreg_bundle)" ")" else if [[ ${jtreg_bundle: -4} == ".zip" ]]; then - exec_command "(" cd "$workdir" "&&" wget "$jtreg_bundle" "&&" unzip "$(basename $jtreg_bundle)" ";" rm -f "$(basename $jtreg_bundle)" ")" + exec_command "(" cd "$workdir" "&&" wget --no-check-certificate "$jtreg_bundle" "&&" unzip "$(basename $jtreg_bundle)" ";" rm -f "$(basename $jtreg_bundle)" ")" else fatal 'Unsupported extension of JREG bundle ['$JT_BUNDLE_URL']. Only *.zip or *.tar.gz is supported.' fi diff --git a/test/jdk/tools/jpackage/share/MultiLauncherTwoPhaseTest.java b/test/jdk/tools/jpackage/share/MultiLauncherTwoPhaseTest.java index 5df3609e3ba..b048d6db335 100644 --- a/test/jdk/tools/jpackage/share/MultiLauncherTwoPhaseTest.java +++ b/test/jdk/tools/jpackage/share/MultiLauncherTwoPhaseTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, 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 @@ -69,8 +69,6 @@ public class MultiLauncherTwoPhaseTest { launcher2.applyTo(appImageCmd); PackageTest packageTest = new PackageTest() - .addLauncherName("bar") // Add launchers name for verification - .addLauncherName("foo") .addRunOnceInitializer(() -> appImageCmd.execute()) .addBundleDesktopIntegrationVerifier(true) .addInitializer(cmd -> { diff --git a/test/jdk/tools/jpackage/test_jpackage.sh b/test/jdk/tools/jpackage/test_jpackage.sh deleted file mode 100644 index c4b28020bc0..00000000000 --- a/test/jdk/tools/jpackage/test_jpackage.sh +++ /dev/null @@ -1,100 +0,0 @@ -#!/bin/bash - -# Copyright (c) 2020, 2021, 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. - - -# -# Complete testing of jpackage platform-specific packaging. -# -# The script does the following: -# 1. Create packages. -# 2. Install created packages. -# 3. Verifies packages are installed. -# 4. Uninstall created packages. -# 5. Verifies packages are uninstalled. -# -# For the list of accepted command line arguments see `run_tests.sh` script. -# - -# Fail fast -set -e; set -o pipefail; - -# Script debug -dry_run=${JPACKAGE_TEST_DRY_RUN} - -# Default directory where jpackage should write bundle files -output_dir=~/jpackage_bundles - - -set_args () -{ - args=() - local arg_is_output_dir= - local arg_is_mode= - local output_dir_set= - local with_append_actions=yes - for arg in "$@"; do - if [ "$arg" == "-o" ]; then - arg_is_output_dir=yes - output_dir_set=yes - elif [ "$arg" == "-m" ]; then - arg_is_mode=yes - continue - elif [ "$arg" == '--' ]; then - append_actions - with_append_actions= - continue - elif ! case "$arg" in -Djpackage.test.action=*) false;; esac; then - continue - elif [ -n "$arg_is_output_dir" ]; then - arg_is_output_dir= - output_dir="$arg" - elif [ -n "$arg_is_mode" ]; then - arg_is_mode= - continue - fi - - args+=( "$arg" ) - done - [ -n "$output_dir_set" ] || args=( -o "$output_dir" "${args[@]}" ) - [ -z "$with_append_actions" ] || append_actions -} - - -append_actions () -{ - args+=( '--' '-Djpackage.test.action=create,install,verify-install,uninstall,verify-uninstall' ) -} - - -exec_command () -{ - if [ -n "$dry_run" ]; then - echo "$@" - else - eval "$@" - fi -} - -set_args "$@" -basedir="$(dirname $0)" -exec_command ${SHELL} "$basedir/run_tests.sh" -m create "${args[@]}" diff --git a/test/jdk/tools/jpackage/windows/WinUpgradeUUIDTest.java b/test/jdk/tools/jpackage/windows/WinUpgradeUUIDTest.java index 0c233b0e652..968ed94b345 100644 --- a/test/jdk/tools/jpackage/windows/WinUpgradeUUIDTest.java +++ b/test/jdk/tools/jpackage/windows/WinUpgradeUUIDTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, 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 @@ -100,7 +100,7 @@ public class WinUpgradeUUIDTest { // It will be uninstalled automatically when the second // package will be installed. // However uninstall verification for the first package will be executed. - PackageTest test1 = init.get().setPackageUninstaller(cmd -> {}); + PackageTest test1 = init.get().disablePackageUninstaller(); PackageTest test2 = init.get().addInitializer(cmd -> { cmd.setArgumentValue("--app-version", "2.0"); -- GitLab From 1eec16b47be300e1462528bddf5d0686df3f042c Mon Sep 17 00:00:00 2001 From: Xiaohong Gong Date: Thu, 17 Feb 2022 05:44:12 +0000 Subject: [PATCH 536/564] 8281803: AArch64: Optimize masked vector NOT/AND_NOT for SVE Reviewed-by: aph, njian --- src/hotspot/cpu/aarch64/aarch64_sve.ad | 64 ++++++- src/hotspot/cpu/aarch64/aarch64_sve_ad.m4 | 56 ++++++- src/hotspot/cpu/aarch64/assembler_aarch64.hpp | 1 + test/hotspot/gtest/aarch64/aarch64-asmtest.py | 1 + test/hotspot/gtest/aarch64/asmtest.out.h | 158 +++++++++--------- 5 files changed, 198 insertions(+), 82 deletions(-) diff --git a/src/hotspot/cpu/aarch64/aarch64_sve.ad b/src/hotspot/cpu/aarch64/aarch64_sve.ad index bf00892b936..c048a463c1a 100644 --- a/src/hotspot/cpu/aarch64/aarch64_sve.ad +++ b/src/hotspot/cpu/aarch64/aarch64_sve.ad @@ -1,6 +1,6 @@ // -// Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. -// Copyright (c) 2020, 2021, Arm Limited. All rights reserved. +// Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2020, 2022, Arm Limited. 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 @@ -1288,6 +1288,36 @@ instruct vnotL(vReg dst, vReg src, immL_M1 m1) %{ ins_pipe(pipe_slow); %} +// vector not - predicated + +instruct vnotI_masked(vReg dst, vReg src, immI_M1 m1, pRegGov pg) %{ + predicate(UseSVE > 0); + match(Set dst (XorV (Binary src (ReplicateB m1)) pg)); + match(Set dst (XorV (Binary src (ReplicateS m1)) pg)); + match(Set dst (XorV (Binary src (ReplicateI m1)) pg)); + ins_cost(SVE_COST); + format %{ "sve_not $dst, $pg, $src\t# vector (sve) B/H/S" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + __ sve_not(as_FloatRegister($dst$$reg), __ elemType_to_regVariant(bt), + as_PRegister($pg$$reg), as_FloatRegister($src$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vnotL_masked(vReg dst, vReg src, immL_M1 m1, pRegGov pg) %{ + predicate(UseSVE > 0); + match(Set dst (XorV (Binary src (ReplicateL m1)) pg)); + ins_cost(SVE_COST); + format %{ "sve_not $dst, $pg, $src\t# vector (sve) D" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + __ sve_not(as_FloatRegister($dst$$reg), __ elemType_to_regVariant(bt), + as_PRegister($pg$$reg), as_FloatRegister($src$$reg)); + %} + ins_pipe(pipe_slow); +%} + // vector and_not instruct vand_notI(vReg dst, vReg src1, vReg src2, immI_M1 m1) %{ @@ -1318,6 +1348,36 @@ instruct vand_notL(vReg dst, vReg src1, vReg src2, immL_M1 m1) %{ ins_pipe(pipe_slow); %} +// vector and_not - predicated + +instruct vand_notI_masked(vReg dst_src1, vReg src2, immI_M1 m1, pRegGov pg) %{ + predicate(UseSVE > 0); + match(Set dst_src1 (AndV (Binary dst_src1 (XorV src2 (ReplicateB m1))) pg)); + match(Set dst_src1 (AndV (Binary dst_src1 (XorV src2 (ReplicateS m1))) pg)); + match(Set dst_src1 (AndV (Binary dst_src1 (XorV src2 (ReplicateI m1))) pg)); + ins_cost(SVE_COST); + format %{ "sve_bic $dst_src1, $pg, $dst_src1, $src2\t# vector (sve) B/H/S" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + __ sve_bic(as_FloatRegister($dst_src1$$reg), __ elemType_to_regVariant(bt), + as_PRegister($pg$$reg), as_FloatRegister($src2$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vand_notL_masked(vReg dst_src1, vReg src2, immL_M1 m1, pRegGov pg) %{ + predicate(UseSVE > 0); + match(Set dst_src1 (AndV (Binary dst_src1 (XorV src2 (ReplicateL m1))) pg)); + ins_cost(SVE_COST); + format %{ "sve_bic $dst_src1, $pg, $dst_src1, $src2\t# vector (sve) D" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + __ sve_bic(as_FloatRegister($dst_src1$$reg), __ elemType_to_regVariant(bt), + as_PRegister($pg$$reg), as_FloatRegister($src2$$reg)); + %} + ins_pipe(pipe_slow); +%} + // vector float div instruct vdivF(vReg dst_src1, vReg src2) %{ diff --git a/src/hotspot/cpu/aarch64/aarch64_sve_ad.m4 b/src/hotspot/cpu/aarch64/aarch64_sve_ad.m4 index 7e0acdc52c2..874cdf6e4e0 100644 --- a/src/hotspot/cpu/aarch64/aarch64_sve_ad.m4 +++ b/src/hotspot/cpu/aarch64/aarch64_sve_ad.m4 @@ -1,6 +1,6 @@ // -// Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. -// Copyright (c) 2020, 2021, Arm Limited. All rights reserved. +// Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2020, 2022, Arm Limited. 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,6 +745,32 @@ VECTOR_NOT(I, B/H/S) VECTOR_NOT(L, D) undefine(MATCH_RULE) dnl +// vector not - predicated +dnl +define(`MATCH_RULE', `ifelse($1, I, +`match(Set dst (XorV (Binary src (ReplicateB m1)) pg)); + match(Set dst (XorV (Binary src (ReplicateS m1)) pg)); + match(Set dst (XorV (Binary src (ReplicateI m1)) pg));', +`match(Set dst (XorV (Binary src (ReplicateL m1)) pg));')')dnl +dnl +define(`VECTOR_NOT_PREDICATE', ` +instruct vnot$1_masked`'(vReg dst, vReg src, imm$1_M1 m1, pRegGov pg) %{ + predicate(UseSVE > 0); + MATCH_RULE($1) + ins_cost(SVE_COST); + format %{ "sve_not $dst, $pg, $src\t# vector (sve) $2" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + __ sve_not(as_FloatRegister($dst$$reg), __ elemType_to_regVariant(bt), + as_PRegister($pg$$reg), as_FloatRegister($src$$reg)); + %} + ins_pipe(pipe_slow); +%}')dnl +dnl $1, $2 +VECTOR_NOT_PREDICATE(I, B/H/S) +VECTOR_NOT_PREDICATE(L, D) +undefine(MATCH_RULE) +dnl // vector and_not dnl define(`MATCH_RULE', `ifelse($1, I, @@ -771,6 +797,32 @@ VECTOR_AND_NOT(I, B/H/S) VECTOR_AND_NOT(L, D) undefine(MATCH_RULE) dnl +// vector and_not - predicated +dnl +define(`MATCH_RULE', `ifelse($1, I, +`match(Set dst_src1 (AndV (Binary dst_src1 (XorV src2 (ReplicateB m1))) pg)); + match(Set dst_src1 (AndV (Binary dst_src1 (XorV src2 (ReplicateS m1))) pg)); + match(Set dst_src1 (AndV (Binary dst_src1 (XorV src2 (ReplicateI m1))) pg));', +`match(Set dst_src1 (AndV (Binary dst_src1 (XorV src2 (ReplicateL m1))) pg));')')dnl +dnl +define(`VECTOR_AND_NOT_PREDICATE', ` +instruct vand_not$1_masked`'(vReg dst_src1, vReg src2, imm$1_M1 m1, pRegGov pg) %{ + predicate(UseSVE > 0); + MATCH_RULE($1) + ins_cost(SVE_COST); + format %{ "sve_bic $dst_src1, $pg, $dst_src1, $src2\t# vector (sve) $2" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + __ sve_bic(as_FloatRegister($dst_src1$$reg), __ elemType_to_regVariant(bt), + as_PRegister($pg$$reg), as_FloatRegister($src2$$reg)); + %} + ins_pipe(pipe_slow); +%}')dnl +dnl $1, $2 +VECTOR_AND_NOT_PREDICATE(I, B/H/S) +VECTOR_AND_NOT_PREDICATE(L, D) +undefine(MATCH_RULE) +dnl dnl VDIVF($1, $2 , $3 ) dnl VDIVF(name_suffix, size, min_vec_len) define(`VDIVF', ` diff --git a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp index 3717756d9d9..9482c3a65c2 100644 --- a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp @@ -3045,6 +3045,7 @@ public: INSN(sve_and, 0b00000100, 0b011010000); // vector and INSN(sve_andv, 0b00000100, 0b011010001); // bitwise and reduction to scalar INSN(sve_asr, 0b00000100, 0b010000100); // vector arithmetic shift right + INSN(sve_bic, 0b00000100, 0b011011000); // vector bitwise clear INSN(sve_cnt, 0b00000100, 0b011010101); // count non-zero bits INSN(sve_cpy, 0b00000101, 0b100000100); // copy scalar to each active vector element INSN(sve_eor, 0b00000100, 0b011001000); // vector eor diff --git a/test/hotspot/gtest/aarch64/aarch64-asmtest.py b/test/hotspot/gtest/aarch64/aarch64-asmtest.py index d43733535ae..1bbcdbb103a 100644 --- a/test/hotspot/gtest/aarch64/aarch64-asmtest.py +++ b/test/hotspot/gtest/aarch64/aarch64-asmtest.py @@ -1792,6 +1792,7 @@ generate(SVEVectorOp, [["add", "ZZZ"], ["add", "ZPZ", "m", "dn"], ["and", "ZPZ", "m", "dn"], ["asr", "ZPZ", "m", "dn"], + ["bic", "ZPZ", "m", "dn"], ["cnt", "ZPZ", "m"], ["eor", "ZPZ", "m", "dn"], ["lsl", "ZPZ", "m", "dn"], diff --git a/test/hotspot/gtest/aarch64/asmtest.out.h b/test/hotspot/gtest/aarch64/asmtest.out.h index 4975cce511d..2dbb48d3d01 100644 --- a/test/hotspot/gtest/aarch64/asmtest.out.h +++ b/test/hotspot/gtest/aarch64/asmtest.out.h @@ -1078,53 +1078,54 @@ __ sve_add(z8, __ D, p5, z16); // add z8.d, p5/m, z8.d, z16.d __ sve_and(z15, __ S, p1, z4); // and z15.s, p1/m, z15.s, z4.s __ sve_asr(z8, __ B, p1, z29); // asr z8.b, p1/m, z8.b, z29.b - __ sve_cnt(z28, __ D, p4, z29); // cnt z28.d, p4/m, z29.d - __ sve_eor(z9, __ H, p3, z2); // eor z9.h, p3/m, z9.h, z2.h - __ sve_lsl(z28, __ B, p0, z7); // lsl z28.b, p0/m, z28.b, z7.b - __ sve_lsr(z26, __ H, p5, z17); // lsr z26.h, p5/m, z26.h, z17.h - __ sve_mul(z8, __ D, p4, z21); // mul z8.d, p4/m, z8.d, z21.d - __ sve_neg(z5, __ S, p5, z21); // neg z5.s, p5/m, z21.s - __ sve_not(z22, __ S, p4, z29); // not z22.s, p4/m, z29.s - __ sve_orr(z19, __ S, p0, z4); // orr z19.s, p0/m, z19.s, z4.s - __ sve_smax(z23, __ B, p1, z19); // smax z23.b, p1/m, z23.b, z19.b - __ sve_smin(z23, __ B, p6, z19); // smin z23.b, p6/m, z23.b, z19.b - __ sve_sub(z8, __ D, p2, z14); // sub z8.d, p2/m, z8.d, z14.d - __ sve_fabs(z17, __ S, p7, z21); // fabs z17.s, p7/m, z21.s - __ sve_fadd(z30, __ D, p0, z10); // fadd z30.d, p0/m, z30.d, z10.d - __ sve_fdiv(z12, __ S, p0, z9); // fdiv z12.s, p0/m, z12.s, z9.s - __ sve_fmax(z24, __ D, p4, z4); // fmax z24.d, p4/m, z24.d, z4.d - __ sve_fmin(z6, __ D, p2, z27); // fmin z6.d, p2/m, z6.d, z27.d - __ sve_fmul(z13, __ D, p4, z30); // fmul z13.d, p4/m, z13.d, z30.d - __ sve_fneg(z22, __ D, p5, z30); // fneg z22.d, p5/m, z30.d - __ sve_frintm(z9, __ S, p3, z19); // frintm z9.s, p3/m, z19.s - __ sve_frintn(z20, __ S, p7, z9); // frintn z20.s, p7/m, z9.s - __ sve_frintp(z13, __ S, p3, z19); // frintp z13.s, p3/m, z19.s - __ sve_fsqrt(z24, __ S, p2, z19); // fsqrt z24.s, p2/m, z19.s - __ sve_fsub(z17, __ S, p4, z16); // fsub z17.s, p4/m, z17.s, z16.s - __ sve_fmad(z0, __ S, p0, z11, z7); // fmad z0.s, p0/m, z11.s, z7.s - __ sve_fmla(z14, __ D, p4, z4, z15); // fmla z14.d, p4/m, z4.d, z15.d - __ sve_fmls(z5, __ D, p0, z10, z21); // fmls z5.d, p0/m, z10.d, z21.d - __ sve_fnmla(z3, __ D, p0, z9, z19); // fnmla z3.d, p0/m, z9.d, z19.d - __ sve_fnmls(z10, __ S, p6, z3, z19); // fnmls z10.s, p6/m, z3.s, z19.s - __ sve_mla(z23, __ H, p7, z13, z21); // mla z23.h, p7/m, z13.h, z21.h - __ sve_mls(z26, __ S, p3, z17, z30); // mls z26.s, p3/m, z17.s, z30.s - __ sve_and(z14, z2, z29); // and z14.d, z2.d, z29.d - __ sve_eor(z21, z20, z7); // eor z21.d, z20.d, z7.d - __ sve_orr(z2, z1, z26); // orr z2.d, z1.d, z26.d - __ sve_bic(z9, z16, z17); // bic z9.d, z16.d, z17.d - __ sve_uzp1(z0, __ D, z4, z2); // uzp1 z0.d, z4.d, z2.d - __ sve_uzp2(z14, __ S, z6, z11); // uzp2 z14.s, z6.s, z11.s + __ sve_bic(z28, __ D, p4, z29); // bic z28.d, p4/m, z28.d, z29.d + __ sve_cnt(z9, __ H, p3, z2); // cnt z9.h, p3/m, z2.h + __ sve_eor(z28, __ B, p0, z7); // eor z28.b, p0/m, z28.b, z7.b + __ sve_lsl(z26, __ H, p5, z17); // lsl z26.h, p5/m, z26.h, z17.h + __ sve_lsr(z8, __ D, p4, z21); // lsr z8.d, p4/m, z8.d, z21.d + __ sve_mul(z5, __ S, p5, z21); // mul z5.s, p5/m, z5.s, z21.s + __ sve_neg(z22, __ S, p4, z29); // neg z22.s, p4/m, z29.s + __ sve_not(z19, __ S, p0, z4); // not z19.s, p0/m, z4.s + __ sve_orr(z23, __ B, p1, z19); // orr z23.b, p1/m, z23.b, z19.b + __ sve_smax(z23, __ B, p6, z19); // smax z23.b, p6/m, z23.b, z19.b + __ sve_smin(z8, __ D, p2, z14); // smin z8.d, p2/m, z8.d, z14.d + __ sve_sub(z17, __ B, p7, z21); // sub z17.b, p7/m, z17.b, z21.b + __ sve_fabs(z30, __ D, p0, z10); // fabs z30.d, p0/m, z10.d + __ sve_fadd(z12, __ S, p0, z9); // fadd z12.s, p0/m, z12.s, z9.s + __ sve_fdiv(z24, __ D, p4, z4); // fdiv z24.d, p4/m, z24.d, z4.d + __ sve_fmax(z6, __ D, p2, z27); // fmax z6.d, p2/m, z6.d, z27.d + __ sve_fmin(z13, __ D, p4, z30); // fmin z13.d, p4/m, z13.d, z30.d + __ sve_fmul(z22, __ D, p5, z30); // fmul z22.d, p5/m, z22.d, z30.d + __ sve_fneg(z9, __ S, p3, z19); // fneg z9.s, p3/m, z19.s + __ sve_frintm(z20, __ S, p7, z9); // frintm z20.s, p7/m, z9.s + __ sve_frintn(z13, __ S, p3, z19); // frintn z13.s, p3/m, z19.s + __ sve_frintp(z24, __ S, p2, z19); // frintp z24.s, p2/m, z19.s + __ sve_fsqrt(z17, __ S, p4, z16); // fsqrt z17.s, p4/m, z16.s + __ sve_fsub(z0, __ S, p0, z11); // fsub z0.s, p0/m, z0.s, z11.s + __ sve_fmad(z15, __ S, p3, z15, z4); // fmad z15.s, p3/m, z15.s, z4.s + __ sve_fmla(z29, __ D, p1, z0, z10); // fmla z29.d, p1/m, z0.d, z10.d + __ sve_fmls(z26, __ D, p0, z0, z9); // fmls z26.d, p0/m, z0.d, z9.d + __ sve_fnmla(z28, __ D, p2, z24, z3); // fnmla z28.d, p2/m, z24.d, z3.d + __ sve_fnmls(z7, __ D, p6, z28, z13); // fnmls z7.d, p6/m, z28.d, z13.d + __ sve_mla(z10, __ D, p6, z12, z17); // mla z10.d, p6/m, z12.d, z17.d + __ sve_mls(z17, __ S, p3, z2, z29); // mls z17.s, p3/m, z2.s, z29.s + __ sve_and(z21, z20, z7); // and z21.d, z20.d, z7.d + __ sve_eor(z2, z1, z26); // eor z2.d, z1.d, z26.d + __ sve_orr(z9, z16, z17); // orr z9.d, z16.d, z17.d + __ sve_bic(z0, z4, z2); // bic z0.d, z4.d, z2.d + __ sve_uzp1(z14, __ S, z6, z11); // uzp1 z14.s, z6.s, z11.s + __ sve_uzp2(z14, __ H, z16, z29); // uzp2 z14.h, z16.h, z29.h // SVEReductionOp - __ sve_andv(v14, __ H, p4, z29); // andv h14, p4, z29.h - __ sve_orv(v3, __ H, p0, z22); // orv h3, p0, z22.h - __ sve_eorv(v3, __ B, p6, z27); // eorv b3, p6, z27.b - __ sve_smaxv(v19, __ D, p5, z7); // smaxv d19, p5, z7.d - __ sve_sminv(v21, __ H, p3, z5); // sminv h21, p3, z5.h - __ sve_fminv(v25, __ D, p1, z21); // fminv d25, p1, z21.d - __ sve_fmaxv(v17, __ S, p0, z3); // fmaxv s17, p0, z3.s - __ sve_fadda(v19, __ S, p3, z7); // fadda s19, p3, s19, z7.s - __ sve_uaddv(v14, __ H, p4, z17); // uaddv d14, p4, z17.h + __ sve_andv(v3, __ H, p0, z22); // andv h3, p0, z22.h + __ sve_orv(v3, __ B, p6, z27); // orv b3, p6, z27.b + __ sve_eorv(v19, __ D, p5, z7); // eorv d19, p5, z7.d + __ sve_smaxv(v21, __ H, p3, z5); // smaxv h21, p3, z5.h + __ sve_sminv(v25, __ S, p1, z21); // sminv s25, p1, z21.s + __ sve_fminv(v17, __ S, p0, z3); // fminv s17, p0, z3.s + __ sve_fmaxv(v19, __ S, p3, z7); // fmaxv s19, p3, z7.s + __ sve_fadda(v14, __ S, p4, z17); // fadda s14, p4, s14, z17.s + __ sve_uaddv(v13, __ D, p6, z17); // uaddv d13, p6, z17.d __ bind(forth); @@ -1143,30 +1144,30 @@ 0x9101a1a0, 0xb10a5cc8, 0xd10810aa, 0xf10fd061, 0x120cb166, 0x321764bc, 0x52174681, 0x720c0227, 0x9241018e, 0xb25a2969, 0xd278b411, 0xf26aad01, - 0x14000000, 0x17ffffd7, 0x140003a5, 0x94000000, - 0x97ffffd4, 0x940003a2, 0x3400000a, 0x34fffa2a, - 0x340073ea, 0x35000008, 0x35fff9c8, 0x35007388, - 0xb400000b, 0xb4fff96b, 0xb400732b, 0xb500001d, - 0xb5fff91d, 0xb50072dd, 0x10000013, 0x10fff8b3, - 0x10007273, 0x90000013, 0x36300016, 0x3637f836, - 0x363071f6, 0x3758000c, 0x375ff7cc, 0x3758718c, + 0x14000000, 0x17ffffd7, 0x140003a6, 0x94000000, + 0x97ffffd4, 0x940003a3, 0x3400000a, 0x34fffa2a, + 0x3400740a, 0x35000008, 0x35fff9c8, 0x350073a8, + 0xb400000b, 0xb4fff96b, 0xb400734b, 0xb500001d, + 0xb5fff91d, 0xb50072fd, 0x10000013, 0x10fff8b3, + 0x10007293, 0x90000013, 0x36300016, 0x3637f836, + 0x36307216, 0x3758000c, 0x375ff7cc, 0x375871ac, 0x128313a0, 0x528a32c7, 0x7289173b, 0x92ab3acc, 0xd2a0bf94, 0xf2c285e8, 0x9358722f, 0x330e652f, 0x53067f3b, 0x93577c53, 0xb34a1aac, 0xd35a4016, 0x13946c63, 0x93c3dbc8, 0x54000000, 0x54fff5a0, - 0x54006f60, 0x54000001, 0x54fff541, 0x54006f01, - 0x54000002, 0x54fff4e2, 0x54006ea2, 0x54000002, - 0x54fff482, 0x54006e42, 0x54000003, 0x54fff423, - 0x54006de3, 0x54000003, 0x54fff3c3, 0x54006d83, - 0x54000004, 0x54fff364, 0x54006d24, 0x54000005, - 0x54fff305, 0x54006cc5, 0x54000006, 0x54fff2a6, - 0x54006c66, 0x54000007, 0x54fff247, 0x54006c07, - 0x54000008, 0x54fff1e8, 0x54006ba8, 0x54000009, - 0x54fff189, 0x54006b49, 0x5400000a, 0x54fff12a, - 0x54006aea, 0x5400000b, 0x54fff0cb, 0x54006a8b, - 0x5400000c, 0x54fff06c, 0x54006a2c, 0x5400000d, - 0x54fff00d, 0x540069cd, 0x5400000e, 0x54ffefae, - 0x5400696e, 0x5400000f, 0x54ffef4f, 0x5400690f, + 0x54006f80, 0x54000001, 0x54fff541, 0x54006f21, + 0x54000002, 0x54fff4e2, 0x54006ec2, 0x54000002, + 0x54fff482, 0x54006e62, 0x54000003, 0x54fff423, + 0x54006e03, 0x54000003, 0x54fff3c3, 0x54006da3, + 0x54000004, 0x54fff364, 0x54006d44, 0x54000005, + 0x54fff305, 0x54006ce5, 0x54000006, 0x54fff2a6, + 0x54006c86, 0x54000007, 0x54fff247, 0x54006c27, + 0x54000008, 0x54fff1e8, 0x54006bc8, 0x54000009, + 0x54fff189, 0x54006b69, 0x5400000a, 0x54fff12a, + 0x54006b0a, 0x5400000b, 0x54fff0cb, 0x54006aab, + 0x5400000c, 0x54fff06c, 0x54006a4c, 0x5400000d, + 0x54fff00d, 0x540069ed, 0x5400000e, 0x54ffefae, + 0x5400698e, 0x5400000f, 0x54ffef4f, 0x5400692f, 0xd40658e1, 0xd4014d22, 0xd4046543, 0xd4273f60, 0xd44cad80, 0xd503201f, 0xd69f03e0, 0xd6bf03e0, 0xd5033fdf, 0xd5033e9f, 0xd50332bf, 0xd61f0200, @@ -1198,7 +1199,7 @@ 0x791f226d, 0xf95aa2f3, 0xb9587bb7, 0x395f7176, 0x795d9143, 0x399e7e08, 0x799a2697, 0x79df3422, 0xb99c2624, 0xfd5c2374, 0xbd5fa1d9, 0xfd1d595a, - 0xbd1b1869, 0x5800595b, 0x1800000b, 0xf8945060, + 0xbd1b1869, 0x5800597b, 0x1800000b, 0xf8945060, 0xd8000000, 0xf8ae6ba0, 0xf99a0080, 0x1a070035, 0x3a0700a8, 0x5a0e0367, 0x7a11009b, 0x9a000380, 0xba1e030c, 0xda0f0320, 0xfa030301, 0x0b340b11, @@ -1365,17 +1366,18 @@ 0x25a0c6cd, 0x2521cf00, 0x0583c5b1, 0x05407336, 0x05001e62, 0x04e400f4, 0x04a80407, 0x65c402d3, 0x65cb0ac9, 0x659007c5, 0x0456ac36, 0x04c01608, - 0x049a048f, 0x041087a8, 0x04dab3bc, 0x04590c49, - 0x041380fc, 0x0451963a, 0x04d012a8, 0x0497b6a5, - 0x049eb3b6, 0x04980093, 0x04080677, 0x040a1a77, - 0x04c109c8, 0x049cbeb1, 0x65c0815e, 0x658d812c, - 0x65c69098, 0x65c78b66, 0x65c293cd, 0x04ddb7d6, - 0x6582ae69, 0x6580bd34, 0x6581ae6d, 0x658daa78, - 0x65819211, 0x65a78160, 0x65ef108e, 0x65f52145, - 0x65f34123, 0x65b3786a, 0x04555db7, 0x049e6e3a, - 0x043d304e, 0x04a73295, 0x047a3022, 0x04f13209, - 0x05e26880, 0x05ab6cce, 0x045a33ae, 0x045822c3, - 0x04193b63, 0x04c834f3, 0x044a2cb5, 0x65c726b9, - 0x65862071, 0x65982cf3, 0x0441322e, + 0x049a048f, 0x041087a8, 0x04db13bc, 0x045aac49, + 0x041900fc, 0x0453963a, 0x04d192a8, 0x049016a5, + 0x0497b3b6, 0x049ea093, 0x04180677, 0x04081a77, + 0x04ca09c8, 0x04011eb1, 0x04dca15e, 0x6580812c, + 0x65cd9098, 0x65c68b66, 0x65c793cd, 0x65c297d6, + 0x049dae69, 0x6582bd34, 0x6580ae6d, 0x6581aa78, + 0x658db211, 0x65818160, 0x65a48def, 0x65ea041d, + 0x65e9201a, 0x65e34b1c, 0x65ed7b87, 0x04d1598a, + 0x049d6c51, 0x04273295, 0x04ba3022, 0x04713209, + 0x04e23080, 0x05ab68ce, 0x057d6e0e, 0x045a22c3, + 0x04183b63, 0x04d934f3, 0x04482cb5, 0x048a26b9, + 0x65872071, 0x65862cf3, 0x6598322e, 0x04c13a2d, + }; // END Generated code -- do not edit -- GitLab From 1864481df10d2f616cbfdecebf3bebbae04de5e1 Mon Sep 17 00:00:00 2001 From: Ioi Lam Date: Thu, 17 Feb 2022 06:40:46 +0000 Subject: [PATCH 537/564] 8279969: NULL return from map_bitmap_region() needs to be checked Reviewed-by: ccheung, coleenp --- src/hotspot/share/cds/filemap.cpp | 13 ++++++++++--- src/hotspot/share/cds/heapShared.cpp | 4 ++++ .../cds/appcds/SharedArchiveConsistency.java | 8 ++++++++ 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/hotspot/share/cds/filemap.cpp b/src/hotspot/share/cds/filemap.cpp index 63ba7fb2893..69ab7430e16 100644 --- a/src/hotspot/share/cds/filemap.cpp +++ b/src/hotspot/share/cds/filemap.cpp @@ -2168,6 +2168,15 @@ void FileMapInfo::map_heap_regions_impl() { assert(is_aligned(relocated_closed_heap_region_bottom, HeapRegion::GrainBytes), "must be"); + if (_heap_pointers_need_patching) { + char* bitmap_base = map_bitmap_region(); + if (bitmap_base == NULL) { + log_info(cds)("CDS heap cannot be used because bitmap region cannot be mapped"); + _heap_pointers_need_patching = false; + return; + } + } + // Map the closed heap regions: GC does not write into these regions. if (map_heap_regions(MetaspaceShared::first_closed_heap_region, MetaspaceShared::max_num_closed_heap_regions, @@ -2297,9 +2306,7 @@ void FileMapInfo::patch_heap_embedded_pointers() { void FileMapInfo::patch_heap_embedded_pointers(MemRegion* regions, int num_regions, int first_region_idx) { char* bitmap_base = map_bitmap_region(); - if (bitmap_base == NULL) { - return; - } + assert(bitmap_base != NULL, "must have already been mapped"); for (int i=0; imap_bitmap_region(); + if (bitmap_base == 0) { + _loading_failed = true; + return false; // OOM or CRC error + } uintptr_t load_address = buffer; for (int i = 0; i < num_loaded_regions; i++) { LoadedArchiveHeapRegion* ri = &loaded_regions[i]; diff --git a/test/hotspot/jtreg/runtime/cds/appcds/SharedArchiveConsistency.java b/test/hotspot/jtreg/runtime/cds/appcds/SharedArchiveConsistency.java index fd0291f06e0..cec5b66a12f 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/SharedArchiveConsistency.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/SharedArchiveConsistency.java @@ -80,6 +80,14 @@ public class SharedArchiveConsistency { OutputAnalyzer output = shareAuto ? TestCommon.execAuto(execArgs) : TestCommon.execCommon(execArgs); String stdtxt = output.getOutput(); System.out.println("Note: this test may fail in very rare occasions due to CRC32 checksum collision"); + for (String opt : execArgs) { + if (opt.equals("-XX:+VerifySharedSpaces")) { + // If VerifySharedSpaces is enabled, the VM should never crash even if the archive + // is corrupted (unless if we are so lucky that the corrupted archive ends up + // have the same checksum as recoreded in the header) + output.shouldNotContain("A fatal error has been detected by the Java Runtime Environment"); + } + } for (String message : matchMessages) { if (stdtxt.contains(message)) { // match any to return -- GitLab From c0275e18b7cb4a01385b79ced46560322aeacc97 Mon Sep 17 00:00:00 2001 From: Tyler Steele Date: Thu, 17 Feb 2022 08:49:22 +0000 Subject: [PATCH 538/564] 8203290: [AIX] Check functionality of JDK-8199712 (Flight Recorder) Implements JFR for AIX Reviewed-by: erikj, mdoerr, mgronlun, stuefe, ihse --- make/autoconf/jvm-features.m4 | 23 - src/hotspot/os/aix/libperfstat_aix.cpp | 61 +- src/hotspot/os/aix/libperfstat_aix.hpp | 153 ++- src/hotspot/os/aix/loadlib_aix.cpp | 178 ++-- src/hotspot/os/aix/loadlib_aix.hpp | 12 + src/hotspot/os/aix/os_aix.cpp | 8 +- src/hotspot/os/aix/os_perf_aix.cpp | 982 ++++++------------ src/hotspot/os_cpu/aix_ppc/thread_aix_ppc.cpp | 73 +- test/jdk/ProblemList.txt | 2 +- .../runtime/TestNativeLibrariesEvent.java | 5 +- 10 files changed, 728 insertions(+), 769 deletions(-) diff --git a/make/autoconf/jvm-features.m4 b/make/autoconf/jvm-features.m4 index 70457149edc..8dfc0d362b9 100644 --- a/make/autoconf/jvm-features.m4 +++ b/make/autoconf/jvm-features.m4 @@ -264,22 +264,6 @@ AC_DEFUN_ONCE([JVM_FEATURES_CHECK_DTRACE], ]) ]) -############################################################################### -# Check if the feature 'jfr' is available on this platform. -# -AC_DEFUN_ONCE([JVM_FEATURES_CHECK_JFR], -[ - JVM_FEATURES_CHECK_AVAILABILITY(jfr, [ - AC_MSG_CHECKING([if platform is supported by JFR]) - if test "x$OPENJDK_TARGET_OS" = xaix; then - AC_MSG_RESULT([no, $OPENJDK_TARGET_OS-$OPENJDK_TARGET_CPU]) - AVAILABLE=false - else - AC_MSG_RESULT([yes]) - fi - ]) -]) - ############################################################################### # Check if the feature 'jvmci' is available on this platform. # @@ -399,18 +383,11 @@ AC_DEFUN_ONCE([JVM_FEATURES_PREPARE_PLATFORM], JVM_FEATURES_CHECK_CDS JVM_FEATURES_CHECK_DTRACE - JVM_FEATURES_CHECK_JFR JVM_FEATURES_CHECK_JVMCI JVM_FEATURES_CHECK_SHENANDOAHGC JVM_FEATURES_CHECK_STATIC_BUILD JVM_FEATURES_CHECK_ZGC - # Filter out features by default for all variants on certain platforms. - # Make sure to just add to JVM_FEATURES_PLATFORM_FILTER, since it could - # have a value already from custom extensions. - if test "x$OPENJDK_TARGET_OS" = xaix; then - JVM_FEATURES_PLATFORM_FILTER="$JVM_FEATURES_PLATFORM_FILTER jfr" - fi ]) ############################################################################### diff --git a/src/hotspot/os/aix/libperfstat_aix.cpp b/src/hotspot/os/aix/libperfstat_aix.cpp index 65a937ef261..cec0ac1d287 100644 --- a/src/hotspot/os/aix/libperfstat_aix.cpp +++ b/src/hotspot/os/aix/libperfstat_aix.cpp @@ -1,5 +1,7 @@ /* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2018 SAP SE. All rights reserved. + * Copyright (c) 2022, IBM Corp. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,12 +32,22 @@ // Handle to the libperfstat. static void* g_libhandle = NULL; +typedef int (*fun_perfstat_cpu_t) (perfstat_id_t *name, PERFSTAT_CPU_T_LATEST* userbuff, + int sizeof_userbuff, int desired_number); + typedef int (*fun_perfstat_cpu_total_t) (perfstat_id_t *name, PERFSTAT_CPU_TOTAL_T_LATEST* userbuff, int sizeof_userbuff, int desired_number); typedef int (*fun_perfstat_memory_total_t) (perfstat_id_t *name, perfstat_memory_total_t* userbuff, int sizeof_userbuff, int desired_number); +typedef int (*fun_perfstat_netinterface_t) (perfstat_id_t *name, perfstat_netinterface_t* userbuff, + int sizeof_userbuff, int desired_number); + +typedef int (*fun_perfstat_process_t) (perfstat_id_t *name, + PERFSTAT_PROCESS_T_LATEST* userbuff, int sizeof_userbuff, + int desired_number); + typedef int (*fun_perfstat_partition_total_t) (perfstat_id_t *name, PERFSTAT_PARTITON_TOTAL_T_LATEST* userbuff, int sizeof_userbuff, int desired_number); @@ -48,12 +60,15 @@ typedef void (*fun_perfstat_reset_t) (); typedef cid_t (*fun_wpar_getcid_t) (); -static fun_perfstat_cpu_total_t g_fun_perfstat_cpu_total = NULL; -static fun_perfstat_memory_total_t g_fun_perfstat_memory_total = NULL; +static fun_perfstat_cpu_total_t g_fun_perfstat_cpu_total = NULL; +static fun_perfstat_cpu_t g_fun_perfstat_cpu = NULL; +static fun_perfstat_memory_total_t g_fun_perfstat_memory_total = NULL; +static fun_perfstat_netinterface_t g_fun_perfstat_netinterface = NULL; static fun_perfstat_partition_total_t g_fun_perfstat_partition_total = NULL; -static fun_perfstat_wpar_total_t g_fun_perfstat_wpar_total = NULL; -static fun_perfstat_reset_t g_fun_perfstat_reset = NULL; -static fun_wpar_getcid_t g_fun_wpar_getcid = NULL; +static fun_perfstat_process_t g_fun_perfstat_process = NULL; +static fun_perfstat_wpar_total_t g_fun_perfstat_wpar_total = NULL; +static fun_perfstat_reset_t g_fun_perfstat_reset = NULL; +static fun_wpar_getcid_t g_fun_wpar_getcid = NULL; bool libperfstat::init() { @@ -84,7 +99,10 @@ bool libperfstat::init() { // These functions are required for every release. RESOLVE_FUN(perfstat_cpu_total); + RESOLVE_FUN(perfstat_cpu); RESOLVE_FUN(perfstat_memory_total); + RESOLVE_FUN(perfstat_netinterface); + RESOLVE_FUN(perfstat_process); RESOLVE_FUN(perfstat_reset); trcVerbose("libperfstat loaded."); @@ -108,6 +126,22 @@ void libperfstat::cleanup() { } +int libperfstat::perfstat_cpu_total(perfstat_id_t *name, PERFSTAT_CPU_TOTAL_T_LATEST* userbuff, + int sizeof_userbuff, int desired_number) { + if (g_fun_perfstat_cpu_total == NULL) { + return -1; + } + return g_fun_perfstat_cpu_total(name, userbuff, sizeof_userbuff, desired_number); +} + +int libperfstat::perfstat_cpu(perfstat_id_t *name, PERFSTAT_CPU_T_LATEST* userbuff, + int sizeof_userbuff, int desired_number) { + if (g_fun_perfstat_cpu == NULL) { + return -1; + } + return g_fun_perfstat_cpu(name, userbuff, sizeof_userbuff, desired_number); +} + int libperfstat::perfstat_memory_total(perfstat_id_t *name, perfstat_memory_total_t* userbuff, int sizeof_userbuff, int desired_number) { @@ -117,12 +151,13 @@ int libperfstat::perfstat_memory_total(perfstat_id_t *name, return g_fun_perfstat_memory_total(name, userbuff, sizeof_userbuff, desired_number); } -int libperfstat::perfstat_cpu_total(perfstat_id_t *name, PERFSTAT_CPU_TOTAL_T_LATEST* userbuff, - int sizeof_userbuff, int desired_number) { - if (g_fun_perfstat_cpu_total == NULL) { +int libperfstat::perfstat_netinterface(perfstat_id_t *name, + perfstat_netinterface_t* userbuff, + int sizeof_userbuff, int desired_number) { + if (g_fun_perfstat_netinterface == NULL) { return -1; } - return g_fun_perfstat_cpu_total(name, userbuff, sizeof_userbuff, desired_number); + return g_fun_perfstat_netinterface(name, userbuff, sizeof_userbuff, desired_number); } int libperfstat::perfstat_partition_total(perfstat_id_t *name, PERFSTAT_PARTITON_TOTAL_T_LATEST* userbuff, @@ -133,6 +168,14 @@ int libperfstat::perfstat_partition_total(perfstat_id_t *name, PERFSTAT_PARTITON return g_fun_perfstat_partition_total(name, userbuff, sizeof_userbuff, desired_number); } +int libperfstat::perfstat_process(perfstat_id_t *name, perfstat_process_t* userbuff, + int sizeof_userbuff, int desired_number) { + if (g_fun_perfstat_process == NULL) { + return -1; + } + return g_fun_perfstat_process(name, userbuff, sizeof_userbuff, desired_number); +} + int libperfstat::perfstat_wpar_total(perfstat_id_wpar_t *name, PERFSTAT_WPAR_TOTAL_T_LATEST* userbuff, int sizeof_userbuff, int desired_number) { if (g_fun_perfstat_wpar_total == NULL) { diff --git a/src/hotspot/os/aix/libperfstat_aix.hpp b/src/hotspot/os/aix/libperfstat_aix.hpp index d323b8e8bbc..30f08c57a03 100644 --- a/src/hotspot/os/aix/libperfstat_aix.hpp +++ b/src/hotspot/os/aix/libperfstat_aix.hpp @@ -1,5 +1,7 @@ /* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2018 SAP SE. All rights reserved. + * Copyright (c) 2022, IBM Corp. * 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 +49,9 @@ // work without recompilation on all newer AIX versions. // -#define IDENTIFIER_LENGTH 64 /* length of strings included in the structures */ +#define IDENTIFIER_LENGTH 64 /* length of strings included in the structures */ +#define FIRST_CPU "" /* pseudo-name for fist CPU */ +#define FIRST_NETINTERFACE "" /* pseudo-name for first NETINTERFACE */ typedef struct { /* structure element identifier */ @@ -439,6 +443,102 @@ typedef struct { /* global cpu information AIX 7.2 / 6.1 TL6 (see oslevel -r) * * of perfstat_cpu_total_t data structure */ } perfstat_cpu_total_t_72; +typedef struct { /* component perfstat_cpu_t from AIX 7.2 documentation */ + char name [IDENTIFIER_LENGTH]; /* Logical processor name (processor0, processor1,.). */ + ulong_t state; /* Specifies whether the CPU is offline or online. + * (NOTE: The type of 'state' is not specified in the documentation, but + * ulong_t is the correct length) */ + u_longlong_t user; /* Raw number of clock ticks spent in user mode. */ + u_longlong_t sys; /* Raw number of clock ticks spent in system mode. */ + u_longlong_t idle; /* Raw number of clock ticks spent idle. */ + u_longlong_t wait; /* Raw number of clock ticks spent waiting for I/O. */ + u_longlong_t pswitch; /* Number of context switches (changes of currently running process). */ + u_longlong_t syscall; /* Number of system calls executed. */ + u_longlong_t sysread; /* Number of read system calls executed. */ + u_longlong_t syswrite; /* Number of write system calls executed. */ + u_longlong_t sysfork; /* Number of fork system call executed. */ + u_longlong_t sysexec; /* Number of exec system call executed. */ + u_longlong_t readch; /* Number of characters transferred with read system call. */ + u_longlong_t writech; /* Number of characters transferred with write system call. */ + u_longlong_t bread; /* Number of block reads. */ + u_longlong_t bwrite; /* Number of block writes. */ + u_longlong_t lread; /* Number of logical read requests. */ + u_longlong_t lwrite; /* Number of logical write requests. */ + u_longlong_t phread; /* Number of physical reads (reads on raw device). */ + u_longlong_t phwrite; /* Number of physical writes (writes on raw device). */ + u_longlong_t iget; /* Number of inode lookups. */ + u_longlong_t namei; /* Number of vnode lookup from a path name. */ + u_longlong_t dirblk; /* Number of 512-byte blocks reads by the directory search routine to locate an entry for a file. */ + u_longlong_t msg; /* Number of interprocess communication (IPC) message operations. */ + u_longlong_t sema; /* Number of IPC semaphore operations. */ + u_longlong_t minfaults; /* Number of page faults with no I/O. */ + u_longlong_t majfaults; /* Number of page faults with disk I/O. */ + u_longlong_t puser; /* Raw number of physical processor ticks in user mode. */ + u_longlong_t psys; /* Raw number of physical processor ticks in system mode. */ + u_longlong_t pidle; /* Raw number of physical processor ticks idle. */ + u_longlong_t pwait; /* Raw number of physical processor ticks waiting for I/O. */ + u_longlong_t redisp_sd0; /* Number of thread redispatches within the scheduler affinity domain 0. */ + u_longlong_t redisp_sd1; /* Number of thread redispatches within the scheduler affinity domain 1. */ + u_longlong_t redisp_sd2; /* Number of thread redispatches within the scheduler affinity domain 2. */ + u_longlong_t redisp_sd3; /* Number of thread redispatches within the scheduler affinity domain 3. */ + u_longlong_t redisp_sd4; /* Number of thread redispatches within the scheduler affinity domain 4. */ + u_longlong_t redisp_sd5; /* Number of thread redispatches within the scheduler affinity domain 5. */ + u_longlong_t migration_push; /* Number of thread migrations from the local runque to another queue due to starvation load balancing. */ + u_longlong_t migration_S3grq; /* Number of thread migrations from the global runque to the local runque resulting in a move across scheduling domain 3. */ + u_longlong_t migration_S3pull; /* Number of thread migrations from another processor's runque resulting in a move across scheduling domain 3. */ + u_longlong_t invol_cswitch; /* Number of involuntary thread context switches. */ + u_longlong_t vol_cswitch; /* Number of voluntary thread context switches. */ + u_longlong_t runque; /* Number of threads on the runque. */ + u_longlong_t bound; /* Number of bound threads. */ + u_longlong_t decrintrs; /* Number of decrementer interrupts. */ + u_longlong_t mpcrintrs; /* Number of received interrupts for MPC. */ + u_longlong_t mpcsintrs; /* Number of sent interrupts for MPC. */ + u_longlong_t devintrs; /* Number of device interrupts. */ + u_longlong_t softintrs; /* Number of offlevel handlers called. */ + u_longlong_t phantintrs; /* Number of phantom interrupts. */ + u_longlong_t idle_donated_purr; /* Number of idle cycles donated by a dedicated partition enabled for donation. */ + u_longlong_t idle_donated_spurr; /* Number of idle spurr cycles donated by a dedicated partition enabled for donation. */ + u_longlong_t busy_donated_purr; /* Number of busy cycles donated by a dedicated partition enabled for donation. */ + u_longlong_t busy_donated_spurr; /* Number of busy spurr cycles donated by a dedicated partition enabled for donation. */ + u_longlong_t idle_stolen_purr; /* Number of idle cycles stolen by the hypervisor from a dedicated partition. */ + u_longlong_t idle_stolen_spurr; /* Number of idle spurr cycles stolen by the hypervisor from a dedicated partition. */ + u_longlong_t busy_stolen_purr; /* Number of busy cycles stolen by the hypervisor from a dedicated partition. */ + u_longlong_t busy_stolen_spurr; /* Number of busy spurr cycles stolen by the hypervisor from a dedicated partition.*/ + u_longlong_t shcpus_in_sys; /* Number of physical processors allocated for shared processor use, across all shared processors pools. */ + u_longlong_t entitled_pool_capacity; /* Entitled processor capacity of partition’s pool. */ + u_longlong_t pool_max_time; /* Summation of maximum time that can be consumed by the pool (nanoseconds). */ + u_longlong_t pool_busy_time; /* Summation of busy (nonidle) time accumulated across all partitions in the pool (nanoseconds). */ + u_longlong_t pool_scaled_busy_time; /* Scaled summation of busy (nonidle) time accumulated across all partitions in the pool (nanoseconds). */ + u_longlong_t shcpu_tot_time; /* Summation of total time across all physical processors allocated for shared processor use (nanoseconds). */ + u_longlong_t shcpu_busy_time; /* Summation of busy (nonidle) time accumulated across all shared processor partitions (nanoseconds). */ + u_longlong_t shcpu_scaled_busy_time; /* Scaled summation of busy time accumulated across all shared processor partitions (nanoseconds). */ + int ams_pool_id; /* AMS pool ID of the pool the LPAR belongs to. */ + int var_mem_weight; /* Variable memory capacity weight. */ + u_longlong_t iome; /* I/O memory entitlement of the partition in bytes. */ + u_longlong_t pmem; /* Physical memory currently backing the partition's logical memory in bytes. */ + u_longlong_t hpi; /* Number of hypervisor page-ins. */ + u_longlong_t hpit; /* Time spent in hypervisor page-ins (in nanoseconds). */ + u_longlong_t hypv_pagesize; /* Hypervisor page size in KB. */ + uint online_lcpus; /* Number of online logical processors. */ + uint smt_thrds; /* Number of SMT threads. */ +} perfstat_cpu_t; + +typedef struct { + char name[IDENTIFIER_LENGTH]; /* Name of the interface. */ + char description[IDENTIFIER_LENGTH]; /* Interface description (from ODM, similar to lscfg output). */ + uchar type; /* Ethernet, token ring, and so on. Interpretation can be done using the /usr/include/net/if_types.h file. */ + u_longlong_t mtu; /* Network frame size. */ + u_longlong_t ipacets; /* Number of packets received on interface. */ + u_longlong_t ibytes; /* Number of bytes received on interface. */ + u_longlong_t ierrors; /* Number of input errors on interface. */ + u_longlong_t opackets; /* Number of packets sent on interface. */ + u_longlong_t obytes; /* Number of bytes sent on interface. */ + u_longlong_t oerrors; /* Number of output errors on interface. */ + u_longlong_t collisions; /* Number of collisions on csma interface. */ + u_longlong_t bitrate; /* Adapter rating in bit per second. */ + u_longlong_t if_iqdrops; /* Dropped on input, this interface. */ + u_longlong_t if_arpdrops; /* Dropped because no arp response. */ +} perfstat_netinterface_t; typedef union { uint w; @@ -797,6 +897,38 @@ typedef struct { /* partition total information AIX 7.1 >= TL1*/ * of perfstat_partition_total_t data structure */ } perfstat_partition_total_t_71_1; +typedef struct { + u_longlong_t version; /* Version number of the data structure. */ + u_longlong_t pid; /* Process ID. */ + char proc_name[64]; /* Name of the process. */ + int proc_priority; /* Process priority. */ + u_longlong_t num_threads; /* Thread count. */ + u_longlong_t proc_uid; /* Owner information. */ + u_longlong_t proc_classid; /* WLM class name. */ + u_longlong_t proc_size; /* Virtual size of the process (exclusive usage, leaving all shared library text & shared file pages, shared memory, and memory mapped). */ + u_longlong_t proc_real_mem_data; /* Real memory used for data in KB. */ + u_longlong_t proc_real_mem_text; /* Real memory used for text in KB. */ + u_longlong_t proc_virt_mem_data; /* Virtual memory used for data in KB. */ + u_longlong_t proc_virt_mem_text; /* Virtual memory used for text in KB. */ + u_longlong_t shared_lib_data_size; /* Data size from shared library in KB. */ + u_longlong_t heap_size; /* Heap size in KB. */ + u_longlong_t real_inuse; /* The Real memory (in KB) in use by the process including all kind of segments (excluding system segments). This includes text, data, shared library text, shared library data, file pages, shared memory, and memory mapped. */ + u_longlong_t virt_inuse; /* The virtual memory (in KB) in use by the process including all kind of segments (excluding system segments). This includes text, data, shared library text, shared library data, file pages, shared memory, and memory mapped. */ + u_longlong_t pinned; /* Pinned memory (in KB) for this process inclusive of all segments. */ + u_longlong_t pgsp_inuse; /* Paging space used (in KB) inclusive of all segments. */ + u_longlong_t filepages; /* File pages used (in KB) including shared pages. */ + u_longlong_t real_inuse_map; /* Real memory used (in KB) for shared memory and memory mapped regions */ + u_longlong_t virt_inuse_map; /* Virtual memory used (in KB) for shared memory and memory mapped regions. */ + u_longlong_t pinned_inuse_map; /* Pinned memory used (in KB) for shared memory and memory mapped regions. */ + double ucpu_time; /* User mode CPU time is in percentage or milliseconds, which is based on, whether it is filled by perfstat_process_util or perfstat_process respectively. */ + double scpu_time; /* System mode CPU time is in percentage or milliseconds, which is based on whether it is filled by perfstat_process_util or perfstat_process respectively. */ + u_longlong_t last_timebase; /* Timebase counter. */ + u_longlong_t inBytes; /* Bytes written to disk. */ + u_longlong_t outBytes; /* Bytes read from disk. */ + u_longlong_t inOps; /* In operations from disk. */ + u_longlong_t outOps; /* Out operations from disk */ +} perfstat_process_t; + typedef union { /* WPAR Type & Flags */ uint w; struct { @@ -854,9 +986,14 @@ typedef struct { /* WPAR identifier */ // end: libperfstat.h (AIX 5.2, 5.3, 6.1, 7.1) ////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#define PERFSTAT_PARTITON_TOTAL_T_LATEST perfstat_partition_total_t_71_1/* latest perfstat_partition_total_t structure */ -#define PERFSTAT_CPU_TOTAL_T_LATEST perfstat_cpu_total_t_72 /* latest perfstat_cpu_total_t structure */ -#define PERFSTAT_WPAR_TOTAL_T_LATEST perfstat_wpar_total_t_71 /* latest perfstat_wpar_total_t structure */ +#define PERFSTAT_PARTITON_TOTAL_T_LATEST perfstat_partition_total_t_71_1 /* latest perfstat_partition_total_t structure */ +#define PERFSTAT_PROCESS_T_LATEST perfstat_process_t /* latest perfstat_process_t structure */ +#define PERFSTAT_CPU_TOTAL_T_LATEST perfstat_cpu_total_t_72 /* latest perfstat_cpu_total_t structure */ +#define PERFSTAT_CPU_T_LATEST perfstat_cpu_t /* latest perfstat_cpu_t structure */ +#define PERFSTAT_NETINTERFACE_T_LATEST perfstat_netinterface_t /* latest perfstat_netinterface_t structure */ +#define PERFSTAT_WPAR_TOTAL_T_LATEST perfstat_wpar_total_t_71 /* latest perfstat_wpar_total_t structure */ + +typedef PERFSTAT_CPU_TOTAL_T_LATEST perfstat_cpu_total_t; class libperfstat { @@ -886,6 +1023,14 @@ public: static cid_t wpar_getcid(); + static int perfstat_cpu(perfstat_id_t *name, PERFSTAT_CPU_T_LATEST* userbuff, + int sizeof_userbuff, int desired_number); + + static int perfstat_process(perfstat_id_t *name, PERFSTAT_PROCESS_T_LATEST* userbuff, + int sizeof_userbuff, int desired_number); + + static int perfstat_netinterface(perfstat_id_t *name, PERFSTAT_NETINTERFACE_T_LATEST* userbuff, + int sizeof_userbuff, int desired_number); //////////////////////////////////////////////////////////////// // The convenience functions get_partitioninfo(), get_cpuinfo(), get_wparinfo() return diff --git a/src/hotspot/os/aix/loadlib_aix.cpp b/src/hotspot/os/aix/loadlib_aix.cpp index 9ac761f6212..a111e0199fa 100644 --- a/src/hotspot/os/aix/loadlib_aix.cpp +++ b/src/hotspot/os/aix/loadlib_aix.cpp @@ -1,6 +1,7 @@ /* - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2019 SAP SE. All rights reserved. + * Copyright (c) 2022, IBM Corp. * 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,13 +111,7 @@ static StringList g_stringlist; // eternal - this list is rebuilt on every reload. // Note that we do not hand out those entries, but copies of them. -struct entry_t { - entry_t* next; - loaded_module_t info; -}; - -static void print_entry(const entry_t* e, outputStream* os) { - const loaded_module_t* const lm = &(e->info); +static void print_entry(const loaded_module_t* lm, outputStream* os) { os->print(" %c text: " INTPTR_FORMAT " - " INTPTR_FORMAT ", data: " INTPTR_FORMAT " - " INTPTR_FORMAT " " "%s", @@ -129,50 +124,50 @@ static void print_entry(const entry_t* e, outputStream* os) { } } -static entry_t* g_first = NULL; +static loaded_module_t* g_first = NULL; -static entry_t* find_entry_for_text_address(const void* p) { - for (entry_t* e = g_first; e; e = e->next) { - if ((uintptr_t)p >= (uintptr_t)e->info.text && - (uintptr_t)p < ((uintptr_t)e->info.text + e->info.text_len)) { - return e; +static loaded_module_t* find_entry_for_text_address(const void* p) { + for (loaded_module_t* lm = g_first; lm; lm = lm->next) { + if ((uintptr_t)p >= (uintptr_t)lm->text && + (uintptr_t)p < ((uintptr_t)lm->text + lm->text_len)) { + return lm; } } return NULL; } -static entry_t* find_entry_for_data_address(const void* p) { - for (entry_t* e = g_first; e; e = e->next) { - if ((uintptr_t)p >= (uintptr_t)e->info.data && - (uintptr_t)p < ((uintptr_t)e->info.data + e->info.data_len)) { - return e; +static loaded_module_t* find_entry_for_data_address(const void* p) { + for (loaded_module_t* lm = g_first; lm; lm = lm->next) { + if ((uintptr_t)p >= (uintptr_t)lm->data && + (uintptr_t)p < ((uintptr_t)lm->data + lm->data_len)) { + return lm; } } return NULL; } // Adds a new entry to the list (ordered by text address ascending). -static void add_entry_to_list(entry_t* e, entry_t** start) { - entry_t* last = NULL; - entry_t* e2 = *start; - while (e2 && e2->info.text < e->info.text) { - last = e2; - e2 = e2->next; +static void add_entry_to_list(loaded_module_t* lm, loaded_module_t** start) { + loaded_module_t* last = NULL; + loaded_module_t* lm2 = *start; + while (lm2 && lm2->text < lm->text) { + last = lm2; + lm2 = lm2->next; } if (last) { - last->next = e; + last->next = lm; } else { - *start = e; + *start = lm; } - e->next = e2; + lm->next = lm2; } -static void free_entry_list(entry_t** start) { - entry_t* e = *start; - while (e) { - entry_t* const e2 = e->next; - ::free(e); - e = e2; +static void free_entry_list(loaded_module_t** start) { + loaded_module_t* lm = *start; + while (lm) { + loaded_module_t* const lm2 = lm->next; + ::free(lm); + lm = lm2; } *start = NULL; } @@ -186,7 +181,7 @@ static bool reload_table() { trcVerbose("reload module table..."); - entry_t* new_list = NULL; + loaded_module_t* new_list = NULL; const struct ld_info* ldi = NULL; // Call loadquery(L_GETINFO..) to get a list of all loaded Dlls from AIX. loadquery @@ -214,33 +209,33 @@ static bool reload_table() { for (;;) { - entry_t* e = (entry_t*) ::malloc(sizeof(entry_t)); - if (!e) { + loaded_module_t* lm = (loaded_module_t*) ::malloc(sizeof(loaded_module_t)); + if (!lm) { trcVerbose("OOM."); goto cleanup; } - memset(e, 0, sizeof(entry_t)); + memset(lm, 0, sizeof(loaded_module_t)); - e->info.text = ldi->ldinfo_textorg; - e->info.text_len = ldi->ldinfo_textsize; - e->info.data = ldi->ldinfo_dataorg; - e->info.data_len = ldi->ldinfo_datasize; + lm->text = ldi->ldinfo_textorg; + lm->text_len = ldi->ldinfo_textsize; + lm->data = ldi->ldinfo_dataorg; + lm->data_len = ldi->ldinfo_datasize; - e->info.path = g_stringlist.add(ldi->ldinfo_filename); - if (!e->info.path) { + lm->path = g_stringlist.add(ldi->ldinfo_filename); + if (!lm->path) { trcVerbose("OOM."); goto cleanup; } // Extract short name { - const char* p = strrchr(e->info.path, '/'); + const char* p = strrchr(lm->path, '/'); if (p) { p ++; - e->info.shortname = p; + lm->shortname = p; } else { - e->info.shortname = e->info.path; + lm->shortname = lm->path; } } @@ -248,32 +243,32 @@ static bool reload_table() { const char* p_mbr_name = ldi->ldinfo_filename + strlen(ldi->ldinfo_filename) + 1; if (*p_mbr_name) { - e->info.member = g_stringlist.add(p_mbr_name); - if (!e->info.member) { + lm->member = g_stringlist.add(p_mbr_name); + if (!lm->member) { trcVerbose("OOM."); goto cleanup; } } else { - e->info.member = NULL; + lm->member = NULL; } - if (strcmp(e->info.shortname, "libjvm.so") == 0) { + if (strcmp(lm->shortname, "libjvm.so") == 0) { // Note that this, theoretically, is fuzzy. We may accidentally contain // more than one libjvm.so. But that is improbable, so lets go with this // solution. - e->info.is_in_vm = true; + lm->is_in_vm = true; } trcVerbose("entry: %p " SIZE_FORMAT ", %p " SIZE_FORMAT ", %s %s %s, %d", - e->info.text, e->info.text_len, - e->info.data, e->info.data_len, - e->info.path, e->info.shortname, - (e->info.member ? e->info.member : "NULL"), - e->info.is_in_vm + lm->text, lm->text_len, + lm->data, lm->data_len, + lm->path, lm->shortname, + (lm->member ? lm->member : "NULL"), + lm->is_in_vm ); // Add to list. - add_entry_to_list(e, &new_list); + add_entry_to_list(lm, &new_list); // Next entry... if (ldi->ldinfo_next) { @@ -304,6 +299,23 @@ cleanup: } // end LoadedLibraries::reload() +// Callback for loaded module information (from os.hpp) +// Input parameters: +// char* module_file_name, +// address module_base_addr, +// address module_top_addr, +// void* param +static bool for_each_internal(os::LoadedModulesCallbackFunc cb, void* param) { + + for (const loaded_module_t* lm = g_first; lm; lm = lm->next) { + (*cb)(lm->shortname, + (address) lm->text, + (address) lm->text + lm->text_len, + param); + } + + return true; +} /////////////////////////////////////////////////////////////////////////////// // Externals @@ -322,8 +334,8 @@ void LoadedLibraries::print(outputStream* os) { if (!g_first) { reload_table(); } - for (entry_t* e = g_first; e; e = e->next) { - print_entry(e, os); + for (loaded_module_t* lm = g_first; lm; lm = lm->next) { + print_entry(lm, os); os->cr(); } } @@ -334,14 +346,17 @@ bool LoadedLibraries::find_for_text_address(const void* p, if (!g_first) { reload_table(); } - const entry_t* const e = find_entry_for_text_address(p); - if (e) { - if (info) { - *info = e->info; - } - return true; + + const loaded_module_t* const lm = find_entry_for_text_address(p); + if (!lm) { + return false; } - return false; + + if (info) { + memcpy(info, lm, sizeof(loaded_module_t)); + info->next = nullptr; + } + return true; } @@ -353,13 +368,30 @@ bool LoadedLibraries::find_for_data_address ( if (!g_first) { reload_table(); } - const entry_t* const e = find_entry_for_data_address(p); - if (e) { - if (info) { - *info = e->info; + + const loaded_module_t* const lm = find_entry_for_data_address(p); + if (!lm) { + return false; + } + + if (info) { + memcpy(info, lm, sizeof(loaded_module_t)); + info->next = nullptr; + } + return true; +} + +bool LoadedLibraries::for_each(os::LoadedModulesCallbackFunc cb, void* param) { + MiscUtils::AutoCritSect lck(&g_cs); + + if (!g_first) { + if (!reload_table()) { + // If the table is not loaded and cannot be initialized, + // then we must quit. + return false; } - return true; } - return false; + + return for_each_internal(cb, param); } diff --git a/src/hotspot/os/aix/loadlib_aix.hpp b/src/hotspot/os/aix/loadlib_aix.hpp index 354dccf4c7b..18cd6e59864 100644 --- a/src/hotspot/os/aix/loadlib_aix.hpp +++ b/src/hotspot/os/aix/loadlib_aix.hpp @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2013 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -32,6 +33,9 @@ #ifndef OS_AIX_LOADLIB_AIX_HPP #define OS_AIX_LOADLIB_AIX_HPP +#include "misc_aix.hpp" +#include "runtime/os.hpp" + #include class outputStream; @@ -66,6 +70,9 @@ struct loaded_module_t { // True if this module is part of the vm. bool is_in_vm; + // Next item in the list, or NULL if no such item exits + loaded_module_t* next; + }; // This class is a singleton holding a map of all loaded binaries @@ -99,6 +106,11 @@ class LoadedLibraries // Output debug info static void print(outputStream* os); + // Apply the callback to each loaded_module_t in the list + // Return false if module table is empty and cannot be loaded. + static bool for_each(os::LoadedModulesCallbackFunc cb, void* param); + }; + #endif // OS_AIX_LOADLIB_AIX_HPP diff --git a/src/hotspot/os/aix/os_aix.cpp b/src/hotspot/os/aix/os_aix.cpp index 419e2ce92fd..b586da9a78d 100644 --- a/src/hotspot/os/aix/os_aix.cpp +++ b/src/hotspot/os/aix/os_aix.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2021 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -1131,7 +1131,11 @@ void os::get_summary_os_info(char* buf, size_t buflen) { } int os::get_loaded_modules_info(os::LoadedModulesCallbackFunc callback, void *param) { - // Not yet implemented. + + if (!LoadedLibraries::for_each(callback, param)) { + return -1; + } + return 0; } diff --git a/src/hotspot/os/aix/os_perf_aix.cpp b/src/hotspot/os/aix/os_perf_aix.cpp index bdccca0c1c5..ad031de3cdc 100644 --- a/src/hotspot/os/aix/os_perf_aix.cpp +++ b/src/hotspot/os/aix/os_perf_aix.cpp @@ -1,5 +1,6 @@ /* - * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, IBM Corp. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,197 +25,42 @@ #include "precompiled.hpp" #include "jvm.h" +#include "libperfstat_aix.hpp" #include "memory/allocation.inline.hpp" +#include "memory/resourceArea.hpp" #include "os_aix.inline.hpp" #include "runtime/os.hpp" #include "runtime/os_perf.hpp" #include "runtime/vm_version.hpp" +#include "utilities/debug.hpp" #include "utilities/globalDefinitions.hpp" -#include -#include -#include +#include +#include #include +#include +#include +#include +#include #include +#include #include -#include #include -#include +#include #include -#include -#include -#include - -/** - /proc/[number]/stat - Status information about the process. This is used by ps(1). It is defined in /usr/src/linux/fs/proc/array.c. - - The fields, in order, with their proper scanf(3) format specifiers, are: - - 1. pid %d The process id. - - 2. comm %s - The filename of the executable, in parentheses. This is visible whether or not the executable is swapped out. - - 3. state %c - One character from the string "RSDZTW" where R is running, S is sleeping in an interruptible wait, D is waiting in uninterruptible disk - sleep, Z is zombie, T is traced or stopped (on a signal), and W is paging. - - 4. ppid %d - The PID of the parent. - - 5. pgrp %d - The process group ID of the process. - - 6. session %d - The session ID of the process. - - 7. tty_nr %d - The tty the process uses. - - 8. tpgid %d - The process group ID of the process which currently owns the tty that the process is connected to. - - 9. flags %lu - The flags of the process. The math bit is decimal 4, and the traced bit is decimal 10. - - 10. minflt %lu - The number of minor faults the process has made which have not required loading a memory page from disk. - - 11. cminflt %lu - The number of minor faults that the process's waited-for children have made. - - 12. majflt %lu - The number of major faults the process has made which have required loading a memory page from disk. - - 13. cmajflt %lu - The number of major faults that the process's waited-for children have made. - - 14. utime %lu - The number of jiffies that this process has been scheduled in user mode. - - 15. stime %lu - The number of jiffies that this process has been scheduled in kernel mode. - - 16. cutime %ld - The number of jiffies that this process's waited-for children have been scheduled in user mode. (See also times(2).) - - 17. cstime %ld - The number of jiffies that this process' waited-for children have been scheduled in kernel mode. - - 18. priority %ld - The standard nice value, plus fifteen. The value is never negative in the kernel. - - 19. nice %ld - The nice value ranges from 19 (nicest) to -19 (not nice to others). - - 20. 0 %ld This value is hard coded to 0 as a placeholder for a removed field. - - 21. itrealvalue %ld - The time in jiffies before the next SIGALRM is sent to the process due to an interval timer. - - 22. starttime %lu - The time in jiffies the process started after system boot. - - 23. vsize %lu - Virtual memory size in bytes. - - 24. rss %ld - Resident Set Size: number of pages the process has in real memory, minus 3 for administrative purposes. This is just the pages which count - towards text, data, or stack space. This does not include pages which have not been demand-loaded in, or which are swapped out. - - 25. rlim %lu - Current limit in bytes on the rss of the process (usually 4294967295 on i386). - - 26. startcode %lu - The address above which program text can run. - - 27. endcode %lu - The address below which program text can run. - - 28. startstack %lu - The address of the start of the stack. - - 29. kstkesp %lu - The current value of esp (stack pointer), as found in the kernel stack page for the process. - - 30. kstkeip %lu - The current EIP (instruction pointer). - - 31. signal %lu - The bitmap of pending signals (usually 0). - - 32. blocked %lu - The bitmap of blocked signals (usually 0, 2 for shells). - - 33. sigignore %lu - The bitmap of ignored signals. - - 34. sigcatch %lu - The bitmap of catched signals. - - 35. wchan %lu - This is the "channel" in which the process is waiting. It is the address of a system call, and can be looked up in a namelist if you need - a textual name. (If you have an up-to-date /etc/psdatabase, then try ps -l to see the WCHAN field in action.) - - 36. nswap %lu - Number of pages swapped - not maintained. - - 37. cnswap %lu - Cumulative nswap for child processes. - - 38. exit_signal %d - Signal to be sent to parent when we die. - - 39. processor %d - CPU number last executed on. - - - - ///// SSCANF FORMAT STRING. Copy and use. - -field: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 -format: %d %s %c %d %d %d %d %d %lu %lu %lu %lu %lu %lu %lu %ld %ld %ld %ld %ld %ld %lu %lu %ld %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %d %d - - -*/ - -/** - * For platforms that have them, when declaring - * a printf-style function, - * formatSpec is the parameter number (starting at 1) - * that is the format argument ("%d pid %s") - * params is the parameter number where the actual args to - * the format starts. If the args are in a va_list, this - * should be 0. - */ -#ifndef PRINTF_ARGS -# define PRINTF_ARGS(formatSpec, params) ATTRIBUTE_PRINTF(formatSpec, params) -#endif - -#ifndef SCANF_ARGS -# define SCANF_ARGS(formatSpec, params) ATTRIBUTE_SCANF(formatSpec, params) -#endif - -#ifndef _PRINTFMT_ -# define _PRINTFMT_ -#endif - -#ifndef _SCANFMT_ -# define _SCANFMT_ -#endif - +#include -struct CPUPerfTicks { - uint64_t used; - uint64_t usedKernel; - uint64_t total; -}; +typedef struct { + u_longlong_t user; + u_longlong_t sys; + u_longlong_t idle; + u_longlong_t wait; +} cpu_tick_store_t; -typedef enum { - CPU_LOAD_VM_ONLY, - CPU_LOAD_GLOBAL, -} CpuLoadTarget; +typedef struct { + double utime; + double stime; +} jvm_time_store_t; enum { UNDETECTED, @@ -223,318 +69,299 @@ enum { BAREMETAL }; -struct CPUPerfCounters { - int nProcs; - CPUPerfTicks jvmTicks; - CPUPerfTicks* cpus; -}; - -static double get_cpu_load(int which_logical_cpu, CPUPerfCounters* counters, double* pkernelLoad, CpuLoadTarget target); - -/** reads /proc//stat data, with some checks and some skips. - * Ensure that 'fmt' does _NOT_ contain the first two "%d %s" +/** + * Get info for requested PID from /proc//psinfo file */ -static int SCANF_ARGS(2, 0) vread_statdata(const char* procfile, _SCANFMT_ const char* fmt, va_list args) { - FILE*f; - int n; - char buf[2048]; - - if ((f = os::fopen(procfile, "r")) == NULL) { - return -1; - } - - if ((n = fread(buf, 1, sizeof(buf), f)) != -1) { - char *tmp; - - buf[n-1] = '\0'; - /** skip through pid and exec name. */ - if ((tmp = strrchr(buf, ')')) != NULL) { - // skip the ')' and the following space - // but check that buffer is long enough - tmp += 2; - if (tmp < buf + n) { - n = vsscanf(tmp, fmt, args); - } - } - } +static bool read_psinfo(const u_longlong_t& pid, psinfo_t& psinfo) { + static size_t BUF_LENGTH = 32 + sizeof(u_longlong_t); - fclose(f); + FILE* fp; + char buf[BUF_LENGTH]; + int len; - return n; -} + jio_snprintf(buf, BUF_LENGTH, "/proc/%llu/psinfo", pid); + fp = fopen(buf, "r"); -static int SCANF_ARGS(2, 3) read_statdata(const char* procfile, _SCANFMT_ const char* fmt, ...) { - int n; - va_list args; + if (!fp) { + return false; + } - va_start(args, fmt); - n = vread_statdata(procfile, fmt, args); - va_end(args); - return n; + len = fread(&psinfo, 1, sizeof(psinfo_t), fp); + return len == sizeof(psinfo_t); } /** - * on Linux we got the ticks related information from /proc/stat - * this does not work on AIX, libperfstat might be an alternative + * Get and set ticks for the specified lcpu */ -static OSReturn get_total_ticks(int which_logical_cpu, CPUPerfTicks* pticks) { - return OS_ERR; -} +static OSReturn get_lcpu_ticks(perfstat_id_t* lcpu_name, cpu_tick_store_t* pticks) { + perfstat_cpu_t lcpu_stats; -/** read user and system ticks from a named procfile, assumed to be in 'stat' format then. */ -static int read_ticks(const char* procfile, uint64_t* userTicks, uint64_t* systemTicks) { - return read_statdata(procfile, "%*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u " UINT64_FORMAT " " UINT64_FORMAT, - userTicks, systemTicks); -} + if (!pticks) { + return OS_ERR; + } -/** - * Return the number of ticks spent in any of the processes belonging - * to the JVM on any CPU. - */ -static OSReturn get_jvm_ticks(CPUPerfTicks* pticks) { - return OS_ERR; + // populate cpu_stats + if (libperfstat::perfstat_cpu(lcpu_name, &lcpu_stats, sizeof(perfstat_cpu_t), 1) < 1) { + memset(pticks, 0, sizeof(cpu_tick_store_t)); + return OS_ERR; + } + + pticks->user = lcpu_stats.user; + pticks->sys = lcpu_stats.sys; + pticks->idle = lcpu_stats.idle; + pticks->wait = lcpu_stats.wait; + + return OS_OK; } /** - * Return the load of the CPU as a double. 1.0 means the CPU process uses all - * available time for user or system processes, 0.0 means the CPU uses all time - * being idle. - * - * Returns a negative value if there is a problem in determining the CPU load. + * Return CPU load caused by the currently executing process (the jvm). */ -static double get_cpu_load(int which_logical_cpu, CPUPerfCounters* counters, double* pkernelLoad, CpuLoadTarget target) { - uint64_t udiff, kdiff, tdiff; - CPUPerfTicks* pticks; - CPUPerfTicks tmp; - double user_load; +static OSReturn get_jvm_load(double* jvm_uload, double* jvm_sload) { + static clock_t ticks_per_sec = sysconf(_SC_CLK_TCK); + static u_longlong_t last_timebase = 0; - *pkernelLoad = 0.0; + perfstat_process_t jvm_stats; + perfstat_id_t name_holder; + u_longlong_t timebase_diff; - if (target == CPU_LOAD_VM_ONLY) { - pticks = &counters->jvmTicks; - } else if (-1 == which_logical_cpu) { - pticks = &counters->cpus[counters->nProcs]; - } else { - pticks = &counters->cpus[which_logical_cpu]; + jio_snprintf(name_holder.name, IDENTIFIER_LENGTH, "%d", getpid()); + if (libperfstat::perfstat_process(&name_holder, &jvm_stats, sizeof(perfstat_process_t), 1) < 1) { + return OS_ERR; } - tmp = *pticks; + // Update timebase + timebase_diff = jvm_stats.last_timebase - last_timebase; + last_timebase = jvm_stats.last_timebase; - if (target == CPU_LOAD_VM_ONLY) { - if (get_jvm_ticks(pticks) != OS_OK) { - return -1.0; - } - } else if (get_total_ticks(which_logical_cpu, pticks) != OS_OK) { - return -1.0; + if (jvm_uload) { + *jvm_uload = jvm_stats.ucpu_time / timebase_diff; + } + if (jvm_sload) { + *jvm_sload = jvm_stats.scpu_time / timebase_diff; } - // seems like we sometimes end up with less kernel ticks when - // reading /proc/self/stat a second time, timing issue between cpus? - if (pticks->usedKernel < tmp.usedKernel) { - kdiff = 0; - } else { - kdiff = pticks->usedKernel - tmp.usedKernel; + return OS_OK; +} + +static void update_prev_time(jvm_time_store_t* from, jvm_time_store_t* to) { + if (from && to) { + memcpy(to, from, sizeof(jvm_time_store_t)); } - tdiff = pticks->total - tmp.total; - udiff = pticks->used - tmp.used; +} - if (tdiff == 0) { - return 0.0; - } else if (tdiff < (udiff + kdiff)) { - tdiff = udiff + kdiff; +static void update_prev_ticks(cpu_tick_store_t* from, cpu_tick_store_t* to) { + if (from && to) { + memcpy(to, from, sizeof(cpu_tick_store_t)); } - *pkernelLoad = (kdiff / (double)tdiff); - // BUG9044876, normalize return values to sane values - *pkernelLoad = MAX2(*pkernelLoad, 0.0); - *pkernelLoad = MIN2(*pkernelLoad, 1.0); +} - user_load = (udiff / (double)tdiff); - user_load = MAX2(user_load, 0.0); - user_load = MIN2(user_load, 1.0); +/** + * Calculate the current system load from current ticks using previous ticks as a starting point. + */ +static void calculate_updated_load(cpu_tick_store_t* update, cpu_tick_store_t* prev, double* load) { + cpu_tick_store_t diff; - return user_load; -} + if (update && prev && load) { + diff.user = update->user - prev->user; + diff.sys = update->sys - prev->sys; + diff.idle = update->idle - prev->idle; + diff.wait = update->wait - prev->wait; -static int SCANF_ARGS(1, 2) parse_stat(_SCANFMT_ const char* fmt, ...) { - return OS_ERR; + *load = 1.0 - diff.idle/(diff.sys + diff.user + diff.idle + diff.wait); + } } -static int get_noof_context_switches(uint64_t* switches) { - return parse_stat("ctxt " UINT64_FORMAT "\n", switches); -} +/** + * Look up lcpu names for later re-use. + */ +static bool populate_lcpu_names(int ncpus, perfstat_id_t* lcpu_names) { + ResourceMark rm; + perfstat_cpu_t* all_lcpu_stats; + perfstat_cpu_t* lcpu_stats; + perfstat_id_t name_holder; -/** returns boot time in _seconds_ since epoch */ -static int get_boot_time(uint64_t* time) { - return parse_stat("btime " UINT64_FORMAT "\n", time); -} + assert(lcpu_names, "Names pointer NULL"); -static int perf_context_switch_rate(double* rate) { - static pthread_mutex_t contextSwitchLock = PTHREAD_MUTEX_INITIALIZER; - static uint64_t bootTime; - static uint64_t lastTimeNanos; - static uint64_t lastSwitches; - static double lastRate; + strncpy(name_holder.name, FIRST_CPU, IDENTIFIER_LENGTH); - uint64_t bt = 0; - int res = 0; + all_lcpu_stats = NEW_RESOURCE_ARRAY(perfstat_cpu_t, ncpus); - // First time through bootTime will be zero. - if (bootTime == 0) { - uint64_t tmp; - if (get_boot_time(&tmp) < 0) { - return OS_ERR; - } - bt = tmp * 1000; + // If perfstat_cpu does not return the expected number of names, signal error to caller + if (ncpus != libperfstat::perfstat_cpu(&name_holder, all_lcpu_stats, sizeof(perfstat_cpu_t), ncpus)) { + return false; } - res = OS_OK; + for (int n = 0; n < ncpus; n++) { + strncpy(lcpu_names[n].name, all_lcpu_stats[n].name, IDENTIFIER_LENGTH); + } - pthread_mutex_lock(&contextSwitchLock); - { + return true; +} - uint64_t sw; - s8 t, d; +/** + * Calculates the context switch rate. + * (Context Switches / Tick) * (Tick / s) = Context Switches per second + */ +static OSReturn perf_context_switch_rate(double* rate) { + static clock_t ticks_per_sec = sysconf(_SC_CLK_TCK); - if (bootTime == 0) { - // First interval is measured from boot time which is - // seconds since the epoch. Thereafter we measure the - // elapsed time using javaTimeNanos as it is monotonic- - // non-decreasing. - lastTimeNanos = os::javaTimeNanos(); - t = os::javaTimeMillis(); - d = t - bt; - // keep bootTime zero for now to use as a first-time-through flag - } else { - t = os::javaTimeNanos(); - d = nanos_to_millis(t - lastTimeNanos); - } + u_longlong_t ticks; + perfstat_cpu_total_t cpu_stats; - if (d == 0) { - *rate = lastRate; - } else if (get_noof_context_switches(&sw) == 0) { - *rate = ( (double)(sw - lastSwitches) / d ) * 1000; - lastRate = *rate; - lastSwitches = sw; - if (bootTime != 0) { - lastTimeNanos = t; - } - } else { - *rate = 0; - res = OS_ERR; - } - if (*rate <= 0) { - *rate = 0; - lastRate = 0; - } + if (libperfstat::perfstat_cpu_total(NULL, &cpu_stats, sizeof(perfstat_cpu_total_t), 1) < 0) { + return OS_ERR; + } - if (bootTime == 0) { - bootTime = bt; - } - } - pthread_mutex_unlock(&contextSwitchLock); + ticks = cpu_stats.user + cpu_stats.sys + cpu_stats.idle + cpu_stats.wait; + *rate = (cpu_stats.pswitch / ticks) * ticks_per_sec; - return res; + return OS_OK; } class CPUPerformanceInterface::CPUPerformance : public CHeapObj { - friend class CPUPerformanceInterface; private: - CPUPerfCounters _counters; - - int cpu_load(int which_logical_cpu, double* cpu_load); - int context_switch_rate(double* rate); - int cpu_load_total_process(double* cpu_load); - int cpu_loads_process(double* pjvmUserLoad, double* pjvmKernelLoad, double* psystemTotalLoad); + int _ncpus; + perfstat_id_t* _lcpu_names; + cpu_tick_store_t* _prev_ticks; public: CPUPerformance(); bool initialize(); ~CPUPerformance(); + + int cpu_load(int which_logical_cpu, double* cpu_load); + int context_switch_rate(double* rate); + int cpu_load_total_process(double* cpu_load); + int cpu_loads_process(double* pjvmUserLoad, double* pjvmKernelLoad, double* psystemTotalLoad); }; -CPUPerformanceInterface::CPUPerformance::CPUPerformance() { - _counters.nProcs = os::active_processor_count(); - _counters.cpus = NULL; -} +CPUPerformanceInterface::CPUPerformance::CPUPerformance(): + _ncpus(0), + _lcpu_names(NULL), + _prev_ticks(NULL) {} bool CPUPerformanceInterface::CPUPerformance::initialize() { - size_t array_entry_count = _counters.nProcs + 1; - _counters.cpus = NEW_C_HEAP_ARRAY(CPUPerfTicks, array_entry_count, mtInternal); - memset(_counters.cpus, 0, array_entry_count * sizeof(*_counters.cpus)); + perfstat_cpu_total_t cpu_stats; - // For the CPU load total - get_total_ticks(-1, &_counters.cpus[_counters.nProcs]); - - // For each CPU - for (int i = 0; i < _counters.nProcs; i++) { - get_total_ticks(i, &_counters.cpus[i]); + if (libperfstat::perfstat_cpu_total(NULL, &cpu_stats, sizeof(perfstat_cpu_total_t), 1) < 0) { + return false; + } + if (cpu_stats.ncpus <= 0) { + return false; } - // For JVM load - get_jvm_ticks(&_counters.jvmTicks); - // initialize context switch system - // the double is only for init - double init_ctx_switch_rate; - perf_context_switch_rate(&init_ctx_switch_rate); + _ncpus = cpu_stats.ncpus; + _lcpu_names = NEW_C_HEAP_ARRAY(perfstat_id_t, _ncpus, mtInternal); + + _prev_ticks = NEW_C_HEAP_ARRAY(cpu_tick_store_t, _ncpus, mtInternal); + // Set all prev-tick values to 0 + memset(_prev_ticks, 0, _ncpus*sizeof(cpu_tick_store_t)); + + if (!populate_lcpu_names(_ncpus, _lcpu_names)) { + return false; + } return true; } CPUPerformanceInterface::CPUPerformance::~CPUPerformance() { - if (_counters.cpus != NULL) { - FREE_C_HEAP_ARRAY(char, _counters.cpus); + if (_lcpu_names) { + FREE_C_HEAP_ARRAY(perfstat_id_t, _lcpu_names); + } + if (_prev_ticks) { + FREE_C_HEAP_ARRAY(cpu_tick_store_t, _prev_ticks); } } -int CPUPerformanceInterface::CPUPerformance::cpu_load(int which_logical_cpu, double* cpu_load) { - double u, s; - u = get_cpu_load(which_logical_cpu, &_counters, &s, CPU_LOAD_GLOBAL); - if (u < 0) { - *cpu_load = 0.0; +/** + * Get CPU load for all processes on specified logical CPU. + */ +int CPUPerformanceInterface::CPUPerformance::cpu_load(int lcpu_number, double* lcpu_load) { + cpu_tick_store_t ticks; + + assert(lcpu_load != NULL, "NULL pointer passed to cpu_load"); + assert(lcpu_number < _ncpus, "Invalid lcpu passed to cpu_load"); + + if (get_lcpu_ticks(&_lcpu_names[lcpu_number], &ticks) == OS_ERR) { + *lcpu_load = -1.0; return OS_ERR; } - // Cap total systemload to 1.0 - *cpu_load = MIN2((u + s), 1.0); + + calculate_updated_load(&ticks, &_prev_ticks[lcpu_number], lcpu_load); + update_prev_ticks(&ticks, &_prev_ticks[lcpu_number]); + return OS_OK; } -int CPUPerformanceInterface::CPUPerformance::cpu_load_total_process(double* cpu_load) { - double u, s; - u = get_cpu_load(-1, &_counters, &s, CPU_LOAD_VM_ONLY); - if (u < 0) { - *cpu_load = 0.0; - return OS_ERR; +/** + * Get CPU load for all processes on all CPUs. + */ +int CPUPerformanceInterface::CPUPerformance::cpu_load_total_process(double* total_load) { + cpu_tick_store_t total_ticks; + cpu_tick_store_t prev_total_ticks; + + assert(total_load != NULL, "NULL pointer passed to cpu_load_total_process"); + + memset(&total_ticks, 0, sizeof(cpu_tick_store_t)); + memset(&prev_total_ticks, 0, sizeof(cpu_tick_store_t)); + + for (int lcpu = 0; lcpu < _ncpus; lcpu++) { + cpu_tick_store_t lcpu_ticks; + + if (get_lcpu_ticks(&_lcpu_names[lcpu], &lcpu_ticks) == OS_ERR) { + *total_load = -1.0; + return OS_ERR; + } + + total_ticks.user = lcpu_ticks.user; + total_ticks.sys = lcpu_ticks.sys; + total_ticks.idle = lcpu_ticks.idle; + total_ticks.wait = lcpu_ticks.wait; + + prev_total_ticks.user += _prev_ticks[lcpu].user; + prev_total_ticks.sys += _prev_ticks[lcpu].sys; + prev_total_ticks.idle += _prev_ticks[lcpu].idle; + prev_total_ticks.wait += _prev_ticks[lcpu].wait; + + update_prev_ticks(&lcpu_ticks, &_prev_ticks[lcpu]); } - *cpu_load = u + s; + + calculate_updated_load(&total_ticks, &prev_total_ticks, total_load); + return OS_OK; } +/** + * Get CPU load for all CPUs. + * + * Set values for: + * - pjvmUserLoad: CPU load due to jvm process in user mode. Jvm process assumed to be self process + * - pjvmKernelLoad: CPU load due to jvm process in kernel mode. Jvm process assumed to be self process + * - psystemTotalLoad: Total CPU load from all process on all logical CPUs + * + * Note: If any of the above loads cannot be calculated, this procedure returns OS_ERR and any load that could not be calculated is set to -1 + * + */ int CPUPerformanceInterface::CPUPerformance::cpu_loads_process(double* pjvmUserLoad, double* pjvmKernelLoad, double* psystemTotalLoad) { - double u, s, t; + double u, k, t; - assert(pjvmUserLoad != NULL, "pjvmUserLoad not inited"); - assert(pjvmKernelLoad != NULL, "pjvmKernelLoad not inited"); - assert(psystemTotalLoad != NULL, "psystemTotalLoad not inited"); - - u = get_cpu_load(-1, &_counters, &s, CPU_LOAD_VM_ONLY); - if (u < 0) { - *pjvmUserLoad = 0.0; - *pjvmKernelLoad = 0.0; - *psystemTotalLoad = 0.0; - return OS_ERR; + int retval = OS_OK; + if (get_jvm_load(&u, &k) == OS_ERR || cpu_load_total_process(&t) == OS_ERR) { + retval = OS_ERR; } - cpu_load(-1, &t); - // clamp at user+system and 1.0 - if (u + s > t) { - t = MIN2(u + s, 1.0); + if (pjvmUserLoad) { + *pjvmUserLoad = u; + } + if (pjvmKernelLoad) { + *pjvmKernelLoad = k; + } + if (psystemTotalLoad) { + *psystemTotalLoad = t; } - *pjvmUserLoad = u; - *pjvmKernelLoad = s; - *psystemTotalLoad = t; - - return OS_OK; + return retval; } int CPUPerformanceInterface::CPUPerformance::context_switch_rate(double* rate) { @@ -573,267 +400,85 @@ int CPUPerformanceInterface::context_switch_rate(double* rate) const { } class SystemProcessInterface::SystemProcesses : public CHeapObj { - friend class SystemProcessInterface; - private: - class ProcessIterator : public CHeapObj { - friend class SystemProcessInterface::SystemProcesses; - private: - DIR* _dir; - struct dirent* _entry; - bool _valid; - char _exeName[PATH_MAX]; - char _exePath[PATH_MAX]; - - ProcessIterator(); - ~ProcessIterator(); - bool initialize(); - - bool is_valid() const { return _valid; } - bool is_valid_entry(struct dirent* entry) const; - bool is_dir(const char* name) const; - int fsize(const char* name, uint64_t& size) const; - - char* allocate_string(const char* str) const; - void get_exe_name(); - char* get_exe_path(); - char* get_cmdline(); - - int current(SystemProcess* process_info); - int next_process(); - }; - - ProcessIterator* _iterator; + private: + char* allocate_string(const char* str) const; + + public: SystemProcesses(); bool initialize(); ~SystemProcesses(); - - //information about system processes int system_processes(SystemProcess** system_processes, int* no_of_sys_processes) const; }; -bool SystemProcessInterface::SystemProcesses::ProcessIterator::is_dir(const char* name) const { - struct stat mystat; - int ret_val = 0; - - ret_val = stat(name, &mystat); - if (ret_val < 0) { - return false; - } - ret_val = S_ISDIR(mystat.st_mode); - return ret_val > 0; -} - -int SystemProcessInterface::SystemProcesses::ProcessIterator::fsize(const char* name, uint64_t& size) const { - assert(name != NULL, "name pointer is NULL!"); - size = 0; - struct stat fbuf; - - if (stat(name, &fbuf) < 0) { - return OS_ERR; - } - size = fbuf.st_size; - return OS_OK; -} - -// if it has a numeric name, is a directory and has a 'stat' file in it -bool SystemProcessInterface::SystemProcesses::ProcessIterator::is_valid_entry(struct dirent* entry) const { - char buffer[PATH_MAX]; - uint64_t size = 0; - - if (atoi(entry->d_name) != 0) { - jio_snprintf(buffer, PATH_MAX, "/proc/%s", entry->d_name); - buffer[PATH_MAX - 1] = '\0'; - - if (is_dir(buffer)) { - jio_snprintf(buffer, PATH_MAX, "/proc/%s/stat", entry->d_name); - buffer[PATH_MAX - 1] = '\0'; - if (fsize(buffer, size) != OS_ERR) { - return true; - } - } - } - return false; -} - -// get exe-name from /proc//stat -void SystemProcessInterface::SystemProcesses::ProcessIterator::get_exe_name() { - FILE* fp; - char buffer[PATH_MAX]; - - jio_snprintf(buffer, PATH_MAX, "/proc/%s/stat", _entry->d_name); - buffer[PATH_MAX - 1] = '\0'; - if ((fp = os::fopen(buffer, "r")) != NULL) { - if (fgets(buffer, PATH_MAX, fp) != NULL) { - char* start, *end; - // exe-name is between the first pair of ( and ) - start = strchr(buffer, '('); - if (start != NULL && start[1] != '\0') { - start++; - end = strrchr(start, ')'); - if (end != NULL) { - size_t len; - len = MIN2(end - start, sizeof(_exeName) - 1); - memcpy(_exeName, start, len); - _exeName[len] = '\0'; - } - } - } - fclose(fp); - } +SystemProcessInterface::SystemProcesses::SystemProcesses() { } -// get command line from /proc//cmdline -char* SystemProcessInterface::SystemProcesses::ProcessIterator::get_cmdline() { - FILE* fp; - char buffer[PATH_MAX]; - char* cmdline = NULL; - - jio_snprintf(buffer, PATH_MAX, "/proc/%s/cmdline", _entry->d_name); - buffer[PATH_MAX - 1] = '\0'; - if ((fp = os::fopen(buffer, "r")) != NULL) { - size_t size = 0; - char dummy; - - // find out how long the file is (stat always returns 0) - while (fread(&dummy, 1, 1, fp) == 1) { - size++; - } - if (size > 0) { - cmdline = NEW_C_HEAP_ARRAY(char, size + 1, mtInternal); - cmdline[0] = '\0'; - if (fseek(fp, 0, SEEK_SET) == 0) { - if (fread(cmdline, 1, size, fp) == size) { - // the file has the arguments separated by '\0', - // so we translate '\0' to ' ' - for (size_t i = 0; i < size; i++) { - if (cmdline[i] == '\0') { - cmdline[i] = ' '; - } - } - cmdline[size] = '\0'; - } - } - } - fclose(fp); - } - return cmdline; +bool SystemProcessInterface::SystemProcesses::initialize() { + return true; } -// get full path to exe from /proc//exe symlink -char* SystemProcessInterface::SystemProcesses::ProcessIterator::get_exe_path() { - char buffer[PATH_MAX]; - - jio_snprintf(buffer, PATH_MAX, "/proc/%s/exe", _entry->d_name); - buffer[PATH_MAX - 1] = '\0'; - return realpath(buffer, _exePath); +SystemProcessInterface::SystemProcesses::~SystemProcesses() { } -char* SystemProcessInterface::SystemProcesses::ProcessIterator::allocate_string(const char* str) const { +char* SystemProcessInterface::SystemProcesses::allocate_string(const char* str) const { if (str != NULL) { return os::strdup_check_oom(str, mtInternal); } return NULL; } -int SystemProcessInterface::SystemProcesses::ProcessIterator::current(SystemProcess* process_info) { - if (!is_valid()) { - return OS_ERR; - } - - process_info->set_pid(atoi(_entry->d_name)); - - get_exe_name(); - process_info->set_name(allocate_string(_exeName)); +int SystemProcessInterface::SystemProcesses::system_processes(SystemProcess** system_processes, int* nprocs) const { + ResourceMark rm; + perfstat_process_t* proc_stats; + SystemProcess* head; + perfstat_id_t name_holder; + int records_allocated = 0; - if (get_exe_path() != NULL) { - process_info->set_path(allocate_string(_exePath)); - } - - char* cmdline = NULL; - cmdline = get_cmdline(); - if (cmdline != NULL) { - process_info->set_command_line(allocate_string(cmdline)); - FREE_C_HEAP_ARRAY(char, cmdline); - } + assert(nprocs != NULL, "system_processes counter pointers is NULL!"); - return OS_OK; -} + head = NULL; + *nprocs = 0; + strncpy(name_holder.name, "", IDENTIFIER_LENGTH); -int SystemProcessInterface::SystemProcesses::ProcessIterator::next_process() { - if (!is_valid()) { + // calling perfstat_(NULL, NULL, _, 0) returns number of available records + *nprocs = libperfstat::perfstat_process(NULL, NULL, sizeof(perfstat_process_t), 0); + if(*nprocs < 1) { + // expect at least 1 process return OS_ERR; } - do { - _entry = os::readdir(_dir); - if (_entry == NULL) { - // Error or reached end. Could use errno to distinguish those cases. - _valid = false; - return OS_ERR; - } - } while(!is_valid_entry(_entry)); - - _valid = true; - return OS_OK; -} - -SystemProcessInterface::SystemProcesses::ProcessIterator::ProcessIterator() { - _dir = NULL; - _entry = NULL; - _valid = false; -} + records_allocated = *nprocs; + proc_stats = NEW_RESOURCE_ARRAY(perfstat_process_t, records_allocated); -bool SystemProcessInterface::SystemProcesses::ProcessIterator::initialize() { - // Not yet implemented. - return false; -} + // populate stats && set the actual number of procs that have been populated + // should never be higher than requested, but may be lower due to process death + *nprocs = libperfstat::perfstat_process(&name_holder, proc_stats, sizeof(perfstat_process_t), records_allocated); -SystemProcessInterface::SystemProcesses::ProcessIterator::~ProcessIterator() { - if (_dir != NULL) { - os::closedir(_dir); - } -} + for (int n = 0; n < *nprocs; n++) { + psinfo_t psinfo; + // Note: SystemProcess with free these in its dtor. + char* name = NEW_C_HEAP_ARRAY(char, IDENTIFIER_LENGTH, mtInternal); + char* exe_name = NEW_C_HEAP_ARRAY(char, PRFNSZ, mtInternal); + char* cmd_line = NEW_C_HEAP_ARRAY(char, PRARGSZ, mtInternal); -SystemProcessInterface::SystemProcesses::SystemProcesses() { - _iterator = NULL; -} + strncpy(name, proc_stats[n].proc_name, IDENTIFIER_LENGTH); -bool SystemProcessInterface::SystemProcesses::initialize() { - _iterator = new SystemProcessInterface::SystemProcesses::ProcessIterator(); - return _iterator->initialize(); -} + if (read_psinfo(proc_stats[n].pid, psinfo)) { + strncpy(exe_name, psinfo.pr_fname, PRFNSZ); + strncpy(cmd_line, psinfo.pr_psargs, PRARGSZ); + } -SystemProcessInterface::SystemProcesses::~SystemProcesses() { - if (_iterator != NULL) { - delete _iterator; + // create a new SystemProcess with next pointing to current head. + SystemProcess* sp = new SystemProcess(proc_stats[n].pid, + name, + exe_name, + cmd_line, + head); + // update head. + head = sp; } -} - -int SystemProcessInterface::SystemProcesses::system_processes(SystemProcess** system_processes, int* no_of_sys_processes) const { - assert(system_processes != NULL, "system_processes pointer is NULL!"); - assert(no_of_sys_processes != NULL, "system_processes counter pointers is NULL!"); - assert(_iterator != NULL, "iterator is NULL!"); - - // initialize pointers - *no_of_sys_processes = 0; - *system_processes = NULL; - while (_iterator->is_valid()) { - SystemProcess* tmp = new SystemProcess(); - _iterator->current(tmp); - - //if already existing head - if (*system_processes != NULL) { - //move "first to second" - tmp->set_next(*system_processes); - } - // new head - *system_processes = tmp; - // increment - (*no_of_sys_processes)++; - // step forward - _iterator->next_process(); - } + *system_processes = head; return OS_OK; } @@ -897,29 +542,68 @@ int CPUInformationInterface::cpu_information(CPUInformation& cpu_info) { } class NetworkPerformanceInterface::NetworkPerformance : public CHeapObj { - friend class NetworkPerformanceInterface; + NONCOPYABLE(NetworkPerformance); + private: + char* allocate_string(const char* str) const; + + public: NetworkPerformance(); - NONCOPYABLE(NetworkPerformance); bool initialize(); ~NetworkPerformance(); int network_utilization(NetworkInterface** network_interfaces) const; }; -NetworkPerformanceInterface::NetworkPerformance::NetworkPerformance() { - -} +NetworkPerformanceInterface::NetworkPerformance::NetworkPerformance() {} bool NetworkPerformanceInterface::NetworkPerformance::initialize() { return true; } -NetworkPerformanceInterface::NetworkPerformance::~NetworkPerformance() { -} +NetworkPerformanceInterface::NetworkPerformance::~NetworkPerformance() {} + +int NetworkPerformanceInterface::NetworkPerformance::network_utilization(NetworkInterface** network_interfaces) const { + int n_records = 0; + perfstat_netinterface_t* net_stats; + perfstat_id_t name_holder; + int records_allocated = 0; + + assert(network_interfaces != NULL, "network_interfaces is NULL"); + + *network_interfaces = NULL; + strncpy(name_holder.name , FIRST_NETINTERFACE, IDENTIFIER_LENGTH); + + // calling perfstat_(NULL, NULL, _, 0) returns number of available records + if ((n_records = libperfstat::perfstat_netinterface(NULL, NULL, sizeof(perfstat_netinterface_t), 0)) < 0) { + return OS_ERR; + } -int NetworkPerformanceInterface::NetworkPerformance::network_utilization(NetworkInterface** network_interfaces) const -{ - return FUNCTIONALITY_NOT_IMPLEMENTED; + records_allocated = n_records; + net_stats = NEW_C_HEAP_ARRAY(perfstat_netinterface_t, records_allocated, mtInternal); + + n_records = libperfstat::perfstat_netinterface(&name_holder, net_stats, sizeof(perfstat_netinterface_t), n_records); + + // check for error + if (n_records < 0) { + FREE_C_HEAP_ARRAY(perfstat_netinterface_t, net_stats); + return OS_ERR; + } + + for (int i = 0; i < n_records; i++) { + // Create new Network interface *with current head as next node* + // Note: NetworkInterface makes copies of these string values into RA memory + // this means: + // (1) we are free to clean our values upon exiting this proc + // (2) we avoid using RA-alloced memory here (ie. do not use NEW_RESOURCE_ARRAY) + NetworkInterface* new_interface = new NetworkInterface(net_stats[i].name, + net_stats[i].ibytes, + net_stats[i].obytes, + *network_interfaces); + *network_interfaces = new_interface; + } + + FREE_C_HEAP_ARRAY(perfstat_netinterface_t, net_stats); + return OS_OK; } NetworkPerformanceInterface::NetworkPerformanceInterface() { diff --git a/src/hotspot/os_cpu/aix_ppc/thread_aix_ppc.cpp b/src/hotspot/os_cpu/aix_ppc/thread_aix_ppc.cpp index 6b810bd3918..44c7baebd79 100644 --- a/src/hotspot/os_cpu/aix_ppc/thread_aix_ppc.cpp +++ b/src/hotspot/os_cpu/aix_ppc/thread_aix_ppc.cpp @@ -1,6 +1,7 @@ /* * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2014 SAP SE. All rights reserved. + * Copyright (c) 2022, IBM Corp. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +25,7 @@ */ #include "precompiled.hpp" +#include "memory/metaspace.hpp" #include "runtime/frame.inline.hpp" #include "runtime/thread.hpp" @@ -34,6 +36,8 @@ frame JavaThread::pd_last_frame() { address pc = _anchor.last_Java_pc(); // Last_Java_pc ist not set, if we come here from compiled code. + // Assume spill slot for link register contains a suitable pc. + // Should have been filled by method entry code. if (pc == NULL) pc = (address) *(sp + 2); @@ -41,16 +45,71 @@ frame JavaThread::pd_last_frame() { } bool JavaThread::pd_get_top_frame_for_profiling(frame* fr_addr, void* ucontext, bool isInJava) { - ucontext_t* uc = (ucontext_t*) ucontext; - *fr_addr = frame((intptr_t*)uc->uc_mcontext.jmp_context.gpr[1/*REG_SP*/], - (address)uc->uc_mcontext.jmp_context.iar); - return true; + + // If we have a last_Java_frame, then we should use it even if + // isInJava == true. It should be more reliable than ucontext info. + if (has_last_Java_frame() && frame_anchor()->walkable()) { + *fr_addr = pd_last_frame(); + return true; + } + + // At this point, we don't have a last_Java_frame, so + // we try to glean some information out of the ucontext + // if we were running Java code when SIGPROF came in. + if (isInJava) { + ucontext_t* uc = (ucontext_t*) ucontext; + address pc = (address)uc->uc_mcontext.jmp_context.iar; + + if (pc == NULL) { + // ucontext wasn't useful + return false; + } + + frame ret_frame((intptr_t*)uc->uc_mcontext.jmp_context.gpr[1/*REG_SP*/], pc); + + if (ret_frame.fp() == NULL) { + // The found frame does not have a valid frame pointer. + // Bail out because this will create big trouble later on, either + // - when using istate, calculated as (NULL - ijava_state_size) or + // - when using fp() directly in safe_for_sender() + // + // There is no conclusive description (yet) how this could happen, but it does. + // For more details on what was observed, see thread_linux_s390.cpp + return false; + } + + if (ret_frame.is_interpreted_frame()) { + frame::ijava_state *istate = ret_frame.get_ijava_state(); + const Method *m = (const Method*)(istate->method); + if (!Method::is_valid_method(m)) return false; + if (!Metaspace::contains(m->constMethod())) return false; + + uint64_t reg_bcp = uc->uc_mcontext.jmp_context.gpr[14/*R14_bcp*/]; + uint64_t istate_bcp = istate->bcp; + uint64_t code_start = (uint64_t)(m->code_base()); + uint64_t code_end = (uint64_t)(m->code_base() + m->code_size()); + if (istate_bcp >= code_start && istate_bcp < code_end) { + // we have a valid bcp, don't touch it, do nothing + } else if (reg_bcp >= code_start && reg_bcp < code_end) { + istate->bcp = reg_bcp; + } else { + return false; + } + } + if (!ret_frame.safe_for_sender(this)) { + // nothing else to try if the frame isn't good + return false; + } + *fr_addr = ret_frame; + return true; + } + // nothing else to try + return false; } -// Forte Analyzer AsyncGetCallTrace profiling support is not implemented on Aix/PPC. +// Forte Analyzer AsyncGetCallTrace profiling support. bool JavaThread::pd_get_top_frame_for_signal_handler(frame* fr_addr, void* ucontext, bool isInJava) { - Unimplemented(); - return false; + return pd_get_top_frame_for_profiling(fr_addr, ucontext, isInJava); } void JavaThread::cache_global_variables() { } diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 8e00e12f1ba..81c2dffe2d1 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -821,7 +821,7 @@ javax/script/Test7.java 8239361 generic- # jdk_jfr -jdk/jfr/event/runtime/TestNetworkUtilizationEvent.java 8228990 generic-all +jdk/jfr/event/runtime/TestNetworkUtilizationEvent.java 8228990 macosx-all,linux-all,windows-all jdk/jfr/event/compiler/TestCodeSweeper.java 8225209 generic-all jdk/jfr/event/os/TestThreadContextSwitches.java 8247776 windows-all jdk/jfr/startupargs/TestStartName.java 8214685 windows-x64 diff --git a/test/jdk/jdk/jfr/event/runtime/TestNativeLibrariesEvent.java b/test/jdk/jdk/jfr/event/runtime/TestNativeLibrariesEvent.java index f3299820925..77eb0362841 100644 --- a/test/jdk/jdk/jfr/event/runtime/TestNativeLibrariesEvent.java +++ b/test/jdk/jdk/jfr/event/runtime/TestNativeLibrariesEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -77,7 +77,10 @@ public class TestNativeLibrariesEvent { libTemplate = "lib%s.dylib"; } else if (Platform.isLinux()) { libTemplate = "lib%s.so"; + } else if (Platform.isAix()) { + libTemplate = "lib%s.so"; } + if (libTemplate == null) { throw new Exception("Unsupported OS"); } -- GitLab From b4900b1298e536c0ceaa77bc0ac0e8e6ccba6400 Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Thu, 17 Feb 2022 09:36:05 +0000 Subject: [PATCH 539/564] 8264743: Add forRemoval for deprecated classes and method in javax/swing/plaf/basic Reviewed-by: trebari, prr --- .../javax/swing/plaf/basic/BasicDirectoryModel.java | 6 +++--- .../classes/javax/swing/plaf/basic/BasicMenuItemUI.java | 2 +- .../classes/javax/swing/plaf/basic/BasicScrollPaneUI.java | 8 ++++---- .../classes/javax/swing/plaf/basic/BasicToolBarUI.java | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicDirectoryModel.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicDirectoryModel.java index 34c53ca915f..63e8309fda2 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicDirectoryModel.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicDirectoryModel.java @@ -228,7 +228,7 @@ public class BasicDirectoryModel extends AbstractListModel implements Pr * @param e list data event * @deprecated Obsolete method, not used anymore. */ - @Deprecated(since = "17") + @Deprecated(since = "17", forRemoval = true) public void intervalAdded(ListDataEvent e) { } @@ -237,7 +237,7 @@ public class BasicDirectoryModel extends AbstractListModel implements Pr * @param e list data event * @deprecated Obsolete method, not used anymore. */ - @Deprecated(since = "17") + @Deprecated(since = "17", forRemoval = true) public void intervalRemoved(ListDataEvent e) { } @@ -257,7 +257,7 @@ public class BasicDirectoryModel extends AbstractListModel implements Pr * @param b another file * @deprecated Obsolete method, not used anymore. */ - @Deprecated(since = "17") + @Deprecated(since = "17", forRemoval = true) protected boolean lt(File a, File b) { // First ignore case when comparing int diff = a.getName().toLowerCase().compareTo(b.getName().toLowerCase()); diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java index db9eee52f1f..cbe840c1ad6 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java @@ -928,7 +928,7 @@ public class BasicMenuItemUI extends MenuItemUI * All its functionality has been moved into Handler. * @deprecated */ - @Deprecated(since = "17") + @Deprecated(since = "17", forRemoval = true) protected class MouseInputHandler implements MouseInputListener { // NOTE: This class exists only for backward compatibility. All // its functionality has been moved into Handler. If you need to add diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicScrollPaneUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicScrollPaneUI.java index 714199af15b..e017ac6722b 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicScrollPaneUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicScrollPaneUI.java @@ -500,7 +500,7 @@ public class BasicScrollPaneUI * All its functionality has been moved into Handler. * @deprecated */ - @Deprecated(since = "17") + @Deprecated(since = "17", forRemoval = true) public class ViewportChangeHandler implements ChangeListener { /** @@ -534,7 +534,7 @@ public class BasicScrollPaneUI * All its functionality has been moved into Handler. * @deprecated */ - @Deprecated(since = "17") + @Deprecated(since = "17", forRemoval = true) public class HSBChangeListener implements ChangeListener { /** @@ -577,7 +577,7 @@ public class BasicScrollPaneUI * All its functionality has been moved into Handler. * @deprecated */ - @Deprecated(since = "17") + @Deprecated(since = "17", forRemoval = true) public class VSBChangeListener implements ChangeListener { /** @@ -786,7 +786,7 @@ public class BasicScrollPaneUI * All its functionality has been moved into Handler. * @deprecated */ - @Deprecated(since = "17") + @Deprecated(since = "17", forRemoval = true) public class PropertyChangeHandler implements PropertyChangeListener { /** diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicToolBarUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicToolBarUI.java index 8a13bf119a5..975272a03b7 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicToolBarUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicToolBarUI.java @@ -551,7 +551,7 @@ public class BasicToolBarUI extends ToolBarUI implements SwingConstants * @deprecated It is recommended that {@link BasicToolBarUI#createFloatingWindow(JToolBar)} * be used instead */ - @Deprecated(since = "17") + @Deprecated(since = "17", forRemoval = true) protected JFrame createFloatingFrame(JToolBar toolbar) { Window window = SwingUtilities.getWindowAncestor(toolbar); @SuppressWarnings("serial") // anonymous class -- GitLab From 9ca435b4c03f9741709bbfab22fb006de8c8c9d3 Mon Sep 17 00:00:00 2001 From: Julia Boes Date: Thu, 17 Feb 2022 10:35:05 +0000 Subject: [PATCH 540/564] 8281305: Test com/sun/net/httpserver/simpleserver/MapToPathTest.java fails on Windows 11 Reviewed-by: dfuchs --- .../simpleserver/FileServerHandler.java | 5 +- .../simpleserver/URIPathSegment.java | 44 +++++++++++++++ .../simpleserver/URIPathSegment.java | 53 +++++++++++++++++++ .../simpleserver/MapToPathTest.java | 43 ++++++++++++--- 4 files changed, 138 insertions(+), 7 deletions(-) create mode 100644 src/jdk.httpserver/unix/classes/sun/net/httpserver/simpleserver/URIPathSegment.java create mode 100644 src/jdk.httpserver/windows/classes/sun/net/httpserver/simpleserver/URIPathSegment.java diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/FileServerHandler.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/FileServerHandler.java index e0e9736cad4..b3dc1ff5f4a 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/FileServerHandler.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/FileServerHandler.java @@ -227,9 +227,12 @@ public final class FileServerHandler implements HttpHandler { // resolve each path segment against the root Path path = root; for (var segment : pathSegment) { + if (!URIPathSegment.isSupported(segment)) { + return null; // stop resolution, null results in 404 response + } path = path.resolve(segment); if (!Files.isReadable(path) || isHiddenOrSymLink(path)) { - return null; // stop resolution, null results in 404 response + return null; // stop resolution } } path = path.normalize(); diff --git a/src/jdk.httpserver/unix/classes/sun/net/httpserver/simpleserver/URIPathSegment.java b/src/jdk.httpserver/unix/classes/sun/net/httpserver/simpleserver/URIPathSegment.java new file mode 100644 index 00000000000..497ccd7a850 --- /dev/null +++ b/src/jdk.httpserver/unix/classes/sun/net/httpserver/simpleserver/URIPathSegment.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.net.httpserver.simpleserver; + +/** + * A class that represents a URI path segment. + */ +final class URIPathSegment { + + private URIPathSegment() { throw new AssertionError(); } + + /** + * Checks if the segment of a URI path is supported. + * + * @param segment the segment string + * @return true + */ + static boolean isSupported(String segment) { + return true; + } +} diff --git a/src/jdk.httpserver/windows/classes/sun/net/httpserver/simpleserver/URIPathSegment.java b/src/jdk.httpserver/windows/classes/sun/net/httpserver/simpleserver/URIPathSegment.java new file mode 100644 index 00000000000..0de28f188dc --- /dev/null +++ b/src/jdk.httpserver/windows/classes/sun/net/httpserver/simpleserver/URIPathSegment.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.net.httpserver.simpleserver; + +/** + * A class that represents a URI path segment. + */ +final class URIPathSegment { + + private URIPathSegment() { throw new AssertionError(); } + + /** + * Checks if the segment of a URI path is supported. For example, + * "C:" is supported as a drive on Windows only. + * + * @param segment the segment string + * @return true if the segment is supported + */ + static boolean isSupported(String segment) { + // apply same logic as WindowsPathParser + if (segment.length() >= 2 && isLetter(segment.charAt(0)) && segment.charAt(1) == ':') { + return false; + } + return true; + } + + private static boolean isLetter(char c) { + return ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')); + } +} diff --git a/test/jdk/com/sun/net/httpserver/simpleserver/MapToPathTest.java b/test/jdk/com/sun/net/httpserver/simpleserver/MapToPathTest.java index d6e61da4073..aa8f37acc1b 100644 --- a/test/jdk/com/sun/net/httpserver/simpleserver/MapToPathTest.java +++ b/test/jdk/com/sun/net/httpserver/simpleserver/MapToPathTest.java @@ -137,19 +137,27 @@ public class MapToPathTest { var res3 = client.send(req3, BodyHandlers.ofString()); assertEquals(res3.statusCode(), 404); // not found - var req4 = HttpRequest.newBuilder(uri(server, "/foo/file:" + TEST_DIR.getParent())).build(); + var req4 = HttpRequest.newBuilder(uri(server, "/foo/bar/baz/c:.//")).build(); var res4 = client.send(req4, BodyHandlers.ofString()); assertEquals(res4.statusCode(), 404); // not found - var req5 = HttpRequest.newBuilder(uri(server, "/foo/bar/\\..\\../")).build(); + var req5 = HttpRequest.newBuilder(uri(server, "/foo/bar/baz/c:..//")).build(); var res5 = client.send(req5, BodyHandlers.ofString()); assertEquals(res5.statusCode(), 404); // not found - var req6 = HttpRequest.newBuilder(uri(server, "/foo")).build(); + var req6 = HttpRequest.newBuilder(uri(server, "/foo/file:" + TEST_DIR.getParent())).build(); var res6 = client.send(req6, BodyHandlers.ofString()); - assertEquals(res6.statusCode(), 301); // redirect - assertEquals(res6.headers().firstValue("content-length").get(), "0"); - assertEquals(res6.headers().firstValue("location").get(), "/foo/"); + assertEquals(res6.statusCode(), 404); // not found + + var req7 = HttpRequest.newBuilder(uri(server, "/foo/bar/\\..\\../")).build(); + var res7 = client.send(req7, BodyHandlers.ofString()); + assertEquals(res7.statusCode(), 404); // not found + + var req8 = HttpRequest.newBuilder(uri(server, "/foo")).build(); + var res8 = client.send(req8, BodyHandlers.ofString()); + assertEquals(res8.statusCode(), 301); // redirect + assertEquals(res8.headers().firstValue("content-length").get(), "0"); + assertEquals(res8.headers().firstValue("location").get(), "/foo/"); } finally { server.stop(0); } @@ -250,6 +258,29 @@ public class MapToPathTest { server.stop(0); } } + { + // Test that a request path segment that is a Windows root drive + // does not circumvent access restrictions. + // + // For example, given the test directory tree: + // + // |-- TEST_DIR + // |-- foo + // |-- bar ----->>> if hidden, itself and any of its subdirectories are not accessible + // |-- baz + // |-- file.txt + // ... + var handler = SimpleFileServer.createFileHandler(TEST_DIR); + var server = HttpServer.create(LOOPBACK_ADDR, 10, "/", handler, OUTPUT_FILTER); + server.start(); + try { + var req1 = HttpRequest.newBuilder(uri(server, "/foo/bar/c:/baz/")).build(); + var res1 = client.send(req1, BodyHandlers.ofString()); + assertEquals(res1.statusCode(), 404); // not found + } finally { + server.stop(0); + } + } } // Tests with a mixture of in-memory and file handlers. -- GitLab From 3b7a3cfce345cc900e042c5378d35d1237bdcd78 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Thu, 17 Feb 2022 11:40:43 +0000 Subject: [PATCH 541/564] 8281971: Remove unimplemented InstanceRefKlass::do_next Reviewed-by: dholmes --- src/hotspot/share/oops/instanceRefKlass.hpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/hotspot/share/oops/instanceRefKlass.hpp b/src/hotspot/share/oops/instanceRefKlass.hpp index 4156559df05..16a9bb53c3a 100644 --- a/src/hotspot/share/oops/instanceRefKlass.hpp +++ b/src/hotspot/share/oops/instanceRefKlass.hpp @@ -97,9 +97,6 @@ class InstanceRefKlass: public InstanceKlass { template static void do_referent(oop obj, OopClosureType* closure, Contains& contains); - template - static void do_next(oop obj, OopClosureType* closure, Contains& contains); - template static void do_discovered(oop obj, OopClosureType* closure, Contains& contains); -- GitLab From d0e11808fd688d96e5cfeb586d1de277f26da5ad Mon Sep 17 00:00:00 2001 From: Andrey Turbanov Date: Thu, 17 Feb 2022 12:31:37 +0000 Subject: [PATCH 542/564] 8282019: Unused static fields DEGREES_TO_RADIANS, RADIANS_TO_DEGREES in StrictMath Reviewed-by: bpb, darcy --- .../share/classes/java/lang/StrictMath.java | 21 ++++--------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/src/java.base/share/classes/java/lang/StrictMath.java b/src/java.base/share/classes/java/lang/StrictMath.java index b5e3541c85c..53b25fedebb 100644 --- a/src/java.base/share/classes/java/lang/StrictMath.java +++ b/src/java.base/share/classes/java/lang/StrictMath.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2022, 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,19 +101,6 @@ public final class StrictMath { */ public static final double PI = 3.14159265358979323846; - /** - * Constant by which to multiply an angular value in degrees to obtain an - * angular value in radians. - */ - private static final double DEGREES_TO_RADIANS = 0.017453292519943295; - - /** - * Constant by which to multiply an angular value in radians to obtain an - * angular value in degrees. - */ - - private static final double RADIANS_TO_DEGREES = 57.29577951308232; - /** * Returns the trigonometric sine of an angle. Special cases: *
    • If the argument is NaN or an infinity, then the @@ -397,7 +384,7 @@ public final class StrictMath { * @param a the value to be floored or ceiled * @param negativeBoundary result for values in (-1, 0) * @param positiveBoundary result for values in (0, 1) - * @param increment value to add when the argument is non-integral + * @param sign the sign of the result */ private static double floorOrCeil(double a, double negativeBoundary, @@ -408,8 +395,8 @@ public final class StrictMath { if (exponent < 0) { /* * Absolute value of argument is less than 1. - * floorOrceil(-0.0) => -0.0 - * floorOrceil(+0.0) => +0.0 + * floorOrCeil(-0.0) => -0.0 + * floorOrCeil(+0.0) => +0.0 */ return ((a == 0.0) ? a : ( (a < 0.0) ? negativeBoundary : positiveBoundary) ); -- GitLab From 4c7f8b49a4845acf58272c42327328d6d2837cea Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Thu, 17 Feb 2022 17:12:40 +0000 Subject: [PATCH 543/564] 8268250: Class.arrayType() for a 255-d array throws undocumented IllegalArgumentException Reviewed-by: sundar, alanb --- .../share/classes/java/lang/Class.java | 11 ++++- test/jdk/java/lang/Class/ArrayType.java | 49 +++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 test/jdk/java/lang/Class/ArrayType.java diff --git a/src/java.base/share/classes/java/lang/Class.java b/src/java.base/share/classes/java/lang/Class.java index fce7793fbcf..840abc63aaf 100644 --- a/src/java.base/share/classes/java/lang/Class.java +++ b/src/java.base/share/classes/java/lang/Class.java @@ -4485,12 +4485,21 @@ public final class Class implements java.io.Serializable, * Returns a {@code Class} for an array type whose component type * is described by this {@linkplain Class}. * + * @throws UnsupportedOperationException if this component type is {@linkplain + * Void#TYPE void} or if the number of dimensions of the resulting array + * type would exceed 255. * @return a {@code Class} describing the array type + * @jvms 4.3.2 Field Descriptors + * @jvms 4.4.1 The {@code CONSTANT_Class_info} Structure * @since 12 */ @Override public Class arrayType() { - return Array.newInstance(this, 0).getClass(); + try { + return Array.newInstance(this, 0).getClass(); + } catch (IllegalArgumentException iae) { + throw new UnsupportedOperationException(iae); + } } /** diff --git a/test/jdk/java/lang/Class/ArrayType.java b/test/jdk/java/lang/Class/ArrayType.java new file mode 100644 index 00000000000..9764dd0b366 --- /dev/null +++ b/test/jdk/java/lang/Class/ArrayType.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2021, 2022, 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 8268250 + * @summary Check exceptional behavior of Class.arrayType + */ + +import java.lang.reflect.*; +import java.util.function.*; + +public class ArrayType { + public static void main(String... args) { + expectException(() -> Void.TYPE); + expectException(() -> Array.newInstance(int.class, new int[255]) + .getClass()); + } + + private static void expectException(Supplier> arrayTypeArg) { + try { + Class arrayClazz = arrayTypeArg.get().arrayType(); + throw new RuntimeException("Expected exception not thrown: " + + arrayClazz); + } catch (UnsupportedOperationException uoe) { + ; // Expected + } + } +} -- GitLab From a6f8a386efa7af162f4b815951287f0a9bc1f396 Mon Sep 17 00:00:00 2001 From: Tim Prinzing Date: Thu, 17 Feb 2022 17:34:39 +0000 Subject: [PATCH 544/564] 8281000: ClassLoader::registerAsParallelCapable throws NPE if caller is null Reviewed-by: erikj, ihse, mchung, bchristi --- make/test/JtregNativeJdk.gmk | 2 + .../share/classes/java/lang/ClassLoader.java | 10 +++ .../BadRegisterAsParallelCapableCaller.java | 57 ++++++++++++++ .../NullCallerClassLoaderTest.java | 71 +++++++++++++++++ .../exeNullCallerClassLoaderTest.c | 76 +++++++++++++++++++ 5 files changed, 216 insertions(+) create mode 100644 test/jdk/java/lang/ClassLoader/BadRegisterAsParallelCapableCaller.java create mode 100644 test/jdk/java/lang/ClassLoader/exeNullCallerClassLoaderTest/NullCallerClassLoaderTest.java create mode 100644 test/jdk/java/lang/ClassLoader/exeNullCallerClassLoaderTest/exeNullCallerClassLoaderTest.c diff --git a/make/test/JtregNativeJdk.gmk b/make/test/JtregNativeJdk.gmk index 974ab77cb7b..6797952bc05 100644 --- a/make/test/JtregNativeJdk.gmk +++ b/make/test/JtregNativeJdk.gmk @@ -62,6 +62,7 @@ ifeq ($(call isTargetOs, windows), true) WIN_LIB_JLI := $(SUPPORT_OUTPUTDIR)/native/java.base/libjli/jli.lib BUILD_JDK_JTREG_EXECUTABLES_LIBS_exeJliLaunchTest := $(WIN_LIB_JLI) BUILD_JDK_JTREG_EXECUTABLES_LIBS_exeCallerAccessTest := jvm.lib + BUILD_JDK_JTREG_EXECUTABLES_LIBS_exeNullCallerClassLoaderTest := jvm.lib BUILD_JDK_JTREG_EXECUTABLES_LIBS_exeNullCallerLookupTest := jvm.lib BUILD_JDK_JTREG_EXECUTABLES_LIBS_exerevokeall := advapi32.lib BUILD_JDK_JTREG_LIBRARIES_CFLAGS_libAsyncStackWalk := /EHsc @@ -81,6 +82,7 @@ else endif BUILD_JDK_JTREG_EXECUTABLES_LIBS_exeJliLaunchTest := -ljli BUILD_JDK_JTREG_EXECUTABLES_LIBS_exeCallerAccessTest := -ljvm + BUILD_JDK_JTREG_EXECUTABLES_LIBS_exeNullCallerClassLoaderTest := -ljvm BUILD_JDK_JTREG_EXECUTABLES_LIBS_exeNullCallerLookupTest := -ljvm endif diff --git a/src/java.base/share/classes/java/lang/ClassLoader.java b/src/java.base/share/classes/java/lang/ClassLoader.java index ed5ad09da44..0aeb7620189 100644 --- a/src/java.base/share/classes/java/lang/ClassLoader.java +++ b/src/java.base/share/classes/java/lang/ClassLoader.java @@ -1606,9 +1606,16 @@ public abstract class ClassLoader { * *

      Note that once a class loader is registered as parallel capable, there * is no way to change it back.

      + *

      + * In cases where this method is called from a context where the caller is + * not a subclass of {@code ClassLoader} or there is no caller frame on the + * stack (e.g. when called directly from a JNI attached thread), + * {@code IllegalCallerException} is thrown. + *

      * * @return {@code true} if the caller is successfully registered as * parallel capable and {@code false} if otherwise. + * @throws IllegalCallerException if the caller is not a subclass of {@code ClassLoader} * * @see #isRegisteredAsParallelCapable() * @@ -1622,6 +1629,9 @@ public abstract class ClassLoader { // Caller-sensitive adapter method for reflective invocation @CallerSensitiveAdapter private static boolean registerAsParallelCapable(Class caller) { + if ((caller == null) || !ClassLoader.class.isAssignableFrom(caller)) { + throw new IllegalCallerException(caller + " not a subclass of ClassLoader"); + } return ParallelLoaders.register(caller.asSubclass(ClassLoader.class)); } diff --git a/test/jdk/java/lang/ClassLoader/BadRegisterAsParallelCapableCaller.java b/test/jdk/java/lang/ClassLoader/BadRegisterAsParallelCapableCaller.java new file mode 100644 index 00000000000..8b1c8d24d5e --- /dev/null +++ b/test/jdk/java/lang/ClassLoader/BadRegisterAsParallelCapableCaller.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2022, 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 8281000 + * @summary Test ClassLoader.isRegisteredAsParallelCapable() method with an + * invalid caller (non-JNI cases). This test uses reflection and opens + * the java.base module so it runs separate from behavior tests of + * isRegisteredParallelCapable to avoid side effects. + * @modules java.base/java.lang:open + * @run main/othervm BadRegisterAsParallelCapableCaller + */ + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +public class BadRegisterAsParallelCapableCaller { + + public static void main(String[] args) throws Exception { + + Throwable thrown = null; + final Method m = ClassLoader.class.getDeclaredMethod("registerAsParallelCapable"); + m.setAccessible(true); + try { + m.invoke(null); + } catch (InvocationTargetException ite) { + thrown = ite.getCause(); + } + if (! (thrown instanceof IllegalCallerException)) { + throw new RuntimeException("Didn't get expected IllegalCallerException, got "+ thrown); + } else { + System.out.println("Invalid caller threw IllegalCallerException as expected"); + } + } + +} diff --git a/test/jdk/java/lang/ClassLoader/exeNullCallerClassLoaderTest/NullCallerClassLoaderTest.java b/test/jdk/java/lang/ClassLoader/exeNullCallerClassLoaderTest/NullCallerClassLoaderTest.java new file mode 100644 index 00000000000..52427f01e6e --- /dev/null +++ b/test/jdk/java/lang/ClassLoader/exeNullCallerClassLoaderTest/NullCallerClassLoaderTest.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2022, 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 8281000 + * @summary Test uses custom launcher that starts VM using JNI that verifies + * ClassLoader.registerAsParallelCapable with null caller class + * throws an IllegalCallerException. + * @library /test/lib + * @requires os.family != "aix" + * @run main/native NullCallerClassLoaderTest + */ + +// Test disabled on AIX since we cannot invoke the JVM on the primordial thread. + +import java.io.File; +import java.util.Map; +import jdk.test.lib.Platform; +import jdk.test.lib.process.OutputAnalyzer; + +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; + +public class NullCallerClassLoaderTest { + public static void main(String[] args) throws IOException { + Path launcher = Path.of(System.getProperty("test.nativepath"), "NullCallerClassLoaderTest"); + ProcessBuilder pb = new ProcessBuilder(launcher.toString()); + Map env = pb.environment(); + + String libDir = Platform.libDir().toString(); + String vmDir = Platform.jvmLibDir().toString(); + + // set up shared library path + String sharedLibraryPathEnvName = Platform.sharedLibraryPathVariableName(); + env.compute(sharedLibraryPathEnvName, + (k, v) -> (v == null) ? libDir : v + File.pathSeparator + libDir); + env.compute(sharedLibraryPathEnvName, + (k, v) -> (v == null) ? vmDir : v + File.pathSeparator + vmDir); + + System.out.println("Launching: " + launcher + " shared library path: " + + env.get(sharedLibraryPathEnvName)); + new OutputAnalyzer(pb.start()) + .outputTo(System.out) + .errorTo(System.err) + .shouldHaveExitValue(0); + } +} + diff --git a/test/jdk/java/lang/ClassLoader/exeNullCallerClassLoaderTest/exeNullCallerClassLoaderTest.c b/test/jdk/java/lang/ClassLoader/exeNullCallerClassLoaderTest/exeNullCallerClassLoaderTest.c new file mode 100644 index 00000000000..d488c74bf6c --- /dev/null +++ b/test/jdk/java/lang/ClassLoader/exeNullCallerClassLoaderTest/exeNullCallerClassLoaderTest.c @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include +#include + +#include "jni.h" +#include "assert.h" + +static jclass class_IllegalCallerException; + +int checkAndClearIllegalCallerExceptionThrown(JNIEnv *env) { + jthrowable t = (*env)->ExceptionOccurred(env); + if ((*env)->IsInstanceOf(env, t, class_IllegalCallerException) == JNI_TRUE) { + (*env)->ExceptionClear(env); + return JNI_TRUE; + } + return JNI_FALSE; +} + +int main(int argc, char** args) { + JavaVM *jvm; + JNIEnv *env; + JavaVMInitArgs vm_args; + JavaVMOption options[1]; + jint rc; + + + vm_args.version = JNI_VERSION_1_2; + vm_args.nOptions = 0; + vm_args.options = options; + + if ((rc = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args)) != JNI_OK) { + printf("ERROR: cannot create VM.\n"); + exit(-1); + } + class_IllegalCallerException = (*env)->FindClass(env, "java/lang/IllegalCallerException"); + assert (class_IllegalCallerException != NULL); + + // call ClassLoader.registerAsParallelCapable() + jclass class_ClassLoader = (*env)->FindClass(env, "java/lang/ClassLoader"); + assert(class_ClassLoader != NULL); + jmethodID mid_ClassLoader_registerAsParallelCapable = (*env)->GetStaticMethodID(env, class_ClassLoader, "registerAsParallelCapable", "()Z" ); + assert(mid_ClassLoader_registerAsParallelCapable != NULL); + jboolean b = (*env)->CallStaticBooleanMethod(env, class_ClassLoader, mid_ClassLoader_registerAsParallelCapable ); + if ((rc = checkAndClearIllegalCallerExceptionThrown(env)) != JNI_TRUE) { + printf("ERROR: Didn't get the expected IllegalCallerException.\n"); + exit(-1); + } + + printf("Expected IllegalCallerException was thrown\n"); + + (*jvm)->DestroyJavaVM(jvm); + return 0; +} + -- GitLab From cd9a3cf05b2c200709103e2e8596414a62a1c441 Mon Sep 17 00:00:00 2001 From: Mahendra Chhipa Date: Thu, 17 Feb 2022 17:45:06 +0000 Subject: [PATCH 545/564] 8282017: sun/net/www/protocol/https/HttpsURLConnection/B6216082.java fails with "SocketException: Unexpected end of file from server" Reviewed-by: dfuchs --- test/jdk/ProblemList.txt | 2 -- .../www/protocol/https/HttpsURLConnection/TunnelProxy.java | 6 +++--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 81c2dffe2d1..7e19b4bd713 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -597,8 +597,6 @@ java/net/MulticastSocket/SetGetNetworkInterfaceTest.java 8219083 windows- java/net/ServerSocket/AcceptInheritHandle.java 8211854 aix-ppc64 -sun/net/www/protocol/https/HttpsURLConnection/B6216082.java 8282017 generic-all - ############################################################################ # jdk_nio diff --git a/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/TunnelProxy.java b/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/TunnelProxy.java index 979e8be9acd..9cec3987d9e 100644 --- a/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/TunnelProxy.java +++ b/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/TunnelProxy.java @@ -261,9 +261,9 @@ public class TunnelProxy { boolean res; try { InputStream is = new BufferedInputStream (new NioInputStream (chan)); - String requestline = readLine (is); - HttpHeaderParser mhead = new HttpHeaderParser (is); - String[] req = requestline.split (" "); + HttpHeaderParser mHead = new HttpHeaderParser (is); + String requestLine = mHead.getRequestDetails(); + String[] req = requestLine.split (" "); if (req.length < 2) { /* invalid request line */ return false; -- GitLab From 129277653e51e9b1387ecee279a6ccee9199c8ff Mon Sep 17 00:00:00 2001 From: Naoto Sato Date: Thu, 17 Feb 2022 19:03:08 +0000 Subject: [PATCH 546/564] 8281317: CompactNumberFormat displays 4-digit values when rounding to a new range Reviewed-by: joehw --- .../java/text/CompactNumberFormat.java | 41 ++++++++++++++++--- .../TestCompactPatternsValidity.java | 12 +++--- 2 files changed, 42 insertions(+), 11 deletions(-) diff --git a/src/java.base/share/classes/java/text/CompactNumberFormat.java b/src/java.base/share/classes/java/text/CompactNumberFormat.java index 0449133d5b8..551945cc832 100644 --- a/src/java.base/share/classes/java/text/CompactNumberFormat.java +++ b/src/java.base/share/classes/java/text/CompactNumberFormat.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2022, 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 @@ -589,6 +589,10 @@ public final class CompactNumberFormat extends NumberFormat { if (compactDataIndex != -1) { long divisor = (Long) divisors.get(compactDataIndex); int iPart = getIntegerPart(number, divisor); + if (checkIncrement(iPart, compactDataIndex, divisor)) { + divisor = (Long) divisors.get(++compactDataIndex); + iPart = getIntegerPart(number, divisor); + } String prefix = getAffix(false, true, isNegative, compactDataIndex, iPart); String suffix = getAffix(false, false, isNegative, compactDataIndex, iPart); @@ -658,6 +662,10 @@ public final class CompactNumberFormat extends NumberFormat { if (compactDataIndex != -1) { long divisor = (Long) divisors.get(compactDataIndex); int iPart = getIntegerPart(number, divisor); + if (checkIncrement(iPart, compactDataIndex, divisor)) { + divisor = (Long) divisors.get(++compactDataIndex); + iPart = getIntegerPart(number, divisor); + } String prefix = getAffix(false, true, isNegative, compactDataIndex, iPart); String suffix = getAffix(false, false, isNegative, compactDataIndex, iPart); if (!prefix.isEmpty() || !suffix.isEmpty()) { @@ -753,6 +761,10 @@ public final class CompactNumberFormat extends NumberFormat { if (compactDataIndex != -1) { Number divisor = divisors.get(compactDataIndex); int iPart = getIntegerPart(number.doubleValue(), divisor.doubleValue()); + if (checkIncrement(iPart, compactDataIndex, divisor.doubleValue())) { + divisor = divisors.get(++compactDataIndex); + iPart = getIntegerPart(number.doubleValue(), divisor.doubleValue()); + } String prefix = getAffix(false, true, isNegative, compactDataIndex, iPart); String suffix = getAffix(false, false, isNegative, compactDataIndex, iPart); if (!prefix.isEmpty() || !suffix.isEmpty()) { @@ -820,6 +832,10 @@ public final class CompactNumberFormat extends NumberFormat { if (compactDataIndex != -1) { Number divisor = divisors.get(compactDataIndex); int iPart = getIntegerPart(number.doubleValue(), divisor.doubleValue()); + if (checkIncrement(iPart, compactDataIndex, divisor.doubleValue())) { + divisor = divisors.get(++compactDataIndex); + iPart = getIntegerPart(number.doubleValue(), divisor.doubleValue()); + } String prefix = getAffix(false, true, isNegative, compactDataIndex, iPart); String suffix = getAffix(false, false, isNegative, compactDataIndex, iPart); if (!prefix.isEmpty() || !suffix.isEmpty()) { @@ -875,7 +891,7 @@ public final class CompactNumberFormat extends NumberFormat { * Appends the {@code prefix} to the {@code result} and also set the * {@code NumberFormat.Field.SIGN} and {@code NumberFormat.Field.PREFIX} * field positions. - * @param result the resulting string, where the pefix is to be appended + * @param result the resulting string, where the prefix is to be appended * @param prefix prefix to append * @param delegate notified of the locations of * {@code NumberFormat.Field.SIGN} and @@ -910,7 +926,7 @@ public final class CompactNumberFormat extends NumberFormat { * @param result the resulting string, where the text is to be appended * @param string the text to append * @param delegate notified of the locations of sub fields - * @param positions a list of {@code FieldPostion} in the given + * @param positions a list of {@code FieldPosition} in the given * string */ private void append(StringBuffer result, String string, @@ -956,10 +972,10 @@ public final class CompactNumberFormat extends NumberFormat { } /** - * Returns a list of {@code FieldPostion} in the given {@code pattern}. + * Returns a list of {@code FieldPosition} in the given {@code pattern}. * @param pattern the pattern to be parsed for {@code FieldPosition} * @param field whether a PREFIX or SUFFIX field - * @return a list of {@code FieldPostion} + * @return a list of {@code FieldPosition} */ private List getFieldPositions(String pattern, Field field) { List positions = new ArrayList<>(); @@ -1769,7 +1785,7 @@ public final class CompactNumberFormat extends NumberFormat { if (cnfMultiplier.longValue() != 1L) { double doubleResult = number.doubleValue() * cnfMultiplier.doubleValue(); doubleResult = (double) convertIfNegative(doubleResult, status, gotLongMin); - // Check if a double can be represeneted as a long + // Check if a double can be represented as a long long longResult = (long) doubleResult; gotDouble = ((doubleResult != (double) longResult) || (doubleResult == 0.0 && 1 / doubleResult < 0.0)); @@ -2396,6 +2412,19 @@ public final class CompactNumberFormat extends NumberFormat { .divide(BigDecimal.valueOf(divisor), roundingMode).intValue(); } + // Checks whether the iPart is incremented by the BigDecimal division in + // getIntegerPart(), and affects the compact number index. + private boolean checkIncrement(int iPart, int index, double divisor) { + if (index < compactPatterns.length - 1 && + !"".equals(compactPatterns[index])) { // ignore empty pattern + var nextDiv = divisors.get(index + 1).doubleValue(); + if (divisor != nextDiv) { + return Math.log10(iPart) == Math.log10(nextDiv) - Math.log10(divisor); + } + } + return false; + } + /** * Returns LDML's tag from the plurals rules * diff --git a/test/jdk/java/text/Format/CompactNumberFormat/TestCompactPatternsValidity.java b/test/jdk/java/text/Format/CompactNumberFormat/TestCompactPatternsValidity.java index 6ca1f25ea90..8476b568ba0 100644 --- a/test/jdk/java/text/Format/CompactNumberFormat/TestCompactPatternsValidity.java +++ b/test/jdk/java/text/Format/CompactNumberFormat/TestCompactPatternsValidity.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,7 +22,7 @@ */ /* * @test - * @bug 8177552 8217254 8251499 + * @bug 8177552 8217254 8251499 8281317 * @summary Checks the validity of compact number patterns specified through * CompactNumberFormat constructor * @run testng/othervm TestCompactPatternsValidity @@ -101,8 +101,9 @@ public class TestCompactPatternsValidity { {COMPACT_PATTERN5, List.of(100, 1000, 30000), List.of("100", "1K", "K3")}, {COMPACT_PATTERN6, List.of(20.99, 1000, 30000), List.of("21", ".1K", ".30K")}, {COMPACT_PATTERN7, List.of(100, 1000, new BigInteger("12345678987654321")), List.of("100", "1K,", "12345678987654K,")}, - {COMPACT_PATTERN8, List.of(new BigInteger("223565686837667632"), new BigDecimal("12322456774334.89766"), 30000, 3456.78), - List.of("223566T", "12T", "30K", "3K")}, + {COMPACT_PATTERN8, List.of(new BigInteger("223565686837667632"), new BigDecimal("12322456774334.89766"), 30000, 3456.78, + new BigInteger("999999999999"), new BigDecimal("999999999999.0"), 999_999, 999_999_999), + List.of("223566T", "12T", "30K", "3K", "1T", "1T", "1M", "1B")}, {COMPACT_PATTERN9, List.of(new BigInteger("223566000000000000"), new BigDecimal("12345678987654567"), 30000, 3000), List.of("223,566,000,000,000,000", "12,345,678,987,654,567", "30,000", "3,000")}, {COMPACT_PATTERN10, List.of(new BigInteger("100000000000000000"), new BigInteger("10000000000000000000"), new BigDecimal("555555555555555555555.89766"), 30000), @@ -110,7 +111,8 @@ public class TestCompactPatternsValidity { {COMPACT_PATTERN11, List.of(20.99, -20.99, 1000, -1000, 30000, -30000, new BigInteger("12345678987654321"), new BigInteger("-12345678987654321")), List.of("21", "-21", "elfu 1", "elfu -1", "elfu 30", "elfu -30", "milioni 12345678988", "milioni -12345678988")}, {COMPACT_PATTERN12, List.of(0, 500, -500, 30000, -3000, 5000000), List.of("0", "H5H", "H-5H", "30K", "3K-", "H50G")}, - {COMPACT_PATTERN13, List.of(1000, new BigInteger("10000000000000000000")), List.of("Thousand", "BeyondLong")}, + {COMPACT_PATTERN13, List.of(1000, new BigInteger("10000000000000000000"), new BigDecimal("9999999999999999999.9")), + List.of("Thousand", "BeyondLong", "BeyondLong")}, }; } -- GitLab From 69fc273f202352f74a313c37db0198be2be08616 Mon Sep 17 00:00:00 2001 From: "Daniel D. Daugherty" Date: Thu, 17 Feb 2022 20:56:46 +0000 Subject: [PATCH 547/564] 8282075: ProblemList 3 compiler/whitebox tests on macosx-x64 Reviewed-by: mikael, bpb --- test/hotspot/jtreg/ProblemList.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index a09185a4b19..9c9b1b0b3c5 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -67,9 +67,9 @@ compiler/rtm/print/TestPrintPreciseRTMLockingStatistics.java 8183263 generic-x64 compiler/c2/Test8004741.java 8235801 generic-all -compiler/whitebox/ClearMethodStateTest.java 8265360 macosx-aarch64 -compiler/whitebox/EnqueueMethodForCompilationTest.java 8265360 macosx-aarch64 -compiler/whitebox/MakeMethodNotCompilableTest.java 8265360 macosx-aarch64 +compiler/whitebox/ClearMethodStateTest.java 8265360 macosx-generic +compiler/whitebox/EnqueueMethodForCompilationTest.java 8265360 macosx-generic +compiler/whitebox/MakeMethodNotCompilableTest.java 8265360 macosx-generic compiler/codecache/jmx/PoolsIndependenceTest.java 8264632 macosx-generic compiler/codecache/TestStressCodeBuffers.java 8272094 generic-aarch64 -- GitLab From f830cbec909b91ad0f00f46a3496d83ecb5912ed Mon Sep 17 00:00:00 2001 From: Magnus Ihse Bursie Date: Thu, 17 Feb 2022 21:18:15 +0000 Subject: [PATCH 548/564] 8188073: Add Capstone as backend for hsdis Co-authored-by: Magnus Ihse Bursie Co-authored-by: Jorn Vernee Reviewed-by: erikj --- make/Hsdis.gmk | 151 +++++++++++------- make/autoconf/help.m4 | 4 + make/autoconf/jdk-options.m4 | 42 ++++- make/autoconf/spec.gmk.in | 3 +- src/utils/hsdis/README | 102 ------------ src/utils/hsdis/README.md | 133 +++++++++++++++ .../{hsdis.c => binutils/hsdis-binutils.c} | 0 src/utils/hsdis/capstone/hsdis-capstone.c | 97 +++++++++++ src/utils/hsdis/hsdis.h | 20 ++- 9 files changed, 381 insertions(+), 171 deletions(-) delete mode 100644 src/utils/hsdis/README create mode 100644 src/utils/hsdis/README.md rename src/utils/hsdis/{hsdis.c => binutils/hsdis-binutils.c} (100%) create mode 100644 src/utils/hsdis/capstone/hsdis-capstone.c diff --git a/make/Hsdis.gmk b/make/Hsdis.gmk index 02f09b320f0..fa5238c80f6 100644 --- a/make/Hsdis.gmk +++ b/make/Hsdis.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -36,89 +36,111 @@ include JdkNativeCompilation.gmk HSDIS_OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/hsdis +HSDIS_TOOLCHAIN := TOOLCHAIN_DEFAULT +HSDIS_TOOLCHAIN_CFLAGS := $(CFLAGS_JDKLIB) +HSDIS_TOOLCHAIN_LDFLAGS := $(LDFLAGS_JDKLIB) + ifeq ($(call isTargetOs, windows), true) INSTALLED_HSDIS_DIR := $(JDK_OUTPUTDIR)/bin + IMAGE_HSDIS_DIR := $(JDK_IMAGE_DIR)/bin +else + INSTALLED_HSDIS_DIR := $(JDK_OUTPUTDIR)/lib + IMAGE_HSDIS_DIR := $(JDK_IMAGE_DIR)/lib +endif - # On windows, we need to "fake" a completely different toolchain using gcc - # instead of the normal microsoft toolchain. This is quite hacky... +ifeq ($(HSDIS_BACKEND), capstone) + ifeq ($(call isTargetCpuArch, x86), true) + CAPSTONE_ARCH := CS_ARCH_X86 + CAPSTONE_MODE := CS_MODE_$(OPENJDK_TARGET_CPU_BITS) + else ifeq ($(call isTargetCpuArch, aarch64), true) + CAPSTONE_ARCH := CS_ARCH_ARM64 + CAPSTONE_MODE := CS_MODE_ARM + else + $(error No support for Capstone on this platform) + endif - MINGW_BASE := x86_64-w64-mingw32 + HSDIS_CFLAGS += -DCAPSTONE_ARCH=$(CAPSTONE_ARCH) \ + -DCAPSTONE_MODE=$(CAPSTONE_MODE) +endif + +ifeq ($(HSDIS_BACKEND), binutils) + ifeq ($(call isTargetOs, windows), true) + # On windows, we need to "fake" a completely different toolchain using gcc + # instead of the normal microsoft toolchain. This is quite hacky... - MINGW_SYSROOT = $(shell $(MINGW_BASE)-gcc -print-sysroot) - ifeq ($(wildcard $(MINGW_SYSROOT)), ) - # Use fallback path - MINGW_SYSROOT := /usr/$(MINGW_BASE) + MINGW_BASE := x86_64-w64-mingw32 + + MINGW_SYSROOT = $(shell $(MINGW_BASE)-gcc -print-sysroot) ifeq ($(wildcard $(MINGW_SYSROOT)), ) - $(error mingw sysroot not found) + # Use fallback path + MINGW_SYSROOT := /usr/$(MINGW_BASE) + ifeq ($(wildcard $(MINGW_SYSROOT)), ) + $(error mingw sysroot not found) + endif endif - endif - $(eval $(call DefineNativeToolchain, TOOLCHAIN_MINGW, \ - CC := $(MINGW_BASE)-gcc, \ - LD := $(MINGW_BASE)-ld, \ - OBJCOPY := $(MINGW_BASE)-objcopy, \ - RC := $(RC), \ - SYSROOT_CFLAGS := --sysroot=$(MINGW_SYSROOT), \ - SYSROOT_LDFLAGS := --sysroot=$(MINGW_SYSROOT), \ - )) - - MINGW_SYSROOT_LIB_PATH := $(MINGW_SYSROOT)/mingw/lib - ifeq ($(wildcard $(MINGW_SYSROOT_LIB_PATH)), ) - # Try without mingw - MINGW_SYSROOT_LIB_PATH := $(MINGW_SYSROOT)/lib + $(eval $(call DefineNativeToolchain, TOOLCHAIN_MINGW, \ + CC := $(MINGW_BASE)-gcc, \ + LD := $(MINGW_BASE)-ld, \ + OBJCOPY := $(MINGW_BASE)-objcopy, \ + RC := $(RC), \ + SYSROOT_CFLAGS := --sysroot=$(MINGW_SYSROOT), \ + SYSROOT_LDFLAGS := --sysroot=$(MINGW_SYSROOT), \ + )) + + MINGW_SYSROOT_LIB_PATH := $(MINGW_SYSROOT)/mingw/lib ifeq ($(wildcard $(MINGW_SYSROOT_LIB_PATH)), ) - $(error mingw sysroot lib path not found) + # Try without mingw + MINGW_SYSROOT_LIB_PATH := $(MINGW_SYSROOT)/lib + ifeq ($(wildcard $(MINGW_SYSROOT_LIB_PATH)), ) + $(error mingw sysroot lib path not found) + endif endif - endif - MINGW_VERSION = $(shell $(MINGW_BASE)-gcc -v 2>&1 | $(GREP) "gcc version" | $(CUT) -d " " -f 3) - MINGW_GCC_LIB_PATH := /usr/lib/gcc/$(MINGW_BASE)/$(MINGW_VERSION) - ifeq ($(wildcard $(MINGW_GCC_LIB_PATH)), ) - # Try using only major version number - MINGW_VERSION_MAJOR := $(firstword $(subst ., , $(MINGW_VERSION))) - MINGW_GCC_LIB_PATH := /usr/lib/gcc/$(MINGW_BASE)/$(MINGW_VERSION_MAJOR) + MINGW_VERSION = $(shell $(MINGW_BASE)-gcc -v 2>&1 | $(GREP) "gcc version" | $(CUT) -d " " -f 3) + MINGW_GCC_LIB_PATH := /usr/lib/gcc/$(MINGW_BASE)/$(MINGW_VERSION) ifeq ($(wildcard $(MINGW_GCC_LIB_PATH)), ) - $(error mingw gcc lib path not found) + # Try using only major version number + MINGW_VERSION_MAJOR := $(firstword $(subst ., , $(MINGW_VERSION))) + MINGW_GCC_LIB_PATH := /usr/lib/gcc/$(MINGW_BASE)/$(MINGW_VERSION_MAJOR) + ifeq ($(wildcard $(MINGW_GCC_LIB_PATH)), ) + $(error mingw gcc lib path not found) + endif endif - endif - TOOLCHAIN_TYPE := gcc - OPENJDK_TARGET_OS := linux - CC_OUT_OPTION := -o$(SPACE) - LD_OUT_OPTION := -o$(SPACE) - GENDEPS_FLAGS := -MMD -MF - CFLAGS_DEBUG_SYMBOLS := -g - DISABLED_WARNINGS := - DISABLE_WARNING_PREFIX := -Wno- - CFLAGS_WARNINGS_ARE_ERRORS := -Werror - SHARED_LIBRARY_FLAGS := -shared - - HSDIS_TOOLCHAIN := TOOLCHAIN_MINGW - HSDIS_TOOLCHAIN_CFLAGS := - HSDIS_TOOLCHAIN_LDFLAGS := -L$(MINGW_GCC_LIB_PATH) -L$(MINGW_SYSROOT_LIB_PATH) - MINGW_DLLCRT := $(MINGW_SYSROOT_LIB_PATH)/dllcrt2.o - HSDIS_TOOLCHAIN_LIBS := $(MINGW_DLLCRT) -lmingw32 -lgcc -lgcc_eh -lmoldname \ - -lmingwex -lmsvcrt -lpthread -ladvapi32 -lshell32 -luser32 -lkernel32 -else - INSTALLED_HSDIS_DIR := $(JDK_OUTPUTDIR)/lib - - HSDIS_TOOLCHAIN := TOOLCHAIN_DEFAULT - HSDIS_TOOLCHAIN_CFLAGS := $(CFLAGS_JDKLIB) - HSDIS_TOOLCHAIN_LDFLAGS := $(LDFLAGS_JDKLIB) - HSDIS_TOOLCHAIN_LIBS := -ldl + TOOLCHAIN_TYPE := gcc + OPENJDK_TARGET_OS := linux + CC_OUT_OPTION := -o$(SPACE) + LD_OUT_OPTION := -o$(SPACE) + GENDEPS_FLAGS := -MMD -MF + CFLAGS_DEBUG_SYMBOLS := -g + DISABLED_WARNINGS := + DISABLE_WARNING_PREFIX := -Wno- + CFLAGS_WARNINGS_ARE_ERRORS := -Werror + SHARED_LIBRARY_FLAGS := -shared + + HSDIS_TOOLCHAIN := TOOLCHAIN_MINGW + HSDIS_TOOLCHAIN_CFLAGS := + HSDIS_TOOLCHAIN_LDFLAGS := -L$(MINGW_GCC_LIB_PATH) -L$(MINGW_SYSROOT_LIB_PATH) + MINGW_DLLCRT := $(MINGW_SYSROOT_LIB_PATH)/dllcrt2.o + HSDIS_TOOLCHAIN_LIBS := $(MINGW_DLLCRT) -lmingw32 -lgcc -lgcc_eh -lmoldname \ + -lmingwex -lmsvcrt -lpthread -ladvapi32 -lshell32 -luser32 -lkernel32 + else + HSDIS_TOOLCHAIN_LIBS := -ldl + endif endif - $(eval $(call SetupJdkLibrary, BUILD_HSDIS, \ NAME := hsdis, \ - SRC := $(TOPDIR)/src/utils/hsdis, \ + SRC := $(TOPDIR)/src/utils/hsdis/$(HSDIS_BACKEND), \ + EXTRA_HEADER_DIRS := $(TOPDIR)/src/utils/hsdis, \ TOOLCHAIN := $(HSDIS_TOOLCHAIN), \ OUTPUT_DIR := $(HSDIS_OUTPUT_DIR), \ OBJECT_DIR := $(HSDIS_OUTPUT_DIR), \ DISABLED_WARNINGS_gcc := undef format-nonliteral sign-compare, \ DISABLED_WARNINGS_clang := undef format-nonliteral, \ CFLAGS := $(HSDIS_TOOLCHAIN_CFLAGS) $(HSDIS_CFLAGS), \ - LDFLAGS := $(HSDIS_TOOLCHAIN_LDFLAGS) $(SHARED_LIBRARY_FLAGS), \ + LDFLAGS := $(HSDIS_TOOLCHAIN_LDFLAGS) $(HSDIS_LDFLAGS) $(SHARED_LIBRARY_FLAGS), \ LIBS := $(HSDIS_LIBS) $(HSDIS_TOOLCHAIN_LIBS), \ )) @@ -129,13 +151,18 @@ TARGETS += build INSTALLED_HSDIS_NAME := hsdis-$(OPENJDK_TARGET_CPU_LEGACY_LIB)$(SHARED_LIBRARY_SUFFIX) INSTALLED_HSDIS := $(INSTALLED_HSDIS_DIR)/$(INSTALLED_HSDIS_NAME) +INSTALLED_HSDIS_IMAGE := $(IMAGE_HSDIS_DIR)/$(INSTALLED_HSDIS_NAME) $(INSTALLED_HSDIS): $(BUILD_HSDIS_TARGET) - $(call LogWarn, NOTE: The resulting build might not be redistributable. Seek legal advice before distibuting.) + ifeq ($(HSDIS_BACKEND), binutils) + $(call LogWarn, NOTE: The resulting build might not be redistributable. Seek legal advice before distributing.) + endif $(install-file) +$(INSTALLED_HSDIS_IMAGE): $(INSTALLED_HSDIS) + $(install-file) -install: $(INSTALLED_HSDIS) +install: $(INSTALLED_HSDIS_IMAGE) TARGETS += install diff --git a/make/autoconf/help.m4 b/make/autoconf/help.m4 index 09e82e36c94..486e78d4fcf 100644 --- a/make/autoconf/help.m4 +++ b/make/autoconf/help.m4 @@ -117,6 +117,8 @@ apt_help() { PKGHANDLER_COMMAND="sudo apt-get install ccache" ;; dtrace) PKGHANDLER_COMMAND="sudo apt-get install systemtap-sdt-dev" ;; + capstone) + PKGHANDLER_COMMAND="sudo apt-get install libcapstone-dev" ;; esac } @@ -168,6 +170,8 @@ brew_help() { PKGHANDLER_COMMAND="brew install freetype" ;; ccache) PKGHANDLER_COMMAND="brew install ccache" ;; + capstone) + PKGHANDLER_COMMAND="brew install capstone" ;; esac } diff --git a/make/autoconf/jdk-options.m4 b/make/autoconf/jdk-options.m4 index 0a7145c9116..7692407316a 100644 --- a/make/autoconf/jdk-options.m4 +++ b/make/autoconf/jdk-options.m4 @@ -811,7 +811,10 @@ AC_DEFUN([JDKOPT_BUILD_BINUTILS], AC_DEFUN_ONCE([JDKOPT_SETUP_HSDIS], [ AC_ARG_WITH([hsdis], [AS_HELP_STRING([--with-hsdis], - [what hsdis backend to use ('none', 'binutils') @<:@none@:>@])]) + [what hsdis backend to use ('none', 'capstone', 'binutils') @<:@none@:>@])]) + + AC_ARG_WITH(capstone, [AS_HELP_STRING([--with-capstone], + [where to find the Capstone files needed for hsdis/capstone])]) AC_ARG_WITH([binutils], [AS_HELP_STRING([--with-binutils], [where to find the binutils files needed for hsdis/binutils])]) @@ -826,6 +829,41 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_HSDIS], elif test "x$with_hsdis" = xnone || test "x$with_hsdis" = xno || test "x$with_hsdis" = x; then HSDIS_BACKEND=none AC_MSG_RESULT(['none', hsdis will not be built]) + elif test "x$with_hsdis" = xcapstone; then + HSDIS_BACKEND=capstone + AC_MSG_RESULT(['capstone']) + + if test "x$with_capstone" != x; then + AC_MSG_CHECKING([for capstone]) + CAPSTONE="$with_capstone" + AC_MSG_RESULT([$CAPSTONE]) + + HSDIS_CFLAGS="-I${CAPSTONE}/include/capstone" + if test "x$OPENJDK_TARGET_OS" != xwindows; then + HSDIS_LDFLAGS="-L${CAPSTONE}/lib" + HSDIS_LIBS="-lcapstone" + else + HSDIS_LDFLAGS="-nodefaultlib:libcmt.lib" + HSDIS_LIBS="${CAPSTONE}/capstone.lib" + fi + else + if test "x$OPENJDK_TARGET_OS" = xwindows; then + # There is no way to auto-detect capstone on Windowos + AC_MSG_NOTICE([You must specify capstone location using --with-capstone=]) + AC_MSG_ERROR([Cannot continue]) + fi + + PKG_CHECK_MODULES(CAPSTONE, capstone, [CAPSTONE_FOUND=yes], [CAPSTONE_FOUND=no]) + if test "x$CAPSTONE_FOUND" = xyes; then + HSDIS_CFLAGS="$CAPSTONE_CFLAGS" + HSDIS_LDFLAGS="$CAPSTONE_LDFLAGS" + HSDIS_LIBS="$CAPSTONE_LIBS" + else + HELP_MSG_MISSING_DEPENDENCY([capstone]) + AC_MSG_NOTICE([Cannot locate capstone which is needed for hsdis/capstone. Try using --with-capstone=. $HELP_MSG]) + AC_MSG_ERROR([Cannot continue]) + fi + fi elif test "x$with_hsdis" = xbinutils; then HSDIS_BACKEND=binutils AC_MSG_RESULT(['binutils']) @@ -853,6 +891,7 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_HSDIS], test -e $BINUTILS_DIR/opcodes/libopcodes.a && \ test -e $BINUTILS_DIR/libiberty/libiberty.a; then HSDIS_CFLAGS="-I$BINUTILS_DIR/include -I$BINUTILS_DIR/bfd -DLIBARCH_$OPENJDK_TARGET_CPU_LEGACY_LIB" + HSDIS_LDFLAGS="" HSDIS_LIBS="$BINUTILS_DIR/bfd/libbfd.a $BINUTILS_DIR/opcodes/libopcodes.a $BINUTILS_DIR/libiberty/libiberty.a $BINUTILS_DIR/zlib/libz.a" fi fi @@ -895,5 +934,6 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_HSDIS], AC_SUBST(HSDIS_BACKEND) AC_SUBST(HSDIS_CFLAGS) + AC_SUBST(HSDIS_LDFLAGS) AC_SUBST(HSDIS_LIBS) ]) diff --git a/make/autoconf/spec.gmk.in b/make/autoconf/spec.gmk.in index 3dce730970e..d286d5cc2cc 100644 --- a/make/autoconf/spec.gmk.in +++ b/make/autoconf/spec.gmk.in @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2022, 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 @@ -361,6 +361,7 @@ ALLOW_ABSOLUTE_PATHS_IN_OUTPUT := @ALLOW_ABSOLUTE_PATHS_IN_OUTPUT@ HSDIS_BACKEND := @HSDIS_BACKEND@ HSDIS_CFLAGS := @HSDIS_CFLAGS@ +HSDIS_LDFLAGS := @HSDIS_LDFLAGS@ HSDIS_LIBS := @HSDIS_LIBS@ # The boot jdk to use. This is overridden in bootcycle-spec.gmk. Make sure to keep diff --git a/src/utils/hsdis/README b/src/utils/hsdis/README deleted file mode 100644 index 64a8ab61a7c..00000000000 --- a/src/utils/hsdis/README +++ /dev/null @@ -1,102 +0,0 @@ -Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved. -DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - -The Universal Permissive License (UPL), Version 1.0 - -Subject to the condition set forth below, permission is hereby granted to -any person obtaining a copy of this software, associated documentation -and/or data (collectively the "Software"), free of charge and under any -and all copyright rights in the Software, and any and all patent rights -owned or freely licensable by each licensor hereunder covering either (i) -the unmodified Software as contributed to or provided by such licensor, -or (ii) the Larger Works (as defined below), to deal in both - -(a) the Software, and - -(b) any piece of software and/or hardware listed in the lrgrwrks.txt file -if one is included with the Software (each a "Larger Work" to which the -Software is contributed by such licensors), - -without restriction, including without limitation the rights to copy, -create derivative works of, display, perform, and distribute the Software -and make, use, sell, offer for sale, import, export, have made, and have -sold the Software and the Larger Work(s), and to sublicense the foregoing -rights on either these or other terms. - -This license is subject to the following condition: - -The above copyright notice and either this complete permission notice or -at a minimum a reference to the UPL must be included in all copies or -substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -USE OR OTHER DEALINGS IN THE SOFTWARE. - -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. - -________________________________________________________________________ - -'hsdis': A HotSpot plugin for disassembling dynamically generated code. - -The files in this directory are built independently of the HotSpot JVM. - -* Building - -To build this project you need a copy of GNU binutils to build against. It is -known to work with binutils 2.37. Building against versions older than 2.29 is -not supported. Download a copy of the software from -http://directory.fsf.org/project/binutils or one of its mirrors. - -To build this library, you must enable building in configure by "bash configure ---with-hsdis=binutils". - -You must also specify where binutils is located. To facilitate building, you can -point to a place where the (unpacked) binutils sources are located using -"--with-binutils-src=", and configure will build binutils for you. On -repeated runs, you can keep this command line option, since configure will -figure out that the binutils binaries are already present and skip building, or -you can replace it with "--with-binutils=". - -If you have pre-built binutils binaries, you can point to them directly using -"--with-binutils=". - -If you want to build hsdis with binutils provided by system -(e.g. binutils-devel from Fedora, binutils-dev from Ubuntu), you can pass -"--with-binutils=system". "system" is available on Linux only. - -When you have created a proper configuration, you can then build the hsdis -library using "make build-hsdis". - -* Building on Windows - -On Windows, the normal Microsoft Visual Studio toolchain cannot build binutils. -Instead we need to use the mingw compiler. This is available as a cygwin -package. You need to install the "gcc-core" and "mingw64-x86_64-gcc-core" -packages (or "mingw64-i686-gcc-core", if you want the 32-bit version) and -"mingw64-x86_64-glib2.0". - -* Installing - -To build the hsdis library, run "make build-hsdis". This will build the library -in a separate directory, but not make it available to the JDK in the -configuration. To actually install it in the JDK, run "make install-hsdis". - -Note: The resulting build may not be distributable. Please get legal advice if -you intend to distribute the result of your build. - -* Using the library - -The hsdis library will be automatically loaded by Hotspot when you use the -diagnostic option "-XX:+PrintAssembly". Note that since this is a diagnostic -option, you need to unlock these first, so in practice you activate it using -"-XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly". - -More information is available at the wiki -[https://wiki.openjdk.java.net/display/HotSpot/PrintAssembly]. diff --git a/src/utils/hsdis/README.md b/src/utils/hsdis/README.md new file mode 100644 index 00000000000..bc8bdb767b7 --- /dev/null +++ b/src/utils/hsdis/README.md @@ -0,0 +1,133 @@ +``` +Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved. +DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + +The Universal Permissive License (UPL), Version 1.0 + +Subject to the condition set forth below, permission is hereby granted to +any person obtaining a copy of this software, associated documentation +and/or data (collectively the "Software"), free of charge and under any +and all copyright rights in the Software, and any and all patent rights +owned or freely licensable by each licensor hereunder covering either (i) +the unmodified Software as contributed to or provided by such licensor, +or (ii) the Larger Works (as defined below), to deal in both + +(a) the Software, and + +(b) any piece of software and/or hardware listed in the lrgrwrks.txt file +if one is included with the Software (each a "Larger Work" to which the +Software is contributed by such licensors), + +without restriction, including without limitation the rights to copy, +create derivative works of, display, perform, and distribute the Software +and make, use, sell, offer for sale, import, export, have made, and have +sold the Software and the Larger Work(s), and to sublicense the foregoing +rights on either these or other terms. + +This license is subject to the following condition: + +The above copyright notice and either this complete permission notice or +at a minimum a reference to the UPL must be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +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. +``` + +--- + +# hsdis - a HotSpot plugin for disassembling dynamically generated code + +The files in this directory are built independently of the HotSpot JVM. + +hsdis is an interface exposed by Hotspot. There are several backends that +implement this interface, using different disassembly engines. Included in the +JDK is support for building hsdis with Capstone or GNU binutils. The interface +is fairly straightforward and easy to implement using other backends. + +## Building and installing + +To compile hsdis, you need to activate hsdis support, and select the proper +backend to use. This is done with the configure switch `--with-hsdis=`, +where `` is either `capstone` or `binutils`. For details, see the +sections on the respective backends below. + +To build the hsdis library, run `make build-hsdis`. This will build the library +in a separate directory, but not make it available to the JDK in the +configuration. To actually install it in the JDK, run `make install-hsdis`. + +**NOTE:** If you do this using the binutils backend, the resulting build may not +be distributable. Please get legal advice if you intend to distribute the result +of your build. + +## Using the library + +The hsdis library will be automatically loaded by Hotspot when you use the +diagnostic option `-XX:+PrintAssembly`. Note that since this is a diagnostic +option, you need to unlock these first, so in practice you activate it using +`-XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly`. + +More information is available at the [HotSpot +wiki](https://wiki.openjdk.java.net/display/HotSpot/PrintAssembly). + +## Building with Capstone + +To build this project using Capstone you need to have Capstone installed. +Typical ways of installation can be `sudo apt install libcapstone-dev` (on +Debian and derivatives), or `brew install capstone` (on macOS with Homebrew). +For Windows, you need to download the "Core Engine", and unzip it. See the +[Capstone Download +page](https://www.capstone-engine.org/download.html#windows---core-engine-) for +up-to-date download links. + +This has been tested with Capstone v4.0.2, but earlier (and later) versions are +also likely to work. + +To build hsdis using Capstone, you must enable it in configure by `bash +configure --with-hsdis=capstone`. + +On Linux and macOS, the location Capstone can most often be auto-detected. If +this fails, or if you are building on Windows, you need to specify where +Capstone is located using `--with-capstone=`. This path should point to +where you have extracted the Core Engine zip file. + +## Building with binutils + +To build this project using binutils you need a copy of GNU binutils to build +against. It is known to work with binutils 2.37. Building against versions older +than 2.29 is not supported. Download a copy of the software from [FSF binutils +page](http://directory.fsf.org/project/binutils) or one of its mirrors. + +To build this library, you must enable building in configure by `bash configure +--with-hsdis=binutils`. + +You must also specify where binutils is located. To facilitate building, you can +point to a place where the (unpacked) binutils sources are located using +`--with-binutils-src=`, and configure will build binutils for you. On +repeated runs, you can keep this command line option, since configure will +figure out that the binutils binaries are already present and skip building, or +you can replace it with `--with-binutils=`. + +If you have pre-built binutils binaries, you can point to them directly using +`--with-binutils=`. + +If you want to build hsdis with binutils provided by system (e.g. binutils-devel +from Fedora, binutils-dev from Ubuntu), you can pass `--with-binutils=system`. +`system` is available on Linux only. + +### Building with binutils on Windows + +On Windows, the normal Microsoft Visual Studio toolchain cannot build binutils. +Instead we need to use the mingw compiler. This is available as a cygwin +package. You need to install the `gcc-core` and `mingw64-x86_64-gcc-core` +packages (or `mingw64-i686-gcc-core`, if you want the 32-bit version) and +`mingw64-x86_64-glib2.0`. diff --git a/src/utils/hsdis/hsdis.c b/src/utils/hsdis/binutils/hsdis-binutils.c similarity index 100% rename from src/utils/hsdis/hsdis.c rename to src/utils/hsdis/binutils/hsdis-binutils.c diff --git a/src/utils/hsdis/capstone/hsdis-capstone.c b/src/utils/hsdis/capstone/hsdis-capstone.c new file mode 100644 index 00000000000..d71330ee6a7 --- /dev/null +++ b/src/utils/hsdis/capstone/hsdis-capstone.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * The Universal Permissive License (UPL), Version 1.0 + * + * Subject to the condition set forth below, permission is hereby granted to + * any person obtaining a copy of this software, associated documentation + * and/or data (collectively the "Software"), free of charge and under any + * and all copyright rights in the Software, and any and all patent rights + * owned or freely licensable by each licensor hereunder covering either (i) + * the unmodified Software as contributed to or provided by such licensor, + * or (ii) the Larger Works (as defined below), to deal in both + * + * (a) the Software, and + * + * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file + * if one is included with the Software (each a "Larger Work" to which the + * Software is contributed by such licensors), + * + * without restriction, including without limitation the rights to copy, + * create derivative works of, display, perform, and distribute the Software + * and make, use, sell, offer for sale, import, export, have made, and have + * sold the Software and the Larger Work(s), and to sublicense the foregoing + * rights on either these or other terms. + * + * This license is subject to the following condition: + * + * The above copyright notice and either this complete permission notice or + * at a minimum a reference to the UPL must be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * 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. + * + */ + +/* hsdis.c -- dump a range of addresses as native instructions + This implements the plugin protocol required by the + HotSpot PrintAssembly option. +*/ + +#include + +#include + +#include "hsdis.h" + +/* short names for stuff in hsdis.h */ +typedef decode_instructions_event_callback_ftype event_callback_t; +typedef decode_instructions_printf_callback_ftype printf_callback_t; + +#define print(...) (*printf_callback) (printf_stream, __VA_ARGS__) + +#ifdef _WIN32 +__declspec(dllexport) +#endif +void* decode_instructions_virtual(uintptr_t start_va, uintptr_t end_va, + unsigned char* buffer, uintptr_t length, + void* (*event_callback)(void*, const char*, void*), + void* event_stream, + int (*printf_callback)(void*, const char*, ...), + void* printf_stream, + const char* options, + int newline /* bool value for nice new line */) { + csh cs_handle; + + if (cs_open(CAPSTONE_ARCH, CAPSTONE_MODE, &cs_handle) != CS_ERR_OK) { + print("Could not open cs_handle"); + return NULL; + } + + // TODO: Support intel syntax + cs_option(cs_handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_ATT); + + cs_insn *insn; + size_t count = cs_disasm(cs_handle, buffer, length, (uintptr_t) buffer, 0 , &insn); + if (count) { + for (unsigned int j = 0; j < count; j++) { + print(" 0x%" PRIx64 ":\t%s\t\t%s\n", insn[j].address, insn[j].mnemonic, insn[j].op_str); + } + cs_free(insn, count); + } + + cs_close(&cs_handle); + + return NULL; +} diff --git a/src/utils/hsdis/hsdis.h b/src/utils/hsdis/hsdis.h index a6b45a57ba8..7e3b8e397af 100644 --- a/src/utils/hsdis/hsdis.h +++ b/src/utils/hsdis/hsdis.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -72,9 +72,14 @@ #ifndef SHARED_TOOLS_HSDIS_H #define SHARED_TOOLS_HSDIS_H +#ifdef __cplusplus +extern "C" +{ +#endif + extern -#ifdef DLL_EXPORT - DLL_EXPORT +#ifdef _WIN32 +__declspec(dllexport) #endif void* decode_instructions_virtual(uintptr_t start_va, uintptr_t end_va, unsigned char* buffer, uintptr_t length, @@ -87,8 +92,8 @@ void* decode_instructions_virtual(uintptr_t start_va, uintptr_t end_va, /* This is the compatability interface for older versions of hotspot */ extern -#ifdef DLL_ENTRY - DLL_ENTRY +#ifdef _WIN32 +__declspec(dllexport) #endif void* decode_instructions(void* start_pv, void* end_pv, void* (*event_callback)(void*, const char*, void*), @@ -115,4 +120,9 @@ typedef void* (*decode_func_stype) (void* start_pv, void* end_pv, decode_instructions_printf_callback_ftype printf_callback, void* printf_stream, const char* options); + +#ifdef __cplusplus +} +#endif + #endif /* SHARED_TOOLS_HSDIS_H */ -- GitLab From fdce35f3a1c12a64238d0c76c02451a25b0b4abb Mon Sep 17 00:00:00 2001 From: Jie Fu Date: Thu, 17 Feb 2022 22:53:53 +0000 Subject: [PATCH 549/564] 8282025: assert(ctrl != __null) failed: control out is assumed to be unique after JDK-8281732 Reviewed-by: kvn, thartmann, chagedorn --- src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp index f46d9436316..849b40f3d79 100644 --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp @@ -1,5 +1,6 @@ /* * Copyright (c) 2015, 2021, Red Hat, Inc. All rights reserved. + * Copyright (C) 2022 THL A29 Limited, a Tencent company. 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 @@ -706,7 +707,7 @@ Node* ShenandoahBarrierC2Support::no_branches(Node* c, Node* dom, bool allow_one Node* iffproj = NULL; while (c != dom) { Node* next = phase->idom(c); - assert(next->unique_ctrl_out() == c || c->is_Proj() || c->is_Region(), "multiple control flow out but no proj or region?"); + assert(next->unique_ctrl_out_or_null() == c || c->is_Proj() || c->is_Region(), "multiple control flow out but no proj or region?"); if (c->is_Region()) { ResourceMark rm; Unique_Node_List wq; -- GitLab From a22f422b7f18dc134e48c6193bf690004635bf7d Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Fri, 18 Feb 2022 04:56:05 +0000 Subject: [PATCH 550/564] 8037573: Typo in DefaultTreeModel docs: askAllowsChildren instead of asksAllowsChildren Reviewed-by: prr, jdv, azvegint --- .../share/classes/javax/swing/tree/DefaultTreeModel.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java.desktop/share/classes/javax/swing/tree/DefaultTreeModel.java b/src/java.desktop/share/classes/javax/swing/tree/DefaultTreeModel.java index 6d2a692c043..4cdec3f6b38 100644 --- a/src/java.desktop/share/classes/javax/swing/tree/DefaultTreeModel.java +++ b/src/java.desktop/share/classes/javax/swing/tree/DefaultTreeModel.java @@ -204,7 +204,7 @@ public class DefaultTreeModel implements Serializable, TreeModel { /** * Returns whether the specified node is a leaf node. * The way the test is performed depends on the - * askAllowsChildren setting. + * asksAllowsChildren setting. * * @param node the node to check * @return true if the node is a leaf node -- GitLab From c9289583eb6919ced3b4115cf981180f6a957fbf Mon Sep 17 00:00:00 2001 From: Jie Fu Date: Fri, 18 Feb 2022 05:02:19 +0000 Subject: [PATCH 551/564] 8281936: compiler/arguments/TestCodeEntryAlignment.java fails on AVX512 machines Reviewed-by: shade, kvn --- src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp index 6597c91bb42..8bfbe3303da 100644 --- a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp +++ b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp @@ -3002,7 +3002,7 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(address destination, const cha // allocate space for the code ResourceMark rm; - CodeBuffer buffer(name, 1000, 512); + CodeBuffer buffer(name, 1200, 512); MacroAssembler* masm = new MacroAssembler(&buffer); int frame_size_in_words; -- GitLab From 7bcca7692b62a37f70c757694f6acff0295371cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20Casta=C3=B1eda=20Lozano?= Date: Fri, 18 Feb 2022 08:35:52 +0000 Subject: [PATCH 552/564] 8279068: IGV: Update to work with JDK 16 and 17 Reviewed-by: kvn, neliasso, chagedorn --- .../IdealGraphVisualizer/Bytecodes/pom.xml | 6 ++++- .../IdealGraphVisualizer/ControlFlow/pom.xml | 6 ++++- .../IdealGraphVisualizer/Coordinator/pom.xml | 6 ++++- src/utils/IdealGraphVisualizer/Data/pom.xml | 6 ++++- .../IdealGraphVisualizer/Difference/pom.xml | 6 ++++- src/utils/IdealGraphVisualizer/Filter/pom.xml | 8 +++++-- .../IdealGraphVisualizer/FilterWindow/pom.xml | 6 ++++- src/utils/IdealGraphVisualizer/Graal/pom.xml | 6 ++++- src/utils/IdealGraphVisualizer/Graph/pom.xml | 6 ++++- .../HierarchicalLayout/pom.xml | 6 ++++- src/utils/IdealGraphVisualizer/Layout/pom.xml | 6 ++++- .../NetworkConnection/pom.xml | 6 ++++- src/utils/IdealGraphVisualizer/README.md | 2 +- .../SelectionCoordinator/pom.xml | 6 ++++- .../ServerCompiler/pom.xml | 4 ++++ .../IdealGraphVisualizer/Settings/pom.xml | 6 ++++- src/utils/IdealGraphVisualizer/Util/pom.xml | 6 ++++- src/utils/IdealGraphVisualizer/View/pom.xml | 6 ++++- .../IdealGraphVisualizer/application/pom.xml | 5 +++- .../main/resources/idealgraphvisualizer.conf | 24 +++++++++++++++++++ .../IdealGraphVisualizer/branding/pom.xml | 6 ++++- src/utils/IdealGraphVisualizer/pom.xml | 24 ++++++++++++++++++- 22 files changed, 142 insertions(+), 21 deletions(-) create mode 100644 src/utils/IdealGraphVisualizer/application/src/main/resources/idealgraphvisualizer.conf diff --git a/src/utils/IdealGraphVisualizer/Bytecodes/pom.xml b/src/utils/IdealGraphVisualizer/Bytecodes/pom.xml index 188537f81d6..e87ad7fb509 100644 --- a/src/utils/IdealGraphVisualizer/Bytecodes/pom.xml +++ b/src/utils/IdealGraphVisualizer/Bytecodes/pom.xml @@ -1,6 +1,6 @@ diff --git a/src/utils/IdealGraphVisualizer/application/src/main/resources/idealgraphvisualizer.conf b/src/utils/IdealGraphVisualizer/application/src/main/resources/idealgraphvisualizer.conf new file mode 100644 index 00000000000..500ed32f280 --- /dev/null +++ b/src/utils/IdealGraphVisualizer/application/src/main/resources/idealgraphvisualizer.conf @@ -0,0 +1,24 @@ +# Copyright (c) 2022, 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. + +# Open/export modules still accessed by the NetBeans Platform. +# All options must be passed in a single line for multi-platform support. +default_options="-J--add-opens=java.base/java.net=ALL-UNNAMED -J--add-opens=java.desktop/javax.swing.plaf.synth=ALL-UNNAMED -J--add-opens=java.desktop/com.sun.java.swing.plaf.gtk=ALL-UNNAMED -J--add-opens=java.desktop/javax.swing=ALL-UNNAMED -J--add-exports=java.desktop/sun.awt=ALL-UNNAMED" \ No newline at end of file diff --git a/src/utils/IdealGraphVisualizer/branding/pom.xml b/src/utils/IdealGraphVisualizer/branding/pom.xml index 67821ff4621..ed33298d3e4 100644 --- a/src/utils/IdealGraphVisualizer/branding/pom.xml +++ b/src/utils/IdealGraphVisualizer/branding/pom.xml @@ -1,6 +1,6 @@