From 960161db82191b679b92094c8bd661e868dfb424 Mon Sep 17 00:00:00 2001 From: Yasumasa Suenaga Date: Thu, 26 Mar 2026 07:22:04 +0000 Subject: [PATCH 001/116] 8380764: Vector classes should have @ValueBased Reviewed-by: liach --- .../share/classes/jdk/incubator/vector/ByteVector128.java | 6 ++++-- .../share/classes/jdk/incubator/vector/ByteVector256.java | 6 ++++-- .../share/classes/jdk/incubator/vector/ByteVector512.java | 6 ++++-- .../share/classes/jdk/incubator/vector/ByteVector64.java | 6 ++++-- .../share/classes/jdk/incubator/vector/ByteVectorMax.java | 6 ++++-- .../share/classes/jdk/incubator/vector/DoubleVector128.java | 6 ++++-- .../share/classes/jdk/incubator/vector/DoubleVector256.java | 6 ++++-- .../share/classes/jdk/incubator/vector/DoubleVector512.java | 6 ++++-- .../share/classes/jdk/incubator/vector/DoubleVector64.java | 6 ++++-- .../share/classes/jdk/incubator/vector/DoubleVectorMax.java | 6 ++++-- .../share/classes/jdk/incubator/vector/FloatVector128.java | 6 ++++-- .../share/classes/jdk/incubator/vector/FloatVector256.java | 6 ++++-- .../share/classes/jdk/incubator/vector/FloatVector512.java | 6 ++++-- .../share/classes/jdk/incubator/vector/FloatVector64.java | 6 ++++-- .../share/classes/jdk/incubator/vector/FloatVectorMax.java | 6 ++++-- .../share/classes/jdk/incubator/vector/IntVector128.java | 6 ++++-- .../share/classes/jdk/incubator/vector/IntVector256.java | 6 ++++-- .../share/classes/jdk/incubator/vector/IntVector512.java | 6 ++++-- .../share/classes/jdk/incubator/vector/IntVector64.java | 6 ++++-- .../share/classes/jdk/incubator/vector/IntVectorMax.java | 6 ++++-- .../share/classes/jdk/incubator/vector/LongVector128.java | 6 ++++-- .../share/classes/jdk/incubator/vector/LongVector256.java | 6 ++++-- .../share/classes/jdk/incubator/vector/LongVector512.java | 6 ++++-- .../share/classes/jdk/incubator/vector/LongVector64.java | 6 ++++-- .../share/classes/jdk/incubator/vector/LongVectorMax.java | 6 ++++-- .../share/classes/jdk/incubator/vector/ShortVector128.java | 6 ++++-- .../share/classes/jdk/incubator/vector/ShortVector256.java | 6 ++++-- .../share/classes/jdk/incubator/vector/ShortVector512.java | 6 ++++-- .../share/classes/jdk/incubator/vector/ShortVector64.java | 6 ++++-- .../share/classes/jdk/incubator/vector/ShortVectorMax.java | 6 ++++-- .../classes/jdk/incubator/vector/X-VectorBits.java.template | 6 ++++-- 31 files changed, 124 insertions(+), 62 deletions(-) diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector128.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector128.java index c38e8d0f8a0..360afedbbbb 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector128.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector128.java @@ -31,6 +31,7 @@ import java.util.Objects; import java.util.function.IntUnaryOperator; +import jdk.internal.ValueBased; import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; @@ -41,6 +42,7 @@ // -- This file was mechanically generated: Do not edit! -- // @SuppressWarnings("cast") // warning: redundant cast +@ValueBased final class ByteVector128 extends ByteVector { static final ByteSpecies VSPECIES = (ByteSpecies) ByteVector.SPECIES_128; @@ -598,7 +600,7 @@ public ByteVector128 withLaneHelper(int i, byte e) { } // Mask - + @ValueBased static final class ByteMask128 extends AbstractMask { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM @@ -831,7 +833,7 @@ static ByteMask128 maskAll(boolean bit) { } // Shuffle - + @ValueBased static final class ByteShuffle128 extends AbstractShuffle { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector256.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector256.java index 0eec0c56e37..ca0c59dd49e 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector256.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector256.java @@ -31,6 +31,7 @@ import java.util.Objects; import java.util.function.IntUnaryOperator; +import jdk.internal.ValueBased; import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; @@ -41,6 +42,7 @@ // -- This file was mechanically generated: Do not edit! -- // @SuppressWarnings("cast") // warning: redundant cast +@ValueBased final class ByteVector256 extends ByteVector { static final ByteSpecies VSPECIES = (ByteSpecies) ByteVector.SPECIES_256; @@ -630,7 +632,7 @@ public ByteVector256 withLaneHelper(int i, byte e) { } // Mask - + @ValueBased static final class ByteMask256 extends AbstractMask { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM @@ -863,7 +865,7 @@ static ByteMask256 maskAll(boolean bit) { } // Shuffle - + @ValueBased static final class ByteShuffle256 extends AbstractShuffle { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector512.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector512.java index 138319b60d4..1a0c69153bc 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector512.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector512.java @@ -31,6 +31,7 @@ import java.util.Objects; import java.util.function.IntUnaryOperator; +import jdk.internal.ValueBased; import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; @@ -41,6 +42,7 @@ // -- This file was mechanically generated: Do not edit! -- // @SuppressWarnings("cast") // warning: redundant cast +@ValueBased final class ByteVector512 extends ByteVector { static final ByteSpecies VSPECIES = (ByteSpecies) ByteVector.SPECIES_512; @@ -694,7 +696,7 @@ public ByteVector512 withLaneHelper(int i, byte e) { } // Mask - + @ValueBased static final class ByteMask512 extends AbstractMask { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM @@ -927,7 +929,7 @@ static ByteMask512 maskAll(boolean bit) { } // Shuffle - + @ValueBased static final class ByteShuffle512 extends AbstractShuffle { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector64.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector64.java index d7c7c78534b..50561eca0f8 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector64.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector64.java @@ -31,6 +31,7 @@ import java.util.Objects; import java.util.function.IntUnaryOperator; +import jdk.internal.ValueBased; import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; @@ -41,6 +42,7 @@ // -- This file was mechanically generated: Do not edit! -- // @SuppressWarnings("cast") // warning: redundant cast +@ValueBased final class ByteVector64 extends ByteVector { static final ByteSpecies VSPECIES = (ByteSpecies) ByteVector.SPECIES_64; @@ -582,7 +584,7 @@ public ByteVector64 withLaneHelper(int i, byte e) { } // Mask - + @ValueBased static final class ByteMask64 extends AbstractMask { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM @@ -815,7 +817,7 @@ static ByteMask64 maskAll(boolean bit) { } // Shuffle - + @ValueBased static final class ByteShuffle64 extends AbstractShuffle { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVectorMax.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVectorMax.java index 636aa83893a..ee931bbc077 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVectorMax.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVectorMax.java @@ -31,6 +31,7 @@ import java.util.Objects; import java.util.function.IntUnaryOperator; +import jdk.internal.ValueBased; import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; @@ -41,6 +42,7 @@ // -- This file was mechanically generated: Do not edit! -- // @SuppressWarnings("cast") // warning: redundant cast +@ValueBased final class ByteVectorMax extends ByteVector { static final ByteSpecies VSPECIES = (ByteSpecies) ByteVector.SPECIES_MAX; @@ -568,7 +570,7 @@ public ByteVectorMax withLaneHelper(int i, byte e) { } // Mask - + @ValueBased static final class ByteMaskMax extends AbstractMask { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM @@ -801,7 +803,7 @@ static ByteMaskMax maskAll(boolean bit) { } // Shuffle - + @ValueBased static final class ByteShuffleMax extends AbstractShuffle { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector128.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector128.java index 1140d377e9b..43c7e3f0c46 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector128.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector128.java @@ -31,6 +31,7 @@ import java.util.Objects; import java.util.function.IntUnaryOperator; +import jdk.internal.ValueBased; import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; @@ -41,6 +42,7 @@ // -- This file was mechanically generated: Do not edit! -- // @SuppressWarnings("cast") // warning: redundant cast +@ValueBased final class DoubleVector128 extends DoubleVector { static final DoubleSpecies VSPECIES = (DoubleSpecies) DoubleVector.SPECIES_128; @@ -559,7 +561,7 @@ public DoubleVector128 withLaneHelper(int i, double e) { } // Mask - + @ValueBased static final class DoubleMask128 extends AbstractMask { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM @@ -792,7 +794,7 @@ static DoubleMask128 maskAll(boolean bit) { } // Shuffle - + @ValueBased static final class DoubleShuffle128 extends AbstractShuffle { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector256.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector256.java index 59b7913cfcb..5f176854dbd 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector256.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector256.java @@ -31,6 +31,7 @@ import java.util.Objects; import java.util.function.IntUnaryOperator; +import jdk.internal.ValueBased; import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; @@ -41,6 +42,7 @@ // -- This file was mechanically generated: Do not edit! -- // @SuppressWarnings("cast") // warning: redundant cast +@ValueBased final class DoubleVector256 extends DoubleVector { static final DoubleSpecies VSPECIES = (DoubleSpecies) DoubleVector.SPECIES_256; @@ -563,7 +565,7 @@ public DoubleVector256 withLaneHelper(int i, double e) { } // Mask - + @ValueBased static final class DoubleMask256 extends AbstractMask { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM @@ -796,7 +798,7 @@ static DoubleMask256 maskAll(boolean bit) { } // Shuffle - + @ValueBased static final class DoubleShuffle256 extends AbstractShuffle { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector512.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector512.java index 8ed21953394..0696f48163d 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector512.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector512.java @@ -31,6 +31,7 @@ import java.util.Objects; import java.util.function.IntUnaryOperator; +import jdk.internal.ValueBased; import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; @@ -41,6 +42,7 @@ // -- This file was mechanically generated: Do not edit! -- // @SuppressWarnings("cast") // warning: redundant cast +@ValueBased final class DoubleVector512 extends DoubleVector { static final DoubleSpecies VSPECIES = (DoubleSpecies) DoubleVector.SPECIES_512; @@ -571,7 +573,7 @@ public DoubleVector512 withLaneHelper(int i, double e) { } // Mask - + @ValueBased static final class DoubleMask512 extends AbstractMask { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM @@ -804,7 +806,7 @@ static DoubleMask512 maskAll(boolean bit) { } // Shuffle - + @ValueBased static final class DoubleShuffle512 extends AbstractShuffle { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector64.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector64.java index 7e1a8cf768d..5b74c2c4619 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector64.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector64.java @@ -31,6 +31,7 @@ import java.util.Objects; import java.util.function.IntUnaryOperator; +import jdk.internal.ValueBased; import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; @@ -41,6 +42,7 @@ // -- This file was mechanically generated: Do not edit! -- // @SuppressWarnings("cast") // warning: redundant cast +@ValueBased final class DoubleVector64 extends DoubleVector { static final DoubleSpecies VSPECIES = (DoubleSpecies) DoubleVector.SPECIES_64; @@ -557,7 +559,7 @@ public DoubleVector64 withLaneHelper(int i, double e) { } // Mask - + @ValueBased static final class DoubleMask64 extends AbstractMask { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM @@ -790,7 +792,7 @@ static DoubleMask64 maskAll(boolean bit) { } // Shuffle - + @ValueBased static final class DoubleShuffle64 extends AbstractShuffle { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVectorMax.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVectorMax.java index 46c090e066e..07d227d641a 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVectorMax.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVectorMax.java @@ -31,6 +31,7 @@ import java.util.Objects; import java.util.function.IntUnaryOperator; +import jdk.internal.ValueBased; import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; @@ -41,6 +42,7 @@ // -- This file was mechanically generated: Do not edit! -- // @SuppressWarnings("cast") // warning: redundant cast +@ValueBased final class DoubleVectorMax extends DoubleVector { static final DoubleSpecies VSPECIES = (DoubleSpecies) DoubleVector.SPECIES_MAX; @@ -556,7 +558,7 @@ public DoubleVectorMax withLaneHelper(int i, double e) { } // Mask - + @ValueBased static final class DoubleMaskMax extends AbstractMask { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM @@ -789,7 +791,7 @@ static DoubleMaskMax maskAll(boolean bit) { } // Shuffle - + @ValueBased static final class DoubleShuffleMax extends AbstractShuffle { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector128.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector128.java index 1e3867e84fc..17c1fdba4fc 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector128.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector128.java @@ -31,6 +31,7 @@ import java.util.Objects; import java.util.function.IntUnaryOperator; +import jdk.internal.ValueBased; import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; @@ -41,6 +42,7 @@ // -- This file was mechanically generated: Do not edit! -- // @SuppressWarnings("cast") // warning: redundant cast +@ValueBased final class FloatVector128 extends FloatVector { static final FloatSpecies VSPECIES = (FloatSpecies) FloatVector.SPECIES_128; @@ -563,7 +565,7 @@ public FloatVector128 withLaneHelper(int i, float e) { } // Mask - + @ValueBased static final class FloatMask128 extends AbstractMask { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM @@ -796,7 +798,7 @@ static FloatMask128 maskAll(boolean bit) { } // Shuffle - + @ValueBased static final class FloatShuffle128 extends AbstractShuffle { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector256.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector256.java index f267025972d..7badb71415e 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector256.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector256.java @@ -31,6 +31,7 @@ import java.util.Objects; import java.util.function.IntUnaryOperator; +import jdk.internal.ValueBased; import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; @@ -41,6 +42,7 @@ // -- This file was mechanically generated: Do not edit! -- // @SuppressWarnings("cast") // warning: redundant cast +@ValueBased final class FloatVector256 extends FloatVector { static final FloatSpecies VSPECIES = (FloatSpecies) FloatVector.SPECIES_256; @@ -571,7 +573,7 @@ public FloatVector256 withLaneHelper(int i, float e) { } // Mask - + @ValueBased static final class FloatMask256 extends AbstractMask { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM @@ -804,7 +806,7 @@ static FloatMask256 maskAll(boolean bit) { } // Shuffle - + @ValueBased static final class FloatShuffle256 extends AbstractShuffle { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector512.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector512.java index 439e26f0d89..7c0786b7fcd 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector512.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector512.java @@ -31,6 +31,7 @@ import java.util.Objects; import java.util.function.IntUnaryOperator; +import jdk.internal.ValueBased; import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; @@ -41,6 +42,7 @@ // -- This file was mechanically generated: Do not edit! -- // @SuppressWarnings("cast") // warning: redundant cast +@ValueBased final class FloatVector512 extends FloatVector { static final FloatSpecies VSPECIES = (FloatSpecies) FloatVector.SPECIES_512; @@ -587,7 +589,7 @@ public FloatVector512 withLaneHelper(int i, float e) { } // Mask - + @ValueBased static final class FloatMask512 extends AbstractMask { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM @@ -820,7 +822,7 @@ static FloatMask512 maskAll(boolean bit) { } // Shuffle - + @ValueBased static final class FloatShuffle512 extends AbstractShuffle { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector64.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector64.java index 9e81a52d27b..fc4877e5ae8 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector64.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector64.java @@ -31,6 +31,7 @@ import java.util.Objects; import java.util.function.IntUnaryOperator; +import jdk.internal.ValueBased; import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; @@ -41,6 +42,7 @@ // -- This file was mechanically generated: Do not edit! -- // @SuppressWarnings("cast") // warning: redundant cast +@ValueBased final class FloatVector64 extends FloatVector { static final FloatSpecies VSPECIES = (FloatSpecies) FloatVector.SPECIES_64; @@ -559,7 +561,7 @@ public FloatVector64 withLaneHelper(int i, float e) { } // Mask - + @ValueBased static final class FloatMask64 extends AbstractMask { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM @@ -792,7 +794,7 @@ static FloatMask64 maskAll(boolean bit) { } // Shuffle - + @ValueBased static final class FloatShuffle64 extends AbstractShuffle { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVectorMax.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVectorMax.java index 4813f153544..5cfafecdb58 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVectorMax.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVectorMax.java @@ -31,6 +31,7 @@ import java.util.Objects; import java.util.function.IntUnaryOperator; +import jdk.internal.ValueBased; import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; @@ -41,6 +42,7 @@ // -- This file was mechanically generated: Do not edit! -- // @SuppressWarnings("cast") // warning: redundant cast +@ValueBased final class FloatVectorMax extends FloatVector { static final FloatSpecies VSPECIES = (FloatSpecies) FloatVector.SPECIES_MAX; @@ -556,7 +558,7 @@ public FloatVectorMax withLaneHelper(int i, float e) { } // Mask - + @ValueBased static final class FloatMaskMax extends AbstractMask { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM @@ -789,7 +791,7 @@ static FloatMaskMax maskAll(boolean bit) { } // Shuffle - + @ValueBased static final class FloatShuffleMax extends AbstractShuffle { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector128.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector128.java index cc8f31a4bc2..04b10386127 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector128.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector128.java @@ -31,6 +31,7 @@ import java.util.Objects; import java.util.function.IntUnaryOperator; +import jdk.internal.ValueBased; import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; @@ -41,6 +42,7 @@ // -- This file was mechanically generated: Do not edit! -- // @SuppressWarnings("cast") // warning: redundant cast +@ValueBased final class IntVector128 extends IntVector { static final IntSpecies VSPECIES = (IntSpecies) IntVector.SPECIES_128; @@ -574,7 +576,7 @@ public IntVector128 withLaneHelper(int i, int e) { } // Mask - + @ValueBased static final class IntMask128 extends AbstractMask { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM @@ -807,7 +809,7 @@ static IntMask128 maskAll(boolean bit) { } // Shuffle - + @ValueBased static final class IntShuffle128 extends AbstractShuffle { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector256.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector256.java index 0630cd958f2..20d9df1cd60 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector256.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector256.java @@ -31,6 +31,7 @@ import java.util.Objects; import java.util.function.IntUnaryOperator; +import jdk.internal.ValueBased; import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; @@ -41,6 +42,7 @@ // -- This file was mechanically generated: Do not edit! -- // @SuppressWarnings("cast") // warning: redundant cast +@ValueBased final class IntVector256 extends IntVector { static final IntSpecies VSPECIES = (IntSpecies) IntVector.SPECIES_256; @@ -582,7 +584,7 @@ public IntVector256 withLaneHelper(int i, int e) { } // Mask - + @ValueBased static final class IntMask256 extends AbstractMask { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM @@ -815,7 +817,7 @@ static IntMask256 maskAll(boolean bit) { } // Shuffle - + @ValueBased static final class IntShuffle256 extends AbstractShuffle { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector512.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector512.java index 92eb5a0f2d2..4f3a16e2777 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector512.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector512.java @@ -31,6 +31,7 @@ import java.util.Objects; import java.util.function.IntUnaryOperator; +import jdk.internal.ValueBased; import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; @@ -41,6 +42,7 @@ // -- This file was mechanically generated: Do not edit! -- // @SuppressWarnings("cast") // warning: redundant cast +@ValueBased final class IntVector512 extends IntVector { static final IntSpecies VSPECIES = (IntSpecies) IntVector.SPECIES_512; @@ -598,7 +600,7 @@ public IntVector512 withLaneHelper(int i, int e) { } // Mask - + @ValueBased static final class IntMask512 extends AbstractMask { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM @@ -831,7 +833,7 @@ static IntMask512 maskAll(boolean bit) { } // Shuffle - + @ValueBased static final class IntShuffle512 extends AbstractShuffle { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector64.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector64.java index c3f92285034..dd51669943b 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector64.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector64.java @@ -31,6 +31,7 @@ import java.util.Objects; import java.util.function.IntUnaryOperator; +import jdk.internal.ValueBased; import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; @@ -41,6 +42,7 @@ // -- This file was mechanically generated: Do not edit! -- // @SuppressWarnings("cast") // warning: redundant cast +@ValueBased final class IntVector64 extends IntVector { static final IntSpecies VSPECIES = (IntSpecies) IntVector.SPECIES_64; @@ -570,7 +572,7 @@ public IntVector64 withLaneHelper(int i, int e) { } // Mask - + @ValueBased static final class IntMask64 extends AbstractMask { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM @@ -803,7 +805,7 @@ static IntMask64 maskAll(boolean bit) { } // Shuffle - + @ValueBased static final class IntShuffle64 extends AbstractShuffle { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVectorMax.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVectorMax.java index 8d3c251536c..0b785b01aec 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVectorMax.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVectorMax.java @@ -31,6 +31,7 @@ import java.util.Objects; import java.util.function.IntUnaryOperator; +import jdk.internal.ValueBased; import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; @@ -41,6 +42,7 @@ // -- This file was mechanically generated: Do not edit! -- // @SuppressWarnings("cast") // warning: redundant cast +@ValueBased final class IntVectorMax extends IntVector { static final IntSpecies VSPECIES = (IntSpecies) IntVector.SPECIES_MAX; @@ -568,7 +570,7 @@ public IntVectorMax withLaneHelper(int i, int e) { } // Mask - + @ValueBased static final class IntMaskMax extends AbstractMask { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM @@ -812,7 +814,7 @@ static boolean[] maskLowerHalf() { } // Shuffle - + @ValueBased static final class IntShuffleMax extends AbstractShuffle { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector128.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector128.java index f8dad12ff89..594c82ca1fc 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector128.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector128.java @@ -31,6 +31,7 @@ import java.util.Objects; import java.util.function.IntUnaryOperator; +import jdk.internal.ValueBased; import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; @@ -41,6 +42,7 @@ // -- This file was mechanically generated: Do not edit! -- // @SuppressWarnings("cast") // warning: redundant cast +@ValueBased final class LongVector128 extends LongVector { static final LongSpecies VSPECIES = (LongSpecies) LongVector.SPECIES_128; @@ -560,7 +562,7 @@ public LongVector128 withLaneHelper(int i, long e) { } // Mask - + @ValueBased static final class LongMask128 extends AbstractMask { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM @@ -793,7 +795,7 @@ static LongMask128 maskAll(boolean bit) { } // Shuffle - + @ValueBased static final class LongShuffle128 extends AbstractShuffle { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector256.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector256.java index 144e2c1c64d..c3d1ff4c276 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector256.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector256.java @@ -31,6 +31,7 @@ import java.util.Objects; import java.util.function.IntUnaryOperator; +import jdk.internal.ValueBased; import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; @@ -41,6 +42,7 @@ // -- This file was mechanically generated: Do not edit! -- // @SuppressWarnings("cast") // warning: redundant cast +@ValueBased final class LongVector256 extends LongVector { static final LongSpecies VSPECIES = (LongSpecies) LongVector.SPECIES_256; @@ -564,7 +566,7 @@ public LongVector256 withLaneHelper(int i, long e) { } // Mask - + @ValueBased static final class LongMask256 extends AbstractMask { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM @@ -797,7 +799,7 @@ static LongMask256 maskAll(boolean bit) { } // Shuffle - + @ValueBased static final class LongShuffle256 extends AbstractShuffle { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector512.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector512.java index b49d0c7c147..b8c95967a99 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector512.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector512.java @@ -31,6 +31,7 @@ import java.util.Objects; import java.util.function.IntUnaryOperator; +import jdk.internal.ValueBased; import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; @@ -41,6 +42,7 @@ // -- This file was mechanically generated: Do not edit! -- // @SuppressWarnings("cast") // warning: redundant cast +@ValueBased final class LongVector512 extends LongVector { static final LongSpecies VSPECIES = (LongSpecies) LongVector.SPECIES_512; @@ -572,7 +574,7 @@ public LongVector512 withLaneHelper(int i, long e) { } // Mask - + @ValueBased static final class LongMask512 extends AbstractMask { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM @@ -805,7 +807,7 @@ static LongMask512 maskAll(boolean bit) { } // Shuffle - + @ValueBased static final class LongShuffle512 extends AbstractShuffle { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector64.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector64.java index 5e8451695bc..3c9b525f6d0 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector64.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector64.java @@ -31,6 +31,7 @@ import java.util.Objects; import java.util.function.IntUnaryOperator; +import jdk.internal.ValueBased; import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; @@ -41,6 +42,7 @@ // -- This file was mechanically generated: Do not edit! -- // @SuppressWarnings("cast") // warning: redundant cast +@ValueBased final class LongVector64 extends LongVector { static final LongSpecies VSPECIES = (LongSpecies) LongVector.SPECIES_64; @@ -558,7 +560,7 @@ public LongVector64 withLaneHelper(int i, long e) { } // Mask - + @ValueBased static final class LongMask64 extends AbstractMask { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM @@ -791,7 +793,7 @@ static LongMask64 maskAll(boolean bit) { } // Shuffle - + @ValueBased static final class LongShuffle64 extends AbstractShuffle { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVectorMax.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVectorMax.java index 3469da8f2f4..4752959f884 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVectorMax.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVectorMax.java @@ -31,6 +31,7 @@ import java.util.Objects; import java.util.function.IntUnaryOperator; +import jdk.internal.ValueBased; import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; @@ -41,6 +42,7 @@ // -- This file was mechanically generated: Do not edit! -- // @SuppressWarnings("cast") // warning: redundant cast +@ValueBased final class LongVectorMax extends LongVector { static final LongSpecies VSPECIES = (LongSpecies) LongVector.SPECIES_MAX; @@ -558,7 +560,7 @@ public LongVectorMax withLaneHelper(int i, long e) { } // Mask - + @ValueBased static final class LongMaskMax extends AbstractMask { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM @@ -791,7 +793,7 @@ static LongMaskMax maskAll(boolean bit) { } // Shuffle - + @ValueBased static final class LongShuffleMax extends AbstractShuffle { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector128.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector128.java index e989cdbdbea..89ec97c6be0 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector128.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector128.java @@ -31,6 +31,7 @@ import java.util.Objects; import java.util.function.IntUnaryOperator; +import jdk.internal.ValueBased; import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; @@ -41,6 +42,7 @@ // -- This file was mechanically generated: Do not edit! -- // @SuppressWarnings("cast") // warning: redundant cast +@ValueBased final class ShortVector128 extends ShortVector { static final ShortSpecies VSPECIES = (ShortSpecies) ShortVector.SPECIES_128; @@ -582,7 +584,7 @@ public ShortVector128 withLaneHelper(int i, short e) { } // Mask - + @ValueBased static final class ShortMask128 extends AbstractMask { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM @@ -815,7 +817,7 @@ static ShortMask128 maskAll(boolean bit) { } // Shuffle - + @ValueBased static final class ShortShuffle128 extends AbstractShuffle { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector256.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector256.java index c74188e22f5..0f5751c27d8 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector256.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector256.java @@ -31,6 +31,7 @@ import java.util.Objects; import java.util.function.IntUnaryOperator; +import jdk.internal.ValueBased; import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; @@ -41,6 +42,7 @@ // -- This file was mechanically generated: Do not edit! -- // @SuppressWarnings("cast") // warning: redundant cast +@ValueBased final class ShortVector256 extends ShortVector { static final ShortSpecies VSPECIES = (ShortSpecies) ShortVector.SPECIES_256; @@ -598,7 +600,7 @@ public ShortVector256 withLaneHelper(int i, short e) { } // Mask - + @ValueBased static final class ShortMask256 extends AbstractMask { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM @@ -831,7 +833,7 @@ static ShortMask256 maskAll(boolean bit) { } // Shuffle - + @ValueBased static final class ShortShuffle256 extends AbstractShuffle { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector512.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector512.java index 46b5d652200..3d38dfd88fd 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector512.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector512.java @@ -31,6 +31,7 @@ import java.util.Objects; import java.util.function.IntUnaryOperator; +import jdk.internal.ValueBased; import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; @@ -41,6 +42,7 @@ // -- This file was mechanically generated: Do not edit! -- // @SuppressWarnings("cast") // warning: redundant cast +@ValueBased final class ShortVector512 extends ShortVector { static final ShortSpecies VSPECIES = (ShortSpecies) ShortVector.SPECIES_512; @@ -630,7 +632,7 @@ public ShortVector512 withLaneHelper(int i, short e) { } // Mask - + @ValueBased static final class ShortMask512 extends AbstractMask { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM @@ -863,7 +865,7 @@ static ShortMask512 maskAll(boolean bit) { } // Shuffle - + @ValueBased static final class ShortShuffle512 extends AbstractShuffle { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector64.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector64.java index 66ff3efe522..b319d98f784 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector64.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector64.java @@ -31,6 +31,7 @@ import java.util.Objects; import java.util.function.IntUnaryOperator; +import jdk.internal.ValueBased; import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; @@ -41,6 +42,7 @@ // -- This file was mechanically generated: Do not edit! -- // @SuppressWarnings("cast") // warning: redundant cast +@ValueBased final class ShortVector64 extends ShortVector { static final ShortSpecies VSPECIES = (ShortSpecies) ShortVector.SPECIES_64; @@ -574,7 +576,7 @@ public ShortVector64 withLaneHelper(int i, short e) { } // Mask - + @ValueBased static final class ShortMask64 extends AbstractMask { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM @@ -807,7 +809,7 @@ static ShortMask64 maskAll(boolean bit) { } // Shuffle - + @ValueBased static final class ShortShuffle64 extends AbstractShuffle { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVectorMax.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVectorMax.java index b9a9b85126b..69b298857c9 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVectorMax.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVectorMax.java @@ -31,6 +31,7 @@ import java.util.Objects; import java.util.function.IntUnaryOperator; +import jdk.internal.ValueBased; import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; @@ -41,6 +42,7 @@ // -- This file was mechanically generated: Do not edit! -- // @SuppressWarnings("cast") // warning: redundant cast +@ValueBased final class ShortVectorMax extends ShortVector { static final ShortSpecies VSPECIES = (ShortSpecies) ShortVector.SPECIES_MAX; @@ -568,7 +570,7 @@ public ShortVectorMax withLaneHelper(int i, short e) { } // Mask - + @ValueBased static final class ShortMaskMax extends AbstractMask { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM @@ -801,7 +803,7 @@ static ShortMaskMax maskAll(boolean bit) { } // Shuffle - + @ValueBased static final class ShortShuffleMax extends AbstractShuffle { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-VectorBits.java.template b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-VectorBits.java.template index bbf02f9c6cd..35041a0b70f 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-VectorBits.java.template +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-VectorBits.java.template @@ -31,6 +31,7 @@ import java.util.Arrays; import java.util.Objects; import java.util.function.IntUnaryOperator; +import jdk.internal.ValueBased; import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; @@ -41,6 +42,7 @@ import static jdk.incubator.vector.VectorOperators.*; #warn This file is preprocessed before being compiled @SuppressWarnings("cast") // warning: redundant cast +@ValueBased final class $vectortype$ extends $abstractvectortype$ { static final $Type$Species VSPECIES = ($Type$Species) $Type$Vector.SPECIES_$BITS$; @@ -855,7 +857,7 @@ final class $vectortype$ extends $abstractvectortype$ { #end[FP] // Mask - + @ValueBased static final class $masktype$ extends AbstractMask<$Boxtype$> { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM @@ -1103,7 +1105,7 @@ final class $vectortype$ extends $abstractvectortype$ { } // Shuffle - + @ValueBased static final class $shuffletype$ extends AbstractShuffle<$Boxtype$> { static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM From c64f7357a536a7577432964ea8ce723c5373a184 Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Thu, 26 Mar 2026 08:19:31 +0000 Subject: [PATCH 002/116] 8379516: Adjust JVM debug helper exports Reviewed-by: kbarrett, lucy, clanger --- src/hotspot/share/utilities/debug.cpp | 104 +++++++++++++++++--------- 1 file changed, 69 insertions(+), 35 deletions(-) diff --git a/src/hotspot/share/utilities/debug.cpp b/src/hotspot/share/utilities/debug.cpp index e8533e29460..23e8281f000 100644 --- a/src/hotspot/share/utilities/debug.cpp +++ b/src/hotspot/share/utilities/debug.cpp @@ -342,20 +342,20 @@ class Command : public StackObj { int Command::level = 0; -extern "C" DEBUGEXPORT void blob(CodeBlob* cb) { +extern "C" NOINLINE void blob(CodeBlob* cb) { Command c("blob"); cb->print(); } -extern "C" DEBUGEXPORT void dump_vtable(address p) { +extern "C" NOINLINE void dump_vtable(address p) { Command c("dump_vtable"); Klass* k = (Klass*)p; k->vtable().print(); } -extern "C" DEBUGEXPORT void nm(intptr_t p) { +extern "C" NOINLINE void nm(intptr_t p) { // Actually we look through all CodeBlobs (the nm name has been kept for backwards compatibility) Command c("nm"); CodeBlob* cb = CodeCache::find_blob((address)p); @@ -367,7 +367,7 @@ extern "C" DEBUGEXPORT void nm(intptr_t p) { } -extern "C" DEBUGEXPORT void disnm(intptr_t p) { +extern "C" NOINLINE void disnm(intptr_t p) { Command c("disnm"); CodeBlob* cb = CodeCache::find_blob((address) p); if (cb != nullptr) { @@ -382,7 +382,7 @@ extern "C" DEBUGEXPORT void disnm(intptr_t p) { } -extern "C" DEBUGEXPORT void printnm(intptr_t p) { +extern "C" NOINLINE void printnm(intptr_t p) { char buffer[256]; os::snprintf_checked(buffer, sizeof(buffer), "printnm: " INTPTR_FORMAT, p); Command c(buffer); @@ -396,14 +396,14 @@ extern "C" DEBUGEXPORT void printnm(intptr_t p) { } -extern "C" DEBUGEXPORT void universe() { +extern "C" NOINLINE void universe() { Command c("universe"); if (!c.onThread()) return; Universe::print_on(tty); } -extern "C" DEBUGEXPORT void verify() { +extern "C" NOINLINE void verify() { // try to run a verify on the entire system // note: this may not be safe if we're not at a safepoint; for debugging, // this manipulates the safepoint settings to avoid assertion failures @@ -421,7 +421,7 @@ extern "C" DEBUGEXPORT void verify() { } -extern "C" DEBUGEXPORT void pp(void* p) { +extern "C" NOINLINE void pp(void* p) { Command c("pp"); if (!c.onThread()) return; FlagSetting fl(DisplayVMOutput, true); @@ -445,7 +445,7 @@ extern "C" DEBUGEXPORT void pp(void* p) { } -extern "C" DEBUGEXPORT void ps() { // print stack +extern "C" NOINLINE void ps() { // print stack // Prints the stack of the current Java thread Command c("ps"); if (!c.onThread()) return; @@ -477,7 +477,7 @@ extern "C" DEBUGEXPORT void ps() { // print stack } } -extern "C" DEBUGEXPORT void pfl() { +extern "C" NOINLINE void pfl() { // print frame layout Command c("pfl"); if (!c.onThread()) return; @@ -494,7 +494,7 @@ extern "C" DEBUGEXPORT void pfl() { } } -extern "C" DEBUGEXPORT void psf() { // print stack frames +extern "C" NOINLINE void psf() { // print stack frames Command c("psf"); if (!c.onThread()) return; JavaThread* p = JavaThread::active(); @@ -511,21 +511,21 @@ extern "C" DEBUGEXPORT void psf() { // print stack frames } -extern "C" DEBUGEXPORT void threads() { +extern "C" NOINLINE void threads() { Command c("threads"); if (!c.onThread()) return; Threads::print(false, true); } -extern "C" DEBUGEXPORT void psd() { +extern "C" NOINLINE void psd() { Command c("psd"); if (!c.onThread()) return; SystemDictionary::print(); } -extern "C" DEBUGEXPORT void pss() { // print all stacks +extern "C" NOINLINE void pss() { // print all stacks Command c("pss"); if (!c.onThread()) return; Threads::print(true, PRODUCT_ONLY(false) NOT_PRODUCT(true)); @@ -533,7 +533,7 @@ extern "C" DEBUGEXPORT void pss() { // print all stacks // #ifndef PRODUCT -extern "C" DEBUGEXPORT void debug() { // to set things up for compiler debugging +extern "C" NOINLINE void debug() { // to set things up for compiler debugging Command c("debug"); NOT_PRODUCT(WizardMode = true;) PrintCompilation = true; @@ -542,7 +542,7 @@ extern "C" DEBUGEXPORT void debug() { // to set things up for comp } -extern "C" DEBUGEXPORT void ndebug() { // undo debug() +extern "C" NOINLINE void ndebug() { // undo debug() Command c("ndebug"); PrintCompilation = false; PrintInlining = PrintAssembly = false; @@ -550,36 +550,36 @@ extern "C" DEBUGEXPORT void ndebug() { // undo debug() } -extern "C" DEBUGEXPORT void flush() { +extern "C" NOINLINE void flush() { Command c("flush"); tty->flush(); } -extern "C" DEBUGEXPORT void events() { +extern "C" NOINLINE void events() { Command c("events"); Events::print(); } -extern "C" DEBUGEXPORT Method* findm(intptr_t pc) { +extern "C" NOINLINE Method* findm(intptr_t pc) { Command c("findm"); nmethod* nm = CodeCache::find_nmethod((address)pc); return (nm == nullptr) ? (Method*)nullptr : nm->method(); } -extern "C" DEBUGEXPORT nmethod* findnm(intptr_t addr) { +extern "C" NOINLINE nmethod* findnm(intptr_t addr) { Command c("findnm"); return CodeCache::find_nmethod((address)addr); } -extern "C" DEBUGEXPORT void find(intptr_t x) { +extern "C" NOINLINE void find(intptr_t x) { Command c("find"); if (!c.onThread()) return; os::print_location(tty, x, false); } -extern "C" DEBUGEXPORT void findpc(intptr_t x) { +extern "C" NOINLINE void findpc(intptr_t x) { Command c("findpc"); if (!c.onThread()) return; os::print_location(tty, x, true); @@ -591,15 +591,14 @@ extern "C" DEBUGEXPORT void findpc(intptr_t x) { // call findclass("java/lang/Object", 0x3) -> find j.l.Object and disasm all of its methods // call findmethod("*ang/Object*", "wait", 0xff) -> detailed disasm of all "wait" methods in j.l.Object // call findmethod("*ang/Object*", "wait:(*J*)V", 0x1) -> list all "wait" methods in j.l.Object that have a long parameter -extern "C" DEBUGEXPORT void findclass(const char* class_name_pattern, int flags) { +extern "C" NOINLINE void findclass(const char* class_name_pattern, int flags) { Command c("findclass"); if (!c.onThread()) return; ClassPrinter::print_flags_help(tty); ClassPrinter::print_classes(class_name_pattern, flags, tty); } -extern "C" DEBUGEXPORT void findmethod(const char* class_name_pattern, - const char* method_pattern, int flags) { +extern "C" NOINLINE void findmethod(const char* class_name_pattern, const char* method_pattern, int flags) { Command c("findmethod"); if (!c.onThread()) return; ClassPrinter::print_flags_help(tty); @@ -607,7 +606,7 @@ extern "C" DEBUGEXPORT void findmethod(const char* class_name_pattern, } // Need method pointer to find bcp -extern "C" DEBUGEXPORT void findbcp(intptr_t method, intptr_t bcp) { +extern "C" NOINLINE void findbcp(intptr_t method, intptr_t bcp) { Command c("findbcp"); Method* mh = (Method*)method; if (!mh->is_native()) { @@ -618,7 +617,7 @@ extern "C" DEBUGEXPORT void findbcp(intptr_t method, intptr_t bcp) { } // check and decode a single u5 value -extern "C" DEBUGEXPORT u4 u5decode(intptr_t addr) { +extern "C" NOINLINE u4 u5decode(intptr_t addr) { Command c("u5decode"); u1* arr = (u1*)addr; size_t off = 0, lim = 5; @@ -635,9 +634,7 @@ extern "C" DEBUGEXPORT u4 u5decode(intptr_t addr) { // there is no limit on the count of items printed; the // printing stops when an null is printed or at limit. // See documentation for UNSIGNED5::Reader::print(count). -extern "C" DEBUGEXPORT intptr_t u5p(intptr_t addr, - intptr_t limit, - int count) { +extern "C" NOINLINE intptr_t u5p(intptr_t addr, intptr_t limit, int count) { Command c("u5p"); u1* arr = (u1*)addr; if (limit && limit < addr) limit = addr; @@ -650,10 +647,10 @@ extern "C" DEBUGEXPORT intptr_t u5p(intptr_t addr, // int versions of all methods to avoid having to type type casts in the debugger -void pp(intptr_t p) { pp((void*)p); } -void pp(oop p) { pp((void*)p); } +NOINLINE void pp(intptr_t p) { pp((void*)p); } +NOINLINE void pp(oop p) { pp((void*)p); } -extern "C" DEBUGEXPORT void help() { +extern "C" NOINLINE void help() { Command c("help"); tty->print_cr("basic"); tty->print_cr(" pp(void* p) - try to make sense of p"); @@ -709,7 +706,7 @@ extern "C" DEBUGEXPORT void help() { } #ifndef PRODUCT -extern "C" DEBUGEXPORT void pns(void* sp, void* fp, void* pc) { // print native stack +extern "C" NOINLINE void pns(void* sp, void* fp, void* pc) { // print native stack Command c("pns"); if (!c.onThread()) return; static char buf[O_BUFLEN]; @@ -728,7 +725,7 @@ extern "C" DEBUGEXPORT void pns(void* sp, void* fp, void* pc) { // print native // WARNING: Only intended for use when debugging. Do not leave calls to // pns2() in committed source (product or debug). // -extern "C" DEBUGEXPORT void pns2() { // print native stack +extern "C" NOINLINE void pns2() { // print native stack Command c("pns2"); if (!c.onThread()) return; static char buf[O_BUFLEN]; @@ -739,6 +736,43 @@ extern "C" DEBUGEXPORT void pns2() { // print native stack } #endif +// just an exported helper; to avoid link time elimination of the referenced functions +extern "C" JNIEXPORT void JVM_debug_helpers_keeper(void* p1, void* p2, void* p3, intptr_t ip, oop oh, address adr) { + blob((CodeBlob*)p1); + dump_vtable(adr); + nm(ip); + disnm(ip); + printnm(ip); + universe(); + verify(); + pp(p1); + ps(); + pfl(); + psf(); + threads(); + psd(); + pss(); + debug(); + ndebug(); + flush(); + events(); + findm(ip); + findnm(ip); + find(ip); + findpc(ip); + findclass("", 0); + findmethod("", "", 0); + findbcp(ip, ip); + u5decode(ip); + u5p(ip, ip, 0); + pp(ip); + pp(oh); + help(); +#ifndef PRODUCT + pns(p1, p2, p3); + pns2(); +#endif +} // Returns true iff the address p is readable and *(intptr_t*)p != errvalue extern "C" bool dbg_is_safe(const void* p, intptr_t errvalue) { From aea8947e9df84bf583ef658c5bf5f61ad87b73fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20=C3=96sterlund?= Date: Thu, 26 Mar 2026 09:29:53 +0000 Subject: [PATCH 003/116] 8378176: Concurrent GC worker threads may suffer from priority inversion Reviewed-by: kbarrett, ayang, tschatzl --- src/hotspot/share/gc/shared/concurrentGCThread.cpp | 3 +-- src/hotspot/share/gc/shared/concurrentGCThread.hpp | 2 +- src/hotspot/share/gc/shared/workerThread.cpp | 2 -- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/hotspot/share/gc/shared/concurrentGCThread.cpp b/src/hotspot/share/gc/shared/concurrentGCThread.cpp index ed6c1b4d283..c7765631cd9 100644 --- a/src/hotspot/share/gc/shared/concurrentGCThread.cpp +++ b/src/hotspot/share/gc/shared/concurrentGCThread.cpp @@ -33,9 +33,8 @@ ConcurrentGCThread::ConcurrentGCThread() : _should_terminate(false), _has_terminated(false) {} -void ConcurrentGCThread::create_and_start(ThreadPriority prio) { +void ConcurrentGCThread::create_and_start() { if (os::create_thread(this, os::gc_thread)) { - os::set_priority(this, prio); os::start_thread(this); } } diff --git a/src/hotspot/share/gc/shared/concurrentGCThread.hpp b/src/hotspot/share/gc/shared/concurrentGCThread.hpp index 0c764546045..5322d676493 100644 --- a/src/hotspot/share/gc/shared/concurrentGCThread.hpp +++ b/src/hotspot/share/gc/shared/concurrentGCThread.hpp @@ -36,7 +36,7 @@ class ConcurrentGCThread: public NamedThread { Atomic _has_terminated; protected: - void create_and_start(ThreadPriority prio = NearMaxPriority); + void create_and_start(); virtual void run_service() = 0; virtual void stop_service() = 0; diff --git a/src/hotspot/share/gc/shared/workerThread.cpp b/src/hotspot/share/gc/shared/workerThread.cpp index 2f6f003608f..2738c98e5c3 100644 --- a/src/hotspot/share/gc/shared/workerThread.cpp +++ b/src/hotspot/share/gc/shared/workerThread.cpp @@ -210,8 +210,6 @@ WorkerThread::WorkerThread(const char* name_prefix, uint name_suffix, WorkerTask } void WorkerThread::run() { - os::set_priority(this, NearMaxPriority); - while (true) { _dispatcher->worker_run_task(); } From ab659d4ee48b33a4bad21857b02f0a29314f2b43 Mon Sep 17 00:00:00 2001 From: Dusan Balek Date: Thu, 26 Mar 2026 10:19:37 +0000 Subject: [PATCH 004/116] 8371817: javac with annotation processor throws AssertionError: Cannot add metadata to this type: METHOD when dealing with local classes Reviewed-by: mcimadamore --- .../com/sun/tools/javac/jvm/ClassReader.java | 9 +- .../classfile/LocalClassesTest.java | 163 ++++++++++++++++++ 2 files changed, 168 insertions(+), 4 deletions(-) create mode 100644 test/langtools/tools/javac/annotations/typeAnnotations/classfile/LocalClassesTest.java diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java index 017d740dc0a..08ba0442781 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java @@ -1367,9 +1367,7 @@ protected void readEnclosingMethodAttr(Symbol sym) { else self.fullname = ClassSymbol.formFullName(self.name, self.owner); - if (m != null) { - ((ClassType)sym.type).setEnclosingType(m.type); - } else if ((self.flags_field & STATIC) == 0) { + if ((self.flags_field & STATIC) == 0 && (m == null || (m.flags_field & STATIC) == 0)) { ((ClassType)sym.type).setEnclosingType(c.type); } else { ((ClassType)sym.type).setEnclosingType(Type.noType); @@ -2687,6 +2685,7 @@ MethodSymbol readMethod() { // won't pass the "hasOuterInstance" check above, but those that don't have an // enclosing method (i.e. from initializers) will pass that check. boolean local = forceLocal = + currentOwner.owner.kind != TYP || !currentOwner.owner.members().includes(currentOwner, LookupKind.NON_RECURSIVE); if (!currentOwner.name.isEmpty() && !local) type = new MethodType(adjustMethodParams(flags, type.getParameterTypes()), @@ -3038,7 +3037,9 @@ void skipInnerClasses() { * `typevars'. */ protected void enterTypevars(Symbol sym, Type t) { - if (t.getEnclosingType() != null) { + if (sym.owner.kind == MTH) { + enterTypevars(sym.owner, sym.owner.type); + } else if (t.getEnclosingType() != null) { if (!t.getEnclosingType().hasTag(TypeTag.NONE)) { enterTypevars(sym.owner, t.getEnclosingType()); } diff --git a/test/langtools/tools/javac/annotations/typeAnnotations/classfile/LocalClassesTest.java b/test/langtools/tools/javac/annotations/typeAnnotations/classfile/LocalClassesTest.java new file mode 100644 index 00000000000..66b55c8d209 --- /dev/null +++ b/test/langtools/tools/javac/annotations/typeAnnotations/classfile/LocalClassesTest.java @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 8371817 + * @summary Check for type annotating types that refer to local classes read + * from classfiles + * @library /tools/lib + * @modules + * jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + * @build toolbox.ToolBox toolbox.JavacTask + * @run junit LocalClassesTest + */ + +import com.sun.source.tree.ClassTree; +import com.sun.source.util.TaskEvent; +import com.sun.source.util.TaskListener; +import com.sun.source.util.TreePathScanner; +import com.sun.source.util.Trees; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import javax.annotation.processing.AbstractProcessor; +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.TypeElement; +import javax.lang.model.type.DeclaredType; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.ElementFilter; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInfo; +import toolbox.JavacTask; +import toolbox.ToolBox; + +public class LocalClassesTest { + + ToolBox tb = new ToolBox(); + Path base; + + @Test + void test() throws Exception { + Path classes = base.resolve("classes"); + Files.createDirectories(classes); + + Map local2enclosing = new HashMap<>(); + new JavacTask(tb) + .options("-d", classes.toString()) + .sources(""" + import java.lang.annotation.ElementType; + import java.lang.annotation.Target; + + public class Test { + public static void m1() { + class Local1 { + @Nullable Local1 l; + } + } + public void m2() { + class Local2 { + @Nullable Local2 l; + } + } + } + + @Target({ElementType.TYPE_USE}) + @interface Nullable {} + """) + .callback(task -> { + task.addTaskListener(new TaskListener() { + @Override + public void finished(TaskEvent e) { + if (e.getKind() == TaskEvent.Kind.ANALYZE) { + Trees trees = Trees.instance(task); + new TreePathScanner<>() { + @Override + public Object visitClass(ClassTree node, Object p) { + if (node.getSimpleName().toString().startsWith("Local")) { + Element el = trees.getElement(getCurrentPath()); + TypeMirror type = trees.getTypeMirror(getCurrentPath()); + local2enclosing.put(el.getSimpleName().toString(), ((DeclaredType) type).getEnclosingType().toString()); + } + return super.visitClass(node, p); + } + }.scan(e.getCompilationUnit(), null); + } + } + }); + }) + .run() + .writeAll(); + + Path classes2 = base.resolve("classes2"); + Files.createDirectories(classes2); + + ProcessorImpl p = new ProcessorImpl(); + new JavacTask(tb) + .options("-cp", classes.toString(), "-d", classes2.toString()) + .processors(p) + .classes("Test$1Local1", "Test$1Local2") + .run() + .writeAll(); + + Assertions.assertEquals(local2enclosing.get("Local1"), p.local2enclosing.get("Local1")); + Assertions.assertEquals(local2enclosing.get("Local2"), p.local2enclosing.get("Local2")); + } + + @SupportedAnnotationTypes("*") + private static class ProcessorImpl extends AbstractProcessor { + private Map local2enclosing = new HashMap<>(); + + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + for (TypeElement te : ElementFilter.typesIn(roundEnv.getRootElements())) { + if (te.getSimpleName().toString().startsWith("Local")) { + local2enclosing.put(te.getSimpleName().toString(), ((DeclaredType) te.asType()).getEnclosingType().toString()); + } + } + return false; + } + + @Override + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latestSupported(); + } + } + + @BeforeEach + public void setup(TestInfo info) { + base = Paths.get(".") + .resolve(info.getTestMethod() + .orElseThrow() + .getName()); + } +} From da296cbea1603e8b1de46c9daafced76fce921e6 Mon Sep 17 00:00:00 2001 From: Thomas Stuefe Date: Thu, 26 Mar 2026 11:08:48 +0000 Subject: [PATCH 005/116] 8363996: Obsolete UseCompressedClassPointers Reviewed-by: rkennke, kvn, adinn, dholmes, mdoerr, iklam, fyang --- src/hotspot/cpu/aarch64/aarch64.ad | 12 +- .../cpu/aarch64/c1_LIRAssembler_aarch64.cpp | 27 +- .../cpu/aarch64/c1_LIRGenerator_aarch64.cpp | 10 +- .../cpu/aarch64/c1_MacroAssembler_aarch64.cpp | 12 +- .../cpu/aarch64/macroAssembler_aarch64.cpp | 74 ++---- src/hotspot/cpu/arm/matcher_arm.hpp | 3 +- src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp | 4 +- src/hotspot/cpu/ppc/macroAssembler_ppc.cpp | 65 ++--- src/hotspot/cpu/ppc/matcher_ppc.hpp | 1 - .../riscv/c1_LIRAssembler_arraycopy_riscv.cpp | 11 +- .../cpu/riscv/c1_LIRAssembler_riscv.cpp | 24 +- .../cpu/riscv/c1_LIRGenerator_riscv.cpp | 10 +- .../cpu/riscv/c1_MacroAssembler_riscv.cpp | 12 +- .../cpu/riscv/c2_MacroAssembler_riscv.cpp | 15 +- .../cpu/riscv/macroAssembler_riscv.cpp | 34 +-- src/hotspot/cpu/riscv/riscv.ad | 9 +- src/hotspot/cpu/riscv/stubGenerator_riscv.cpp | 8 +- src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp | 15 +- .../cpu/s390/c1_MacroAssembler_s390.cpp | 8 +- src/hotspot/cpu/s390/macroAssembler_s390.cpp | 160 +++++------- src/hotspot/cpu/s390/macroAssembler_s390.hpp | 5 +- src/hotspot/cpu/s390/matcher_s390.hpp | 3 +- src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp | 39 +-- src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp | 10 +- src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp | 9 +- src/hotspot/cpu/x86/macroAssembler_x86.cpp | 38 +-- src/hotspot/cpu/x86/macroAssembler_x86.hpp | 3 +- src/hotspot/cpu/x86/matcher_x86.hpp | 3 +- src/hotspot/cpu/x86/x86.ad | 9 +- src/hotspot/share/cds/aotMapLogger.cpp | 1 - src/hotspot/share/cds/aotMappedHeapLoader.hpp | 2 +- src/hotspot/share/cds/aotMappedHeapWriter.cpp | 2 - src/hotspot/share/cds/aotMetaspace.cpp | 222 ++++++++-------- .../share/cds/aotStreamedHeapWriter.cpp | 1 - src/hotspot/share/cds/archiveBuilder.cpp | 7 +- src/hotspot/share/cds/archiveBuilder.hpp | 2 - src/hotspot/share/cds/archiveUtils.cpp | 4 +- src/hotspot/share/cds/cdsConfig.cpp | 4 - src/hotspot/share/cds/filemap.cpp | 24 +- src/hotspot/share/cds/filemap.hpp | 2 - .../classfile/systemDictionaryShared.cpp | 4 +- src/hotspot/share/code/aotCodeCache.cpp | 7 - src/hotspot/share/code/aotCodeCache.hpp | 11 +- src/hotspot/share/code/compiledIC.cpp | 15 +- .../share/gc/shared/c2/barrierSetC2.cpp | 1 - src/hotspot/share/gc/shared/gcTrace.cpp | 9 +- .../share/gc/shenandoah/shenandoahAsserts.cpp | 32 ++- src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp | 4 +- src/hotspot/share/gc/z/zDebug.gdb | 6 +- .../types/traceid/jfrTraceIdKlassQueue.cpp | 4 +- .../share/jvmci/jvmciCompilerToVMInit.cpp | 10 +- src/hotspot/share/jvmci/vmStructs_jvmci.cpp | 4 +- .../share/memory/classLoaderMetaspace.cpp | 6 +- .../share/memory/classLoaderMetaspace.hpp | 17 +- src/hotspot/share/memory/metaspace.cpp | 239 +++++++++--------- src/hotspot/share/memory/metaspace.hpp | 10 +- .../memory/metaspace/metaspaceReporter.cpp | 214 ++++++++-------- .../memory/metaspace/metaspaceStatistics.cpp | 28 +- .../memory/metaspace/virtualSpaceNode.cpp | 11 +- src/hotspot/share/nmt/memReporter.cpp | 10 +- src/hotspot/share/oops/arrayOop.hpp | 5 +- src/hotspot/share/oops/compressedKlass.cpp | 33 +-- src/hotspot/share/oops/compressedKlass.hpp | 8 - .../share/oops/compressedKlass.inline.hpp | 4 +- src/hotspot/share/oops/instanceKlass.cpp | 6 +- src/hotspot/share/oops/klass.cpp | 12 +- src/hotspot/share/oops/objLayout.cpp | 10 +- src/hotspot/share/oops/objLayout.hpp | 10 +- src/hotspot/share/oops/objLayout.inline.hpp | 4 +- src/hotspot/share/oops/oop.cpp | 5 +- src/hotspot/share/oops/oop.hpp | 9 +- src/hotspot/share/oops/oop.inline.hpp | 33 +-- src/hotspot/share/opto/cfgnode.cpp | 2 +- src/hotspot/share/opto/chaitin.cpp | 4 +- src/hotspot/share/opto/compile.cpp | 8 +- src/hotspot/share/opto/lcm.cpp | 5 +- src/hotspot/share/opto/memnode.cpp | 4 +- src/hotspot/share/opto/narrowptrnode.cpp | 4 +- src/hotspot/share/opto/type.cpp | 2 +- src/hotspot/share/prims/whitebox.cpp | 1 - src/hotspot/share/runtime/arguments.cpp | 19 +- src/hotspot/share/runtime/globals.hpp | 3 - src/hotspot/share/runtime/os.cpp | 5 +- src/hotspot/share/runtime/vmStructs.cpp | 3 +- src/hotspot/share/services/memoryService.cpp | 12 +- src/hotspot/share/utilities/macros.hpp | 14 +- src/hotspot/share/utilities/vmError.cpp | 15 +- .../classes/sun/jvm/hotspot/oops/Array.java | 6 +- .../sun/jvm/hotspot/oops/Instance.java | 6 +- .../classes/sun/jvm/hotspot/oops/Oop.java | 21 +- .../classes/sun/jvm/hotspot/runtime/VM.java | 18 +- .../gtest/metaspace/test_is_metaspace_obj.cpp | 6 +- .../gtest/metaspace/test_metaspaceUtils.cpp | 61 ++--- test/hotspot/gtest/oops/test_arrayOop.cpp | 20 +- .../gtest/oops/test_compressedKlass.cpp | 30 --- test/hotspot/gtest/oops/test_objArrayOop.cpp | 40 ++- .../arraycopy/TestObjectArrayClone.java | 6 +- .../c1/TestArrayCopyToFromObject.java | 5 +- .../c2/TestReduceAllocationAndLoadKlass.java | 63 ----- .../AllocationMergesTests.java | 22 +- .../compilerToVM/GetResolvedJavaTypeTest.java | 3 +- .../jdk/vm/ci/code/test/DataPatchTest.java | 4 +- .../vm/ci/code/test/TestHotSpotVMConfig.java | 3 +- .../types/TestCheckCastPPBecomesTOP.java | 3 - .../jtreg/compiler/unsafe/OpaqueAccesses.java | 18 +- .../arguments/TestCompressedClassFlags.java | 53 ---- .../gc/g1/TestSharedArchiveWithPreTouch.java | 6 +- .../gc/metaspace/TestMetaspaceMemoryPool.java | 15 +- .../metaspace/TestMetaspacePerfCounters.java | 37 +-- .../TestPerfCountersAndMemoryPools.java | 7 +- .../gc/metaspace/TestSizeTransitions.java | 48 ++-- test/hotspot/jtreg/gtest/ArrayTests.java | 27 +- .../jtreg/gtest/CompressedKlassGtest.java | 10 +- test/hotspot/jtreg/gtest/MetaspaceGtests.java | 11 +- test/hotspot/jtreg/gtest/ObjArrayTests.java | 54 +--- .../CDSCompressedKPtrs.java | 66 ----- .../CompressedClassPointers.java | 22 +- .../CompressedClassSpaceSize.java | 9 +- .../CompressedKlassPointerAndOops.java | 6 +- .../TestVMConfigInHsErrFile.java | 15 +- .../runtime/FieldLayout/BaseOffsets.java | 42 +-- .../runtime/FieldLayout/FieldDensityTest.java | 5 +- .../FieldLayout/TestOopMapSizeMinimal.java | 39 +-- .../Metaspace/MaxMetaspaceSizeTest.java | 3 +- .../runtime/Metaspace/PrintMetaspaceDcmd.java | 60 +---- .../cds/appcds/CommandLineFlagCombo.java | 4 +- .../appcds/CommandLineFlagComboNegative.java | 8 +- .../cds/appcds/FillerObjectLoadTest.java | 53 ---- .../appcds/TestCombinedCompressedFlags.java | 87 +------ .../runtime/cds/appcds/TestZGCWithCDS.java | 62 +---- .../cds/appcds/aotCache/OldClassSupport2.java | 7 +- .../cacheObject/DifferentHeapSizes.java | 4 +- .../dynamicArchive/CDSStreamTestDriver.java | 4 +- .../DynamicArchiveTestBase.java | 7 +- .../sharedStrings/IncompatibleOptions.java | 16 +- .../dcmd/vm/ClassLoaderStatsTest.java | 15 +- .../ir_framework/tests/TestIRMatching.java | 19 -- .../GetObjectSizeIntrinsicsTest.java | 5 +- .../TestObjectAllocationInNewTLABEvent.java | 9 +- .../TestObjectAllocationOutsideTLABEvent.java | 9 +- ...ObjectAllocationSampleEventThrottling.java | 9 +- .../TestHeapSummaryEventDefNewSerial.java | 12 +- .../objectcount/ObjectCountEventVerifier.java | 4 +- ...CountAfterGCEventWithG1ConcurrentMark.java | 4 +- ...CountAfterGCEventWithG1FullCollection.java | 4 +- ...bjectCountAfterGCEventWithParallelOld.java | 4 +- ...TestObjectCountAfterGCEventWithSerial.java | 4 +- .../gc/objectcount/TestObjectCountEvent.java | 4 +- test/jtreg-ext/requires/VMProps.java | 11 +- 149 files changed, 940 insertions(+), 2081 deletions(-) delete mode 100644 test/hotspot/jtreg/compiler/c2/TestReduceAllocationAndLoadKlass.java delete mode 100644 test/hotspot/jtreg/gc/arguments/TestCompressedClassFlags.java delete mode 100644 test/hotspot/jtreg/runtime/CDSCompressedKPtrs/CDSCompressedKPtrs.java delete mode 100644 test/hotspot/jtreg/runtime/cds/appcds/FillerObjectLoadTest.java diff --git a/src/hotspot/cpu/aarch64/aarch64.ad b/src/hotspot/cpu/aarch64/aarch64.ad index b79030f07e7..05b2514a456 100644 --- a/src/hotspot/cpu/aarch64/aarch64.ad +++ b/src/hotspot/cpu/aarch64/aarch64.ad @@ -2233,15 +2233,9 @@ uint BoxLockNode::size(PhaseRegAlloc *ra_) const { void MachUEPNode::format(PhaseRegAlloc* ra_, outputStream* st) const { st->print_cr("# MachUEPNode"); - if (UseCompressedClassPointers) { - st->print_cr("\tldrw rscratch1, [j_rarg0 + oopDesc::klass_offset_in_bytes()]\t# compressed klass"); - st->print_cr("\tldrw r10, [rscratch2 + CompiledICData::speculated_klass_offset()]\t# compressed klass"); - st->print_cr("\tcmpw rscratch1, r10"); - } else { - st->print_cr("\tldr rscratch1, [j_rarg0 + oopDesc::klass_offset_in_bytes()]\t# compressed klass"); - st->print_cr("\tldr r10, [rscratch2 + CompiledICData::speculated_klass_offset()]\t# compressed klass"); - st->print_cr("\tcmp rscratch1, r10"); - } + st->print_cr("\tldrw rscratch1, [j_rarg0 + oopDesc::klass_offset_in_bytes()]\t# compressed klass"); + st->print_cr("\tldrw r10, [rscratch2 + CompiledICData::speculated_klass_offset()]\t# compressed klass"); + st->print_cr("\tcmpw rscratch1, r10"); st->print_cr("\tbne, SharedRuntime::_ic_miss_stub"); } #endif diff --git a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp index 30048a2079d..e7d8c2d3648 100644 --- a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, 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. * @@ -59,22 +59,6 @@ const Register SHIFT_count = r0; // where count for shift operations must be #define __ _masm-> -static void select_different_registers(Register preserve, - Register extra, - Register &tmp1, - Register &tmp2) { - if (tmp1 == preserve) { - assert_different_registers(tmp1, tmp2, extra); - tmp1 = extra; - } else if (tmp2 == preserve) { - assert_different_registers(tmp1, tmp2, extra); - tmp2 = extra; - } - assert_different_registers(preserve, tmp1, tmp2); -} - - - static void select_different_registers(Register preserve, Register extra, Register &tmp1, @@ -1269,12 +1253,9 @@ void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, L } else if (obj == klass_RInfo) { klass_RInfo = dst; } - if (k->is_loaded() && !UseCompressedClassPointers) { - select_different_registers(obj, dst, k_RInfo, klass_RInfo); - } else { - Rtmp1 = op->tmp3()->as_register(); - select_different_registers(obj, dst, k_RInfo, klass_RInfo, Rtmp1); - } + + Rtmp1 = op->tmp3()->as_register(); + select_different_registers(obj, dst, k_RInfo, klass_RInfo, Rtmp1); assert_different_registers(obj, k_RInfo, klass_RInfo); diff --git a/src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp index ad26d494b2d..f10c5197d91 100644 --- a/src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2026, 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. * @@ -1287,9 +1287,7 @@ void LIRGenerator::do_CheckCast(CheckCast* x) { } LIR_Opr reg = rlock_result(x); LIR_Opr tmp3 = LIR_OprFact::illegalOpr; - if (!x->klass()->is_loaded() || UseCompressedClassPointers) { - tmp3 = new_register(objectType); - } + tmp3 = new_register(objectType); __ checkcast(reg, obj.result(), x->klass(), new_register(objectType), new_register(objectType), tmp3, x->direct_compare(), info_for_exception, patching_info, stub, @@ -1308,9 +1306,7 @@ void LIRGenerator::do_InstanceOf(InstanceOf* x) { } obj.load_item(); LIR_Opr tmp3 = LIR_OprFact::illegalOpr; - if (!x->klass()->is_loaded() || UseCompressedClassPointers) { - tmp3 = new_register(objectType); - } + tmp3 = new_register(objectType); __ instanceof(reg, obj.result(), x->klass(), new_register(objectType), new_register(objectType), tmp3, x->direct_compare(), patching_info, x->profiled_method(), x->profiled_bci()); diff --git a/src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.cpp index e934632715c..89a9422ea48 100644 --- a/src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2026, 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. * @@ -105,12 +105,8 @@ void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register } else { mov(t1, checked_cast(markWord::prototype().value())); str(t1, Address(obj, oopDesc::mark_offset_in_bytes())); - if (UseCompressedClassPointers) { // Take care not to kill klass - encode_klass_not_null(t1, klass); - strw(t1, Address(obj, oopDesc::klass_offset_in_bytes())); - } else { - str(klass, Address(obj, oopDesc::klass_offset_in_bytes())); - } + encode_klass_not_null(t1, klass); // Take care not to kill klass + strw(t1, Address(obj, oopDesc::klass_offset_in_bytes())); } if (len->is_valid()) { @@ -121,7 +117,7 @@ void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register // Clear gap/first 4 bytes following the length field. strw(zr, Address(obj, base_offset)); } - } else if (UseCompressedClassPointers && !UseCompactObjectHeaders) { + } else if (!UseCompactObjectHeaders) { store_klass_gap(obj, zr); } } diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp index 3e3e95be07e..732d94180ae 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp @@ -762,7 +762,7 @@ void MacroAssembler::call_VM_base(Register oop_result, assert(java_thread == rthread, "unexpected register"); #ifdef ASSERT // TraceBytecodes does not use r12 but saves it over the call, so don't verify - // if ((UseCompressedOops || UseCompressedClassPointers) && !TraceBytecodes) verify_heapbase("call_VM_base: heap base corrupted?"); + // if (!TraceBytecodes) verify_heapbase("call_VM_base: heap base corrupted?"); #endif // ASSERT assert(java_thread != oop_result , "cannot use the same register for java_thread & oop_result"); @@ -1002,14 +1002,10 @@ int MacroAssembler::ic_check(int end_alignment) { load_narrow_klass_compact(tmp1, receiver); ldrw(tmp2, Address(data, CompiledICData::speculated_klass_offset())); cmpw(tmp1, tmp2); - } else if (UseCompressedClassPointers) { + } else { ldrw(tmp1, Address(receiver, oopDesc::klass_offset_in_bytes())); ldrw(tmp2, Address(data, CompiledICData::speculated_klass_offset())); cmpw(tmp1, tmp2); - } else { - ldr(tmp1, Address(receiver, oopDesc::klass_offset_in_bytes())); - ldr(tmp2, Address(data, CompiledICData::speculated_klass_offset())); - cmp(tmp1, tmp2); } Label dont; @@ -3278,7 +3274,6 @@ int MacroAssembler::pop_p(unsigned int bitset, Register stack) { #ifdef ASSERT void MacroAssembler::verify_heapbase(const char* msg) { #if 0 - assert (UseCompressedOops || UseCompressedClassPointers, "should be compressed"); assert (Universe::heap() != nullptr, "java heap should be initialized"); if (!UseCompressedOops || Universe::ptr_base() == nullptr) { // rheapbase is allocated as general register @@ -5067,13 +5062,10 @@ void MacroAssembler::load_narrow_klass_compact(Register dst, Register src) { void MacroAssembler::load_klass(Register dst, Register src) { if (UseCompactObjectHeaders) { load_narrow_klass_compact(dst, src); - decode_klass_not_null(dst); - } else if (UseCompressedClassPointers) { - ldrw(dst, Address(src, oopDesc::klass_offset_in_bytes())); - decode_klass_not_null(dst); } else { - ldr(dst, Address(src, oopDesc::klass_offset_in_bytes())); + ldrw(dst, Address(src, oopDesc::klass_offset_in_bytes())); } + decode_klass_not_null(dst); } void MacroAssembler::restore_cpu_control_state_after_jni(Register tmp1, Register tmp2) { @@ -5125,25 +5117,21 @@ void MacroAssembler::load_mirror(Register dst, Register method, Register tmp1, R void MacroAssembler::cmp_klass(Register obj, Register klass, Register tmp) { assert_different_registers(obj, klass, tmp); - if (UseCompressedClassPointers) { - if (UseCompactObjectHeaders) { - load_narrow_klass_compact(tmp, obj); - } else { - ldrw(tmp, Address(obj, oopDesc::klass_offset_in_bytes())); - } - if (CompressedKlassPointers::base() == nullptr) { - cmp(klass, tmp, LSL, CompressedKlassPointers::shift()); - return; - } else if (((uint64_t)CompressedKlassPointers::base() & 0xffffffff) == 0 - && CompressedKlassPointers::shift() == 0) { - // Only the bottom 32 bits matter - cmpw(klass, tmp); - return; - } - decode_klass_not_null(tmp); + if (UseCompactObjectHeaders) { + load_narrow_klass_compact(tmp, obj); } else { - ldr(tmp, Address(obj, oopDesc::klass_offset_in_bytes())); + ldrw(tmp, Address(obj, oopDesc::klass_offset_in_bytes())); + } + if (CompressedKlassPointers::base() == nullptr) { + cmp(klass, tmp, LSL, CompressedKlassPointers::shift()); + return; + } else if (((uint64_t)CompressedKlassPointers::base() & 0xffffffff) == 0 + && CompressedKlassPointers::shift() == 0) { + // Only the bottom 32 bits matter + cmpw(klass, tmp); + return; } + decode_klass_not_null(tmp); cmp(klass, tmp); } @@ -5151,36 +5139,25 @@ void MacroAssembler::cmp_klasses_from_objects(Register obj1, Register obj2, Regi if (UseCompactObjectHeaders) { load_narrow_klass_compact(tmp1, obj1); load_narrow_klass_compact(tmp2, obj2); - cmpw(tmp1, tmp2); - } else if (UseCompressedClassPointers) { + } else { ldrw(tmp1, Address(obj1, oopDesc::klass_offset_in_bytes())); ldrw(tmp2, Address(obj2, oopDesc::klass_offset_in_bytes())); - cmpw(tmp1, tmp2); - } else { - ldr(tmp1, Address(obj1, oopDesc::klass_offset_in_bytes())); - ldr(tmp2, Address(obj2, oopDesc::klass_offset_in_bytes())); - cmp(tmp1, tmp2); } + cmpw(tmp1, tmp2); } void MacroAssembler::store_klass(Register dst, Register src) { // FIXME: Should this be a store release? concurrent gcs assumes // klass length is valid if klass field is not null. assert(!UseCompactObjectHeaders, "not with compact headers"); - if (UseCompressedClassPointers) { - encode_klass_not_null(src); - strw(src, Address(dst, oopDesc::klass_offset_in_bytes())); - } else { - str(src, Address(dst, oopDesc::klass_offset_in_bytes())); - } + encode_klass_not_null(src); + strw(src, Address(dst, oopDesc::klass_offset_in_bytes())); } void MacroAssembler::store_klass_gap(Register dst, Register src) { assert(!UseCompactObjectHeaders, "not with compact headers"); - if (UseCompressedClassPointers) { - // Store to klass gap in destination - strw(src, Address(dst, oopDesc::klass_gap_offset_in_bytes())); - } + // Store to klass gap in destination + strw(src, Address(dst, oopDesc::klass_gap_offset_in_bytes())); } // Algorithm must match CompressedOops::encode. @@ -5326,8 +5303,6 @@ MacroAssembler::KlassDecodeMode MacroAssembler::klass_decode_mode() { } MacroAssembler::KlassDecodeMode MacroAssembler::klass_decode_mode(address base, int shift, const size_t range) { - assert(UseCompressedClassPointers, "not using compressed class pointers"); - // KlassDecodeMode shouldn't be set already. assert(_klass_decode_mode == KlassDecodeNone, "set once"); @@ -5457,8 +5432,6 @@ void MacroAssembler::decode_klass_not_null_for_aot(Register dst, Register src) { } void MacroAssembler::decode_klass_not_null(Register dst, Register src) { - assert (UseCompressedClassPointers, "should only be used for compressed headers"); - if (AOTCodeCache::is_on_for_dump()) { decode_klass_not_null_for_aot(dst, src); return; @@ -5525,7 +5498,6 @@ void MacroAssembler::set_narrow_oop(Register dst, jobject obj) { } void MacroAssembler::set_narrow_klass(Register dst, Klass* k) { - assert (UseCompressedClassPointers, "should only be used for compressed headers"); assert (oop_recorder() != nullptr, "this assembler needs an OopRecorder"); int index = oop_recorder()->find_index(k); diff --git a/src/hotspot/cpu/arm/matcher_arm.hpp b/src/hotspot/cpu/arm/matcher_arm.hpp index 6c818e1f20d..7978a5b7090 100644 --- a/src/hotspot/cpu/arm/matcher_arm.hpp +++ b/src/hotspot/cpu/arm/matcher_arm.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -75,7 +75,6 @@ static bool narrow_klass_use_complex_address() { NOT_LP64(ShouldNotCallThis()); - assert(UseCompressedClassPointers, "only for compressed klass code"); return false; } diff --git a/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp b/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp index 798451446e5..4d7af0e4a71 100644 --- a/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2025 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -144,7 +144,7 @@ void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register if (len->is_valid()) { stw(len, arrayOopDesc::length_offset_in_bytes(), obj); - } else if (UseCompressedClassPointers && !UseCompactObjectHeaders) { + } else if (!UseCompactObjectHeaders) { // Otherwise length is in the class gap. store_klass_gap(obj); } diff --git a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp index 14e90ddf185..5fbcce94029 100644 --- a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp @@ -3201,23 +3201,17 @@ Register MacroAssembler::encode_klass_not_null(Register dst, Register src) { void MacroAssembler::store_klass(Register dst_oop, Register klass, Register ck) { assert(!UseCompactObjectHeaders, "not with compact headers"); - if (UseCompressedClassPointers) { - Register compressedKlass = encode_klass_not_null(ck, klass); - stw(compressedKlass, oopDesc::klass_offset_in_bytes(), dst_oop); - } else { - std(klass, oopDesc::klass_offset_in_bytes(), dst_oop); - } + Register compressedKlass = encode_klass_not_null(ck, klass); + stw(compressedKlass, oopDesc::klass_offset_in_bytes(), dst_oop); } void MacroAssembler::store_klass_gap(Register dst_oop, Register val) { assert(!UseCompactObjectHeaders, "not with compact headers"); - if (UseCompressedClassPointers) { - if (val == noreg) { - val = R0; - li(val, 0); - } - stw(val, oopDesc::klass_gap_offset_in_bytes(), dst_oop); + if (val == noreg) { + val = R0; + li(val, 0); } + stw(val, oopDesc::klass_gap_offset_in_bytes(), dst_oop); } int MacroAssembler::instr_size_for_decode_klass_not_null() { @@ -3226,17 +3220,13 @@ int MacroAssembler::instr_size_for_decode_klass_not_null() { // Not yet computed? if (computed_size == -1) { - if (!UseCompressedClassPointers) { - computed_size = 0; - } else { - // Determine by scratch emit. - ResourceMark rm; - int code_size = 8 * BytesPerInstWord; - CodeBuffer cb("decode_klass_not_null scratch buffer", code_size, 0); - MacroAssembler* a = new MacroAssembler(&cb); - a->decode_klass_not_null(R11_scratch1); - computed_size = a->offset(); - } + // Determine by scratch emit. + ResourceMark rm; + int code_size = 8 * BytesPerInstWord; + CodeBuffer cb("decode_klass_not_null scratch buffer", code_size, 0); + MacroAssembler* a = new MacroAssembler(&cb); + a->decode_klass_not_null(R11_scratch1); + computed_size = a->offset(); } return computed_size; @@ -3259,18 +3249,14 @@ void MacroAssembler::decode_klass_not_null(Register dst, Register src) { void MacroAssembler::load_klass_no_decode(Register dst, Register src) { if (UseCompactObjectHeaders) { load_narrow_klass_compact(dst, src); - } else if (UseCompressedClassPointers) { - lwz(dst, oopDesc::klass_offset_in_bytes(), src); } else { - ld(dst, oopDesc::klass_offset_in_bytes(), src); + lwz(dst, oopDesc::klass_offset_in_bytes(), src); } } void MacroAssembler::load_klass(Register dst, Register src) { load_klass_no_decode(dst, src); - if (UseCompressedClassPointers) { // also true for UseCompactObjectHeaders - decode_klass_not_null(dst); - } + decode_klass_not_null(dst); } // Loads the obj's Klass* into dst. @@ -3286,18 +3272,13 @@ void MacroAssembler::load_narrow_klass_compact(Register dst, Register src) { void MacroAssembler::cmp_klass(ConditionRegister dst, Register obj, Register klass, Register tmp, Register tmp2) { assert_different_registers(obj, klass, tmp); - if (UseCompressedClassPointers) { - if (UseCompactObjectHeaders) { - load_narrow_klass_compact(tmp, obj); - } else { - lwz(tmp, oopDesc::klass_offset_in_bytes(), obj); - } - Register encoded_klass = encode_klass_not_null(tmp2, klass); - cmpw(dst, tmp, encoded_klass); + if (UseCompactObjectHeaders) { + load_narrow_klass_compact(tmp, obj); } else { - ld(tmp, oopDesc::klass_offset_in_bytes(), obj); - cmpd(dst, tmp, klass); + lwz(tmp, oopDesc::klass_offset_in_bytes(), obj); } + Register encoded_klass = encode_klass_not_null(tmp2, klass); + cmpw(dst, tmp, encoded_klass); } void MacroAssembler::cmp_klasses_from_objects(ConditionRegister dst, Register obj1, Register obj2, Register tmp1, Register tmp2) { @@ -3305,14 +3286,10 @@ void MacroAssembler::cmp_klasses_from_objects(ConditionRegister dst, Register ob load_narrow_klass_compact(tmp1, obj1); load_narrow_klass_compact(tmp2, obj2); cmpw(dst, tmp1, tmp2); - } else if (UseCompressedClassPointers) { + } else { lwz(tmp1, oopDesc::klass_offset_in_bytes(), obj1); lwz(tmp2, oopDesc::klass_offset_in_bytes(), obj2); cmpw(dst, tmp1, tmp2); - } else { - ld(tmp1, oopDesc::klass_offset_in_bytes(), obj1); - ld(tmp2, oopDesc::klass_offset_in_bytes(), obj2); - cmpd(dst, tmp1, tmp2); } } diff --git a/src/hotspot/cpu/ppc/matcher_ppc.hpp b/src/hotspot/cpu/ppc/matcher_ppc.hpp index 2ddbec3e48c..cbe882648b8 100644 --- a/src/hotspot/cpu/ppc/matcher_ppc.hpp +++ b/src/hotspot/cpu/ppc/matcher_ppc.hpp @@ -87,7 +87,6 @@ static bool narrow_klass_use_complex_address() { NOT_LP64(ShouldNotCallThis()); - assert(UseCompressedClassPointers, "only for compressed klass code"); // TODO: PPC port if (MatchDecodeNodes) return true; return false; } diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_arraycopy_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_arraycopy_riscv.cpp index 819d6c05654..58eb1a55553 100644 --- a/src/hotspot/cpu/riscv/c1_LIRAssembler_arraycopy_riscv.cpp +++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_arraycopy_riscv.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -196,12 +196,9 @@ void LIR_Assembler::arraycopy_type_check(Register src, Register src_pos, Registe if (UseCompactObjectHeaders) { __ load_narrow_klass_compact(tmp, src); __ load_narrow_klass_compact(t0, dst); - } else if (UseCompressedClassPointers) { + } else { __ lwu(tmp, Address(src, oopDesc::klass_offset_in_bytes())); __ lwu(t0, Address(dst, oopDesc::klass_offset_in_bytes())); - } else { - __ ld(tmp, Address(src, oopDesc::klass_offset_in_bytes())); - __ ld(t0, Address(dst, oopDesc::klass_offset_in_bytes())); } __ bne(tmp, t0, *stub->entry(), /* is_far */ true); } else { @@ -257,9 +254,7 @@ void LIR_Assembler::arraycopy_assert(Register src, Register dst, Register tmp, c // but not necessarily exactly of type default_type. Label known_ok, halt; __ mov_metadata(tmp, default_type->constant_encoding()); - if (UseCompressedClassPointers) { - __ encode_klass_not_null(tmp); - } + __ encode_klass_not_null(tmp); if (basic_type != T_OBJECT) { __ cmp_klass_compressed(dst, tmp, t0, halt, false); diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp index 63e2fd015d7..29e5d86d0cc 100644 --- a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. * Copyright (c) 2020, 2023, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -55,20 +55,6 @@ const Register SHIFT_count = x10; // where count for shift operations must be #define __ _masm-> -static void select_different_registers(Register preserve, - Register extra, - Register &tmp1, - Register &tmp2) { - if (tmp1 == preserve) { - assert_different_registers(tmp1, tmp2, extra); - tmp1 = extra; - } else if (tmp2 == preserve) { - assert_different_registers(tmp1, tmp2, extra); - tmp2 = extra; - } - assert_different_registers(preserve, tmp1, tmp2); -} - static void select_different_registers(Register preserve, Register extra, Register &tmp1, @@ -1155,12 +1141,8 @@ void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, L } else if (obj == klass_RInfo) { klass_RInfo = dst; } - if (k->is_loaded() && !UseCompressedClassPointers) { - select_different_registers(obj, dst, k_RInfo, klass_RInfo); - } else { - Rtmp1 = op->tmp3()->as_register(); - select_different_registers(obj, dst, k_RInfo, klass_RInfo, Rtmp1); - } + Rtmp1 = op->tmp3()->as_register(); + select_different_registers(obj, dst, k_RInfo, klass_RInfo, Rtmp1); assert_different_registers(obj, k_RInfo, klass_RInfo); diff --git a/src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp index 88565d9136f..f290708a231 100644 --- a/src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp +++ b/src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -1073,9 +1073,7 @@ void LIRGenerator::do_CheckCast(CheckCast* x) { } LIR_Opr reg = rlock_result(x); LIR_Opr tmp3 = LIR_OprFact::illegalOpr; - if (!x->klass()->is_loaded() || UseCompressedClassPointers) { - tmp3 = new_register(objectType); - } + tmp3 = new_register(objectType); __ checkcast(reg, obj.result(), x->klass(), new_register(objectType), new_register(objectType), tmp3, x->direct_compare(), info_for_exception, patching_info, stub, @@ -1094,9 +1092,7 @@ void LIRGenerator::do_InstanceOf(InstanceOf* x) { } obj.load_item(); LIR_Opr tmp3 = LIR_OprFact::illegalOpr; - if (!x->klass()->is_loaded() || UseCompressedClassPointers) { - tmp3 = new_register(objectType); - } + tmp3 = new_register(objectType); __ instanceof(reg, obj.result(), x->klass(), new_register(objectType), new_register(objectType), tmp3, x->direct_compare(), patching_info, x->profiled_method(), x->profiled_bci()); diff --git a/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp index aeb077ba0a0..abcc070b253 100644 --- a/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -92,12 +92,8 @@ void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register // This assumes that all prototype bits fitr in an int32_t mv(tmp1, checked_cast(markWord::prototype().value())); sd(tmp1, Address(obj, oopDesc::mark_offset_in_bytes())); - if (UseCompressedClassPointers) { // Take care not to kill klass - encode_klass_not_null(tmp1, klass, tmp2); - sw(tmp1, Address(obj, oopDesc::klass_offset_in_bytes())); - } else { - sd(klass, Address(obj, oopDesc::klass_offset_in_bytes())); - } + encode_klass_not_null(tmp1, klass, tmp2); + sw(tmp1, Address(obj, oopDesc::klass_offset_in_bytes())); } if (len->is_valid()) { @@ -108,7 +104,7 @@ void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register // Clear gap/first 4 bytes following the length field. sw(zr, Address(obj, base_offset)); } - } else if (UseCompressedClassPointers && !UseCompactObjectHeaders) { + } else if (!UseCompactObjectHeaders) { store_klass_gap(obj, zr); } } diff --git a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp index 72a90ddde1f..0d06fd469de 100644 --- a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp @@ -1175,8 +1175,7 @@ void C2_MacroAssembler::string_compare_long_same_encoding(Register result, Regis Label TAIL_CHECK, TAIL, NEXT_WORD, DIFFERENCE; const int base_offset = arrayOopDesc::base_offset_in_bytes(T_BYTE); - assert((base_offset % (UseCompactObjectHeaders ? 4 : - (UseCompressedClassPointers ? 8 : 4))) == 0, "Must be"); + assert((base_offset % (UseCompactObjectHeaders ? 4 : 8)) == 0, "Must be"); const int minCharsInWord = isLL ? wordSize : wordSize / 2; @@ -1269,8 +1268,7 @@ void C2_MacroAssembler::string_compare_long_different_encoding(Register result, Label TAIL, NEXT_WORD, DIFFERENCE; const int base_offset = arrayOopDesc::base_offset_in_bytes(T_BYTE); - assert((base_offset % (UseCompactObjectHeaders ? 4 : - (UseCompressedClassPointers ? 8 : 4))) == 0, "Must be"); + assert((base_offset % (UseCompactObjectHeaders ? 4 : 8)) == 0, "Must be"); Register strL = isLU ? str1 : str2; Register strU = isLU ? str2 : str1; @@ -1485,8 +1483,7 @@ void C2_MacroAssembler::arrays_equals(Register a1, Register a2, int length_offset = arrayOopDesc::length_offset_in_bytes(); int base_offset = arrayOopDesc::base_offset_in_bytes(elem_size == 2 ? T_CHAR : T_BYTE); - assert((base_offset % (UseCompactObjectHeaders ? 4 : - (UseCompressedClassPointers ? 8 : 4))) == 0, "Must be"); + assert((base_offset % (UseCompactObjectHeaders ? 4 : 8)) == 0, "Must be"); Register cnt1 = tmp3; Register cnt2 = tmp1; // cnt2 only used in array length compare @@ -1611,8 +1608,7 @@ void C2_MacroAssembler::string_equals(Register a1, Register a2, int base_offset = arrayOopDesc::base_offset_in_bytes(T_BYTE); - assert((base_offset % (UseCompactObjectHeaders ? 4 : - (UseCompressedClassPointers ? 8 : 4))) == 0, "Must be"); + assert((base_offset % (UseCompactObjectHeaders ? 4 : 8)) == 0, "Must be"); BLOCK_COMMENT("string_equals {"); @@ -2699,8 +2695,7 @@ void C2_MacroAssembler::arrays_equals_v(Register a1, Register a2, Register resul int length_offset = arrayOopDesc::length_offset_in_bytes(); int base_offset = arrayOopDesc::base_offset_in_bytes(elem_size == 2 ? T_CHAR : T_BYTE); - assert((base_offset % (UseCompactObjectHeaders ? 4 : - (UseCompressedClassPointers ? 8 : 4))) == 0, "Must be"); + assert((base_offset % (UseCompactObjectHeaders ? 4 : 8)) == 0, "Must be"); BLOCK_COMMENT("arrays_equals_v {"); diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp index 4f5e7afc166..b0305fa2977 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. * Copyright (c) 2020, 2024, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -3514,10 +3514,8 @@ void MacroAssembler::orptr(Address adr, RegisterOrConstant src, Register tmp1, R void MacroAssembler::cmp_klass_compressed(Register oop, Register trial_klass, Register tmp, Label &L, bool equal) { if (UseCompactObjectHeaders) { load_narrow_klass_compact(tmp, oop); - } else if (UseCompressedClassPointers) { - lwu(tmp, Address(oop, oopDesc::klass_offset_in_bytes())); } else { - ld(tmp, Address(oop, oopDesc::klass_offset_in_bytes())); + lwu(tmp, Address(oop, oopDesc::klass_offset_in_bytes())); } if (equal) { beq(trial_klass, tmp, L); @@ -3741,11 +3739,9 @@ void MacroAssembler::load_klass(Register dst, Register src, Register tmp) { if (UseCompactObjectHeaders) { load_narrow_klass_compact(dst, src); decode_klass_not_null(dst, tmp); - } else if (UseCompressedClassPointers) { + } else { lwu(dst, Address(src, oopDesc::klass_offset_in_bytes())); decode_klass_not_null(dst, tmp); - } else { - ld(dst, Address(src, oopDesc::klass_offset_in_bytes())); } } @@ -3753,20 +3749,15 @@ void MacroAssembler::store_klass(Register dst, Register src, Register tmp) { // FIXME: Should this be a store release? concurrent gcs assumes // klass length is valid if klass field is not null. assert(!UseCompactObjectHeaders, "not with compact headers"); - if (UseCompressedClassPointers) { - encode_klass_not_null(src, tmp); - sw(src, Address(dst, oopDesc::klass_offset_in_bytes())); - } else { - sd(src, Address(dst, oopDesc::klass_offset_in_bytes())); - } + encode_klass_not_null(src, tmp); + sw(src, Address(dst, oopDesc::klass_offset_in_bytes())); + } void MacroAssembler::store_klass_gap(Register dst, Register src) { assert(!UseCompactObjectHeaders, "not with compact headers"); - if (UseCompressedClassPointers) { - // Store to klass gap in destination - sw(src, Address(dst, oopDesc::klass_gap_offset_in_bytes())); - } + // Store to klass gap in destination + sw(src, Address(dst, oopDesc::klass_gap_offset_in_bytes())); } void MacroAssembler::decode_klass_not_null(Register r, Register tmp) { @@ -3775,7 +3766,6 @@ void MacroAssembler::decode_klass_not_null(Register r, Register tmp) { } void MacroAssembler::decode_klass_not_null(Register dst, Register src, Register tmp) { - assert(UseCompressedClassPointers, "should only be used for compressed headers"); assert_different_registers(dst, tmp); assert_different_registers(src, tmp); @@ -3806,8 +3796,6 @@ void MacroAssembler::encode_klass_not_null(Register r, Register tmp) { } void MacroAssembler::encode_klass_not_null(Register dst, Register src, Register tmp) { - assert(UseCompressedClassPointers, "should only be used for compressed headers"); - if (CompressedKlassPointers::base() == nullptr) { if (CompressedKlassPointers::shift() != 0) { srli(dst, src, CompressedKlassPointers::shift()); @@ -5337,7 +5325,6 @@ void MacroAssembler::set_narrow_oop(Register dst, jobject obj) { } void MacroAssembler::set_narrow_klass(Register dst, Klass* k) { - assert (UseCompressedClassPointers, "should only be used for compressed headers"); assert (oop_recorder() != nullptr, "this assembler needs an OopRecorder"); int index = oop_recorder()->find_index(k); @@ -5417,12 +5404,9 @@ int MacroAssembler::ic_check(int end_alignment) { if (UseCompactObjectHeaders) { load_narrow_klass_compact(tmp1, receiver); lwu(tmp2, Address(data, CompiledICData::speculated_klass_offset())); - } else if (UseCompressedClassPointers) { + } else { lwu(tmp1, Address(receiver, oopDesc::klass_offset_in_bytes())); lwu(tmp2, Address(data, CompiledICData::speculated_klass_offset())); - } else { - ld(tmp1, Address(receiver, oopDesc::klass_offset_in_bytes())); - ld(tmp2, Address(data, CompiledICData::speculated_klass_offset())); } Label ic_hit; diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad index 54c0d9c0955..e236d03e6d2 100644 --- a/src/hotspot/cpu/riscv/riscv.ad +++ b/src/hotspot/cpu/riscv/riscv.ad @@ -1801,13 +1801,8 @@ void MachUEPNode::format(PhaseRegAlloc* ra_, outputStream* st) const { assert_cond(st != nullptr); st->print_cr("# MachUEPNode"); - if (UseCompressedClassPointers) { - st->print_cr("\tlwu t1, [j_rarg0 + oopDesc::klass_offset_in_bytes()]\t# compressed klass"); - st->print_cr("\tlwu t2, [t0 + CompiledICData::speculated_klass_offset()]\t# compressed klass"); - } else { - st->print_cr("\tld t1, [j_rarg0 + oopDesc::klass_offset_in_bytes()]\t# compressed klass"); - st->print_cr("\tld t2, [t0 + CompiledICData::speculated_klass_offset()]\t# compressed klass"); - } + st->print_cr("\tlwu t1, [j_rarg0 + oopDesc::klass_offset_in_bytes()]\t# compressed klass"); + st->print_cr("\tlwu t2, [t0 + CompiledICData::speculated_klass_offset()]\t# compressed klass"); st->print_cr("\tbeq t1, t2, ic_hit"); st->print_cr("\tj, SharedRuntime::_ic_miss_stub\t # Inline cache check"); st->print_cr("\tic_hit:"); diff --git a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp index 127ac9f6951..964c6d98e9c 100644 --- a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp +++ b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2025, Red Hat Inc. All rights reserved. * Copyright (c) 2020, 2025, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -3070,8 +3070,7 @@ class StubGenerator: public StubCodeGenerator { const Register tmp = x30, tmpLval = x12; int base_offset = arrayOopDesc::base_offset_in_bytes(T_BYTE); - assert((base_offset % (UseCompactObjectHeaders ? 4 : - (UseCompressedClassPointers ? 8 : 4))) == 0, "Must be"); + assert((base_offset % (UseCompactObjectHeaders ? 4 : 8)) == 0, "Must be"); #ifdef ASSERT if (AvoidUnalignedAccesses) { @@ -3128,8 +3127,7 @@ class StubGenerator: public StubCodeGenerator { tmp1 = x28, tmp2 = x29, tmp3 = x30, tmp4 = x12; int base_offset = arrayOopDesc::base_offset_in_bytes(T_BYTE); - assert((base_offset % (UseCompactObjectHeaders ? 4 : - (UseCompressedClassPointers ? 8 : 4))) == 0, "Must be"); + assert((base_offset % (UseCompactObjectHeaders ? 4 : 8)) == 0, "Must be"); Register strU = isLU ? str2 : str1, strL = isLU ? str1 : str2, diff --git a/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp b/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp index 93d6051aa76..e1d8d062c23 100644 --- a/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp +++ b/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2024 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -2251,9 +2251,7 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) { // but not necessarily exactly of type default_type. NearLabel known_ok, halt; metadata2reg(default_type->constant_encoding(), tmp); - if (UseCompressedClassPointers) { - __ encode_klass_not_null(tmp); - } + __ encode_klass_not_null(tmp); if (basic_type != T_OBJECT) { __ cmp_klass(tmp, dst, Z_R1_scratch); @@ -2540,13 +2538,8 @@ void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, L // Get object class. // Not a safepoint as obj null check happens earlier. if (op->fast_check()) { - if (UseCompressedClassPointers) { - __ load_klass(klass_RInfo, obj); - __ compareU64_and_branch(k_RInfo, klass_RInfo, Assembler::bcondNotEqual, *failure_target); - } else { - __ z_cg(k_RInfo, Address(obj, oopDesc::klass_offset_in_bytes())); - __ branch_optimized(Assembler::bcondNotEqual, *failure_target); - } + __ load_klass(klass_RInfo, obj); + __ compareU64_and_branch(k_RInfo, klass_RInfo, Assembler::bcondNotEqual, *failure_target); // Successful cast, fall through to profile or jump. } else { bool need_slow_path = !k->is_loaded() || diff --git a/src/hotspot/cpu/s390/c1_MacroAssembler_s390.cpp b/src/hotspot/cpu/s390/c1_MacroAssembler_s390.cpp index 993c1a1b552..813143938f9 100644 --- a/src/hotspot/cpu/s390/c1_MacroAssembler_s390.cpp +++ b/src/hotspot/cpu/s390/c1_MacroAssembler_s390.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2024 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -107,10 +107,10 @@ void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register } if (len->is_valid()) { - // Length will be in the klass gap, if one exists. + // Length will be in the klass gap. z_st(len, Address(obj, arrayOopDesc::length_offset_in_bytes())); - } else if (UseCompressedClassPointers && !UseCompactObjectHeaders) { - store_klass_gap(Rzero, obj); // Zero klass gap for compressed oops. + } else if (!UseCompactObjectHeaders) { + store_klass_gap(Rzero, obj); // Zero klass gap. } } diff --git a/src/hotspot/cpu/s390/macroAssembler_s390.cpp b/src/hotspot/cpu/s390/macroAssembler_s390.cpp index 6e132f895bd..de3608e74ba 100644 --- a/src/hotspot/cpu/s390/macroAssembler_s390.cpp +++ b/src/hotspot/cpu/s390/macroAssembler_s390.cpp @@ -1237,7 +1237,6 @@ void MacroAssembler::load_narrow_oop(Register t, narrowOop a) { // Load narrow klass constant, compression required. void MacroAssembler::load_narrow_klass(Register t, Klass* k) { - assert(UseCompressedClassPointers, "must be on to call this method"); narrowKlass encoded_k = CompressedKlassPointers::encode(k); load_const_32to64(t, encoded_k, false /*sign_extend*/); } @@ -1255,7 +1254,6 @@ void MacroAssembler::compare_immediate_narrow_oop(Register oop1, narrowOop oop2) // Compare narrow oop in reg with narrow oop constant, no decompression. void MacroAssembler::compare_immediate_narrow_klass(Register klass1, Klass* klass2) { - assert(UseCompressedClassPointers, "must be on to call this method"); narrowKlass encoded_k = CompressedKlassPointers::encode(klass2); Assembler::z_clfi(klass1, encoded_k); @@ -1348,8 +1346,6 @@ int MacroAssembler::patch_load_narrow_oop(address pos, oop o) { // Patching the immediate value of CPU version dependent load_narrow_klass sequence. // The passed ptr must NOT be in compressed format! int MacroAssembler::patch_load_narrow_klass(address pos, Klass* k) { - assert(UseCompressedClassPointers, "Can only patch compressed klass pointers"); - narrowKlass nk = CompressedKlassPointers::encode(k); return patch_load_const_32to64(pos, nk); } @@ -1364,8 +1360,6 @@ int MacroAssembler::patch_compare_immediate_narrow_oop(address pos, oop o) { // Patching the immediate value of CPU version dependent compare_immediate_narrow_klass sequence. // The passed ptr must NOT be in compressed format! int MacroAssembler::patch_compare_immediate_narrow_klass(address pos, Klass* k) { - assert(UseCompressedClassPointers, "Can only patch compressed klass pointers"); - narrowKlass nk = CompressedKlassPointers::encode(k); return patch_compare_immediate_32(pos, nk); } @@ -2235,10 +2229,8 @@ int MacroAssembler::ic_check(int end_alignment) { if (UseCompactObjectHeaders) { load_narrow_klass_compact(R1_scratch, R2_receiver); - } else if (UseCompressedClassPointers) { - z_llgf(R1_scratch, Address(R2_receiver, oopDesc::klass_offset_in_bytes())); } else { - z_lg(R1_scratch, Address(R2_receiver, oopDesc::klass_offset_in_bytes())); + z_llgf(R1_scratch, Address(R2_receiver, oopDesc::klass_offset_in_bytes())); } z_cg(R1_scratch, Address(R9_data, in_bytes(CompiledICData::speculated_klass_offset()))); z_bre(success); @@ -3916,7 +3908,6 @@ void MacroAssembler::encode_klass_not_null(Register dst, Register src) { address base = CompressedKlassPointers::base(); int shift = CompressedKlassPointers::shift(); bool need_zero_extend = base != nullptr; - assert(UseCompressedClassPointers, "only for compressed klass ptrs"); BLOCK_COMMENT("cKlass encoder {"); @@ -4013,7 +4004,6 @@ int MacroAssembler::instr_size_for_decode_klass_not_null() { address base = CompressedKlassPointers::base(); int shift_size = CompressedKlassPointers::shift() == 0 ? 0 : 6; /* sllg */ int addbase_size = 0; - assert(UseCompressedClassPointers, "only for compressed klass ptrs"); if (base != nullptr) { unsigned int base_h = ((unsigned long)base)>>32; @@ -4043,7 +4033,6 @@ void MacroAssembler::decode_klass_not_null(Register dst) { address base = CompressedKlassPointers::base(); int shift = CompressedKlassPointers::shift(); int beg_off = offset(); - assert(UseCompressedClassPointers, "only for compressed klass ptrs"); BLOCK_COMMENT("cKlass decoder (const size) {"); @@ -4085,7 +4074,6 @@ void MacroAssembler::decode_klass_not_null(Register dst) { void MacroAssembler::decode_klass_not_null(Register dst, Register src) { address base = CompressedKlassPointers::base(); int shift = CompressedKlassPointers::shift(); - assert(UseCompressedClassPointers, "only for compressed klass ptrs"); BLOCK_COMMENT("cKlass decoder {"); @@ -4125,13 +4113,9 @@ void MacroAssembler::decode_klass_not_null(Register dst, Register src) { } void MacroAssembler::load_klass(Register klass, Address mem) { - if (UseCompressedClassPointers) { - z_llgf(klass, mem); - // Attention: no null check here! - decode_klass_not_null(klass); - } else { - z_lg(klass, mem); - } + z_llgf(klass, mem); + // Attention: no null check here! + decode_klass_not_null(klass); } // Loads the obj's Klass* into dst. @@ -4154,10 +4138,8 @@ void MacroAssembler::cmp_klass(Register klass, Register obj, Register tmp) { assert_different_registers(klass, obj, tmp); load_narrow_klass_compact(tmp, obj); z_cr(klass, tmp); - } else if (UseCompressedClassPointers) { - z_c(klass, Address(obj, oopDesc::klass_offset_in_bytes())); } else { - z_cg(klass, Address(obj, oopDesc::klass_offset_in_bytes())); + z_c(klass, Address(obj, oopDesc::klass_offset_in_bytes())); } BLOCK_COMMENT("} cmp_klass"); } @@ -4170,12 +4152,9 @@ void MacroAssembler::cmp_klasses_from_objects(Register obj1, Register obj2, Regi load_narrow_klass_compact(tmp1, obj1); load_narrow_klass_compact(tmp2, obj2); z_cr(tmp1, tmp2); - } else if (UseCompressedClassPointers) { + } else { z_l(tmp1, Address(obj1, oopDesc::klass_offset_in_bytes())); z_c(tmp1, Address(obj2, oopDesc::klass_offset_in_bytes())); - } else { - z_lg(tmp1, Address(obj1, oopDesc::klass_offset_in_bytes())); - z_cg(tmp1, Address(obj2, oopDesc::klass_offset_in_bytes())); } BLOCK_COMMENT("} cmp_klasses_from_objects"); } @@ -4184,36 +4163,28 @@ void MacroAssembler::load_klass(Register klass, Register src_oop) { if (UseCompactObjectHeaders) { load_narrow_klass_compact(klass, src_oop); decode_klass_not_null(klass); - } else if (UseCompressedClassPointers) { + } else { z_llgf(klass, oopDesc::klass_offset_in_bytes(), src_oop); decode_klass_not_null(klass); - } else { - z_lg(klass, oopDesc::klass_offset_in_bytes(), src_oop); } } void MacroAssembler::store_klass(Register klass, Register dst_oop, Register ck) { assert(!UseCompactObjectHeaders, "Don't use with compact headers"); - if (UseCompressedClassPointers) { - assert_different_registers(dst_oop, klass, Z_R0); - if (ck == noreg) ck = klass; - encode_klass_not_null(ck, klass); - z_st(ck, Address(dst_oop, oopDesc::klass_offset_in_bytes())); - } else { - z_stg(klass, Address(dst_oop, oopDesc::klass_offset_in_bytes())); - } + assert_different_registers(dst_oop, klass, Z_R0); + if (ck == noreg) ck = klass; + encode_klass_not_null(ck, klass); + z_st(ck, Address(dst_oop, oopDesc::klass_offset_in_bytes())); } void MacroAssembler::store_klass_gap(Register s, Register d) { assert(!UseCompactObjectHeaders, "Don't use with compact headers"); - if (UseCompressedClassPointers) { - assert(s != d, "not enough registers"); - // Support s = noreg. - if (s != noreg) { - z_st(s, Address(d, oopDesc::klass_gap_offset_in_bytes())); - } else { - z_mvhi(Address(d, oopDesc::klass_gap_offset_in_bytes()), 0); - } + assert(s != d, "not enough registers"); + // Support s = noreg. + if (s != noreg) { + z_st(s, Address(d, oopDesc::klass_gap_offset_in_bytes())); + } else { + z_mvhi(Address(d, oopDesc::klass_gap_offset_in_bytes()), 0); } } @@ -4227,67 +4198,64 @@ void MacroAssembler::compare_klass_ptr(Register Rop1, int64_t disp, Register Rba BLOCK_COMMENT("compare klass ptr {"); - if (UseCompressedClassPointers) { - const int shift = CompressedKlassPointers::shift(); - address base = CompressedKlassPointers::base(); + const int shift = CompressedKlassPointers::shift(); + address base = CompressedKlassPointers::base(); + + if (UseCompactObjectHeaders) { + assert(shift >= 3, "cKlass encoder detected bad shift"); + } else { + assert((shift == 0) || (shift == 3), "cKlass encoder detected bad shift"); + } + assert_different_registers(Rop1, Z_R0); + assert_different_registers(Rop1, Rbase, Z_R1); - if (UseCompactObjectHeaders) { - assert(shift >= 3, "cKlass encoder detected bad shift"); + // First encode register oop and then compare with cOop in memory. + // This sequence saves an unnecessary cOop load and decode. + if (base == nullptr) { + if (shift == 0) { + z_cl(Rop1, disp, Rbase); // Unscaled } else { - assert((shift == 0) || (shift == 3), "cKlass encoder detected bad shift"); + z_srlg(Z_R0, Rop1, shift); // ZeroBased + z_cl(Z_R0, disp, Rbase); } - assert_different_registers(Rop1, Z_R0); - assert_different_registers(Rop1, Rbase, Z_R1); - - // First encode register oop and then compare with cOop in memory. - // This sequence saves an unnecessary cOop load and decode. - if (base == nullptr) { - if (shift == 0) { - z_cl(Rop1, disp, Rbase); // Unscaled - } else { - z_srlg(Z_R0, Rop1, shift); // ZeroBased - z_cl(Z_R0, disp, Rbase); - } - } else { // HeapBased + } else { // HeapBased #ifdef ASSERT - bool used_R0 = true; - bool used_R1 = true; + bool used_R0 = true; + bool used_R1 = true; #endif - Register current = Rop1; - Label done; + Register current = Rop1; + Label done; - if (maybenull) { // null pointer must be preserved! - z_ltgr(Z_R0, current); - z_bre(done); - current = Z_R0; - } + if (maybenull) { // null pointer must be preserved! + z_ltgr(Z_R0, current); + z_bre(done); + current = Z_R0; + } - unsigned int base_h = ((unsigned long)base)>>32; - unsigned int base_l = (unsigned int)((unsigned long)base); - if ((base_h != 0) && (base_l == 0) && VM_Version::has_HighWordInstr()) { - lgr_if_needed(Z_R0, current); - z_aih(Z_R0, -((int)base_h)); // Base has no set bits in lower half. - } else if ((base_h == 0) && (base_l != 0)) { - lgr_if_needed(Z_R0, current); - z_agfi(Z_R0, -(int)base_l); - } else { - int pow2_offset = get_oop_base_complement(Z_R1, ((uint64_t)(intptr_t)base)); - add2reg_with_index(Z_R0, pow2_offset, Z_R1, Rop1); // Subtract base by adding complement. - } + unsigned int base_h = ((unsigned long)base)>>32; + unsigned int base_l = (unsigned int)((unsigned long)base); + if ((base_h != 0) && (base_l == 0) && VM_Version::has_HighWordInstr()) { + lgr_if_needed(Z_R0, current); + z_aih(Z_R0, -((int)base_h)); // Base has no set bits in lower half. + } else if ((base_h == 0) && (base_l != 0)) { + lgr_if_needed(Z_R0, current); + z_agfi(Z_R0, -(int)base_l); + } else { + int pow2_offset = get_oop_base_complement(Z_R1, ((uint64_t)(intptr_t)base)); + add2reg_with_index(Z_R0, pow2_offset, Z_R1, Rop1); // Subtract base by adding complement. + } - if (shift != 0) { - z_srlg(Z_R0, Z_R0, shift); - } - bind(done); - z_cl(Z_R0, disp, Rbase); + if (shift != 0) { + z_srlg(Z_R0, Z_R0, shift); + } + bind(done); + z_cl(Z_R0, disp, Rbase); #ifdef ASSERT - if (used_R0) preset_reg(Z_R0, 0xb05bUL, 2); - if (used_R1) preset_reg(Z_R1, 0xb06bUL, 2); + if (used_R0) preset_reg(Z_R0, 0xb05bUL, 2); + if (used_R1) preset_reg(Z_R1, 0xb06bUL, 2); #endif - } - } else { - z_clg(Rop1, disp, Z_R0, Rbase); } + BLOCK_COMMENT("} compare klass ptr"); } diff --git a/src/hotspot/cpu/s390/macroAssembler_s390.hpp b/src/hotspot/cpu/s390/macroAssembler_s390.hpp index da24ae80d45..32e484d4790 100644 --- a/src/hotspot/cpu/s390/macroAssembler_s390.hpp +++ b/src/hotspot/cpu/s390/macroAssembler_s390.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2024 SAP SE. All rights reserved. * Copyright (c) 2024 IBM Corporation. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -842,8 +842,7 @@ class MacroAssembler: public Assembler { void store_klass(Register klass, Register dst_oop, Register ck = noreg); // Klass will get compressed if ck not provided. void store_klass_gap(Register s, Register dst_oop); void load_narrow_klass_compact(Register dst, Register src); - // Compares the Klass pointer of an object to a given Klass (which might be narrow, - // depending on UseCompressedClassPointers). + // Compares the narrow Klass pointer of an object to a given narrow Klass void cmp_klass(Register klass, Register obj, Register tmp); // Compares the Klass pointer of two objects obj1 and obj2. Result is in the condition flags. // Uses tmp1 and tmp2 as temporary registers. diff --git a/src/hotspot/cpu/s390/matcher_s390.hpp b/src/hotspot/cpu/s390/matcher_s390.hpp index 99461e33e3c..b04a6566d41 100644 --- a/src/hotspot/cpu/s390/matcher_s390.hpp +++ b/src/hotspot/cpu/s390/matcher_s390.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2017, 2024 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -82,7 +82,6 @@ static bool narrow_klass_use_complex_address() { NOT_LP64(ShouldNotCallThis()); - assert(UseCompressedClassPointers, "only for compressed klass code"); // TODO HS25: z port if (MatchDecodeNodes) return true; return false; } diff --git a/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp b/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp index d9be0fdcc8d..5397a230642 100644 --- a/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -77,23 +77,6 @@ const Register SHIFT_count = rcx; // where count for shift operations must be #define __ _masm-> - -static void select_different_registers(Register preserve, - Register extra, - Register &tmp1, - Register &tmp2) { - if (tmp1 == preserve) { - assert_different_registers(tmp1, tmp2, extra); - tmp1 = extra; - } else if (tmp2 == preserve) { - assert_different_registers(tmp1, tmp2, extra); - tmp2 = extra; - } - assert_different_registers(preserve, tmp1, tmp2); -} - - - static void select_different_registers(Register preserve, Register extra, Register &tmp1, @@ -1309,12 +1292,8 @@ void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, L } else if (obj == klass_RInfo) { klass_RInfo = dst; } - if (k->is_loaded() && !UseCompressedClassPointers) { - select_different_registers(obj, dst, k_RInfo, klass_RInfo); - } else { - Rtmp1 = op->tmp3()->as_register(); - select_different_registers(obj, dst, k_RInfo, klass_RInfo, Rtmp1); - } + Rtmp1 = op->tmp3()->as_register(); + select_different_registers(obj, dst, k_RInfo, klass_RInfo, Rtmp1); assert_different_registers(obj, k_RInfo, klass_RInfo); @@ -1348,12 +1327,8 @@ void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, L if (op->fast_check()) { // get object class // not a safepoint as obj null check happens earlier - if (UseCompressedClassPointers) { - __ load_klass(Rtmp1, obj, tmp_load_klass); - __ cmpptr(k_RInfo, Rtmp1); - } else { - __ cmpptr(k_RInfo, Address(obj, oopDesc::klass_offset_in_bytes())); - } + __ load_klass(Rtmp1, obj, tmp_load_klass); + __ cmpptr(k_RInfo, Rtmp1); __ jcc(Assembler::notEqual, *failure_target); // successful cast, fall through to profile or jump } else { @@ -2651,9 +2626,7 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) { // but not necessarily exactly of type default_type. Label known_ok, halt; __ mov_metadata(tmp, default_type->constant_encoding()); - if (UseCompressedClassPointers) { - __ encode_klass_not_null(tmp, rscratch1); - } + __ encode_klass_not_null(tmp, rscratch1); if (basic_type != T_OBJECT) { __ cmp_klass(tmp, dst, tmp2); diff --git a/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp b/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp index 5459e8df229..f448e4ee17f 100644 --- a/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp +++ b/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1291,9 +1291,7 @@ void LIRGenerator::do_CheckCast(CheckCast* x) { } LIR_Opr reg = rlock_result(x); LIR_Opr tmp3 = LIR_OprFact::illegalOpr; - if (!x->klass()->is_loaded() || UseCompressedClassPointers) { - tmp3 = new_register(objectType); - } + tmp3 = new_register(objectType); __ checkcast(reg, obj.result(), x->klass(), new_register(objectType), new_register(objectType), tmp3, x->direct_compare(), info_for_exception, patching_info, stub, @@ -1313,9 +1311,7 @@ void LIRGenerator::do_InstanceOf(InstanceOf* x) { } obj.load_item(); LIR_Opr tmp3 = LIR_OprFact::illegalOpr; - if (!x->klass()->is_loaded() || UseCompressedClassPointers) { - tmp3 = new_register(objectType); - } + tmp3 = new_register(objectType); __ instanceof(reg, obj.result(), x->klass(), new_register(objectType), new_register(objectType), tmp3, x->direct_compare(), patching_info, x->profiled_method(), x->profiled_bci()); diff --git a/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp b/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp index 88e2e6c8ba9..7adaea48ff1 100644 --- a/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -85,14 +85,11 @@ void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register if (UseCompactObjectHeaders) { movptr(t1, Address(klass, Klass::prototype_header_offset())); movptr(Address(obj, oopDesc::mark_offset_in_bytes()), t1); - } else if (UseCompressedClassPointers) { // Take care not to kill klass + } else { // Take care not to kill klass movptr(Address(obj, oopDesc::mark_offset_in_bytes()), checked_cast(markWord::prototype().value())); movptr(t1, klass); encode_klass_not_null(t1, rscratch1); movl(Address(obj, oopDesc::klass_offset_in_bytes()), t1); - } else { - movptr(Address(obj, oopDesc::mark_offset_in_bytes()), checked_cast(markWord::prototype().value())); - movptr(Address(obj, oopDesc::klass_offset_in_bytes()), klass); } if (len->is_valid()) { @@ -104,7 +101,7 @@ void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register xorl(t1, t1); movl(Address(obj, base_offset), t1); } - } else if (UseCompressedClassPointers && !UseCompactObjectHeaders) { + } else if (!UseCompactObjectHeaders) { xorptr(t1, t1); store_klass_gap(obj, t1); } diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.cpp b/src/hotspot/cpu/x86/macroAssembler_x86.cpp index 1d77be26bd9..a0f08145d55 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp @@ -985,12 +985,9 @@ int MacroAssembler::ic_check(int end_alignment) { if (UseCompactObjectHeaders) { load_narrow_klass_compact(temp, receiver); cmpl(temp, Address(data, CompiledICData::speculated_klass_offset())); - } else if (UseCompressedClassPointers) { + } else { movl(temp, Address(receiver, oopDesc::klass_offset_in_bytes())); cmpl(temp, Address(data, CompiledICData::speculated_klass_offset())); - } else { - movptr(temp, Address(receiver, oopDesc::klass_offset_in_bytes())); - cmpptr(temp, Address(data, CompiledICData::speculated_klass_offset())); } // if inline cache check fails, then jump to runtime routine @@ -5384,11 +5381,9 @@ void MacroAssembler::load_klass(Register dst, Register src, Register tmp) { if (UseCompactObjectHeaders) { load_narrow_klass_compact(dst, src); decode_klass_not_null(dst, tmp); - } else if (UseCompressedClassPointers) { + } else { movl(dst, Address(src, oopDesc::klass_offset_in_bytes())); decode_klass_not_null(dst, tmp); - } else { - movptr(dst, Address(src, oopDesc::klass_offset_in_bytes())); } } @@ -5396,12 +5391,8 @@ void MacroAssembler::store_klass(Register dst, Register src, Register tmp) { assert(!UseCompactObjectHeaders, "not with compact headers"); assert_different_registers(src, tmp); assert_different_registers(dst, tmp); - if (UseCompressedClassPointers) { - encode_klass_not_null(src, tmp); - movl(Address(dst, oopDesc::klass_offset_in_bytes()), src); - } else { - movptr(Address(dst, oopDesc::klass_offset_in_bytes()), src); - } + encode_klass_not_null(src, tmp); + movl(Address(dst, oopDesc::klass_offset_in_bytes()), src); } void MacroAssembler::cmp_klass(Register klass, Register obj, Register tmp) { @@ -5410,10 +5401,8 @@ void MacroAssembler::cmp_klass(Register klass, Register obj, Register tmp) { assert_different_registers(klass, obj, tmp); load_narrow_klass_compact(tmp, obj); cmpl(klass, tmp); - } else if (UseCompressedClassPointers) { - cmpl(klass, Address(obj, oopDesc::klass_offset_in_bytes())); } else { - cmpptr(klass, Address(obj, oopDesc::klass_offset_in_bytes())); + cmpl(klass, Address(obj, oopDesc::klass_offset_in_bytes())); } } @@ -5424,12 +5413,9 @@ void MacroAssembler::cmp_klasses_from_objects(Register obj1, Register obj2, Regi load_narrow_klass_compact(tmp1, obj1); load_narrow_klass_compact(tmp2, obj2); cmpl(tmp1, tmp2); - } else if (UseCompressedClassPointers) { + } else { movl(tmp1, Address(obj1, oopDesc::klass_offset_in_bytes())); cmpl(tmp1, Address(obj2, oopDesc::klass_offset_in_bytes())); - } else { - movptr(tmp1, Address(obj1, oopDesc::klass_offset_in_bytes())); - cmpptr(tmp1, Address(obj2, oopDesc::klass_offset_in_bytes())); } } @@ -5478,10 +5464,8 @@ void MacroAssembler::store_heap_oop_null(Address dst) { void MacroAssembler::store_klass_gap(Register dst, Register src) { assert(!UseCompactObjectHeaders, "Don't use with compact headers"); - if (UseCompressedClassPointers) { - // Store to klass gap in destination - movl(Address(dst, oopDesc::klass_gap_offset_in_bytes()), src); - } + // Store to klass gap in destination + movl(Address(dst, oopDesc::klass_gap_offset_in_bytes()), src); } #ifdef ASSERT @@ -5671,7 +5655,6 @@ void MacroAssembler::decode_klass_not_null(Register r, Register tmp) { BLOCK_COMMENT("decode_klass_not_null {"); assert_different_registers(r, tmp); // Note: it will change flags - assert(UseCompressedClassPointers, "should only be used for compressed headers"); // Cannot assert, unverified entry point counts instructions (see .ad file) // vtableStubs also counts instructions in pd_code_size_limit. // Also do not verify_oop as this is called by verify_oop. @@ -5693,7 +5676,6 @@ void MacroAssembler::decode_and_move_klass_not_null(Register dst, Register src) BLOCK_COMMENT("decode_and_move_klass_not_null {"); assert_different_registers(src, dst); // Note: it will change flags - assert (UseCompressedClassPointers, "should only be used for compressed headers"); // Cannot assert, unverified entry point counts instructions (see .ad file) // vtableStubs also counts instructions in pd_code_size_limit. // Also do not verify_oop as this is called by verify_oop. @@ -5750,7 +5732,6 @@ void MacroAssembler::set_narrow_oop(Address dst, jobject obj) { } void MacroAssembler::set_narrow_klass(Register dst, Klass* k) { - assert (UseCompressedClassPointers, "should only be used for compressed headers"); assert (oop_recorder() != nullptr, "this assembler needs an OopRecorder"); int klass_index = oop_recorder()->find_index(k); RelocationHolder rspec = metadata_Relocation::spec(klass_index); @@ -5758,7 +5739,6 @@ void MacroAssembler::set_narrow_klass(Register dst, Klass* k) { } void MacroAssembler::set_narrow_klass(Address dst, Klass* k) { - assert (UseCompressedClassPointers, "should only be used for compressed headers"); assert (oop_recorder() != nullptr, "this assembler needs an OopRecorder"); int klass_index = oop_recorder()->find_index(k); RelocationHolder rspec = metadata_Relocation::spec(klass_index); @@ -5784,7 +5764,6 @@ void MacroAssembler::cmp_narrow_oop(Address dst, jobject obj) { } void MacroAssembler::cmp_narrow_klass(Register dst, Klass* k) { - assert (UseCompressedClassPointers, "should only be used for compressed headers"); assert (oop_recorder() != nullptr, "this assembler needs an OopRecorder"); int klass_index = oop_recorder()->find_index(k); RelocationHolder rspec = metadata_Relocation::spec(klass_index); @@ -5792,7 +5771,6 @@ void MacroAssembler::cmp_narrow_klass(Register dst, Klass* k) { } void MacroAssembler::cmp_narrow_klass(Address dst, Klass* k) { - assert (UseCompressedClassPointers, "should only be used for compressed headers"); assert (oop_recorder() != nullptr, "this assembler needs an OopRecorder"); int klass_index = oop_recorder()->find_index(k); RelocationHolder rspec = metadata_Relocation::spec(klass_index); diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.hpp b/src/hotspot/cpu/x86/macroAssembler_x86.hpp index 8469deaa8be..3bdd1e4477a 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.hpp @@ -351,8 +351,7 @@ class MacroAssembler: public Assembler { void load_klass(Register dst, Register src, Register tmp); void store_klass(Register dst, Register src, Register tmp); - // Compares the Klass pointer of an object to a given Klass (which might be narrow, - // depending on UseCompressedClassPointers). + // Compares the narrow Klass pointer of an object to a given narrow Klass. void cmp_klass(Register klass, Register obj, Register tmp); // Compares the Klass pointer of two objects obj1 and obj2. Result is in the condition flags. diff --git a/src/hotspot/cpu/x86/matcher_x86.hpp b/src/hotspot/cpu/x86/matcher_x86.hpp index f7973a8564e..62a5d2827bc 100644 --- a/src/hotspot/cpu/x86/matcher_x86.hpp +++ b/src/hotspot/cpu/x86/matcher_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -75,7 +75,6 @@ } static bool narrow_klass_use_complex_address() { - assert(UseCompressedClassPointers, "only for compressed klass code"); return (CompressedKlassPointers::shift() <= 3); } diff --git a/src/hotspot/cpu/x86/x86.ad b/src/hotspot/cpu/x86/x86.ad index 2fd4e5516fc..f31d64f3d7e 100644 --- a/src/hotspot/cpu/x86/x86.ad +++ b/src/hotspot/cpu/x86/x86.ad @@ -2605,13 +2605,8 @@ uint BoxLockNode::size(PhaseRegAlloc *ra_) const #ifndef PRODUCT void MachUEPNode::format(PhaseRegAlloc* ra_, outputStream* st) const { - if (UseCompressedClassPointers) { - st->print_cr("movl rscratch1, [j_rarg0 + oopDesc::klass_offset_in_bytes()]\t# compressed klass"); - st->print_cr("\tcmpl rscratch1, [rax + CompiledICData::speculated_klass_offset()]\t # Inline cache check"); - } else { - st->print_cr("movq rscratch1, [j_rarg0 + oopDesc::klass_offset_in_bytes()]\t# compressed klass"); - st->print_cr("\tcmpq rscratch1, [rax + CompiledICData::speculated_klass_offset()]\t # Inline cache check"); - } + st->print_cr("movl rscratch1, [j_rarg0 + oopDesc::klass_offset_in_bytes()]\t# compressed klass"); + st->print_cr("\tcmpl rscratch1, [rax + CompiledICData::speculated_klass_offset()]\t # Inline cache check"); st->print_cr("\tjne SharedRuntime::_ic_miss_stub"); } #endif diff --git a/src/hotspot/share/cds/aotMapLogger.cpp b/src/hotspot/share/cds/aotMapLogger.cpp index 98336ff9b1f..9f338826fd6 100644 --- a/src/hotspot/share/cds/aotMapLogger.cpp +++ b/src/hotspot/share/cds/aotMapLogger.cpp @@ -589,7 +589,6 @@ class AOTMapLogger::FakeOop { } Klass* real_klass() { - assert(UseCompressedClassPointers, "heap archiving requires UseCompressedClassPointers"); return _data._klass; } diff --git a/src/hotspot/share/cds/aotMappedHeapLoader.hpp b/src/hotspot/share/cds/aotMappedHeapLoader.hpp index 7c5ca1b1f9e..10f5ce3124f 100644 --- a/src/hotspot/share/cds/aotMappedHeapLoader.hpp +++ b/src/hotspot/share/cds/aotMappedHeapLoader.hpp @@ -54,7 +54,7 @@ class AOTMappedHeapLoader : AllStatic { // Can this VM map archived heap region? Currently only G1+compressed{oops,cp} static bool can_map() { - CDS_JAVA_HEAP_ONLY(return (UseG1GC && UseCompressedClassPointers);) + CDS_JAVA_HEAP_ONLY(return UseG1GC;) NOT_CDS_JAVA_HEAP(return false;) } diff --git a/src/hotspot/share/cds/aotMappedHeapWriter.cpp b/src/hotspot/share/cds/aotMappedHeapWriter.cpp index 3456c845938..8f810ef5244 100644 --- a/src/hotspot/share/cds/aotMappedHeapWriter.cpp +++ b/src/hotspot/share/cds/aotMappedHeapWriter.cpp @@ -450,7 +450,6 @@ int AOTMappedHeapWriter::filler_array_length(size_t fill_bytes) { } HeapWord* AOTMappedHeapWriter::init_filler_array_at_buffer_top(int array_length, size_t fill_bytes) { - assert(UseCompressedClassPointers, "Archived heap only supported for compressed klasses"); Klass* oak = Universe::objectArrayKlass(); // already relocated to point to archived klass HeapWord* mem = offset_to_buffered_address(_buffer_used); memset(mem, 0, fill_bytes); @@ -724,7 +723,6 @@ template void AOTMappedHeapWriter::mark_oop_pointer(T* buffered_add } void AOTMappedHeapWriter::update_header_for_requested_obj(oop requested_obj, oop src_obj, Klass* src_klass) { - assert(UseCompressedClassPointers, "Archived heap only supported for compressed klasses"); narrowKlass nk = ArchiveBuilder::current()->get_requested_narrow_klass(src_klass); address buffered_addr = requested_addr_to_buffered_addr(cast_from_oop
(requested_obj)); diff --git a/src/hotspot/share/cds/aotMetaspace.cpp b/src/hotspot/share/cds/aotMetaspace.cpp index 76c37194882..55e9f93b3ab 100644 --- a/src/hotspot/share/cds/aotMetaspace.cpp +++ b/src/hotspot/share/cds/aotMetaspace.cpp @@ -250,9 +250,9 @@ static bool shared_base_too_high(char* specified_base, char* aligned_base, size_ static char* compute_shared_base(size_t cds_max) { char* specified_base = (char*)SharedBaseAddress; size_t alignment = AOTMetaspace::core_region_alignment(); - if (UseCompressedClassPointers && CompressedKlassPointers::needs_class_space()) { - alignment = MAX2(alignment, Metaspace::reserve_alignment()); - } +#if INCLUDE_CLASS_SPACE + alignment = MAX2(alignment, Metaspace::reserve_alignment()); +#endif if (SharedBaseAddress == 0) { // Special meaning of -XX:SharedBaseAddress=0 -> Always map archive at os-selected address. @@ -1637,32 +1637,29 @@ MapArchiveResult AOTMetaspace::map_archives(FileMapInfo* static_mapinfo, FileMap aot_log_debug(aot)("Failed to reserve spaces (use_requested_addr=%u)", (unsigned)use_requested_addr); } else { - if (Metaspace::using_class_space()) { - prot_zone_size = protection_zone_size(); - } + CLASS_SPACE_ONLY(prot_zone_size = protection_zone_size();) -#ifdef ASSERT // Some sanity checks after reserving address spaces for archives // and class space. assert(archive_space_rs.is_reserved(), "Sanity"); - if (Metaspace::using_class_space()) { - assert(archive_space_rs.base() == mapped_base_address && - archive_space_rs.size() > protection_zone_size(), - "Archive space must lead and include the protection zone"); - // Class space must closely follow the archive space. Both spaces - // must be aligned correctly. - assert(class_space_rs.is_reserved() && class_space_rs.size() > 0, - "A class space should have been reserved"); - assert(class_space_rs.base() >= archive_space_rs.end(), - "class space should follow the cds archive space"); - assert(is_aligned(archive_space_rs.base(), - core_region_alignment()), - "Archive space misaligned"); - assert(is_aligned(class_space_rs.base(), - Metaspace::reserve_alignment()), - "class space misaligned"); - } -#endif // ASSERT + +#if INCLUDE_CLASS_SPACE + assert(archive_space_rs.base() == mapped_base_address && + archive_space_rs.size() > protection_zone_size(), + "Archive space must lead and include the protection zone"); + // Class space must closely follow the archive space. Both spaces + // must be aligned correctly. + assert(class_space_rs.is_reserved() && class_space_rs.size() > 0, + "A class space should have been reserved"); + assert(class_space_rs.base() >= archive_space_rs.end(), + "class space should follow the cds archive space"); + assert(is_aligned(archive_space_rs.base(), + core_region_alignment()), + "Archive space misaligned"); + assert(is_aligned(class_space_rs.base(), + Metaspace::reserve_alignment()), + "class space misaligned"); +#endif // INCLUDE_CLASS_SPACE aot_log_info(aot)("Reserved archive_space_rs [" INTPTR_FORMAT " - " INTPTR_FORMAT "] (%zu) bytes%s", p2i(archive_space_rs.base()), p2i(archive_space_rs.end()), archive_space_rs.size(), @@ -1764,62 +1761,60 @@ MapArchiveResult AOTMetaspace::map_archives(FileMapInfo* static_mapinfo, FileMap if (result == MAP_ARCHIVE_SUCCESS) { SharedBaseAddress = (size_t)mapped_base_address; -#ifdef _LP64 - if (Metaspace::using_class_space()) { - assert(prot_zone_size > 0 && - *(mapped_base_address) == 'P' && - *(mapped_base_address + prot_zone_size - 1) == 'P', - "Protection zone was overwritten?"); - // Set up ccs in metaspace. - Metaspace::initialize_class_space(class_space_rs); - - // Set up compressed Klass pointer encoding: the encoding range must - // cover both archive and class space. - const address klass_range_start = (address)mapped_base_address; - const size_t klass_range_size = (address)class_space_rs.end() - klass_range_start; - if (INCLUDE_CDS_JAVA_HEAP || UseCompactObjectHeaders) { - // The CDS archive may contain narrow Klass IDs that were precomputed at archive generation time: - // - every archived java object header (only if INCLUDE_CDS_JAVA_HEAP) - // - every archived Klass' prototype (only if +UseCompactObjectHeaders) - // - // In order for those IDs to still be valid, we need to dictate base and shift: base should be the - // mapping start (including protection zone), shift should be the shift used at archive generation time. - CompressedKlassPointers::initialize_for_given_encoding( - klass_range_start, klass_range_size, - klass_range_start, ArchiveBuilder::precomputed_narrow_klass_shift() // precomputed encoding, see ArchiveBuilder - ); - assert(CompressedKlassPointers::base() == klass_range_start, "must be"); +#if INCLUDE_CLASS_SPACE + assert(prot_zone_size > 0 && + *(mapped_base_address) == 'P' && + *(mapped_base_address + prot_zone_size - 1) == 'P', + "Protection zone was overwritten?"); + // Set up ccs in metaspace. + Metaspace::initialize_class_space(class_space_rs); + + // Set up compressed Klass pointer encoding: the encoding range must + // cover both archive and class space. + const address klass_range_start = (address)mapped_base_address; + const size_t klass_range_size = (address)class_space_rs.end() - klass_range_start; + if (INCLUDE_CDS_JAVA_HEAP || UseCompactObjectHeaders) { + // The CDS archive may contain narrow Klass IDs that were precomputed at archive generation time: + // - every archived java object header (only if INCLUDE_CDS_JAVA_HEAP) + // - every archived Klass' prototype (only if +UseCompactObjectHeaders) + // + // In order for those IDs to still be valid, we need to dictate base and shift: base should be the + // mapping start (including protection zone), shift should be the shift used at archive generation time. + CompressedKlassPointers::initialize_for_given_encoding( + klass_range_start, klass_range_size, + klass_range_start, ArchiveBuilder::precomputed_narrow_klass_shift() // precomputed encoding, see ArchiveBuilder + ); + assert(CompressedKlassPointers::base() == klass_range_start, "must be"); + } else { + // Let JVM freely choose encoding base and shift + CompressedKlassPointers::initialize(klass_range_start, klass_range_size); + assert(CompressedKlassPointers::base() == nullptr || + CompressedKlassPointers::base() == klass_range_start, "must be"); + } + // Establish protection zone, but only if we need one + if (CompressedKlassPointers::base() == klass_range_start) { + CompressedKlassPointers::establish_protection_zone(klass_range_start, prot_zone_size); + } + + if (static_mapinfo->can_use_heap_region()) { + if (static_mapinfo->object_streaming_mode()) { + HeapShared::initialize_loading_mode(HeapArchiveMode::_streaming); } else { - // Let JVM freely choose encoding base and shift - CompressedKlassPointers::initialize(klass_range_start, klass_range_size); - assert(CompressedKlassPointers::base() == nullptr || - CompressedKlassPointers::base() == klass_range_start, "must be"); + // map_or_load_heap_region() compares the current narrow oop and klass encodings + // with the archived ones, so it must be done after all encodings are determined. + static_mapinfo->map_or_load_heap_region(); + HeapShared::initialize_loading_mode(HeapArchiveMode::_mapping); } - // Establish protection zone, but only if we need one - if (CompressedKlassPointers::base() == klass_range_start) { - CompressedKlassPointers::establish_protection_zone(klass_range_start, prot_zone_size); + } else { + FileMapRegion* r = static_mapinfo->region_at(AOTMetaspace::hp); + if (r->used() > 0) { + AOTMetaspace::report_loading_error("Cannot use CDS heap data."); } - - if (static_mapinfo->can_use_heap_region()) { - if (static_mapinfo->object_streaming_mode()) { - HeapShared::initialize_loading_mode(HeapArchiveMode::_streaming); - } else { - // map_or_load_heap_region() compares the current narrow oop and klass encodings - // with the archived ones, so it must be done after all encodings are determined. - static_mapinfo->map_or_load_heap_region(); - HeapShared::initialize_loading_mode(HeapArchiveMode::_mapping); - } - } else { - FileMapRegion* r = static_mapinfo->region_at(AOTMetaspace::hp); - if (r->used() > 0) { - AOTMetaspace::report_loading_error("Cannot use CDS heap data."); - } - if (!CDSConfig::is_dumping_static_archive()) { - CDSConfig::stop_using_full_module_graph("No CDS heap data"); - } + if (!CDSConfig::is_dumping_static_archive()) { + CDSConfig::stop_using_full_module_graph("No CDS heap data"); } } -#endif // _LP64 +#endif // INCLUDE_CLASS_SPACE log_info(aot)("initial optimized module handling: %s", CDSConfig::is_using_optimized_module_handling() ? "enabled" : "disabled"); log_info(aot)("initial full module graph: %s", CDSConfig::is_using_full_module_graph() ? "enabled" : "disabled"); } else { @@ -1852,8 +1847,13 @@ MapArchiveResult AOTMetaspace::map_archives(FileMapInfo* static_mapinfo, FileMap // (The gap may result from different alignment requirements between metaspace // and CDS) // -// If UseCompressedClassPointers is disabled, only one address space will be -// reserved: +// The range encompassing both spaces will be suitable to en/decode narrow Klass +// pointers: the base will be valid for encoding the range [Base, End) and not +// surpass the max. range for that encoding. +// +// On 32-bit, a "narrow" Klass is just the pointer itself, and the Klass encoding +// range encompasses the whole address range. Consequently, we can "decode" and +// "encode" any pointer anywhere, and so are free to place the CDS archive anywhere: // // +-- Base address End // | | @@ -1867,27 +1867,21 @@ MapArchiveResult AOTMetaspace::map_archives(FileMapInfo* static_mapinfo, FileMap // use_archive_base_addr address is false, this base address is determined // by the platform. // -// If UseCompressedClassPointers=1, the range encompassing both spaces will be -// suitable to en/decode narrow Klass pointers: the base will be valid for -// encoding, the range [Base, End) and not surpass the max. range for that encoding. -// // Return: // // - On success: // - total_space_rs will be reserved as whole for archive_space_rs and -// class_space_rs if UseCompressedClassPointers is true. +// class_space_rs on 64-bit. // On Windows, try reserve archive_space_rs and class_space_rs // separately first if use_archive_base_addr is true. // - archive_space_rs will be reserved and large enough to host static and // if needed dynamic archive: [Base, A). // archive_space_rs.base and size will be aligned to CDS reserve // granularity. -// - class_space_rs: If UseCompressedClassPointers=1, class_space_rs will -// be reserved. Its start address will be aligned to metaspace reserve -// alignment, which may differ from CDS alignment. It will follow the cds -// archive space, close enough such that narrow class pointer encoding -// covers both spaces. -// If UseCompressedClassPointers=0, class_space_rs remains unreserved. +// - class_space_rs: On 64-bit, class_space_rs will be reserved. Its start +// address will be aligned to metaspace reserve alignment, which may differ +// from CDS alignment. It will follow the cds archive space, close enough +// such that narrow class pointer encoding covers both spaces. // - On error: null is returned and the spaces remain unreserved. char* AOTMetaspace::reserve_address_space_for_archives(FileMapInfo* static_mapinfo, FileMapInfo* dynamic_mapinfo, @@ -1903,32 +1897,34 @@ char* AOTMetaspace::reserve_address_space_for_archives(FileMapInfo* static_mapin size_t archive_end_offset = (dynamic_mapinfo == nullptr) ? static_mapinfo->mapping_end_offset() : dynamic_mapinfo->mapping_end_offset(); size_t archive_space_size = align_up(archive_end_offset, archive_space_alignment); - if (!Metaspace::using_class_space()) { - // Get the simple case out of the way first: - // no compressed class space, simple allocation. +#if !INCLUDE_CLASS_SPACE - // When running without class space, requested archive base should be aligned to cds core alignment. - assert(is_aligned(base_address, archive_space_alignment), - "Archive base address unaligned: " PTR_FORMAT ", needs alignment: %zu.", - p2i(base_address), archive_space_alignment); + // Get the simple case out of the way first: + // no compressed class space, simple allocation. - archive_space_rs = MemoryReserver::reserve((char*)base_address, - archive_space_size, - archive_space_alignment, - os::vm_page_size(), - mtNone); - if (archive_space_rs.is_reserved()) { - assert(base_address == nullptr || - (address)archive_space_rs.base() == base_address, "Sanity"); - // Register archive space with NMT. - MemTracker::record_virtual_memory_tag(archive_space_rs, mtClassShared); - return archive_space_rs.base(); - } - return nullptr; + // When running without class space, requested archive base should be aligned to cds core alignment. + assert(is_aligned(base_address, archive_space_alignment), + "Archive base address unaligned: " PTR_FORMAT ", needs alignment: %zu.", + p2i(base_address), archive_space_alignment); + + archive_space_rs = MemoryReserver::reserve((char*)base_address, + archive_space_size, + archive_space_alignment, + os::vm_page_size(), + mtNone); + if (archive_space_rs.is_reserved()) { + assert(base_address == nullptr || + (address)archive_space_rs.base() == base_address, "Sanity"); + // Register archive space with NMT. + MemTracker::record_virtual_memory_tag(archive_space_rs, mtClassShared); + return archive_space_rs.base(); } -#ifdef _LP64 + return nullptr; + +#else + // INCLUDE_CLASS_SPACE=1 // Complex case: two spaces adjacent to each other, both to be addressable // with narrow class pointers. // We reserve the whole range spanning both spaces, then split that range up. @@ -2040,11 +2036,7 @@ char* AOTMetaspace::reserve_address_space_for_archives(FileMapInfo* static_mapin return archive_space_rs.base(); -#else - ShouldNotReachHere(); - return nullptr; -#endif - +#endif // INCLUDE_CLASS_SPACE } void AOTMetaspace::release_reserved_spaces(ReservedSpace& total_space_rs, diff --git a/src/hotspot/share/cds/aotStreamedHeapWriter.cpp b/src/hotspot/share/cds/aotStreamedHeapWriter.cpp index ad363f21fdb..25bef10a673 100644 --- a/src/hotspot/share/cds/aotStreamedHeapWriter.cpp +++ b/src/hotspot/share/cds/aotStreamedHeapWriter.cpp @@ -369,7 +369,6 @@ template void AOTStreamedHeapWriter::map_oop_field_in_buffer(oop ob } void AOTStreamedHeapWriter::update_header_for_buffered_addr(address buffered_addr, oop src_obj, Klass* src_klass) { - assert(UseCompressedClassPointers, "Archived heap only supported for compressed klasses"); narrowKlass nk = ArchiveBuilder::current()->get_requested_narrow_klass(src_klass); markWord mw = markWord::prototype(); diff --git a/src/hotspot/share/cds/archiveBuilder.cpp b/src/hotspot/share/cds/archiveBuilder.cpp index b2d6600e44f..21eef3d7b0b 100644 --- a/src/hotspot/share/cds/archiveBuilder.cpp +++ b/src/hotspot/share/cds/archiveBuilder.cpp @@ -1092,20 +1092,17 @@ class RelocateBufferToRequested : public BitMapClosure { } }; -#ifdef _LP64 int ArchiveBuilder::precomputed_narrow_klass_shift() { - // Legacy Mode: - // We use 32 bits for narrowKlass, which should cover the full 4G Klass range. Shift can be 0. + // Standard Mode: + // We use 32 bits for narrowKlass, which should cover a full 4G Klass range. Shift can be 0. // CompactObjectHeader Mode: // narrowKlass is much smaller, and we use the highest possible shift value to later get the maximum // Klass encoding range. // // Note that all of this may change in the future, if we decide to correct the pre-calculated // narrow Klass IDs at archive load time. - assert(UseCompressedClassPointers, "Only needed for compressed class pointers"); return UseCompactObjectHeaders ? CompressedKlassPointers::max_shift() : 0; } -#endif // _LP64 void ArchiveBuilder::relocate_to_requested() { if (!ro_region()->is_packed()) { diff --git a/src/hotspot/share/cds/archiveBuilder.hpp b/src/hotspot/share/cds/archiveBuilder.hpp index b3667ea11b4..6a9df87092b 100644 --- a/src/hotspot/share/cds/archiveBuilder.hpp +++ b/src/hotspot/share/cds/archiveBuilder.hpp @@ -484,7 +484,6 @@ class ArchiveBuilder : public StackObj { void print_stats(); void report_out_of_space(const char* name, size_t needed_bytes); -#ifdef _LP64 // The CDS archive contains pre-computed narrow Klass IDs. It carries them in the headers of // archived heap objects. With +UseCompactObjectHeaders, it also carries them in prototypes // in Klass. @@ -504,7 +503,6 @@ class ArchiveBuilder : public StackObj { // TinyClassPointer Mode: // We use the highest possible shift value to maximize the encoding range size. static int precomputed_narrow_klass_shift(); -#endif // _LP64 }; diff --git a/src/hotspot/share/cds/archiveUtils.cpp b/src/hotspot/share/cds/archiveUtils.cpp index f79b1e134e8..6e0608e196b 100644 --- a/src/hotspot/share/cds/archiveUtils.cpp +++ b/src/hotspot/share/cds/archiveUtils.cpp @@ -360,8 +360,8 @@ char* DumpRegion::allocate_metaspace_obj(size_t num_bytes, address src, Metaspac bool is_instance_class = is_class && ((Klass*)src)->is_instance_klass(); #ifdef _LP64 - // More strict alignments needed for UseCompressedClassPointers - if (is_class && UseCompressedClassPointers) { + // More strict alignments needed for Klass objects + if (is_class) { size_t klass_alignment = checked_cast(nth_bit(ArchiveBuilder::precomputed_narrow_klass_shift())); alignment = MAX2(alignment, klass_alignment); precond(is_aligned(alignment, SharedSpaceObjectAlignment)); diff --git a/src/hotspot/share/cds/cdsConfig.cpp b/src/hotspot/share/cds/cdsConfig.cpp index 9d191bf0121..ecf3c6d2231 100644 --- a/src/hotspot/share/cds/cdsConfig.cpp +++ b/src/hotspot/share/cds/cdsConfig.cpp @@ -891,10 +891,6 @@ const char* CDSConfig::type_of_archive_being_written() { // If an incompatible VM options is found, return a text message that explains why static const char* check_options_incompatible_with_dumping_heap() { #if INCLUDE_CDS_JAVA_HEAP - if (!UseCompressedClassPointers) { - return "UseCompressedClassPointers must be true"; - } - return nullptr; #else return "JVM not configured for writing Java heap objects"; diff --git a/src/hotspot/share/cds/filemap.cpp b/src/hotspot/share/cds/filemap.cpp index a07f13cefca..38502b2b2d8 100644 --- a/src/hotspot/share/cds/filemap.cpp +++ b/src/hotspot/share/cds/filemap.cpp @@ -225,15 +225,9 @@ void FileMapHeader::populate(FileMapInfo *info, size_t core_region_alignment, } #endif _compressed_oops = UseCompressedOops; - _compressed_class_ptrs = UseCompressedClassPointers; - if (UseCompressedClassPointers) { -#ifdef _LP64 - _narrow_klass_pointer_bits = CompressedKlassPointers::narrow_klass_pointer_bits(); - _narrow_klass_shift = ArchiveBuilder::precomputed_narrow_klass_shift(); -#endif - } else { - _narrow_klass_pointer_bits = _narrow_klass_shift = -1; - } + _narrow_klass_pointer_bits = CompressedKlassPointers::narrow_klass_pointer_bits(); + _narrow_klass_shift = ArchiveBuilder::precomputed_narrow_klass_shift(); + // Which JIT compier is used _compiler_type = (u1)CompilerConfig::compiler_type(); _type_profile_level = TypeProfileLevel; @@ -295,7 +289,6 @@ void FileMapHeader::print(outputStream* st) { st->print_cr("- max_heap_size: %zu", _max_heap_size); st->print_cr("- narrow_oop_mode: %d", _narrow_oop_mode); st->print_cr("- compressed_oops: %d", _compressed_oops); - st->print_cr("- compressed_class_ptrs: %d", _compressed_class_ptrs); st->print_cr("- narrow_klass_pointer_bits: %d", _narrow_klass_pointer_bits); st->print_cr("- narrow_klass_shift: %d", _narrow_klass_shift); st->print_cr("- cloned_vtables: %u", cast_to_u4(_cloned_vtables)); @@ -1926,11 +1919,12 @@ bool FileMapHeader::validate() { _has_platform_or_app_classes = false; } - aot_log_info(aot)("The %s was created with UseCompressedOops = %d, UseCompressedClassPointers = %d, UseCompactObjectHeaders = %d", - file_type, compressed_oops(), compressed_class_pointers(), compact_headers()); - if (compressed_oops() != UseCompressedOops || compressed_class_pointers() != UseCompressedClassPointers) { - aot_log_warning(aot)("Unable to use %s.\nThe saved state of UseCompressedOops and UseCompressedClassPointers is " - "different from runtime, CDS will be disabled.", file_type); + aot_log_info(aot)("The %s was created with UseCompressedOops = %d, UseCompactObjectHeaders = %d", + file_type, compressed_oops(), compact_headers()); + if (compressed_oops() != UseCompressedOops) { + aot_log_warning(aot)("Unable to use %s.\nThe saved state of UseCompressedOops (%d) is " + "different from runtime (%d), CDS will be disabled.", file_type, + compressed_oops(), UseCompressedOops); return false; } diff --git a/src/hotspot/share/cds/filemap.hpp b/src/hotspot/share/cds/filemap.hpp index 56b88df378a..bae08bd5bc7 100644 --- a/src/hotspot/share/cds/filemap.hpp +++ b/src/hotspot/share/cds/filemap.hpp @@ -120,7 +120,6 @@ class FileMapHeader: private CDSFileMapHeaderBase { CompressedOops::Mode _narrow_oop_mode; // compressed oop encoding mode bool _object_streaming_mode; // dump was created for object streaming bool _compressed_oops; // save the flag UseCompressedOops - bool _compressed_class_ptrs; // save the flag UseCompressedClassPointers int _narrow_klass_pointer_bits; // save number of bits in narrowKlass int _narrow_klass_shift; // save shift width used to pre-compute narrowKlass IDs in archived heap objects narrowPtr _cloned_vtables; // The address of the first cloned vtable @@ -200,7 +199,6 @@ class FileMapHeader: private CDSFileMapHeaderBase { bool has_platform_or_app_classes() const { return _has_platform_or_app_classes; } bool has_aot_linked_classes() const { return _has_aot_linked_classes; } bool compressed_oops() const { return _compressed_oops; } - bool compressed_class_pointers() const { return _compressed_class_ptrs; } int narrow_klass_pointer_bits() const { return _narrow_klass_pointer_bits; } int narrow_klass_shift() const { return _narrow_klass_shift; } bool has_full_module_graph() const { return _has_full_module_graph; } diff --git a/src/hotspot/share/classfile/systemDictionaryShared.cpp b/src/hotspot/share/classfile/systemDictionaryShared.cpp index 5947050e31a..58d432a628c 100644 --- a/src/hotspot/share/classfile/systemDictionaryShared.cpp +++ b/src/hotspot/share/classfile/systemDictionaryShared.cpp @@ -89,11 +89,9 @@ DEBUG_ONLY(bool SystemDictionaryShared::_class_loading_may_happen = true;) #ifdef ASSERT static void check_klass_after_loading(const Klass* k) { -#ifdef _LP64 - if (k != nullptr && UseCompressedClassPointers) { + if (k != nullptr) { CompressedKlassPointers::check_encodable(k); } -#endif } #endif diff --git a/src/hotspot/share/code/aotCodeCache.cpp b/src/hotspot/share/code/aotCodeCache.cpp index b29cf906736..4ad5e12d808 100644 --- a/src/hotspot/share/code/aotCodeCache.cpp +++ b/src/hotspot/share/code/aotCodeCache.cpp @@ -388,9 +388,6 @@ void AOTCodeCache::Config::record(uint cpu_features_offset) { if (UseCompressedOops) { _flags |= compressedOops; } - if (UseCompressedClassPointers) { - _flags |= compressedClassPointers; - } if (UseTLAB) { _flags |= useTLAB; } @@ -474,10 +471,6 @@ bool AOTCodeCache::Config::verify(AOTCodeCache* cache) const { return false; } - if (((_flags & compressedClassPointers) != 0) != UseCompressedClassPointers) { - log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with UseCompressedClassPointers = %s", UseCompressedClassPointers ? "false" : "true"); - return false; - } if (_compressedKlassShift != (uint)CompressedKlassPointers::shift()) { log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with CompressedKlassPointers::shift() = %d vs current %d", _compressedKlassShift, CompressedKlassPointers::shift()); return false; diff --git a/src/hotspot/share/code/aotCodeCache.hpp b/src/hotspot/share/code/aotCodeCache.hpp index bd8721fea8c..7996388faa6 100644 --- a/src/hotspot/share/code/aotCodeCache.hpp +++ b/src/hotspot/share/code/aotCodeCache.hpp @@ -177,12 +177,11 @@ class AOTCodeCache : public CHeapObj { none = 0, debugVM = 1, compressedOops = 2, - compressedClassPointers = 4, - useTLAB = 8, - systemClassAssertions = 16, - userClassAssertions = 32, - enableContendedPadding = 64, - restrictContendedPadding = 128 + useTLAB = 4, + systemClassAssertions = 8, + userClassAssertions = 16, + enableContendedPadding = 32, + restrictContendedPadding = 64 }; uint _flags; uint _cpu_features_offset; // offset in the cache where cpu features are stored diff --git a/src/hotspot/share/code/compiledIC.cpp b/src/hotspot/share/code/compiledIC.cpp index 5f5c9711441..07d96d6cd44 100644 --- a/src/hotspot/share/code/compiledIC.cpp +++ b/src/hotspot/share/code/compiledIC.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -76,11 +76,7 @@ CompiledICData::CompiledICData() // Inline cache callsite info is initialized once the first time it is resolved void CompiledICData::initialize(CallInfo* call_info, Klass* receiver_klass) { _speculated_method = call_info->selected_method(); - if (UseCompressedClassPointers) { - _speculated_klass = (uintptr_t)CompressedKlassPointers::encode_not_null(receiver_klass); - } else { - _speculated_klass = (uintptr_t)receiver_klass; - } + _speculated_klass = (uintptr_t)CompressedKlassPointers::encode_not_null(receiver_klass); if (call_info->call_kind() == CallInfo::itable_call) { assert(call_info->resolved_method() != nullptr, "virtual or interface method must be found"); _itable_defc_klass = call_info->resolved_method()->method_holder(); @@ -133,12 +129,7 @@ Klass* CompiledICData::speculated_klass() const { if (is_speculated_klass_unloaded()) { return nullptr; } - - if (UseCompressedClassPointers) { - return CompressedKlassPointers::decode_not_null((narrowKlass)_speculated_klass); - } else { - return (Klass*)_speculated_klass; - } + return CompressedKlassPointers::decode_not_null((narrowKlass)_speculated_klass); } //----------------------------------------------------------------------------- diff --git a/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp b/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp index a888ea81707..afe7d2acfa7 100644 --- a/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp +++ b/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp @@ -708,7 +708,6 @@ int BarrierSetC2::arraycopy_payload_base_offset(bool is_array) { // 12 - 64-bit VM, compressed klass // 16 - 64-bit VM, normal klass if (base_off % BytesPerLong != 0) { - assert(UseCompressedClassPointers, ""); assert(!UseCompactObjectHeaders, ""); if (is_array) { // Exclude length to copy by 8 bytes words. diff --git a/src/hotspot/share/gc/shared/gcTrace.cpp b/src/hotspot/share/gc/shared/gcTrace.cpp index bad9c707b1e..5d0627e779e 100644 --- a/src/hotspot/share/gc/shared/gcTrace.cpp +++ b/src/hotspot/share/gc/shared/gcTrace.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -122,11 +122,10 @@ void GCTracer::report_gc_heap_summary(GCWhen::Type when, const GCHeapSummary& he void GCTracer::report_metaspace_summary(GCWhen::Type when, const MetaspaceSummary& summary) const { send_meta_space_summary_event(when, summary); - send_metaspace_chunk_free_list_summary(when, Metaspace::NonClassType, summary.metaspace_chunk_free_list_summary()); - if (UseCompressedClassPointers) { - send_metaspace_chunk_free_list_summary(when, Metaspace::ClassType, summary.class_chunk_free_list_summary()); - } +#if INCLUDE_CLASS_SPACE + send_metaspace_chunk_free_list_summary(when, Metaspace::ClassType, summary.class_chunk_free_list_summary()); +#endif } void YoungGCTracer::report_gc_end_impl(const Ticks& timestamp, TimePartitions* time_partitions) { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahAsserts.cpp b/src/hotspot/share/gc/shenandoah/shenandoahAsserts.cpp index baeaffb9c7b..268f5b13035 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahAsserts.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahAsserts.cpp @@ -559,26 +559,24 @@ bool ShenandoahAsserts::extract_klass_safely(oop obj, narrowKlass& nk, const Kla if (!os::is_readable_pointer(obj)) { return false; } - if (UseCompressedClassPointers) { - if (UseCompactObjectHeaders) { // look in forwardee - markWord mark = obj->mark(); - if (mark.is_marked()) { - oop fwd = cast_to_oop(mark.clear_lock_bits().to_pointer()); - if (!os::is_readable_pointer(fwd)) { - return false; - } - mark = fwd->mark(); + + if (UseCompactObjectHeaders) { // look in forwardee + markWord mark = obj->mark(); + if (mark.is_marked()) { + oop fwd = cast_to_oop(mark.clear_lock_bits().to_pointer()); + if (!os::is_readable_pointer(fwd)) { + return false; } - nk = mark.narrow_klass(); - } else { - nk = obj->narrow_klass(); - } - if (!CompressedKlassPointers::is_valid_narrow_klass_id(nk)) { - return false; + mark = fwd->mark(); } - k = CompressedKlassPointers::decode_not_null_without_asserts(nk); + nk = mark.narrow_klass(); } else { - k = obj->klass(); + nk = obj->narrow_klass(); } + if (!CompressedKlassPointers::is_valid_narrow_klass_id(nk)) { + return false; + } + k = CompressedKlassPointers::decode_not_null_without_asserts(nk); + return k != nullptr; } diff --git a/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp b/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp index 650918e2d30..0a3dac1e100 100644 --- a/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp +++ b/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -442,7 +442,7 @@ void ZBarrierSetC2::clone_at_expansion(PhaseMacroExpand* phase, ArrayCopyNode* a assert(src_offset == dest_offset, "should be equal"); const jlong offset = src_offset->get_long(); if (offset != arrayOopDesc::base_offset_in_bytes(T_OBJECT)) { - assert(!UseCompressedClassPointers || UseCompactObjectHeaders, "should only happen without compressed class pointers"); + assert(UseCompactObjectHeaders, "should only happen with COH"); assert((arrayOopDesc::base_offset_in_bytes(T_OBJECT) - offset) == BytesPerLong, "unexpected offset"); length = phase->transform_later(new SubLNode(length, phase->longcon(1))); // Size is in longs src_offset = phase->longcon(arrayOopDesc::base_offset_in_bytes(T_OBJECT)); diff --git a/src/hotspot/share/gc/z/zDebug.gdb b/src/hotspot/share/gc/z/zDebug.gdb index d502eea7ce3..df087c4a42d 100644 --- a/src/hotspot/share/gc/z/zDebug.gdb +++ b/src/hotspot/share/gc/z/zDebug.gdb @@ -50,11 +50,7 @@ define zpo end printf "\t Page: %llu\n", ((uintptr_t)$obj & ZAddressOffsetMask) >> ZGranuleSizeShift x/16gx $obj - if (UseCompressedClassPointers) - set $klass = (Klass*)(void*)((uintptr_t)CompressedKlassPointers::_base +((uintptr_t)$obj->_metadata->_compressed_klass << CompressedKlassPointers::_shift)) - else - set $klass = $obj->_metadata->_klass - end + set $klass = (Klass*)(void*)((uintptr_t)CompressedKlassPointers::_base +((uintptr_t)$obj->_compressed_klass << CompressedKlassPointers::_shift)) printf "Mark: 0x%016llx\tKlass: %s\n", (uintptr_t)$obj->_mark, (char*)$klass->_name->_body end diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdKlassQueue.cpp b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdKlassQueue.cpp index 9c57374d6c6..eab7de20545 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdKlassQueue.cpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdKlassQueue.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -75,7 +75,7 @@ static size_t element_size(bool compressed) { } static bool can_compress_element(traceid id) { - return Metaspace::using_class_space() && id < uncompressed_threshold; + return INCLUDE_CLASS_SPACE == 1 && id < uncompressed_threshold; } static size_t element_size(const Klass* klass) { diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp index 6214f6a2746..6048c19d911 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp @@ -206,13 +206,8 @@ void CompilerToVM::Data::initialize(JVMCI_TRAPS) { Universe_narrow_oop_base = nullptr; Universe_narrow_oop_shift = 0; } - if (UseCompressedClassPointers) { - Universe_narrow_klass_base = CompressedKlassPointers::base(); - Universe_narrow_klass_shift = CompressedKlassPointers::shift(); - } else { - Universe_narrow_klass_base = nullptr; - Universe_narrow_klass_shift = 0; - } + Universe_narrow_klass_base = CompressedKlassPointers::base(); + Universe_narrow_klass_shift = CompressedKlassPointers::shift(); Universe_non_oop_bits = Universe::non_oop_word(); Universe_verify_oop_mask = Universe::verify_oop_mask(); Universe_verify_oop_bits = Universe::verify_oop_bits(); @@ -390,7 +385,6 @@ JVMCIObjectArray CompilerToVM::initialize_intrinsics(JVMCI_TRAPS) { X86_ONLY(do_int_flag(UseAVX)) \ do_bool_flag(UseCRC32Intrinsics) \ do_bool_flag(UseAdler32Intrinsics) \ - do_bool_flag(UseCompressedClassPointers) \ do_bool_flag(UseCompressedOops) \ X86_ONLY(do_bool_flag(UseCountLeadingZerosInstruction)) \ X86_ONLY(do_bool_flag(UseCountTrailingZerosInstruction)) \ diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp index ac532e1bb4c..1fdf98588fd 100644 --- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -342,7 +342,7 @@ volatile_nonstatic_field(ObjectMonitor, _succ, int64_t) \ \ volatile_nonstatic_field(oopDesc, _mark, markWord) \ - volatile_nonstatic_field(oopDesc, _metadata._klass, Klass*) \ + volatile_nonstatic_field(oopDesc, _compressed_klass, narrowKlass) \ \ static_field(StubRoutines, _verify_oop_count, jint) \ \ diff --git a/src/hotspot/share/memory/classLoaderMetaspace.cpp b/src/hotspot/share/memory/classLoaderMetaspace.cpp index c1ff172071d..af3b8b1b77f 100644 --- a/src/hotspot/share/memory/classLoaderMetaspace.cpp +++ b/src/hotspot/share/memory/classLoaderMetaspace.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, 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. * @@ -162,10 +162,12 @@ void ClassLoaderMetaspace::deallocate(MetaWord* ptr, size_t word_size) { MetaBlock bl(ptr, word_size); // Add to class arena only if block is usable for encodable Klass storage. MetaspaceArena* receiving_arena = non_class_space_arena(); - if (Metaspace::using_class_space() && Metaspace::is_in_class_space(ptr) && +#if INCLUDE_CLASS_SPACE + if (Metaspace::is_in_class_space(ptr) && is_aligned(ptr, class_space_arena()->allocation_alignment_bytes())) { receiving_arena = class_space_arena(); } +#endif receiving_arena->deallocate(bl); DEBUG_ONLY(InternalStats::inc_num_deallocs();) } diff --git a/src/hotspot/share/memory/classLoaderMetaspace.hpp b/src/hotspot/share/memory/classLoaderMetaspace.hpp index aa43e171708..dc782611e98 100644 --- a/src/hotspot/share/memory/classLoaderMetaspace.hpp +++ b/src/hotspot/share/memory/classLoaderMetaspace.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,9 +40,10 @@ namespace metaspace { // A ClassLoaderMetaspace manages MetaspaceArena(s) for a CLD. // -// A CLD owns one MetaspaceArena if UseCompressedClassPointers is false. Otherwise -// it owns two - one for the Klass* objects from the class space, one for the other -// types of MetaspaceObjs from the non-class space. +// 64-bit: +// +// A CLD owns two MetaspaceArenas - one for the Klass* objects from the class space, +// one for the other types of MetaspaceObjs from the non-class space. // // +------+ +----------------------+ +-------------------+ // | CLD | ---> | ClassLoaderMetaspace | ----> | (non class) Arena | @@ -58,6 +59,11 @@ namespace metaspace { // ^ // alloc top // +// 32-bit: +// +// A CLD owns just one MetaspaceArena. In that arena all metadata - Klass and other - +// are placed. + class ClassLoaderMetaspace : public CHeapObj { friend class metaspace::ClmsTester; // for gtests @@ -67,11 +73,10 @@ class ClassLoaderMetaspace : public CHeapObj { const Metaspace::MetaspaceType _space_type; // Arena for allocations from non-class metaspace - // (resp. for all allocations if -XX:-UseCompressedClassPointers). metaspace::MetaspaceArena* _non_class_space_arena; // Arena for allocations from class space - // (null if -XX:-UseCompressedClassPointers). + // (null for 32-bit). metaspace::MetaspaceArena* _class_space_arena; Mutex* lock() const { return _lock; } diff --git a/src/hotspot/share/memory/metaspace.cpp b/src/hotspot/share/memory/metaspace.cpp index e686b324004..da6ebc991c8 100644 --- a/src/hotspot/share/memory/metaspace.cpp +++ b/src/hotspot/share/memory/metaspace.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2017, 2021 SAP SE. All rights reserved. * Copyright (c) 2023, 2025, Red Hat, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -166,33 +166,33 @@ void MetaspaceUtils::print_metaspace_change(const MetaspaceCombinedStats& pre_me // it is a constant (to uninformed users, often confusingly large). For non-class space, it would // be interesting since free chunks can be uncommitted, but for now it is left out. - if (Metaspace::using_class_space()) { - log_info(gc, metaspace)(HEAP_CHANGE_FORMAT" " - HEAP_CHANGE_FORMAT" " - HEAP_CHANGE_FORMAT, - HEAP_CHANGE_FORMAT_ARGS("Metaspace", - pre_meta_values.used(), - pre_meta_values.committed(), - meta_values.used(), - meta_values.committed()), - HEAP_CHANGE_FORMAT_ARGS("NonClass", - pre_meta_values.non_class_used(), - pre_meta_values.non_class_committed(), - meta_values.non_class_used(), - meta_values.non_class_committed()), - HEAP_CHANGE_FORMAT_ARGS("Class", - pre_meta_values.class_used(), - pre_meta_values.class_committed(), - meta_values.class_used(), - meta_values.class_committed())); - } else { - log_info(gc, metaspace)(HEAP_CHANGE_FORMAT, - HEAP_CHANGE_FORMAT_ARGS("Metaspace", - pre_meta_values.used(), - pre_meta_values.committed(), - meta_values.used(), - meta_values.committed())); - } +#if INCLUDE_CLASS_SPACE + log_info(gc, metaspace)(HEAP_CHANGE_FORMAT" " + HEAP_CHANGE_FORMAT" " + HEAP_CHANGE_FORMAT, + HEAP_CHANGE_FORMAT_ARGS("Metaspace", + pre_meta_values.used(), + pre_meta_values.committed(), + meta_values.used(), + meta_values.committed()), + HEAP_CHANGE_FORMAT_ARGS("NonClass", + pre_meta_values.non_class_used(), + pre_meta_values.non_class_committed(), + meta_values.non_class_used(), + meta_values.non_class_committed()), + HEAP_CHANGE_FORMAT_ARGS("Class", + pre_meta_values.class_used(), + pre_meta_values.class_committed(), + meta_values.class_used(), + meta_values.class_committed())); +#else + log_info(gc, metaspace)(HEAP_CHANGE_FORMAT, + HEAP_CHANGE_FORMAT_ARGS("Metaspace", + pre_meta_values.used(), + pre_meta_values.committed(), + meta_values.used(), + meta_values.committed())); +#endif // INCLUDE_CLASS_SPACE } // This will print out a basic metaspace usage report but @@ -226,41 +226,36 @@ void MetaspaceUtils::print_on(outputStream* out) { stats.committed()/K, stats.reserved()/K); - if (Metaspace::using_class_space()) { - StreamIndentor si(out, 1); - out->print("class space "); - out->fill_to(17); - out->print_cr("used %zuK, " - "committed %zuK, " - "reserved %zuK", - stats.class_space_stats().used()/K, - stats.class_space_stats().committed()/K, - stats.class_space_stats().reserved()/K); - } +#if INCLUDE_CLASS_SPACE + StreamIndentor si(out, 1); + out->print("class space "); + out->fill_to(17); + out->print_cr("used %zuK, " + "committed %zuK, " + "reserved %zuK", + stats.class_space_stats().used()/K, + stats.class_space_stats().committed()/K, + stats.class_space_stats().reserved()/K); +#endif // INCLUDE_CLASS_SPACE } #ifdef ASSERT void MetaspaceUtils::verify() { if (Metaspace::initialized()) { - // Verify non-class chunkmanager... ChunkManager* cm = ChunkManager::chunkmanager_nonclass(); cm->verify(); - // ... and space list. VirtualSpaceList* vsl = VirtualSpaceList::vslist_nonclass(); vsl->verify(); - if (Metaspace::using_class_space()) { - // If we use compressed class pointers, verify class chunkmanager... - cm = ChunkManager::chunkmanager_class(); - cm->verify(); - - // ... and class spacelist. - vsl = VirtualSpaceList::vslist_class(); - vsl->verify(); - } +#if INCLUDE_CLASS_SPACE + cm = ChunkManager::chunkmanager_class(); + cm->verify(); + vsl = VirtualSpaceList::vslist_class(); + vsl->verify(); +#endif // INCLUDE_CLASS_SPACE } } #endif @@ -387,7 +382,8 @@ void MetaspaceGC::post_initialize() { bool MetaspaceGC::can_expand(size_t word_size, bool is_class) { // Check if the compressed class space is full. - if (is_class && Metaspace::using_class_space()) { +#if INCLUDE_CLASS_SPACE + if (is_class) { size_t class_committed = MetaspaceUtils::committed_bytes(Metaspace::ClassType); if (class_committed + word_size * BytesPerWord > CompressedClassSpaceSize) { log_trace(gc, metaspace, freelist)("Cannot expand %s metaspace by %zu words (CompressedClassSpaceSize = %zu words)", @@ -395,6 +391,7 @@ bool MetaspaceGC::can_expand(size_t word_size, bool is_class) { return false; } } +#endif // INCLUDE_CLASS_SPACE // Check if the user has imposed a limit on the metaspace memory. size_t committed_bytes = MetaspaceUtils::committed_bytes(); @@ -548,7 +545,7 @@ const void* Metaspace::_class_space_end = nullptr; bool Metaspace::initialized() { return metaspace::MetaspaceContext::context_nonclass() != nullptr - LP64_ONLY(&& (using_class_space() ? Metaspace::class_space_is_initialized() : true)); + CLASS_SPACE_ONLY(&& Metaspace::class_space_is_initialized()); } #ifdef _LP64 @@ -566,9 +563,9 @@ void Metaspace::print_compressed_class_space(outputStream* st) { // Given a prereserved space, use that to set up the compressed class space list. void Metaspace::initialize_class_space(ReservedSpace rs) { + STATIC_ASSERT(INCLUDE_CLASS_SPACE == 1); assert(rs.size() >= CompressedClassSpaceSize, "%zu != %zu", rs.size(), CompressedClassSpaceSize); - assert(using_class_space(), "Must be using class space"); assert(rs.size() == CompressedClassSpaceSize, "%zu != %zu", rs.size(), CompressedClassSpaceSize); @@ -658,49 +655,51 @@ void Metaspace::ergo_initialize() { MaxMetaspaceSize = MAX2(MaxMetaspaceSize, commit_alignment()); - if (UseCompressedClassPointers) { - // Let Class Space not be larger than 80% of MaxMetaspaceSize. Note that is - // grossly over-dimensioned for most usage scenarios; typical ratio of - // class space : non class space usage is about 1:6. With many small classes, - // it can get as low as 1:2. It is not a big deal though since ccs is only - // reserved and will be committed on demand only. - const size_t max_ccs_size = 8 * (MaxMetaspaceSize / 10); - - // Sanity check. - const size_t max_klass_range = CompressedKlassPointers::max_klass_range_size(); - assert(max_klass_range >= reserve_alignment(), - "Klass range (%zu) must cover at least a full root chunk (%zu)", - max_klass_range, reserve_alignment()); - - size_t adjusted_ccs_size = MIN3(CompressedClassSpaceSize, max_ccs_size, max_klass_range); - - // CCS must be aligned to root chunk size, and be at least the size of one - // root chunk. - adjusted_ccs_size = align_up(adjusted_ccs_size, reserve_alignment()); - adjusted_ccs_size = MAX2(adjusted_ccs_size, reserve_alignment()); - - // Print a warning if the adjusted size differs from the users input - if (CompressedClassSpaceSize != adjusted_ccs_size) { - #define X "CompressedClassSpaceSize adjusted from user input " \ - "%zu bytes to %zu bytes", CompressedClassSpaceSize, adjusted_ccs_size - if (FLAG_IS_CMDLINE(CompressedClassSpaceSize)) { - log_warning(metaspace)(X); - } else { - log_info(metaspace)(X); - } - #undef X +#if INCLUDE_CLASS_SPACE + + // Let Class Space not be larger than 80% of MaxMetaspaceSize. Note that is + // grossly over-dimensioned for most usage scenarios; typical ratio of + // class space : non class space usage is about 1:6. With many small classes, + // it can get as low as 1:2. It is not a big deal though since ccs is only + // reserved and will be committed on demand only. + const size_t max_ccs_size = 8 * (MaxMetaspaceSize / 10); + + // Sanity check. + const size_t max_klass_range = CompressedKlassPointers::max_klass_range_size(); + assert(max_klass_range >= reserve_alignment(), + "Klass range (%zu) must cover at least a full root chunk (%zu)", + max_klass_range, reserve_alignment()); + + size_t adjusted_ccs_size = MIN3(CompressedClassSpaceSize, max_ccs_size, max_klass_range); + + // CCS must be aligned to root chunk size, and be at least the size of one + // root chunk. + adjusted_ccs_size = align_up(adjusted_ccs_size, reserve_alignment()); + adjusted_ccs_size = MAX2(adjusted_ccs_size, reserve_alignment()); + + // Print a warning if the adjusted size differs from the users input + if (CompressedClassSpaceSize != adjusted_ccs_size) { + #define X "CompressedClassSpaceSize adjusted from user input " \ + "%zu bytes to %zu bytes", CompressedClassSpaceSize, adjusted_ccs_size + if (FLAG_IS_CMDLINE(CompressedClassSpaceSize)) { + log_warning(metaspace)(X); + } else { + log_info(metaspace)(X); } + #undef X + } - // Note: re-adjusting may have us left with a CompressedClassSpaceSize - // larger than MaxMetaspaceSize for very small values of MaxMetaspaceSize. - // Lets just live with that, its not a big deal. - if (adjusted_ccs_size != CompressedClassSpaceSize) { - FLAG_SET_ERGO(CompressedClassSpaceSize, adjusted_ccs_size); - log_info(metaspace)("Setting CompressedClassSpaceSize to %zu.", - CompressedClassSpaceSize); - } + // Note: re-adjusting may have us left with a CompressedClassSpaceSize + // larger than MaxMetaspaceSize for very small values of MaxMetaspaceSize. + // Lets just live with that, its not a big deal. + if (adjusted_ccs_size != CompressedClassSpaceSize) { + FLAG_SET_ERGO(CompressedClassSpaceSize, adjusted_ccs_size); + log_info(metaspace)("Setting CompressedClassSpaceSize to %zu.", + CompressedClassSpaceSize); } +#endif // INCLUDE_CLASS_SPACE + // Set MetaspaceSize, MinMetaspaceExpansion and MaxMetaspaceExpansion if (MetaspaceSize > MaxMetaspaceSize) { MetaspaceSize = MaxMetaspaceSize; @@ -724,15 +723,12 @@ void Metaspace::global_initialize() { AOTMetaspace::initialize_for_static_dump(); } - // If UseCompressedClassPointers=1, we have two cases: + // We have two cases: // a) if CDS is active (runtime, Xshare=on), it will create the class space - // for us, initialize it and set up CompressedKlassPointers encoding. - // Class space will be reserved above the mapped archives. + // for us. It then will set up encoding to cover both CDS archive space and class space. // b) if CDS either deactivated (Xshare=off) or a static dump is to be done (Xshare:dump), - // we will create the class space on our own. It will be placed above the java heap, - // since we assume it has been placed in low - // address regions. We may rethink this (see JDK-8244943). Failing that, - // it will be placed anywhere. + // we will create the class space on our own and set up encoding to only cover the + // class space. #if INCLUDE_CDS // case (a) @@ -746,9 +742,9 @@ void Metaspace::global_initialize() { } #endif // INCLUDE_CDS -#ifdef _LP64 +#if INCLUDE_CLASS_SPACE - if (using_class_space() && !class_space_is_initialized()) { + if (!class_space_is_initialized()) { assert(!CDSConfig::is_using_archive(), "CDS archive is not mapped at this point"); // case (b) (No CDS) @@ -835,28 +831,23 @@ void Metaspace::global_initialize() { } #else - // +UseCompressedClassPointers on 32-bit: does not need class space. Klass can live wherever. - if (UseCompressedClassPointers) { - const address start = (address)os::vm_min_address(); // but not in the zero page - const address end = (address)CompressedKlassPointers::max_klass_range_size(); - CompressedKlassPointers::initialize(start, end - start); - } -#endif // __LP64 + // 32-bit: + const address start = (address)os::vm_min_address(); // but not in the zero page + const address end = (address)CompressedKlassPointers::max_klass_range_size(); + CompressedKlassPointers::initialize(start, end - start); +#endif // INCLUDE_CLASS_SPACE // Initialize non-class virtual space list, and its chunk manager: MetaspaceContext::initialize_nonclass_space_context(); _tracer = new MetaspaceTracer(); - if (UseCompressedClassPointers) { - // Note: "cds" would be a better fit but keep this for backward compatibility. - LogTarget(Info, gc, metaspace) lt; - if (lt.is_enabled()) { - LogStream ls(lt); - CDS_ONLY(AOTMetaspace::print_on(&ls);) - Metaspace::print_compressed_class_space(&ls); - CompressedKlassPointers::print_mode(&ls); - } + LogTarget(Info, gc, metaspace) lt; + if (lt.is_enabled()) { + LogStream ls(lt); + CDS_ONLY(AOTMetaspace::print_on(&ls);) + Metaspace::print_compressed_class_space(&ls); + CompressedKlassPointers::print_mode(&ls); } } @@ -888,15 +879,13 @@ MetaWord* Metaspace::allocate(ClassLoaderData* loader_data, size_t word_size, MetaWord* result = loader_data->metaspace_non_null()->allocate(word_size, mdtype); if (result != nullptr) { -#ifdef ASSERT - if (using_class_space() && mdtype == ClassType) { + if (INCLUDE_CLASS_SPACE == 1 && mdtype == ClassType) { assert(is_in_class_space(result) && is_aligned(result, CompressedKlassPointers::klass_alignment_in_bytes()), "Sanity"); } else { assert((is_in_class_space(result) || is_in_nonclass_metaspace(result)) && is_aligned(result, Metaspace::min_allocation_alignment_bytes), "Sanity"); } -#endif // Zero initialize. Copy::fill_to_words((HeapWord*)result, word_size, 0); log_trace(metaspace)("Metaspace::allocate: type %d return " PTR_FORMAT ".", (int)type, p2i(result)); @@ -1017,12 +1006,12 @@ void Metaspace::purge(bool classes_unloaded) { if (cm != nullptr) { cm->purge(); } - if (using_class_space()) { - cm = ChunkManager::chunkmanager_class(); - if (cm != nullptr) { - cm->purge(); - } +#if INCLUDE_CLASS_SPACE + cm = ChunkManager::chunkmanager_class(); + if (cm != nullptr) { + cm->purge(); } +#endif // INCLUDE_CLASS_SPACE } // Try to satisfy queued metaspace allocation requests. diff --git a/src/hotspot/share/memory/metaspace.hpp b/src/hotspot/share/memory/metaspace.hpp index 01ef4b4dd49..96f5a2459ce 100644 --- a/src/hotspot/share/memory/metaspace.hpp +++ b/src/hotspot/share/memory/metaspace.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2017, 2021 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -164,18 +164,12 @@ class Metaspace : public AllStatic { static void print_compressed_class_space(outputStream* st) NOT_LP64({}); - // Return TRUE only if UseCompressedClassPointers is True. - static bool using_class_space() { - return NOT_LP64(false) LP64_ONLY(UseCompressedClassPointers); - } - static bool is_class_space_allocation(MetadataType mdType) { - return mdType == ClassType && using_class_space(); + return CLASS_SPACE_ONLY(mdType == ClassType) NOT_CLASS_SPACE(false); } static bool initialized(); }; - #endif // SHARE_MEMORY_METASPACE_HPP diff --git a/src/hotspot/share/memory/metaspace/metaspaceReporter.cpp b/src/hotspot/share/memory/metaspace/metaspaceReporter.cpp index 3cff2a50d03..f6683f50fd1 100644 --- a/src/hotspot/share/memory/metaspace/metaspaceReporter.cpp +++ b/src/hotspot/share/memory/metaspace/metaspaceReporter.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2018, 2020 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -59,39 +59,39 @@ static void print_vs(outputStream* out, size_t scale) { const size_t committed_nc = RunningCounters::committed_words_nonclass(); const int num_nodes_nc = VirtualSpaceList::vslist_nonclass()->num_nodes(); - if (Metaspace::using_class_space()) { - const size_t reserved_c = RunningCounters::reserved_words_class(); - const size_t committed_c = RunningCounters::committed_words_class(); - const int num_nodes_c = VirtualSpaceList::vslist_class()->num_nodes(); - - out->print(" Non-class space: "); - print_scaled_words(out, reserved_nc, scale, 7); - out->print(" reserved, "); - print_scaled_words_and_percentage(out, committed_nc, reserved_nc, scale, 7); - out->print(" committed, "); - out->print(" %d nodes.", num_nodes_nc); - out->cr(); - out->print(" Class space: "); - print_scaled_words(out, reserved_c, scale, 7); - out->print(" reserved, "); - print_scaled_words_and_percentage(out, committed_c, reserved_c, scale, 7); - out->print(" committed, "); - out->print(" %d nodes.", num_nodes_c); - out->cr(); - out->print(" Both: "); - print_scaled_words(out, reserved_c + reserved_nc, scale, 7); - out->print(" reserved, "); - print_scaled_words_and_percentage(out, committed_c + committed_nc, reserved_c + reserved_nc, scale, 7); - out->print(" committed. "); - out->cr(); - } else { - print_scaled_words(out, reserved_nc, scale, 7); - out->print(" reserved, "); - print_scaled_words_and_percentage(out, committed_nc, reserved_nc, scale, 7); - out->print(" committed, "); - out->print(" %d nodes.", num_nodes_nc); - out->cr(); - } +#if INCLUDE_CLASS_SPACE + const size_t reserved_c = RunningCounters::reserved_words_class(); + const size_t committed_c = RunningCounters::committed_words_class(); + const int num_nodes_c = VirtualSpaceList::vslist_class()->num_nodes(); + + out->print(" Non-class space: "); + print_scaled_words(out, reserved_nc, scale, 7); + out->print(" reserved, "); + print_scaled_words_and_percentage(out, committed_nc, reserved_nc, scale, 7); + out->print(" committed, "); + out->print(" %d nodes.", num_nodes_nc); + out->cr(); + out->print(" Class space: "); + print_scaled_words(out, reserved_c, scale, 7); + out->print(" reserved, "); + print_scaled_words_and_percentage(out, committed_c, reserved_c, scale, 7); + out->print(" committed, "); + out->print(" %d nodes.", num_nodes_c); + out->cr(); + out->print(" Both: "); + print_scaled_words(out, reserved_c + reserved_nc, scale, 7); + out->print(" reserved, "); + print_scaled_words_and_percentage(out, committed_c + committed_nc, reserved_c + reserved_nc, scale, 7); + out->print(" committed. "); + out->cr(); +#else + print_scaled_words(out, reserved_nc, scale, 7); + out->print(" reserved, "); + print_scaled_words_and_percentage(out, committed_nc, reserved_nc, scale, 7); + out->print(" committed, "); + out->print(" %d nodes.", num_nodes_nc); + out->cr(); +#endif // INCLUDE_CLASS_SPACE } static void print_settings(outputStream* out, size_t scale) { @@ -102,12 +102,12 @@ static void print_settings(outputStream* out, size_t scale) { print_human_readable_size(out, MaxMetaspaceSize, scale); } out->cr(); - if (Metaspace::using_class_space()) { - out->print("CompressedClassSpaceSize: "); - print_human_readable_size(out, CompressedClassSpaceSize, scale); - } else { - out->print("No class space"); - } +#if INCLUDE_CLASS_SPACE + out->print("CompressedClassSpaceSize: "); + print_human_readable_size(out, CompressedClassSpaceSize, scale); +#else + out->print("No class space"); +#endif // INCLUDE_CLASS_SPACE out->cr(); out->print("Initial GC threshold: "); print_human_readable_size(out, MetaspaceSize, scale); @@ -117,9 +117,7 @@ static void print_settings(outputStream* out, size_t scale) { out->cr(); out->print_cr("CDS: %s", (CDSConfig::is_using_archive() ? "on" : (CDSConfig::is_dumping_static_archive() ? "dump" : "off"))); Settings::print_on(out); -#ifdef _LP64 CompressedKlassPointers::print_mode(out); -#endif } // This will print out a basic metaspace usage report but @@ -131,9 +129,7 @@ void MetaspaceReporter::print_basic_report(outputStream* out, size_t scale) { } out->cr(); out->print_cr("Usage:"); - if (Metaspace::using_class_space()) { - out->print(" Non-class: "); - } + CLASS_SPACE_ONLY(out->print(" Non-class: ");) // Note: since we want to purely rely on counters, without any locking or walking the CLDG, // for Usage stats (statistics over in-use chunks) all we can print is the @@ -144,37 +140,35 @@ void MetaspaceReporter::print_basic_report(outputStream* out, size_t scale) { print_scaled_words(out, used_nc, scale, 5); out->print(" used."); out->cr(); - if (Metaspace::using_class_space()) { - const size_t used_c = MetaspaceUtils::used_words(Metaspace::ClassType); - out->print(" Class: "); - print_scaled_words(out, used_c, scale, 5); - out->print(" used."); - out->cr(); - out->print(" Both: "); - const size_t used = used_nc + used_c; - print_scaled_words(out, used, scale, 5); - out->print(" used."); - out->cr(); - } +#if INCLUDE_CLASS_SPACE + const size_t used_c = MetaspaceUtils::used_words(Metaspace::ClassType); + out->print(" Class: "); + print_scaled_words(out, used_c, scale, 5); + out->print(" used."); + out->cr(); + out->print(" Both: "); + const size_t used = used_nc + used_c; + print_scaled_words(out, used, scale, 5); + out->print(" used."); + out->cr(); +#endif // INCLUDE_CLASS_SPACE out->cr(); out->print_cr("Virtual space:"); print_vs(out, scale); out->cr(); out->print_cr("Chunk freelists:"); - if (Metaspace::using_class_space()) { - out->print(" Non-Class: "); - } + CLASS_SPACE_ONLY(out->print(" Non-Class: ");) print_scaled_words(out, ChunkManager::chunkmanager_nonclass()->total_word_size(), scale); out->cr(); - if (Metaspace::using_class_space()) { - out->print(" Class: "); - print_scaled_words(out, ChunkManager::chunkmanager_class()->total_word_size(), scale); - out->cr(); - out->print(" Both: "); - print_scaled_words(out, ChunkManager::chunkmanager_nonclass()->total_word_size() + - ChunkManager::chunkmanager_class()->total_word_size(), scale); - out->cr(); - } +#if INCLUDE_CLASS_SPACE + out->print(" Class: "); + print_scaled_words(out, ChunkManager::chunkmanager_class()->total_word_size(), scale); + out->cr(); + out->print(" Both: "); + print_scaled_words(out, ChunkManager::chunkmanager_nonclass()->total_word_size() + + ChunkManager::chunkmanager_class()->total_word_size(), scale); + out->cr(); +#endif // INCLUDE_CLASS_SPACE out->cr(); // Print basic settings @@ -256,70 +250,70 @@ void MetaspaceReporter::print_report(outputStream* out, size_t scale, int flags) // -- Print VirtualSpaceList details. if ((flags & (int)Option::ShowVSList) > 0) { out->cr(); - out->print_cr("Virtual space list%s:", Metaspace::using_class_space() ? "s" : ""); - - if (Metaspace::using_class_space()) { - out->print_cr(" Non-Class:"); - } +#if INCLUDE_CLASS_SPACE + out->print_cr("Virtual space lists:"); + out->print_cr(" Non-Class:"); VirtualSpaceList::vslist_nonclass()->print_on(out); out->cr(); - if (Metaspace::using_class_space()) { - out->print_cr(" Class:"); - VirtualSpaceList::vslist_class()->print_on(out); - out->cr(); - } + out->print_cr(" Class:"); + VirtualSpaceList::vslist_class()->print_on(out); + out->cr(); +#else + out->print_cr("Virtual space list:"); + VirtualSpaceList::vslist_nonclass()->print_on(out); + out->cr(); +#endif // INCLUDE_CLASS_SPACE } out->cr(); //////////// Freelists (ChunkManager) section /////////////////////////// - out->cr(); - out->print_cr("Chunk freelist%s:", Metaspace::using_class_space() ? "s" : ""); - ChunkManagerStats non_class_cm_stat; ChunkManagerStats class_cm_stat; ChunkManagerStats total_cm_stat; ChunkManager::chunkmanager_nonclass()->add_to_statistics(&non_class_cm_stat); - if (Metaspace::using_class_space()) { - ChunkManager::chunkmanager_nonclass()->add_to_statistics(&non_class_cm_stat); - ChunkManager::chunkmanager_class()->add_to_statistics(&class_cm_stat); - total_cm_stat.add(non_class_cm_stat); - total_cm_stat.add(class_cm_stat); +#if INCLUDE_CLASS_SPACE + ChunkManager::chunkmanager_class()->add_to_statistics(&class_cm_stat); + total_cm_stat.add(non_class_cm_stat); + total_cm_stat.add(class_cm_stat); - out->print_cr(" Non-Class:"); - non_class_cm_stat.print_on(out, scale); - out->cr(); - out->print_cr(" Class:"); - class_cm_stat.print_on(out, scale); - out->cr(); - out->print_cr(" Both:"); - total_cm_stat.print_on(out, scale); - out->cr(); - } else { - ChunkManager::chunkmanager_nonclass()->add_to_statistics(&non_class_cm_stat); - non_class_cm_stat.print_on(out, scale); - out->cr(); - } + out->print_cr("Chunk freelists:"); + out->cr(); + out->print_cr(" Non-Class:"); + non_class_cm_stat.print_on(out, scale); + out->cr(); + out->print_cr(" Class:"); + class_cm_stat.print_on(out, scale); + out->cr(); + out->print_cr(" Both:"); + total_cm_stat.print_on(out, scale); + out->cr(); +#else + out->print_cr("Chunk freelist:"); + ChunkManager::chunkmanager_nonclass()->add_to_statistics(&non_class_cm_stat); + non_class_cm_stat.print_on(out, scale); + out->cr(); +#endif // INCLUDE_CLASS_SPACE // -- Print Chunkmanager details. if ((flags & (int)Option::ShowChunkFreeList) > 0) { out->cr(); out->print_cr("Chunk freelist details:"); - if (Metaspace::using_class_space()) { - out->print_cr(" Non-Class:"); - } +#if INCLUDE_CLASS_SPACE + out->print_cr(" Non-Class:"); ChunkManager::chunkmanager_nonclass()->print_on(out); out->cr(); - if (Metaspace::using_class_space()) { - out->print_cr(" Class:"); - ChunkManager::chunkmanager_class()->print_on(out); - out->cr(); - } + out->print_cr(" Class:"); + ChunkManager::chunkmanager_class()->print_on(out); + out->cr(); +#else + ChunkManager::chunkmanager_nonclass()->print_on(out); + out->cr(); +#endif // INCLUDE_CLASS_SPACE } out->cr(); - //////////// Waste section /////////////////////////// // As a convenience, print a summary of common waste. out->cr(); diff --git a/src/hotspot/share/memory/metaspace/metaspaceStatistics.cpp b/src/hotspot/share/memory/metaspace/metaspaceStatistics.cpp index aab46d64db5..d90e8ed090d 100644 --- a/src/hotspot/share/memory/metaspace/metaspaceStatistics.cpp +++ b/src/hotspot/share/memory/metaspace/metaspaceStatistics.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2018, 2020 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -205,27 +205,25 @@ ArenaStats ClmsStats::totals() const { void ClmsStats::print_on(outputStream* st, size_t scale, bool detailed) const { StreamIndentor si(st, 2); st->cr(); - if (Metaspace::using_class_space()) { - st->print("Non-Class: "); - } + CLASS_SPACE_ONLY(st->print("Non-Class: ");) _arena_stats_nonclass.print_on(st, scale, detailed); if (detailed) { st->cr(); } - if (Metaspace::using_class_space()) { +#if INCLUDE_CLASS_SPACE + st->cr(); + st->print(" Class: "); + _arena_stats_class.print_on(st, scale, detailed); + if (detailed) { st->cr(); - st->print(" Class: "); - _arena_stats_class.print_on(st, scale, detailed); - if (detailed) { - st->cr(); - } + } + st->cr(); + st->print(" Both: "); + totals().print_on(st, scale, detailed); + if (detailed) { st->cr(); - st->print(" Both: "); - totals().print_on(st, scale, detailed); - if (detailed) { - st->cr(); - } } +#endif // INCLUDE_CLASS_SPACE st->cr(); } diff --git a/src/hotspot/share/memory/metaspace/virtualSpaceNode.cpp b/src/hotspot/share/memory/metaspace/virtualSpaceNode.cpp index df4e507b104..a934a628582 100644 --- a/src/hotspot/share/memory/metaspace/virtualSpaceNode.cpp +++ b/src/hotspot/share/memory/metaspace/virtualSpaceNode.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2018, 2021 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -259,12 +259,11 @@ VirtualSpaceNode* VirtualSpaceNode::create_node(size_t word_size, } #ifndef _LP64 - // On 32-bit, with +UseCompressedClassPointers, the whole address space is the encoding range. We therefore - // don't need a class space. However, as a pragmatic workaround for pesty overflow problems on 32-bit, we leave - // a small area at the end of the address space out of the encoding range. We just assume no Klass will ever live + // On 32-bit, the whole address space is the encoding range. We therefore don't need a class space. + // However, as a pragmatic workaround for pesty overflow problems on 32-bit, we leave a small area + // at the end of the address space out of the encoding range. We just assume no Klass will ever live // there (it won't, for no OS we support on 32-bit has user-addressable memory up there). - assert(!UseCompressedClassPointers || - rs.end() <= (char*)CompressedKlassPointers::max_klass_range_size(), "Weirdly high address"); + assert(rs.end() <= (char*)CompressedKlassPointers::max_klass_range_size(), "Weirdly high address"); #endif // _LP64 MemTracker::record_virtual_memory_tag(rs, mtMetaspace); diff --git a/src/hotspot/share/nmt/memReporter.cpp b/src/hotspot/share/nmt/memReporter.cpp index 27a94ec7bc0..429db6ad31f 100644 --- a/src/hotspot/share/nmt/memReporter.cpp +++ b/src/hotspot/share/nmt/memReporter.cpp @@ -272,9 +272,7 @@ void MemSummaryReporter::report_summary_of_tag(MemTag mem_tag, } else if (mem_tag == mtClass) { // Metadata information report_metadata(Metaspace::NonClassType); - if (Metaspace::using_class_space()) { - report_metadata(Metaspace::ClassType); - } + CLASS_SPACE_ONLY(report_metadata(Metaspace::ClassType);) } out->cr(); } @@ -754,9 +752,9 @@ void MemSummaryDiffReporter::diff_summary_of_tag(MemTag mem_tag, void MemSummaryDiffReporter::print_metaspace_diff(const MetaspaceCombinedStats& current_ms, const MetaspaceCombinedStats& early_ms) const { print_metaspace_diff("Metadata", current_ms.non_class_space_stats(), early_ms.non_class_space_stats()); - if (Metaspace::using_class_space()) { - print_metaspace_diff("Class space", current_ms.class_space_stats(), early_ms.class_space_stats()); - } +#if INCLUDE_CLASS_SPACE + print_metaspace_diff("Class space", current_ms.class_space_stats(), early_ms.class_space_stats()); +#endif } void MemSummaryDiffReporter::print_metaspace_diff(const char* header, diff --git a/src/hotspot/share/oops/arrayOop.hpp b/src/hotspot/share/oops/arrayOop.hpp index f0c476a2486..836a1b9250d 100644 --- a/src/hotspot/share/oops/arrayOop.hpp +++ b/src/hotspot/share/oops/arrayOop.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -80,8 +80,7 @@ class arrayOopDesc : public oopDesc { // The _length field is not declared in C++. It is allocated after the // mark-word when using compact headers (+UseCompactObjectHeaders), otherwise - // after the compressed Klass* when running with compressed class-pointers - // (+UseCompressedClassPointers), or else after the full Klass*. + // after the compressed Klass*. static int length_offset_in_bytes() { return oopDesc::base_offset_in_bytes(); } diff --git a/src/hotspot/share/oops/compressedKlass.cpp b/src/hotspot/share/oops/compressedKlass.cpp index b32d10c74d2..ca1c46d4095 100644 --- a/src/hotspot/share/oops/compressedKlass.cpp +++ b/src/hotspot/share/oops/compressedKlass.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -95,7 +95,7 @@ void CompressedKlassPointers::sanity_check_after_initialization() { // We should need a class space if address space is larger than what narrowKlass can address const bool should_need_class_space = (BytesPerWord * BitsPerByte) > narrow_klass_pointer_bits(); - ASSERT_HERE(should_need_class_space == needs_class_space()); + ASSERT_HERE(should_need_class_space == (INCLUDE_CLASS_SPACE ? true : false)); const size_t klass_align = klass_alignment_in_bytes(); @@ -318,24 +318,19 @@ void CompressedKlassPointers::initialize(address addr, size_t len) { } void CompressedKlassPointers::print_mode(outputStream* st) { - st->print_cr("UseCompressedClassPointers %d, UseCompactObjectHeaders %d", - UseCompressedClassPointers, UseCompactObjectHeaders); - if (UseCompressedClassPointers) { - st->print_cr("Narrow klass pointer bits %d, Max shift %d", - _narrow_klass_pointer_bits, _max_shift); - st->print_cr("Narrow klass base: " PTR_FORMAT ", Narrow klass shift: %d", - p2i(base()), shift()); - st->print_cr("Encoding Range: " RANGE2FMT, RANGE2FMTARGS(_base, encoding_range_end())); - st->print_cr("Klass Range: " RANGE2FMT, RANGE2FMTARGS(_klass_range_start, _klass_range_end)); - st->print_cr("Klass ID Range: [%u - %u) (%u)", _lowest_valid_narrow_klass_id, _highest_valid_narrow_klass_id + 1, - _highest_valid_narrow_klass_id + 1 - _lowest_valid_narrow_klass_id); - if (_protection_zone_size > 0) { - st->print_cr("Protection zone: " RANGEFMT, RANGEFMTARGS(_base, _protection_zone_size)); - } else { - st->print_cr("No protection zone."); - } + st->print_cr("UseCompactObjectHeaders %d", UseCompactObjectHeaders); + st->print_cr("Narrow klass pointer bits %d, Max shift %d", + _narrow_klass_pointer_bits, _max_shift); + st->print_cr("Narrow klass base: " PTR_FORMAT ", Narrow klass shift: %d", + p2i(base()), shift()); + st->print_cr("Encoding Range: " RANGE2FMT, RANGE2FMTARGS(_base, encoding_range_end())); + st->print_cr("Klass Range: " RANGE2FMT, RANGE2FMTARGS(_klass_range_start, _klass_range_end)); + st->print_cr("Klass ID Range: [%u - %u) (%u)", _lowest_valid_narrow_klass_id, _highest_valid_narrow_klass_id + 1, + _highest_valid_narrow_klass_id + 1 - _lowest_valid_narrow_klass_id); + if (_protection_zone_size > 0) { + st->print_cr("Protection zone: " RANGEFMT, RANGEFMTARGS(_base, _protection_zone_size)); } else { - st->print_cr("UseCompressedClassPointers off"); + st->print_cr("No protection zone."); } } diff --git a/src/hotspot/share/oops/compressedKlass.hpp b/src/hotspot/share/oops/compressedKlass.hpp index 98a9eafdbf4..fe1ce9e07ae 100644 --- a/src/hotspot/share/oops/compressedKlass.hpp +++ b/src/hotspot/share/oops/compressedKlass.hpp @@ -98,7 +98,6 @@ class Klass; // If compressed klass pointers then use narrowKlass. typedef juint narrowKlass; -// For UseCompressedClassPointers. class CompressedKlassPointers : public AllStatic { friend class VMStructs; friend class ArchiveBuilder; @@ -161,7 +160,6 @@ class CompressedKlassPointers : public AllStatic { // Initialization sequence: // 1) Parse arguments. The following arguments take a role: - // - UseCompressedClassPointers // - UseCompactObjectHeaders // - Xshare on off dump // - CompressedClassSpaceSize @@ -192,12 +190,6 @@ class CompressedKlassPointers : public AllStatic { // resulting from the current encoding settings (base, shift), capped to a certain max. value. static size_t max_klass_range_size(); - // On 64-bit, we need the class space to confine Klass structures to the encoding range, which is determined - // by bit size of narrowKlass IDs and the shift. On 32-bit, we support compressed class pointer only - // "pro-forma": narrowKlass have the same size as addresses (32 bits), and therefore the encoding range is - // equal to the address space size. Here, we don't need a class space. - static constexpr bool needs_class_space() { return LP64_ONLY(true) NOT_LP64(false); } - // Reserve a range of memory that is to contain Klass strucutures which are referenced by narrow Klass IDs. // If optimize_for_zero_base is true, the implementation will attempt to reserve optimized for zero-based encoding. static char* reserve_address_space_for_compressed_classes(size_t size, bool aslr, bool optimize_for_zero_base); diff --git a/src/hotspot/share/oops/compressedKlass.inline.hpp b/src/hotspot/share/oops/compressedKlass.inline.hpp index 65732b3b289..834264286bc 100644 --- a/src/hotspot/share/oops/compressedKlass.inline.hpp +++ b/src/hotspot/share/oops/compressedKlass.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -75,7 +75,6 @@ inline narrowKlass CompressedKlassPointers::encode(const Klass* v) { #ifdef ASSERT inline void CompressedKlassPointers::check_encodable(const void* addr) { - assert(UseCompressedClassPointers, "Only call for +UseCCP"); assert(addr != nullptr, "Null Klass?"); assert(is_encodable(addr), "Address " PTR_FORMAT " is not encodable (Klass range: " RANGEFMT ", klass alignment: %d)", @@ -84,7 +83,6 @@ inline void CompressedKlassPointers::check_encodable(const void* addr) { inline void CompressedKlassPointers::check_valid_narrow_klass_id(narrowKlass nk) { check_init(_base); - assert(UseCompressedClassPointers, "Only call for +UseCCP"); assert(nk > 0, "narrow Klass ID is 0"); const uint64_t nk_mask = ~right_n_bits(narrow_klass_pointer_bits()); assert(((uint64_t)nk & nk_mask) == 0, "narrow klass id bit spillover (%u)", nk); diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp index 919afbf3abd..d3333e72c2a 100644 --- a/src/hotspot/share/oops/instanceKlass.cpp +++ b/src/hotspot/share/oops/instanceKlass.cpp @@ -486,10 +486,8 @@ InstanceKlass* InstanceKlass::allocate_instance_klass(const ClassFileParser& par ik = new (loader_data, size, THREAD) InstanceKlass(parser); } - if (ik != nullptr && UseCompressedClassPointers) { - assert(CompressedKlassPointers::is_encodable(ik), - "Klass " PTR_FORMAT "needs a narrow Klass ID, but is not encodable", p2i(ik)); - } + assert(ik == nullptr || CompressedKlassPointers::is_encodable(ik), + "Klass " PTR_FORMAT "needs a narrow Klass ID, but is not encodable", p2i(ik)); // Check for pending exception before adding to the loader data and incrementing // class count. Can get OOM here. diff --git a/src/hotspot/share/oops/klass.cpp b/src/hotspot/share/oops/klass.cpp index 001e9eba790..84a1766a702 100644 --- a/src/hotspot/share/oops/klass.cpp +++ b/src/hotspot/share/oops/klass.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1055,14 +1055,8 @@ void Klass::verify_on(outputStream* st) { // This can be expensive, but it is worth checking that this klass is actually // in the CLD graph but not in production. -#ifdef ASSERT - if (UseCompressedClassPointers) { - // Stricter checks for both correct alignment and placement - CompressedKlassPointers::check_encodable(this); - } else { - assert(Metaspace::contains((address)this), "Should be"); - } -#endif // ASSERT + // Stricter checks for both correct alignment and placement + DEBUG_ONLY(CompressedKlassPointers::check_encodable(this)); guarantee(this->is_klass(),"should be klass"); diff --git a/src/hotspot/share/oops/objLayout.cpp b/src/hotspot/share/oops/objLayout.cpp index b8cd8249da1..2c426a7ddff 100644 --- a/src/hotspot/share/oops/objLayout.cpp +++ b/src/hotspot/share/oops/objLayout.cpp @@ -38,21 +38,17 @@ void ObjLayout::initialize() { _klass_mode = Compact; _oop_base_offset_in_bytes = sizeof(markWord); _oop_has_klass_gap = false; - } else if (UseCompressedClassPointers) { + } else { _klass_mode = Compressed; _oop_base_offset_in_bytes = sizeof(markWord) + sizeof(narrowKlass); _oop_has_klass_gap = true; - } else { - _klass_mode = Uncompressed; - _oop_base_offset_in_bytes = sizeof(markWord) + sizeof(Klass*); - _oop_has_klass_gap = false; } #else assert(_klass_mode == Undefined, "ObjLayout initialized twice"); assert(!UseCompactObjectHeaders, "COH unsupported on 32-bit"); - // We support +-UseCompressedClassPointers on 32-bit, but the layout + // We support narrow Klass pointers on 32-bit, but the layout // is exactly the same as it was with uncompressed klass pointers - _klass_mode = UseCompressedClassPointers ? Compressed : Uncompressed; + _klass_mode = Compressed; _oop_base_offset_in_bytes = sizeof(markWord) + sizeof(Klass*); _oop_has_klass_gap = false; #endif diff --git a/src/hotspot/share/oops/objLayout.hpp b/src/hotspot/share/oops/objLayout.hpp index e434524d4b0..37ed0b7a532 100644 --- a/src/hotspot/share/oops/objLayout.hpp +++ b/src/hotspot/share/oops/objLayout.hpp @@ -27,8 +27,8 @@ /* * This class helps to avoid loading more than one flag in some - * operations that require checking UseCompressedClassPointers, - * UseCompactObjectHeaders and possibly more. + * operations that require checking UseCompactObjectHeaders and - in the future - + * possibly more. * * This is important on some performance critical paths, e.g. where * the Klass* is accessed frequently, especially by GC oop iterators @@ -37,12 +37,10 @@ class ObjLayout { public: enum Mode { - // +UseCompactObjectHeaders (implies +UseCompressedClassPointers) + // +UseCompactObjectHeaders Compact, - // +UseCompressedClassPointers (-UseCompactObjectHeaders) + // -UseCompactObjectHeaders (compressed Klass pointers) Compressed, - // -UseCompressedClassPointers (-UseCompactObjectHeaders) - Uncompressed, // Not yet initialized Undefined }; diff --git a/src/hotspot/share/oops/objLayout.inline.hpp b/src/hotspot/share/oops/objLayout.inline.hpp index 6aa9e39ce28..adad490378d 100644 --- a/src/hotspot/share/oops/objLayout.inline.hpp +++ b/src/hotspot/share/oops/objLayout.inline.hpp @@ -32,10 +32,8 @@ inline ObjLayout::Mode ObjLayout::klass_mode() { assert(_klass_mode != Undefined, "KlassMode not yet initialized"); if (UseCompactObjectHeaders) { assert(_klass_mode == Compact, "Klass mode does not match flags"); - } else if (UseCompressedClassPointers) { - assert(_klass_mode == Compressed, "Klass mode does not match flags"); } else { - assert(_klass_mode == Uncompressed, "Klass mode does not match flags"); + assert(_klass_mode == Compressed, "Klass mode does not match flags"); } #endif return _klass_mode; diff --git a/src/hotspot/share/oops/oop.cpp b/src/hotspot/share/oops/oop.cpp index 5f453241c3d..415732af4f6 100644 --- a/src/hotspot/share/oops/oop.cpp +++ b/src/hotspot/share/oops/oop.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -152,8 +152,7 @@ bool oopDesc::is_typeArray_noinline() const { return is_typeArray(); } #if INCLUDE_CDS_JAVA_HEAP void oopDesc::set_narrow_klass(narrowKlass nk) { assert(CDSConfig::is_dumping_heap(), "Used by CDS only. Do not abuse!"); - assert(UseCompressedClassPointers, "must be"); - _metadata._compressed_klass = nk; + _compressed_klass = nk; } #endif diff --git a/src/hotspot/share/oops/oop.hpp b/src/hotspot/share/oops/oop.hpp index 0dc6590750e..d6cc71a60d8 100644 --- a/src/hotspot/share/oops/oop.hpp +++ b/src/hotspot/share/oops/oop.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,10 +49,7 @@ class oopDesc { friend class JVMCIVMStructs; private: volatile markWord _mark; - union _metadata { - Klass* _klass; - narrowKlass _compressed_klass; - } _metadata; + narrowKlass _compressed_klass; // There may be ordering constraints on the initialization of fields that // make use of the C++ copy/assign incorrect. @@ -338,7 +335,7 @@ class oopDesc { } else #endif { - return (int)offset_of(oopDesc, _metadata._klass); + return (int)offset_of(oopDesc, _compressed_klass); } } static int klass_gap_offset_in_bytes() { diff --git a/src/hotspot/share/oops/oop.inline.hpp b/src/hotspot/share/oops/oop.inline.hpp index b445eae933b..d5cb80e1122 100644 --- a/src/hotspot/share/oops/oop.inline.hpp +++ b/src/hotspot/share/oops/oop.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -99,9 +99,9 @@ Klass* oopDesc::klass() const { case ObjLayout::Compact: return mark().klass(); case ObjLayout::Compressed: - return CompressedKlassPointers::decode_not_null(_metadata._compressed_klass); + return CompressedKlassPointers::decode_not_null(_compressed_klass); default: - return _metadata._klass; + ShouldNotReachHere(); } } @@ -110,9 +110,9 @@ Klass* oopDesc::klass_or_null() const { case ObjLayout::Compact: return mark().klass_or_null(); case ObjLayout::Compressed: - return CompressedKlassPointers::decode(_metadata._compressed_klass); + return CompressedKlassPointers::decode(_compressed_klass); default: - return _metadata._klass; + ShouldNotReachHere(); } } @@ -121,11 +121,11 @@ Klass* oopDesc::klass_or_null_acquire() const { case ObjLayout::Compact: return mark_acquire().klass(); case ObjLayout::Compressed: { - narrowKlass narrow_klass = AtomicAccess::load_acquire(&_metadata._compressed_klass); + narrowKlass narrow_klass = AtomicAccess::load_acquire(&_compressed_klass); return CompressedKlassPointers::decode(narrow_klass); } default: - return AtomicAccess::load_acquire(&_metadata._klass); + ShouldNotReachHere(); } } @@ -134,9 +134,9 @@ Klass* oopDesc::klass_without_asserts() const { case ObjLayout::Compact: return mark().klass_without_asserts(); case ObjLayout::Compressed: - return CompressedKlassPointers::decode_without_asserts(_metadata._compressed_klass); + return CompressedKlassPointers::decode_without_asserts(_compressed_klass); default: - return _metadata._klass; + ShouldNotReachHere(); } } @@ -145,7 +145,7 @@ narrowKlass oopDesc::narrow_klass() const { case ObjLayout::Compact: return mark().narrow_klass(); case ObjLayout::Compressed: - return _metadata._compressed_klass; + return _compressed_klass; default: ShouldNotReachHere(); } @@ -154,23 +154,14 @@ narrowKlass oopDesc::narrow_klass() const { void oopDesc::set_klass(Klass* k) { assert(Universe::is_bootstrapping() || (k != nullptr && k->is_klass()), "incorrect Klass"); assert(!UseCompactObjectHeaders, "don't set Klass* with compact headers"); - if (UseCompressedClassPointers) { - _metadata._compressed_klass = CompressedKlassPointers::encode_not_null(k); - } else { - _metadata._klass = k; - } + _compressed_klass = CompressedKlassPointers::encode_not_null(k); } void oopDesc::release_set_klass(HeapWord* mem, Klass* k) { assert(Universe::is_bootstrapping() || (k != nullptr && k->is_klass()), "incorrect Klass"); assert(!UseCompactObjectHeaders, "don't set Klass* with compact headers"); char* raw_mem = ((char*)mem + klass_offset_in_bytes()); - if (UseCompressedClassPointers) { - AtomicAccess::release_store((narrowKlass*)raw_mem, - CompressedKlassPointers::encode_not_null(k)); - } else { - AtomicAccess::release_store((Klass**)raw_mem, k); - } + AtomicAccess::release_store((narrowKlass*)raw_mem, CompressedKlassPointers::encode_not_null(k)); } void oopDesc::set_klass_gap(HeapWord* mem, int v) { diff --git a/src/hotspot/share/opto/cfgnode.cpp b/src/hotspot/share/opto/cfgnode.cpp index a251a253ed1..0915f79a503 100644 --- a/src/hotspot/share/opto/cfgnode.cpp +++ b/src/hotspot/share/opto/cfgnode.cpp @@ -2689,7 +2689,7 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) { #ifdef _LP64 // Push DecodeN/DecodeNKlass down through phi. // The rest of phi graph will transform by split EncodeP node though phis up. - if ((UseCompressedOops || UseCompressedClassPointers) && can_reshape && progress == nullptr) { + if (can_reshape && progress == nullptr) { bool may_push = true; bool has_decodeN = false; bool is_decodeN = false; diff --git a/src/hotspot/share/opto/chaitin.cpp b/src/hotspot/share/opto/chaitin.cpp index 3ba3ffc1045..ef017ee15ec 100644 --- a/src/hotspot/share/opto/chaitin.cpp +++ b/src/hotspot/share/opto/chaitin.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -2633,7 +2633,7 @@ void PhaseChaitin::verify_base_ptrs(ResourceArea* a) const { #ifdef _LP64 (UseCompressedOops && check->as_Mach()->ideal_Opcode() == Op_CastPP) || (UseCompressedOops && check->as_Mach()->ideal_Opcode() == Op_DecodeN) || - (UseCompressedClassPointers && check->as_Mach()->ideal_Opcode() == Op_DecodeNKlass) || + (check->as_Mach()->ideal_Opcode() == Op_DecodeNKlass) || #endif // _LP64 check->as_Mach()->ideal_Opcode() == Op_LoadP || check->as_Mach()->ideal_Opcode() == Op_LoadKlass))) { diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index f34c75656a4..7ab384a29c7 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -3414,8 +3414,7 @@ void Compile::final_graph_reshaping_main_switch(Node* n, Final_Reshape_Counts& f Node *addp = n->in(AddPNode::Address); assert(n->as_AddP()->address_input_has_same_base(), "Base pointers must match (addp %u)", addp->_idx ); #ifdef _LP64 - if ((UseCompressedOops || UseCompressedClassPointers) && - addp->Opcode() == Op_ConP && + if (addp->Opcode() == Op_ConP && addp == n->in(AddPNode::Base) && n->in(AddPNode::Offset)->is_Con()) { // If the transformation of ConP to ConN+DecodeN is beneficial depends @@ -3428,7 +3427,7 @@ void Compile::final_graph_reshaping_main_switch(Node* n, Final_Reshape_Counts& f bool is_klass = t->isa_klassptr() != nullptr; if ((is_oop && UseCompressedOops && Matcher::const_oop_prefer_decode() ) || - (is_klass && UseCompressedClassPointers && Matcher::const_klass_prefer_decode() && + (is_klass && Matcher::const_klass_prefer_decode() && t->isa_klassptr()->exact_klass()->is_in_encoding_range())) { Node* nn = nullptr; @@ -3975,8 +3974,7 @@ void Compile::final_graph_reshaping_walk(Node_Stack& nstack, Node* root, Final_R } // Skip next transformation if compressed oops are not used. - if ((UseCompressedOops && !Matcher::gen_narrow_oop_implicit_null_checks()) || - (!UseCompressedOops && !UseCompressedClassPointers)) + if (UseCompressedOops && !Matcher::gen_narrow_oop_implicit_null_checks()) return; // Go over safepoints nodes to skip DecodeN/DecodeNKlass nodes for debug edges. diff --git a/src/hotspot/share/opto/lcm.cpp b/src/hotspot/share/opto/lcm.cpp index 53a503866fa..450d267e821 100644 --- a/src/hotspot/share/opto/lcm.cpp +++ b/src/hotspot/share/opto/lcm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -306,8 +306,7 @@ void PhaseCFG::implicit_null_check(Block* block, Node *proj, Node *val, int allo // cannot reason about it; is probably not implicit null exception } else { const TypePtr* tptr; - if ((UseCompressedOops && CompressedOops::shift() == 0) || - (UseCompressedClassPointers && CompressedKlassPointers::shift() == 0)) { + if ((UseCompressedOops && CompressedOops::shift() == 0) || CompressedKlassPointers::shift() == 0) { // 32-bits narrow oop can be the base of address expressions tptr = base->get_ptr_type(); } else { diff --git a/src/hotspot/share/opto/memnode.cpp b/src/hotspot/share/opto/memnode.cpp index 3cd553e4bd1..46f6729c82f 100644 --- a/src/hotspot/share/opto/memnode.cpp +++ b/src/hotspot/share/opto/memnode.cpp @@ -2486,7 +2486,6 @@ Node* LoadKlassNode::make(PhaseGVN& gvn, Node* mem, Node* adr, const TypePtr* at assert(adr_type != nullptr, "expecting TypeKlassPtr"); #ifdef _LP64 if (adr_type->is_ptr_to_narrowklass()) { - assert(UseCompressedClassPointers, "no compressed klasses"); Node* load_klass = gvn.transform(new LoadNKlassNode(mem, adr, at, tk->make_narrowklass(), MemNode::unordered)); return new DecodeNKlassNode(load_klass, load_klass->bottom_type()->make_ptr()); } @@ -2816,8 +2815,7 @@ StoreNode* StoreNode::make(PhaseGVN& gvn, Node* ctl, Node* mem, Node* adr, const val = gvn.transform(new EncodePNode(val, val->bottom_type()->make_narrowoop())); return new StoreNNode(ctl, mem, adr, adr_type, val, mo); } else if (adr->bottom_type()->is_ptr_to_narrowklass() || - (UseCompressedClassPointers && val->bottom_type()->isa_klassptr() && - adr->bottom_type()->isa_rawptr())) { + (val->bottom_type()->isa_klassptr() && adr->bottom_type()->isa_rawptr())) { val = gvn.transform(new EncodePKlassNode(val, val->bottom_type()->make_narrowklass())); return new StoreNKlassNode(ctl, mem, adr, adr_type, val, mo); } diff --git a/src/hotspot/share/opto/narrowptrnode.cpp b/src/hotspot/share/opto/narrowptrnode.cpp index 7f86b8caecf..8b91bfaa944 100644 --- a/src/hotspot/share/opto/narrowptrnode.cpp +++ b/src/hotspot/share/opto/narrowptrnode.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -102,7 +102,7 @@ const Type* EncodePKlassNode::Value(PhaseGVN* phase) const { if (t == Type::TOP) return Type::TOP; assert (t != TypePtr::NULL_PTR, "null klass?"); - assert(UseCompressedClassPointers && t->isa_klassptr(), "only klass ptr here"); + assert(t->isa_klassptr(), "only klass ptr here"); return t->make_narrowklass(); } diff --git a/src/hotspot/share/opto/type.cpp b/src/hotspot/share/opto/type.cpp index aab2ea3cd3b..308ec819773 100644 --- a/src/hotspot/share/opto/type.cpp +++ b/src/hotspot/share/opto/type.cpp @@ -3489,7 +3489,7 @@ TypeOopPtr::TypeOopPtr(TYPES t, PTR ptr, ciKlass* k, const TypeInterfaces* inter #ifdef _LP64 if (_offset > 0 || _offset == Type::OffsetTop || _offset == Type::OffsetBot) { if (_offset == oopDesc::klass_offset_in_bytes()) { - _is_ptr_to_narrowklass = UseCompressedClassPointers; + _is_ptr_to_narrowklass = true; } else if (klass() == nullptr) { // Array with unknown body type assert(this->isa_aryptr(), "only arrays without klass"); diff --git a/src/hotspot/share/prims/whitebox.cpp b/src/hotspot/share/prims/whitebox.cpp index 5df1461c0fd..a13d0ba47c8 100644 --- a/src/hotspot/share/prims/whitebox.cpp +++ b/src/hotspot/share/prims/whitebox.cpp @@ -333,7 +333,6 @@ WB_ENTRY(void, WB_ReadFromNoaccessArea(JNIEnv* env, jobject o)) WB_END WB_ENTRY(void, WB_DecodeNKlassAndAccessKlass(JNIEnv* env, jobject o, jint nKlass)) - assert(UseCompressedClassPointers, "Should only call for UseCompressedClassPointers"); const narrowKlass nk = (narrowKlass)nKlass; const Klass* const k = CompressedKlassPointers::decode_not_null_without_asserts(nKlass); printf("WB_DecodeNKlassAndAccessKlass: nk %u k " PTR_FORMAT "\n", nk, p2i(k)); diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index dac34017e45..1d79c4d0488 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -1554,7 +1554,7 @@ void Arguments::set_heap_size() { } #ifdef _LP64 - if (UseCompressedOops || UseCompressedClassPointers) { + if (UseCompressedOops) { // HeapBaseMinAddress can be greater than default but not less than. if (!FLAG_IS_DEFAULT(HeapBaseMinAddress)) { if (HeapBaseMinAddress < DefaultHeapBaseMinAddress) { @@ -1567,9 +1567,7 @@ void Arguments::set_heap_size() { FLAG_SET_ERGO(HeapBaseMinAddress, DefaultHeapBaseMinAddress); } } - } - if (UseCompressedOops) { uintptr_t heap_end = HeapBaseMinAddress + MaxHeapSize; uintptr_t max_coop_heap = max_heap_for_compressed_oops(); @@ -3782,10 +3780,6 @@ jint Arguments::parse(const JavaVMInitArgs* initial_cmd_args) { void Arguments::set_compact_headers_flags() { #ifdef _LP64 - if (UseCompactObjectHeaders && FLAG_IS_CMDLINE(UseCompressedClassPointers) && !UseCompressedClassPointers) { - warning("Compact object headers require compressed class pointers. Disabling compact object headers."); - FLAG_SET_DEFAULT(UseCompactObjectHeaders, false); - } if (UseCompactObjectHeaders && !UseObjectMonitorTable) { // If UseCompactObjectHeaders is on the command line, turn on UseObjectMonitorTable. if (FLAG_IS_CMDLINE(UseCompactObjectHeaders)) { @@ -3799,9 +3793,6 @@ void Arguments::set_compact_headers_flags() { FLAG_SET_DEFAULT(UseObjectMonitorTable, true); } } - if (UseCompactObjectHeaders && !UseCompressedClassPointers) { - FLAG_SET_DEFAULT(UseCompressedClassPointers, true); - } #endif } @@ -3817,9 +3808,7 @@ jint Arguments::apply_ergo() { set_compact_headers_flags(); - if (UseCompressedClassPointers) { - CompressedKlassPointers::pre_initialize(); - } + CompressedKlassPointers::pre_initialize(); CDSConfig::ergo_initialize(); @@ -3864,10 +3853,6 @@ jint Arguments::apply_ergo() { DebugNonSafepoints = true; } - if (FLAG_IS_CMDLINE(CompressedClassSpaceSize) && !UseCompressedClassPointers) { - warning("Setting CompressedClassSpaceSize has no effect when compressed class pointers are not used"); - } - // Treat the odd case where local verification is enabled but remote // verification is not as if both were enabled. if (BytecodeVerificationLocal && !BytecodeVerificationRemote) { diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index 60feddde09b..b5c19d8aa36 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -1368,9 +1368,6 @@ const int ObjectAlignmentInBytes = 8; "Maximum size of Metaspaces (in bytes)") \ constraint(MaxMetaspaceSizeConstraintFunc,AfterErgo) \ \ - product(bool, UseCompressedClassPointers, true, \ - "(Deprecated) Use 32-bit class pointers.") \ - \ product(size_t, CompressedClassSpaceSize, 1*G, \ "Maximum size of class area in Metaspace when compressed " \ "class pointers are used") \ diff --git a/src/hotspot/share/runtime/os.cpp b/src/hotspot/share/runtime/os.cpp index 129f8f76e73..d55cf454256 100644 --- a/src/hotspot/share/runtime/os.cpp +++ b/src/hotspot/share/runtime/os.cpp @@ -1285,7 +1285,7 @@ void os::print_location(outputStream* st, intptr_t x, bool verbose) { bool accessible = is_readable_pointer(addr); // Check if addr points into the narrow Klass protection zone - if (UseCompressedClassPointers && CompressedKlassPointers::is_in_protection_zone(addr)) { + if (CompressedKlassPointers::is_in_protection_zone(addr)) { st->print_cr(PTR_FORMAT " points into nKlass protection zone", p2i(addr)); return; } @@ -1339,8 +1339,9 @@ void os::print_location(outputStream* st, intptr_t x, bool verbose) { } // Compressed klass needs to be decoded first. + // Todo: questionable for COH - can we do this better? #ifdef _LP64 - if (UseCompressedClassPointers && ((uintptr_t)addr &~ (uintptr_t)max_juint) == 0) { + if (((uintptr_t)addr &~ (uintptr_t)max_juint) == 0) { narrowKlass narrow_klass = (narrowKlass)(uintptr_t)addr; Klass* k = CompressedKlassPointers::decode_without_asserts(narrow_klass); diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp index b6294a9a168..ad9463443b2 100644 --- a/src/hotspot/share/runtime/vmStructs.cpp +++ b/src/hotspot/share/runtime/vmStructs.cpp @@ -163,8 +163,7 @@ /******************************************************************/ \ \ volatile_nonstatic_field(oopDesc, _mark, markWord) \ - volatile_nonstatic_field(oopDesc, _metadata._klass, Klass*) \ - volatile_nonstatic_field(oopDesc, _metadata._compressed_klass, narrowKlass) \ + volatile_nonstatic_field(oopDesc, _compressed_klass, narrowKlass) \ static_field(BarrierSet, _barrier_set, BarrierSet*) \ nonstatic_field(ArrayKlass, _dimension, const int) \ volatile_nonstatic_field(ArrayKlass, _higher_dimension, ObjArrayKlass*) \ diff --git a/src/hotspot/share/services/memoryService.cpp b/src/hotspot/share/services/memoryService.cpp index f64da3c5477..4636f125079 100644 --- a/src/hotspot/share/services/memoryService.cpp +++ b/src/hotspot/share/services/memoryService.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -119,11 +119,11 @@ void MemoryService::add_metaspace_memory_pools() { mgr->add_pool(_metaspace_pool); _pools_list->append(_metaspace_pool); - if (UseCompressedClassPointers) { - _compressed_class_pool = new CompressedKlassSpacePool(); - mgr->add_pool(_compressed_class_pool); - _pools_list->append(_compressed_class_pool); - } +#if INCLUDE_CLASS_SPACE + _compressed_class_pool = new CompressedKlassSpacePool(); + mgr->add_pool(_compressed_class_pool); + _pools_list->append(_compressed_class_pool); +#endif _managers_list->append(mgr); } diff --git a/src/hotspot/share/utilities/macros.hpp b/src/hotspot/share/utilities/macros.hpp index a03255b5cf3..3621f675ecb 100644 --- a/src/hotspot/share/utilities/macros.hpp +++ b/src/hotspot/share/utilities/macros.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -586,6 +586,18 @@ #define BIG_ENDIAN_ONLY(code) code #endif +#ifdef _LP64 +#define INCLUDE_CLASS_SPACE 1 +#define CLASS_SPACE_ONLY(x) x +#define NOT_CLASS_SPACE(x) +#else +// On 32-bit we use fake "narrow class pointers" which are really just 32-bit pointers, +// but we don't use a class space (would cause too much address space fragmentation) +#define INCLUDE_CLASS_SPACE 0 +#define CLASS_SPACE_ONLY(x) +#define NOT_CLASS_SPACE(x) x +#endif + #define define_pd_global(type, name, value) const type pd_##name = value; // Helper macros for constructing file names for includes. diff --git a/src/hotspot/share/utilities/vmError.cpp b/src/hotspot/share/utilities/vmError.cpp index 48fae6868ab..d78fd331b56 100644 --- a/src/hotspot/share/utilities/vmError.cpp +++ b/src/hotspot/share/utilities/vmError.cpp @@ -533,8 +533,7 @@ static void report_vm_version(outputStream* st, char* buf, int buflen) { "", "", #endif UseCompressedOops ? ", compressed oops" : "", - UseCompactObjectHeaders ? ", compact obj headers" - : (UseCompressedClassPointers ? ", compressed class ptrs" : ""), + UseCompactObjectHeaders ? ", compact obj headers" : "", GCConfig::hs_err_name(), VM_Version::vm_platform_string() ); @@ -1215,7 +1214,7 @@ void VMError::report(outputStream* st, bool _verbose) { CompressedOops::print_mode(st); st->cr(); - STEP_IF("printing compressed klass pointers mode", _verbose && UseCompressedClassPointers) + STEP_IF("printing compressed klass pointers mode", _verbose) CDS_ONLY(AOTMetaspace::print_on(st);) Metaspace::print_compressed_class_space(st); CompressedKlassPointers::print_mode(st); @@ -1437,12 +1436,10 @@ void VMError::print_vm_info(outputStream* st) { #endif // STEP("printing compressed class ptrs mode") - if (UseCompressedClassPointers) { - CDS_ONLY(AOTMetaspace::print_on(st);) - Metaspace::print_compressed_class_space(st); - CompressedKlassPointers::print_mode(st); - st->cr(); - } + CDS_ONLY(AOTMetaspace::print_on(st);) + Metaspace::print_compressed_class_space(st); + CompressedKlassPointers::print_mode(st); + st->cr(); // Take heap lock over heap, GC and metaspace printing so that information // is consistent. diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Array.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Array.java index c4eeaf4a367..61067e63707 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Array.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Array.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -83,10 +83,8 @@ private static long lengthOffsetInBytes() { } if (VM.getVM().isCompactObjectHeadersEnabled()) { lengthOffsetInBytes = Oop.getHeaderSize(); - } else if (VM.getVM().isCompressedKlassPointersEnabled()) { - lengthOffsetInBytes = typeSize - VM.getVM().getIntSize(); } else { - lengthOffsetInBytes = typeSize; + lengthOffsetInBytes = typeSize - VM.getVM().getIntSize(); } return lengthOffsetInBytes; } diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Instance.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Instance.java index 66efbe3484a..fea4fdaabc2 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Instance.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Instance.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,10 +57,8 @@ private static synchronized void initialize(TypeDataBase db) throws WrongTypeExc public static long getHeaderSize() { if (VM.getVM().isCompactObjectHeadersEnabled()) { return Oop.getHeaderSize(); - } else if (VM.getVM().isCompressedKlassPointersEnabled()) { - return typeSize - VM.getVM().getIntSize(); } else { - return typeSize; + return typeSize - VM.getVM().getIntSize(); } } diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Oop.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Oop.java index 75ad4ab1d66..951499974fa 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Oop.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Oop.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,8 +51,7 @@ private static synchronized void initialize(TypeDataBase db) throws WrongTypeExc headerSize = markType.getSize(); } else { headerSize = type.getSize(); - klass = new MetadataField(type.getAddressField("_metadata._klass"), 0); - compressedKlass = new NarrowKlassField(type.getAddressField("_metadata._compressed_klass"), 0); + compressedKlass = new NarrowKlassField(type.getAddressField("_compressed_klass"), 0); } } @@ -75,7 +74,6 @@ private static synchronized void initialize(TypeDataBase db) throws WrongTypeExc public static long getHeaderSize() { return headerSize; } // Header size in bytes. private static CIntField mark; - private static MetadataField klass; private static NarrowKlassField compressedKlass; // Accessors for declared fields @@ -83,12 +81,9 @@ private static synchronized void initialize(TypeDataBase db) throws WrongTypeExc public Klass getKlass() { if (VM.getVM().isCompactObjectHeadersEnabled()) { - assert(VM.getVM().isCompressedKlassPointersEnabled()); return getMark().getKlass(); - } else if (VM.getVM().isCompressedKlassPointersEnabled()) { - return (Klass)compressedKlass.getValue(getHandle()); } else { - return (Klass)klass.getValue(getHandle()); + return (Klass)compressedKlass.getValue(getHandle()); } } @@ -157,11 +152,7 @@ void iterateFields(OopVisitor visitor, boolean doVMFields) { if (doVMFields) { visitor.doCInt(mark, true); if (!VM.getVM().isCompactObjectHeadersEnabled()) { - if (VM.getVM().isCompressedKlassPointersEnabled()) { - visitor.doMetadata(compressedKlass, true); - } else { - visitor.doMetadata(klass, true); - } + visitor.doMetadata(compressedKlass, true); } } } @@ -220,10 +211,8 @@ public static Klass getKlassForOopHandle(OopHandle handle) { if (VM.getVM().isCompactObjectHeadersEnabled()) { Mark mark = new Mark(handle); return mark.getKlass(); - } else if (VM.getVM().isCompressedKlassPointersEnabled()) { - return (Klass)Metadata.instantiateWrapperFor(handle.getCompKlassAddressAt(compressedKlass.getOffset())); } else { - return (Klass)Metadata.instantiateWrapperFor(handle.getAddressAt(klass.getOffset())); + return (Klass)Metadata.instantiateWrapperFor(handle.getCompKlassAddressAt(compressedKlass.getOffset())); } } }; diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java index 1607563150a..2ec96121934 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -144,7 +144,6 @@ public class VM { private static CIntegerType boolType; private Boolean sharingEnabled; private Boolean compressedOopsEnabled; - private Boolean compressedKlassPointersEnabled; private Boolean compactObjectHeadersEnabled; // command line flags supplied to VM - see struct JVMFlag in jvmFlag.hpp @@ -515,11 +514,7 @@ private VM(TypeDataBase db, JVMDebugger debugger, boolean isBigEndian) { heapOopSize = (int)getOopSize(); } - if (isCompressedKlassPointersEnabled()) { - klassPtrSize = (int)getIntSize(); - } else { - klassPtrSize = (int)getOopSize(); // same as an oop - } + klassPtrSize = (int)getIntSize(); } /** This could be used by a reflective runtime system */ @@ -938,15 +933,6 @@ public boolean isCompressedOopsEnabled() { return compressedOopsEnabled.booleanValue(); } - public boolean isCompressedKlassPointersEnabled() { - if (compressedKlassPointersEnabled == null) { - Flag flag = getCommandLineFlag("UseCompressedClassPointers"); - compressedKlassPointersEnabled = (flag == null) ? Boolean.FALSE: - (flag.getBool()? Boolean.TRUE: Boolean.FALSE); - } - return compressedKlassPointersEnabled.booleanValue(); - } - public boolean isCompactObjectHeadersEnabled() { if (compactObjectHeadersEnabled == null) { Flag flag = getCommandLineFlag("UseCompactObjectHeaders"); diff --git a/test/hotspot/gtest/metaspace/test_is_metaspace_obj.cpp b/test/hotspot/gtest/metaspace/test_is_metaspace_obj.cpp index a35888c62e2..c1b4abfb355 100644 --- a/test/hotspot/gtest/metaspace/test_is_metaspace_obj.cpp +++ b/test/hotspot/gtest/metaspace/test_is_metaspace_obj.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, 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. * @@ -65,8 +65,8 @@ class MetaspaceIsMetaspaceObjTest { // Test VirtualSpaceList::contains const VirtualSpaceList* const vslist = - (mdType == Metaspace::ClassType && Metaspace::using_class_space()) ? - VirtualSpaceList::vslist_class() : VirtualSpaceList::vslist_nonclass(); + (mdType == Metaspace::ClassType && INCLUDE_CLASS_SPACE) ? + VirtualSpaceList::vslist_class() : VirtualSpaceList::vslist_nonclass(); ASSERT_TRUE(vslist->contains((MetaWord*)p)); diff --git a/test/hotspot/gtest/metaspace/test_metaspaceUtils.cpp b/test/hotspot/gtest/metaspace/test_metaspaceUtils.cpp index 49ab816c4a0..68deb283784 100644 --- a/test/hotspot/gtest/metaspace/test_metaspaceUtils.cpp +++ b/test/hotspot/gtest/metaspace/test_metaspaceUtils.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, 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. * @@ -37,15 +37,15 @@ TEST_VM(metaspace, MetaspaceUtils_reserved) { EXPECT_LE(reserved_metadata, reserved); } +#if INCLUDE_CLASS_SPACE TEST_VM(metaspace, MetaspaceUtils_reserved_compressed_class_pointers) { - if (UseCompressedClassPointers && CompressedKlassPointers::needs_class_space()) { - size_t reserved = MetaspaceUtils::reserved_bytes(); - EXPECT_GT(reserved, 0UL); - size_t reserved_class = MetaspaceUtils::reserved_bytes(Metaspace::ClassType); - EXPECT_GT(reserved_class, 0UL); - EXPECT_LE(reserved_class, reserved); - } + size_t reserved = MetaspaceUtils::reserved_bytes(); + EXPECT_GT(reserved, 0UL); + size_t reserved_class = MetaspaceUtils::reserved_bytes(Metaspace::ClassType); + EXPECT_GT(reserved_class, 0UL); + EXPECT_LE(reserved_class, reserved); } +#endif // INCLUDE_CLASS_SPACE TEST_VM(metaspace, MetaspaceUtils_committed) { size_t committed = MetaspaceUtils::committed_bytes(); @@ -59,30 +59,15 @@ TEST_VM(metaspace, MetaspaceUtils_committed) { EXPECT_LE(committed_metadata, committed); } +#if INCLUDE_CLASS_SPACE TEST_VM(metaspace, MetaspaceUtils_committed_compressed_class_pointers) { - if (UseCompressedClassPointers && CompressedKlassPointers::needs_class_space()) { - size_t committed = MetaspaceUtils::committed_bytes(); - EXPECT_GT(committed, 0UL); - size_t committed_class = MetaspaceUtils::committed_bytes(Metaspace::ClassType); - EXPECT_GT(committed_class, 0UL); - EXPECT_LE(committed_class, committed); - } -} - -TEST_VM(metaspace, MetaspaceUtils_non_compressed_class_pointers) { - if (UseCompressedClassPointers) { - return; - } - + size_t committed = MetaspaceUtils::committed_bytes(); + EXPECT_GT(committed, 0UL); size_t committed_class = MetaspaceUtils::committed_bytes(Metaspace::ClassType); - EXPECT_EQ(committed_class, 0UL); - - size_t used_class = MetaspaceUtils::used_bytes(Metaspace::ClassType); - EXPECT_EQ(used_class, 0UL); - - size_t reserved_class = MetaspaceUtils::reserved_bytes(Metaspace::ClassType); - EXPECT_EQ(reserved_class, 0UL); + EXPECT_GT(committed_class, 0UL); + EXPECT_LE(committed_class, committed); } +#endif // INCLUDE_CLASS_SPACE static void check_metaspace_stats_are_consistent(const MetaspaceStats& stats) { EXPECT_LE(stats.committed(), stats.reserved()); @@ -102,13 +87,13 @@ TEST_VM(MetaspaceUtils, MetaspaceUtils_get_statistics) { check_metaspace_stats_are_not_null(combined_stats.non_class_space_stats()); check_metaspace_stats_are_consistent(combined_stats.non_class_space_stats()); - if (CompressedKlassPointers::needs_class_space() && UseCompressedClassPointers) { - check_metaspace_stats_are_not_null(combined_stats.class_space_stats()); - check_metaspace_stats_are_consistent(combined_stats.class_space_stats()); - } else { - // if we don't have a class space, combined stats should equal non-class stats - EXPECT_EQ(combined_stats.non_class_space_stats().reserved(), combined_stats.reserved()); - EXPECT_EQ(combined_stats.non_class_space_stats().committed(), combined_stats.committed()); - EXPECT_EQ(combined_stats.non_class_space_stats().used(), combined_stats.used()); - } +#if INCLUDE_CLASS_SPACE + check_metaspace_stats_are_not_null(combined_stats.class_space_stats()); + check_metaspace_stats_are_consistent(combined_stats.class_space_stats()); +#else + // if we don't have a class space, combined stats should equal non-class stats + EXPECT_EQ(combined_stats.non_class_space_stats().reserved(), combined_stats.reserved()); + EXPECT_EQ(combined_stats.non_class_space_stats().committed(), combined_stats.committed()); + EXPECT_EQ(combined_stats.non_class_space_stats().used(), combined_stats.used()); +#endif // INCLUDE_CLASS_SPACE } diff --git a/test/hotspot/gtest/oops/test_arrayOop.cpp b/test/hotspot/gtest/oops/test_arrayOop.cpp index 33163de427c..bb5f54b3f58 100644 --- a/test/hotspot/gtest/oops/test_arrayOop.cpp +++ b/test/hotspot/gtest/oops/test_arrayOop.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -97,7 +97,7 @@ TEST_VM(arrayOopDesc, base_offset) { EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_OBJECT), 16); EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_ARRAY), 16); } - } else if (UseCompressedClassPointers) { + } else { EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_BOOLEAN), 16); EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_BYTE), 16); EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_SHORT), 16); @@ -108,22 +108,6 @@ TEST_VM(arrayOopDesc, base_offset) { EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_DOUBLE), 16); EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_OBJECT), 16); EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_ARRAY), 16); - } else { - EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_BOOLEAN), 20); - EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_BYTE), 20); - EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_SHORT), 20); - EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_CHAR), 20); - EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_INT), 20); - EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_FLOAT), 20); - EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_LONG), 24); - EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_DOUBLE), 24); - if (UseCompressedOops) { - EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_OBJECT), 20); - EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_ARRAY), 20); - } else { - EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_OBJECT), 24); - EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_ARRAY), 24); - } } #else EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_BOOLEAN), 12); diff --git a/test/hotspot/gtest/oops/test_compressedKlass.cpp b/test/hotspot/gtest/oops/test_compressedKlass.cpp index dcdb335adb5..5a7323edc03 100644 --- a/test/hotspot/gtest/oops/test_compressedKlass.cpp +++ b/test/hotspot/gtest/oops/test_compressedKlass.cpp @@ -29,9 +29,6 @@ #include "unittest.hpp" TEST_VM(CompressedKlass, basics) { - if (!UseCompressedClassPointers) { - return; - } ASSERT_LE(CompressedKlassPointers::base(), CompressedKlassPointers::klass_range_start()); ASSERT_LT(CompressedKlassPointers::klass_range_start(), CompressedKlassPointers::klass_range_end()); ASSERT_LE(CompressedKlassPointers::klass_range_end(), CompressedKlassPointers::encoding_range_end()); @@ -54,22 +51,7 @@ TEST_VM(CompressedKlass, basics) { #endif // _LP64 } -TEST_VM(CompressedKlass, ccp_off) { - if (UseCompressedClassPointers) { - return; - } - ASSERT_EQ(CompressedKlassPointers::klass_range_start(), (address)nullptr); - ASSERT_EQ(CompressedKlassPointers::klass_range_end(), (address)nullptr); - // We should be able to call CompressedKlassPointers::is_encodable, and it should - // always return false - ASSERT_FALSE(CompressedKlassPointers::is_encodable((address)0x12345)); -} - - TEST_VM(CompressedKlass, test_too_low_address) { - if (!UseCompressedClassPointers) { - return; - } address really_low = (address) 32; ASSERT_FALSE(CompressedKlassPointers::is_encodable(really_low)); address low = CompressedKlassPointers::klass_range_start() - 1; @@ -77,9 +59,6 @@ TEST_VM(CompressedKlass, test_too_low_address) { } TEST_VM(CompressedKlass, test_too_high_address) { - if (!UseCompressedClassPointers) { - return; - } address really_high = (address) UINTPTR_MAX; ASSERT_FALSE(CompressedKlassPointers::is_encodable(really_high)); address high = CompressedKlassPointers::klass_range_end(); @@ -87,9 +66,6 @@ TEST_VM(CompressedKlass, test_too_high_address) { } TEST_VM(CompressedKlass, test_unaligned_address) { - if (!UseCompressedClassPointers) { - return; - } const size_t alignment = CompressedKlassPointers::klass_alignment_in_bytes(); address addr = CompressedKlassPointers::klass_range_start() + alignment - 1; ASSERT_FALSE(CompressedKlassPointers::is_encodable(addr)); @@ -103,9 +79,6 @@ TEST_VM(CompressedKlass, test_unaligned_address) { } TEST_VM(CompressedKlass, test_good_address) { - if (!UseCompressedClassPointers) { - return; - } const size_t alignment = CompressedKlassPointers::klass_alignment_in_bytes(); address addr = CompressedKlassPointers::klass_range_start(); ASSERT_TRUE(CompressedKlassPointers::is_encodable(addr)); @@ -114,9 +87,6 @@ TEST_VM(CompressedKlass, test_good_address) { } TEST_VM(CompressedKlass, test_is_valid_narrow_klass) { - if (!UseCompressedClassPointers) { - return; - } ASSERT_FALSE(CompressedKlassPointers::is_valid_narrow_klass_id(0)); narrowKlass nk_jlC = CompressedKlassPointers::encode((Klass*)vmClasses::Class_klass()); ASSERT_TRUE(CompressedKlassPointers::is_valid_narrow_klass_id(nk_jlC)); diff --git a/test/hotspot/gtest/oops/test_objArrayOop.cpp b/test/hotspot/gtest/oops/test_objArrayOop.cpp index 22c9b2efc11..f6a53a3031f 100644 --- a/test/hotspot/gtest/oops/test_objArrayOop.cpp +++ b/test/hotspot/gtest/oops/test_objArrayOop.cpp @@ -27,35 +27,29 @@ TEST_VM(objArrayOop, osize) { static const struct { - int objal; bool ccp; bool coops; bool coh; int result; + int objal; bool coops; bool coh; int result; } x[] = { -// ObjAligInB, UseCCP, UseCoops, UseCOH, object size in heap words +// ObjAligInB, UseCoops, UseCOH, object size in heap words #ifdef _LP64 - { 8, false, false, false, 4 }, // 20 byte header, 8 byte oops - { 8, false, true, false, 3 }, // 20 byte header, 4 byte oops - { 8, true, false, false, 3 }, // 16 byte header, 8 byte oops - { 8, true, true, false, 3 }, // 16 byte header, 4 byte oops - { 8, true, false, true, 3 }, // 12 byte header, 8 byte oops - { 8, true, true, true, 2 }, // 12 byte header, 4 byte oops - { 16, false, false, false, 4 }, // 20 byte header, 8 byte oops, 16-byte align - { 16, false, true, false, 4 }, // 20 byte header, 4 byte oops, 16-byte align - { 16, true, false, false, 4 }, // 16 byte header, 8 byte oops, 16-byte align - { 16, true, true, false, 4 }, // 16 byte header, 4 byte oops, 16-byte align - { 16, true, false, true, 4 }, // 12 byte header, 8 byte oops, 16-byte align - { 16, true, true, true, 2 }, // 12 byte header, 4 byte oops, 16-byte align - { 256, false, false, false, 32 }, // 20 byte header, 8 byte oops, 256-byte align - { 256, false, true, false, 32 }, // 20 byte header, 4 byte oops, 256-byte align - { 256, true, false, false, 32 }, // 16 byte header, 8 byte oops, 256-byte align - { 256, true, true, false, 32 }, // 16 byte header, 4 byte oops, 256-byte align - { 256, true, false, true, 32 }, // 12 byte header, 8 byte oops, 256-byte align - { 256, true, true, true, 32 }, // 12 byte header, 4 byte oops, 256-byte align + { 8, false, false, 3 }, // 16 byte header, 8 byte oops + { 8, true, false, 3 }, // 16 byte header, 4 byte oops + { 8, false, true, 3 }, // 12 byte header, 8 byte oops + { 8, true, true, 2 }, // 12 byte header, 4 byte oops + { 16, false, false, 4 }, // 16 byte header, 8 byte oops, 16-byte align + { 16, true, false, 4 }, // 16 byte header, 4 byte oops, 16-byte align + { 16, false, true, 4 }, // 12 byte header, 8 byte oops, 16-byte align + { 16, true, true, 2 }, // 12 byte header, 4 byte oops, 16-byte align + { 256, false, false, 32 }, // 16 byte header, 8 byte oops, 256-byte align + { 256, true, false, 32 }, // 16 byte header, 4 byte oops, 256-byte align + { 256, false, true, 32 }, // 12 byte header, 8 byte oops, 256-byte align + { 256, true, true, 32 }, // 12 byte header, 4 byte oops, 256-byte align #else - { 8, false, false, false, 4 }, // 12 byte header, 4 byte oops, wordsize 4 + { 8, false, false, 4 }, // 12 byte header, 4 byte oops, wordsize 4 #endif - { -1, false, false, false, -1 } + { -1, false, false, -1 } }; for (int i = 0; x[i].result != -1; i++) { - if (x[i].objal == (int)ObjectAlignmentInBytes && x[i].ccp == UseCompressedClassPointers && x[i].coops == UseCompressedOops && + if (x[i].objal == (int)ObjectAlignmentInBytes && x[i].coops == UseCompressedOops && x[i].coh == UseCompactObjectHeaders) { EXPECT_EQ(objArrayOopDesc::object_size(1), (size_t)x[i].result); } diff --git a/test/hotspot/jtreg/compiler/arraycopy/TestObjectArrayClone.java b/test/hotspot/jtreg/compiler/arraycopy/TestObjectArrayClone.java index b7e5b135c64..595205055ee 100644 --- a/test/hotspot/jtreg/compiler/arraycopy/TestObjectArrayClone.java +++ b/test/hotspot/jtreg/compiler/arraycopy/TestObjectArrayClone.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,10 +34,6 @@ * @run main/othervm -XX:CompileCommand=compileonly,compiler.arraycopy.TestObjectArrayClone::testClone* * -XX:CompileCommand=compileonly,jdk.internal.reflect.GeneratedMethodAccessor*::invoke * compiler.arraycopy.TestObjectArrayClone - * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-UseCompressedClassPointers -Xmx128m - * -XX:CompileCommand=compileonly,compiler.arraycopy.TestObjectArrayClone::testClone* - * -XX:CompileCommand=compileonly,jdk.internal.reflect.GeneratedMethodAccessor*::invoke - * compiler.arraycopy.TestObjectArrayClone * @run main/othervm -Xbatch -XX:-UseTypeProfile * -XX:CompileCommand=compileonly,compiler.arraycopy.TestObjectArrayClone::testClone* * -XX:CompileCommand=compileonly,jdk.internal.reflect.GeneratedMethodAccessor*::invoke diff --git a/test/hotspot/jtreg/compiler/c1/TestArrayCopyToFromObject.java b/test/hotspot/jtreg/compiler/c1/TestArrayCopyToFromObject.java index 98c8c24dd3a..176226806a6 100644 --- a/test/hotspot/jtreg/compiler/c1/TestArrayCopyToFromObject.java +++ b/test/hotspot/jtreg/compiler/c1/TestArrayCopyToFromObject.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,8 +25,7 @@ * @test * @bug 8160591 * @summary C1-generated code for System.arraycopy() does not throw an ArrayStoreException if 'dst' is no a "proper" array (i.e., it is java.lang.Object) - * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -Xcomp -XX:-UseCompressedClassPointers -XX:CompileOnly=TestArrayCopyToFromObject::test TestArrayCopyToFromObject - * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -Xcomp -XX:+UseCompressedClassPointers -XX:CompileOnly=TestArrayCopyToFromObject::test TestArrayCopyToFromObject + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -Xcomp -XX:CompileOnly=TestArrayCopyToFromObject::test TestArrayCopyToFromObject */ public class TestArrayCopyToFromObject { diff --git a/test/hotspot/jtreg/compiler/c2/TestReduceAllocationAndLoadKlass.java b/test/hotspot/jtreg/compiler/c2/TestReduceAllocationAndLoadKlass.java deleted file mode 100644 index a8997535aae..00000000000 --- a/test/hotspot/jtreg/compiler/c2/TestReduceAllocationAndLoadKlass.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * 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 8330795 - * @summary Check that Reduce Allocation Merges doesn't crash when CompressedClassPointers - * is disabled and there is an access to Klass "field" through the phi. - * @requires vm.bits == 64 & vm.flagless & vm.compiler2.enabled & vm.opt.final.EliminateAllocations - * @run main/othervm -XX:CompileCommand=dontinline,*TestReduceAllocationAndLoadKlass*::test - * -XX:CompileCommand=compileonly,*TestReduceAllocationAndLoadKlass*::test - * -XX:CompileCommand=compileonly,*Shape*::*init* - * -XX:CompileCommand=compileonly,*Point*::*init* - * -XX:CompileCommand=exclude,*TestReduceAllocationAndLoadKlass*::dummy - * -XX:-TieredCompilation - * -XX:-UseCompressedClassPointers - * -Xbatch - * -Xcomp - * compiler.c2.TestReduceAllocationAndLoadKlass - */ - -package compiler.c2; - -public class TestReduceAllocationAndLoadKlass { - public static void main(String[] args) { - Point p = new Point(); - Line q = new Line(); - - test(true); - test(false); - } - - static Class test(boolean cond) { - Object p = cond ? dummy() : new Line(); - return p.getClass(); - } - - static Point dummy() { return new Point(); } - - static class Shape { } - static class Point extends Shape { } - static class Line extends Shape { } -} diff --git a/test/hotspot/jtreg/compiler/c2/irTests/scalarReplacement/AllocationMergesTests.java b/test/hotspot/jtreg/compiler/c2/irTests/scalarReplacement/AllocationMergesTests.java index 24065bd97b9..2c84ad2676e 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/scalarReplacement/AllocationMergesTests.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/scalarReplacement/AllocationMergesTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * 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,26 +46,13 @@ public static void main(String[] args) { "-XX:+TraceReduceAllocationMerges", "-XX:+DeoptimizeALot", "-XX:+UseCompressedOops", - "-XX:+UseCompressedClassPointers", "-XX:CompileCommand=inline,*::charAt*", "-XX:CompileCommand=inline,*PicturePositions::*", "-XX:CompileCommand=inline,*Point::*", "-XX:CompileCommand=inline,*Nested::*", "-XX:CompileCommand=exclude,*::dummy*"); - Scenario scenario1 = new Scenario(1, "-XX:+UnlockDiagnosticVMOptions", - "-XX:+ReduceAllocationMerges", - "-XX:+TraceReduceAllocationMerges", - "-XX:+DeoptimizeALot", - "-XX:+UseCompressedOops", - "-XX:-UseCompressedClassPointers", - "-XX:CompileCommand=inline,*::charAt*", - "-XX:CompileCommand=inline,*PicturePositions::*", - "-XX:CompileCommand=inline,*Point::*", - "-XX:CompileCommand=inline,*Nested::*", - "-XX:CompileCommand=exclude,*::dummy*"); - - Scenario scenario2 = new Scenario(2, "-XX:+UnlockDiagnosticVMOptions", + Scenario scenario1 = new Scenario(2, "-XX:+UnlockDiagnosticVMOptions", "-XX:+ReduceAllocationMerges", "-XX:+TraceReduceAllocationMerges", "-XX:+DeoptimizeALot", @@ -76,12 +63,11 @@ public static void main(String[] args) { "-XX:CompileCommand=inline,*Nested::*", "-XX:CompileCommand=exclude,*::dummy*"); - Scenario scenario3 = new Scenario(3, "-XX:+UnlockDiagnosticVMOptions", + Scenario scenario2 = new Scenario(3, "-XX:+UnlockDiagnosticVMOptions", "-XX:+ReduceAllocationMerges", "-XX:+TraceReduceAllocationMerges", "-XX:+DeoptimizeALot", "-XX:+UseCompressedOops", - "-XX:+UseCompressedClassPointers", "-XX:-OptimizePtrCompare", "-XX:+VerifyReduceAllocationMerges", "-XX:CompileCommand=inline,*::charAt*", @@ -90,7 +76,7 @@ public static void main(String[] args) { "-XX:CompileCommand=inline,*Nested::*", "-XX:CompileCommand=exclude,*::dummy*"); - framework.addScenarios(scenario0, scenario1, scenario2, scenario3).start(); + framework.addScenarios(scenario0, scenario1, scenario2).start(); } // ------------------ No Scalar Replacement Should Happen in The Tests Below ------------------- // diff --git a/test/hotspot/jtreg/compiler/jvmci/compilerToVM/GetResolvedJavaTypeTest.java b/test/hotspot/jtreg/compiler/jvmci/compilerToVM/GetResolvedJavaTypeTest.java index e0302e7b5aa..1e2e2d50232 100644 --- a/test/hotspot/jtreg/compiler/jvmci/compilerToVM/GetResolvedJavaTypeTest.java +++ b/test/hotspot/jtreg/compiler/jvmci/compilerToVM/GetResolvedJavaTypeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -159,7 +159,6 @@ HotSpotResolvedObjectType getResolvedJavaType() { /* a compressed parameter for tested method is set to false because unsafe.getKlassPointer always returns uncompressed pointer */ private static final boolean COMPRESSED = false; - // = WB.getBooleanVMFlag("UseCompressedClassPointers"); private static long getPtrToKlass() { Field field; diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/DataPatchTest.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/DataPatchTest.java index adbad3e0b4d..b0c7d11edfe 100644 --- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/DataPatchTest.java +++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/DataPatchTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -119,7 +119,6 @@ public void testInlineMetadata() { @Test public void testInlineNarrowMetadata() { - Assume.assumeTrue(config.useCompressedClassPointers); test(asm -> { ResolvedJavaType type = metaAccess.lookupJavaType(getConstClass()); HotSpotConstant hub = (HotSpotConstant) constantReflection.asObjectHub(type); @@ -144,7 +143,6 @@ public void testMetadataInDataSection() { @Test public void testNarrowMetadataInDataSection() { - Assume.assumeTrue(config.useCompressedClassPointers); test(asm -> { ResolvedJavaType type = metaAccess.lookupJavaType(getConstClass()); HotSpotConstant hub = (HotSpotConstant) constantReflection.asObjectHub(type); diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/TestHotSpotVMConfig.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/TestHotSpotVMConfig.java index a26872b96ae..4b0065d0e70 100644 --- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/TestHotSpotVMConfig.java +++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/TestHotSpotVMConfig.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,7 +36,6 @@ public TestHotSpotVMConfig(HotSpotVMConfigStore config, Architecture arch) { } public final boolean useCompressedOops = getFlag("UseCompressedOops", Boolean.class); - public final boolean useCompressedClassPointers = getFlag("UseCompressedClassPointers", Boolean.class); public final long narrowOopBase = getFieldValue("CompilerToVM::Data::Universe_narrow_oop_base", Long.class, "address"); public final int narrowOopShift = getFieldValue("CompilerToVM::Data::Universe_narrow_oop_shift", Integer.class, "int"); diff --git a/test/hotspot/jtreg/compiler/types/TestCheckCastPPBecomesTOP.java b/test/hotspot/jtreg/compiler/types/TestCheckCastPPBecomesTOP.java index 5c57e479307..38ab9121b47 100644 --- a/test/hotspot/jtreg/compiler/types/TestCheckCastPPBecomesTOP.java +++ b/test/hotspot/jtreg/compiler/types/TestCheckCastPPBecomesTOP.java @@ -30,9 +30,6 @@ * @run main/othervm -XX:-TieredCompilation -XX:-UseOnStackReplacement -XX:-BackgroundCompilation * -XX:CompileOnly=TestCheckCastPPBecomesTOP::test1 -XX:LoopMaxUnroll=0 * -XX:CompileCommand=dontinline,TestCheckCastPPBecomesTOP::notInlined -XX:+UseParallelGC TestCheckCastPPBecomesTOP - * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:-UseOnStackReplacement -XX:-BackgroundCompilation - * -XX:CompileOnly=TestCheckCastPPBecomesTOP::test1 -XX:LoopMaxUnroll=0 - * -XX:CompileCommand=dontinline,TestCheckCastPPBecomesTOP::notInlined -XX:+UseParallelGC -XX:-UseCompressedClassPointers TestCheckCastPPBecomesTOP * */ diff --git a/test/hotspot/jtreg/compiler/unsafe/OpaqueAccesses.java b/test/hotspot/jtreg/compiler/unsafe/OpaqueAccesses.java index 9a31cbbb057..00c3ce5fb7f 100644 --- a/test/hotspot/jtreg/compiler/unsafe/OpaqueAccesses.java +++ b/test/hotspot/jtreg/compiler/unsafe/OpaqueAccesses.java @@ -247,28 +247,14 @@ public static void main(String[] args) { "--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED", "-XX:+IgnoreUnrecognizedVMOptions", "-XX:+UnlockDiagnosticVMOptions", "-XX:-TieredCompilation", "-Xbatch", - "-XX:+UseCompressedOops", "-XX:+UseCompressedClassPointers", + "-XX:+UseCompressedOops", "-XX:CompileCommand=dontinline,compiler.unsafe.OpaqueAccesses::test*" ); TestFramework.runWithFlags( "--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED", "-XX:+IgnoreUnrecognizedVMOptions", "-XX:+UnlockDiagnosticVMOptions", "-XX:-TieredCompilation", "-Xbatch", - "-XX:+UseCompressedOops", "-XX:-UseCompressedClassPointers", - "-XX:CompileCommand=dontinline,compiler.unsafe.OpaqueAccesses::test*" - ); - TestFramework.runWithFlags( - "--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED", - "-XX:+IgnoreUnrecognizedVMOptions", "-XX:+UnlockDiagnosticVMOptions", - "-XX:-TieredCompilation", "-Xbatch", - "-XX:-UseCompressedOops", "-XX:+UseCompressedClassPointers", - "-XX:CompileCommand=dontinline,compiler.unsafe.OpaqueAccesses::test*" - ); - TestFramework.runWithFlags( - "--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED", - "-XX:+IgnoreUnrecognizedVMOptions", "-XX:+UnlockDiagnosticVMOptions", - "-XX:-TieredCompilation", "-Xbatch", - "-XX:-UseCompressedOops", "-XX:-UseCompressedClassPointers", + "-XX:-UseCompressedOops", "-XX:CompileCommand=dontinline,compiler.unsafe.OpaqueAccesses::test*" ); } diff --git a/test/hotspot/jtreg/gc/arguments/TestCompressedClassFlags.java b/test/hotspot/jtreg/gc/arguments/TestCompressedClassFlags.java deleted file mode 100644 index b152fc8c936..00000000000 --- a/test/hotspot/jtreg/gc/arguments/TestCompressedClassFlags.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package gc.arguments; - -import jdk.test.lib.process.OutputAnalyzer; -import jdk.test.lib.Platform; - -/* - * @test - * @bug 8015107 - * @summary Tests that VM prints a warning when -XX:CompressedClassSpaceSize - * is used together with -XX:-UseCompressedClassPointers - * @library /test/lib - * @library / - * @modules java.base/jdk.internal.misc - * java.management - * @requires vm.opt.CompressedClassSpaceSize == null & vm.opt.UseCompressedClassPointers == null - * @run driver gc.arguments.TestCompressedClassFlags - */ -public class TestCompressedClassFlags { - public static void main(String[] args) throws Exception { - if (Platform.is64bit()) { - OutputAnalyzer output = GCArguments.executeTestJava( - "-XX:CompressedClassSpaceSize=1g", - "-XX:-UseCompressedClassPointers", - "-version"); - output.shouldContain("warning"); - output.shouldNotContain("error"); - output.shouldHaveExitValue(0); - } - } -} diff --git a/test/hotspot/jtreg/gc/g1/TestSharedArchiveWithPreTouch.java b/test/hotspot/jtreg/gc/g1/TestSharedArchiveWithPreTouch.java index 1156a2166c1..bba3c850213 100644 --- a/test/hotspot/jtreg/gc/g1/TestSharedArchiveWithPreTouch.java +++ b/test/hotspot/jtreg/gc/g1/TestSharedArchiveWithPreTouch.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -53,7 +53,7 @@ public static void main(String[] args) throws Exception { List dump_args = new ArrayList(BaseOptions); if (Platform.is64bit()) { - dump_args.addAll(0, Arrays.asList(new String[] { "-XX:+UseCompressedClassPointers", "-XX:+UseCompressedOops" })); + dump_args.addFirst("-XX:+UseCompressedOops" ); } dump_args.addAll(Arrays.asList(new String[] { "-Xshare:dump", "-Xlog:cds" })); @@ -66,7 +66,7 @@ public static void main(String[] args) throws Exception { List load_args = new ArrayList(BaseOptions); if (Platform.is64bit()) { - load_args.addAll(0, Arrays.asList(new String[] { "-XX:+UseCompressedClassPointers", "-XX:+UseCompressedOops" })); + load_args.addFirst("-XX:+UseCompressedOops" ); } load_args.addAll(Arrays.asList(new String[] { "-Xshare:on", "-version" })); diff --git a/test/hotspot/jtreg/gc/metaspace/TestMetaspaceMemoryPool.java b/test/hotspot/jtreg/gc/metaspace/TestMetaspaceMemoryPool.java index 71cf2003ddd..2f4ce3df8b2 100644 --- a/test/hotspot/jtreg/gc/metaspace/TestMetaspaceMemoryPool.java +++ b/test/hotspot/jtreg/gc/metaspace/TestMetaspaceMemoryPool.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,10 +37,9 @@ * @library / * @modules java.base/jdk.internal.misc * java.management - * @run main/othervm -XX:-UseCompressedOops gc.metaspace.TestMetaspaceMemoryPool - * @run main/othervm -XX:-UseCompressedOops -XX:MaxMetaspaceSize=60m gc.metaspace.TestMetaspaceMemoryPool - * @run main/othervm -XX:+UseCompressedOops -XX:+UseCompressedClassPointers gc.metaspace.TestMetaspaceMemoryPool - * @run main/othervm -XX:+UseCompressedOops -XX:+UseCompressedClassPointers -XX:CompressedClassSpaceSize=60m gc.metaspace.TestMetaspaceMemoryPool + * @run main/othervm gc.metaspace.TestMetaspaceMemoryPool + * @run main/othervm -XX:MaxMetaspaceSize=60m gc.metaspace.TestMetaspaceMemoryPool + * @run main/othervm -XX:CompressedClassSpaceSize=60m gc.metaspace.TestMetaspaceMemoryPool */ public class TestMetaspaceMemoryPool { @@ -51,10 +50,8 @@ public static void main(String[] args) { verifyMemoryPool(getMemoryPool("Metaspace"), isMetaspaceMaxDefined); if (Platform.is64bit()) { - if (InputArguments.contains("-XX:+UseCompressedOops")) { - MemoryPoolMXBean cksPool = getMemoryPool("Compressed Class Space"); - verifyMemoryPool(cksPool, true); - } + MemoryPoolMXBean cksPool = getMemoryPool("Compressed Class Space"); + verifyMemoryPool(cksPool, true); } } diff --git a/test/hotspot/jtreg/gc/metaspace/TestMetaspacePerfCounters.java b/test/hotspot/jtreg/gc/metaspace/TestMetaspacePerfCounters.java index b0f779109e1..5ead40c9068 100644 --- a/test/hotspot/jtreg/gc/metaspace/TestMetaspacePerfCounters.java +++ b/test/hotspot/jtreg/gc/metaspace/TestMetaspacePerfCounters.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,8 +48,7 @@ * java.compiler * java.management/sun.management * jdk.internal.jvmstat/sun.jvmstat.monitor - * @run main/othervm -XX:-UseCompressedOops -XX:-UseCompressedClassPointers -XX:+UsePerfData -XX:+UseSerialGC gc.metaspace.TestMetaspacePerfCounters - * @run main/othervm -XX:+UseCompressedOops -XX:+UseCompressedClassPointers -XX:+UsePerfData -XX:+UseSerialGC gc.metaspace.TestMetaspacePerfCounters + * @run main/othervm -XX:+UseCompressedOops -XX:+UsePerfData -XX:+UseSerialGC gc.metaspace.TestMetaspacePerfCounters */ /* @test id=Parallel-64 @@ -63,8 +62,7 @@ * java.compiler * java.management/sun.management * jdk.internal.jvmstat/sun.jvmstat.monitor - * @run main/othervm -XX:-UseCompressedOops -XX:-UseCompressedClassPointers -XX:+UsePerfData -XX:+UseParallelGC gc.metaspace.TestMetaspacePerfCounters - * @run main/othervm -XX:+UseCompressedOops -XX:+UseCompressedClassPointers -XX:+UsePerfData -XX:+UseParallelGC gc.metaspace.TestMetaspacePerfCounters + * @run main/othervm -XX:+UseCompressedOops -XX:+UsePerfData -XX:+UseParallelGC gc.metaspace.TestMetaspacePerfCounters */ /* @test id=G1-64 @@ -78,8 +76,7 @@ * java.compiler * java.management/sun.management * jdk.internal.jvmstat/sun.jvmstat.monitor - * @run main/othervm -XX:-UseCompressedOops -XX:-UseCompressedClassPointers -XX:+UsePerfData -XX:+UseG1GC gc.metaspace.TestMetaspacePerfCounters - * @run main/othervm -XX:+UseCompressedOops -XX:+UseCompressedClassPointers -XX:+UsePerfData -XX:+UseG1GC gc.metaspace.TestMetaspacePerfCounters + * @run main/othervm -XX:+UseCompressedOops -XX:+UsePerfData -XX:+UseG1GC gc.metaspace.TestMetaspacePerfCounters */ /* @test id=Shenandoah-64 @@ -93,8 +90,7 @@ * java.compiler * java.management/sun.management * jdk.internal.jvmstat/sun.jvmstat.monitor - * @run main/othervm -XX:-UseCompressedOops -XX:-UseCompressedClassPointers -XX:+UsePerfData -XX:+UseShenandoahGC gc.metaspace.TestMetaspacePerfCounters - * @run main/othervm -XX:+UseCompressedOops -XX:+UseCompressedClassPointers -XX:+UsePerfData -XX:+UseShenandoahGC gc.metaspace.TestMetaspacePerfCounters + * @run main/othervm -XX:+UseCompressedOops -XX:+UsePerfData -XX:+UseShenandoahGC gc.metaspace.TestMetaspacePerfCounters */ /* @test id=Epsilon-64 @@ -108,8 +104,7 @@ * java.compiler * java.management/sun.management * jdk.internal.jvmstat/sun.jvmstat.monitor - * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:-UseCompressedOops -XX:-UseCompressedClassPointers -XX:+UsePerfData -XX:+UseEpsilonGC gc.metaspace.TestMetaspacePerfCounters - * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseCompressedOops -XX:+UseCompressedClassPointers -XX:+UsePerfData -XX:+UseEpsilonGC gc.metaspace.TestMetaspacePerfCounters + * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseCompressedOops -XX:+UsePerfData -XX:+UseEpsilonGC gc.metaspace.TestMetaspacePerfCounters */ /* @test id=Serial-32 @@ -227,14 +222,8 @@ public static void main(String[] args) throws Exception { String ccs = "sun.gc.compressedclassspace"; checkPerfCounters(metaspace); - - if (isUsingCompressedClassPointers()) { - checkPerfCounters(ccs); - checkUsedIncreasesWhenLoadingClass(ccs); - } else { - checkEmptyPerfCounters(ccs); - checkUsedIncreasesWhenLoadingClass(metaspace); - } + checkPerfCounters(ccs); + checkUsedIncreasesWhenLoadingClass(ccs); } private static void checkPerfCounters(String ns) throws Exception { @@ -262,13 +251,6 @@ private static void checkPerfCounters(String ns) throws Exception { assertGTE(snap1.maxCapacity, snap1.capacity); } - private static void checkEmptyPerfCounters(String ns) throws Exception { - for (PerfCounter counter : countersInNamespace(ns)) { - String msg = "Expected " + counter.getName() + " to equal 0"; - assertEQ(counter.longValue(), 0L, msg); - } - } - private static void checkUsedIncreasesWhenLoadingClass(String ns) throws Exception { // Need to ensure that used is up to date and that all unreachable // classes are unloaded before doing this check. @@ -296,7 +278,4 @@ private static Class compileAndLoad(String name, String source) throws Except return ByteCodeLoader.load(name, byteCode); } - private static boolean isUsingCompressedClassPointers() { - return Platform.is64bit() && InputArguments.contains("-XX:+UseCompressedClassPointers"); - } } diff --git a/test/hotspot/jtreg/gc/metaspace/TestPerfCountersAndMemoryPools.java b/test/hotspot/jtreg/gc/metaspace/TestPerfCountersAndMemoryPools.java index fb32c439940..6d5cdf181b9 100644 --- a/test/hotspot/jtreg/gc/metaspace/TestPerfCountersAndMemoryPools.java +++ b/test/hotspot/jtreg/gc/metaspace/TestPerfCountersAndMemoryPools.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,8 +40,7 @@ * @modules java.base/jdk.internal.misc * java.management * jdk.internal.jvmstat/sun.jvmstat.monitor - * @run main/othervm -Xlog:class+load,class+unload=trace -XX:-UseCompressedOops -XX:-UseCompressedClassPointers -XX:+UseSerialGC -XX:+UsePerfData -Xint gc.metaspace.TestPerfCountersAndMemoryPools - * @run main/othervm -Xlog:class+load,class+unload=trace -XX:+UseCompressedOops -XX:+UseCompressedClassPointers -XX:+UseSerialGC -XX:+UsePerfData -Xint gc.metaspace.TestPerfCountersAndMemoryPools + * @run main/othervm -Xlog:class+load,class+unload=trace -XX:+UseCompressedOops -XX:+UseSerialGC -XX:+UsePerfData -Xint gc.metaspace.TestPerfCountersAndMemoryPools */ /* @test TestPerfCountersAndMemoryPools @@ -60,7 +59,7 @@ public class TestPerfCountersAndMemoryPools { public static void main(String[] args) throws Exception { checkMemoryUsage("Metaspace", "sun.gc.metaspace"); - if (InputArguments.contains("-XX:+UseCompressedClassPointers") && Platform.is64bit()) { + if (Platform.is64bit()) { checkMemoryUsage("Compressed Class Space", "sun.gc.compressedclassspace"); } } diff --git a/test/hotspot/jtreg/gc/metaspace/TestSizeTransitions.java b/test/hotspot/jtreg/gc/metaspace/TestSizeTransitions.java index 4237b8ce1dd..db698782e8f 100644 --- a/test/hotspot/jtreg/gc/metaspace/TestSizeTransitions.java +++ b/test/hotspot/jtreg/gc/metaspace/TestSizeTransitions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019, Twitter, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -35,24 +35,21 @@ * @requires vm.gc.Serial * @summary Tests that the metaspace size transition logging is done correctly. * @library /test/lib - * @run driver gc.metaspace.TestSizeTransitions false -XX:+UseSerialGC - * @run driver gc.metaspace.TestSizeTransitions true -XX:+UseSerialGC + * @run driver gc.metaspace.TestSizeTransitions -XX:+UseSerialGC */ /* @test TestSizeTransitionsParallel * @requires vm.gc.Parallel * @summary Tests that the metaspace size transition logging is done correctly. * @library /test/lib - * @run driver gc.metaspace.TestSizeTransitions false -XX:+UseParallelGC - * @run driver gc.metaspace.TestSizeTransitions true -XX:+UseParallelGC + * @run driver gc.metaspace.TestSizeTransitions -XX:+UseParallelGC */ /* @test TestSizeTransitionsG1 * @requires vm.gc.G1 * @summary Tests that the metaspace size transition logging is done correctly. * @library /test/lib - * @run driver gc.metaspace.TestSizeTransitions false -XX:+UseG1GC - * @run driver gc.metaspace.TestSizeTransitions true -XX:+UseG1GC + * @run driver gc.metaspace.TestSizeTransitions -XX:+UseG1GC */ public class TestSizeTransitions { @@ -76,13 +73,13 @@ public static void main(String... args) throws Exception { private static final String SIZE_TRANSITION_REGEX = "\\d+K\\(\\d+K\\)->\\d+K\\(\\d+K\\)"; // matches -coops metaspace size transitions - private static final String NO_COMPRESSED_KLASS_POINTERS_REGEX = + private static final String WITHOUT_CLASS_SPACE_REGEX = String.format("^%s.* Metaspace: %s$", LOG_TAGS_REGEX, SIZE_TRANSITION_REGEX); // matches +coops metaspace size transitions - private static final String COMPRESSED_KLASS_POINTERS_REGEX = + private static final String WITH_CLASS_SPACE_REGEX = String.format("^%s.* Metaspace: %s NonClass: %s Class: %s$", LOG_TAGS_REGEX, SIZE_TRANSITION_REGEX, @@ -90,26 +87,11 @@ public static void main(String... args) throws Exception { SIZE_TRANSITION_REGEX); public static void main(String... args) throws Exception { - // args: - if (args.length != 2) { - throw new RuntimeException("wrong number of args: " + args.length); + if (args.length == 0) { + throw new RuntimeException("expected jvm args: " + args.length); } - final boolean hasCompressedKlassPointers = Platform.is64bit(); - final boolean useCompressedKlassPointers = Boolean.parseBoolean(args[0]); - final String gcArg = args[1]; - - if (!hasCompressedKlassPointers && useCompressedKlassPointers) { - // No need to run this configuration. - System.out.println("Skipping test."); - return; - } - - List jvmArgs = new ArrayList<>(); - if (hasCompressedKlassPointers) { - jvmArgs.add(useCompressedKlassPointers ? "-XX:+UseCompressedClassPointers" : "-XX:-UseCompressedClassPointers"); - } - jvmArgs.add(gcArg); + List jvmArgs = new ArrayList<>(List.of(args)); jvmArgs.add("-Xmx256m"); jvmArgs.add("-Xlog:gc,gc+metaspace=info"); jvmArgs.add(TestSizeTransitions.Run.class.getName()); @@ -123,12 +105,14 @@ public static void main(String... args) throws Exception { System.out.println(output.getStdout()); output.shouldHaveExitValue(0); - if (useCompressedKlassPointers) { - output.stdoutShouldMatch(COMPRESSED_KLASS_POINTERS_REGEX); - output.stdoutShouldNotMatch(NO_COMPRESSED_KLASS_POINTERS_REGEX); + // 32-bit uses narrow Pointers but no class space + final boolean hasClassSpace = Platform.is64bit(); + if (hasClassSpace) { + output.stdoutShouldMatch(WITH_CLASS_SPACE_REGEX); + output.stdoutShouldNotMatch(WITHOUT_CLASS_SPACE_REGEX); } else { - output.stdoutShouldMatch(NO_COMPRESSED_KLASS_POINTERS_REGEX); - output.stdoutShouldNotMatch(COMPRESSED_KLASS_POINTERS_REGEX); + output.stdoutShouldMatch(WITHOUT_CLASS_SPACE_REGEX); + output.stdoutShouldNotMatch(WITH_CLASS_SPACE_REGEX); } } } diff --git a/test/hotspot/jtreg/gtest/ArrayTests.java b/test/hotspot/jtreg/gtest/ArrayTests.java index b1afa4795d2..d3a8498d5eb 100644 --- a/test/hotspot/jtreg/gtest/ArrayTests.java +++ b/test/hotspot/jtreg/gtest/ArrayTests.java @@ -26,31 +26,18 @@ * This tests object array sizes by running gtests with different settings. */ -/* @test id=with-coops-with-ccp - * @summary Run object array size tests with compressed oops and compressed class pointers +/* @test id=with-coops + * @summary Run object array size tests with compressed oops * @library /test/lib * @modules java.base/jdk.internal.misc * java.xml - * @run main/native GTestWrapper --gtest_filter=arrayOop -XX:+UseCompressedClassPointers -XX:+UseCompressedOops + * @run main/native GTestWrapper --gtest_filter=arrayOop -XX:+UseCompressedOops */ -/* @test id=with-coops-no-ccp - * @summary Run object array size tests with compressed oops and compressed class pointers - * @library /test/lib - * @modules java.base/jdk.internal.misc - * java.xml - * @run main/native GTestWrapper --gtest_filter=arrayOop -XX:-UseCompressedClassPointers -XX:+UseCompressedOops - */ -/* @test id=no-coops-with-ccp - * @summary Run object array size tests with compressed oops and compressed class pointers - * @library /test/lib - * @modules java.base/jdk.internal.misc - * java.xml - * @run main/native GTestWrapper --gtest_filter=arrayOop -XX:+UseCompressedClassPointers -XX:-UseCompressedOops - */ -/* @test id=no-coops-no-ccp - * @summary Run object array size tests with compressed oops and compressed class pointers + +/* @test id=no-coops + * @summary Run object array size tests with compressed oops * @library /test/lib * @modules java.base/jdk.internal.misc * java.xml - * @run main/native GTestWrapper --gtest_filter=arrayOop -XX:-UseCompressedClassPointers -XX:-UseCompressedOops + * @run main/native GTestWrapper --gtest_filter=arrayOop -XX:-UseCompressedOops */ diff --git a/test/hotspot/jtreg/gtest/CompressedKlassGtest.java b/test/hotspot/jtreg/gtest/CompressedKlassGtest.java index ba801724558..24f1dff5a30 100644 --- a/test/hotspot/jtreg/gtest/CompressedKlassGtest.java +++ b/test/hotspot/jtreg/gtest/CompressedKlassGtest.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2024, Red Hat, Inc. All rights reserved. - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,14 +39,6 @@ * @run main/native GTestWrapper --gtest_filter=CompressedKlass* -XX:-UseCompactObjectHeaders -Xlog:metaspace* -Xmx6g -Xms128m -Xshare:off -XX:CompressedClassSpaceSize=128m */ -/* @test id=ccp_off - * @library /test/lib - * @requires vm.bits == "64" - * @modules java.base/jdk.internal.misc - * java.xml - * @run main/native GTestWrapper --gtest_filter=CompressedKlass* -XX:-UseCompressedClassPointers -Xlog:metaspace* -Xmx6g -Xms128m - */ - /* @test id=use-zero-based-encoding-coh * @library /test/lib * @requires vm.bits == "64" diff --git a/test/hotspot/jtreg/gtest/MetaspaceGtests.java b/test/hotspot/jtreg/gtest/MetaspaceGtests.java index 38fef145125..26faa2c7c2d 100644 --- a/test/hotspot/jtreg/gtest/MetaspaceGtests.java +++ b/test/hotspot/jtreg/gtest/MetaspaceGtests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, 2023 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -40,15 +40,6 @@ * @run main/native GTestWrapper --gtest_filter=metaspace* -XX:+UnlockDiagnosticVMOptions -XX:VerifyMetaspaceInterval=1 */ -/* @test id=no-ccs - * @summary Run metaspace-related gtests with compressed class pointers off - * @library /test/lib - * @modules java.base/jdk.internal.misc - * java.xml - * @requires vm.bits == 64 - * @requires vm.flagless - * @run main/native GTestWrapper --gtest_filter=metaspace* -XX:+UnlockDiagnosticVMOptions -XX:-UseCompressedClassPointers - */ /* @test id=UseCompactObjectHeaders * @summary Run metaspace-related gtests with tiny classpointers diff --git a/test/hotspot/jtreg/gtest/ObjArrayTests.java b/test/hotspot/jtreg/gtest/ObjArrayTests.java index baae1840417..ede85948335 100644 --- a/test/hotspot/jtreg/gtest/ObjArrayTests.java +++ b/test/hotspot/jtreg/gtest/ObjArrayTests.java @@ -26,60 +26,34 @@ * This tests object array sizes by running gtests with different settings. */ -/* @test id=with-coops-with-ccp - * @summary Run object array size tests with compressed oops and compressed class pointers +/* @test id=with-coops + * @summary Run object array size tests with compressed oops * @library /test/lib * @modules java.base/jdk.internal.misc * java.xml - * @run main/native GTestWrapper --gtest_filter=objArrayOop -XX:+UseCompressedClassPointers -XX:+UseCompressedOops - */ -/* @test id=with-coops-no-ccp - * @summary Run object array size tests with compressed oops and compressed class pointers - * @library /test/lib - * @modules java.base/jdk.internal.misc - * java.xml - * @run main/native GTestWrapper --gtest_filter=objArrayOop -XX:-UseCompressedClassPointers -XX:+UseCompressedOops - */ -/* @test id=no-coops-with-ccp - * @summary Run object array size tests with compressed oops and compressed class pointers - * @library /test/lib - * @modules java.base/jdk.internal.misc - * java.xml - * @run main/native GTestWrapper --gtest_filter=objArrayOop -XX:+UseCompressedClassPointers -XX:-UseCompressedOops - */ -/* @test id=no-coops-no-ccp - * @summary Run object array size tests with compressed oops and compressed class pointers - * @library /test/lib - * @modules java.base/jdk.internal.misc - * java.xml - * @run main/native GTestWrapper --gtest_filter=objArrayOop -XX:-UseCompressedClassPointers -XX:-UseCompressedOops + * @run main/native GTestWrapper --gtest_filter=objArrayOop -XX:+UseCompressedOops */ -/* @test id=with-coops-with-ccp-large-align - * @summary Run object array size tests with compressed oops and compressed class pointers +/* @test id=no-coops + * @summary Run object array size tests with compressed oops * @library /test/lib * @modules java.base/jdk.internal.misc * java.xml - * @run main/native GTestWrapper --gtest_filter=objArrayOop -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:ObjAlignmentInBytes=256 + * @run main/native GTestWrapper --gtest_filter=objArrayOop -XX:-UseCompressedOops */ -/* @test id=with-coops-no-ccp-large-align - * @summary Run object array size tests with compressed oops and compressed class pointers - * @library /test/lib - * @modules java.base/jdk.internal.misc - * java.xml - * @run main/native GTestWrapper --gtest_filter=objArrayOop -XX:-UseCompressedClassPointers -XX:+UseCompressedOops -XX:ObjAlignmentInBytes=256 - */ -/* @test id=no-coops-with-ccp-large-align - * @summary Run object array size tests with compressed oops and compressed class pointers + +/* @test id=with-coops-large-align + * @summary Run object array size tests with compressed oops * @library /test/lib * @modules java.base/jdk.internal.misc * java.xml - * @run main/native GTestWrapper --gtest_filter=objArrayOop -XX:+UseCompressedClassPointers -XX:-UseCompressedOops -XX:ObjAlignmentInBytes=256 + * @run main/native GTestWrapper --gtest_filter=objArrayOop -XX:+UseCompressedOops -XX:ObjAlignmentInBytes=256 */ -/* @test id=no-coops-no-ccp-large-align - * @summary Run object array size tests with compressed oops and compressed class pointers + +/* @test id=no-coops-large-align + * @summary Run object array size tests with compressed oops * @library /test/lib * @modules java.base/jdk.internal.misc * java.xml - * @run main/native GTestWrapper --gtest_filter=objArrayOop -XX:-UseCompressedClassPointers -XX:-UseCompressedOops -XX:ObjAlignmentInBytes=256 + * @run main/native GTestWrapper --gtest_filter=objArrayOop -XX:-UseCompressedOops -XX:ObjAlignmentInBytes=256 */ diff --git a/test/hotspot/jtreg/runtime/CDSCompressedKPtrs/CDSCompressedKPtrs.java b/test/hotspot/jtreg/runtime/CDSCompressedKPtrs/CDSCompressedKPtrs.java deleted file mode 100644 index 51b0469ce46..00000000000 --- a/test/hotspot/jtreg/runtime/CDSCompressedKPtrs/CDSCompressedKPtrs.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/** - * @test - * @requires vm.cds - * @requires vm.bits == 64 - * @requires vm.flagless - * @bug 8003424 - * @summary Testing UseCompressedClassPointers with CDS - * @library /test/lib - * @modules java.base/jdk.internal.misc - * java.management - * @run driver CDSCompressedKPtrs - */ - -import jdk.test.lib.Platform; -import jdk.test.lib.process.ProcessTools; -import jdk.test.lib.process.OutputAnalyzer; -import jtreg.SkippedException; - -public class CDSCompressedKPtrs { - public static void main(String[] args) throws Exception { - ProcessBuilder pb; - pb = ProcessTools.createLimitedTestJavaProcessBuilder( - "-XX:+UseCompressedClassPointers", "-XX:+UseCompressedOops", - "-XX:+UnlockDiagnosticVMOptions", "-XX:SharedArchiveFile=./CDSCompressedKPtrs.jsa", "-Xshare:dump", "-Xlog:cds"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); - try { - output.shouldContain("Loading classes to share"); - output.shouldHaveExitValue(0); - - pb = ProcessTools.createLimitedTestJavaProcessBuilder( - "-XX:+UseCompressedClassPointers", "-XX:+UseCompressedOops", - "-XX:+UnlockDiagnosticVMOptions", "-XX:SharedArchiveFile=./CDSCompressedKPtrs.jsa", "-Xshare:on", "-version"); - output = new OutputAnalyzer(pb.start()); - output.shouldContain("sharing"); - output.shouldHaveExitValue(0); - - } catch (RuntimeException e) { - output.shouldContain("Unable to use shared archive"); - output.shouldHaveExitValue(1); - throw new SkippedException("CDS was turned off"); - } - } -} diff --git a/test/hotspot/jtreg/runtime/CompressedOops/CompressedClassPointers.java b/test/hotspot/jtreg/runtime/CompressedOops/CompressedClassPointers.java index e4b6f2a0548..fe1f8cb92fc 100644 --- a/test/hotspot/jtreg/runtime/CompressedOops/CompressedClassPointers.java +++ b/test/hotspot/jtreg/runtime/CompressedOops/CompressedClassPointers.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,7 +40,6 @@ import jdk.test.lib.Platform; import jdk.test.lib.process.ProcessTools; import jdk.test.lib.process.OutputAnalyzer; -import jtreg.SkippedException; public class CompressedClassPointers { @@ -218,7 +217,6 @@ public static void sharingTest() throws Exception { public static void smallHeapTestNoCoop() throws Exception { ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( "-XX:-UseCompressedOops", - "-XX:+UseCompressedClassPointers", "-XX:+UnlockDiagnosticVMOptions", "-XX:SharedBaseAddress=8g", "-Xmx128m", @@ -236,7 +234,6 @@ public static void smallHeapTestNoCoop() throws Exception { public static void smallHeapTestWith1GNoCoop() throws Exception { ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( "-XX:-UseCompressedOops", - "-XX:+UseCompressedClassPointers", "-XX:+UnlockDiagnosticVMOptions", "-XX:CompressedClassSpaceSize=1g", "-Xmx128m", @@ -258,7 +255,6 @@ public static void smallHeapTestWith1GNoCoop() throws Exception { public static void largeHeapTestNoCoop() throws Exception { ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( "-XX:-UseCompressedOops", - "-XX:+UseCompressedClassPointers", "-XX:+UnlockDiagnosticVMOptions", "-XX:+UnlockExperimentalVMOptions", "-Xmx30g", @@ -280,7 +276,6 @@ public static void largeHeapTestNoCoop() throws Exception { public static void largePagesTestNoCoop() throws Exception { ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( "-XX:-UseCompressedOops", - "-XX:+UseCompressedClassPointers", "-XX:+UnlockDiagnosticVMOptions", "-Xmx128m", "-XX:+UseLargePages", @@ -291,23 +286,10 @@ public static void largePagesTestNoCoop() throws Exception { output.shouldHaveExitValue(0); } - public static void heapBaseMinAddressTestNoCoop() throws Exception { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( - "-XX:-UseCompressedOops", - "-XX:+UseCompressedClassPointers", - "-XX:HeapBaseMinAddress=1m", - "-Xlog:gc+heap+coops=debug", - "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); - output.shouldContain("HeapBaseMinAddress must be at least"); - output.shouldHaveExitValue(0); - } - public static void sharingTestNoCoop() throws Exception { // Test small heaps ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( "-XX:-UseCompressedOops", - "-XX:+UseCompressedClassPointers", "-XX:+UnlockDiagnosticVMOptions", "-XX:SharedArchiveFile=./CompressedClassPointers.jsa", "-Xmx128m", @@ -325,7 +307,6 @@ public static void sharingTestNoCoop() throws Exception { pb = ProcessTools.createLimitedTestJavaProcessBuilder( "-XX:-UseCompressedOops", - "-XX:+UseCompressedClassPointers", "-XX:+UnlockDiagnosticVMOptions", "-XX:SharedArchiveFile=./CompressedClassPointers.jsa", "-Xmx128m", @@ -356,7 +337,6 @@ public static void main(String[] args) throws Exception { smallHeapTestWith1GNoCoop(); largeHeapTestNoCoop(); largePagesTestNoCoop(); - heapBaseMinAddressTestNoCoop(); sharingTestNoCoop(); } } diff --git a/test/hotspot/jtreg/runtime/CompressedOops/CompressedClassSpaceSize.java b/test/hotspot/jtreg/runtime/CompressedOops/CompressedClassSpaceSize.java index 7bbb9edb7b4..0898e6b96eb 100644 --- a/test/hotspot/jtreg/runtime/CompressedOops/CompressedClassSpaceSize.java +++ b/test/hotspot/jtreg/runtime/CompressedOops/CompressedClassSpaceSize.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -107,13 +107,6 @@ public static void main(String[] args) throws Exception { output = new OutputAnalyzer(pb.start()); output.shouldContain("outside the allowed range") .shouldHaveExitValue(1); - - pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:-UseCompressedClassPointers", - "-XX:CompressedClassSpaceSize=" + minAllowedClassSpaceSize, - "-version"); - output = new OutputAnalyzer(pb.start()); - output.shouldContain("Setting CompressedClassSpaceSize has no effect when compressed class pointers are not used") - .shouldHaveExitValue(0); } break; case "valid_small": { diff --git a/test/hotspot/jtreg/runtime/CompressedOops/CompressedKlassPointerAndOops.java b/test/hotspot/jtreg/runtime/CompressedOops/CompressedKlassPointerAndOops.java index 403654d1cc8..32bb432308b 100644 --- a/test/hotspot/jtreg/runtime/CompressedOops/CompressedKlassPointerAndOops.java +++ b/test/hotspot/jtreg/runtime/CompressedOops/CompressedKlassPointerAndOops.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,8 +23,7 @@ /* * @test - * @bug 8000968 - * @summary NPG: UseCompressedClassPointers asserts with ObjectAlignmentInBytes=32 + * @summary Test Compressed Oops with different object alignments * @library /test/lib * @modules java.base/jdk.internal.misc * java.management @@ -51,7 +50,6 @@ private static void runWithAlignment(int alignment) throws Exception { OutputAnalyzer output; pb = ProcessTools.createLimitedTestJavaProcessBuilder( - "-XX:+UseCompressedClassPointers", "-XX:+UseCompressedOops", "-XX:ObjectAlignmentInBytes=" + alignment, "-version"); diff --git a/test/hotspot/jtreg/runtime/ErrorHandling/TestVMConfigInHsErrFile.java b/test/hotspot/jtreg/runtime/ErrorHandling/TestVMConfigInHsErrFile.java index 1e168221726..8f41121fbc1 100644 --- a/test/hotspot/jtreg/runtime/ErrorHandling/TestVMConfigInHsErrFile.java +++ b/test/hotspot/jtreg/runtime/ErrorHandling/TestVMConfigInHsErrFile.java @@ -56,7 +56,7 @@ public class TestVMConfigInHsErrFile { public static void main(String[] args) throws Exception { switch (args[0]) { case "coh-on" -> testCompactObjectHeaders(); - case "coh-off" -> testCompressedClassPointers(); + case "coh-off" -> testNotCompactObjectHeaders(); } } @@ -79,20 +79,16 @@ private static void testCompactObjectHeaders() throws Exception { Pattern[] expectedPatterns = new Pattern[] { Pattern.compile("# Java VM: .*compact obj headers.*") }; - Pattern[] notExpectedPatterns = new Pattern[] { - Pattern.compile("# Java VM: .*compressed class ptrs.*") - }; - HsErrFileUtils.checkHsErrFileContent(f, expectedPatterns, notExpectedPatterns, true, true); + HsErrFileUtils.checkHsErrFileContent(f, expectedPatterns, null, true, true); } - private static void testCompressedClassPointers() throws Exception { + private static void testNotCompactObjectHeaders() throws Exception { ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( "-XX:+UnlockDiagnosticVMOptions", "-XX:+UnlockExperimentalVMOptions", "-XX:-UseCompactObjectHeaders", - "-XX:+UseCompressedClassPointers", "-Xmx100M", "-XX:-CreateCoredumpOnCrash", "-XX:ErrorHandlerTest=14", @@ -104,14 +100,11 @@ private static void testCompressedClassPointers() throws Exception { // extract hs-err file File f = HsErrFileUtils.openHsErrFileFromOutput(output); - Pattern[] expectedPatterns = new Pattern[] { - Pattern.compile("# Java VM: .*compressed class ptrs.*") - }; Pattern[] notExpectedPatterns = new Pattern[] { Pattern.compile("# Java VM: .*compact obj headers.*") }; - HsErrFileUtils.checkHsErrFileContent(f, expectedPatterns, notExpectedPatterns, true, true); + HsErrFileUtils.checkHsErrFileContent(f, null, notExpectedPatterns, true, true); } } diff --git a/test/hotspot/jtreg/runtime/FieldLayout/BaseOffsets.java b/test/hotspot/jtreg/runtime/FieldLayout/BaseOffsets.java index 73f5a1c6137..00b09fec6ed 100644 --- a/test/hotspot/jtreg/runtime/FieldLayout/BaseOffsets.java +++ b/test/hotspot/jtreg/runtime/FieldLayout/BaseOffsets.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,47 +22,29 @@ */ /* - * @test id=with-coops-with-ccp + * @test id=with-coops * @library /test/lib / * @requires vm.bits == "64" * @modules java.base/jdk.internal.misc * java.management * @build jdk.test.whitebox.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseCompressedOops -XX:+UseCompressedClassPointers -XX:-UseCompactObjectHeaders BaseOffsets - */ -/* - * @test id=no-coops-with-ccp - * @library /test/lib / - * @requires vm.bits == "64" - * @modules java.base/jdk.internal.misc - * java.management - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:-UseCompressedOops -XX:+UseCompressedClassPointers -XX:-UseCompactObjectHeaders BaseOffsets - */ -/* - * @test id=with-coops-no-ccp - * @library /test/lib / - * @requires vm.bits == "64" - * @modules java.base/jdk.internal.misc - * java.management - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseCompressedOops -XX:-UseCompressedClassPointers -XX:-UseCompactObjectHeaders BaseOffsets + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseCompressedOops -XX:-UseCompactObjectHeaders BaseOffsets */ + /* - * @test id=no-coops-no-ccp + * @test id=no-coops * @library /test/lib / * @requires vm.bits == "64" * @modules java.base/jdk.internal.misc * java.management * @build jdk.test.whitebox.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:-UseCompressedOops -XX:-UseCompressedClassPointers -XX:-UseCompactObjectHeaders BaseOffsets + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:-UseCompressedOops -XX:-UseCompactObjectHeaders BaseOffsets */ + /* - * @test id=with-coop--with-coh + * @test id=with-coop-with-coh * @library /test/lib / * @requires vm.bits == "64" * @modules java.base/jdk.internal.misc @@ -71,6 +53,7 @@ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseCompressedOops -XX:+UseCompactObjectHeaders BaseOffsets */ + /* * @test id=no-coops-with-coh * @library /test/lib / @@ -81,6 +64,7 @@ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:-UseCompressedOops -XX:+UseCompactObjectHeaders BaseOffsets */ + /* * @test id=32bit * @library /test/lib / @@ -117,14 +101,10 @@ static class LIClass { INT_OFFSET = 8; INT_ARRAY_OFFSET = 12; LONG_ARRAY_OFFSET = 16; - } else if (WB.getBooleanVMFlag("UseCompressedClassPointers")) { + } else { INT_OFFSET = 12; INT_ARRAY_OFFSET = 16; LONG_ARRAY_OFFSET = 16; - } else { - INT_OFFSET = 16; - INT_ARRAY_OFFSET = 20; - LONG_ARRAY_OFFSET = 24; } } diff --git a/test/hotspot/jtreg/runtime/FieldLayout/FieldDensityTest.java b/test/hotspot/jtreg/runtime/FieldLayout/FieldDensityTest.java index 5f4fb7a79c4..019b428ae84 100644 --- a/test/hotspot/jtreg/runtime/FieldLayout/FieldDensityTest.java +++ b/test/hotspot/jtreg/runtime/FieldLayout/FieldDensityTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,8 +37,7 @@ * @library /test/lib * @modules java.base/jdk.internal.misc * java.management - * @run main/othervm -XX:+UseCompressedOops -XX:+UseCompressedClassPointers FieldDensityTest - * @run main/othervm -XX:+UseCompressedOops -XX:-UseCompressedClassPointers FieldDensityTest + * @run main/othervm -XX:+UseCompressedOops FieldDensityTest */ import java.lang.reflect.Field; diff --git a/test/hotspot/jtreg/runtime/FieldLayout/TestOopMapSizeMinimal.java b/test/hotspot/jtreg/runtime/FieldLayout/TestOopMapSizeMinimal.java index 861f1aa3d1b..263bd750ca3 100644 --- a/test/hotspot/jtreg/runtime/FieldLayout/TestOopMapSizeMinimal.java +++ b/test/hotspot/jtreg/runtime/FieldLayout/TestOopMapSizeMinimal.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2025, Red Hat, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -30,53 +30,43 @@ import java.util.List; /* - * @test id=no_coops_no_ccptr_no_coh + * @test id=no_coops_no_coh * @library /test/lib * @modules java.base/jdk.internal.misc * java.management * @build jdk.test.whitebox.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:-UseCompressedOops -XX:-UseCompressedClassPointers -XX:-UseCompactObjectHeaders TestOopMapSizeMinimal + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:-UseCompressedOops -XX:-UseCompactObjectHeaders TestOopMapSizeMinimal */ /* - * @test id=coops_no_ccptr_no_coh + * @test id=coops_no_coh * @library /test/lib * @modules java.base/jdk.internal.misc * java.management * @build jdk.test.whitebox.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:+UseCompressedOops -XX:-UseCompressedClassPointers -XX:-UseCompactObjectHeaders TestOopMapSizeMinimal + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:+UseCompressedOops -XX:-UseCompactObjectHeaders TestOopMapSizeMinimal */ /* - * @test id=no_coops_ccptr_no_coh + * @test id=no_coops_coh * @library /test/lib * @modules java.base/jdk.internal.misc * java.management * @build jdk.test.whitebox.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:-UseCompressedOops -XX:+UseCompressedClassPointers -XX:-UseCompactObjectHeaders TestOopMapSizeMinimal - */ - -/* - * @test id=coops_ccptr_no_coh - * @library /test/lib - * @modules java.base/jdk.internal.misc - * java.management - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:+UseCompressedOops -XX:+UseCompressedClassPointers -XX:-UseCompactObjectHeaders TestOopMapSizeMinimal + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:-UseCompressedOops -XX:+UseCompactObjectHeaders TestOopMapSizeMinimal */ /* - * @test id=no_coops_ccptr_coh + * @test id=coops_coh * @library /test/lib * @modules java.base/jdk.internal.misc * java.management * @build jdk.test.whitebox.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:-UseCompressedOops -XX:+UseCompactObjectHeaders TestOopMapSizeMinimal + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:+UseCompressedOops -XX:+UseCompactObjectHeaders TestOopMapSizeMinimal */ public class TestOopMapSizeMinimal { @@ -99,10 +89,8 @@ public class TestOopMapSizeMinimal { if (is_64_bit) { if (WB.getBooleanVMFlag("UseCompactObjectHeaders")) { HEADER_SIZE_IN_BYTES = 8; - } else if (WB.getBooleanVMFlag("UseCompressedClassPointers")) { - HEADER_SIZE_IN_BYTES = 12; } else { - HEADER_SIZE_IN_BYTES = 16; + HEADER_SIZE_IN_BYTES = 12; } } else { HEADER_SIZE_IN_BYTES = 8; @@ -188,10 +176,9 @@ public static void main(String[] args) throws Exception { // DERIVED4 o4 oopmap entry 2 (reversed order) // i4 - // There are two combinations that have gaps: - // -UseCompressedOops + +COH, and -UseCompressedOops + -UseCompressedClassPointers. - // In both cases there is a gap following i1, and i2 will therefore nestle into that gap. - // Otherwise the same logic applies. + // There is one combination that has gaps: + // -UseCompressedOops + +COH: A gap will be following i1, and i2 will therefore nestle into that gap. + // Otherwise, the same logic applies. if (OOP_SIZE_IN_BYTES == 4 || // oop size == int size (OOP_SIZE_IN_BYTES == 8 && HEADER_SIZE_IN_BYTES == 12) diff --git a/test/hotspot/jtreg/runtime/Metaspace/MaxMetaspaceSizeTest.java b/test/hotspot/jtreg/runtime/Metaspace/MaxMetaspaceSizeTest.java index b2ff8ed9bde..a42a6ee3a52 100644 --- a/test/hotspot/jtreg/runtime/Metaspace/MaxMetaspaceSizeTest.java +++ b/test/hotspot/jtreg/runtime/Metaspace/MaxMetaspaceSizeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,7 +39,6 @@ public static void main(String... args) throws Exception { "-Xshare:off", "-Xmx1g", "-XX:MaxMetaspaceSize=4K", - "-XX:+UseCompressedClassPointers", "-XX:CompressedClassSpaceSize=1g", "--version"); OutputAnalyzer output = new OutputAnalyzer(pb.start()); diff --git a/test/hotspot/jtreg/runtime/Metaspace/PrintMetaspaceDcmd.java b/test/hotspot/jtreg/runtime/Metaspace/PrintMetaspaceDcmd.java index 7ff19326324..f526405900d 100644 --- a/test/hotspot/jtreg/runtime/Metaspace/PrintMetaspaceDcmd.java +++ b/test/hotspot/jtreg/runtime/Metaspace/PrintMetaspaceDcmd.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2018, SAP and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -22,62 +22,27 @@ * questions. */ +import jdk.test.lib.Platform; import jdk.test.lib.dcmd.PidJcmdExecutor; import jdk.test.lib.process.OutputAnalyzer; -/* - * @test id=test-64bit-ccs - * @summary Test the VM.metaspace command - * @requires vm.bits == "64" - * @library /test/lib - * @modules java.base/jdk.internal.misc - * java.management - * @run main/othervm -Dwith-compressed-class-space -XX:MaxMetaspaceSize=201M -Xmx100M -XX:+UseCompressedOops -XX:+UseCompressedClassPointers PrintMetaspaceDcmd - */ +import java.io.IOException; /* - * @test id=test-64bit-noccs - * @summary Test the VM.metaspace command - * @requires vm.bits == "64" - * @library /test/lib - * @modules java.base/jdk.internal.misc - * java.management - * @run main/othervm -Dwithout-compressed-class-space -XX:MaxMetaspaceSize=201M -Xmx100M -XX:-UseCompressedOops -XX:-UseCompressedClassPointers PrintMetaspaceDcmd - */ - - /* - * @test id=test-nospecified + * @test * @summary Test the VM.metaspace command - * @requires vm.bits == "64" * @library /test/lib * @modules java.base/jdk.internal.misc * java.management - * @run main/othervm -Dno-specified-flag -Xmx100M -XX:-UseCompressedOops -XX:-UseCompressedClassPointers PrintMetaspaceDcmd - */ - -/* - * @test test-32bit - * @summary Test the VM.metaspace command - * @requires vm.bits == "32" - * @library /test/lib - * @modules java.base/jdk.internal.misc - * java.management - * @run main/othervm -Dwithout-compressed-class-space -XX:MaxMetaspaceSize=201M -Xmx100M PrintMetaspaceDcmd + * @run main/othervm -Dwith-compressed-class-space -XX:MaxMetaspaceSize=201M -Xmx100M PrintMetaspaceDcmd */ public class PrintMetaspaceDcmd { - private static void doTheNoSpecifiedPropTest() throws Exception { - ProcessBuilder pb = new ProcessBuilder(); - OutputAnalyzer output; + public static void main(String [] args) throws IOException { - pb.command(new PidJcmdExecutor().getCommandLine("VM.metaspace", "basic")); - output = new OutputAnalyzer(pb.start()); - output.shouldHaveExitValue(0); - output.shouldMatch("MaxMetaspaceSize: unlimited"); - } + final boolean usesCompressedClassSpace = Platform.is64bit(); - private static void doTheCCSPropTest(boolean usesCompressedClassSpace) throws Exception { ProcessBuilder pb = new ProcessBuilder(); OutputAnalyzer output; @@ -172,15 +137,4 @@ private static void doTheCCSPropTest(boolean usesCompressedClassSpace) throws Ex output.shouldMatch("MaxMetaspaceSize:.*210763776 bytes"); } - public static void main(String args[]) throws Exception { - if (System.getProperty("no-specified-flag") != null) { - doTheNoSpecifiedPropTest(); - } else if (System.getProperty("with-compressed-class-space") != null) { - doTheCCSPropTest(true); - } else if (System.getProperty("without-compressed-class-space") != null) { - doTheCCSPropTest(false); - } else { - throw new IllegalArgumentException("Unrecognized running mode"); - } - } } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/CommandLineFlagCombo.java b/test/hotspot/jtreg/runtime/cds/appcds/CommandLineFlagCombo.java index 6ab9b18c1e9..da994edeb27 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, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -55,7 +55,6 @@ public class CommandLineFlagCombo { private static final String[] testTable = { "-XX:+UseG1GC", "-XX:+UseSerialGC", "-XX:+UseParallelGC", "-XX:+UseLargePages", // may only take effect on machines with large-pages - "-XX:+UseCompressedClassPointers", "-XX:+UseCompressedOops", "-XX:ObjectAlignmentInBytes=16", "-XX:ObjectAlignmentInBytes=32", @@ -123,7 +122,6 @@ private static boolean skipTestCase(String testEntry) throws Exception { if (Platform.is32bit()) { if (testEntry.equals("-XX:+UseCompressedOops") || - testEntry.equals("-XX:+UseCompressedClassPointers") || testEntry.contains("ObjectAlignmentInBytes") ) { System.out.println("Test case not applicable on 32-bit platforms"); diff --git a/test/hotspot/jtreg/runtime/cds/appcds/CommandLineFlagComboNegative.java b/test/hotspot/jtreg/runtime/cds/appcds/CommandLineFlagComboNegative.java index 89fe868349b..d5aafb2bcf6 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/CommandLineFlagComboNegative.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/CommandLineFlagComboNegative.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -66,9 +66,9 @@ private void initTestTable() { "An error has occurred while processing the shared archive file", 1) ); } testTable.add( new TestVector("-XX:+UseCompressedOops", "-XX:-UseCompressedOops", - "The saved state of UseCompressedOops and UseCompressedClassPointers is different from runtime, CDS will be disabled.", 1) ); - testTable.add( new TestVector("-XX:+UseCompressedClassPointers", "-XX:-UseCompressedClassPointers", - "The saved state of UseCompressedOops and UseCompressedClassPointers is different from runtime, CDS will be disabled.", 1) ); + "The saved state of UseCompressedOops (1) is different from runtime (0), CDS will be disabled.", 1) ); + testTable.add( new TestVector("-XX:-UseCompressedOops", "-XX:+UseCompressedOops", + "The saved state of UseCompressedOops (0) is different from runtime (1), CDS will be disabled.", 1) ); } private void runTests() throws Exception diff --git a/test/hotspot/jtreg/runtime/cds/appcds/FillerObjectLoadTest.java b/test/hotspot/jtreg/runtime/cds/appcds/FillerObjectLoadTest.java deleted file mode 100644 index 8538155375c..00000000000 --- a/test/hotspot/jtreg/runtime/cds/appcds/FillerObjectLoadTest.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2022, Tencent. All rights reserved. - * 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 8286066 - * @summary VM crash caused by unloaded FillerObject_klass - * @library /test/lib - * @requires vm.cds - * @requires vm.flagless - * @run driver FillerObjectLoadTest - */ - -import jdk.test.lib.process.OutputAnalyzer; -import jdk.test.lib.process.ProcessTools; - -public class FillerObjectLoadTest { - public static void main(String... args) throws Exception { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( - "-XX:+IgnoreUnrecognizedVMOptions", "-XX:-UseCompressedClassPointers", - "-XX:+UnlockExperimentalVMOptions", "-XX:+UseEpsilonGC", "-Xshare:dump", - "-XX:SharedArchiveFile=" + TestCommon.getNewArchiveName()); - OutputAnalyzer analyzer = new OutputAnalyzer(pb.start()); - analyzer.shouldHaveExitValue(0); - - pb = ProcessTools.createLimitedTestJavaProcessBuilder( - "-XX:+IgnoreUnrecognizedVMOptions", "-XX:-UseCompressedClassPointers", - "-XX:TLABSize=2048", "-Xshare:dump", - "-XX:SharedArchiveFile=" + TestCommon.getNewArchiveName()); - analyzer = new OutputAnalyzer(pb.start()); - analyzer.shouldHaveExitValue(0); - } -} diff --git a/test/hotspot/jtreg/runtime/cds/appcds/TestCombinedCompressedFlags.java b/test/hotspot/jtreg/runtime/cds/appcds/TestCombinedCompressedFlags.java index 4f3681d30df..f0700b14b55 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/TestCombinedCompressedFlags.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/TestCombinedCompressedFlags.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,12 +46,10 @@ public class TestCombinedCompressedFlags { static class ConfArg { public boolean useCompressedOops; // UseCompressedOops - public boolean useCompressedClassPointers; // UseCompressedClassPointers public String msg; public int code; - public ConfArg(boolean useCompressedOops, boolean useCompressedClassPointers, String msg, int code) { + public ConfArg(boolean useCompressedOops, String msg, int code) { this.useCompressedOops = useCompressedOops; - this.useCompressedClassPointers = useCompressedClassPointers; this.msg = msg; this.code = code; } @@ -65,67 +63,13 @@ public RunArg(ConfArg arg) { initExecArgs(); } private void initExecArgs() { - /* The combinations have four cases. - * UseCompressedOops UseCompressedClassPointers Result - * 1. - * dump: on on - * test: on on Pass - * on off Fail - * off on Fail - * off off Fail - * 2. - * dump: on off - * test: on off Pass - * on on Fail - * off on Pass - * off off Fail - * 3. - * dump: off on - * test: off on Pass - * on on Fail - * on off Fail - * 4. - * dump: off off - * test: off off Pass - * on on Fail - * on off Fail - **/ + // We fail this test if the UseCompressedOops setting used at dumptime differs from runtime, + // succeed if it is identical execArgs = new ArrayList(); - if (dumpArg.useCompressedOops && dumpArg.useCompressedClassPointers) { - execArgs - .add(new ConfArg(true, true, HELLO_STRING, PASS)); - execArgs - .add(new ConfArg(true, false, EXEC_ABNORMAL_MSG, FAIL)); - execArgs - .add(new ConfArg(false, true, EXEC_ABNORMAL_MSG, FAIL)); - execArgs - .add(new ConfArg(false, false, EXEC_ABNORMAL_MSG, FAIL)); - - } else if(dumpArg.useCompressedOops && !dumpArg.useCompressedClassPointers) { - execArgs - .add(new ConfArg(true, false, HELLO_STRING, PASS)); - execArgs - .add(new ConfArg(true, true, EXEC_ABNORMAL_MSG, FAIL)); - execArgs - .add(new ConfArg(false, true, EXEC_ABNORMAL_MSG, FAIL)); - execArgs - .add(new ConfArg(false, false, EXEC_ABNORMAL_MSG, FAIL)); - - } else if (!dumpArg.useCompressedOops && dumpArg.useCompressedClassPointers) { - execArgs - .add(new ConfArg(false, true, HELLO_STRING, PASS)); - execArgs - .add(new ConfArg(true, true, EXEC_ABNORMAL_MSG, FAIL)); - execArgs - .add(new ConfArg(true, false, EXEC_ABNORMAL_MSG, FAIL)); - } else if (!dumpArg.useCompressedOops && !dumpArg.useCompressedClassPointers) { - execArgs - .add(new ConfArg(false, false, HELLO_STRING, PASS)); - execArgs - .add(new ConfArg(true, true, EXEC_ABNORMAL_MSG, FAIL)); - execArgs - .add(new ConfArg(true, false, EXEC_ABNORMAL_MSG, FAIL)); - } + execArgs + .add(new ConfArg(dumpArg.useCompressedOops, HELLO_STRING, PASS)); + execArgs + .add(new ConfArg(!dumpArg.useCompressedOops, EXEC_ABNORMAL_MSG, FAIL)); } } @@ -134,23 +78,14 @@ public static String getCompressedOopsArg(boolean on) { else return "-XX:-UseCompressedOops"; } - public static String getCompressedClassPointersArg(boolean on) { - if (on) return "-XX:+UseCompressedClassPointers"; - else return "-XX:-UseCompressedClassPointers"; - } - public static List runList; public static void configureRunArgs() { runList = new ArrayList(); runList - .add(new RunArg(new ConfArg(true, true, null, PASS))); - runList - .add(new RunArg(new ConfArg(true, false, null, PASS))); - runList - .add(new RunArg(new ConfArg(false, true, null, PASS))); + .add(new RunArg(new ConfArg(true, null, PASS))); runList - .add(new RunArg(new ConfArg(false, false, null, PASS))); + .add(new RunArg(new ConfArg(false, null, PASS))); } public static void main(String[] args) throws Exception { @@ -162,7 +97,6 @@ public static void main(String[] args) throws Exception { .dump(helloJar, new String[] {"Hello"}, getCompressedOopsArg(t.dumpArg.useCompressedOops), - getCompressedClassPointersArg(t.dumpArg.useCompressedClassPointers), "-Xlog:cds", "-XX:NativeMemoryTracking=detail"); out.shouldContain("Dumping shared data to file:"); @@ -175,7 +109,6 @@ public static void main(String[] args) throws Exception { "-Xlog:cds", "-XX:NativeMemoryTracking=detail", getCompressedOopsArg(c.useCompressedOops), - getCompressedClassPointersArg(c.useCompressedClassPointers), "Hello"); out.shouldContain(c.msg); out.shouldHaveExitValue(c.code); diff --git a/test/hotspot/jtreg/runtime/cds/appcds/TestZGCWithCDS.java b/test/hotspot/jtreg/runtime/cds/appcds/TestZGCWithCDS.java index eb42bb9f93d..bff2bcc727d 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/TestZGCWithCDS.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/TestZGCWithCDS.java @@ -36,7 +36,6 @@ * @comment Driver sets compressed oops/class pointers, jtreg overrides will cause problems. Only run the test if the flags are not set via the command line. * @requires vm.opt.UseCompressedOops == null - * @requires vm.opt.UseCompressedClassPointers == null * @run driver TestZGCWithCDS true */ @@ -55,7 +54,6 @@ * @comment Driver sets compressed oops/class pointers, jtreg overrides will cause problems. Only run the test if the flags are not set via the command line. * @requires vm.opt.UseCompressedOops == null - * @requires vm.opt.UseCompressedClassPointers == null * @run driver TestZGCWithCDS false */ @@ -65,7 +63,7 @@ public class TestZGCWithCDS { public final static String HELLO = "Hello World"; public final static String UNABLE_TO_USE_ARCHIVE = "Unable to use shared archive."; - public final static String ERR_MSG = "The saved state of UseCompressedOops and UseCompressedClassPointers is different from runtime, CDS will be disabled."; + public final static String ERR_MSG = "The saved state of UseCompressedOops (0) is different from runtime (1), CDS will be disabled."; public static void main(String... args) throws Exception { boolean compactHeadersOn = Boolean.valueOf(args[0]); String compactHeaders = "-XX:" + (compactHeadersOn ? "+" : "-") + "UseCompactObjectHeaders"; @@ -80,7 +78,7 @@ public static void main(String... args) throws Exception { out.shouldContain("Dumping shared data to file:"); out.shouldHaveExitValue(0); - System.out.println("1. Run with same args of dump"); + System.out.println("Run with same args of dump"); out = TestCommon .exec(helloJar, "-XX:+UseZGC", @@ -90,12 +88,11 @@ public static void main(String... args) throws Exception { out.shouldContain(HELLO); out.shouldHaveExitValue(0); - System.out.println("2. Run with +UseCompressedOops +UseCompressedClassPointers"); + System.out.println("Run with ZGC, +UseCompressedOops"); out = TestCommon .exec(helloJar, "-XX:-UseZGC", "-XX:+UseCompressedOops", // in case turned off by vmoptions - "-XX:+UseCompressedClassPointers", // by jtreg compactHeaders, "-Xlog:cds", "Hello"); @@ -103,37 +100,22 @@ public static void main(String... args) throws Exception { out.shouldContain(ERR_MSG); out.shouldHaveExitValue(1); - System.out.println("3. Run with -UseCompressedOops -UseCompressedClassPointers"); + System.out.println("Run with SerialGC, -UseCompressedOops"); out = TestCommon .exec(helloJar, "-XX:+UseSerialGC", "-XX:-UseCompressedOops", - "-XX:-UseCompressedClassPointers", - compactHeaders, - "-Xlog:cds", - "Hello"); - out.shouldContain(UNABLE_TO_USE_ARCHIVE); - out.shouldContain(ERR_MSG); - out.shouldHaveExitValue(1); - - System.out.println("4. Run with -UseCompressedOops +UseCompressedClassPointers"); - out = TestCommon - .exec(helloJar, - "-XX:+UseSerialGC", - "-XX:-UseCompressedOops", - "-XX:+UseCompressedClassPointers", compactHeaders, "-Xlog:cds", "Hello"); out.shouldContain(HELLO); out.shouldHaveExitValue(0); - System.out.println("5. Run with +UseCompressedOops -UseCompressedClassPointers"); + System.out.println("Run with SerialGC, +UseCompressedOops"); out = TestCommon .exec(helloJar, "-XX:+UseSerialGC", "-XX:+UseCompressedOops", - "-XX:-UseCompressedClassPointers", compactHeaders, "-Xlog:cds", "Hello"); @@ -141,39 +123,5 @@ public static void main(String... args) throws Exception { out.shouldContain(ERR_MSG); out.shouldHaveExitValue(1); - System.out.println("6. Run with +UseCompressedOops +UseCompressedClassPointers"); - out = TestCommon - .exec(helloJar, - "-XX:+UseSerialGC", - "-XX:+UseCompressedOops", - "-XX:+UseCompressedClassPointers", - compactHeaders, - "-Xlog:cds", - "Hello"); - out.shouldContain(UNABLE_TO_USE_ARCHIVE); - out.shouldContain(ERR_MSG); - out.shouldHaveExitValue(1); - - System.out.println("7. Dump with -UseCompressedOops -UseCompressedClassPointers"); - out = TestCommon - .dump(helloJar, - new String[] {"Hello"}, - "-XX:+UseSerialGC", - "-XX:-UseCompressedOops", - "-XX:+UseCompressedClassPointers", - compactHeaders, - "-Xlog:cds"); - out.shouldContain("Dumping shared data to file:"); - out.shouldHaveExitValue(0); - - System.out.println("8. Run with ZGC"); - out = TestCommon - .exec(helloJar, - "-XX:+UseZGC", - compactHeaders, - "-Xlog:cds", - "Hello"); - out.shouldContain(HELLO); - out.shouldHaveExitValue(0); } } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/OldClassSupport2.java b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/OldClassSupport2.java index 16a4d258e4f..b0db450e352 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/OldClassSupport2.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/OldClassSupport2.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -53,11 +53,6 @@ public static void main(String[] args) throws Exception { // This will disable AOT class linking. Tester tester2 = new Tester("-Djdk.module.showModuleResolution=true"); tester2.run(new String[] {"AOT", "--two-step-training"} ); - - // Heap archiving is disable with -XX:-UseCompressedClassPointers. - // This will disable AOT class linking. - Tester tester3 = new Tester("-XX:-UseCompressedClassPointers"); - tester3.run(new String[] {"AOT", "--two-step-training"} ); } static class Tester extends CDSAppTester { diff --git a/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/DifferentHeapSizes.java b/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/DifferentHeapSizes.java index aeeac7ee0a4..fbf84a2a42d 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/DifferentHeapSizes.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/DifferentHeapSizes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -84,7 +84,7 @@ public static void main(String[] args) throws Exception { } else { result .assertAbnormalExit("Unable to use shared archive.", - "The saved state of UseCompressedOops and UseCompressedClassPointers is different from runtime, CDS will be disabled."); + "The saved state of UseCompressedOops (1) is different from runtime (0), CDS will be disabled."); } } } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/CDSStreamTestDriver.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/CDSStreamTestDriver.java index 88af964d836..8d66ff3336f 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/CDSStreamTestDriver.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/CDSStreamTestDriver.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -69,7 +69,7 @@ static void doTest() throws Exception { } catch (SkippedException s) { if (GC.Z.isSelected() && s.toString().equals(skippedException)) { System.out.println("Got " + s.toString() + " as expected."); - System.out.println("Because the test was run with ZGC with UseCompressedOops and UseCompressedClassPointers disabled,"); + System.out.println("Because the test was run with ZGC with UseCompressedOops disabled,"); System.out.println("but the base archive was created with the options enabled"); } else { throw new RuntimeException("Archive mapping should always succeed after JDK-8231610 (did the machine run out of memory?)"); diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/DynamicArchiveTestBase.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/DynamicArchiveTestBase.java index 108002246db..8ee3b405604 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, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -306,9 +306,8 @@ private static String getTempBaseArchive() throws Exception { * the JDK was built via cross-compilation on a different platform; * - the VM under test was started with a different options than the ones * when the default CDS archive was built. E.g. the VM was started with - * -XX:+UseZGC which implicitly disabled the UseCompressedOoops and the - * UseCompressedClassPointers options. Those "compressed" options were - * enabled when the default CDS archive was built. + * -XX:+UseZGC which implicitly disables the UseCompressedOops option. + * UseCompressedOops was enabled when the default CDS archive was built. */ public static boolean isUseSharedSpacesDisabled() { return !WB.isSharingEnabled(); diff --git a/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/IncompatibleOptions.java b/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/IncompatibleOptions.java index ddbfe2ed862..f2ec33cdefe 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/IncompatibleOptions.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/IncompatibleOptions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -83,7 +83,9 @@ public class IncompatibleOptions { static final String COMPACT_STRING_MISMATCH = "The shared archive file's CompactStrings setting .* does not equal the current CompactStrings setting"; static final String COMPRESSED_OOPS_NOT_CONSISTENT = - "The saved state of UseCompressedOops and UseCompressedClassPointers is different from runtime, CDS will be disabled."; + "The saved state of UseCompressedOops \\(%d\\) is different from runtime \\(%d\\), CDS will be disabled."; + static final String COMPRESSED_OOPS_NOT_CONSISTENT_10 = COMPRESSED_OOPS_NOT_CONSISTENT.formatted(1, 0); + static final String COMPRESSED_OOPS_NOT_CONSISTENT_01 = COMPRESSED_OOPS_NOT_CONSISTENT.formatted(0, 1); static String appJar; static String[] vmOptionsPrefix = {}; @@ -117,7 +119,7 @@ public static void test(String[] args_ignored) throws Exception { // Explicitly archive with compressed oops, run without. testDump(3, "-XX:+UseG1GC", "-XX:+UseCompressedOops", null, false); - testExec(3, "-XX:+UseG1GC", "-XX:-UseCompressedOops", COMPRESSED_OOPS_NOT_CONSISTENT, true); + testExec(3, "-XX:+UseG1GC", "-XX:-UseCompressedOops", COMPRESSED_OOPS_NOT_CONSISTENT_10, true); // NOTE: No warning is displayed, by design // Still run, to ensure no crash or exception @@ -130,14 +132,14 @@ public static void test(String[] args_ignored) throws Exception { testExec(4, "-XX:+UseSerialGC", "", "", false); if (GC.Z.isSupported()) { - testExec(4, "-XX:+UseZGC", "", COMPRESSED_OOPS_NOT_CONSISTENT, true); + testExec(4, "-XX:+UseZGC", "", COMPRESSED_OOPS_NOT_CONSISTENT_10, true); } // Explicitly archive with object streaming and COOPs with one GC, run with other GCs. testDump(4, "-XX:-UseCompressedOops", "-XX:+AOTStreamableObjects", null, false); - testExec(4, "-XX:+UseG1GC", "", COMPRESSED_OOPS_NOT_CONSISTENT, true); - testExec(4, "-XX:+UseParallelGC", "", COMPRESSED_OOPS_NOT_CONSISTENT, true); - testExec(4, "-XX:+UseSerialGC", "", COMPRESSED_OOPS_NOT_CONSISTENT, true); + testExec(4, "-XX:+UseG1GC", "", COMPRESSED_OOPS_NOT_CONSISTENT_01, true); + testExec(4, "-XX:+UseParallelGC", "", COMPRESSED_OOPS_NOT_CONSISTENT_01, true); + testExec(4, "-XX:+UseSerialGC", "", COMPRESSED_OOPS_NOT_CONSISTENT_01, true); testExec(4, "-XX:+UseParallelGC", "-XX:-UseCompressedOops", "", false); testExec(4, "-XX:+UseSerialGC", "-XX:-UseCompressedOops", "", false); diff --git a/test/hotspot/jtreg/serviceability/dcmd/vm/ClassLoaderStatsTest.java b/test/hotspot/jtreg/serviceability/dcmd/vm/ClassLoaderStatsTest.java index a89f2508852..aaf54e03f9e 100644 --- a/test/hotspot/jtreg/serviceability/dcmd/vm/ClassLoaderStatsTest.java +++ b/test/hotspot/jtreg/serviceability/dcmd/vm/ClassLoaderStatsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,17 +32,6 @@ * @run testng/othervm --add-exports=java.base/jdk.internal.misc=ALL-UNNAMED --add-exports=jdk.internal.jvmstat/sun.jvmstat.monitor=ALL-UNNAMED ClassLoaderStatsTest */ -/* - * @test - * @summary Test of diagnostic command VM.classloader_stats (-UseCCP) - * @library /test/lib - * @requires vm.bits != "32" - * @modules java.base/jdk.internal.misc - * java.compiler - * java.management - * jdk.internal.jvmstat/sun.jvmstat.monitor - * @run testng/othervm -XX:-UseCompressedClassPointers --add-exports=java.base/jdk.internal.misc=ALL-UNNAMED --add-exports=jdk.internal.jvmstat/sun.jvmstat.monitor=ALL-UNNAMED ClassLoaderStatsTest - */ import org.testng.annotations.Test; import org.testng.Assert; @@ -110,7 +99,7 @@ public void run(CommandExecutor executor) throws ClassNotFoundException { // Minimum expected sizes: initial capacity is governed by the chunk size of the first chunk, which // depends on the arena growth policy. Since this is a normal class loader, we expect as initial chunk - // size at least 4k (if UseCompressedClassPointers is off). + // size at least 4k. // Minimum used size is difficult to guess but should be at least 1k. // Maximum expected sizes: We just assume a reasonable maximum. We only loaded one class, so // we should not see values > 64k. diff --git a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestIRMatching.java b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestIRMatching.java index fc8a92cf9a2..e4111238b59 100644 --- a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestIRMatching.java +++ b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestIRMatching.java @@ -165,25 +165,6 @@ public static void main(String[] args) { BadFailOnConstraint.create(RunTests.class, "bad1", 2, "Load") ); - runCheck(new String[] {"-XX:+IgnoreUnrecognizedVMOptions", "-XX:-UseCompressedClassPointers"}, - BadFailOnConstraint.create(Loads.class, "load", 1, 1, "Load"), - BadFailOnConstraint.create(Loads.class, "load", 1, 3, "LoadI"), - BadCountsConstraint.create(Loads.class, "load", 1, 1, 0), - BadCountsConstraint.create(Loads.class, "load", 1, 2, 1,"Load"), - GoodRuleConstraint.create(Loads.class, "load", 2), - GoodFailOnConstraint.create(Loads.class, "load", 3), - BadCountsConstraint.create(Loads.class, "load", 3, 2, 2,"Store"), - BadFailOnConstraint.create(Loads.class, "load", 4, 2, "Store"), - BadFailOnConstraint.create(Loads.class, "load", 5, "Load"), - BadFailOnConstraint.create(Loads.class, "load", 6, "Load"), - BadFailOnConstraint.create(Loads.class, "load", 7, "Load"), - GoodRuleConstraint.create(Loads.class, "load", 8), - GoodRuleConstraint.create(Loads.class, "load", 9), - GoodRuleConstraint.create(Loads.class, "load", 10), - BadFailOnConstraint.create(Loads.class, "loadKlass", 1), - BadCountsConstraint.create(Loads.class, "loadKlass", 2, 2,"Field") - ); - // Loops runCheck(BadFailOnConstraint.create(Loops.class, "loop", 1, "Loop"), GoodRuleConstraint.create(Loops.class, "loop", 2), diff --git a/test/jdk/java/lang/instrument/GetObjectSizeIntrinsicsTest.java b/test/jdk/java/lang/instrument/GetObjectSizeIntrinsicsTest.java index 44276a9f7f5..cdaa94e8289 100644 --- a/test/jdk/java/lang/instrument/GetObjectSizeIntrinsicsTest.java +++ b/test/jdk/java/lang/instrument/GetObjectSizeIntrinsicsTest.java @@ -314,8 +314,9 @@ public class GetObjectSizeIntrinsicsTest extends ASimpleInstrumentationTestCase 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; - static final boolean CCP = WhiteBox.getWhiteBox().getBooleanVMFlag("UseCompressedClassPointers"); - static final int ARRAY_HEADER_SIZE = CCP ? 16 : (Platform.is64bit() ? 20 : 12); + // 64-bit: 8mw-4ccp-4len + // 32-bit: 4mw-4ccp-4len-4gap + static final int ARRAY_HEADER_SIZE = 16; final String mode; diff --git a/test/jdk/jdk/jfr/event/allocation/TestObjectAllocationInNewTLABEvent.java b/test/jdk/jdk/jfr/event/allocation/TestObjectAllocationInNewTLABEvent.java index 9112cfbc247..9cc3141cd2d 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, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -64,9 +64,10 @@ public class TestObjectAllocationInNewTLABEvent { private final static String EVENT_NAME = EventNames.ObjectAllocationInNewTLAB; - 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; + // 64-bit COH: MW8 + L4 + End Alignment = 16 + // 64-bit -COH: MW8 + K4 + L4 = 16 + // 32-bit : MW4 + K4 + L4 + End Alignment = 16 + private static final int BYTE_ARRAY_OVERHEAD = 16; private static final int OBJECT_SIZE = 128 * 1024; private static final int OBJECTS_TO_ALLOCATE = 100; diff --git a/test/jdk/jdk/jfr/event/allocation/TestObjectAllocationOutsideTLABEvent.java b/test/jdk/jdk/jfr/event/allocation/TestObjectAllocationOutsideTLABEvent.java index a7695b76849..9a4f0f28974 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, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -64,9 +64,10 @@ public class TestObjectAllocationOutsideTLABEvent { private static final String EVENT_NAME = EventNames.ObjectAllocationOutsideTLAB; - 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; + // 64-bit COH: MW8 + L4 + End Alignment = 16 + // 64-bit -COH: MW8 + K4 + L4 = 16 + // 32-bit : MW4 + K4 + L4 + End Alignment = 16 + private static final int BYTE_ARRAY_OVERHEAD = 16; private static final int OBJECT_SIZE = 128 * 1024; private static final int OBJECTS_TO_ALLOCATE = 100; diff --git a/test/jdk/jdk/jfr/event/allocation/TestObjectAllocationSampleEventThrottling.java b/test/jdk/jdk/jfr/event/allocation/TestObjectAllocationSampleEventThrottling.java index 47f5b31f881..214f7336a73 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, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -52,9 +52,10 @@ public class TestObjectAllocationSampleEventThrottling { private static final String EVENT_NAME = EventNames.ObjectAllocationSample; - 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; + // 64-bit COH: MW8 + L4 + End Alignment = 16 + // 64-bit -COH: MW8 + K4 + L4 = 16 + // 32-bit : MW4 + K4 + L4 + End Alignment = 16 + private static final int BYTE_ARRAY_OVERHEAD = 16; private static final int OBJECT_SIZE = 128 * 1024; private static final int OBJECTS_TO_ALLOCATE = 100; diff --git a/test/jdk/jdk/jfr/event/gc/heapsummary/TestHeapSummaryEventDefNewSerial.java b/test/jdk/jdk/jfr/event/gc/heapsummary/TestHeapSummaryEventDefNewSerial.java index f70d7a85f16..b880bd93bc5 100644 --- a/test/jdk/jdk/jfr/event/gc/heapsummary/TestHeapSummaryEventDefNewSerial.java +++ b/test/jdk/jdk/jfr/event/gc/heapsummary/TestHeapSummaryEventDefNewSerial.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,16 +33,6 @@ * @run main/othervm -XX:+UseSerialGC jdk.jfr.event.gc.heapsummary.TestHeapSummaryEventDefNewSerial */ -/** - * @test - * @bug 8264008 - * @requires vm.flagless - * @requires vm.hasJFR & vm.bits == 64 - * @requires vm.gc == "Serial" | vm.gc == null - * @library /test/lib /test/jdk - * @run main/othervm -XX:+UseSerialGC -XX:-UseCompressedClassPointers - * jdk.jfr.event.gc.heapsummary.TestHeapSummaryEventDefNewSerial - */ public class TestHeapSummaryEventDefNewSerial { public static void main(String[] args) throws Exception { HeapSummaryEventAllGcs.test(GCHelper.gcDefNew, GCHelper.gcSerialOld); diff --git a/test/jdk/jdk/jfr/event/gc/objectcount/ObjectCountEventVerifier.java b/test/jdk/jdk/jfr/event/gc/objectcount/ObjectCountEventVerifier.java index 0ab663f130a..d7e6b3209d3 100644 --- a/test/jdk/jdk/jfr/event/gc/objectcount/ObjectCountEventVerifier.java +++ b/test/jdk/jdk/jfr/event/gc/objectcount/ObjectCountEventVerifier.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -70,7 +70,7 @@ public static void verify(List objectCountEvents) throws Exceptio private static long expectedFooArraySize(long count) { boolean runsOn32Bit = System.getProperty("sun.arch.data.model").equals("32"); int bytesPerWord = runsOn32Bit ? 4 : 8; - int objectHeaderSize = bytesPerWord * 3; // length will be aligned on 64 bits + int objectHeaderSize = runsOn32Bit ? 12 : 16; int alignmentInOopArray = runsOn32Bit ? 4 : 0; int ptrSize = bytesPerWord; return objectHeaderSize + alignmentInOopArray + count * ptrSize; diff --git a/test/jdk/jdk/jfr/event/gc/objectcount/TestObjectCountAfterGCEventWithG1ConcurrentMark.java b/test/jdk/jdk/jfr/event/gc/objectcount/TestObjectCountAfterGCEventWithG1ConcurrentMark.java index eb69289aa5e..fbf2d8b543d 100644 --- a/test/jdk/jdk/jfr/event/gc/objectcount/TestObjectCountAfterGCEventWithG1ConcurrentMark.java +++ b/test/jdk/jdk/jfr/event/gc/objectcount/TestObjectCountAfterGCEventWithG1ConcurrentMark.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,7 +31,7 @@ * @requires (vm.gc == "G1" | vm.gc == null) * & vm.opt.ExplicitGCInvokesConcurrent != false * @library /test/lib /test/jdk - * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseG1GC -XX:+ExplicitGCInvokesConcurrent -XX:MarkSweepDeadRatio=0 -XX:-UseCompressedOops -XX:-UseCompressedClassPointers -XX:+IgnoreUnrecognizedVMOptions jdk.jfr.event.gc.objectcount.TestObjectCountAfterGCEventWithG1ConcurrentMark + * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseG1GC -XX:+ExplicitGCInvokesConcurrent -XX:MarkSweepDeadRatio=0 -XX:-UseCompressedOops -XX:+IgnoreUnrecognizedVMOptions jdk.jfr.event.gc.objectcount.TestObjectCountAfterGCEventWithG1ConcurrentMark */ public class TestObjectCountAfterGCEventWithG1ConcurrentMark { public static void main(String[] args) throws Exception { diff --git a/test/jdk/jdk/jfr/event/gc/objectcount/TestObjectCountAfterGCEventWithG1FullCollection.java b/test/jdk/jdk/jfr/event/gc/objectcount/TestObjectCountAfterGCEventWithG1FullCollection.java index 6e91cf4c644..758ab6988b5 100644 --- a/test/jdk/jdk/jfr/event/gc/objectcount/TestObjectCountAfterGCEventWithG1FullCollection.java +++ b/test/jdk/jdk/jfr/event/gc/objectcount/TestObjectCountAfterGCEventWithG1FullCollection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,7 +31,7 @@ * @requires (vm.gc == "G1" | vm.gc == null) * & vm.opt.ExplicitGCInvokesConcurrent != true * @library /test/lib /test/jdk - * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:-UseFastUnorderedTimeStamps -XX:+UseG1GC -XX:MarkSweepDeadRatio=0 -XX:-UseCompressedOops -XX:-UseCompressedClassPointers -XX:+IgnoreUnrecognizedVMOptions jdk.jfr.event.gc.objectcount.TestObjectCountAfterGCEventWithG1FullCollection + * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:-UseFastUnorderedTimeStamps -XX:+UseG1GC -XX:MarkSweepDeadRatio=0 -XX:-UseCompressedOops -XX:+IgnoreUnrecognizedVMOptions jdk.jfr.event.gc.objectcount.TestObjectCountAfterGCEventWithG1FullCollection */ public class TestObjectCountAfterGCEventWithG1FullCollection { public static void main(String[] args) throws Exception { diff --git a/test/jdk/jdk/jfr/event/gc/objectcount/TestObjectCountAfterGCEventWithParallelOld.java b/test/jdk/jdk/jfr/event/gc/objectcount/TestObjectCountAfterGCEventWithParallelOld.java index 2a17e540be8..ac43d0d24e4 100644 --- a/test/jdk/jdk/jfr/event/gc/objectcount/TestObjectCountAfterGCEventWithParallelOld.java +++ b/test/jdk/jdk/jfr/event/gc/objectcount/TestObjectCountAfterGCEventWithParallelOld.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,7 @@ * @requires vm.hasJFR * @requires vm.gc == "Parallel" | vm.gc == null * @library /test/lib /test/jdk - * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:-UseFastUnorderedTimeStamps -XX:+UseParallelGC -XX:MarkSweepDeadRatio=0 -XX:-UseCompressedOops -XX:-UseCompressedClassPointers -XX:+IgnoreUnrecognizedVMOptions jdk.jfr.event.gc.objectcount.TestObjectCountAfterGCEventWithParallelOld + * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:-UseFastUnorderedTimeStamps -XX:+UseParallelGC -XX:MarkSweepDeadRatio=0 -XX:-UseCompressedOops -XX:+IgnoreUnrecognizedVMOptions jdk.jfr.event.gc.objectcount.TestObjectCountAfterGCEventWithParallelOld */ public class TestObjectCountAfterGCEventWithParallelOld { public static void main(String[] args) throws Exception { diff --git a/test/jdk/jdk/jfr/event/gc/objectcount/TestObjectCountAfterGCEventWithSerial.java b/test/jdk/jdk/jfr/event/gc/objectcount/TestObjectCountAfterGCEventWithSerial.java index 888eb089027..eac0e935fea 100644 --- a/test/jdk/jdk/jfr/event/gc/objectcount/TestObjectCountAfterGCEventWithSerial.java +++ b/test/jdk/jdk/jfr/event/gc/objectcount/TestObjectCountAfterGCEventWithSerial.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,7 @@ * @requires vm.hasJFR * @requires vm.gc == "Serial" | vm.gc == null * @library /test/lib /test/jdk - * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:-UseFastUnorderedTimeStamps -XX:+UseSerialGC -XX:MarkSweepDeadRatio=0 -XX:-UseCompressedOops -XX:-UseCompressedClassPointers -XX:+IgnoreUnrecognizedVMOptions jdk.jfr.event.gc.objectcount.TestObjectCountAfterGCEventWithSerial + * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:-UseFastUnorderedTimeStamps -XX:+UseSerialGC -XX:MarkSweepDeadRatio=0 -XX:-UseCompressedOops -XX:+IgnoreUnrecognizedVMOptions jdk.jfr.event.gc.objectcount.TestObjectCountAfterGCEventWithSerial */ public class TestObjectCountAfterGCEventWithSerial { public static void main(String[] args) throws Exception { diff --git a/test/jdk/jdk/jfr/event/gc/objectcount/TestObjectCountEvent.java b/test/jdk/jdk/jfr/event/gc/objectcount/TestObjectCountEvent.java index a9034ba0eaa..0a5d48e83c8 100644 --- a/test/jdk/jdk/jfr/event/gc/objectcount/TestObjectCountEvent.java +++ b/test/jdk/jdk/jfr/event/gc/objectcount/TestObjectCountEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,7 +39,7 @@ * @requires vm.hasJFR * @requires vm.gc == "Serial" | vm.gc == null * @library /test/lib /test/jdk - * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:-UseFastUnorderedTimeStamps -XX:+UseSerialGC -XX:-UseCompressedOops -XX:-UseCompressedClassPointers -XX:MarkSweepDeadRatio=0 -XX:+IgnoreUnrecognizedVMOptions jdk.jfr.event.gc.objectcount.TestObjectCountEvent + * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:-UseFastUnorderedTimeStamps -XX:+UseSerialGC -XX:-UseCompressedOops -XX:MarkSweepDeadRatio=0 -XX:+IgnoreUnrecognizedVMOptions jdk.jfr.event.gc.objectcount.TestObjectCountEvent */ public class TestObjectCountEvent { private static final String objectCountEventPath = EventNames.ObjectCount; diff --git a/test/jtreg-ext/requires/VMProps.java b/test/jtreg-ext/requires/VMProps.java index 2d604a92b75..16fd32e626b 100644 --- a/test/jtreg-ext/requires/VMProps.java +++ b/test/jtreg-ext/requires/VMProps.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -474,8 +474,7 @@ protected String vmCDSForCustomLoaders() { /** * @return true if it's possible for "java -Xshare:dump" to write Java heap objects - * with the current set of jtreg VM options. For example, false will be returned - * if -XX:-UseCompressedClassPointers is specified. + * with the current set of jtreg VM options. */ protected String vmCDSCanWriteArchivedJavaHeap() { return "" + ("true".equals(vmCDS()) && WB.canWriteJavaHeapArchive()); @@ -483,8 +482,7 @@ protected String vmCDSCanWriteArchivedJavaHeap() { /** * @return true if it's possible for "java -Xshare:dump" to write Java heap objects - * with the current set of jtreg VM options. For example, false will be returned - * if -XX:-UseCompressedClassPointers is specified. + * with the current set of jtreg VM options. */ protected String vmCDSCanWriteMappedArchivedJavaHeap() { return "" + ("true".equals(vmCDS()) && WB.canWriteMappedJavaHeapArchive()); @@ -492,8 +490,7 @@ protected String vmCDSCanWriteMappedArchivedJavaHeap() { /** * @return true if it's possible for "java -Xshare:dump" to write Java heap objects - * with the current set of jtreg VM options. For example, false will be returned - * if -XX:-UseCompressedClassPointers is specified. + * with the current set of jtreg VM options. */ protected String vmCDSCanWriteStreamedArchivedJavaHeap() { return "" + ("true".equals(vmCDS()) && WB.canWriteStreamedJavaHeapArchive()); From e07ab7fb9b5e49093f84b05fb6cecfa00f1b0f52 Mon Sep 17 00:00:00 2001 From: Arno Zeller Date: Thu, 26 Mar 2026 11:17:18 +0000 Subject: [PATCH 006/116] 8380288: [BACKOUT] Incorrect Interpretation of POSIX TZ Environment Variable on AIX Reviewed-by: mbaesken, mdoerr --- .../unix/native/libjava/TimeZone_md.c | 66 +++++++------------ 1 file changed, 22 insertions(+), 44 deletions(-) diff --git a/src/java.base/unix/native/libjava/TimeZone_md.c b/src/java.base/unix/native/libjava/TimeZone_md.c index 39e7b726220..cd253edde60 100644 --- a/src/java.base/unix/native/libjava/TimeZone_md.c +++ b/src/java.base/unix/native/libjava/TimeZone_md.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2026, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -352,15 +352,33 @@ getPlatformTimeZoneID() } static char * -getJavaTimezoneFromPlatform(const char *tz_buf, size_t tz_len, const char *mapfilename) { +mapPlatformToJavaTimezone(const char *java_home_dir, const char *tz) { FILE *tzmapf; + char mapfilename[PATH_MAX + 1]; char line[256]; int linecount = 0; + char *tz_buf = NULL; + char *temp_tz = NULL; char *javatz = NULL; + size_t tz_len = 0; + /* On AIX, the TZ environment variable may end with a comma + * followed by modifier fields until early AIX6.1. + * This restriction has been removed from AIX7. */ + + tz_buf = strdup(tz); + tz_len = strlen(tz_buf); + + /* Open tzmappings file, with buffer overrun check */ + if ((strlen(java_home_dir) + 15) > PATH_MAX) { + jio_fprintf(stderr, "Path %s/lib/tzmappings exceeds maximum path length\n", java_home_dir); + goto tzerr; + } + strcpy(mapfilename, java_home_dir); + strcat(mapfilename, "/lib/tzmappings"); if ((tzmapf = fopen(mapfilename, "r")) == NULL) { jio_fprintf(stderr, "can't open %s\n", mapfilename); - return NULL; + goto tzerr; } while (fgets(line, sizeof(line), tzmapf) != NULL) { @@ -413,50 +431,10 @@ getJavaTimezoneFromPlatform(const char *tz_buf, size_t tz_len, const char *mapfi break; } } - (void) fclose(tzmapf); - return javatz; -} - -static char * -mapPlatformToJavaTimezone(const char *java_home_dir, const char *tz) { - char mapfilename[PATH_MAX + 1]; - char *tz_buf = NULL; - char *javatz = NULL; - char *temp_tz = NULL; - size_t tz_len = 0; - - /* On AIX, the TZ environment variable may end with a comma - * followed by modifier fields until early AIX6.1. - * This restriction has been removed from AIX7. */ - - tz_buf = strdup(tz); - tz_len = strlen(tz_buf); - - /* Open tzmappings file, with buffer overrun check */ - if ((strlen(java_home_dir) + 15) > PATH_MAX) { - jio_fprintf(stderr, "Path %s/lib/tzmappings exceeds maximum path length\n", java_home_dir); - goto tzerr; - } - strcpy(mapfilename, java_home_dir); - strcat(mapfilename, "/lib/tzmappings"); - - // First attempt to find the Java timezone for the full tz string - javatz = getJavaTimezoneFromPlatform(tz_buf, tz_len, mapfilename); - - // If no match was found, check for timezone with truncated value - if (javatz == NULL) { - temp_tz = strchr(tz, ','); - tz_len = (temp_tz == NULL) ? strlen(tz) : temp_tz - tz; - free((void *) tz_buf); - tz_buf = (char *)malloc(tz_len + 1); - memcpy(tz_buf, tz, tz_len); - tz_buf[tz_len] = '\0'; - javatz = getJavaTimezoneFromPlatform(tz_buf, tz_len, mapfilename); - } tzerr: - if (tz_buf != NULL) { + if (tz_buf != NULL ) { free((void *) tz_buf); } From 407b677d5fe20f1958f530207e62234d510daca4 Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Thu, 26 Mar 2026 11:41:10 +0000 Subject: [PATCH 007/116] 8380942: Fix whitespace and conditional logic in interpreter code Reviewed-by: dholmes, aartemov --- src/hotspot/share/interpreter/interpreterRuntime.cpp | 8 +++----- src/hotspot/share/interpreter/linkResolver.cpp | 10 +++++----- src/hotspot/share/interpreter/oopMapCache.cpp | 10 +++++----- 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/hotspot/share/interpreter/interpreterRuntime.cpp b/src/hotspot/share/interpreter/interpreterRuntime.cpp index 59d5f29023c..e7b35b121a2 100644 --- a/src/hotspot/share/interpreter/interpreterRuntime.cpp +++ b/src/hotspot/share/interpreter/interpreterRuntime.cpp @@ -243,9 +243,9 @@ JRT_ENTRY(void, InterpreterRuntime::multianewarray(JavaThread* current, jint* fi // We may want to pass in more arguments - could make this slightly faster LastFrameAccessor last_frame(current); ConstantPool* constants = last_frame.method()->constants(); - int i = last_frame.get_index_u2(Bytecodes::_multianewarray); - Klass* klass = constants->klass_at(i, CHECK); - int nof_dims = last_frame.number_of_dimensions(); + int i = last_frame.get_index_u2(Bytecodes::_multianewarray); + Klass* klass = constants->klass_at(i, CHECK); + int nof_dims = last_frame.number_of_dimensions(); assert(klass->is_klass(), "not a class"); assert(nof_dims >= 1, "multianewarray rank must be nonzero"); @@ -756,12 +756,10 @@ JRT_LEAF(void, InterpreterRuntime::monitorexit(BasicObjectLock* elem)) elem->set_obj(nullptr); JRT_END - JRT_ENTRY(void, InterpreterRuntime::throw_illegal_monitor_state_exception(JavaThread* current)) THROW(vmSymbols::java_lang_IllegalMonitorStateException()); JRT_END - JRT_ENTRY(void, InterpreterRuntime::new_illegal_monitor_state_exception(JavaThread* current)) // Returns an illegal exception to install into the current thread. The // pending_exception flag is cleared so normal exception handling does not diff --git a/src/hotspot/share/interpreter/linkResolver.cpp b/src/hotspot/share/interpreter/linkResolver.cpp index c82398b654c..25fff580c9d 100644 --- a/src/hotspot/share/interpreter/linkResolver.cpp +++ b/src/hotspot/share/interpreter/linkResolver.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1045,7 +1045,7 @@ void LinkResolver::resolve_field(fieldDescriptor& fd, stringStream ss; ss.print("Update to %s final field %s.%s attempted from a different class (%s) than the field's declaring class", is_static ? "static" : "non-static", resolved_klass->external_name(), fd.name()->as_C_string(), - current_klass->external_name()); + current_klass->external_name()); THROW_MSG(vmSymbols::java_lang_IllegalAccessError(), ss.as_string()); } @@ -1260,7 +1260,7 @@ void LinkResolver::runtime_resolve_special_method(CallInfo& result, methodHandle sel_method(THREAD, resolved_method()); if (link_info.check_access() && - // check if the method is not + // check if the method is not , which is never inherited resolved_method->name() != vmSymbols::object_initializer_name()) { Klass* current_klass = link_info.current_klass(); @@ -1724,8 +1724,8 @@ void LinkResolver::resolve_invoke(CallInfo& result, Handle recv, const constantP } void LinkResolver::resolve_invoke(CallInfo& result, Handle& recv, - const methodHandle& attached_method, - Bytecodes::Code byte, TRAPS) { + const methodHandle& attached_method, + Bytecodes::Code byte, TRAPS) { Klass* defc = attached_method->method_holder(); Symbol* name = attached_method->name(); Symbol* type = attached_method->signature(); diff --git a/src/hotspot/share/interpreter/oopMapCache.cpp b/src/hotspot/share/interpreter/oopMapCache.cpp index d7c02296f33..5a1ad7b7883 100644 --- a/src/hotspot/share/interpreter/oopMapCache.cpp +++ b/src/hotspot/share/interpreter/oopMapCache.cpp @@ -256,8 +256,8 @@ bool OopMapCacheEntry::verify_mask(CellTypeState* vars, CellTypeState* stack, in 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; + bool v1 = is_oop(i); + bool v2 = vars[i].is_reference(); assert(v1 == v2, "locals oop mask generation error"); if (log) st.print("%d", v1 ? 1 : 0); } @@ -265,8 +265,8 @@ bool OopMapCacheEntry::verify_mask(CellTypeState* vars, CellTypeState* stack, in 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; + bool v1 = is_oop(max_locals + j); + bool v2 = stack[j].is_reference(); assert(v1 == v2, "stack oop mask generation error"); if (log) st.print("%d", v1 ? 1 : 0); } @@ -350,7 +350,7 @@ void OopMapCacheEntry::set_mask(CellTypeState *vars, CellTypeState *stack, int s } // set oop bit - if ( cell->is_reference()) { + if (cell->is_reference()) { value |= (mask << oop_bit_number ); _num_oops++; } From 60ce4857f406a3fe68be008ab1ca206b032412dc Mon Sep 17 00:00:00 2001 From: Daniel Fuchs Date: Thu, 26 Mar 2026 11:48:34 +0000 Subject: [PATCH 008/116] 8380931: Refactor remaining java/nio/channels TestNG tests to use JUnit Reviewed-by: alanb --- .../SocketChannel/AdaptorStreams.java | 81 +++-- .../SocketChannel/ConnectionReset.java | 22 +- .../SocketChannel/ReadWriteAfterClose.java | 54 +-- .../channels/etc/LocalSocketAddressType.java | 63 ++-- .../java/nio/channels/etc/OpenAndConnect.java | 199 ++++++----- .../nio/channels/etc/ProtocolFamilies.java | 239 ++++++------- .../unixdomain/EmptySunPathForSocketFile.java | 16 +- .../channels/unixdomain/FileAttributes.java | 27 +- .../nio/channels/unixdomain/IOExchanges.java | 328 ++++++++++-------- .../nio/channels/unixdomain/NullTest.java | 13 +- 10 files changed, 561 insertions(+), 481 deletions(-) diff --git a/test/jdk/java/nio/channels/SocketChannel/AdaptorStreams.java b/test/jdk/java/nio/channels/SocketChannel/AdaptorStreams.java index 3487ae45de1..240d9e3baf7 100644 --- a/test/jdk/java/nio/channels/SocketChannel/AdaptorStreams.java +++ b/test/jdk/java/nio/channels/SocketChannel/AdaptorStreams.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* @test * @bug 8222774 4430139 - * @run testng AdaptorStreams + * @run junit AdaptorStreams * @summary Exercise socket adaptor input/output streams */ @@ -44,77 +44,82 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; -import org.testng.annotations.Test; -import static org.testng.Assert.*; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; -@Test public class AdaptorStreams { /** * Test read when bytes are available */ + @Test public void testRead1() throws Exception { withConnection((sc, peer) -> { peer.getOutputStream().write(99); int n = sc.socket().getInputStream().read(); - assertEquals(n, 99); + assertEquals(99, n); }); } /** * Test read blocking before bytes are available */ + @Test public void testRead2() throws Exception { withConnection((sc, peer) -> { scheduleWrite(peer.getOutputStream(), 99, 1000); int n = sc.socket().getInputStream().read(); - assertEquals(n, 99); + assertEquals(99, n); }); } /** * Test read when peer has closed connection */ + @Test public void testRead3() throws Exception { withConnection((sc, peer) -> { peer.close(); int n = sc.socket().getInputStream().read(); - assertEquals(n, -1); + assertEquals(-1, n); }); } /** * Test read blocking before peer closes connection */ + @Test public void testRead4() throws Exception { withConnection((sc, peer) -> { scheduleClose(peer, 1000); int n = sc.socket().getInputStream().read(); - assertEquals(n, -1); + assertEquals(-1, n); }); } /** * Test async close of socket when thread blocked in read */ + @Test public void testRead5() throws Exception { withConnection((sc, peer) -> { scheduleClose(sc, 2000); InputStream in = sc.socket().getInputStream(); - expectThrows(IOException.class, () -> in.read()); + assertThrows(IOException.class, () -> in.read()); }); } /** * Test interrupted status set before read */ + @Test public void testRead6() throws Exception { withConnection((sc, peer) -> { Socket s = sc.socket(); Thread.currentThread().interrupt(); try { InputStream in = s.getInputStream(); - expectThrows(IOException.class, () -> in.read()); + assertThrows(IOException.class, () -> in.read()); } finally { Thread.interrupted(); // clear interrupt } @@ -125,13 +130,14 @@ public void testRead6() throws Exception { /** * Test interrupt of thread blocked in read */ + @Test public void testRead7() throws Exception { withConnection((sc, peer) -> { Future interrupter = scheduleInterrupt(Thread.currentThread(), 2000); Socket s = sc.socket(); try { InputStream in = s.getInputStream(); - expectThrows(IOException.class, () -> in.read()); + assertThrows(IOException.class, () -> in.read()); } finally { interrupter.cancel(true); Thread.interrupted(); // clear interrupt @@ -143,68 +149,74 @@ public void testRead7() throws Exception { /** * Test read when channel is configured non-blocking */ + @Test public void testRead8() throws Exception { withConnection((sc, peer) -> { sc.configureBlocking(false); InputStream in = sc.socket().getInputStream(); - expectThrows(IllegalBlockingModeException.class, () -> in.read()); + assertThrows(IllegalBlockingModeException.class, () -> in.read()); }); } /** * Test timed read when bytes are available */ + @Test public void testTimedRead1() throws Exception { withConnection((sc, peer) -> { peer.getOutputStream().write(99); Socket s = sc.socket(); s.setSoTimeout(60_000); int n = s.getInputStream().read(); - assertEquals(n, 99); + assertEquals(99, n); }); } /** * Test timed read blocking before bytes are available */ + @Test public void testTimedRead2() throws Exception { withConnection((sc, peer) -> { scheduleWrite(peer.getOutputStream(), 99, 1000); Socket s = sc.socket(); s.setSoTimeout(60_000); int n = s.getInputStream().read(); - assertEquals(n, 99); + assertEquals(99, n); }); } /** * Test timed read when the read times out */ + @Test public void testTimedRead3() throws Exception { withConnection((sc, peer) -> { Socket s = sc.socket(); s.setSoTimeout(500); InputStream in = s.getInputStream(); - expectThrows(SocketTimeoutException.class, () -> in.read()); + assertThrows(SocketTimeoutException.class, () -> in.read()); }); } /** * Test async close of socket when thread blocked in timed read */ + @Test public void testTimedRead4() throws Exception { withConnection((sc, peer) -> { scheduleClose(sc, 2000); Socket s = sc.socket(); s.setSoTimeout(60_000); InputStream in = s.getInputStream(); - expectThrows(IOException.class, () -> in.read()); + assertThrows(IOException.class, () -> in.read()); }); } /** * Test interrupted status set before timed read */ + @Test public void testTimedRead5() throws Exception { withConnection((sc, peer) -> { Socket s = sc.socket(); @@ -212,7 +224,7 @@ public void testTimedRead5() throws Exception { try { s.setSoTimeout(60_000); InputStream in = s.getInputStream(); - expectThrows(IOException.class, () -> in.read()); + assertThrows(IOException.class, () -> in.read()); } finally { Thread.interrupted(); // clear interrupt } @@ -223,6 +235,7 @@ public void testTimedRead5() throws Exception { /** * Test interrupt of thread blocked in timed read */ + @Test public void testTimedRead6() throws Exception { withConnection((sc, peer) -> { Future interrupter = scheduleInterrupt(Thread.currentThread(), 2000); @@ -230,7 +243,7 @@ public void testTimedRead6() throws Exception { try { s.setSoTimeout(60_000); InputStream in = s.getInputStream(); - expectThrows(IOException.class, () -> in.read()); + assertThrows(IOException.class, () -> in.read()); assertTrue(s.isClosed()); } finally { interrupter.cancel(true); @@ -243,10 +256,11 @@ public void testTimedRead6() throws Exception { /** * Test async close of socket when thread blocked in write */ + @Test public void testWrite1() throws Exception { withConnection((sc, peer) -> { scheduleClose(sc, 2000); - expectThrows(IOException.class, () -> { + assertThrows(IOException.class, () -> { OutputStream out = sc.socket().getOutputStream(); byte[] data = new byte[64*1000]; while (true) { @@ -259,13 +273,14 @@ public void testWrite1() throws Exception { /** * Test interrupted status set before write */ + @Test public void testWrite2() throws Exception { withConnection((sc, peer) -> { Socket s = sc.socket(); Thread.currentThread().interrupt(); try { OutputStream out = s.getOutputStream(); - expectThrows(IOException.class, () -> out.write(99)); + assertThrows(IOException.class, () -> out.write(99)); } finally { Thread.interrupted(); // clear interrupt } @@ -276,12 +291,13 @@ public void testWrite2() throws Exception { /** * Test interrupt of thread blocked in write */ + @Test public void testWrite3() throws Exception { withConnection((sc, peer) -> { Future interrupter = scheduleInterrupt(Thread.currentThread(), 2000); Socket s = sc.socket(); try { - expectThrows(IOException.class, () -> { + assertThrows(IOException.class, () -> { OutputStream out = sc.socket().getOutputStream(); byte[] data = new byte[64*1000]; while (true) { @@ -299,11 +315,12 @@ public void testWrite3() throws Exception { /** * Test write when channel is configured non-blocking */ + @Test public void testWrite4() throws Exception { withConnection((sc, peer) -> { sc.configureBlocking(false); OutputStream out = sc.socket().getOutputStream(); - expectThrows(IllegalBlockingModeException.class, () -> out.write(99)); + assertThrows(IllegalBlockingModeException.class, () -> out.write(99)); }); } @@ -311,6 +328,7 @@ public void testWrite4() throws Exception { * Test read when there are bytes available and another thread is blocked * in write */ + @Test public void testConcurrentReadWrite1() throws Exception { withConnection((sc, peer) -> { Socket s = sc.socket(); @@ -328,13 +346,14 @@ public void testConcurrentReadWrite1() throws Exception { // test read when bytes are available peer.getOutputStream().write(99); int n = s.getInputStream().read(); - assertEquals(n, 99); + assertEquals(99, n); }); } /** * Test read blocking when another thread is blocked in write */ + @Test public void testConcurrentReadWrite2() throws Exception { withConnection((sc, peer) -> { Socket s = sc.socket(); @@ -352,13 +371,14 @@ public void testConcurrentReadWrite2() throws Exception { // test read blocking until bytes are available scheduleWrite(peer.getOutputStream(), 99, 500); int n = s.getInputStream().read(); - assertEquals(n, 99); + assertEquals(99, n); }); } /** * Test writing when another thread is blocked in read */ + @Test public void testConcurrentReadWrite3() throws Exception { withConnection((sc, peer) -> { Socket s = sc.socket(); @@ -372,7 +392,7 @@ public void testConcurrentReadWrite3() throws Exception { // test write s.getOutputStream().write(99); int n = peer.getInputStream().read(); - assertEquals(n, 99); + assertEquals(99, n); }); } @@ -380,6 +400,7 @@ public void testConcurrentReadWrite3() throws Exception { * Test timed read when there are bytes available and another thread is * blocked in write */ + @Test public void testConcurrentTimedReadWrite1() throws Exception { withConnection((sc, peer) -> { Socket s = sc.socket(); @@ -398,13 +419,14 @@ public void testConcurrentTimedReadWrite1() throws Exception { peer.getOutputStream().write(99); s.setSoTimeout(60_000); int n = s.getInputStream().read(); - assertEquals(n, 99); + assertEquals(99, n); }); } /** * Test timed read blocking when another thread is blocked in write */ + @Test public void testConcurrentTimedReadWrite2() throws Exception { withConnection((sc, peer) -> { Socket s = sc.socket(); @@ -423,13 +445,14 @@ public void testConcurrentTimedReadWrite2() throws Exception { scheduleWrite(peer.getOutputStream(), 99, 500); s.setSoTimeout(60_000); int n = s.getInputStream().read(); - assertEquals(n, 99); + assertEquals(99, n); }); } /** * Test writing when another thread is blocked in read */ + @Test public void testConcurrentTimedReadWrite3() throws Exception { withConnection((sc, peer) -> { Socket s = sc.socket(); @@ -444,7 +467,7 @@ public void testConcurrentTimedReadWrite3() throws Exception { // test write s.getOutputStream().write(99); int n = peer.getInputStream().read(); - assertEquals(n, 99); + assertEquals(99, n); }); } diff --git a/test/jdk/java/nio/channels/SocketChannel/ConnectionReset.java b/test/jdk/java/nio/channels/SocketChannel/ConnectionReset.java index 759d819fa4f..2d89d708110 100644 --- a/test/jdk/java/nio/channels/SocketChannel/ConnectionReset.java +++ b/test/jdk/java/nio/channels/SocketChannel/ConnectionReset.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,9 +21,9 @@ * questions. */ -/** +/* * @test - * @run testng ConnectionReset + * @run junit ConnectionReset * @summary Test behavior of SocketChannel.read and the Socket adaptor read * and available methods when a connection is reset */ @@ -36,12 +36,10 @@ import java.net.Socket; import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; -import java.lang.reflect.Method; -import org.testng.annotations.Test; -import static org.testng.Assert.*; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; -@Test public class ConnectionReset { static final int REPEAT_COUNT = 5; @@ -50,6 +48,7 @@ public class ConnectionReset { * Tests SocketChannel.read when the connection is reset and there are no * bytes to read. */ + @Test public void testSocketChannelReadNoData() throws IOException { System.out.println("testSocketChannelReadNoData"); withResetConnection(null, sc -> { @@ -69,6 +68,7 @@ public void testSocketChannelReadNoData() throws IOException { * Tests SocketChannel.read when the connection is reset and there are bytes * to read. */ + @Test public void testSocketChannelReadData() throws IOException { System.out.println("testSocketChannelReadData"); byte[] data = { 1, 2, 3 }; @@ -99,6 +99,7 @@ public void testSocketChannelReadData() throws IOException { * Tests available before Socket read when the connection is reset and there * are no bytes to read. */ + @Test public void testAvailableBeforeSocketReadNoData() throws IOException { System.out.println("testAvailableBeforeSocketReadNoData"); withResetConnection(null, sc -> { @@ -107,7 +108,7 @@ public void testAvailableBeforeSocketReadNoData() throws IOException { for (int i=0; i %d%n", bytesAvailable); - assertTrue(bytesAvailable == 0); + assertEquals(0, bytesAvailable); try { int bytesRead = in.read(); if (bytesRead == -1) { @@ -127,6 +128,7 @@ public void testAvailableBeforeSocketReadNoData() throws IOException { * Tests available before Socket read when the connection is reset and there * are bytes to read. */ + @Test public void testAvailableBeforeSocketReadData() throws IOException { System.out.println("testAvailableBeforeSocketReadData"); byte[] data = { 1, 2, 3 }; @@ -160,6 +162,7 @@ public void testAvailableBeforeSocketReadData() throws IOException { * Tests Socket read before available when the connection is reset and there * are no bytes to read. */ + @Test public void testSocketReadNoDataBeforeAvailable() throws IOException { System.out.println("testSocketReadNoDataBeforeAvailable"); withResetConnection(null, sc -> { @@ -179,7 +182,7 @@ public void testSocketReadNoDataBeforeAvailable() throws IOException { } int bytesAvailable = in.available(); System.out.format("available => %d%n", bytesAvailable); - assertTrue(bytesAvailable == 0); + assertEquals(0, bytesAvailable); } }); } @@ -188,6 +191,7 @@ public void testSocketReadNoDataBeforeAvailable() throws IOException { * Tests Socket read before available when the connection is reset and there * are bytes to read. */ + @Test public void testSocketReadDataBeforeAvailable() throws IOException { System.out.println("testSocketReadDataBeforeAvailable"); byte[] data = { 1, 2, 3 }; diff --git a/test/jdk/java/nio/channels/SocketChannel/ReadWriteAfterClose.java b/test/jdk/java/nio/channels/SocketChannel/ReadWriteAfterClose.java index 037e750a552..0af09df4949 100644 --- a/test/jdk/java/nio/channels/SocketChannel/ReadWriteAfterClose.java +++ b/test/jdk/java/nio/channels/SocketChannel/ReadWriteAfterClose.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,9 +21,6 @@ * questions. */ -import org.testng.annotations.AfterTest; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.Test; import java.io.IOException; import java.net.InetAddress; @@ -34,38 +31,45 @@ import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; -import static org.testng.Assert.*; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; /* * @test * @bug 8246707 - * @library /test/lib * @summary Reading or Writing to a closed SocketChannel should throw a ClosedChannelException - * @run testng/othervm ReadWriteAfterClose + * @run junit/othervm ReadWriteAfterClose */ public class ReadWriteAfterClose { - private ServerSocketChannel listener; - private SocketAddress saddr; + private static ServerSocketChannel listener; + private static SocketAddress saddr; private static final int bufCapacity = 4; private static final int bufArraySize = 4; private static final Class CCE = ClosedChannelException.class; - @BeforeTest - public void setUp() throws IOException { + @BeforeAll + public static void setUp() throws IOException { listener = ServerSocketChannel.open(); listener.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); saddr = listener.getLocalAddress(); } + @AfterAll + public static void tearDown() throws IOException { + if (listener != null) listener.close(); + } + @Test public void testWriteAfterClose1() throws IOException { SocketChannel sc = SocketChannel.open(saddr); sc.close(); ByteBuffer bufWrite = ByteBuffer.allocate(bufCapacity); - Throwable ex = expectThrows(CCE, () -> sc.write(bufWrite)); - assertEquals(ex.getClass(), CCE); + Throwable ex = assertThrows(CCE, () -> sc.write(bufWrite)); + assertSame(CCE, ex.getClass()); } @Test @@ -73,8 +77,8 @@ public void testWriteAfterClose2() throws IOException { SocketChannel sc = SocketChannel.open(saddr); sc.close(); ByteBuffer[] bufArrayWrite = allocateBufArray(); - Throwable ex = expectThrows(CCE, () -> sc.write(bufArrayWrite)); - assertEquals(ex.getClass(), CCE); + Throwable ex = assertThrows(CCE, () -> sc.write(bufArrayWrite)); + assertSame(CCE, ex.getClass()); } @Test @@ -82,8 +86,8 @@ public void testWriteAfterClose3() throws IOException { SocketChannel sc = SocketChannel.open(saddr); sc.close(); ByteBuffer[] bufArrayWrite = allocateBufArray(); - Throwable ex = expectThrows(CCE, () -> sc.write(bufArrayWrite, 0, bufArraySize)); - assertEquals(ex.getClass(), CCE); + Throwable ex = assertThrows(CCE, () -> sc.write(bufArrayWrite, 0, bufArraySize)); + assertSame(CCE, ex.getClass()); } @Test @@ -91,8 +95,8 @@ public void testReadAfterClose1() throws IOException { SocketChannel sc = SocketChannel.open(saddr); sc.close(); ByteBuffer dst = ByteBuffer.allocate(bufCapacity); - Throwable ex = expectThrows(CCE, () -> sc.read(dst)); - assertEquals(ex.getClass(), CCE); + Throwable ex = assertThrows(CCE, () -> sc.read(dst)); + assertSame(CCE, ex.getClass()); } @Test @@ -100,8 +104,8 @@ public void testReadAfterClose2() throws IOException { SocketChannel sc = SocketChannel.open(saddr); sc.close(); ByteBuffer[] dstArray = allocateBufArray(); - Throwable ex = expectThrows(CCE, () -> sc.read(dstArray)); - assertEquals(ex.getClass(), CCE); + Throwable ex = assertThrows(CCE, () -> sc.read(dstArray)); + assertSame(CCE, ex.getClass()); } @Test @@ -109,8 +113,8 @@ public void testReadAfterClose3() throws IOException { SocketChannel sc = SocketChannel.open(saddr); sc.close(); ByteBuffer[] dstArray = allocateBufArray(); - Throwable ex = expectThrows(CCE, () -> sc.read(dstArray, 0, bufArraySize)); - assertEquals(ex.getClass(), CCE); + Throwable ex = assertThrows(CCE, () -> sc.read(dstArray, 0, bufArraySize)); + assertSame(CCE, ex.getClass()); } public ByteBuffer[] allocateBufArray() { @@ -120,8 +124,4 @@ public ByteBuffer[] allocateBufArray() { return bufArr; } - @AfterTest - public void tearDown() throws IOException { - listener.close(); - } } \ No newline at end of file diff --git a/test/jdk/java/nio/channels/etc/LocalSocketAddressType.java b/test/jdk/java/nio/channels/etc/LocalSocketAddressType.java index 63be790c478..60e41af6288 100644 --- a/test/jdk/java/nio/channels/etc/LocalSocketAddressType.java +++ b/test/jdk/java/nio/channels/etc/LocalSocketAddressType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,40 +26,44 @@ * @summary Test local address type * @library /test/lib * @build jdk.test.lib.NetworkConfiguration - * @run testng/othervm LocalSocketAddressType - * @run testng/othervm -Djava.net.preferIPv4Stack=true LocalSocketAddressType + * @run junit/othervm LocalSocketAddressType + * @run junit/othervm -Djava.net.preferIPv4Stack=true LocalSocketAddressType */ import jdk.test.lib.NetworkConfiguration; import jdk.test.lib.net.IPSupport; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; -import java.net.*; +import java.net.InetAddress; +import java.net.InetSocketAddress; import java.nio.channels.DatagramChannel; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.util.Iterator; -import java.util.stream.Collectors; import java.util.stream.Stream; -import static java.lang.Boolean.parseBoolean; -import static java.lang.System.getProperty; import static java.lang.System.out; -import static jdk.test.lib.Asserts.assertEquals; -import static jdk.test.lib.Asserts.assertTrue; import static jdk.test.lib.net.IPSupport.*; +import jtreg.SkippedException; +import org.junit.jupiter.api.Assumptions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import static org.junit.jupiter.api.Assertions.assertEquals; + public class LocalSocketAddressType { - @BeforeTest() - public void setup() { + @BeforeAll() + public static void setup() { IPSupport.printPlatformSupport(out); - throwSkippedExceptionIfNonOperational(); + try { + throwSkippedExceptionIfNonOperational(); + } catch (SkippedException skippedException) { + // jtreg.SkippedException would cause a JUnit test to fail + Assumptions.assumeTrue(false, skippedException.getMessage()); + } } - @DataProvider(name = "addresses") public static Iterator addresses() throws Exception { NetworkConfiguration nc = NetworkConfiguration.probe(); return Stream.concat(nc.ip4Addresses(), nc.ip6Addresses()) @@ -67,36 +71,39 @@ public static Iterator addresses() throws Exception { .iterator(); } - @Test(dataProvider = "addresses") - public static void testSocketChannel(InetSocketAddress addr) throws Exception { + @ParameterizedTest + @MethodSource("addresses") + public void testSocketChannel(InetSocketAddress addr) throws Exception { try (var c = SocketChannel.open()) { Class cls = addr.getAddress().getClass(); InetAddress ia = ((InetSocketAddress)c.bind(addr).getLocalAddress()).getAddress(); - assertEquals(ia.getClass(), cls); + assertEquals(cls, ia.getClass()); ia = c.socket().getLocalAddress(); - assertEquals(ia.getClass(), cls); + assertEquals(cls, ia.getClass()); } } - @Test(dataProvider = "addresses") - public static void testServerSocketChannel(InetSocketAddress addr) throws Exception { + @ParameterizedTest + @MethodSource("addresses") + public void testServerSocketChannel(InetSocketAddress addr) throws Exception { try (var c = ServerSocketChannel.open()) { Class cls = addr.getAddress().getClass(); InetAddress ia = ((InetSocketAddress)c.bind(addr).getLocalAddress()).getAddress(); - assertEquals(ia.getClass(), cls); + assertEquals(cls, ia.getClass()); ia = c.socket().getInetAddress(); - assertEquals(ia.getClass(), cls); + assertEquals(cls, ia.getClass()); } } - @Test(dataProvider = "addresses") - public static void testDatagramChannel(InetSocketAddress addr) throws Exception { + @ParameterizedTest + @MethodSource("addresses") + public void testDatagramChannel(InetSocketAddress addr) throws Exception { try (var c = DatagramChannel.open()) { Class cls = addr.getAddress().getClass(); InetAddress ia = ((InetSocketAddress)c.bind(addr).getLocalAddress()).getAddress(); - assertEquals(ia.getClass(), cls); + assertEquals(cls, ia.getClass()); ia = c.socket().getLocalAddress(); - assertEquals(ia.getClass(), cls); + assertEquals(cls, ia.getClass()); } } } diff --git a/test/jdk/java/nio/channels/etc/OpenAndConnect.java b/test/jdk/java/nio/channels/etc/OpenAndConnect.java index b183076e49d..0e0347ebb57 100644 --- a/test/jdk/java/nio/channels/etc/OpenAndConnect.java +++ b/test/jdk/java/nio/channels/etc/OpenAndConnect.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,23 +23,32 @@ import jdk.test.lib.NetworkConfiguration; import jdk.test.lib.net.IPSupport; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import java.io.IOException; -import java.net.*; -import java.nio.channels.*; -import java.util.Arrays; +import java.net.Inet4Address; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.ProtocolFamily; +import java.net.SocketAddress; +import java.nio.channels.DatagramChannel; +import java.nio.channels.ServerSocketChannel; +import java.nio.channels.SocketChannel; import java.util.List; import java.util.LinkedList; -import static java.lang.System.getProperty; import static java.lang.System.out; import static java.net.StandardProtocolFamily.INET; import static java.net.StandardProtocolFamily.INET6; import static jdk.test.lib.net.IPSupport.*; +import jtreg.SkippedException; +import org.junit.jupiter.api.Assumptions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + /* * @test * @summary Test SocketChannel, ServerSocketChannel and DatagramChannel @@ -48,10 +57,9 @@ * addresses (Inet4Address, Inet6Address). * @library /test/lib * @build jdk.test.lib.NetworkConfiguration - * @run testng/othervm OpenAndConnect + * @run junit/othervm OpenAndConnect */ - public class OpenAndConnect { static final Inet4Address IA4ANYLOCAL; static final Inet6Address IA6ANYLOCAL; @@ -77,11 +85,16 @@ public class OpenAndConnect { } } - @BeforeTest() - public void setup() { + @BeforeAll() + public static void setup() { NetworkConfiguration.printSystemConfiguration(out); IPSupport.printPlatformSupport(out); - throwSkippedExceptionIfNonOperational(); + try { + throwSkippedExceptionIfNonOperational(); + } catch (SkippedException skippedException) { + // jtreg.SkippedException would cause a JUnit test to fail + Assumptions.assumeTrue(false, skippedException.getMessage()); + } out.println("IA4LOCAL: " + IA4LOCAL); out.println("IA6LOCAL: " + IA6LOCAL); @@ -91,9 +104,8 @@ public void setup() { out.println("IA6LOOPBACK: " + IA6LOOPBACK); } - @DataProvider(name = "openConnect") - public Object[][] openConnect() { - LinkedList l = new LinkedList<>(); + public static List openConnect() { + LinkedList l = new LinkedList<>(); if (IPSupport.hasIPv4()) { l.addAll(openConnectV4Tests); if (IA4LOCAL != null) { @@ -112,7 +124,7 @@ public Object[][] openConnect() { l.addAll(openConnectV4LocalAndV6Tests); } } - return l.toArray(new Object[][]{}); + return l; } // +----- sfam is server/first socket family @@ -127,92 +139,91 @@ public Object[][] openConnect() { // | | | | this is address used for connect // | | | | also. // | | | | - // | | | | - // | | | | - // | | | | - // + + + + - // { sfam, saddr, cfam, caddr, } + // | | | +---------------+ + // | | | | + // | | +---------------+ | + // | | | | + // | +---------------+ | | + // | | | | + // +---------------+ | | | + // | | | | + // + + + + + // Arguments.of( sfam, saddr, cfam, caddr, ) // Basic tests for when an IPv4 is available - public static List openConnectV4Tests = - Arrays.asList(new Object[][] { - { INET, IA4LOOPBACK, INET, IA4LOOPBACK }, - { INET, IA4LOOPBACK, null, IA4LOOPBACK }, - { INET, IA4ANYLOCAL, null, IA4LOOPBACK }, - { INET, IA4ANYLOCAL, INET, IA4LOOPBACK }, - { null, IA4LOOPBACK, INET, IA4ANYLOCAL }, - { null, IA4LOOPBACK, INET, IA4LOOPBACK }, - { null, IA4LOOPBACK, INET, null }, - { null, IA4LOOPBACK, null, null } - }); + public static List openConnectV4Tests = + List.of(Arguments.of( INET, IA4LOOPBACK, INET, IA4LOOPBACK ), + Arguments.of( INET, IA4LOOPBACK, null, IA4LOOPBACK ), + Arguments.of( INET, IA4ANYLOCAL, null, IA4LOOPBACK ), + Arguments.of( INET, IA4ANYLOCAL, INET, IA4LOOPBACK ), + Arguments.of( null, IA4LOOPBACK, INET, IA4ANYLOCAL ), + Arguments.of( null, IA4LOOPBACK, INET, IA4LOOPBACK ), + Arguments.of( null, IA4LOOPBACK, INET, null ), + Arguments.of( null, IA4LOOPBACK, null, null ) + ); // Additional tests for when an IPv4 local address is available - public List openConnectV4LocalTests = - Arrays.asList(new Object[][] { - { INET, IA4LOCAL, INET, IA4LOCAL }, - { INET, IA4LOCAL, null, IA4LOCAL }, - { INET, IA4LOCAL, null, DONT_BIND }, - { INET, IA4ANYLOCAL, INET, IA4LOCAL }, - { INET, IA4ANYLOCAL, null, IA4LOCAL }, - { null, IA4LOCAL, INET, IA4ANYLOCAL }, - { null, IA4LOCAL, INET, IA4LOCAL }, - { null, IA4LOCAL, INET, null }, - { null, IA4LOCAL, null, null } - }); + public static List openConnectV4LocalTests = + List.of(Arguments.of( INET, IA4LOCAL, INET, IA4LOCAL ), + Arguments.of( INET, IA4LOCAL, null, IA4LOCAL ), + Arguments.of( INET, IA4LOCAL, null, DONT_BIND ), + Arguments.of( INET, IA4ANYLOCAL, INET, IA4LOCAL ), + Arguments.of( INET, IA4ANYLOCAL, null, IA4LOCAL ), + Arguments.of( null, IA4LOCAL, INET, IA4ANYLOCAL ), + Arguments.of( null, IA4LOCAL, INET, IA4LOCAL ), + Arguments.of( null, IA4LOCAL, INET, null ), + Arguments.of( null, IA4LOCAL, null, null ) + ); // Basic tests for when an IPv6 is available - public List openConnectV6Tests = - Arrays.asList(new Object[][] { - { INET6, IA6ANYLOCAL, null, IA6LOOPBACK }, - { INET6, IA6ANYLOCAL, INET6, IA6LOOPBACK }, - { INET6, IA6LOOPBACK, INET6, IA6LOOPBACK }, - { INET6, IA6LOOPBACK, INET6, IA6LOOPBACK }, - { null, IA6ANYLOCAL, null, IA6LOOPBACK }, - { null, IA6ANYLOCAL, INET6, IA6LOOPBACK }, - { null, IA6LOOPBACK, INET6, IA6LOOPBACK }, - { null, IA6LOOPBACK, INET6, DONT_BIND }, - { null, IA6LOOPBACK, INET6, null }, - { null, IA6LOOPBACK, null, IA6LOOPBACK }, - { null, IA6LOOPBACK, null, null }, - { null, IA6LOOPBACK, INET6, IA6ANYLOCAL }, - { null, IA6LOOPBACK, null, IA6ANYLOCAL } - }); + public static List openConnectV6Tests = + List.of(Arguments.of( INET6, IA6ANYLOCAL, null, IA6LOOPBACK ), + Arguments.of( INET6, IA6ANYLOCAL, INET6, IA6LOOPBACK ), + Arguments.of( INET6, IA6LOOPBACK, INET6, IA6LOOPBACK ), + Arguments.of( INET6, IA6LOOPBACK, INET6, IA6LOOPBACK ), + Arguments.of( null, IA6ANYLOCAL, null, IA6LOOPBACK ), + Arguments.of( null, IA6ANYLOCAL, INET6, IA6LOOPBACK ), + Arguments.of( null, IA6LOOPBACK, INET6, IA6LOOPBACK ), + Arguments.of( null, IA6LOOPBACK, INET6, DONT_BIND ), + Arguments.of( null, IA6LOOPBACK, INET6, null ), + Arguments.of( null, IA6LOOPBACK, null, IA6LOOPBACK ), + Arguments.of( null, IA6LOOPBACK, null, null ), + Arguments.of( null, IA6LOOPBACK, INET6, IA6ANYLOCAL ), + Arguments.of( null, IA6LOOPBACK, null, IA6ANYLOCAL ) + ); // Additional tests for when an IPv6 local address is available - public List openConnectV6LocalTests = - Arrays.asList(new Object[][] { - { INET6, IA6ANYLOCAL, null, IA6LOCAL }, - { INET6, IA6ANYLOCAL, INET6, IA6LOCAL }, - { INET6, IA6LOCAL, INET6, IA6LOCAL }, - { INET6, IA6LOCAL, null, IA6LOCAL }, - { INET6, IA6LOCAL, null, DONT_BIND }, - { INET6, IA6LOCAL, INET6, IA6LOCAL }, - { null, IA6ANYLOCAL, null, IA6LOCAL }, - { null, IA6ANYLOCAL, INET6, IA6LOCAL }, - { null, IA6LOCAL, INET6, IA6LOCAL }, - { null, IA6LOCAL, INET6, IA6ANYLOCAL }, - { null, IA6LOCAL, null, IA6ANYLOCAL }, - { null, IA6LOCAL, null, IA6LOCAL }, - { null, IA6LOCAL, INET6, null }, - { null, IA6LOCAL, null, null } - }); + public static List openConnectV6LocalTests = + List.of(Arguments.of( INET6, IA6ANYLOCAL, null, IA6LOCAL ), + Arguments.of( INET6, IA6ANYLOCAL, INET6, IA6LOCAL ), + Arguments.of( INET6, IA6LOCAL, INET6, IA6LOCAL ), + Arguments.of( INET6, IA6LOCAL, null, IA6LOCAL ), + Arguments.of( INET6, IA6LOCAL, null, DONT_BIND ), + Arguments.of( INET6, IA6LOCAL, INET6, IA6LOCAL ), + Arguments.of( null, IA6ANYLOCAL, null, IA6LOCAL ), + Arguments.of( null, IA6ANYLOCAL, INET6, IA6LOCAL ), + Arguments.of( null, IA6LOCAL, INET6, IA6LOCAL ), + Arguments.of( null, IA6LOCAL, INET6, IA6ANYLOCAL ), + Arguments.of( null, IA6LOCAL, null, IA6ANYLOCAL ), + Arguments.of( null, IA6LOCAL, null, IA6LOCAL ), + Arguments.of( null, IA6LOCAL, INET6, null ), + Arguments.of( null, IA6LOCAL, null, null ) + ); // Additional tests for when IPv4 and IPv6 are available - public List openConnectV4AndV6Tests = - Arrays.asList(new Object[][] { - { null, IA4LOOPBACK, INET6, IA6ANYLOCAL }, - { null, IA4LOOPBACK, null, IA6ANYLOCAL }, - { null, IA4LOOPBACK, INET6, DONT_BIND }, - { null, IA4LOOPBACK, INET6, null } - }); + public static List openConnectV4AndV6Tests = + List.of(Arguments.of( null, IA4LOOPBACK, INET6, IA6ANYLOCAL ), + Arguments.of( null, IA4LOOPBACK, null, IA6ANYLOCAL ), + Arguments.of( null, IA4LOOPBACK, INET6, DONT_BIND ), + Arguments.of( null, IA4LOOPBACK, INET6, null ) + ); // Additional tests for when IPv4 local address and IPv6 are available - public List openConnectV4LocalAndV6Tests = - Arrays.asList(new Object[][] { - { null, IA4LOCAL, INET6, IA6ANYLOCAL }, - { null, IA4LOCAL, INET6, null }, - { null, IA4LOCAL, null, IA6ANYLOCAL } - }); + public static List openConnectV4LocalAndV6Tests = + List.of(Arguments.of( null, IA4LOCAL, INET6, IA6ANYLOCAL ), + Arguments.of( null, IA4LOCAL, INET6, null ), + Arguments.of( null, IA4LOCAL, null, IA6ANYLOCAL ) + ); /** * If the destination address is the wildcard, it is replaced by the alternate @@ -227,7 +238,8 @@ static InetSocketAddress getDestinationAddress(SocketAddress destination, InetAd return isa; } - @Test(dataProvider = "openConnect") + @ParameterizedTest + @MethodSource("openConnect") public void scOpenAndConnect(ProtocolFamily sfam, InetAddress saddr, ProtocolFamily cfam, @@ -248,7 +260,8 @@ public void scOpenAndConnect(ProtocolFamily sfam, } } - @Test(dataProvider = "openConnect") + @ParameterizedTest + @MethodSource("openConnect") public void dcOpenAndConnect(ProtocolFamily sfam, InetAddress saddr, ProtocolFamily cfam, diff --git a/test/jdk/java/nio/channels/etc/ProtocolFamilies.java b/test/jdk/java/nio/channels/etc/ProtocolFamilies.java index 45226e9a97e..7f823ff35a8 100644 --- a/test/jdk/java/nio/channels/etc/ProtocolFamilies.java +++ b/test/jdk/java/nio/channels/etc/ProtocolFamilies.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,20 +23,38 @@ import jdk.test.lib.NetworkConfiguration; import jdk.test.lib.net.IPSupport; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; -import org.testng.Assert.ThrowingRunnable; + import java.io.IOException; -import java.net.*; -import java.nio.channels.*; +import java.net.Inet4Address; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.ProtocolFamily; +import java.net.SocketAddress; +import java.net.StandardProtocolFamily; +import java.net.UnknownHostException; +import java.nio.channels.DatagramChannel; +import java.nio.channels.ServerSocketChannel; +import java.nio.channels.SocketChannel; +import java.nio.channels.UnsupportedAddressTypeException; import java.nio.channels.spi.SelectorProvider; +import java.util.List; + import static java.lang.System.out; import static java.net.StandardProtocolFamily.INET; import static java.net.StandardProtocolFamily.INET6; import static jdk.test.lib.net.IPSupport.*; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertThrows; + +import jtreg.SkippedException; +import org.junit.jupiter.api.Assumptions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.function.Executable; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import static org.junit.jupiter.api.Assertions.assertThrows; /* * @test @@ -44,8 +62,8 @@ * with various ProtocolFamily combinations * @library /test/lib * @build jdk.test.lib.NetworkConfiguration - * @run testng ProtocolFamilies - * @run testng/othervm -Djava.net.preferIPv4Stack=true ProtocolFamilies + * @run junit ProtocolFamilies + * @run junit/othervm -Djava.net.preferIPv4Stack=true ProtocolFamilies */ @@ -55,11 +73,16 @@ public class ProtocolFamilies { static Inet4Address ia4; static Inet6Address ia6; - @BeforeTest() - public void setup() throws Exception { + @BeforeAll() + public static void setup() throws Exception { NetworkConfiguration.printSystemConfiguration(out); IPSupport.printPlatformSupport(out); - throwSkippedExceptionIfNonOperational(); + try { + throwSkippedExceptionIfNonOperational(); + } catch (SkippedException skippedException) { + // jtreg.SkippedException would cause a JUnit test to fail + Assumptions.assumeTrue(false, skippedException.getMessage()); + } ia4 = getLocalIPv4Address(); ia6 = getLocalIPv6Address(); @@ -70,111 +93,89 @@ public void setup() throws Exception { static final Class UATE = UnsupportedAddressTypeException.class; static final Class UOE = UnsupportedOperationException.class; - @DataProvider(name = "open") - public Object[][] open() { + public static List open() { if (hasIPv6 && !preferIPv4) { - return new Object[][]{ - { INET, null }, - { INET6, null } - }; + return List.of( + Arguments.of( INET, null ), + Arguments.of( INET6, null ) + ); } else { - return new Object[][]{ - { INET, null }, - { INET6, UOE } - }; + return List.of( + Arguments.of( INET, null ), + Arguments.of( INET6, UOE ) + ); } } - @Test(dataProvider = "open") + @ParameterizedTest + @MethodSource("open") public void scOpen(StandardProtocolFamily family, Class expectedException) - throws Throwable + throws IOException { - SocketChannel sc = null; - try { - if (expectedException == UOE) { - try { - sc = openSC(family); - } catch (UnsupportedOperationException e) {} - } else { - sc = openSC(family); - } - } finally { - if (sc != null) - sc.close(); + if (expectedException != null) { + assertThrows(expectedException, () -> openSC(family)); + } else { + try (var _ = openSC(family)) { } } } - @Test(dataProvider = "open") + @ParameterizedTest + @MethodSource("open") public void sscOpen(StandardProtocolFamily family, Class expectedException) - throws Throwable + throws IOException { - ServerSocketChannel ssc = null; - try { - if (expectedException == UOE) { - try { - ssc = openSSC(family); - } catch (UnsupportedOperationException e) {} - } else { - openSSC(family); - } - } finally { - if (ssc != null) - ssc.close(); + if (expectedException != null) { + assertThrows(expectedException, () -> openSSC(family)); + } else { + try (var _ = openSSC(family)) { } } } - @Test(dataProvider = "open") + @ParameterizedTest + @MethodSource("open") public void dcOpen(StandardProtocolFamily family, Class expectedException) - throws Throwable + throws IOException { - DatagramChannel dc = null; - try { - if (expectedException == UOE) { - try { - dc = openDC(family); - } catch (UnsupportedOperationException e) {} - } else { - openDC(family); - } - } finally { - if (dc != null) - dc.close(); + if (expectedException != null) { + assertThrows(expectedException, () -> openDC(family)); + } else { + try (var _ = openDC(family)) { } } } - @DataProvider(name = "openBind") - public Object[][] openBind() { + public static List openBind() { if (hasIPv6 && !preferIPv4) { - return new Object[][]{ - { INET, INET, null }, - { INET, INET6, UATE }, - { INET, null, null }, - { INET6, INET, null }, - { INET6, INET6, null }, - { INET6, null, null }, - { null, INET, null }, - { null, INET6, null }, - { null, null, null } - }; + return List.of( + Arguments.of( INET, INET, null ), + Arguments.of( INET, INET6, UATE ), + Arguments.of( INET, null, null ), + Arguments.of( INET6, INET, null ), + Arguments.of( INET6, INET6, null ), + Arguments.of( INET6, null, null ), + Arguments.of( null, INET, null ), + Arguments.of( null, INET6, null ), + Arguments.of( null, null, null ) + ); } else { - return new Object[][]{ - { INET, INET, null }, - { INET, INET6, UATE }, - { INET, null, null }, - { null, INET, null }, - { null, INET6, UATE }, - { null, null, null } - }; + return List.of( + Arguments.of( INET, INET, null ), + Arguments.of( INET, INET6, UATE ), + Arguments.of( INET, null, null ), + Arguments.of( null, INET, null ), + Arguments.of( null, INET6, UATE ), + Arguments.of( null, null, null ) + ); } } // SocketChannel open - INET, INET6, default // SocketChannel bind - INET, INET6, null - @Test(dataProvider = "openBind") + @ParameterizedTest + @MethodSource("openBind") public void scOpenBind(StandardProtocolFamily ofamily, StandardProtocolFamily bfamily, Class expectedException) @@ -182,9 +183,9 @@ public void scOpenBind(StandardProtocolFamily ofamily, { try (SocketChannel sc = openSC(ofamily)) { SocketAddress addr = getSocketAddress(bfamily); - ThrowingRunnable bindOp = () -> sc.bind(addr); - if (expectedException == null) - bindOp.run(); + Executable bindOp = () -> sc.bind(addr); + if (expectedException == null) + bindOp.execute(); else assertThrows(expectedException, bindOp); } @@ -193,7 +194,8 @@ public void scOpenBind(StandardProtocolFamily ofamily, // ServerSocketChannel open - INET, INET6, default // ServerSocketChannel bind - INET, INET6, null - @Test(dataProvider = "openBind") + @ParameterizedTest + @MethodSource("openBind") public void sscOpenBind(StandardProtocolFamily ofamily, StandardProtocolFamily bfamily, Class expectedException) @@ -201,9 +203,9 @@ public void sscOpenBind(StandardProtocolFamily ofamily, { try (ServerSocketChannel ssc = openSSC(ofamily)) { SocketAddress addr = getSocketAddress(bfamily); - ThrowingRunnable bindOp = () -> ssc.bind(addr); + Executable bindOp = () -> ssc.bind(addr); if (expectedException == null) - bindOp.run(); + bindOp.execute(); else assertThrows(expectedException, bindOp); } @@ -212,7 +214,8 @@ public void sscOpenBind(StandardProtocolFamily ofamily, // DatagramChannel open - INET, INET6, default // DatagramChannel bind - INET, INET6, null - @Test(dataProvider = "openBind") + @ParameterizedTest + @MethodSource("openBind") public void dcOpenBind(StandardProtocolFamily ofamily, StandardProtocolFamily bfamily, Class expectedException) @@ -220,9 +223,9 @@ public void dcOpenBind(StandardProtocolFamily ofamily, { try (DatagramChannel dc = openDC(ofamily)) { SocketAddress addr = getSocketAddress(bfamily); - ThrowingRunnable bindOp = () -> dc.bind(addr); + Executable bindOp = () -> dc.bind(addr); if (expectedException == null) - bindOp.run(); + bindOp.execute(); else assertThrows(expectedException, bindOp); } @@ -231,32 +234,32 @@ public void dcOpenBind(StandardProtocolFamily ofamily, // SocketChannel open - INET, INET6, default // SocketChannel connect - INET, INET6, default - @DataProvider(name = "openConnect") - public Object[][] openConnect() { + public static List openConnect() { if (hasIPv6 && !preferIPv4) { - return new Object[][]{ - { INET, INET, null }, - { INET, INET6, null }, - { INET, null, null }, - { INET6, INET, UATE }, - { INET6, INET6, null }, - { INET6, null, null }, - { null, INET, UATE }, - { null, INET6, null }, - { null, null, null } - }; + return List.of( + Arguments.of( INET, INET, null ), + Arguments.of( INET, INET6, null ), + Arguments.of( INET, null, null ), + Arguments.of( INET6, INET, UATE ), + Arguments.of( INET6, INET6, null ), + Arguments.of( INET6, null, null ), + Arguments.of( null, INET, UATE ), + Arguments.of( null, INET6, null ), + Arguments.of( null, null, null ) + ); } else { // INET6 channels cannot be created - UOE - tested elsewhere - return new Object[][]{ - { INET, INET, null }, - { INET, null, null }, - { null, INET, null }, - { null, null, null } - }; + return List.of( + Arguments.of( INET, INET, null ), + Arguments.of( INET, null, null ), + Arguments.of( null, INET, null ), + Arguments.of( null, null, null ) + ); } } - @Test(dataProvider = "openConnect") + @ParameterizedTest + @MethodSource("openConnect") public void scOpenConnect(StandardProtocolFamily sfamily, StandardProtocolFamily cfamily, Class expectedException) @@ -279,7 +282,7 @@ public void scOpenConnect(StandardProtocolFamily sfamily, // Tests null handling @Test public void testNulls() { - assertThrows(NPE, () -> SocketChannel.open((ProtocolFamily)null)); + assertThrows(NPE, () -> SocketChannel.open((ProtocolFamily) null)); assertThrows(NPE, () -> ServerSocketChannel.open(null)); assertThrows(NPE, () -> DatagramChannel.open(null)); diff --git a/test/jdk/java/nio/channels/unixdomain/EmptySunPathForSocketFile.java b/test/jdk/java/nio/channels/unixdomain/EmptySunPathForSocketFile.java index 79f8ead7aa2..ec47babdff3 100644 --- a/test/jdk/java/nio/channels/unixdomain/EmptySunPathForSocketFile.java +++ b/test/jdk/java/nio/channels/unixdomain/EmptySunPathForSocketFile.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,11 +21,11 @@ * questions. */ -/** +/* * @test * @bug 8256461 * @modules java.base/sun.nio.fs - * @run testng EmptySunPathForSocketFile + * @run junit EmptySunPathForSocketFile */ import java.nio.file.FileSystems; @@ -33,7 +33,8 @@ import java.nio.file.spi.FileSystemProvider; import sun.nio.fs.AbstractFileSystemProvider; -import static org.testng.Assert.assertEquals; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; /** * Check that AbstractFileSystemProvider.getSunPathForSocketFile with @@ -41,9 +42,14 @@ */ public class EmptySunPathForSocketFile { public static void main(String[] args) throws Exception { + new EmptySunPathForSocketFile().test(); + } + + @Test + public void test() { Path path = Path.of(""); FileSystemProvider provider = FileSystems.getDefault().provider(); byte[] bb = ((AbstractFileSystemProvider) provider).getSunPathForSocketFile(path); - assertEquals(bb, new byte[0]); + assertArrayEquals(new byte[0], bb); } } diff --git a/test/jdk/java/nio/channels/unixdomain/FileAttributes.java b/test/jdk/java/nio/channels/unixdomain/FileAttributes.java index 3ff92a6bc05..5e9b65f90b2 100644 --- a/test/jdk/java/nio/channels/unixdomain/FileAttributes.java +++ b/test/jdk/java/nio/channels/unixdomain/FileAttributes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,35 +21,34 @@ * questions. */ -/** +/* * @test * @bug 8252971 - * @library /test/lib - * @run testng FileAttributes + * @run junit FileAttributes */ import java.io.IOException; import java.io.File; -import java.net.*; -import java.nio.channels.*; +import java.net.UnixDomainSocketAddress; +import java.nio.channels.SocketChannel; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.attribute.BasicFileAttributes; -import java.util.Arrays; -import org.testng.annotations.Test; -import org.testng.SkipException; import static java.net.StandardProtocolFamily.UNIX; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertThrows; -import static org.testng.Assert.assertTrue; + +import org.junit.jupiter.api.Assumptions; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; /** */ public class FileAttributes { @Test - public static void test() throws Exception { + public void test() throws Exception { checkSupported(); Path path = null; try (var chan = SocketChannel.open(UNIX)) { @@ -89,7 +88,7 @@ static void checkSupported() { try { SocketChannel.open(UNIX).close(); } catch (UnsupportedOperationException e) { - throw new SkipException("Unix domain channels not supported"); + Assumptions.assumeTrue(false, "Unix domain channels not supported"); } catch (Exception e) { // continue test to see what problem is } diff --git a/test/jdk/java/nio/channels/unixdomain/IOExchanges.java b/test/jdk/java/nio/channels/unixdomain/IOExchanges.java index 33a7b5ef3c4..9924d02504a 100644 --- a/test/jdk/java/nio/channels/unixdomain/IOExchanges.java +++ b/test/jdk/java/nio/channels/unixdomain/IOExchanges.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,38 +21,45 @@ * questions. */ -/** +/* * @test * @bug 8245194 - * @run testng/othervm/timeout=480 IOExchanges + * @run junit/othervm/timeout=480 IOExchanges */ import java.io.IOException; -import java.net.*; -import java.nio.channels.*; +import java.net.ProtocolFamily; +import java.net.SocketAddress; +import java.net.UnixDomainSocketAddress; import java.nio.ByteBuffer; +import java.nio.channels.SelectionKey; +import java.nio.channels.Selector; +import java.nio.channels.ServerSocketChannel; +import java.nio.channels.SocketChannel; import java.nio.file.Files; +import java.util.List; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import static java.lang.System.out; import static java.net.StandardProtocolFamily.*; import static java.nio.channels.SelectionKey.OP_ACCEPT; import static java.nio.channels.SelectionKey.OP_READ; import static java.nio.channels.SelectionKey.OP_WRITE; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertTrue; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; public class IOExchanges { static boolean unixDomainSupported = true; - @BeforeTest() - public void setup() { + @BeforeAll() + public static void setup() { try { - SocketChannel.open(UNIX); + SocketChannel.open(UNIX).close(); } catch (IOException | UnsupportedOperationException e) { unixDomainSupported = false; out.println("Unix domain channels not supported"); @@ -72,8 +79,8 @@ static ServerSocketChannel openServerSocketChannel(ProtocolFamily family) } public static void deleteFile(SocketAddress addr) throws Exception { - if (addr instanceof UnixDomainSocketAddress) { - Files.deleteIfExists(((UnixDomainSocketAddress) addr).getPath()); + if (addr instanceof UnixDomainSocketAddress uaddr) { + Files.deleteIfExists(uaddr.getPath()); } } @@ -118,18 +125,12 @@ public static void deleteFile(SocketAddress addr) throws Exception { SPINBAccep_NBConn_NBIO_RW_12a */ - @DataProvider(name = "family") - public Object[][] family() { - return unixDomainSupported ? - new Object[][] { - { UNIX }, - { INET }} - : new Object[][] { - { INET } - }; + public static List family() { + return unixDomainSupported ? List.of(INET, UNIX) : List.of(INET); } - @Test(dataProvider = "family") + @ParameterizedTest + @MethodSource("family") public void BAccep_BConn_BIO_WR_1(ProtocolFamily family) throws Throwable { try (ServerSocketChannel ssc = openServerSocketChannel(family)) { @@ -140,25 +141,26 @@ public void BAccep_BConn_BIO_WR_1(ProtocolFamily family) try (SocketChannel sc = openSocketChannel(family)) { assertTrue(sc.connect(addr)); ByteBuffer bb = ByteBuffer.allocate(10).put((byte) 0x01).flip(); - assertEquals(sc.write(bb), 1); + assertEquals(1, sc.write(bb)); out.printf("wrote: 0x%x%n", bb.get(0)); - assertEquals(sc.read(bb.clear()), -1); + assertEquals(-1, sc.read(bb.clear())); } }); t.start(); try (SocketChannel sc = ssc.accept()) { ByteBuffer bb = ByteBuffer.allocate(10); - assertEquals(sc.read(bb), 1); + assertEquals(1, sc.read(bb)); out.printf("read: 0x%x%n", bb.get(0)); - assertEquals(bb.get(0), 0x01); + assertEquals(0x01, bb.get(0)); } t.awaitCompletion(); deleteFile(addr); } } - @Test(dataProvider = "family") + @ParameterizedTest + @MethodSource("family") public void BAccep_BConn_BIO_RW_2(ProtocolFamily family) throws Throwable { try (ServerSocketChannel ssc = openServerSocketChannel(family)) { @@ -169,25 +171,26 @@ public void BAccep_BConn_BIO_RW_2(ProtocolFamily family) try (SocketChannel sc = openSocketChannel(family)) { assertTrue(sc.connect(addr)); ByteBuffer bb = ByteBuffer.allocate(10); - assertEquals(sc.read(bb), 1); + assertEquals(1, sc.read(bb)); out.printf("read: 0x%x%n", bb.get(0)); - assertEquals(bb.get(0), 0x02); + assertEquals(0x02, bb.get(0)); } }); t.start(); try (SocketChannel sc = ssc.accept()) { ByteBuffer bb = ByteBuffer.allocate(10).put((byte) 0x02).flip(); - assertEquals(sc.write(bb), 1); + assertEquals(1, sc.write(bb)); out.printf("wrote: 0x%x%n", bb.get(0)); - assertEquals(sc.read(bb.clear()), -1); + assertEquals(-1, sc.read(bb.clear())); } t.awaitCompletion(); deleteFile(addr); } } - @Test(dataProvider = "family") + @ParameterizedTest + @MethodSource("family") public void SELNBAccep_BConn_BIO_WR_3(ProtocolFamily family) throws Throwable { try (ServerSocketChannel ssc = openServerSocketChannel(family); @@ -199,28 +202,29 @@ public void SELNBAccep_BConn_BIO_WR_3(ProtocolFamily family) try (SocketChannel sc = openSocketChannel(family)) { assertTrue(sc.connect(addr)); ByteBuffer bb = ByteBuffer.allocate(10).put((byte) 0x03).flip(); - assertEquals(sc.write(bb), 1); + assertEquals(1, sc.write(bb)); out.printf("wrote: 0x%x%n", bb.get(0)); - assertEquals(sc.read(bb.clear()), -1); + assertEquals(-1, sc.read(bb.clear())); } }); t.start(); ssc.configureBlocking(false).register(selector, OP_ACCEPT); - assertEquals(selector.select(), 1); + assertEquals(1, selector.select()); try (SocketChannel sc = ssc.accept()) { ByteBuffer bb = ByteBuffer.allocate(10); - assertEquals(sc.read(bb), 1); + assertEquals(1, sc.read(bb)); out.printf("read: 0x%x%n", bb.get(0)); - assertEquals(bb.get(0), 0x03); + assertEquals(0x03, bb.get(0)); } t.awaitCompletion(); deleteFile(addr); } } - @Test(dataProvider = "family") + @ParameterizedTest + @MethodSource("family") public void SELNBAccep_BConn_BIO_RW_4(ProtocolFamily family) throws Throwable { try (ServerSocketChannel ssc = openServerSocketChannel(family); @@ -232,21 +236,21 @@ public void SELNBAccep_BConn_BIO_RW_4(ProtocolFamily family) try (SocketChannel sc = openSocketChannel(family)) { assertTrue(sc.connect(addr)); ByteBuffer bb = ByteBuffer.allocate(10); - assertEquals(sc.read(bb), 1); + assertEquals(1, sc.read(bb)); out.printf("read: 0x%x%n", bb.get(0)); - assertEquals(bb.get(0), 0x04); + assertEquals(0x04, bb.get(0)); } }); t.start(); ssc.configureBlocking(false).register(selector, OP_ACCEPT); - assertEquals(selector.select(), 1); + assertEquals(1, selector.select()); try (SocketChannel sc = ssc.accept()) { ByteBuffer bb = ByteBuffer.allocate(10).put((byte) 0x04).flip(); - assertEquals(sc.write(bb), 1); + assertEquals(1, sc.write(bb)); out.printf("wrote: 0x%x%n", bb.get(0)); - assertEquals(sc.read(bb.clear()), -1); + assertEquals(-1, sc.read(bb.clear())); } t.awaitCompletion(); @@ -254,7 +258,8 @@ public void SELNBAccep_BConn_BIO_RW_4(ProtocolFamily family) } } - @Test(dataProvider = "family") + @ParameterizedTest + @MethodSource("family") public void SPINNBAccep_BConn_BIO_WR_5(ProtocolFamily family) throws Throwable { try (ServerSocketChannel ssc = openServerSocketChannel(family)) { @@ -265,9 +270,9 @@ public void SPINNBAccep_BConn_BIO_WR_5(ProtocolFamily family) try (SocketChannel sc = openSocketChannel(family)) { assertTrue(sc.connect(addr)); ByteBuffer bb = ByteBuffer.allocate(10).put((byte) 0x05).flip(); - assertEquals(sc.write(bb), 1); + assertEquals(1, sc.write(bb)); out.printf("wrote: 0x%x%n", bb.get(0)); - assertEquals(sc.read(bb.clear()), -1); + assertEquals(-1, sc.read(bb.clear())); } }); t.start(); @@ -284,16 +289,17 @@ public void SPINNBAccep_BConn_BIO_WR_5(ProtocolFamily family) try (SocketChannel sc = accepted) { ByteBuffer bb = ByteBuffer.allocate(10); - assertEquals(sc.read(bb), 1); + assertEquals(1, sc.read(bb)); out.printf("read: 0x%x%n", bb.get(0)); - assertEquals(bb.get(0), 0x05); + assertEquals(0x05, bb.get(0)); } t.awaitCompletion(); deleteFile(addr); } } - @Test(dataProvider = "family") + @ParameterizedTest + @MethodSource("family") public void SPINNBAccep_BConn_BIO_RW_6(ProtocolFamily family) throws Throwable { try (ServerSocketChannel ssc = openServerSocketChannel(family)) { @@ -304,9 +310,9 @@ public void SPINNBAccep_BConn_BIO_RW_6(ProtocolFamily family) try (SocketChannel sc = openSocketChannel(family)) { assertTrue(sc.connect(addr)); ByteBuffer bb = ByteBuffer.allocate(10); - assertEquals(sc.read(bb), 1); + assertEquals(1, sc.read(bb)); out.printf("read: 0x%x%n", bb.get(0)); - assertEquals(bb.get(0), 0x06); + assertEquals(0x06, bb.get(0)); } }); t.start(); @@ -323,9 +329,9 @@ public void SPINNBAccep_BConn_BIO_RW_6(ProtocolFamily family) try (SocketChannel sc = accepted) { ByteBuffer bb = ByteBuffer.allocate(10).put((byte) 0x06).flip(); - assertEquals(sc.write(bb), 1); + assertEquals(1, sc.write(bb)); out.printf("wrote: 0x%x%n", bb.get(0)); - assertEquals(sc.read(bb.clear()), -1); + assertEquals(-1, sc.read(bb.clear())); } t.awaitCompletion(); @@ -336,7 +342,8 @@ public void SPINNBAccep_BConn_BIO_RW_6(ProtocolFamily family) // Similar to the previous six scenarios, but with same-thread // non-blocking connect. - @Test(dataProvider = "family") + @ParameterizedTest + @MethodSource("family") public void BAccep_NBConn_BIO_WR_7(ProtocolFamily family) throws Throwable { try (ServerSocketChannel ssc = openServerSocketChannel(family)) { @@ -352,16 +359,16 @@ public void BAccep_NBConn_BIO_WR_7(ProtocolFamily family) sc.configureBlocking(true); TestThread t = TestThread.of("t7", () -> { ByteBuffer bb = ByteBuffer.allocate(10).put((byte) 0x07).flip(); - assertEquals(sc.write(bb), 1); + assertEquals(1, sc.write(bb)); out.printf("wrote: 0x%x%n", bb.get(0)); - assertEquals(sc.read(bb.clear()), -1); + assertEquals(-1, sc.read(bb.clear())); }); t.start(); ByteBuffer bb = ByteBuffer.allocate(10); - assertEquals(sc2.read(bb), 1); + assertEquals(1, sc2.read(bb)); out.printf("read: 0x%x%n", bb.get(0)); - assertEquals(bb.get(0), 0x07); + assertEquals(0x07, bb.get(0)); sc2.shutdownOutput(); t.awaitCompletion(); } @@ -370,7 +377,8 @@ public void BAccep_NBConn_BIO_WR_7(ProtocolFamily family) } } - @Test(dataProvider = "family") + @ParameterizedTest + @MethodSource("family") public void BAccep_NBConn_BIO_RW_8(ProtocolFamily family) throws Throwable { try (ServerSocketChannel ssc = openServerSocketChannel(family)) { @@ -386,17 +394,17 @@ public void BAccep_NBConn_BIO_RW_8(ProtocolFamily family) sc.configureBlocking(true); TestThread t = TestThread.of("t8", () -> { ByteBuffer bb = ByteBuffer.allocate(10); - assertEquals(sc.read(bb), 1); + assertEquals(1, sc.read(bb)); out.printf("read: 0x%x%n", bb.get(0)); - assertEquals(bb.get(0), 0x08); + assertEquals(0x08, bb.get(0)); sc.shutdownOutput(); }); t.start(); ByteBuffer bb = ByteBuffer.allocate(10).put((byte) 0x08).flip(); - assertEquals(sc2.write(bb), 1); + assertEquals(1, sc2.write(bb)); out.printf("wrote: 0x%x%n", bb.get(0)); - assertEquals(sc2.read(bb.clear()), -1); + assertEquals(-1, sc2.read(bb.clear())); t.awaitCompletion(); } } @@ -404,7 +412,8 @@ public void BAccep_NBConn_BIO_RW_8(ProtocolFamily family) } } - @Test(dataProvider = "family") + @ParameterizedTest + @MethodSource("family") public void SELNBAccep_NBConn_BIO_WR_9(ProtocolFamily family) throws Throwable { try (ServerSocketChannel ssc = openServerSocketChannel(family)) { @@ -417,23 +426,23 @@ public void SELNBAccep_NBConn_BIO_WR_9(ProtocolFamily family) sc.connect(addr); ssc.configureBlocking(false).register(selector, OP_ACCEPT); - assertEquals(selector.select(), 1); + assertEquals(1, selector.select()); try (SocketChannel sc2 = ssc.accept()) { assertTrue(sc.finishConnect()); sc.configureBlocking(true); TestThread t = TestThread.of("t9", () -> { ByteBuffer bb = ByteBuffer.allocate(10).put((byte) 0x09).flip(); - assertEquals(sc.write(bb), 1); + assertEquals(1, sc.write(bb)); out.printf("wrote: 0x%x%n", bb.get(0)); - assertEquals(sc.read(bb.clear()), -1); + assertEquals(-1, sc.read(bb.clear())); }); t.start(); ByteBuffer bb = ByteBuffer.allocate(10); - assertEquals(sc2.read(bb), 1); + assertEquals(1, sc2.read(bb)); out.printf("read: 0x%x%n", bb.get(0)); - assertEquals(bb.get(0), 0x09); + assertEquals(0x09, bb.get(0)); sc2.shutdownOutput(); t.awaitCompletion(); } @@ -442,7 +451,8 @@ public void SELNBAccep_NBConn_BIO_WR_9(ProtocolFamily family) } } - @Test(dataProvider = "family") + @ParameterizedTest + @MethodSource("family") public void SELNBAccep_NBConn_BIO_RW_10(ProtocolFamily family) throws Throwable { try (ServerSocketChannel ssc = openServerSocketChannel(family)) { @@ -455,24 +465,24 @@ public void SELNBAccep_NBConn_BIO_RW_10(ProtocolFamily family) sc.connect(addr); ssc.configureBlocking(false).register(selector, OP_ACCEPT); - assertEquals(selector.select(), 1); + assertEquals(1, selector.select()); try (SocketChannel sc2 = ssc.accept()) { assertTrue(sc.finishConnect()); sc.configureBlocking(true); TestThread t = TestThread.of("t10", () -> { ByteBuffer bb = ByteBuffer.allocate(10); - assertEquals(sc.read(bb), 1); + assertEquals(1, sc.read(bb)); out.printf("read: 0x%x%n", bb.get(0)); - assertEquals(bb.get(0), 0x10); + assertEquals(0x10, bb.get(0)); sc.shutdownOutput(); }); t.start(); ByteBuffer bb = ByteBuffer.allocate(10).put((byte) 0x10).flip(); - assertEquals(sc2.write(bb), 1); + assertEquals(1, sc2.write(bb)); out.printf("wrote: 0x%x%n", bb.get(0)); - assertEquals(sc2.read(bb.clear()), -1); + assertEquals(-1, sc2.read(bb.clear())); t.awaitCompletion(); } } @@ -480,7 +490,8 @@ public void SELNBAccep_NBConn_BIO_RW_10(ProtocolFamily family) } } - @Test(dataProvider = "family") + @ParameterizedTest + @MethodSource("family") public void SPINNBAccep_NBConn_BIO_WR_11(ProtocolFamily family) throws Throwable { try (ServerSocketChannel ssc = openServerSocketChannel(family)) { @@ -506,16 +517,16 @@ public void SPINNBAccep_NBConn_BIO_WR_11(ProtocolFamily family) sc.configureBlocking(true); TestThread t = TestThread.of("t11", () -> { ByteBuffer bb = ByteBuffer.allocate(10).put((byte) 0x11).flip(); - assertEquals(sc.write(bb), 1); + assertEquals(1, sc.write(bb)); out.printf("wrote: 0x%x%n", bb.get(0)); - assertEquals(sc.read(bb.clear()), -1); + assertEquals(-1, sc.read(bb.clear())); }); t.start(); ByteBuffer bb = ByteBuffer.allocate(10); - assertEquals(sc2.read(bb), 1); + assertEquals(1, sc2.read(bb)); out.printf("read: 0x%x%n", bb.get(0)); - assertEquals(bb.get(0), 0x11); + assertEquals(0x11, bb.get(0)); sc2.shutdownOutput(); t.awaitCompletion(); } @@ -524,7 +535,8 @@ public void SPINNBAccep_NBConn_BIO_WR_11(ProtocolFamily family) } } - @Test(dataProvider = "family") + @ParameterizedTest + @MethodSource("family") public void SPINNBAccep_NBConn_BIO_RW_12(ProtocolFamily family) throws Throwable { try (ServerSocketChannel ssc = openServerSocketChannel(family)) { @@ -550,17 +562,17 @@ public void SPINNBAccep_NBConn_BIO_RW_12(ProtocolFamily family) sc.configureBlocking(true); TestThread t = TestThread.of("t12", () -> { ByteBuffer bb = ByteBuffer.allocate(10); - assertEquals(sc.read(bb), 1); + assertEquals(1, sc.read(bb)); out.printf("read: 0x%x%n", bb.get(0)); - assertEquals(bb.get(0), 0x12); + assertEquals(0x12, bb.get(0)); sc.shutdownOutput(); }); t.start(); ByteBuffer bb = ByteBuffer.allocate(10).put((byte) 0x12).flip(); - assertEquals(sc2.write(bb), 1); + assertEquals(1, sc2.write(bb)); out.printf("wrote: 0x%x%n", bb.get(0)); - assertEquals(sc2.read(bb.clear()), -1); + assertEquals(-1, sc2.read(bb.clear())); t.awaitCompletion(); } } @@ -572,7 +584,8 @@ public void SPINNBAccep_NBConn_BIO_RW_12(ProtocolFamily family) // Similar to the previous twelve scenarios but with non-blocking IO // --- - @Test(dataProvider = "family") + @ParameterizedTest + @MethodSource("family") public void BAccep_BConn_NBIO_WR_1a(ProtocolFamily family) throws Throwable { try (ServerSocketChannel ssc = openServerSocketChannel(family)) { @@ -589,13 +602,13 @@ public void BAccep_BConn_NBIO_WR_1a(ProtocolFamily family) selector.select(); int c; while ((c = sc.write(bb)) < 1) ; - assertEquals(c, 1); + assertEquals(1, c); out.printf("wrote: 0x%x%n", bb.get(0)); k.interestOps(OP_READ); selector.select(); bb.clear(); while ((c = sc.read(bb)) == 0) ; - assertEquals(c, -1); + assertEquals(-1, c); } }); t.start(); @@ -608,16 +621,17 @@ public void BAccep_BConn_NBIO_WR_1a(ProtocolFamily family) selector.select(); int c; while ((c = sc.read(bb)) == 0) ; - assertEquals(c, 1); + assertEquals(1, c); out.printf("read: 0x%x%n", bb.get(0)); - assertEquals(bb.get(0), 0x1A); + assertEquals(0x1A, bb.get(0)); } t.awaitCompletion(); deleteFile(addr); } } - @Test(dataProvider = "family") + @ParameterizedTest + @MethodSource("family") public void BAccep_BConn_NBIO_RW_2a(ProtocolFamily family) throws Throwable { try (ServerSocketChannel ssc = openServerSocketChannel(family)) { @@ -634,9 +648,9 @@ public void BAccep_BConn_NBIO_RW_2a(ProtocolFamily family) selector.select(); int c; while ((c = sc.read(bb)) == 0) ; - assertEquals(c, 1); + assertEquals(1, c); out.printf("read: 0x%x%n", bb.get(0)); - assertEquals(bb.get(0), 0x2A); + assertEquals(0x2A, bb.get(0)); } }); t.start(); @@ -649,20 +663,21 @@ public void BAccep_BConn_NBIO_RW_2a(ProtocolFamily family) selector.select(); int c; while ((c = sc.write(bb)) < 1) ; - assertEquals(c, 1); + assertEquals(1, c); out.printf("wrote: 0x%x%n", bb.get(0)); k.interestOps(OP_READ); selector.select(); bb.clear(); while ((c = sc.read(bb)) == 0) ; - assertEquals(c, -1); + assertEquals(-1, c); } t.awaitCompletion(); deleteFile(addr); } } - @Test(dataProvider = "family") + @ParameterizedTest + @MethodSource("family") public void SELNBAccep_BConn_NBIO_WR_3a(ProtocolFamily family) throws Throwable { try (ServerSocketChannel ssc = openServerSocketChannel(family); @@ -680,19 +695,19 @@ public void SELNBAccep_BConn_NBIO_WR_3a(ProtocolFamily family) selector.select(); int c; while ((c = sc.write(bb)) < 1) ; - assertEquals(c, 1); + assertEquals(1, c); out.printf("wrote: 0x%x%n", bb.get(0)); k.interestOps(OP_READ); selector.select(); bb.clear(); while ((c = sc.read(bb)) == 0) ; - assertEquals(c, -1); + assertEquals(-1, c); } }); t.start(); ssc.configureBlocking(false).register(aselector, OP_ACCEPT); - assertEquals(aselector.select(), 1); + assertEquals(1, aselector.select()); try (SocketChannel sc = ssc.accept(); Selector selector = Selector.open()) { @@ -702,16 +717,17 @@ public void SELNBAccep_BConn_NBIO_WR_3a(ProtocolFamily family) selector.select(); int c; while ((c = sc.read(bb)) == 0) ; - assertEquals(c, 1); + assertEquals(1, c); out.printf("read: 0x%x%n", bb.get(0)); - assertEquals(bb.get(0), 0x3A); + assertEquals(0x3A, bb.get(0)); } t.awaitCompletion(); deleteFile(addr); } } - @Test(dataProvider = "family") + @ParameterizedTest + @MethodSource("family") public void SELNBAccep_BConn_NBIO_RW_4a(ProtocolFamily family) throws Throwable { try (ServerSocketChannel ssc = openServerSocketChannel(family); @@ -729,15 +745,15 @@ public void SELNBAccep_BConn_NBIO_RW_4a(ProtocolFamily family) selector.select(); int c; while ((c = sc.read(bb)) == 0) ; - assertEquals(c, 1); + assertEquals(1, c); out.printf("read: 0x%x%n", bb.get(0)); - assertEquals(bb.get(0), 0x4A); + assertEquals(0x4A, bb.get(0)); } }); t.start(); ssc.configureBlocking(false).register(aselector, OP_ACCEPT); - assertEquals(aselector.select(), 1); + assertEquals(1, aselector.select()); try (SocketChannel sc = ssc.accept(); Selector selector = Selector.open()) { @@ -747,20 +763,21 @@ public void SELNBAccep_BConn_NBIO_RW_4a(ProtocolFamily family) selector.select(); int c; while ((c = sc.write(bb)) < 1) ; - assertEquals(c, 1); + assertEquals(1, c); out.printf("wrote: 0x%x%n", bb.get(0)); k.interestOps(OP_READ); selector.select(); bb.clear(); while ((c = sc.read(bb)) == 0) ; - assertEquals(c, -1); + assertEquals(-1, c); } t.awaitCompletion(); deleteFile(addr); } } - @Test(dataProvider = "family") + @ParameterizedTest + @MethodSource("family") public void SPINNBAccep_BConn_NBIO_WR_5a(ProtocolFamily family) throws Throwable { try (ServerSocketChannel ssc = openServerSocketChannel(family)) { @@ -777,13 +794,13 @@ public void SPINNBAccep_BConn_NBIO_WR_5a(ProtocolFamily family) selector.select(); int c; while ((c = sc.write(bb)) < 1) ; - assertEquals(c, 1); + assertEquals(1, c); out.printf("wrote: 0x%x%n", bb.get(0)); k.interestOps(OP_READ); selector.select(); bb.clear(); while ((c = sc.read(bb)) == 0) ; - assertEquals(c, -1); + assertEquals(-1, c); } }); t.start(); @@ -806,16 +823,17 @@ public void SPINNBAccep_BConn_NBIO_WR_5a(ProtocolFamily family) selector.select(); int c; while ((c = sc.read(bb)) == 0) ; - assertEquals(c, 1); + assertEquals(1, c); out.printf("read: 0x%x%n", bb.get(0)); - assertEquals(bb.get(0), 0x5A); + assertEquals(0x5A, bb.get(0)); } t.awaitCompletion(); deleteFile(addr); } } - @Test(dataProvider = "family") + @ParameterizedTest + @MethodSource("family") public void SPINNBAccep_BConn_NBIO_RW_6a(ProtocolFamily family) throws Throwable { try (ServerSocketChannel ssc = openServerSocketChannel(family)) { @@ -832,9 +850,9 @@ public void SPINNBAccep_BConn_NBIO_RW_6a(ProtocolFamily family) selector.select(); int c; while ((c = sc.read(bb)) == 0) ; - assertEquals(c, 1); + assertEquals(1, c); out.printf("read: 0x%x%n", bb.get(0)); - assertEquals(bb.get(0), 0x6A); + assertEquals(0x6A, bb.get(0)); } }); t.start(); @@ -857,13 +875,13 @@ public void SPINNBAccep_BConn_NBIO_RW_6a(ProtocolFamily family) selector.select(); int c; while ((c = sc.write(bb)) < 1) ; - assertEquals(c, 1); + assertEquals(1, c); out.printf("wrote: 0x%x%n", bb.get(0)); k.interestOps(OP_READ); selector.select(); bb.clear(); while ((c = sc.read(bb)) == 0) ; - assertEquals(c, -1); + assertEquals(-1, c); } t.awaitCompletion(); @@ -874,7 +892,8 @@ public void SPINNBAccep_BConn_NBIO_RW_6a(ProtocolFamily family) // Similar to the previous six scenarios but with same-thread // non-blocking connect. - @Test(dataProvider = "family") + @ParameterizedTest + @MethodSource("family") public void BAccep_NBConn_NBIO_WR_7a(ProtocolFamily family) throws Throwable { try (ServerSocketChannel ssc = openServerSocketChannel(family)) { @@ -895,13 +914,13 @@ public void BAccep_NBConn_NBIO_WR_7a(ProtocolFamily family) selector.select(); int c; while ((c = sc.write(bb)) < 1) ; - assertEquals(c, 1); + assertEquals(1, c); out.printf("wrote: 0x%x%n", bb.get(0)); k.interestOps(OP_READ); selector.select(); bb.clear(); while ((c = sc.read(bb)) == 0) ; - assertEquals(c, -1); + assertEquals(-1, c); } }); t.start(); @@ -913,9 +932,9 @@ public void BAccep_NBConn_NBIO_WR_7a(ProtocolFamily family) selector.select(); int c; while ((c = sc2.read(bb)) == 0) ; - assertEquals(c, 1); + assertEquals(1, c); out.printf("read: 0x%x%n", bb.get(0)); - assertEquals(bb.get(0), 0x7A); + assertEquals(0x7A, bb.get(0)); sc2.shutdownOutput(); } t.awaitCompletion(); @@ -925,7 +944,8 @@ public void BAccep_NBConn_NBIO_WR_7a(ProtocolFamily family) } } - @Test(dataProvider = "family") + @ParameterizedTest + @MethodSource("family") public void BAccep_NBConn_NBIO_RW_8a(ProtocolFamily family) throws Throwable { try (ServerSocketChannel ssc = openServerSocketChannel(family)) { @@ -945,9 +965,9 @@ public void BAccep_NBConn_NBIO_RW_8a(ProtocolFamily family) selector.select(); int c; while ((c = sc.read(bb)) == 0) ; - assertEquals(c, 1); + assertEquals(1, c); out.printf("read: 0x%x%n", bb.get(0)); - assertEquals(bb.get(0), (byte) 0x8A); + assertEquals((byte) 0x8A, bb.get(0)); sc.shutdownOutput(); } }); @@ -960,13 +980,13 @@ public void BAccep_NBConn_NBIO_RW_8a(ProtocolFamily family) selector.select(); int c; while ((c = sc2.write(bb)) < 1) ; - assertEquals(c, 1); + assertEquals(1, c); out.printf("wrote: 0x%x%n", bb.get(0)); k.interestOps(OP_READ); selector.select(); bb.clear(); while ((c = sc2.read(bb)) == 0) ; - assertEquals(c, -1); + assertEquals(-1, c); } t.awaitCompletion(); } @@ -975,7 +995,8 @@ public void BAccep_NBConn_NBIO_RW_8a(ProtocolFamily family) } } - @Test(dataProvider = "family") + @ParameterizedTest + @MethodSource("family") public void SELNBAccep_NBConn_NBIO_WR_9a(ProtocolFamily family) throws Throwable { try (ServerSocketChannel ssc = openServerSocketChannel(family)) { @@ -988,7 +1009,7 @@ public void SELNBAccep_NBConn_NBIO_WR_9a(ProtocolFamily family) Selector aselector = Selector.open(); ssc.configureBlocking(false).register(aselector, OP_ACCEPT); - assertEquals(aselector.select(), 1); + assertEquals(1, aselector.select()); try (SocketChannel sc2 = ssc.accept()) { assertTrue(sc.finishConnect()); @@ -1000,13 +1021,13 @@ public void SELNBAccep_NBConn_NBIO_WR_9a(ProtocolFamily family) selector.select(); int c; while ((c = sc.write(bb)) < 1) ; - assertEquals(c, 1); + assertEquals(1, c); out.printf("wrote: 0x%x%n", bb.get(0)); k.interestOps(OP_READ); selector.select(); bb.clear(); while ((c = sc.read(bb)) == 0) ; - assertEquals(c, -1); + assertEquals(-1, c); } }); t.start(); @@ -1018,9 +1039,9 @@ public void SELNBAccep_NBConn_NBIO_WR_9a(ProtocolFamily family) selector.select(); int c; while ((c = sc2.read(bb)) == 0) ; - assertEquals(c, 1); + assertEquals(1, c); out.printf("read: 0x%x%n", bb.get(0)); - assertEquals(bb.get(0), (byte) 0x9A); + assertEquals((byte) 0x9A, bb.get(0)); sc2.shutdownOutput(); } t.awaitCompletion(); @@ -1030,7 +1051,8 @@ public void SELNBAccep_NBConn_NBIO_WR_9a(ProtocolFamily family) } } - @Test(dataProvider = "family") + @ParameterizedTest + @MethodSource("family") public void SELNBAccep_NBConn_NBIO_RW_10a(ProtocolFamily family) throws Throwable { try (ServerSocketChannel ssc = openServerSocketChannel(family)) { @@ -1043,7 +1065,7 @@ public void SELNBAccep_NBConn_NBIO_RW_10a(ProtocolFamily family) Selector aselector = Selector.open(); ssc.configureBlocking(false).register(aselector, OP_ACCEPT); - assertEquals(aselector.select(), 1); + assertEquals(1, aselector.select()); try (SocketChannel sc2 = ssc.accept()) { assertTrue(sc.finishConnect()); @@ -1054,9 +1076,9 @@ public void SELNBAccep_NBConn_NBIO_RW_10a(ProtocolFamily family) selector.select(); int c; while ((c = sc.read(bb)) == 0) ; - assertEquals(c, 1); + assertEquals(1, c); out.printf("read: 0x%x%n", bb.get(0)); - assertEquals(bb.get(0), (byte) 0xAA); + assertEquals((byte) 0xAA, bb.get(0)); sc.shutdownOutput(); } }); @@ -1069,13 +1091,13 @@ public void SELNBAccep_NBConn_NBIO_RW_10a(ProtocolFamily family) selector.select(); int c; while ((c = sc2.write(bb)) < 1) ; - assertEquals(c, 1); + assertEquals(1, c); out.printf("wrote: 0x%x%n", bb.get(0)); k.interestOps(OP_READ); selector.select(); bb.clear(); while ((c = sc2.read(bb)) == 0) ; - assertEquals(c, -1); + assertEquals(-1, c); } t.awaitCompletion(); } @@ -1084,7 +1106,8 @@ public void SELNBAccep_NBConn_NBIO_RW_10a(ProtocolFamily family) } } - @Test(dataProvider = "family") + @ParameterizedTest + @MethodSource("family") public void SPINBAccep_NBConn_NBIO_WR_11a(ProtocolFamily family) throws Throwable { try (ServerSocketChannel ssc = openServerSocketChannel(family)) { @@ -1115,13 +1138,13 @@ public void SPINBAccep_NBConn_NBIO_WR_11a(ProtocolFamily family) selector.select(); int c; while ((c = sc.write(bb)) < 1) ; - assertEquals(c, 1); + assertEquals(1, c); out.printf("wrote: 0x%x%n", bb.get(0)); k.interestOps(OP_READ); selector.select(); bb.clear(); while ((c = sc.read(bb)) == 0) ; - assertEquals(c, -1); + assertEquals(-1, c); } }); t.start(); @@ -1133,9 +1156,9 @@ public void SPINBAccep_NBConn_NBIO_WR_11a(ProtocolFamily family) selector.select(); int c; while ((c = sc2.read(bb)) == 0) ; - assertEquals(c, 1); + assertEquals(1, c); out.printf("read: 0x%x%n", bb.get(0)); - assertEquals(bb.get(0), (byte) 0xBA); + assertEquals((byte) 0xBA, bb.get(0)); sc2.shutdownOutput(); } t.awaitCompletion(); @@ -1145,7 +1168,8 @@ public void SPINBAccep_NBConn_NBIO_WR_11a(ProtocolFamily family) } } - @Test(dataProvider = "family") + @ParameterizedTest + @MethodSource("family") public void SPINBAccep_NBConn_NBIO_RW_12a(ProtocolFamily family) throws Throwable { try (ServerSocketChannel ssc = openServerSocketChannel(family)) { @@ -1175,9 +1199,9 @@ public void SPINBAccep_NBConn_NBIO_RW_12a(ProtocolFamily family) selector.select(); int c; while ((c = sc.read(bb)) == 0) ; - assertEquals(c, 1); + assertEquals(1, c); out.printf("read: 0x%x%n", bb.get(0)); - assertEquals(bb.get(0), (byte) 0xCA); + assertEquals((byte) 0xCA, bb.get(0)); sc.shutdownOutput(); } }); @@ -1190,13 +1214,13 @@ public void SPINBAccep_NBConn_NBIO_RW_12a(ProtocolFamily family) selector.select(); int c; while ((c = sc2.write(bb)) < 1) ; - assertEquals(c, 1); + assertEquals(1, c); out.printf("wrote: 0x%x%n", bb.get(0)); k.interestOps(OP_READ); selector.select(); bb.clear(); while ((c = sc2.read(bb)) == 0) ; - assertEquals(c, -1); + assertEquals(-1, c); } t.awaitCompletion(); } diff --git a/test/jdk/java/nio/channels/unixdomain/NullTest.java b/test/jdk/java/nio/channels/unixdomain/NullTest.java index ed96cfdecc9..97a5b1d1b8e 100644 --- a/test/jdk/java/nio/channels/unixdomain/NullTest.java +++ b/test/jdk/java/nio/channels/unixdomain/NullTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,10 +21,10 @@ * questions. */ -/** +/* * @test * @bug 8245194 - * @run testng NullTest + * @run junit NullTest */ import java.net.ProtocolFamily; @@ -32,8 +32,9 @@ import java.net.UnixDomainSocketAddress; import java.nio.channels.*; import java.nio.file.Path; -import org.testng.annotations.Test; -import static org.testng.Assert.assertThrows; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertThrows; /** * Check for NPE @@ -45,7 +46,7 @@ public class NullTest { NullPointerException.class; @Test - public static void runTest() throws Exception { + public void runTest() throws Exception { assertThrows(NPE, () -> SocketChannel.open((ProtocolFamily)null)); assertThrows(NPE, () -> SocketChannel.open((SocketAddress)null)); assertThrows(NPE, () -> ServerSocketChannel.open((ProtocolFamily)null)); From 1e3fb444c5aa0038d123c0f43858c1c4c684d958 Mon Sep 17 00:00:00 2001 From: Ioi Lam Date: Thu, 26 Mar 2026 13:54:02 +0000 Subject: [PATCH 009/116] 8380409: JVM crashes when -XX:AOTMode=create uses app.aotconf generated with JVMTI agent Reviewed-by: kvn, asmehra --- src/hotspot/share/cds/aotArtifactFinder.cpp | 27 +++++- src/hotspot/share/cds/aotArtifactFinder.hpp | 4 +- src/hotspot/share/cds/heapShared.cpp | 1 + .../aotCache/RedefineCriticalClasses.java | 83 +++++++++++++++++++ .../aotCache/TransformCriticalClasses.java | 72 ++++++++++++++++ 5 files changed, 185 insertions(+), 2 deletions(-) create mode 100644 test/hotspot/jtreg/runtime/cds/appcds/aotCache/RedefineCriticalClasses.java create mode 100644 test/hotspot/jtreg/runtime/cds/appcds/aotCache/TransformCriticalClasses.java diff --git a/src/hotspot/share/cds/aotArtifactFinder.cpp b/src/hotspot/share/cds/aotArtifactFinder.cpp index f85f1e46520..bd69b18a1aa 100644 --- a/src/hotspot/share/cds/aotArtifactFinder.cpp +++ b/src/hotspot/share/cds/aotArtifactFinder.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,6 +32,7 @@ #include "cds/lambdaProxyClassDictionary.hpp" #include "cds/regeneratedClasses.hpp" #include "classfile/systemDictionaryShared.hpp" +#include "classfile/vmClasses.hpp" #include "logging/log.hpp" #include "memory/metaspaceClosure.hpp" #include "oops/instanceKlass.hpp" @@ -169,6 +170,7 @@ void AOTArtifactFinder::find_artifacts() { end_scanning_for_oops(); TrainingData::cleanup_training_data(); + check_critical_classes(); } void AOTArtifactFinder::start_scanning_for_oops() { @@ -233,6 +235,7 @@ void AOTArtifactFinder::add_cached_instance_class(InstanceKlass* ik) { bool created; _seen_classes->put_if_absent(ik, &created); if (created) { + check_critical_class(ik); append_to_all_cached_classes(ik); // All super types must be added. @@ -310,3 +313,25 @@ void AOTArtifactFinder::all_cached_classes_do(MetaspaceClosure* it) { it->push(_all_cached_classes->adr_at(i)); } } + +void AOTArtifactFinder::check_critical_classes() { + if (CDSConfig::is_dumping_static_archive()) { + // vmClasses are store in the AOT cache (or AOT config file, or static archive). + // If any of the vmClasses is excluded, (usually due to incompatible JVMTI agent), + // the resulting cache/config/archive is unusable. + for (auto id : EnumRange{}) { + check_critical_class(vmClasses::klass_at(id)); + } + } +} + +void AOTArtifactFinder::check_critical_class(InstanceKlass* ik) { + if (SystemDictionaryShared::is_excluded_class(ik)) { + ResourceMark rm; + const char* msg = err_msg("Critical class %s has been excluded. %s cannot be written.", + ik->external_name(), + CDSConfig::type_of_archive_being_written()); + AOTMetaspace::unrecoverable_writing_error(msg); + } +} + diff --git a/src/hotspot/share/cds/aotArtifactFinder.hpp b/src/hotspot/share/cds/aotArtifactFinder.hpp index 05bcde6b0ac..50057b6caee 100644 --- a/src/hotspot/share/cds/aotArtifactFinder.hpp +++ b/src/hotspot/share/cds/aotArtifactFinder.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -81,12 +81,14 @@ class AOTArtifactFinder : AllStatic { static void add_cached_type_array_class(TypeArrayKlass* tak); static void add_cached_instance_class(InstanceKlass* ik); static void append_to_all_cached_classes(Klass* k); + static void check_critical_class(InstanceKlass* ik); public: static void initialize(); static void find_artifacts(); static void add_cached_class(Klass* k); static void add_aot_inited_class(InstanceKlass* ik); static void all_cached_classes_do(MetaspaceClosure* it); + static void check_critical_classes(); static void dispose(); }; diff --git a/src/hotspot/share/cds/heapShared.cpp b/src/hotspot/share/cds/heapShared.cpp index 708a19e9a7d..3d10e7e1f88 100644 --- a/src/hotspot/share/cds/heapShared.cpp +++ b/src/hotspot/share/cds/heapShared.cpp @@ -564,6 +564,7 @@ bool HeapShared::archive_object(oop obj, oop referrer, KlassSubGraphInfo* subgra return false; } + AOTArtifactFinder::add_cached_class(obj->klass()); AOTOopChecker::check(obj); // Make sure contents of this oop are safe. count_allocation(obj->size()); diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/RedefineCriticalClasses.java b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/RedefineCriticalClasses.java new file mode 100644 index 00000000000..c4753ee3878 --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/RedefineCriticalClasses.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 AOT training run should fail if critical classes have been redefined by JVMTI + * @bug 8380409 + * @requires vm.cds.supports.aot.class.linking + * @library /test/lib + * @run driver RedefineClassHelper + * @build RedefineCriticalClasses + * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar RedefineCriticalClassesApp + * @run driver RedefineCriticalClasses + */ + +import java.io.InputStream; +import java.net.URL; +import java.util.ArrayList; +import jdk.test.lib.cds.CDSTestUtils; +import jdk.test.lib.helpers.ClassFileInstaller; +import jdk.test.lib.process.ProcessTools; + +public class RedefineCriticalClasses { + public static void main(String... args) throws Exception { + ArrayList processArgs = new ArrayList<>(); + + // redefineagent.jar is created by "@run driver RedefineClassHelper" + processArgs.add("-javaagent:redefineagent.jar"); + + processArgs.add("-XX:AOTMode=record"); + processArgs.add("-XX:AOTConfiguration=app.aotconfig"); + processArgs.add("-Xlog:aot,cds"); + processArgs.add("-cp"); + processArgs.add("app.jar"); + processArgs.add("RedefineCriticalClassesApp"); + + ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(processArgs); + CDSTestUtils.executeAndLog(pb, "train") + .shouldContain("Redefined: class java.lang.Class") + .shouldContain("Skipping java/lang/Class: Has been redefined") + .shouldContain("Critical class java.lang.Class has been excluded. AOT configuration file cannot be written") + .shouldHaveExitValue(1); + } +} + +class RedefineCriticalClassesApp { + public static void main(String[] args) throws Exception { + // Use RedefineClassHelper (loaded from redefineagent.jar into the boot class loader) + // to redefine java/lang/Class, using the exact same bytecodes as from the JDK. + // The JVM will mark it as having been redefined by JVMTI and will exclude it from the + // AOT configuration file. + + URL url = new URL("jrt:/java.base/java/lang/Class.class"); + try (InputStream in = url.openConnection().getInputStream()) { + byte[] b = in.readAllBytes(); + System.out.println("Length = " + b.length); + RedefineClassHelper.redefineClass(Class.class, b); + System.out.println("Redefined: " + Class.class); + } + } +} diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/TransformCriticalClasses.java b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/TransformCriticalClasses.java new file mode 100644 index 00000000000..9f25d58e01f --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/TransformCriticalClasses.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 AOT training run should fail if critical classes have been transformed by JVMTI + * with ClassFileLoadHook + * @bug 8380409 + * @requires vm.cds.supports.aot.class.linking + * @library /test/lib + * @build TransformCriticalClasses + * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar TransformCriticalClassesApp + * @run main/othervm/native TransformCriticalClasses + */ + +import java.util.ArrayList; +import jdk.test.lib.cds.CDSTestUtils; +import jdk.test.lib.helpers.ClassFileInstaller; +import jdk.test.lib.process.ProcessTools; + +public class TransformCriticalClasses { + public static void main(String... args) throws Exception { + ArrayList processArgs = new ArrayList<>(); + + // Tell the native agent SimpleClassFileLoadHook to do an dummy transformation + // of java/lang/Class. This class will be defined using the exact same bytecodes + // as from the JDK, but the JVM will mark it as having been transformed by JVMTI + // and will exclude it from the AOT configuration file. + processArgs.add("-agentlib:SimpleClassFileLoadHook=-early,java/lang/Class,xxxxxx,xxxxxx"); + + processArgs.add("-XX:AOTMode=record"); + processArgs.add("-XX:AOTConfiguration=app.aotconfig"); + processArgs.add("-Xlog:aot,cds"); + processArgs.add("-cp"); + processArgs.add("app.jar"); + processArgs.add("TransformCriticalClassesApp"); + + ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(processArgs); + CDSTestUtils.executeAndLog(pb, "train") + .shouldContain("Skipping java/lang/Class: From ClassFileLoadHook") + .shouldContain("Critical class java.lang.Class has been excluded. AOT configuration file cannot be written") + .shouldHaveExitValue(1); + } +} + +class TransformCriticalClassesApp { + public static void main(String[] args) { + System.out.println("HelloWorld"); + } +} From b3048bbed0ab050f139d117e11657a2eef081861 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20H=C3=BCbner?= Date: Thu, 26 Mar 2026 14:09:17 +0000 Subject: [PATCH 010/116] 8370504: InterpreterMacroAssembler::profile_virtual_call parameter 'receiver_can_be_null' is unused Reviewed-by: aseoane, azafari, mchevalier, fbredberg --- src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp | 15 ++------------- src/hotspot/cpu/aarch64/interp_masm_aarch64.hpp | 5 ++--- src/hotspot/cpu/arm/interp_masm_arm.cpp | 15 ++------------- src/hotspot/cpu/arm/interp_masm_arm.hpp | 5 ++--- src/hotspot/cpu/ppc/interp_masm_ppc.hpp | 4 ++-- src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp | 17 ++--------------- src/hotspot/cpu/ppc/templateTable_ppc_64.cpp | 6 +++--- src/hotspot/cpu/riscv/interp_masm_riscv.cpp | 15 ++------------- src/hotspot/cpu/riscv/interp_masm_riscv.hpp | 5 ++--- src/hotspot/cpu/s390/interp_masm_s390.cpp | 16 ++-------------- src/hotspot/cpu/s390/interp_masm_s390.hpp | 5 ++--- src/hotspot/cpu/x86/interp_masm_x86.cpp | 17 ++--------------- src/hotspot/cpu/x86/interp_masm_x86.hpp | 5 ++--- 13 files changed, 27 insertions(+), 103 deletions(-) diff --git a/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp b/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp index 2b506b241e0..980fedb406d 100644 --- a/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, 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. * @@ -989,26 +989,15 @@ void InterpreterMacroAssembler::profile_final_call(Register mdp) { void InterpreterMacroAssembler::profile_virtual_call(Register receiver, - Register mdp, - bool receiver_can_be_null) { + Register mdp) { if (ProfileInterpreter) { Label profile_continue; // If no method data exists, go to profile_continue. test_method_data_pointer(mdp, profile_continue); - Label skip_receiver_profile; - if (receiver_can_be_null) { - Label not_null; - // We are making a call. Increment the count for null receiver. - increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); - b(skip_receiver_profile); - bind(not_null); - } - // Record the receiver type. profile_receiver_type(receiver, mdp, 0); - bind(skip_receiver_profile); // The method data pointer needs to be updated to reflect the new target. update_mdp_by_constant(mdp, in_bytes(VirtualCallData::virtual_call_data_size())); diff --git a/src/hotspot/cpu/aarch64/interp_masm_aarch64.hpp b/src/hotspot/cpu/aarch64/interp_masm_aarch64.hpp index 74d4430000d..9a074f1ce69 100644 --- a/src/hotspot/cpu/aarch64/interp_masm_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/interp_masm_aarch64.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2015, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -285,8 +285,7 @@ class InterpreterMacroAssembler: public MacroAssembler { void profile_not_taken_branch(Register mdp); void profile_call(Register mdp); void profile_final_call(Register mdp); - void profile_virtual_call(Register receiver, Register mdp, - bool receiver_can_be_null = false); + void profile_virtual_call(Register receiver, Register mdp); void profile_ret(Register return_bci, Register mdp); void profile_null_seen(Register mdp); void profile_typecheck(Register mdp, Register klass); diff --git a/src/hotspot/cpu/arm/interp_masm_arm.cpp b/src/hotspot/cpu/arm/interp_masm_arm.cpp index 23ecea24eb2..aee407864ee 100644 --- a/src/hotspot/cpu/arm/interp_masm_arm.cpp +++ b/src/hotspot/cpu/arm/interp_masm_arm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1210,7 +1210,7 @@ void InterpreterMacroAssembler::profile_final_call(Register mdp) { // Sets mdp, blows Rtemp. -void InterpreterMacroAssembler::profile_virtual_call(Register mdp, Register receiver, bool receiver_can_be_null) { +void InterpreterMacroAssembler::profile_virtual_call(Register mdp, Register receiver) { assert_different_registers(mdp, receiver, Rtemp); if (ProfileInterpreter) { @@ -1219,19 +1219,8 @@ void InterpreterMacroAssembler::profile_virtual_call(Register mdp, Register rece // If no method data exists, go to profile_continue. test_method_data_pointer(mdp, profile_continue); - Label skip_receiver_profile; - if (receiver_can_be_null) { - Label not_null; - cbnz(receiver, not_null); - // We are making a call. Increment the count for null receiver. - increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset()), Rtemp); - b(skip_receiver_profile); - bind(not_null); - } - // Record the receiver type. record_klass_in_profile(receiver, mdp, Rtemp, true); - bind(skip_receiver_profile); // The method data pointer needs to be updated to reflect the new target. update_mdp_by_constant(mdp, in_bytes(VirtualCallData::virtual_call_data_size())); diff --git a/src/hotspot/cpu/arm/interp_masm_arm.hpp b/src/hotspot/cpu/arm/interp_masm_arm.hpp index 530be1c577e..147cd252b2c 100644 --- a/src/hotspot/cpu/arm/interp_masm_arm.hpp +++ b/src/hotspot/cpu/arm/interp_masm_arm.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -239,8 +239,7 @@ class InterpreterMacroAssembler: public MacroAssembler { void profile_call(Register mdp); // Sets mdp, blows Rtemp. void profile_final_call(Register mdp); // Sets mdp, blows Rtemp. - void profile_virtual_call(Register mdp, Register receiver, // Sets mdp, blows Rtemp. - bool receiver_can_be_null = false); + void profile_virtual_call(Register mdp, Register receiver); // Sets mdp, blows Rtemp. void profile_ret(Register mdp, Register return_bci); // Sets mdp, blows R0-R3/R0-R18, Rtemp, LR void profile_null_seen(Register mdp); // Sets mdp. void profile_typecheck(Register mdp, Register klass); // Sets mdp, blows Rtemp. diff --git a/src/hotspot/cpu/ppc/interp_masm_ppc.hpp b/src/hotspot/cpu/ppc/interp_masm_ppc.hpp index 4ea33ebaf63..275ff92c699 100644 --- a/src/hotspot/cpu/ppc/interp_masm_ppc.hpp +++ b/src/hotspot/cpu/ppc/interp_masm_ppc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2025 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -258,7 +258,7 @@ class InterpreterMacroAssembler: public MacroAssembler { void profile_not_taken_branch(Register scratch1, Register scratch2); void profile_call(Register scratch1, Register scratch2); void profile_final_call(Register scratch1, Register scratch2); - void profile_virtual_call(Register Rreceiver, Register Rscratch1, Register Rscratch2, bool receiver_can_be_null); + void profile_virtual_call(Register Rreceiver, Register Rscratch1, Register Rscratch2); void profile_typecheck(Register Rklass, Register Rscratch1, Register Rscratch2); void profile_ret(TosState state, Register return_bci, Register scratch1, Register scratch2); void profile_switch_default(Register scratch1, Register scratch2); diff --git a/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp b/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp index f7bf457f72c..56eade8e533 100644 --- a/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp +++ b/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2025 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -1340,28 +1340,15 @@ void InterpreterMacroAssembler::profile_final_call(Register scratch1, Register s // Count a virtual call in the bytecodes. void InterpreterMacroAssembler::profile_virtual_call(Register Rreceiver, Register Rscratch1, - Register Rscratch2, - bool receiver_can_be_null) { + Register Rscratch2) { if (!ProfileInterpreter) { return; } Label profile_continue; // If no method data exists, go to profile_continue. test_method_data_pointer(profile_continue); - Label skip_receiver_profile; - if (receiver_can_be_null) { - Label not_null; - cmpdi(CR0, Rreceiver, 0); - bne(CR0, not_null); - // We are making a call. Increment the count for null receiver. - increment_mdp_data_at(in_bytes(CounterData::count_offset()), Rscratch1, Rscratch2); - b(skip_receiver_profile); - bind(not_null); - } - // Record the receiver type. record_klass_in_profile(Rreceiver, Rscratch1, Rscratch2); - bind(skip_receiver_profile); // The method data pointer needs to be updated to reflect the new target. update_mdp_by_constant(in_bytes(VirtualCallData::virtual_call_data_size())); diff --git a/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp b/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp index 8a3af748fa1..37f780535b4 100644 --- a/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp +++ b/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp @@ -3489,7 +3489,7 @@ void TemplateTable::invokevirtual(int byte_no) { // Get receiver klass. __ load_klass_check_null_throw(Rrecv_klass, Rrecv, R11_scratch1); __ verify_klass_ptr(Rrecv_klass); - __ profile_virtual_call(Rrecv_klass, R11_scratch1, R12_scratch2, false); + __ profile_virtual_call(Rrecv_klass, R11_scratch1, R12_scratch2); generate_vtable_call(Rrecv_klass, Rvtableindex_or_method, Rret_addr, R11_scratch1); } @@ -3596,7 +3596,7 @@ void TemplateTable::invokeinterface_object_method(Register Rrecv_klass, // Non-final callc case. __ bind(LnotFinal); __ lhz(Rindex, in_bytes(ResolvedMethodEntry::table_index_offset()), Rcache); - __ profile_virtual_call(Rrecv_klass, Rtemp1, Rscratch, false); + __ profile_virtual_call(Rrecv_klass, Rtemp1, Rscratch); generate_vtable_call(Rrecv_klass, Rindex, Rret, Rscratch); } @@ -3664,7 +3664,7 @@ void TemplateTable::invokeinterface(int byte_no) { __ lookup_interface_method(Rrecv_klass, Rinterface_klass, noreg, noreg, Rscratch1, Rscratch2, L_no_such_interface, /*return_method=*/false); - __ profile_virtual_call(Rrecv_klass, Rscratch1, Rscratch2, false); + __ profile_virtual_call(Rrecv_klass, Rscratch1, Rscratch2); // Find entry point to call. diff --git a/src/hotspot/cpu/riscv/interp_masm_riscv.cpp b/src/hotspot/cpu/riscv/interp_masm_riscv.cpp index 744590bec2b..804c2072ba5 100644 --- a/src/hotspot/cpu/riscv/interp_masm_riscv.cpp +++ b/src/hotspot/cpu/riscv/interp_masm_riscv.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. * Copyright (c) 2020, 2023, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -1040,26 +1040,15 @@ void InterpreterMacroAssembler::profile_final_call(Register mdp) { void InterpreterMacroAssembler::profile_virtual_call(Register receiver, - Register mdp, - bool receiver_can_be_null) { + Register mdp) { if (ProfileInterpreter) { Label profile_continue; // If no method data exists, go to profile_continue. test_method_data_pointer(mdp, profile_continue); - Label skip_receiver_profile; - if (receiver_can_be_null) { - Label not_null; - // We are making a call. Increment the count for null receiver. - increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); - j(skip_receiver_profile); - bind(not_null); - } - // Record the receiver type. profile_receiver_type(receiver, mdp, 0); - bind(skip_receiver_profile); // The method data pointer needs to be updated to reflect the new target. diff --git a/src/hotspot/cpu/riscv/interp_masm_riscv.hpp b/src/hotspot/cpu/riscv/interp_masm_riscv.hpp index 59cc76b022f..df86f0dc532 100644 --- a/src/hotspot/cpu/riscv/interp_masm_riscv.hpp +++ b/src/hotspot/cpu/riscv/interp_masm_riscv.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2015, Red Hat Inc. All rights reserved. * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -274,8 +274,7 @@ class InterpreterMacroAssembler: public MacroAssembler { void profile_not_taken_branch(Register mdp); void profile_call(Register mdp); void profile_final_call(Register mdp); - void profile_virtual_call(Register receiver, Register mdp, - bool receiver_can_be_null = false); + void profile_virtual_call(Register receiver, Register mdp); void profile_ret(Register return_bci, Register mdp); void profile_null_seen(Register mdp); void profile_typecheck(Register mdp, Register klass); diff --git a/src/hotspot/cpu/s390/interp_masm_s390.cpp b/src/hotspot/cpu/s390/interp_masm_s390.cpp index a80ca26239b..d5239898dd7 100644 --- a/src/hotspot/cpu/s390/interp_masm_s390.cpp +++ b/src/hotspot/cpu/s390/interp_masm_s390.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2024 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -1259,27 +1259,15 @@ void InterpreterMacroAssembler::profile_final_call(Register mdp) { void InterpreterMacroAssembler::profile_virtual_call(Register receiver, Register mdp, - Register reg2, - bool receiver_can_be_null) { + Register reg2) { if (ProfileInterpreter) { NearLabel profile_continue; // If no method data exists, go to profile_continue. test_method_data_pointer(mdp, profile_continue); - NearLabel skip_receiver_profile; - if (receiver_can_be_null) { - NearLabel not_null; - compareU64_and_branch(receiver, (intptr_t)0L, bcondNotEqual, not_null); - // We are making a call. Increment the count for null receiver. - increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); - z_bru(skip_receiver_profile); - bind(not_null); - } - // Record the receiver type. record_klass_in_profile(receiver, mdp, reg2); - bind(skip_receiver_profile); // The method data pointer needs to be updated to reflect the new target. update_mdp_by_constant(mdp, in_bytes(VirtualCallData::virtual_call_data_size())); diff --git a/src/hotspot/cpu/s390/interp_masm_s390.hpp b/src/hotspot/cpu/s390/interp_masm_s390.hpp index d981f9ea01e..b816185b065 100644 --- a/src/hotspot/cpu/s390/interp_masm_s390.hpp +++ b/src/hotspot/cpu/s390/interp_masm_s390.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2024 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -296,8 +296,7 @@ class InterpreterMacroAssembler: public MacroAssembler { void profile_call(Register mdp); void profile_final_call(Register mdp); void profile_virtual_call(Register receiver, Register mdp, - Register scratch2, - bool receiver_can_be_null = false); + Register scratch2); void profile_ret(Register return_bci, Register mdp); void profile_null_seen(Register mdp); void profile_typecheck(Register mdp, Register klass, Register scratch); diff --git a/src/hotspot/cpu/x86/interp_masm_x86.cpp b/src/hotspot/cpu/x86/interp_masm_x86.cpp index b2ea4143ac4..a38971c86fb 100644 --- a/src/hotspot/cpu/x86/interp_masm_x86.cpp +++ b/src/hotspot/cpu/x86/interp_masm_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1392,28 +1392,15 @@ void InterpreterMacroAssembler::profile_final_call(Register mdp) { void InterpreterMacroAssembler::profile_virtual_call(Register receiver, - Register mdp, - bool receiver_can_be_null) { + Register mdp) { if (ProfileInterpreter) { Label profile_continue; // If no method data exists, go to profile_continue. test_method_data_pointer(mdp, profile_continue); - Label skip_receiver_profile; - if (receiver_can_be_null) { - Label not_null; - testptr(receiver, receiver); - jccb(Assembler::notZero, not_null); - // We are making a call. Increment the count for null receiver. - increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); - jmp(skip_receiver_profile); - bind(not_null); - } - // Record the receiver type. profile_receiver_type(receiver, mdp, 0); - bind(skip_receiver_profile); // The method data pointer needs to be updated to reflect the new target. update_mdp_by_constant(mdp, in_bytes(VirtualCallData::virtual_call_data_size())); diff --git a/src/hotspot/cpu/x86/interp_masm_x86.hpp b/src/hotspot/cpu/x86/interp_masm_x86.hpp index 4114028f78e..dfbd7ab64e0 100644 --- a/src/hotspot/cpu/x86/interp_masm_x86.hpp +++ b/src/hotspot/cpu/x86/interp_masm_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -243,8 +243,7 @@ class InterpreterMacroAssembler: public MacroAssembler { void profile_not_taken_branch(Register mdp); void profile_call(Register mdp); void profile_final_call(Register mdp); - void profile_virtual_call(Register receiver, Register mdp, - bool receiver_can_be_null = false); + void profile_virtual_call(Register receiver, Register mdp); void profile_ret(Register return_bci, Register mdp); void profile_null_seen(Register mdp); void profile_typecheck(Register mdp, Register klass); From 22831cb0d8f828327b49f45e04f2a62ae33754ee Mon Sep 17 00:00:00 2001 From: Kerem Kat Date: Thu, 26 Mar 2026 14:15:11 +0000 Subject: [PATCH 011/116] 8378005: Exclude boxing calls from guaranteed safepoint check in loop opts Reviewed-by: mhaessig, chagedorn --- src/hotspot/share/opto/loopnode.cpp | 16 +++- .../TestBoxingInfiniteLoopBrokenIf.java | 88 +++++++++++++++++++ ...TestStressLongCountedLoopInfiniteLoop.java | 75 ++++++++++++++++ 3 files changed, 176 insertions(+), 3 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/loopopts/TestBoxingInfiniteLoopBrokenIf.java create mode 100644 test/hotspot/jtreg/compiler/loopopts/TestStressLongCountedLoopInfiniteLoop.java diff --git a/src/hotspot/share/opto/loopnode.cpp b/src/hotspot/share/opto/loopnode.cpp index 686a0a05f66..23186a25320 100644 --- a/src/hotspot/share/opto/loopnode.cpp +++ b/src/hotspot/share/opto/loopnode.cpp @@ -4345,8 +4345,13 @@ void IdealLoopTree::allpaths_check_safepts(VectorSet &visited, Node_List &stack) visited.set(_head->_idx); while (stack.size() > 0) { Node* n = stack.pop(); - if (n->is_Call() && n->as_Call()->guaranteed_safepoint()) { - // Terminate this path + if (n->is_Call() && n->as_Call()->guaranteed_safepoint() + && !(n->is_CallStaticJava() && n->as_CallStaticJava()->is_boxing_method())) { + // Terminate this path: guaranteed safepoint found. + // Boxing CallStaticJava calls are excluded as they may lack a safepoint on the fast path. This is + // not done via CallStaticJavaNode::guaranteed_safepoint() as that also controls PcDesc emission. + // In the future, guaranteed_safepoint() should be reworked to correctly handle boxing methods + // to avoid this additional check. } else if (n->Opcode() == Op_SafePoint) { if (_phase->get_loop(n) != this) { if (_required_safept == nullptr) _required_safept = new Node_List(); @@ -4444,7 +4449,12 @@ void IdealLoopTree::check_safepts(VectorSet &visited, Node_List &stack) { if (!_irreducible) { // Scan the dom-path nodes from tail to head for (Node* n = tail(); n != _head; n = _phase->idom(n)) { - if (n->is_Call() && n->as_Call()->guaranteed_safepoint()) { + // Boxing CallStaticJava calls are excluded as they may lack a safepoint on the fast path. This is + // not done via CallStaticJavaNode::guaranteed_safepoint() as that also controls PcDesc emission. + // In the future, guaranteed_safepoint() should be reworked to correctly handle boxing methods + // to avoid this additional check. + if (n->is_Call() && n->as_Call()->guaranteed_safepoint() + && !(n->is_CallStaticJava() && n->as_CallStaticJava()->is_boxing_method())) { has_call = true; _has_sfpt = 1; // Then no need for a safept! break; diff --git a/test/hotspot/jtreg/compiler/loopopts/TestBoxingInfiniteLoopBrokenIf.java b/test/hotspot/jtreg/compiler/loopopts/TestBoxingInfiniteLoopBrokenIf.java new file mode 100644 index 00000000000..18b4816445b --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/TestBoxingInfiniteLoopBrokenIf.java @@ -0,0 +1,88 @@ +/* + * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 8378005 + * @summary Verify that an infinite loop with boxing does not crash when the containing If is broken + * @library /test/lib / + * @run driver ${test.main.class} + */ + +package compiler.loopopts; +import compiler.lib.ir_framework.*; +import jdk.test.lib.Utils; + +public class TestBoxingInfiniteLoopBrokenIf { + static boolean flag; + static volatile boolean testReturned; + + public static void main(String[] args) { + TestFramework framework = new TestFramework(); + framework.addScenarios( + new Scenario(0), + new Scenario(1, "-XX:PerMethodTrapLimit=0", "-XX:CompileCommand=dontinline,*::valueOf", "-XX:CompileCommand=dontinline,*::throwWrongPath"), + new Scenario(2, "-XX:PerMethodTrapLimit=0", "-XX:CompileCommand=dontinline,*::valueOf", "-XX:CompileCommand=dontinline,*::throwWrongPath", + "-XX:+IgnoreUnrecognizedVMOptions", "-XX:StressLongCountedLoop=1") + ); + framework.start(); + } + + @Test + static void test() { + new Integer(0); // Enable EA + Loop opts + + if (flag) { // Always false + throwWrongPath(); // Not inlined to simplify graph + } else { + // Infinite loop: j is always 0, Integer.valueOf(0) < 1 is always true. + for (int j = 0; Integer.valueOf(j) < 1;) { + j = 0; + } + } + } + + @Run(test = "test") + @Warmup(0) + static void runTest(RunInfo info) { + testReturned = false; + Thread thread = new Thread(() -> { + test(); + testReturned = true; + }); + thread.setDaemon(true); + thread.start(); + try { + Thread.sleep(Utils.adjustTimeout(500)); + } catch (InterruptedException e) { + } + if (testReturned) { + throw new RuntimeException("test() should not return: infinite loop was incorrectly optimized away"); + } + } + + static void throwWrongPath() { + throw new RuntimeException("Wrong path"); + } +} diff --git a/test/hotspot/jtreg/compiler/loopopts/TestStressLongCountedLoopInfiniteLoop.java b/test/hotspot/jtreg/compiler/loopopts/TestStressLongCountedLoopInfiniteLoop.java new file mode 100644 index 00000000000..81996018a2b --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/TestStressLongCountedLoopInfiniteLoop.java @@ -0,0 +1,75 @@ +/* + * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 8378005 + * @summary assert in proj_out when StressLongCountedLoop converts infinite loop to long counted loop nest + * @run main ${test.main.class} + * @run main/othervm -Xbatch -XX:-TieredCompilation -XX:+IgnoreUnrecognizedVMOptions -XX:StressLongCountedLoop=1 + * -XX:CompileCommand=compileonly,${test.main.class}::test ${test.main.class} + */ + +package compiler.loopopts; + +public class TestStressLongCountedLoopInfiniteLoop { + static int RANGE; + + public static void main(String[] args) { + int[] a = new int[RANGE]; + for (int i = 0; i < 10000; i++) { + try { + test(a, 0); + } catch (ArrayIndexOutOfBoundsException e) { + } + } + } + + static void test(int[] a, int invar) { + // new Integer(0) works too, using MyInteger to avoid deprecation warnings. + a[new MyInteger(0).v()] = 0; + + Object o; + for (int i = 0; i < 1; i++) { + o = 1; + } + + // Infinite loop: j is always 0, 0 < 1 is always true. + for (int j = 0; Integer.valueOf(j) < 1;) { + j = 0; + } + } + + static class MyInteger { + int v; + + MyInteger(int v) { + this.v = v; + } + + int v() { + return Integer.valueOf(v); + } + } +} From 8ecb14cecf1f05ea7c65fcfb5bb05e1e3a895d72 Mon Sep 17 00:00:00 2001 From: Yasumasa Suenaga Date: Thu, 26 Mar 2026 14:50:56 +0000 Subject: [PATCH 012/116] 8379454: SA still calculates end address with incorrect alignment Reviewed-by: kevinw, cjplummer --- src/jdk.hotspot.agent/linux/native/libsaproc/libproc_impl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/jdk.hotspot.agent/linux/native/libsaproc/libproc_impl.c b/src/jdk.hotspot.agent/linux/native/libsaproc/libproc_impl.c index e2681be73fe..029aac1f107 100644 --- a/src/jdk.hotspot.agent/linux/native/libsaproc/libproc_impl.c +++ b/src/jdk.hotspot.agent/linux/native/libsaproc/libproc_impl.c @@ -182,13 +182,14 @@ static bool fill_addr_info(lib_info* lib) { return false; } + long page_size = sysconf(_SC_PAGE_SIZE); lib->end = (uintptr_t)-1L; lib->exec_start = (uintptr_t)-1L; lib->exec_end = (uintptr_t)-1L; for (ph = phbuf, cnt = 0; cnt < ehdr.e_phnum; cnt++, ph++) { if (ph->p_type == PT_LOAD) { uintptr_t aligned_start = lib->base + align_down(ph->p_vaddr, ph->p_align); - uintptr_t aligned_end = aligned_start + align_up(ph->p_memsz, ph->p_align); + uintptr_t aligned_end = aligned_start + align_up(ph->p_memsz, page_size); if ((lib->end == (uintptr_t)-1L) || (lib->end < aligned_end)) { lib->end = aligned_end; } From 541557ad1d9dfacc63490b5bd30e20455b0332c4 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Thu, 26 Mar 2026 17:19:50 +0000 Subject: [PATCH 013/116] 8380671: Refactor BasicFloat16ArithTests.java Reviewed-by: bpb --- .../vector/BasicFloat16ArithTests.java | 60 ++++++++++--------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/test/jdk/jdk/incubator/vector/BasicFloat16ArithTests.java b/test/jdk/jdk/incubator/vector/BasicFloat16ArithTests.java index 755745394fc..cdc7ce566f7 100644 --- a/test/jdk/jdk/incubator/vector/BasicFloat16ArithTests.java +++ b/test/jdk/jdk/incubator/vector/BasicFloat16ArithTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,6 +38,8 @@ public class BasicFloat16ArithTests { private static float NaNf = Float.NaN; private static final float MAX_VAL_FP16 = 0x1.ffcp15f; + private static final float MIN_NRM_FP16 = 0x1.0p-14f; + private static final float MIN_VAL_FP16 = 0x1.0p-24f; public static void main(String... args) { checkBitWise(); @@ -145,9 +147,9 @@ private static void checkConstants() { checkInt(PRECISION, 11, "Float16.PRECISION"); checkInt(SIZE, 16, "Float16.SIZE"); - checkFloat16(MIN_VALUE, 0x1.0p-24f, "Float16.MIN_VALUE"); - checkFloat16(MIN_NORMAL, 0x1.0p-14f, "Float16.MIN_NORMAL"); - checkFloat16(MAX_VALUE, 65504.0f, "Float16.MAX_VALUE"); + checkFloat16(MIN_VALUE, MIN_VAL_FP16, "Float16.MIN_VALUE"); + checkFloat16(MIN_NORMAL, MIN_NRM_FP16, "Float16.MIN_NORMAL"); + checkFloat16(MAX_VALUE, 65504.0f, "Float16.MAX_VALUE"); checkFloat16(POSITIVE_INFINITY, InfinityF, "+infinity"); checkFloat16(NEGATIVE_INFINITY, -InfinityF, "-infinity"); @@ -389,12 +391,12 @@ private static void checkGetExponent() { { NaNf, MAX_EXPONENT + 1}, // Subnormal and almost subnormal values - {-0.0f, MIN_EXPONENT - 1}, - {+0.0f, MIN_EXPONENT - 1}, - { 0x1.0p-24f, MIN_EXPONENT - 1}, // Float16.MIN_VALUE - {-0x1.0p-24f, MIN_EXPONENT - 1}, // Float16.MIN_VALUE - { 0x1.0p-14f, MIN_EXPONENT}, // Float16.MIN_NORMAL - {-0x1.0p-14f, MIN_EXPONENT}, // Float16.MIN_NORMAL + {-0.0f, MIN_EXPONENT - 1}, + {+0.0f, MIN_EXPONENT - 1}, + { MIN_VAL_FP16, MIN_EXPONENT - 1}, + {-MIN_VAL_FP16, MIN_EXPONENT - 1}, + { MIN_NRM_FP16, MIN_EXPONENT}, + {-MIN_NRM_FP16, MIN_EXPONENT}, // Normal values { 1.0f, 0}, @@ -424,17 +426,17 @@ private static void checkUlp() { { NaNf, NaNf}, // Zeros, subnormals, and MIN_VALUE all have MIN_VALUE as an ulp. - {-0.0f, 0x1.0p-24f}, - {+0.0f, 0x1.0p-24f}, - { 0x1.0p-24f, 0x1.0p-24f}, - {-0x1.0p-24f, 0x1.0p-24f}, - { 0x1.0p-14f, 0x1.0p-24f}, - {-0x1.0p-14f, 0x1.0p-24f}, - - // ulp is 10 bits away - {0x1.0p0f, 0x0.004p0f}, // 1.0f - {0x1.0p1f, 0x0.004p1f}, // 2.0f - {0x1.0p2f, 0x0.004p2f}, // 4.0f + {-0.0f, MIN_VAL_FP16}, + {+0.0f, MIN_VAL_FP16}, + { MIN_VAL_FP16, MIN_VAL_FP16}, + {-MIN_VAL_FP16, MIN_VAL_FP16}, + { MIN_NRM_FP16, MIN_VAL_FP16}, + {-MIN_NRM_FP16, MIN_VAL_FP16}, + + // ulp is (PRECISION - 1) = 10 bits away + {0x1.0p0f, 0x1.0p-10f}, // 1.0f + {0x1.0p1f, 0x1.0p-9f}, // 2.0f + {0x1.0p2f, 0x1.0p-8f}, // 4.0f {MAX_VAL_FP16*0.5f, 0x0.004p14f}, {MAX_VAL_FP16, 0x0.004p15f}, @@ -507,12 +509,12 @@ private static void checkValueOfDouble() { } private static void checkValueOfLong() { - checkFloat16(valueOf(-65_521), Float.NEGATIVE_INFINITY, "-infinity"); - checkFloat16(valueOf(-65_520), Float.NEGATIVE_INFINITY, "-infinity"); - checkFloat16(valueOf(-65_519), -MAX_VALUE.floatValue(), "-MAX_VALUE"); - checkFloat16(valueOf(65_519), MAX_VALUE.floatValue(), "MAX_VALUE"); - checkFloat16(valueOf(65_520), Float.POSITIVE_INFINITY, "+infinity"); - checkFloat16(valueOf(65_521), Float.POSITIVE_INFINITY, "+infinity"); + checkFloat16(valueOf(-65_521), Float.NEGATIVE_INFINITY, "-65_521"); + checkFloat16(valueOf(-65_520), Float.NEGATIVE_INFINITY, "-65_520"); + checkFloat16(valueOf(-65_519), -MAX_VALUE.floatValue(), "-65_519"); + checkFloat16(valueOf( 65_519), MAX_VALUE.floatValue(), "65_519"); + checkFloat16(valueOf( 65_520), Float.POSITIVE_INFINITY, "65_520"); + checkFloat16(valueOf( 65_521), Float.POSITIVE_INFINITY, "65_521"); } private static void checkValueOfString() { @@ -792,7 +794,7 @@ private static void testRounding() { // threshold; subtracting a non-zero finite value will // result in MAX_VALUE, adding zero or a positive // value will overflow. - {0x1.2p10f, 0x1.c7p5f, -0x1.0p-14f, + {0x1.2p10f, 0x1.c7p5f, -MIN_NRM_FP16, MAX_VAL_FP16}, {0x1.2p10f, 0x1.c7p5f, -0.0f, @@ -801,7 +803,7 @@ private static void testRounding() { {0x1.2p10f, 0x1.c7p5f, +0.0f, InfinityF}, - {0x1.2p10f, 0x1.c7p5f, +0x1.0p-14f, + {0x1.2p10f, 0x1.c7p5f, +MIN_NRM_FP16, InfinityF}, {0x1.2p10f, 0x1.c7p5f, InfinityF, From aecc16358f5f1f6fa5cb78522d6db70430b79987 Mon Sep 17 00:00:00 2001 From: Naoto Sato Date: Thu, 26 Mar 2026 17:53:53 +0000 Subject: [PATCH 014/116] 8230421: Java cannot handle Euro sign at the Simplified Chinese Windows Command Prompt Reviewed-by: sherman --- .../windows/native/libjava/java_props_md.c | 67 +++++++++---------- 1 file changed, 32 insertions(+), 35 deletions(-) diff --git a/src/java.base/windows/native/libjava/java_props_md.c b/src/java.base/windows/native/libjava/java_props_md.c index e152dbe9bef..6504891af34 100644 --- a/src/java.base/windows/native/libjava/java_props_md.c +++ b/src/java.base/windows/native/libjava/java_props_md.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -74,43 +74,32 @@ getEncodingInternal(LCID lcid) case 65001: strcpy(ret, "UTF-8"); break; - case 874: /* 9:Thai */ - case 932: /* 10:Japanese */ - case 949: /* 12:Korean Extended Wansung */ - case 950: /* 13:Chinese (Taiwan, Hongkong, Macau) */ - case 1361: /* 15:Korean Johab */ + case 874: /* Thai */ + case 932: /* Japanese */ + case 936: /* Chinese (Simplified) */ + case 949: /* Korean Extended Wansung */ + case 950: /* Chinese (Taiwan, Hongkong, Macau) */ + case 1361: /* Korean Johab */ ret[0] = 'M'; ret[1] = 'S'; - break; - case 936: - strcpy(ret, "GBK"); - break; - case 54936: - strcpy(ret, "GB18030"); - break; - default: - ret[0] = 'C'; - ret[1] = 'p'; - break; - } - //Traditional Chinese Windows should use MS950_HKSCS_XP as the - //default encoding, if HKSCS patch has been installed. - // "old" MS950 0xfa41 -> u+e001 - // "new" MS950 0xfa41 -> u+92db - if (strcmp(ret, "MS950") == 0) { - TCHAR mbChar[2] = {(char)0xfa, (char)0x41}; - WCHAR unicodeChar; - MultiByteToWideChar(CP_ACP, 0, mbChar, 2, &unicodeChar, 1); - if (unicodeChar == 0x92db) { - strcpy(ret, "MS950_HKSCS_XP"); - } - } else { - //SimpChinese Windows should use GB18030 as the default - //encoding, if gb18030 patch has been installed (on windows - //2000/XP, (1)Codepage 54936 will be available - //(2)simsun18030.ttc will exist under system fonts dir ) - if (strcmp(ret, "GBK") == 0 && IsValidCodePage(54936)) { + // Special handling for Chinese + if (codepage == 950) { + //Traditional Chinese Windows should use MS950_HKSCS_XP as the + //default encoding, if HKSCS patch has been installed. + // "old" MS950 0xfa41 -> u+e001 + // "new" MS950 0xfa41 -> u+92db + TCHAR mbChar[2] = {(char)0xfa, (char)0x41}; + WCHAR unicodeChar; + MultiByteToWideChar(CP_ACP, 0, mbChar, 2, &unicodeChar, 1); + if (unicodeChar == 0x92db) { + strcpy(ret, "MS950_HKSCS_XP"); + } + } else if (codepage == 936 && IsValidCodePage(54936)) { + //SimpChinese Windows should use GB18030 as the default + //encoding, if gb18030 patch has been installed (on windows + //2000/XP, (1)Codepage 54936 will be available + //(2)simsun18030.ttc will exist under system fonts dir ) char systemPath[MAX_PATH + 1]; char* gb18030Font = "\\FONTS\\SimSun18030.ttc"; FILE *f = NULL; @@ -123,6 +112,14 @@ getEncodingInternal(LCID lcid) } } } + break; + case 54936: + strcpy(ret, "GB18030"); + break; + default: + ret[0] = 'C'; + ret[1] = 'p'; + break; } return ret; From 72176305ae24e4e0c8f6541b229c16cae81e4775 Mon Sep 17 00:00:00 2001 From: Leo Korinth Date: Thu, 26 Mar 2026 18:16:17 +0000 Subject: [PATCH 015/116] 8379346: Cleanup casts and implicit conversions to boolean Reviewed-by: stefank, dholmes, ayang --- src/hotspot/os/linux/hugepages.cpp | 4 ++-- src/hotspot/os/linux/os_linux.cpp | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/hotspot/os/linux/hugepages.cpp b/src/hotspot/os/linux/hugepages.cpp index 1340c470dff..213845c7134 100644 --- a/src/hotspot/os/linux/hugepages.cpp +++ b/src/hotspot/os/linux/hugepages.cpp @@ -68,7 +68,7 @@ static size_t scan_default_hugepagesize() { // format has been changed), we'll set largest page size to 0 FILE *fp = os::fopen("/proc/meminfo", "r"); - if (fp) { + if (fp != nullptr) { while (!feof(fp)) { int x = 0; char buf[16]; @@ -81,7 +81,7 @@ static size_t scan_default_hugepagesize() { // skip to next line for (;;) { int ch = fgetc(fp); - if (ch == EOF || ch == (int)'\n') break; + if (ch == EOF || ch == '\n') break; } } } diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index c79b0ab9fb5..bf096897aa7 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -1313,7 +1313,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 = os::fopen("/proc/self/maps", "r"); - if (fp) { + if (fp != nullptr) { address low, high; while (!feof(fp)) { if (fscanf(fp, "%p-%p", &low, &high) == 2) { @@ -1326,7 +1326,7 @@ static bool find_vma(address addr, address* vma_low, address* vma_high) { } for (;;) { int ch = fgetc(fp); - if (ch == EOF || ch == (int)'\n') break; + if (ch == EOF || ch == '\n') break; } } fclose(fp); @@ -4384,7 +4384,7 @@ int os::Linux::get_namespace_pid(int vmid) { os::snprintf_checked(fname, sizeof(fname), "/proc/%d/status", vmid); FILE *fp = os::fopen(fname, "r"); - if (fp) { + if (fp != nullptr) { int pid, nspid; int ret; while (!feof(fp) && !ferror(fp)) { @@ -4398,7 +4398,7 @@ int os::Linux::get_namespace_pid(int vmid) { } for (;;) { int ch = fgetc(fp); - if (ch == EOF || ch == (int)'\n') break; + if (ch == EOF || ch == '\n') break; } } fclose(fp); From c5c5340b521151b9dac44cc72899ef31c2d812cb Mon Sep 17 00:00:00 2001 From: Leo Korinth Date: Thu, 26 Mar 2026 18:37:45 +0000 Subject: [PATCH 016/116] 8379224: Always use zero as invalid page size Reviewed-by: stefank, ayang --- src/hotspot/os/linux/hugepages.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/hotspot/os/linux/hugepages.cpp b/src/hotspot/os/linux/hugepages.cpp index 213845c7134..b065f7b1496 100644 --- a/src/hotspot/os/linux/hugepages.cpp +++ b/src/hotspot/os/linux/hugepages.cpp @@ -35,7 +35,7 @@ #include ExplicitHugePageSupport::ExplicitHugePageSupport() : - _initialized{false}, _os_supported{}, _pre_allocated{}, _default_hugepage_size{SIZE_MAX}, _inconsistent{false} {} + _initialized{false}, _os_supported{}, _pre_allocated{}, _default_hugepage_size{0}, _inconsistent{false} {} os::PageSizes ExplicitHugePageSupport::os_supported() const { assert(_initialized, "Not initialized"); @@ -187,7 +187,7 @@ void ExplicitHugePageSupport::scan_os() { } THPSupport::THPSupport() : - _initialized(false), _mode(THPMode::never), _pagesize(SIZE_MAX) {} + _initialized{false}, _mode{THPMode::never}, _pagesize{0} {} THPMode THPSupport::mode() const { @@ -221,7 +221,6 @@ void THPSupport::scan_os() { } // Scan large page size for THP from hpage_pmd_size - _pagesize = 0; if (read_number_file("/sys/kernel/mm/transparent_hugepage/hpage_pmd_size", &_pagesize)) { assert(_pagesize > 0, "Expected"); } From 40d65f1063a27b081b4c074b04192eb2fcf5dd6a Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Thu, 26 Mar 2026 18:38:04 +0000 Subject: [PATCH 017/116] 8379583: (fs) Files.copy use of posix_fadvise is problematic on Linux Reviewed-by: alanb --- .../classes/sun/nio/fs/LinuxFileSystem.java | 12 +--- .../sun/nio/fs/UnixConstants.java.template | 4 +- .../bench/java/nio/file/FilesCopy.java | 68 +++++++++++++++++++ 3 files changed, 72 insertions(+), 12 deletions(-) create mode 100644 test/micro/org/openjdk/bench/java/nio/file/FilesCopy.java diff --git a/src/java.base/linux/classes/sun/nio/fs/LinuxFileSystem.java b/src/java.base/linux/classes/sun/nio/fs/LinuxFileSystem.java index 44e957f54fb..ec3e135b8b1 100644 --- a/src/java.base/linux/classes/sun/nio/fs/LinuxFileSystem.java +++ b/src/java.base/linux/classes/sun/nio/fs/LinuxFileSystem.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -139,10 +139,7 @@ void bufferedCopy(int dst, int src, long address, int size, long addressToPollForCancel) throws UnixException { - int advice = POSIX_FADV_SEQUENTIAL | // sequential data access - POSIX_FADV_NOREUSE | // will access only once - POSIX_FADV_WILLNEED; // will access in near future - posix_fadvise(src, 0, 0, advice); + posix_fadvise(src, 0, 0, POSIX_FADV_SEQUENTIAL); super.bufferedCopy(dst, src, address, size, addressToPollForCancel); } @@ -151,10 +148,7 @@ void bufferedCopy(int dst, int src, long address, int directCopy(int dst, int src, long addressToPollForCancel) throws UnixException { - int advice = POSIX_FADV_SEQUENTIAL | // sequential data access - POSIX_FADV_NOREUSE | // will access only once - POSIX_FADV_WILLNEED; // will access in near future - posix_fadvise(src, 0, 0, advice); + posix_fadvise(src, 0, 0, POSIX_FADV_SEQUENTIAL); return directCopy0(dst, src, addressToPollForCancel); } diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixConstants.java.template b/src/java.base/unix/classes/sun/nio/fs/UnixConstants.java.template index 6823833582f..7a9a22ac40d 100644 --- a/src/java.base/unix/classes/sun/nio/fs/UnixConstants.java.template +++ b/src/java.base/unix/classes/sun/nio/fs/UnixConstants.java.template @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -173,7 +173,5 @@ class UnixConstants { #ifdef __linux__ // advice flags used with posix_fadvise(2) static final int PREFIX_POSIX_FADV_SEQUENTIAL = POSIX_FADV_SEQUENTIAL; - static final int PREFIX_POSIX_FADV_NOREUSE = POSIX_FADV_NOREUSE; - static final int PREFIX_POSIX_FADV_WILLNEED = POSIX_FADV_WILLNEED; #endif } diff --git a/test/micro/org/openjdk/bench/java/nio/file/FilesCopy.java b/test/micro/org/openjdk/bench/java/nio/file/FilesCopy.java new file mode 100644 index 00000000000..9472920f071 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/nio/file/FilesCopy.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.nio.file; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; +import java.nio.file.Files; +import java.nio.file.Path; +import static java.nio.file.StandardOpenOption.*; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; + +@State(Scope.Benchmark) +public class FilesCopy { + + private static final int SIZE = Integer.MAX_VALUE; + private static final Path FILE = Path.of("file.dat"); + private static final Path COPY = Path.of("copy.dat"); + + @Setup + public void init() throws IOException { + Files.deleteIfExists(FILE); + Files.deleteIfExists(COPY); + try (FileChannel fc = FileChannel.open(FILE, CREATE_NEW, READ, WRITE)) { + fc.position(SIZE); + fc.write(ByteBuffer.wrap(new byte[] {(byte)27})); + } + } + + @TearDown + public void cleanup() throws IOException { + Files.deleteIfExists(FILE); + Files.deleteIfExists(COPY); + } + + @Benchmark + public void copyFile() throws IOException { + Files.copy(FILE, COPY); + Files.delete(COPY); + } + +} From 68c48290d63675d82f2e9e60241031de023c280f Mon Sep 17 00:00:00 2001 From: Kelvin Nilsen Date: Thu, 26 Mar 2026 20:04:13 +0000 Subject: [PATCH 018/116] 8380459: Shenandoah: Do not reset bytes-allocated-since-gc-start when degenerating Reviewed-by: wkemper --- src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp | 5 ++++- .../gc/shenandoah/shenandoahGenerationalControlThread.cpp | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp b/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp index 48183507124..4c6e82c86a5 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp @@ -138,7 +138,10 @@ void ShenandoahControlThread::run_service() { heuristics->cancel_trigger_request(); - heap->reset_bytes_allocated_since_gc_start(); + if (mode != stw_degenerated) { + // If mode is stw_degenerated, count bytes allocated from the start of the conc GC that experienced alloc failure. + heap->reset_bytes_allocated_since_gc_start(); + } MetaspaceCombinedStats meta_sizes = MetaspaceUtils::get_combined_statistics(); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp index 67cc4d2f703..ec33e671053 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp @@ -255,7 +255,8 @@ void ShenandoahGenerationalControlThread::run_gc_cycle(const ShenandoahGCRequest GCIdMark gc_id_mark; - if (gc_mode() != servicing_old) { + if ((gc_mode() != servicing_old) && (gc_mode() != stw_degenerated)) { + // If mode is stw_degenerated, count bytes allocated from the start of the conc GC that experienced alloc failure. _heap->reset_bytes_allocated_since_gc_start(); } From 91892948ee0ac3c62bbddbbf9e6f99e746f3d72f Mon Sep 17 00:00:00 2001 From: Damon Nguyen Date: Thu, 26 Mar 2026 20:21:19 +0000 Subject: [PATCH 019/116] 8380229: 2 Impossible or redundant condition defect groups in 2 files Reviewed-by: honkar, prr --- .../share/native/libharfbuzz/hb-aat-layout-common.hh | 3 +-- .../share/native/libharfbuzz/hb-ot-layout-common.hh | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-common.hh b/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-common.hh index d2ce32616be..4bb41fd0189 100644 --- a/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-common.hh +++ b/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-common.hh @@ -1266,8 +1266,7 @@ struct StateTableDriver next_state == StateTableT::STATE_START_OF_TEXT && start_state_safe_to_break_eot && is_not_actionable && - is_not_epsilon_transition && - !last_range; + is_not_epsilon_transition; if (is_null_transition) { diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-common.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-common.hh index dcacc9cb86c..6b62732bf54 100644 --- a/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-common.hh +++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-common.hh @@ -2480,7 +2480,7 @@ struct VarRegionAxis /* TODO Move these to sanitize(). */ if (unlikely (start > peak || peak > end)) return 1.f; - if (unlikely (start < 0 && end > 0 && peak != 0)) + if (unlikely (start < 0 && end > 0)) return 1.f; if (coord <= start || end <= coord) From 4d2623757fbe8c9fa8c22817a993ca85a2403873 Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Thu, 26 Mar 2026 20:59:45 +0000 Subject: [PATCH 020/116] 8359433: The final modifier on Windows L&F internal UI classes prevents extending them in apps Reviewed-by: prr, aivanov --- .../java/swing/plaf/windows/WindowsBorders.java | 8 ++++---- .../java/swing/plaf/windows/WindowsButtonUI.java | 2 +- .../plaf/windows/WindowsCheckBoxMenuItemUI.java | 4 ++-- .../java/swing/plaf/windows/WindowsCheckBoxUI.java | 2 +- .../plaf/windows/WindowsClassicLookAndFeel.java | 4 ++-- .../java/swing/plaf/windows/WindowsComboBoxUI.java | 10 +++++----- .../swing/plaf/windows/WindowsDesktopIconUI.java | 4 ++-- .../swing/plaf/windows/WindowsDesktopManager.java | 4 ++-- .../swing/plaf/windows/WindowsDesktopPaneUI.java | 4 ++-- .../swing/plaf/windows/WindowsEditorPaneUI.java | 4 ++-- .../swing/plaf/windows/WindowsFileChooserUI.java | 14 +++++++------- .../windows/WindowsInternalFrameTitlePane.java | 8 ++++---- .../swing/plaf/windows/WindowsInternalFrameUI.java | 4 ++-- .../java/swing/plaf/windows/WindowsLabelUI.java | 2 +- .../java/swing/plaf/windows/WindowsMenuBarUI.java | 4 ++-- .../java/swing/plaf/windows/WindowsMenuItemUI.java | 2 +- .../sun/java/swing/plaf/windows/WindowsMenuUI.java | 6 +++--- .../swing/plaf/windows/WindowsOptionPaneUI.java | 4 ++-- .../swing/plaf/windows/WindowsPasswordFieldUI.java | 4 ++-- .../plaf/windows/WindowsPopupMenuSeparatorUI.java | 4 ++-- .../swing/plaf/windows/WindowsPopupMenuUI.java | 4 ++-- .../swing/plaf/windows/WindowsProgressBarUI.java | 4 ++-- .../plaf/windows/WindowsRadioButtonMenuItemUI.java | 4 ++-- .../java/swing/plaf/windows/WindowsRootPaneUI.java | 4 ++-- .../swing/plaf/windows/WindowsScrollBarUI.java | 4 ++-- .../swing/plaf/windows/WindowsScrollPaneUI.java | 4 ++-- .../swing/plaf/windows/WindowsSeparatorUI.java | 4 ++-- .../java/swing/plaf/windows/WindowsSliderUI.java | 4 ++-- .../java/swing/plaf/windows/WindowsSpinnerUI.java | 4 ++-- .../plaf/windows/WindowsSplitPaneDivider.java | 4 ++-- .../swing/plaf/windows/WindowsSplitPaneUI.java | 4 ++-- .../swing/plaf/windows/WindowsTabbedPaneUI.java | 4 ++-- .../swing/plaf/windows/WindowsTableHeaderUI.java | 4 ++-- .../java/swing/plaf/windows/WindowsTextAreaUI.java | 4 ++-- .../swing/plaf/windows/WindowsTextFieldUI.java | 4 ++-- .../java/swing/plaf/windows/WindowsTextPaneUI.java | 4 ++-- .../swing/plaf/windows/WindowsToggleButtonUI.java | 2 +- .../plaf/windows/WindowsToolBarSeparatorUI.java | 4 ++-- .../java/swing/plaf/windows/WindowsToolBarUI.java | 4 ++-- .../sun/java/swing/plaf/windows/WindowsTreeUI.java | 6 +++--- test/jdk/javax/swing/plaf/windows/bug4991587.java | 4 ++-- 41 files changed, 91 insertions(+), 91 deletions(-) diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsBorders.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsBorders.java index 81766db8116..572e9e8c117 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsBorders.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsBorders.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -115,7 +115,7 @@ public static Border getInternalFrameBorder() { } @SuppressWarnings("serial") // Superclass is not serializable across versions - public static final class ProgressBarBorder extends AbstractBorder implements UIResource { + public static class ProgressBarBorder extends AbstractBorder implements UIResource { protected Color shadow; protected Color highlight; @@ -148,7 +148,7 @@ public Insets getBorderInsets(Component c, Insets insets) { * @since 1.4 */ @SuppressWarnings("serial") // Superclass is not serializable across versions - public static final class ToolBarBorder extends AbstractBorder implements UIResource, SwingConstants { + public static class ToolBarBorder extends AbstractBorder implements UIResource, SwingConstants { protected Color shadow; protected Color highlight; @@ -308,7 +308,7 @@ public void paintBorder(Component c, Graphics g, int x, int y, int width, int he * @since 1.4 */ @SuppressWarnings("serial") // Superclass is not serializable across versions - public static final class InternalFrameLineBorder extends LineBorder implements + public static class InternalFrameLineBorder extends LineBorder implements UIResource { protected Color activeColor; protected Color inactiveColor; diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsButtonUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsButtonUI.java index ee07276aa30..63e99e0804a 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsButtonUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsButtonUI.java @@ -56,7 +56,7 @@ * * @author Jeff Dinkins */ -public final class WindowsButtonUI extends BasicButtonUI +public class WindowsButtonUI extends BasicButtonUI { protected int dashedRectGapX; protected int dashedRectGapY; diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxMenuItemUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxMenuItemUI.java index 3a2578b3e0b..47e311486ba 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxMenuItemUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxMenuItemUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,7 +42,7 @@ /** * Windows check box menu item. */ -public final class WindowsCheckBoxMenuItemUI extends BasicCheckBoxMenuItemUI { +public class WindowsCheckBoxMenuItemUI extends BasicCheckBoxMenuItemUI { final WindowsMenuItemUIAccessor accessor = new WindowsMenuItemUIAccessor() { diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxUI.java index 7cb2490fd76..d264393f4d8 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxUI.java @@ -35,7 +35,7 @@ * * @author Jeff Dinkins */ -public final class WindowsCheckBoxUI extends WindowsRadioButtonUI +public class WindowsCheckBoxUI extends WindowsRadioButtonUI { // NOTE: WindowsCheckBoxUI inherits from WindowsRadioButtonUI instead // of BasicCheckBoxUI because we want to pick up all the diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsClassicLookAndFeel.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsClassicLookAndFeel.java index 5716a875cd7..802b5f66888 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsClassicLookAndFeel.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsClassicLookAndFeel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,7 +31,7 @@ * @since 1.5 */ @SuppressWarnings("serial") // Superclass is not serializable across versions -public final class WindowsClassicLookAndFeel extends WindowsLookAndFeel { +public class WindowsClassicLookAndFeel extends WindowsLookAndFeel { @Override public String getName() { return "Windows Classic"; diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsComboBoxUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsComboBoxUI.java index fdc9b03ae7d..8717fd715ea 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsComboBoxUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsComboBoxUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -75,7 +75,7 @@ * @author Tom Santos * @author Igor Kushnirskiy */ -public final class WindowsComboBoxUI extends BasicComboBoxUI { +public class WindowsComboBoxUI extends BasicComboBoxUI { private static final MouseListener rolloverListener = new MouseAdapter() { @@ -532,7 +532,7 @@ WindowsComboBoxUI getWindowsComboBoxUI() { } @SuppressWarnings("serial") // Same-version serialization only - protected final class WinComboPopUp extends BasicComboPopup { + protected class WinComboPopUp extends BasicComboPopup { private Skin listBoxBorder = null; private XPStyle xp; @@ -550,7 +550,7 @@ protected KeyListener createKeyListener() { return new InvocationKeyHandler(); } - protected final class InvocationKeyHandler extends BasicComboPopup.InvocationKeyHandler { + protected class InvocationKeyHandler extends BasicComboPopup.InvocationKeyHandler { protected InvocationKeyHandler() { WinComboPopUp.this.super(); } @@ -570,7 +570,7 @@ protected void paintComponent(Graphics g) { /** * Subclassed to highlight selected item in an editable combo box. */ - public static final class WindowsComboBoxEditor + public static class WindowsComboBoxEditor extends BasicComboBoxEditor.UIResource { /** diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsDesktopIconUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsDesktopIconUI.java index 47ecdf5747b..2cebb050396 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsDesktopIconUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsDesktopIconUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,7 +36,7 @@ /** * Windows icon for a minimized window on the desktop. */ -public final class WindowsDesktopIconUI extends BasicDesktopIconUI { +public class WindowsDesktopIconUI extends BasicDesktopIconUI { private int width; public static ComponentUI createUI(JComponent c) { diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsDesktopManager.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsDesktopManager.java index 79d81bad089..ae081a7690c 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsDesktopManager.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsDesktopManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -52,7 +52,7 @@ * @author Thomas Ball */ @SuppressWarnings("serial") // JDK-implementation class -public final class WindowsDesktopManager extends DefaultDesktopManager +public class WindowsDesktopManager extends DefaultDesktopManager implements java.io.Serializable, javax.swing.plaf.UIResource { /* The frame which is currently selected/activated. diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsDesktopPaneUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsDesktopPaneUI.java index dabbe3fb992..4a3f0ec38b1 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsDesktopPaneUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsDesktopPaneUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,7 +34,7 @@ * * @author David Kloba */ -public final class WindowsDesktopPaneUI extends BasicDesktopPaneUI +public class WindowsDesktopPaneUI extends BasicDesktopPaneUI { public static ComponentUI createUI(JComponent c) { return new WindowsDesktopPaneUI(); diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsEditorPaneUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsEditorPaneUI.java index 44cb0e9634c..ea21b41c619 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsEditorPaneUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsEditorPaneUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,7 +33,7 @@ /** * Windows rendition of the component. */ -public final class WindowsEditorPaneUI extends BasicEditorPaneUI +public class WindowsEditorPaneUI extends BasicEditorPaneUI { /** diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsFileChooserUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsFileChooserUI.java index 08c01760be9..86c40ea70d6 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsFileChooserUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsFileChooserUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -101,7 +101,7 @@ * * @author Jeff Dinkins */ -public final class WindowsFileChooserUI extends BasicFileChooserUI { +public class WindowsFileChooserUI extends BasicFileChooserUI { // The following are private because the implementation of the // Windows FileChooser L&F is not complete yet. @@ -1122,7 +1122,7 @@ protected DirectoryComboBoxModel createDirectoryComboBoxModel(JFileChooser fc) { * Data model for a type-face selection combo-box. */ @SuppressWarnings("serial") // Superclass is not serializable across versions - protected final class DirectoryComboBoxModel extends AbstractListModel implements ComboBoxModel { + protected class DirectoryComboBoxModel extends AbstractListModel implements ComboBoxModel { Vector directories = new Vector(); int[] depths = null; File selectedDirectory = null; @@ -1252,7 +1252,7 @@ protected FilterComboBoxRenderer createFilterComboBoxRenderer() { * Render different type sizes and styles. */ @SuppressWarnings("serial") // Superclass is not serializable across versions - public final class FilterComboBoxRenderer extends DefaultListCellRenderer { + public class FilterComboBoxRenderer extends DefaultListCellRenderer { @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, @@ -1279,7 +1279,7 @@ protected FilterComboBoxModel createFilterComboBoxModel() { * Data model for a type-face selection combo-box. */ @SuppressWarnings("serial") // Superclass is not serializable across versions - protected final class FilterComboBoxModel extends AbstractListModel implements ComboBoxModel, + protected class FilterComboBoxModel extends AbstractListModel implements ComboBoxModel, PropertyChangeListener { protected FileFilter[] filters; protected FilterComboBoxModel() { @@ -1362,7 +1362,7 @@ public void valueChanged(ListSelectionEvent e) { /** * Acts when DirectoryComboBox has changed the selected item. */ - protected final class DirectoryComboBoxAction implements ActionListener { + protected class DirectoryComboBoxAction implements ActionListener { @@ -1387,7 +1387,7 @@ public FileView getFileView(JFileChooser fc) { // *********************** // * FileView operations * // *********************** - protected final class WindowsFileView extends BasicFileView { + protected class WindowsFileView extends BasicFileView { /* FileView type descriptions */ @Override diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsInternalFrameTitlePane.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsInternalFrameTitlePane.java index ba4bde12122..029e139fe8f 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsInternalFrameTitlePane.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsInternalFrameTitlePane.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -418,7 +418,7 @@ protected LayoutManager createLayout() { return new WindowsTitlePaneLayout(); } - public final class WindowsTitlePaneLayout extends BasicInternalFrameTitlePane.TitlePaneLayout { + public class WindowsTitlePaneLayout extends BasicInternalFrameTitlePane.TitlePaneLayout { private Insets captionMargin = null; private Insets contentMargin = null; private XPStyle xp = XPStyle.getXP(); @@ -506,7 +506,7 @@ public void layoutContainer(Container c) { } } // end WindowsTitlePaneLayout - public final class WindowsPropertyChangeHandler extends PropertyChangeHandler { + public class WindowsPropertyChangeHandler extends PropertyChangeHandler { @Override public void propertyChange(PropertyChangeEvent evt) { String prop = evt.getPropertyName(); @@ -530,7 +530,7 @@ public void propertyChange(PropertyChangeEvent evt) { *

* Note: We assume here that icons are square. */ - public static final class ScalableIconUIResource implements Icon, UIResource { + public static class ScalableIconUIResource implements Icon, UIResource { // We can use an arbitrary size here because we scale to it in paintIcon() private static final int SIZE = 16; diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsInternalFrameUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsInternalFrameUI.java index 9db31ba38f9..6e76ac6a5b4 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsInternalFrameUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsInternalFrameUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,7 +45,7 @@ /** * Windows rendition of the component. */ -public final class WindowsInternalFrameUI extends BasicInternalFrameUI +public class WindowsInternalFrameUI extends BasicInternalFrameUI { XPStyle xp = XPStyle.getXP(); diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsLabelUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsLabelUI.java index 4283f743b97..c910b635491 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsLabelUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsLabelUI.java @@ -40,7 +40,7 @@ /** * Windows rendition of the component. */ -public final class WindowsLabelUI extends BasicLabelUI { +public class WindowsLabelUI extends BasicLabelUI { private static final ComponentUI UI = new WindowsLabelUI(); diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuBarUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuBarUI.java index 3d3cf5feee7..ac26dcbf425 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuBarUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuBarUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,7 +57,7 @@ /** * Windows rendition of the component. */ -public final class WindowsMenuBarUI extends BasicMenuBarUI +public class WindowsMenuBarUI extends BasicMenuBarUI { /* to be accessed on the EDT only */ private WindowListener windowListener = null; diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuItemUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuItemUI.java index d15bc93a628..d50540588fb 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuItemUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuItemUI.java @@ -58,7 +58,7 @@ * * @author Igor Kushnirskiy */ -public final class WindowsMenuItemUI extends BasicMenuItemUI { +public class WindowsMenuItemUI extends BasicMenuItemUI { /** * The instance of {@code PropertyChangeListener}. */ diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuUI.java index 259c32c74f4..78028db7c00 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,7 +50,7 @@ /** * Windows rendition of the component. */ -public final class WindowsMenuUI extends BasicMenuUI { +public class WindowsMenuUI extends BasicMenuUI { protected Integer menuBarHeight; protected boolean hotTrackingOn; @@ -283,7 +283,7 @@ protected MouseInputListener createMouseInputListener(JComponent c) { * true when the mouse enters the menu and false when it exits. * @since 1.4 */ - protected final class WindowsMouseInputHandler extends BasicMenuUI.MouseInputHandler { + protected class WindowsMouseInputHandler extends BasicMenuUI.MouseInputHandler { @Override public void mouseEntered(MouseEvent evt) { super.mouseEntered(evt); diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsOptionPaneUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsOptionPaneUI.java index 05c1b177705..3bed1856a55 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsOptionPaneUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsOptionPaneUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,5 +30,5 @@ /** * Windows rendition of the component. */ -public final class WindowsOptionPaneUI extends BasicOptionPaneUI { +public class WindowsOptionPaneUI extends BasicOptionPaneUI { } diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsPasswordFieldUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsPasswordFieldUI.java index 6adf6e402ec..0c30b291648 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsPasswordFieldUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsPasswordFieldUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,7 +33,7 @@ /** * Windows rendition of the component. */ -public final class WindowsPasswordFieldUI extends BasicPasswordFieldUI { +public class WindowsPasswordFieldUI extends BasicPasswordFieldUI { /** * Creates a UI for a JPasswordField diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsPopupMenuSeparatorUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsPopupMenuSeparatorUI.java index 576549ae482..f236c6b14fc 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsPopupMenuSeparatorUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsPopupMenuSeparatorUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,7 +42,7 @@ * @author Igor Kushnirskiy */ -public final class WindowsPopupMenuSeparatorUI extends BasicPopupMenuSeparatorUI { +public class WindowsPopupMenuSeparatorUI extends BasicPopupMenuSeparatorUI { public static ComponentUI createUI(JComponent c) { return new WindowsPopupMenuSeparatorUI(); diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsPopupMenuUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsPopupMenuUI.java index 1361286df4a..1c85cfebd94 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsPopupMenuUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsPopupMenuUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,7 +57,7 @@ * * @author Igor Kushnirskiy */ -public final class WindowsPopupMenuUI extends BasicPopupMenuUI { +public class WindowsPopupMenuUI extends BasicPopupMenuUI { static MnemonicListener mnemonicListener = null; static final Object GUTTER_OFFSET_KEY = diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsProgressBarUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsProgressBarUI.java index 9cc7d277ff1..5440b98cd1b 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsProgressBarUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsProgressBarUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,7 +51,7 @@ * * @author Michael C. Albers */ -public final class WindowsProgressBarUI extends BasicProgressBarUI +public class WindowsProgressBarUI extends BasicProgressBarUI { private Rectangle previousFullBox; diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonMenuItemUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonMenuItemUI.java index 78768c29ab3..2ec78341c2a 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonMenuItemUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonMenuItemUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,7 +42,7 @@ /** * Windows rendition of the component. */ -public final class WindowsRadioButtonMenuItemUI extends BasicRadioButtonMenuItemUI { +public class WindowsRadioButtonMenuItemUI extends BasicRadioButtonMenuItemUI { final WindowsMenuItemUIAccessor accessor = new WindowsMenuItemUIAccessor() { diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsRootPaneUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsRootPaneUI.java index 5e08dcf5605..d41fd9421e4 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsRootPaneUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsRootPaneUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -70,7 +70,7 @@ * @author Mark Davidson * @since 1.4 */ -public final class WindowsRootPaneUI extends BasicRootPaneUI { +public class WindowsRootPaneUI extends BasicRootPaneUI { private static final WindowsRootPaneUI windowsRootPaneUI = new WindowsRootPaneUI(); static final AltProcessor altProcessor = new AltProcessor(); diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsScrollBarUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsScrollBarUI.java index 04a9f2e97cf..2755f3543f1 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsScrollBarUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsScrollBarUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -55,7 +55,7 @@ /** * Windows rendition of the component. */ -public final class WindowsScrollBarUI extends BasicScrollBarUI { +public class WindowsScrollBarUI extends BasicScrollBarUI { private Grid thumbGrid; private Grid highlightGrid; private Dimension horizontalThumbSize; diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsScrollPaneUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsScrollPaneUI.java index 48e7a8c02fb..56b8eb1004e 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsScrollPaneUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsScrollPaneUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,5 +30,5 @@ /** * Windows rendition of the component. */ -public final class WindowsScrollPaneUI extends BasicScrollPaneUI +public class WindowsScrollPaneUI extends BasicScrollPaneUI {} diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsSeparatorUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsSeparatorUI.java index 2a2caef60d2..12eaa33872c 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsSeparatorUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsSeparatorUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,4 +30,4 @@ /** * Windows Separator. */ -public final class WindowsSeparatorUI extends BasicSeparatorUI { } +public class WindowsSeparatorUI extends BasicSeparatorUI { } diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsSliderUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsSliderUI.java index 731775a2575..cfc509babf4 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsSliderUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsSliderUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,7 +44,7 @@ /** * Windows rendition of the component. */ -public final class WindowsSliderUI extends BasicSliderUI +public class WindowsSliderUI extends BasicSliderUI { private boolean rollover = false; private boolean pressed = false; diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsSpinnerUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsSpinnerUI.java index a8e2a2ddcf1..8934bf9ff21 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsSpinnerUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsSpinnerUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,7 +37,7 @@ import static com.sun.java.swing.plaf.windows.XPStyle.Skin; -public final class WindowsSpinnerUI extends BasicSpinnerUI { +public class WindowsSpinnerUI extends BasicSpinnerUI { public static ComponentUI createUI(JComponent c) { return new WindowsSpinnerUI(); } diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsSplitPaneDivider.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsSplitPaneDivider.java index a132756bbee..26cd1bd8c2d 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsSplitPaneDivider.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsSplitPaneDivider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,7 +39,7 @@ * @author Jeff Dinkins */ @SuppressWarnings("serial") // Superclass is not serializable across versions -public final class WindowsSplitPaneDivider extends BasicSplitPaneDivider +public class WindowsSplitPaneDivider extends BasicSplitPaneDivider { /** diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsSplitPaneUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsSplitPaneUI.java index 481fa466a5b..b67ab22f48f 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsSplitPaneUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsSplitPaneUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,7 +33,7 @@ /** * Windows rendition of the component. */ -public final class WindowsSplitPaneUI extends BasicSplitPaneUI +public class WindowsSplitPaneUI extends BasicSplitPaneUI { public WindowsSplitPaneUI() { diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTabbedPaneUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTabbedPaneUI.java index 874b5c65c6e..da8e8b9d385 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTabbedPaneUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTabbedPaneUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,7 +48,7 @@ /** * Windows rendition of the component. */ -public final class WindowsTabbedPaneUI extends BasicTabbedPaneUI { +public class WindowsTabbedPaneUI extends BasicTabbedPaneUI { /** * Keys to use for forward focus traversal when the JComponent is * managing focus. diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTableHeaderUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTableHeaderUI.java index de8f18b4ea1..1db0050f162 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTableHeaderUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTableHeaderUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,7 +50,7 @@ import static com.sun.java.swing.plaf.windows.TMSchema.State; import static com.sun.java.swing.plaf.windows.XPStyle.Skin; -public final class WindowsTableHeaderUI extends BasicTableHeaderUI { +public class WindowsTableHeaderUI extends BasicTableHeaderUI { private TableCellRenderer originalHeaderRenderer; public static ComponentUI createUI(JComponent h) { diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTextAreaUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTextAreaUI.java index 78cceff2a0c..7c9abb12e05 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTextAreaUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTextAreaUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,7 +33,7 @@ /** * Windows rendition of the component. */ -public final class WindowsTextAreaUI extends BasicTextAreaUI { +public class WindowsTextAreaUI extends BasicTextAreaUI { /** * Creates the object to use for a caret. By default an * instance of WindowsCaret is created. This method diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTextFieldUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTextFieldUI.java index 5846dcb9f09..9920ed371d8 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTextFieldUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTextFieldUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -62,7 +62,7 @@ * * @author Timothy Prinzing */ -public final class WindowsTextFieldUI extends BasicTextFieldUI +public class WindowsTextFieldUI extends BasicTextFieldUI { /** * Creates a UI for a JTextField. diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTextPaneUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTextPaneUI.java index 2c645903e51..d1418205385 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTextPaneUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTextPaneUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,7 +33,7 @@ /** * Windows rendition of the component. */ -public final class WindowsTextPaneUI extends BasicTextPaneUI +public class WindowsTextPaneUI extends BasicTextPaneUI { /** * Creates a UI for a JTextPane. diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsToggleButtonUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsToggleButtonUI.java index 67eb5c1d6a0..a612b3f392e 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsToggleButtonUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsToggleButtonUI.java @@ -43,7 +43,7 @@ * * @author Jeff Dinkins */ -public final class WindowsToggleButtonUI extends BasicToggleButtonUI +public class WindowsToggleButtonUI extends BasicToggleButtonUI { protected int dashedRectGapX; protected int dashedRectGapY; diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsToolBarSeparatorUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsToolBarSeparatorUI.java index 47175b83d30..1707ce5a80c 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsToolBarSeparatorUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsToolBarSeparatorUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,7 +40,7 @@ * * @author Mark Davidson */ -public final class WindowsToolBarSeparatorUI extends BasicToolBarSeparatorUI { +public class WindowsToolBarSeparatorUI extends BasicToolBarSeparatorUI { public static ComponentUI createUI( JComponent c ) { return new WindowsToolBarSeparatorUI(); diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsToolBarUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsToolBarUI.java index 025c30c5c96..4e2cf42bf5d 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsToolBarUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsToolBarUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,7 +45,7 @@ import static com.sun.java.swing.plaf.windows.TMSchema.Part; -public final class WindowsToolBarUI extends BasicToolBarUI { +public class WindowsToolBarUI extends BasicToolBarUI { public static ComponentUI createUI(JComponent c) { return new WindowsToolBarUI(); diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTreeUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTreeUI.java index 78384bbd18a..26edfb978bd 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTreeUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTreeUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -167,7 +167,7 @@ public int getIconHeight() { * The plus sign button icon */ @SuppressWarnings("serial") // Superclass is not serializable across versions - public static final class CollapsedIcon extends ExpandedIcon { + public static class CollapsedIcon extends ExpandedIcon { public static Icon createCollapsedIcon() { return new CollapsedIcon(); } @@ -185,7 +185,7 @@ public void paintIcon(Component c, Graphics g, int x, int y) { } @SuppressWarnings("serial") // Superclass is not serializable across versions - public final class WindowsTreeCellRenderer extends DefaultTreeCellRenderer { + public class WindowsTreeCellRenderer extends DefaultTreeCellRenderer { /** * Configures the renderer based on the passed in components. diff --git a/test/jdk/javax/swing/plaf/windows/bug4991587.java b/test/jdk/javax/swing/plaf/windows/bug4991587.java index e4e4fde2b86..439bdd4cc61 100644 --- a/test/jdk/javax/swing/plaf/windows/bug4991587.java +++ b/test/jdk/javax/swing/plaf/windows/bug4991587.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 4991587 + * @bug 4991587 8359433 * @requires (os.family == "windows") * @summary Tests that disabled JButton text is positioned properly in Windows L&F * @modules java.desktop/com.sun.java.swing.plaf.windows From 062d89bff59e09850d335e8de682c9711f28966b Mon Sep 17 00:00:00 2001 From: Phil Race Date: Thu, 26 Mar 2026 21:23:04 +0000 Subject: [PATCH 021/116] 8380804: Remove remaining AppContext usage from the Swing implementation Reviewed-by: dnguyen, serb --- .../classes/javax/swing/RepaintManager.java | 22 +++---- .../classes/javax/swing/SwingUtilities.java | 21 ------- .../classes/javax/swing/SwingWorker.java | 63 +++++++------------ .../share/classes/javax/swing/Timer.java | 5 +- .../share/classes/javax/swing/UIManager.java | 34 ++-------- 5 files changed, 36 insertions(+), 109 deletions(-) diff --git a/src/java.desktop/share/classes/javax/swing/RepaintManager.java b/src/java.desktop/share/classes/javax/swing/RepaintManager.java index db8b13afa22..b587cf2da84 100644 --- a/src/java.desktop/share/classes/javax/swing/RepaintManager.java +++ b/src/java.desktop/share/classes/javax/swing/RepaintManager.java @@ -32,7 +32,6 @@ import java.util.concurrent.atomic.AtomicInteger; import sun.awt.AWTAccessor; -import sun.awt.AppContext; import sun.awt.DisplayChangedListener; import sun.awt.SunToolkit; import sun.java2d.SunGraphicsEnvironment; @@ -1733,21 +1732,14 @@ public void paletteChanged() { } private static void scheduleDisplayChanges() { - // To avoid threading problems, we notify each RepaintManager + // To avoid threading problems, we notify the RepaintManager // on the thread it was created on. - for (AppContext context : AppContext.getAppContexts()) { - synchronized(context) { - if (!context.isDisposed()) { - EventQueue eventQueue = (EventQueue)context.get( - AppContext.EVENT_QUEUE_KEY); - if (eventQueue != null) { - eventQueue.postEvent(new InvocationEvent( - Toolkit.getDefaultToolkit(), - new DisplayChangedRunnable())); - } - } - } - } + EventQueue eventQueue = Toolkit.getDefaultToolkit().getSystemEventQueue(); + eventQueue.postEvent( + new InvocationEvent( + Toolkit.getDefaultToolkit(), + new DisplayChangedRunnable()) + ); } } diff --git a/src/java.desktop/share/classes/javax/swing/SwingUtilities.java b/src/java.desktop/share/classes/javax/swing/SwingUtilities.java index ae5faf64f3b..3603292b0ca 100644 --- a/src/java.desktop/share/classes/javax/swing/SwingUtilities.java +++ b/src/java.desktop/share/classes/javax/swing/SwingUtilities.java @@ -38,7 +38,6 @@ import javax.swing.plaf.UIResource; import javax.swing.text.View; -import sun.awt.AppContext; import sun.awt.AWTAccessor; import sun.awt.AWTAccessor.MouseEventAccessor; @@ -1986,26 +1985,6 @@ static WindowListener getSharedOwnerFrameShutdownListener() throws HeadlessExcep return (WindowListener)sharedOwnerFrame; } - /* Don't make these AppContext accessors public or protected -- - * since AppContext is in sun.awt in 1.2, we shouldn't expose it - * even indirectly with a public API. - */ - // REMIND(aim): phase out use of 4 methods below since they - // are just private covers for AWT methods (?) - - static Object appContextGet(Object key) { - return AppContext.getAppContext().get(key); - } - - static void appContextPut(Object key, Object value) { - AppContext.getAppContext().put(key, value); - } - - static void appContextRemove(Object key) { - AppContext.getAppContext().remove(key); - } - - static Class loadSystemClass(String className) throws ClassNotFoundException { return Class.forName(className, true, Thread.currentThread(). getContextClassLoader()); diff --git a/src/java.desktop/share/classes/javax/swing/SwingWorker.java b/src/java.desktop/share/classes/javax/swing/SwingWorker.java index 75f1700bded..dae695b4868 100644 --- a/src/java.desktop/share/classes/javax/swing/SwingWorker.java +++ b/src/java.desktop/share/classes/javax/swing/SwingWorker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,7 +45,8 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -import sun.awt.AppContext; +import sun.awt.util.ThreadGroupUtils; + import sun.swing.AccumulativeRunnable; /** @@ -266,7 +267,7 @@ public abstract class SwingWorker implements RunnableFuture { */ private AccumulativeRunnable doNotifyProgressChange; - private final AccumulativeRunnable doSubmit = getDoSubmit(); + private final AccumulativeRunnable doSubmit = new DoSubmitAccumulativeRunnable(); /** * Values for the {@code state} bound property. @@ -755,18 +756,16 @@ public void run() { } + private static ExecutorService executorService; + /** * returns workersExecutorService. * - * returns the service stored in the appContext or creates it if - * necessary. + * returns the service and creates it if necessary. * * @return ExecutorService for the {@code SwingWorkers} */ private static synchronized ExecutorService getWorkersExecutorService() { - final AppContext appContext = AppContext.getAppContext(); - ExecutorService executorService = - (ExecutorService) appContext.get(SwingWorker.class); if (executorService == null) { //this creates daemon threads. ThreadFactory threadFactory = @@ -788,46 +787,26 @@ public Thread newThread(final Runnable r) { 10L, TimeUnit.MINUTES, new LinkedBlockingQueue(), threadFactory); - appContext.put(SwingWorker.class, executorService); - // Don't use ShutdownHook here as it's not enough. We should track - // AppContext disposal instead of JVM shutdown, see 6799345 for details - final ExecutorService es = executorService; - appContext.addPropertyChangeListener(AppContext.DISPOSED_PROPERTY_NAME, - new PropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent pce) { - boolean disposed = (Boolean)pce.getNewValue(); - if (disposed) { - final WeakReference executorServiceRef = - new WeakReference(es); - final ExecutorService executorService = - executorServiceRef.get(); - if (executorService != null) { - executorService.shutdown(); - } - } - } + final Runnable shutdownHook = new Runnable() { + final WeakReference executorServiceRef = + new WeakReference(executorService); + public void run() { + final ExecutorService executorService = executorServiceRef.get(); + if (executorService != null) { + executorService.shutdown(); + } } - ); + }; + ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup(); + Thread t = new Thread(rootTG, shutdownHook, + "SwingWorker ES", 0, false); + t.setContextClassLoader(null); + Runtime.getRuntime().addShutdownHook(t); } return executorService; } - private static final Object DO_SUBMIT_KEY = new StringBuilder("doSubmit"); - private static AccumulativeRunnable getDoSubmit() { - synchronized (DO_SUBMIT_KEY) { - final AppContext appContext = AppContext.getAppContext(); - Object doSubmit = appContext.get(DO_SUBMIT_KEY); - if (doSubmit == null) { - doSubmit = new DoSubmitAccumulativeRunnable(); - appContext.put(DO_SUBMIT_KEY, doSubmit); - } - @SuppressWarnings("unchecked") - AccumulativeRunnable tmp = (AccumulativeRunnable) doSubmit; - return tmp; - } - } private static class DoSubmitAccumulativeRunnable extends AccumulativeRunnable implements ActionListener { private static final int DELAY = 1000 / 30; diff --git a/src/java.desktop/share/classes/javax/swing/Timer.java b/src/java.desktop/share/classes/javax/swing/Timer.java index 2cb8381d7d3..1063532715c 100644 --- a/src/java.desktop/share/classes/javax/swing/Timer.java +++ b/src/java.desktop/share/classes/javax/swing/Timer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -173,8 +173,7 @@ public class Timer implements Serializable private final transient Lock lock = new ReentrantLock(); // This field is maintained by TimerQueue. - // eventQueued can also be reset by the TimerQueue, but will only ever - // happen in an AppContext case when TimerQueues thread is destroyed. + // eventQueued can also be reset by the TimerQueue // access to this field is synchronized on getLock() lock. transient TimerQueue.DelayedTimer delayedTimer = null; diff --git a/src/java.desktop/share/classes/javax/swing/UIManager.java b/src/java.desktop/share/classes/javax/swing/UIManager.java index 69063c562e6..f323842ae49 100644 --- a/src/java.desktop/share/classes/javax/swing/UIManager.java +++ b/src/java.desktop/share/classes/javax/swing/UIManager.java @@ -56,7 +56,6 @@ import sun.swing.SwingUtilities2; import java.util.HashMap; import java.util.Objects; -import sun.awt.AppContext; import sun.awt.AWTAccessor; import sun.swing.SwingAccessor; @@ -179,10 +178,7 @@ public class UIManager implements Serializable /** * This class defines the state managed by the UIManager. For * Swing applications the fields in this class could just as well - * be static members of UIManager however we give them - * "AppContext" - * scope instead so that potentially multiple lightweight - * applications running in a single VM have their own state. + * be static members of UIManager. */ private static class LAFState { @@ -206,8 +202,8 @@ private static class LAFState void setSystemDefaults(UIDefaults x) { tables[1] = x; } /** - * Returns the SwingPropertyChangeSupport for the current - * AppContext. If create is a true, a non-null + * Returns the SwingPropertyChangeSupport instance. + * If create is a true, a non-null * SwingPropertyChangeSupport will be returned, if * create is false and this has not been invoked * with true, null will be returned. @@ -1366,18 +1362,7 @@ private static void initializeDefaultLAF(Properties swingProps) return; } - // Try to get default LAF from system property, then from AppContext - // (6653395), then use cross-platform one by default. - String lafName = null; - @SuppressWarnings("unchecked") - HashMap lafData = - (HashMap) AppContext.getAppContext().remove("swing.lafdata"); - if (lafData != null) { - lafName = lafData.remove("defaultlaf"); - } - if (lafName == null) { - lafName = getCrossPlatformLookAndFeelClassName(); - } + String lafName = getCrossPlatformLookAndFeelClassName(); lafName = swingProps.getProperty(defaultLAFKey, lafName); try { @@ -1385,13 +1370,6 @@ private static void initializeDefaultLAF(Properties swingProps) } catch (Exception e) { throw new Error("Cannot load " + lafName); } - - // Set any properties passed through AppContext (6653395). - if (lafData != null) { - for (Object key: lafData.keySet()) { - UIManager.put(key, lafData.get(key)); - } - } } @@ -1451,8 +1429,8 @@ private static void initializeSystemDefaults(Properties swingProps) { /* * This method is called before any code that depends on the - * AppContext specific LAFState object runs. - * In some AppContext cases, it's possible for this method + * LAFState object runs. + * In some cases, it's possible for this method * to be re-entered, which is why we grab a lock before calling * initialize(). */ From 6a92c5314464f62889a4042a98b7a14c247ac889 Mon Sep 17 00:00:00 2001 From: Chen Liang Date: Thu, 26 Mar 2026 22:52:44 +0000 Subject: [PATCH 022/116] 8380915: Cleanup some Java declarations of the Vector API Reviewed-by: psandoz --- .../jdk/incubator/vector/AbstractMask.java | 14 ++-- .../jdk/incubator/vector/AbstractShuffle.java | 9 ++- .../jdk/incubator/vector/AbstractSpecies.java | 26 +++--- .../jdk/incubator/vector/AbstractVector.java | 13 +-- .../jdk/incubator/vector/ByteVector.java | 3 +- .../jdk/incubator/vector/ByteVector128.java | 28 +++---- .../jdk/incubator/vector/ByteVector256.java | 28 +++---- .../jdk/incubator/vector/ByteVector512.java | 28 +++---- .../jdk/incubator/vector/ByteVector64.java | 28 +++---- .../jdk/incubator/vector/ByteVectorMax.java | 28 +++---- .../jdk/incubator/vector/CPUFeatures.java | 4 +- .../jdk/incubator/vector/DoubleVector.java | 3 +- .../jdk/incubator/vector/DoubleVector128.java | 29 ++++--- .../jdk/incubator/vector/DoubleVector256.java | 29 ++++--- .../jdk/incubator/vector/DoubleVector512.java | 29 ++++--- .../jdk/incubator/vector/DoubleVector64.java | 29 ++++--- .../jdk/incubator/vector/DoubleVectorMax.java | 29 ++++--- .../jdk/incubator/vector/Float16Consts.java | 4 +- .../jdk/incubator/vector/FloatVector.java | 3 +- .../jdk/incubator/vector/FloatVector128.java | 30 ++++--- .../jdk/incubator/vector/FloatVector256.java | 30 ++++--- .../jdk/incubator/vector/FloatVector512.java | 30 ++++--- .../jdk/incubator/vector/FloatVector64.java | 30 ++++--- .../jdk/incubator/vector/FloatVectorMax.java | 30 ++++--- .../jdk/incubator/vector/IntVector.java | 3 +- .../jdk/incubator/vector/IntVector128.java | 28 +++---- .../jdk/incubator/vector/IntVector256.java | 28 +++---- .../jdk/incubator/vector/IntVector512.java | 28 +++---- .../jdk/incubator/vector/IntVector64.java | 28 +++---- .../jdk/incubator/vector/IntVectorMax.java | 28 +++---- .../jdk/incubator/vector/LongVector.java | 3 +- .../jdk/incubator/vector/LongVector128.java | 27 +++---- .../jdk/incubator/vector/LongVector256.java | 27 +++---- .../jdk/incubator/vector/LongVector512.java | 27 +++---- .../jdk/incubator/vector/LongVector64.java | 27 +++---- .../jdk/incubator/vector/LongVectorMax.java | 27 +++---- .../jdk/incubator/vector/ShortVector.java | 3 +- .../jdk/incubator/vector/ShortVector128.java | 28 +++---- .../jdk/incubator/vector/ShortVector256.java | 28 +++---- .../jdk/incubator/vector/ShortVector512.java | 28 +++---- .../jdk/incubator/vector/ShortVector64.java | 28 +++---- .../jdk/incubator/vector/ShortVectorMax.java | 28 +++---- .../classes/jdk/incubator/vector/Util.java | 4 +- .../classes/jdk/incubator/vector/Vector.java | 5 +- .../incubator/vector/VectorIntrinsics.java | 4 +- .../jdk/incubator/vector/VectorMask.java | 2 +- .../incubator/vector/VectorMathLibrary.java | 2 +- .../jdk/incubator/vector/VectorOperators.java | 79 +++++-------------- .../jdk/incubator/vector/VectorShuffle.java | 4 +- .../jdk/incubator/vector/VectorSpecies.java | 9 +-- .../incubator/vector/X-Vector.java.template | 3 +- .../vector/X-VectorBits.java.template | 33 ++++---- 52 files changed, 498 insertions(+), 585 deletions(-) diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/AbstractMask.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/AbstractMask.java index 5b762edfd3b..9ac90c08c27 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/AbstractMask.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/AbstractMask.java @@ -24,17 +24,19 @@ */ package jdk.incubator.vector; -import java.util.Objects; - -import jdk.internal.vm.annotation.ForceInline; - import jdk.internal.misc.Unsafe; - +import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; import static jdk.incubator.vector.VectorOperators.*; -abstract class AbstractMask extends VectorMask { +abstract sealed class AbstractMask extends VectorMask + permits ByteVector64.ByteMask64, ByteVector128.ByteMask128, ByteVector256.ByteMask256, ByteVector512.ByteMask512, ByteVectorMax.ByteMaskMax, + DoubleVector64.DoubleMask64, DoubleVector128.DoubleMask128, DoubleVector256.DoubleMask256, DoubleVector512.DoubleMask512, DoubleVectorMax.DoubleMaskMax, + FloatVector64.FloatMask64, FloatVector128.FloatMask128, FloatVector256.FloatMask256, FloatVector512.FloatMask512, FloatVectorMax.FloatMaskMax, + IntVector64.IntMask64, IntVector128.IntMask128, IntVector256.IntMask256, IntVector512.IntMask512, IntVectorMax.IntMaskMax, + LongVector64.LongMask64, LongVector128.LongMask128, LongVector256.LongMask256, LongVector512.LongMask512, LongVectorMax.LongMaskMax, + ShortVector64.ShortMask64, ShortVector128.ShortMask128, ShortVector256.ShortMask256, ShortVector512.ShortMask512, ShortVectorMax.ShortMaskMax { AbstractMask(boolean[] bits) { super(bits); } diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/AbstractShuffle.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/AbstractShuffle.java index 075400a0d4a..bea495f74fc 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/AbstractShuffle.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/AbstractShuffle.java @@ -25,10 +25,17 @@ package jdk.incubator.vector; import java.util.function.IntUnaryOperator; + import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; -abstract class AbstractShuffle extends VectorShuffle { +abstract sealed class AbstractShuffle extends VectorShuffle + permits ByteVector64.ByteShuffle64, ByteVector128.ByteShuffle128, ByteVector256.ByteShuffle256, ByteVector512.ByteShuffle512, ByteVectorMax.ByteShuffleMax, + DoubleVector64.DoubleShuffle64, DoubleVector128.DoubleShuffle128, DoubleVector256.DoubleShuffle256, DoubleVector512.DoubleShuffle512, DoubleVectorMax.DoubleShuffleMax, + FloatVector64.FloatShuffle64, FloatVector128.FloatShuffle128, FloatVector256.FloatShuffle256, FloatVector512.FloatShuffle512, FloatVectorMax.FloatShuffleMax, + IntVector64.IntShuffle64, IntVector128.IntShuffle128, IntVector256.IntShuffle256, IntVector512.IntShuffle512, IntVectorMax.IntShuffleMax, + LongVector64.LongShuffle64, LongVector128.LongShuffle128, LongVector256.LongShuffle256, LongVector512.LongShuffle512, LongVectorMax.LongShuffleMax, + ShortVector64.ShortShuffle64, ShortVector128.ShortShuffle128, ShortVector256.ShortShuffle256, ShortVector512.ShortShuffle512, ShortVectorMax.ShortShuffleMax { static final IntUnaryOperator IDENTITY = i -> i; // Internal representation allows for a maximum index of E.MAX_VALUE - 1 diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/AbstractSpecies.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/AbstractSpecies.java index 6c834077387..3fd2be34346 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/AbstractSpecies.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/AbstractSpecies.java @@ -24,39 +24,31 @@ */ package jdk.incubator.vector; -import java.lang.foreign.MemorySegment; -import jdk.internal.vm.annotation.ForceInline; -import jdk.internal.vm.annotation.Stable; import java.lang.reflect.Array; -import java.nio.ByteOrder; import java.util.Arrays; import java.util.function.Function; import java.util.function.IntUnaryOperator; -abstract class AbstractSpecies extends jdk.internal.vm.vector.VectorSupport.VectorSpecies - implements VectorSpecies { - @Stable +import jdk.internal.vm.annotation.ForceInline; +import jdk.internal.vm.annotation.Stable; +import jdk.internal.vm.annotation.TrustFinalFields; + +@TrustFinalFields +abstract sealed class AbstractSpecies extends jdk.internal.vm.vector.VectorSupport.VectorSpecies + implements VectorSpecies + permits ByteVector.ByteSpecies, DoubleVector.DoubleSpecies, FloatVector.FloatSpecies, + IntVector.IntSpecies, LongVector.LongSpecies, ShortVector.ShortSpecies { final VectorShape vectorShape; - @Stable final LaneType laneType; - @Stable final int laneCount; - @Stable final int laneCountLog2P1; - @Stable final Class> vectorType; - @Stable final Class> maskType; - @Stable final Class> shuffleType; - @Stable final Function> vectorFactory; - @Stable final VectorShape indexShape; - @Stable final int maxScale, minScale; - @Stable final int vectorBitSize, vectorByteSize; AbstractSpecies(VectorShape vectorShape, diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/AbstractVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/AbstractVector.java index 80260c2bd30..ea8112cc2ae 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/AbstractVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/AbstractVector.java @@ -25,22 +25,17 @@ package jdk.incubator.vector; import java.lang.foreign.MemorySegment; +import java.nio.ByteOrder; +import java.util.function.IntUnaryOperator; -import jdk.internal.foreign.AbstractMemorySegmentImpl; -import jdk.internal.foreign.Utils; import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; -import java.lang.foreign.ValueLayout; -import java.lang.reflect.Array; -import java.nio.ByteOrder; -import java.util.Objects; -import java.util.function.IntUnaryOperator; - import static jdk.incubator.vector.VectorOperators.*; @SuppressWarnings("cast") -abstract class AbstractVector extends Vector { +abstract sealed class AbstractVector extends Vector + permits ByteVector, DoubleVector, FloatVector, IntVector, LongVector, ShortVector { /** * The order of vector bytes when stored in natural, * array elements of the same lane type. 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 846032cb5c6..7231ada3273 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 @@ -49,7 +49,8 @@ * {@code byte} values. */ @SuppressWarnings("cast") // warning: redundant cast -public abstract class ByteVector extends AbstractVector { +public abstract sealed class ByteVector extends AbstractVector + permits ByteVector64, ByteVector128, ByteVector256, ByteVector512, ByteVectorMax { ByteVector(byte[] vec) { super(vec); diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector128.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector128.java index 360afedbbbb..36ea8d081a8 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector128.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector128.java @@ -25,7 +25,6 @@ package jdk.incubator.vector; import java.lang.foreign.MemorySegment; -import java.lang.foreign.ValueLayout; import java.nio.ByteOrder; import java.util.Arrays; import java.util.Objects; @@ -35,9 +34,8 @@ import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; -import static jdk.internal.vm.vector.VectorSupport.*; - import static jdk.incubator.vector.VectorOperators.*; +import static jdk.internal.vm.vector.VectorSupport.*; // -- This file was mechanically generated: Do not edit! -- // @@ -373,7 +371,7 @@ final VectorShuffle bitsToShuffle(AbstractSpecies dsp) { @Override @ForceInline public final ByteShuffle128 toShuffle() { - return (ByteShuffle128) toShuffle(vspecies(), false); + return (ByteShuffle128) toShuffle(VSPECIES, false); } // Specialized unary testing @@ -648,7 +646,7 @@ boolean[] getBits() { @Override ByteMask128 uOp(MUnOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); for (int i = 0; i < res.length; i++) { res[i] = f.apply(i, bits[i]); @@ -658,7 +656,7 @@ ByteMask128 uOp(MUnOp f) { @Override ByteMask128 bOp(VectorMask m, MBinOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); boolean[] mbits = ((ByteMask128)m).getBits(); for (int i = 0; i < res.length; i++) { @@ -808,16 +806,16 @@ public boolean laneIsSet(int i) { @ForceInline public boolean anyTrue() { return VectorSupport.test(BT_ne, ByteMask128.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> anyTrueHelper(((ByteMask128)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> anyTrueHelper(((ByteMask128)m).getBits())); } @Override @ForceInline public boolean allTrue() { return VectorSupport.test(BT_overflow, ByteMask128.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> allTrueHelper(((ByteMask128)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> allTrueHelper(((ByteMask128)m).getBits())); } @ForceInline @@ -825,7 +823,7 @@ this, vspecies().maskAll(true), static ByteMask128 maskAll(boolean bit) { return VectorSupport.fromBitsCoerced(ByteMask128.class, LANEBITS_TYPE_ORDINAL, VLENGTH, (bit ? -1 : 0), MODE_BROADCAST, null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + (v, _) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final ByteMask128 TRUE_MASK = new ByteMask128(true); private static final ByteMask128 FALSE_MASK = new ByteMask128(false); @@ -885,7 +883,7 @@ ByteVector128 toBitsVector() { @Override ByteVector128 toBitsVector0() { - return ((ByteVector128) vspecies().asIntegral().dummyVector()).vectorFactory(indices()); + return ((ByteVector128) VSPECIES.asIntegral().dummyVector()).vectorFactory(indices()); } @Override @@ -936,7 +934,7 @@ public void intoMemorySegment(MemorySegment ms, long offset, ByteOrder bo) { @ForceInline public final ByteMask128 laneIsValid() { return (ByteMask128) toBitsVector().compare(VectorOperators.GE, 0) - .cast(vspecies()); + .cast(VSPECIES); } @ForceInline @@ -944,7 +942,7 @@ public final ByteMask128 laneIsValid() { public final ByteShuffle128 rearrange(VectorShuffle shuffle) { ByteShuffle128 concreteShuffle = (ByteShuffle128) shuffle; return (ByteShuffle128) toBitsVector().rearrange(concreteShuffle) - .toShuffle(vspecies(), false); + .toShuffle(VSPECIES, false); } @ForceInline @@ -957,7 +955,7 @@ public final ByteShuffle128 wrapIndexes() { v = (ByteVector128) v.blend(v.lanewise(VectorOperators.ADD, length()), v.compare(VectorOperators.LT, 0)); } - return (ByteShuffle128) v.toShuffle(vspecies(), false); + return (ByteShuffle128) v.toShuffle(VSPECIES, false); } private static byte[] prepare(int[] indices, int offset) { diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector256.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector256.java index ca0c59dd49e..a11268ea40d 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector256.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector256.java @@ -25,7 +25,6 @@ package jdk.incubator.vector; import java.lang.foreign.MemorySegment; -import java.lang.foreign.ValueLayout; import java.nio.ByteOrder; import java.util.Arrays; import java.util.Objects; @@ -35,9 +34,8 @@ import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; -import static jdk.internal.vm.vector.VectorSupport.*; - import static jdk.incubator.vector.VectorOperators.*; +import static jdk.internal.vm.vector.VectorSupport.*; // -- This file was mechanically generated: Do not edit! -- // @@ -373,7 +371,7 @@ final VectorShuffle bitsToShuffle(AbstractSpecies dsp) { @Override @ForceInline public final ByteShuffle256 toShuffle() { - return (ByteShuffle256) toShuffle(vspecies(), false); + return (ByteShuffle256) toShuffle(VSPECIES, false); } // Specialized unary testing @@ -680,7 +678,7 @@ boolean[] getBits() { @Override ByteMask256 uOp(MUnOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); for (int i = 0; i < res.length; i++) { res[i] = f.apply(i, bits[i]); @@ -690,7 +688,7 @@ ByteMask256 uOp(MUnOp f) { @Override ByteMask256 bOp(VectorMask m, MBinOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); boolean[] mbits = ((ByteMask256)m).getBits(); for (int i = 0; i < res.length; i++) { @@ -840,16 +838,16 @@ public boolean laneIsSet(int i) { @ForceInline public boolean anyTrue() { return VectorSupport.test(BT_ne, ByteMask256.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> anyTrueHelper(((ByteMask256)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> anyTrueHelper(((ByteMask256)m).getBits())); } @Override @ForceInline public boolean allTrue() { return VectorSupport.test(BT_overflow, ByteMask256.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> allTrueHelper(((ByteMask256)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> allTrueHelper(((ByteMask256)m).getBits())); } @ForceInline @@ -857,7 +855,7 @@ this, vspecies().maskAll(true), static ByteMask256 maskAll(boolean bit) { return VectorSupport.fromBitsCoerced(ByteMask256.class, LANEBITS_TYPE_ORDINAL, VLENGTH, (bit ? -1 : 0), MODE_BROADCAST, null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + (v, _) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final ByteMask256 TRUE_MASK = new ByteMask256(true); private static final ByteMask256 FALSE_MASK = new ByteMask256(false); @@ -917,7 +915,7 @@ ByteVector256 toBitsVector() { @Override ByteVector256 toBitsVector0() { - return ((ByteVector256) vspecies().asIntegral().dummyVector()).vectorFactory(indices()); + return ((ByteVector256) VSPECIES.asIntegral().dummyVector()).vectorFactory(indices()); } @Override @@ -968,7 +966,7 @@ public void intoMemorySegment(MemorySegment ms, long offset, ByteOrder bo) { @ForceInline public final ByteMask256 laneIsValid() { return (ByteMask256) toBitsVector().compare(VectorOperators.GE, 0) - .cast(vspecies()); + .cast(VSPECIES); } @ForceInline @@ -976,7 +974,7 @@ public final ByteMask256 laneIsValid() { public final ByteShuffle256 rearrange(VectorShuffle shuffle) { ByteShuffle256 concreteShuffle = (ByteShuffle256) shuffle; return (ByteShuffle256) toBitsVector().rearrange(concreteShuffle) - .toShuffle(vspecies(), false); + .toShuffle(VSPECIES, false); } @ForceInline @@ -989,7 +987,7 @@ public final ByteShuffle256 wrapIndexes() { v = (ByteVector256) v.blend(v.lanewise(VectorOperators.ADD, length()), v.compare(VectorOperators.LT, 0)); } - return (ByteShuffle256) v.toShuffle(vspecies(), false); + return (ByteShuffle256) v.toShuffle(VSPECIES, false); } private static byte[] prepare(int[] indices, int offset) { diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector512.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector512.java index 1a0c69153bc..707254e034e 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector512.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector512.java @@ -25,7 +25,6 @@ package jdk.incubator.vector; import java.lang.foreign.MemorySegment; -import java.lang.foreign.ValueLayout; import java.nio.ByteOrder; import java.util.Arrays; import java.util.Objects; @@ -35,9 +34,8 @@ import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; -import static jdk.internal.vm.vector.VectorSupport.*; - import static jdk.incubator.vector.VectorOperators.*; +import static jdk.internal.vm.vector.VectorSupport.*; // -- This file was mechanically generated: Do not edit! -- // @@ -373,7 +371,7 @@ final VectorShuffle bitsToShuffle(AbstractSpecies dsp) { @Override @ForceInline public final ByteShuffle512 toShuffle() { - return (ByteShuffle512) toShuffle(vspecies(), false); + return (ByteShuffle512) toShuffle(VSPECIES, false); } // Specialized unary testing @@ -744,7 +742,7 @@ boolean[] getBits() { @Override ByteMask512 uOp(MUnOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); for (int i = 0; i < res.length; i++) { res[i] = f.apply(i, bits[i]); @@ -754,7 +752,7 @@ ByteMask512 uOp(MUnOp f) { @Override ByteMask512 bOp(VectorMask m, MBinOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); boolean[] mbits = ((ByteMask512)m).getBits(); for (int i = 0; i < res.length; i++) { @@ -904,16 +902,16 @@ public boolean laneIsSet(int i) { @ForceInline public boolean anyTrue() { return VectorSupport.test(BT_ne, ByteMask512.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> anyTrueHelper(((ByteMask512)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> anyTrueHelper(((ByteMask512)m).getBits())); } @Override @ForceInline public boolean allTrue() { return VectorSupport.test(BT_overflow, ByteMask512.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> allTrueHelper(((ByteMask512)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> allTrueHelper(((ByteMask512)m).getBits())); } @ForceInline @@ -921,7 +919,7 @@ this, vspecies().maskAll(true), static ByteMask512 maskAll(boolean bit) { return VectorSupport.fromBitsCoerced(ByteMask512.class, LANEBITS_TYPE_ORDINAL, VLENGTH, (bit ? -1 : 0), MODE_BROADCAST, null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + (v, _) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final ByteMask512 TRUE_MASK = new ByteMask512(true); private static final ByteMask512 FALSE_MASK = new ByteMask512(false); @@ -981,7 +979,7 @@ ByteVector512 toBitsVector() { @Override ByteVector512 toBitsVector0() { - return ((ByteVector512) vspecies().asIntegral().dummyVector()).vectorFactory(indices()); + return ((ByteVector512) VSPECIES.asIntegral().dummyVector()).vectorFactory(indices()); } @Override @@ -1032,7 +1030,7 @@ public void intoMemorySegment(MemorySegment ms, long offset, ByteOrder bo) { @ForceInline public final ByteMask512 laneIsValid() { return (ByteMask512) toBitsVector().compare(VectorOperators.GE, 0) - .cast(vspecies()); + .cast(VSPECIES); } @ForceInline @@ -1040,7 +1038,7 @@ public final ByteMask512 laneIsValid() { public final ByteShuffle512 rearrange(VectorShuffle shuffle) { ByteShuffle512 concreteShuffle = (ByteShuffle512) shuffle; return (ByteShuffle512) toBitsVector().rearrange(concreteShuffle) - .toShuffle(vspecies(), false); + .toShuffle(VSPECIES, false); } @ForceInline @@ -1053,7 +1051,7 @@ public final ByteShuffle512 wrapIndexes() { v = (ByteVector512) v.blend(v.lanewise(VectorOperators.ADD, length()), v.compare(VectorOperators.LT, 0)); } - return (ByteShuffle512) v.toShuffle(vspecies(), false); + return (ByteShuffle512) v.toShuffle(VSPECIES, false); } private static byte[] prepare(int[] indices, int offset) { diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector64.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector64.java index 50561eca0f8..d304edfc0c7 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector64.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector64.java @@ -25,7 +25,6 @@ package jdk.incubator.vector; import java.lang.foreign.MemorySegment; -import java.lang.foreign.ValueLayout; import java.nio.ByteOrder; import java.util.Arrays; import java.util.Objects; @@ -35,9 +34,8 @@ import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; -import static jdk.internal.vm.vector.VectorSupport.*; - import static jdk.incubator.vector.VectorOperators.*; +import static jdk.internal.vm.vector.VectorSupport.*; // -- This file was mechanically generated: Do not edit! -- // @@ -373,7 +371,7 @@ final VectorShuffle bitsToShuffle(AbstractSpecies dsp) { @Override @ForceInline public final ByteShuffle64 toShuffle() { - return (ByteShuffle64) toShuffle(vspecies(), false); + return (ByteShuffle64) toShuffle(VSPECIES, false); } // Specialized unary testing @@ -632,7 +630,7 @@ boolean[] getBits() { @Override ByteMask64 uOp(MUnOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); for (int i = 0; i < res.length; i++) { res[i] = f.apply(i, bits[i]); @@ -642,7 +640,7 @@ ByteMask64 uOp(MUnOp f) { @Override ByteMask64 bOp(VectorMask m, MBinOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); boolean[] mbits = ((ByteMask64)m).getBits(); for (int i = 0; i < res.length; i++) { @@ -792,16 +790,16 @@ public boolean laneIsSet(int i) { @ForceInline public boolean anyTrue() { return VectorSupport.test(BT_ne, ByteMask64.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> anyTrueHelper(((ByteMask64)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> anyTrueHelper(((ByteMask64)m).getBits())); } @Override @ForceInline public boolean allTrue() { return VectorSupport.test(BT_overflow, ByteMask64.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> allTrueHelper(((ByteMask64)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> allTrueHelper(((ByteMask64)m).getBits())); } @ForceInline @@ -809,7 +807,7 @@ this, vspecies().maskAll(true), static ByteMask64 maskAll(boolean bit) { return VectorSupport.fromBitsCoerced(ByteMask64.class, LANEBITS_TYPE_ORDINAL, VLENGTH, (bit ? -1 : 0), MODE_BROADCAST, null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + (v, _) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final ByteMask64 TRUE_MASK = new ByteMask64(true); private static final ByteMask64 FALSE_MASK = new ByteMask64(false); @@ -869,7 +867,7 @@ ByteVector64 toBitsVector() { @Override ByteVector64 toBitsVector0() { - return ((ByteVector64) vspecies().asIntegral().dummyVector()).vectorFactory(indices()); + return ((ByteVector64) VSPECIES.asIntegral().dummyVector()).vectorFactory(indices()); } @Override @@ -920,7 +918,7 @@ public void intoMemorySegment(MemorySegment ms, long offset, ByteOrder bo) { @ForceInline public final ByteMask64 laneIsValid() { return (ByteMask64) toBitsVector().compare(VectorOperators.GE, 0) - .cast(vspecies()); + .cast(VSPECIES); } @ForceInline @@ -928,7 +926,7 @@ public final ByteMask64 laneIsValid() { public final ByteShuffle64 rearrange(VectorShuffle shuffle) { ByteShuffle64 concreteShuffle = (ByteShuffle64) shuffle; return (ByteShuffle64) toBitsVector().rearrange(concreteShuffle) - .toShuffle(vspecies(), false); + .toShuffle(VSPECIES, false); } @ForceInline @@ -941,7 +939,7 @@ public final ByteShuffle64 wrapIndexes() { v = (ByteVector64) v.blend(v.lanewise(VectorOperators.ADD, length()), v.compare(VectorOperators.LT, 0)); } - return (ByteShuffle64) v.toShuffle(vspecies(), false); + return (ByteShuffle64) v.toShuffle(VSPECIES, false); } private static byte[] prepare(int[] indices, int offset) { diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVectorMax.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVectorMax.java index ee931bbc077..0084995346b 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVectorMax.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVectorMax.java @@ -25,7 +25,6 @@ package jdk.incubator.vector; import java.lang.foreign.MemorySegment; -import java.lang.foreign.ValueLayout; import java.nio.ByteOrder; import java.util.Arrays; import java.util.Objects; @@ -35,9 +34,8 @@ import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; -import static jdk.internal.vm.vector.VectorSupport.*; - import static jdk.incubator.vector.VectorOperators.*; +import static jdk.internal.vm.vector.VectorSupport.*; // -- This file was mechanically generated: Do not edit! -- // @@ -373,7 +371,7 @@ final VectorShuffle bitsToShuffle(AbstractSpecies dsp) { @Override @ForceInline public final ByteShuffleMax toShuffle() { - return (ByteShuffleMax) toShuffle(vspecies(), false); + return (ByteShuffleMax) toShuffle(VSPECIES, false); } // Specialized unary testing @@ -618,7 +616,7 @@ boolean[] getBits() { @Override ByteMaskMax uOp(MUnOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); for (int i = 0; i < res.length; i++) { res[i] = f.apply(i, bits[i]); @@ -628,7 +626,7 @@ ByteMaskMax uOp(MUnOp f) { @Override ByteMaskMax bOp(VectorMask m, MBinOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); boolean[] mbits = ((ByteMaskMax)m).getBits(); for (int i = 0; i < res.length; i++) { @@ -778,16 +776,16 @@ public boolean laneIsSet(int i) { @ForceInline public boolean anyTrue() { return VectorSupport.test(BT_ne, ByteMaskMax.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> anyTrueHelper(((ByteMaskMax)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> anyTrueHelper(((ByteMaskMax)m).getBits())); } @Override @ForceInline public boolean allTrue() { return VectorSupport.test(BT_overflow, ByteMaskMax.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> allTrueHelper(((ByteMaskMax)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> allTrueHelper(((ByteMaskMax)m).getBits())); } @ForceInline @@ -795,7 +793,7 @@ this, vspecies().maskAll(true), static ByteMaskMax maskAll(boolean bit) { return VectorSupport.fromBitsCoerced(ByteMaskMax.class, LANEBITS_TYPE_ORDINAL, VLENGTH, (bit ? -1 : 0), MODE_BROADCAST, null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + (v, _) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final ByteMaskMax TRUE_MASK = new ByteMaskMax(true); private static final ByteMaskMax FALSE_MASK = new ByteMaskMax(false); @@ -855,7 +853,7 @@ ByteVectorMax toBitsVector() { @Override ByteVectorMax toBitsVector0() { - return ((ByteVectorMax) vspecies().asIntegral().dummyVector()).vectorFactory(indices()); + return ((ByteVectorMax) VSPECIES.asIntegral().dummyVector()).vectorFactory(indices()); } @Override @@ -906,7 +904,7 @@ public void intoMemorySegment(MemorySegment ms, long offset, ByteOrder bo) { @ForceInline public final ByteMaskMax laneIsValid() { return (ByteMaskMax) toBitsVector().compare(VectorOperators.GE, 0) - .cast(vspecies()); + .cast(VSPECIES); } @ForceInline @@ -914,7 +912,7 @@ public final ByteMaskMax laneIsValid() { public final ByteShuffleMax rearrange(VectorShuffle shuffle) { ByteShuffleMax concreteShuffle = (ByteShuffleMax) shuffle; return (ByteShuffleMax) toBitsVector().rearrange(concreteShuffle) - .toShuffle(vspecies(), false); + .toShuffle(VSPECIES, false); } @ForceInline @@ -927,7 +925,7 @@ public final ByteShuffleMax wrapIndexes() { v = (ByteVectorMax) v.blend(v.lanewise(VectorOperators.ADD, length()), v.compare(VectorOperators.LT, 0)); } - return (ByteShuffleMax) v.toShuffle(vspecies(), false); + return (ByteShuffleMax) v.toShuffle(VSPECIES, false); } private static byte[] prepare(int[] indices, int offset) { diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/CPUFeatures.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/CPUFeatures.java index c0d8ef03ada..0ad7ba1651d 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/CPUFeatures.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/CPUFeatures.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,7 +36,7 @@ /** * Enumerates CPU ISA extensions supported by the JVM on the current hardware. */ -/*package-private*/ class CPUFeatures { +/*package-private*/ final class CPUFeatures { private static final Set features = getCPUFeatures(); private static Set getCPUFeatures() { 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 5e7c97dc56d..6f9b5e53ead 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 @@ -49,7 +49,8 @@ * {@code double} values. */ @SuppressWarnings("cast") // warning: redundant cast -public abstract class DoubleVector extends AbstractVector { +public abstract sealed class DoubleVector extends AbstractVector + permits DoubleVector64, DoubleVector128, DoubleVector256, DoubleVector512, DoubleVectorMax { DoubleVector(double[] vec) { super(vec); diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector128.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector128.java index 43c7e3f0c46..8d3ec21ec9b 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector128.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector128.java @@ -35,9 +35,8 @@ import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; -import static jdk.internal.vm.vector.VectorSupport.*; - import static jdk.incubator.vector.VectorOperators.*; +import static jdk.internal.vm.vector.VectorSupport.*; // -- This file was mechanically generated: Do not edit! -- // @@ -360,7 +359,7 @@ final VectorShuffle bitsToShuffle(AbstractSpecies dsp) { @Override @ForceInline public final DoubleShuffle128 toShuffle() { - return (DoubleShuffle128) toShuffle(vspecies(), false); + return (DoubleShuffle128) toShuffle(VSPECIES, false); } // Specialized unary testing @@ -609,7 +608,7 @@ boolean[] getBits() { @Override DoubleMask128 uOp(MUnOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); for (int i = 0; i < res.length; i++) { res[i] = f.apply(i, bits[i]); @@ -619,7 +618,7 @@ DoubleMask128 uOp(MUnOp f) { @Override DoubleMask128 bOp(VectorMask m, MBinOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); boolean[] mbits = ((DoubleMask128)m).getBits(); for (int i = 0; i < res.length; i++) { @@ -769,16 +768,16 @@ public boolean laneIsSet(int i) { @ForceInline public boolean anyTrue() { return VectorSupport.test(BT_ne, DoubleMask128.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> anyTrueHelper(((DoubleMask128)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> anyTrueHelper(((DoubleMask128)m).getBits())); } @Override @ForceInline public boolean allTrue() { return VectorSupport.test(BT_overflow, DoubleMask128.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> allTrueHelper(((DoubleMask128)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> allTrueHelper(((DoubleMask128)m).getBits())); } @ForceInline @@ -786,7 +785,7 @@ this, vspecies().maskAll(true), static DoubleMask128 maskAll(boolean bit) { return VectorSupport.fromBitsCoerced(DoubleMask128.class, LANEBITS_TYPE_ORDINAL, VLENGTH, (bit ? -1 : 0), MODE_BROADCAST, null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + (v, _) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final DoubleMask128 TRUE_MASK = new DoubleMask128(true); private static final DoubleMask128 FALSE_MASK = new DoubleMask128(false); @@ -835,7 +834,7 @@ public DoubleSpecies vspecies() { @Override @ForceInline public DoubleVector128 toVector() { - return (DoubleVector128) toBitsVector().castShape(vspecies(), 0); + return (DoubleVector128) toBitsVector().castShape(VSPECIES, 0); } @Override @@ -846,7 +845,7 @@ LongVector128 toBitsVector() { @Override LongVector128 toBitsVector0() { - return ((LongVector128) vspecies().asIntegral().dummyVector()).vectorFactory(indices()); + return ((LongVector128) VSPECIES.asIntegral().dummyVector()).vectorFactory(indices()); } @Override @@ -920,7 +919,7 @@ public void intoMemorySegment(MemorySegment ms, long offset, ByteOrder bo) { @ForceInline public final DoubleMask128 laneIsValid() { return (DoubleMask128) toBitsVector().compare(VectorOperators.GE, 0) - .cast(vspecies()); + .cast(VSPECIES); } @ForceInline @@ -928,7 +927,7 @@ public final DoubleMask128 laneIsValid() { public final DoubleShuffle128 rearrange(VectorShuffle shuffle) { DoubleShuffle128 concreteShuffle = (DoubleShuffle128) shuffle; return (DoubleShuffle128) toBitsVector().rearrange(concreteShuffle.cast(LongVector.SPECIES_128)) - .toShuffle(vspecies(), false); + .toShuffle(VSPECIES, false); } @ForceInline @@ -941,7 +940,7 @@ public final DoubleShuffle128 wrapIndexes() { v = (LongVector128) v.blend(v.lanewise(VectorOperators.ADD, length()), v.compare(VectorOperators.LT, 0)); } - return (DoubleShuffle128) v.toShuffle(vspecies(), false); + return (DoubleShuffle128) v.toShuffle(VSPECIES, false); } private static long[] prepare(int[] indices, int offset) { diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector256.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector256.java index 5f176854dbd..c6bb4b7e3d3 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector256.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector256.java @@ -35,9 +35,8 @@ import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; -import static jdk.internal.vm.vector.VectorSupport.*; - import static jdk.incubator.vector.VectorOperators.*; +import static jdk.internal.vm.vector.VectorSupport.*; // -- This file was mechanically generated: Do not edit! -- // @@ -360,7 +359,7 @@ final VectorShuffle bitsToShuffle(AbstractSpecies dsp) { @Override @ForceInline public final DoubleShuffle256 toShuffle() { - return (DoubleShuffle256) toShuffle(vspecies(), false); + return (DoubleShuffle256) toShuffle(VSPECIES, false); } // Specialized unary testing @@ -613,7 +612,7 @@ boolean[] getBits() { @Override DoubleMask256 uOp(MUnOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); for (int i = 0; i < res.length; i++) { res[i] = f.apply(i, bits[i]); @@ -623,7 +622,7 @@ DoubleMask256 uOp(MUnOp f) { @Override DoubleMask256 bOp(VectorMask m, MBinOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); boolean[] mbits = ((DoubleMask256)m).getBits(); for (int i = 0; i < res.length; i++) { @@ -773,16 +772,16 @@ public boolean laneIsSet(int i) { @ForceInline public boolean anyTrue() { return VectorSupport.test(BT_ne, DoubleMask256.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> anyTrueHelper(((DoubleMask256)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> anyTrueHelper(((DoubleMask256)m).getBits())); } @Override @ForceInline public boolean allTrue() { return VectorSupport.test(BT_overflow, DoubleMask256.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> allTrueHelper(((DoubleMask256)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> allTrueHelper(((DoubleMask256)m).getBits())); } @ForceInline @@ -790,7 +789,7 @@ this, vspecies().maskAll(true), static DoubleMask256 maskAll(boolean bit) { return VectorSupport.fromBitsCoerced(DoubleMask256.class, LANEBITS_TYPE_ORDINAL, VLENGTH, (bit ? -1 : 0), MODE_BROADCAST, null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + (v, _) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final DoubleMask256 TRUE_MASK = new DoubleMask256(true); private static final DoubleMask256 FALSE_MASK = new DoubleMask256(false); @@ -839,7 +838,7 @@ public DoubleSpecies vspecies() { @Override @ForceInline public DoubleVector256 toVector() { - return (DoubleVector256) toBitsVector().castShape(vspecies(), 0); + return (DoubleVector256) toBitsVector().castShape(VSPECIES, 0); } @Override @@ -850,7 +849,7 @@ LongVector256 toBitsVector() { @Override LongVector256 toBitsVector0() { - return ((LongVector256) vspecies().asIntegral().dummyVector()).vectorFactory(indices()); + return ((LongVector256) VSPECIES.asIntegral().dummyVector()).vectorFactory(indices()); } @Override @@ -924,7 +923,7 @@ public void intoMemorySegment(MemorySegment ms, long offset, ByteOrder bo) { @ForceInline public final DoubleMask256 laneIsValid() { return (DoubleMask256) toBitsVector().compare(VectorOperators.GE, 0) - .cast(vspecies()); + .cast(VSPECIES); } @ForceInline @@ -932,7 +931,7 @@ public final DoubleMask256 laneIsValid() { public final DoubleShuffle256 rearrange(VectorShuffle shuffle) { DoubleShuffle256 concreteShuffle = (DoubleShuffle256) shuffle; return (DoubleShuffle256) toBitsVector().rearrange(concreteShuffle.cast(LongVector.SPECIES_256)) - .toShuffle(vspecies(), false); + .toShuffle(VSPECIES, false); } @ForceInline @@ -945,7 +944,7 @@ public final DoubleShuffle256 wrapIndexes() { v = (LongVector256) v.blend(v.lanewise(VectorOperators.ADD, length()), v.compare(VectorOperators.LT, 0)); } - return (DoubleShuffle256) v.toShuffle(vspecies(), false); + return (DoubleShuffle256) v.toShuffle(VSPECIES, false); } private static long[] prepare(int[] indices, int offset) { diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector512.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector512.java index 0696f48163d..fb1441efc63 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector512.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector512.java @@ -35,9 +35,8 @@ import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; -import static jdk.internal.vm.vector.VectorSupport.*; - import static jdk.incubator.vector.VectorOperators.*; +import static jdk.internal.vm.vector.VectorSupport.*; // -- This file was mechanically generated: Do not edit! -- // @@ -360,7 +359,7 @@ final VectorShuffle bitsToShuffle(AbstractSpecies dsp) { @Override @ForceInline public final DoubleShuffle512 toShuffle() { - return (DoubleShuffle512) toShuffle(vspecies(), false); + return (DoubleShuffle512) toShuffle(VSPECIES, false); } // Specialized unary testing @@ -621,7 +620,7 @@ boolean[] getBits() { @Override DoubleMask512 uOp(MUnOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); for (int i = 0; i < res.length; i++) { res[i] = f.apply(i, bits[i]); @@ -631,7 +630,7 @@ DoubleMask512 uOp(MUnOp f) { @Override DoubleMask512 bOp(VectorMask m, MBinOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); boolean[] mbits = ((DoubleMask512)m).getBits(); for (int i = 0; i < res.length; i++) { @@ -781,16 +780,16 @@ public boolean laneIsSet(int i) { @ForceInline public boolean anyTrue() { return VectorSupport.test(BT_ne, DoubleMask512.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> anyTrueHelper(((DoubleMask512)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> anyTrueHelper(((DoubleMask512)m).getBits())); } @Override @ForceInline public boolean allTrue() { return VectorSupport.test(BT_overflow, DoubleMask512.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> allTrueHelper(((DoubleMask512)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> allTrueHelper(((DoubleMask512)m).getBits())); } @ForceInline @@ -798,7 +797,7 @@ this, vspecies().maskAll(true), static DoubleMask512 maskAll(boolean bit) { return VectorSupport.fromBitsCoerced(DoubleMask512.class, LANEBITS_TYPE_ORDINAL, VLENGTH, (bit ? -1 : 0), MODE_BROADCAST, null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + (v, _) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final DoubleMask512 TRUE_MASK = new DoubleMask512(true); private static final DoubleMask512 FALSE_MASK = new DoubleMask512(false); @@ -847,7 +846,7 @@ public DoubleSpecies vspecies() { @Override @ForceInline public DoubleVector512 toVector() { - return (DoubleVector512) toBitsVector().castShape(vspecies(), 0); + return (DoubleVector512) toBitsVector().castShape(VSPECIES, 0); } @Override @@ -858,7 +857,7 @@ LongVector512 toBitsVector() { @Override LongVector512 toBitsVector0() { - return ((LongVector512) vspecies().asIntegral().dummyVector()).vectorFactory(indices()); + return ((LongVector512) VSPECIES.asIntegral().dummyVector()).vectorFactory(indices()); } @Override @@ -932,7 +931,7 @@ public void intoMemorySegment(MemorySegment ms, long offset, ByteOrder bo) { @ForceInline public final DoubleMask512 laneIsValid() { return (DoubleMask512) toBitsVector().compare(VectorOperators.GE, 0) - .cast(vspecies()); + .cast(VSPECIES); } @ForceInline @@ -940,7 +939,7 @@ public final DoubleMask512 laneIsValid() { public final DoubleShuffle512 rearrange(VectorShuffle shuffle) { DoubleShuffle512 concreteShuffle = (DoubleShuffle512) shuffle; return (DoubleShuffle512) toBitsVector().rearrange(concreteShuffle.cast(LongVector.SPECIES_512)) - .toShuffle(vspecies(), false); + .toShuffle(VSPECIES, false); } @ForceInline @@ -953,7 +952,7 @@ public final DoubleShuffle512 wrapIndexes() { v = (LongVector512) v.blend(v.lanewise(VectorOperators.ADD, length()), v.compare(VectorOperators.LT, 0)); } - return (DoubleShuffle512) v.toShuffle(vspecies(), false); + return (DoubleShuffle512) v.toShuffle(VSPECIES, false); } private static long[] prepare(int[] indices, int offset) { diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector64.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector64.java index 5b74c2c4619..5583cff80e1 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector64.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector64.java @@ -35,9 +35,8 @@ import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; -import static jdk.internal.vm.vector.VectorSupport.*; - import static jdk.incubator.vector.VectorOperators.*; +import static jdk.internal.vm.vector.VectorSupport.*; // -- This file was mechanically generated: Do not edit! -- // @@ -360,7 +359,7 @@ final VectorShuffle bitsToShuffle(AbstractSpecies dsp) { @Override @ForceInline public final DoubleShuffle64 toShuffle() { - return (DoubleShuffle64) toShuffle(vspecies(), false); + return (DoubleShuffle64) toShuffle(VSPECIES, false); } // Specialized unary testing @@ -607,7 +606,7 @@ boolean[] getBits() { @Override DoubleMask64 uOp(MUnOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); for (int i = 0; i < res.length; i++) { res[i] = f.apply(i, bits[i]); @@ -617,7 +616,7 @@ DoubleMask64 uOp(MUnOp f) { @Override DoubleMask64 bOp(VectorMask m, MBinOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); boolean[] mbits = ((DoubleMask64)m).getBits(); for (int i = 0; i < res.length; i++) { @@ -767,16 +766,16 @@ public boolean laneIsSet(int i) { @ForceInline public boolean anyTrue() { return VectorSupport.test(BT_ne, DoubleMask64.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> anyTrueHelper(((DoubleMask64)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> anyTrueHelper(((DoubleMask64)m).getBits())); } @Override @ForceInline public boolean allTrue() { return VectorSupport.test(BT_overflow, DoubleMask64.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> allTrueHelper(((DoubleMask64)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> allTrueHelper(((DoubleMask64)m).getBits())); } @ForceInline @@ -784,7 +783,7 @@ this, vspecies().maskAll(true), static DoubleMask64 maskAll(boolean bit) { return VectorSupport.fromBitsCoerced(DoubleMask64.class, LANEBITS_TYPE_ORDINAL, VLENGTH, (bit ? -1 : 0), MODE_BROADCAST, null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + (v, _) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final DoubleMask64 TRUE_MASK = new DoubleMask64(true); private static final DoubleMask64 FALSE_MASK = new DoubleMask64(false); @@ -833,7 +832,7 @@ public DoubleSpecies vspecies() { @Override @ForceInline public DoubleVector64 toVector() { - return (DoubleVector64) toBitsVector().castShape(vspecies(), 0); + return (DoubleVector64) toBitsVector().castShape(VSPECIES, 0); } @Override @@ -844,7 +843,7 @@ LongVector64 toBitsVector() { @Override LongVector64 toBitsVector0() { - return ((LongVector64) vspecies().asIntegral().dummyVector()).vectorFactory(indices()); + return ((LongVector64) VSPECIES.asIntegral().dummyVector()).vectorFactory(indices()); } @Override @@ -918,7 +917,7 @@ public void intoMemorySegment(MemorySegment ms, long offset, ByteOrder bo) { @ForceInline public final DoubleMask64 laneIsValid() { return (DoubleMask64) toBitsVector().compare(VectorOperators.GE, 0) - .cast(vspecies()); + .cast(VSPECIES); } @ForceInline @@ -926,7 +925,7 @@ public final DoubleMask64 laneIsValid() { public final DoubleShuffle64 rearrange(VectorShuffle shuffle) { DoubleShuffle64 concreteShuffle = (DoubleShuffle64) shuffle; return (DoubleShuffle64) toBitsVector().rearrange(concreteShuffle.cast(LongVector.SPECIES_64)) - .toShuffle(vspecies(), false); + .toShuffle(VSPECIES, false); } @ForceInline @@ -939,7 +938,7 @@ public final DoubleShuffle64 wrapIndexes() { v = (LongVector64) v.blend(v.lanewise(VectorOperators.ADD, length()), v.compare(VectorOperators.LT, 0)); } - return (DoubleShuffle64) v.toShuffle(vspecies(), false); + return (DoubleShuffle64) v.toShuffle(VSPECIES, false); } private static long[] prepare(int[] indices, int offset) { diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVectorMax.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVectorMax.java index 07d227d641a..41272a5a5e5 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVectorMax.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVectorMax.java @@ -35,9 +35,8 @@ import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; -import static jdk.internal.vm.vector.VectorSupport.*; - import static jdk.incubator.vector.VectorOperators.*; +import static jdk.internal.vm.vector.VectorSupport.*; // -- This file was mechanically generated: Do not edit! -- // @@ -360,7 +359,7 @@ final VectorShuffle bitsToShuffle(AbstractSpecies dsp) { @Override @ForceInline public final DoubleShuffleMax toShuffle() { - return (DoubleShuffleMax) toShuffle(vspecies(), false); + return (DoubleShuffleMax) toShuffle(VSPECIES, false); } // Specialized unary testing @@ -606,7 +605,7 @@ boolean[] getBits() { @Override DoubleMaskMax uOp(MUnOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); for (int i = 0; i < res.length; i++) { res[i] = f.apply(i, bits[i]); @@ -616,7 +615,7 @@ DoubleMaskMax uOp(MUnOp f) { @Override DoubleMaskMax bOp(VectorMask m, MBinOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); boolean[] mbits = ((DoubleMaskMax)m).getBits(); for (int i = 0; i < res.length; i++) { @@ -766,16 +765,16 @@ public boolean laneIsSet(int i) { @ForceInline public boolean anyTrue() { return VectorSupport.test(BT_ne, DoubleMaskMax.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> anyTrueHelper(((DoubleMaskMax)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> anyTrueHelper(((DoubleMaskMax)m).getBits())); } @Override @ForceInline public boolean allTrue() { return VectorSupport.test(BT_overflow, DoubleMaskMax.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> allTrueHelper(((DoubleMaskMax)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> allTrueHelper(((DoubleMaskMax)m).getBits())); } @ForceInline @@ -783,7 +782,7 @@ this, vspecies().maskAll(true), static DoubleMaskMax maskAll(boolean bit) { return VectorSupport.fromBitsCoerced(DoubleMaskMax.class, LANEBITS_TYPE_ORDINAL, VLENGTH, (bit ? -1 : 0), MODE_BROADCAST, null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + (v, _) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final DoubleMaskMax TRUE_MASK = new DoubleMaskMax(true); private static final DoubleMaskMax FALSE_MASK = new DoubleMaskMax(false); @@ -832,7 +831,7 @@ public DoubleSpecies vspecies() { @Override @ForceInline public DoubleVectorMax toVector() { - return (DoubleVectorMax) toBitsVector().castShape(vspecies(), 0); + return (DoubleVectorMax) toBitsVector().castShape(VSPECIES, 0); } @Override @@ -843,7 +842,7 @@ LongVectorMax toBitsVector() { @Override LongVectorMax toBitsVector0() { - return ((LongVectorMax) vspecies().asIntegral().dummyVector()).vectorFactory(indices()); + return ((LongVectorMax) VSPECIES.asIntegral().dummyVector()).vectorFactory(indices()); } @Override @@ -917,7 +916,7 @@ public void intoMemorySegment(MemorySegment ms, long offset, ByteOrder bo) { @ForceInline public final DoubleMaskMax laneIsValid() { return (DoubleMaskMax) toBitsVector().compare(VectorOperators.GE, 0) - .cast(vspecies()); + .cast(VSPECIES); } @ForceInline @@ -925,7 +924,7 @@ public final DoubleMaskMax laneIsValid() { public final DoubleShuffleMax rearrange(VectorShuffle shuffle) { DoubleShuffleMax concreteShuffle = (DoubleShuffleMax) shuffle; return (DoubleShuffleMax) toBitsVector().rearrange(concreteShuffle.cast(LongVector.SPECIES_MAX)) - .toShuffle(vspecies(), false); + .toShuffle(VSPECIES, false); } @ForceInline @@ -938,7 +937,7 @@ public final DoubleShuffleMax wrapIndexes() { v = (LongVectorMax) v.blend(v.lanewise(VectorOperators.ADD, length()), v.compare(VectorOperators.LT, 0)); } - return (DoubleShuffleMax) v.toShuffle(vspecies(), false); + return (DoubleShuffleMax) v.toShuffle(VSPECIES, false); } private static long[] prepare(int[] indices, int offset) { diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float16Consts.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float16Consts.java index 48c4d2199b1..b70b11b0a49 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float16Consts.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float16Consts.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,7 +34,7 @@ * {@code Float16} type. */ -class Float16Consts { +final class Float16Consts { /** * Don't let anyone instantiate this class. */ 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 5862a295fa3..cdf2532e4d9 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 @@ -49,7 +49,8 @@ * {@code float} values. */ @SuppressWarnings("cast") // warning: redundant cast -public abstract class FloatVector extends AbstractVector { +public abstract sealed class FloatVector extends AbstractVector + permits FloatVector64, FloatVector128, FloatVector256, FloatVector512, FloatVectorMax { FloatVector(float[] vec) { super(vec); diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector128.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector128.java index 17c1fdba4fc..24888e966da 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector128.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector128.java @@ -25,7 +25,6 @@ package jdk.incubator.vector; import java.lang.foreign.MemorySegment; -import java.lang.foreign.ValueLayout; import java.nio.ByteOrder; import java.util.Arrays; import java.util.Objects; @@ -35,9 +34,8 @@ import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; -import static jdk.internal.vm.vector.VectorSupport.*; - import static jdk.incubator.vector.VectorOperators.*; +import static jdk.internal.vm.vector.VectorSupport.*; // -- This file was mechanically generated: Do not edit! -- // @@ -360,7 +358,7 @@ final VectorShuffle bitsToShuffle(AbstractSpecies dsp) { @Override @ForceInline public final FloatShuffle128 toShuffle() { - return (FloatShuffle128) toShuffle(vspecies(), false); + return (FloatShuffle128) toShuffle(VSPECIES, false); } // Specialized unary testing @@ -613,7 +611,7 @@ boolean[] getBits() { @Override FloatMask128 uOp(MUnOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); for (int i = 0; i < res.length; i++) { res[i] = f.apply(i, bits[i]); @@ -623,7 +621,7 @@ FloatMask128 uOp(MUnOp f) { @Override FloatMask128 bOp(VectorMask m, MBinOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); boolean[] mbits = ((FloatMask128)m).getBits(); for (int i = 0; i < res.length; i++) { @@ -773,16 +771,16 @@ public boolean laneIsSet(int i) { @ForceInline public boolean anyTrue() { return VectorSupport.test(BT_ne, FloatMask128.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> anyTrueHelper(((FloatMask128)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> anyTrueHelper(((FloatMask128)m).getBits())); } @Override @ForceInline public boolean allTrue() { return VectorSupport.test(BT_overflow, FloatMask128.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> allTrueHelper(((FloatMask128)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> allTrueHelper(((FloatMask128)m).getBits())); } @ForceInline @@ -790,7 +788,7 @@ this, vspecies().maskAll(true), static FloatMask128 maskAll(boolean bit) { return VectorSupport.fromBitsCoerced(FloatMask128.class, LANEBITS_TYPE_ORDINAL, VLENGTH, (bit ? -1 : 0), MODE_BROADCAST, null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + (v, _) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final FloatMask128 TRUE_MASK = new FloatMask128(true); private static final FloatMask128 FALSE_MASK = new FloatMask128(false); @@ -839,7 +837,7 @@ public FloatSpecies vspecies() { @Override @ForceInline public FloatVector128 toVector() { - return (FloatVector128) toBitsVector().castShape(vspecies(), 0); + return (FloatVector128) toBitsVector().castShape(VSPECIES, 0); } @Override @@ -850,7 +848,7 @@ IntVector128 toBitsVector() { @Override IntVector128 toBitsVector0() { - return ((IntVector128) vspecies().asIntegral().dummyVector()).vectorFactory(indices()); + return ((IntVector128) VSPECIES.asIntegral().dummyVector()).vectorFactory(indices()); } @Override @@ -875,7 +873,7 @@ public void intoMemorySegment(MemorySegment ms, long offset, ByteOrder bo) { @ForceInline public final FloatMask128 laneIsValid() { return (FloatMask128) toBitsVector().compare(VectorOperators.GE, 0) - .cast(vspecies()); + .cast(VSPECIES); } @ForceInline @@ -883,7 +881,7 @@ public final FloatMask128 laneIsValid() { public final FloatShuffle128 rearrange(VectorShuffle shuffle) { FloatShuffle128 concreteShuffle = (FloatShuffle128) shuffle; return (FloatShuffle128) toBitsVector().rearrange(concreteShuffle.cast(IntVector.SPECIES_128)) - .toShuffle(vspecies(), false); + .toShuffle(VSPECIES, false); } @ForceInline @@ -896,7 +894,7 @@ public final FloatShuffle128 wrapIndexes() { v = (IntVector128) v.blend(v.lanewise(VectorOperators.ADD, length()), v.compare(VectorOperators.LT, 0)); } - return (FloatShuffle128) v.toShuffle(vspecies(), false); + return (FloatShuffle128) v.toShuffle(VSPECIES, false); } private static int[] prepare(int[] indices, int offset) { diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector256.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector256.java index 7badb71415e..ecbd80046f4 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector256.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector256.java @@ -25,7 +25,6 @@ package jdk.incubator.vector; import java.lang.foreign.MemorySegment; -import java.lang.foreign.ValueLayout; import java.nio.ByteOrder; import java.util.Arrays; import java.util.Objects; @@ -35,9 +34,8 @@ import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; -import static jdk.internal.vm.vector.VectorSupport.*; - import static jdk.incubator.vector.VectorOperators.*; +import static jdk.internal.vm.vector.VectorSupport.*; // -- This file was mechanically generated: Do not edit! -- // @@ -360,7 +358,7 @@ final VectorShuffle bitsToShuffle(AbstractSpecies dsp) { @Override @ForceInline public final FloatShuffle256 toShuffle() { - return (FloatShuffle256) toShuffle(vspecies(), false); + return (FloatShuffle256) toShuffle(VSPECIES, false); } // Specialized unary testing @@ -621,7 +619,7 @@ boolean[] getBits() { @Override FloatMask256 uOp(MUnOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); for (int i = 0; i < res.length; i++) { res[i] = f.apply(i, bits[i]); @@ -631,7 +629,7 @@ FloatMask256 uOp(MUnOp f) { @Override FloatMask256 bOp(VectorMask m, MBinOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); boolean[] mbits = ((FloatMask256)m).getBits(); for (int i = 0; i < res.length; i++) { @@ -781,16 +779,16 @@ public boolean laneIsSet(int i) { @ForceInline public boolean anyTrue() { return VectorSupport.test(BT_ne, FloatMask256.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> anyTrueHelper(((FloatMask256)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> anyTrueHelper(((FloatMask256)m).getBits())); } @Override @ForceInline public boolean allTrue() { return VectorSupport.test(BT_overflow, FloatMask256.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> allTrueHelper(((FloatMask256)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> allTrueHelper(((FloatMask256)m).getBits())); } @ForceInline @@ -798,7 +796,7 @@ this, vspecies().maskAll(true), static FloatMask256 maskAll(boolean bit) { return VectorSupport.fromBitsCoerced(FloatMask256.class, LANEBITS_TYPE_ORDINAL, VLENGTH, (bit ? -1 : 0), MODE_BROADCAST, null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + (v, _) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final FloatMask256 TRUE_MASK = new FloatMask256(true); private static final FloatMask256 FALSE_MASK = new FloatMask256(false); @@ -847,7 +845,7 @@ public FloatSpecies vspecies() { @Override @ForceInline public FloatVector256 toVector() { - return (FloatVector256) toBitsVector().castShape(vspecies(), 0); + return (FloatVector256) toBitsVector().castShape(VSPECIES, 0); } @Override @@ -858,7 +856,7 @@ IntVector256 toBitsVector() { @Override IntVector256 toBitsVector0() { - return ((IntVector256) vspecies().asIntegral().dummyVector()).vectorFactory(indices()); + return ((IntVector256) VSPECIES.asIntegral().dummyVector()).vectorFactory(indices()); } @Override @@ -883,7 +881,7 @@ public void intoMemorySegment(MemorySegment ms, long offset, ByteOrder bo) { @ForceInline public final FloatMask256 laneIsValid() { return (FloatMask256) toBitsVector().compare(VectorOperators.GE, 0) - .cast(vspecies()); + .cast(VSPECIES); } @ForceInline @@ -891,7 +889,7 @@ public final FloatMask256 laneIsValid() { public final FloatShuffle256 rearrange(VectorShuffle shuffle) { FloatShuffle256 concreteShuffle = (FloatShuffle256) shuffle; return (FloatShuffle256) toBitsVector().rearrange(concreteShuffle.cast(IntVector.SPECIES_256)) - .toShuffle(vspecies(), false); + .toShuffle(VSPECIES, false); } @ForceInline @@ -904,7 +902,7 @@ public final FloatShuffle256 wrapIndexes() { v = (IntVector256) v.blend(v.lanewise(VectorOperators.ADD, length()), v.compare(VectorOperators.LT, 0)); } - return (FloatShuffle256) v.toShuffle(vspecies(), false); + return (FloatShuffle256) v.toShuffle(VSPECIES, false); } private static int[] prepare(int[] indices, int offset) { diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector512.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector512.java index 7c0786b7fcd..b5a934dd90c 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector512.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector512.java @@ -25,7 +25,6 @@ package jdk.incubator.vector; import java.lang.foreign.MemorySegment; -import java.lang.foreign.ValueLayout; import java.nio.ByteOrder; import java.util.Arrays; import java.util.Objects; @@ -35,9 +34,8 @@ import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; -import static jdk.internal.vm.vector.VectorSupport.*; - import static jdk.incubator.vector.VectorOperators.*; +import static jdk.internal.vm.vector.VectorSupport.*; // -- This file was mechanically generated: Do not edit! -- // @@ -360,7 +358,7 @@ final VectorShuffle bitsToShuffle(AbstractSpecies dsp) { @Override @ForceInline public final FloatShuffle512 toShuffle() { - return (FloatShuffle512) toShuffle(vspecies(), false); + return (FloatShuffle512) toShuffle(VSPECIES, false); } // Specialized unary testing @@ -637,7 +635,7 @@ boolean[] getBits() { @Override FloatMask512 uOp(MUnOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); for (int i = 0; i < res.length; i++) { res[i] = f.apply(i, bits[i]); @@ -647,7 +645,7 @@ FloatMask512 uOp(MUnOp f) { @Override FloatMask512 bOp(VectorMask m, MBinOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); boolean[] mbits = ((FloatMask512)m).getBits(); for (int i = 0; i < res.length; i++) { @@ -797,16 +795,16 @@ public boolean laneIsSet(int i) { @ForceInline public boolean anyTrue() { return VectorSupport.test(BT_ne, FloatMask512.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> anyTrueHelper(((FloatMask512)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> anyTrueHelper(((FloatMask512)m).getBits())); } @Override @ForceInline public boolean allTrue() { return VectorSupport.test(BT_overflow, FloatMask512.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> allTrueHelper(((FloatMask512)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> allTrueHelper(((FloatMask512)m).getBits())); } @ForceInline @@ -814,7 +812,7 @@ this, vspecies().maskAll(true), static FloatMask512 maskAll(boolean bit) { return VectorSupport.fromBitsCoerced(FloatMask512.class, LANEBITS_TYPE_ORDINAL, VLENGTH, (bit ? -1 : 0), MODE_BROADCAST, null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + (v, _) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final FloatMask512 TRUE_MASK = new FloatMask512(true); private static final FloatMask512 FALSE_MASK = new FloatMask512(false); @@ -863,7 +861,7 @@ public FloatSpecies vspecies() { @Override @ForceInline public FloatVector512 toVector() { - return (FloatVector512) toBitsVector().castShape(vspecies(), 0); + return (FloatVector512) toBitsVector().castShape(VSPECIES, 0); } @Override @@ -874,7 +872,7 @@ IntVector512 toBitsVector() { @Override IntVector512 toBitsVector0() { - return ((IntVector512) vspecies().asIntegral().dummyVector()).vectorFactory(indices()); + return ((IntVector512) VSPECIES.asIntegral().dummyVector()).vectorFactory(indices()); } @Override @@ -899,7 +897,7 @@ public void intoMemorySegment(MemorySegment ms, long offset, ByteOrder bo) { @ForceInline public final FloatMask512 laneIsValid() { return (FloatMask512) toBitsVector().compare(VectorOperators.GE, 0) - .cast(vspecies()); + .cast(VSPECIES); } @ForceInline @@ -907,7 +905,7 @@ public final FloatMask512 laneIsValid() { public final FloatShuffle512 rearrange(VectorShuffle shuffle) { FloatShuffle512 concreteShuffle = (FloatShuffle512) shuffle; return (FloatShuffle512) toBitsVector().rearrange(concreteShuffle.cast(IntVector.SPECIES_512)) - .toShuffle(vspecies(), false); + .toShuffle(VSPECIES, false); } @ForceInline @@ -920,7 +918,7 @@ public final FloatShuffle512 wrapIndexes() { v = (IntVector512) v.blend(v.lanewise(VectorOperators.ADD, length()), v.compare(VectorOperators.LT, 0)); } - return (FloatShuffle512) v.toShuffle(vspecies(), false); + return (FloatShuffle512) v.toShuffle(VSPECIES, false); } private static int[] prepare(int[] indices, int offset) { diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector64.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector64.java index fc4877e5ae8..4d3118739ea 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector64.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector64.java @@ -25,7 +25,6 @@ package jdk.incubator.vector; import java.lang.foreign.MemorySegment; -import java.lang.foreign.ValueLayout; import java.nio.ByteOrder; import java.util.Arrays; import java.util.Objects; @@ -35,9 +34,8 @@ import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; -import static jdk.internal.vm.vector.VectorSupport.*; - import static jdk.incubator.vector.VectorOperators.*; +import static jdk.internal.vm.vector.VectorSupport.*; // -- This file was mechanically generated: Do not edit! -- // @@ -360,7 +358,7 @@ final VectorShuffle bitsToShuffle(AbstractSpecies dsp) { @Override @ForceInline public final FloatShuffle64 toShuffle() { - return (FloatShuffle64) toShuffle(vspecies(), false); + return (FloatShuffle64) toShuffle(VSPECIES, false); } // Specialized unary testing @@ -609,7 +607,7 @@ boolean[] getBits() { @Override FloatMask64 uOp(MUnOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); for (int i = 0; i < res.length; i++) { res[i] = f.apply(i, bits[i]); @@ -619,7 +617,7 @@ FloatMask64 uOp(MUnOp f) { @Override FloatMask64 bOp(VectorMask m, MBinOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); boolean[] mbits = ((FloatMask64)m).getBits(); for (int i = 0; i < res.length; i++) { @@ -769,16 +767,16 @@ public boolean laneIsSet(int i) { @ForceInline public boolean anyTrue() { return VectorSupport.test(BT_ne, FloatMask64.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> anyTrueHelper(((FloatMask64)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> anyTrueHelper(((FloatMask64)m).getBits())); } @Override @ForceInline public boolean allTrue() { return VectorSupport.test(BT_overflow, FloatMask64.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> allTrueHelper(((FloatMask64)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> allTrueHelper(((FloatMask64)m).getBits())); } @ForceInline @@ -786,7 +784,7 @@ this, vspecies().maskAll(true), static FloatMask64 maskAll(boolean bit) { return VectorSupport.fromBitsCoerced(FloatMask64.class, LANEBITS_TYPE_ORDINAL, VLENGTH, (bit ? -1 : 0), MODE_BROADCAST, null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + (v, _) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final FloatMask64 TRUE_MASK = new FloatMask64(true); private static final FloatMask64 FALSE_MASK = new FloatMask64(false); @@ -835,7 +833,7 @@ public FloatSpecies vspecies() { @Override @ForceInline public FloatVector64 toVector() { - return (FloatVector64) toBitsVector().castShape(vspecies(), 0); + return (FloatVector64) toBitsVector().castShape(VSPECIES, 0); } @Override @@ -846,7 +844,7 @@ IntVector64 toBitsVector() { @Override IntVector64 toBitsVector0() { - return ((IntVector64) vspecies().asIntegral().dummyVector()).vectorFactory(indices()); + return ((IntVector64) VSPECIES.asIntegral().dummyVector()).vectorFactory(indices()); } @Override @@ -871,7 +869,7 @@ public void intoMemorySegment(MemorySegment ms, long offset, ByteOrder bo) { @ForceInline public final FloatMask64 laneIsValid() { return (FloatMask64) toBitsVector().compare(VectorOperators.GE, 0) - .cast(vspecies()); + .cast(VSPECIES); } @ForceInline @@ -879,7 +877,7 @@ public final FloatMask64 laneIsValid() { public final FloatShuffle64 rearrange(VectorShuffle shuffle) { FloatShuffle64 concreteShuffle = (FloatShuffle64) shuffle; return (FloatShuffle64) toBitsVector().rearrange(concreteShuffle.cast(IntVector.SPECIES_64)) - .toShuffle(vspecies(), false); + .toShuffle(VSPECIES, false); } @ForceInline @@ -892,7 +890,7 @@ public final FloatShuffle64 wrapIndexes() { v = (IntVector64) v.blend(v.lanewise(VectorOperators.ADD, length()), v.compare(VectorOperators.LT, 0)); } - return (FloatShuffle64) v.toShuffle(vspecies(), false); + return (FloatShuffle64) v.toShuffle(VSPECIES, false); } private static int[] prepare(int[] indices, int offset) { diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVectorMax.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVectorMax.java index 5cfafecdb58..f115a1c79b8 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVectorMax.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVectorMax.java @@ -25,7 +25,6 @@ package jdk.incubator.vector; import java.lang.foreign.MemorySegment; -import java.lang.foreign.ValueLayout; import java.nio.ByteOrder; import java.util.Arrays; import java.util.Objects; @@ -35,9 +34,8 @@ import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; -import static jdk.internal.vm.vector.VectorSupport.*; - import static jdk.incubator.vector.VectorOperators.*; +import static jdk.internal.vm.vector.VectorSupport.*; // -- This file was mechanically generated: Do not edit! -- // @@ -360,7 +358,7 @@ final VectorShuffle bitsToShuffle(AbstractSpecies dsp) { @Override @ForceInline public final FloatShuffleMax toShuffle() { - return (FloatShuffleMax) toShuffle(vspecies(), false); + return (FloatShuffleMax) toShuffle(VSPECIES, false); } // Specialized unary testing @@ -606,7 +604,7 @@ boolean[] getBits() { @Override FloatMaskMax uOp(MUnOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); for (int i = 0; i < res.length; i++) { res[i] = f.apply(i, bits[i]); @@ -616,7 +614,7 @@ FloatMaskMax uOp(MUnOp f) { @Override FloatMaskMax bOp(VectorMask m, MBinOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); boolean[] mbits = ((FloatMaskMax)m).getBits(); for (int i = 0; i < res.length; i++) { @@ -766,16 +764,16 @@ public boolean laneIsSet(int i) { @ForceInline public boolean anyTrue() { return VectorSupport.test(BT_ne, FloatMaskMax.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> anyTrueHelper(((FloatMaskMax)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> anyTrueHelper(((FloatMaskMax)m).getBits())); } @Override @ForceInline public boolean allTrue() { return VectorSupport.test(BT_overflow, FloatMaskMax.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> allTrueHelper(((FloatMaskMax)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> allTrueHelper(((FloatMaskMax)m).getBits())); } @ForceInline @@ -783,7 +781,7 @@ this, vspecies().maskAll(true), static FloatMaskMax maskAll(boolean bit) { return VectorSupport.fromBitsCoerced(FloatMaskMax.class, LANEBITS_TYPE_ORDINAL, VLENGTH, (bit ? -1 : 0), MODE_BROADCAST, null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + (v, _) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final FloatMaskMax TRUE_MASK = new FloatMaskMax(true); private static final FloatMaskMax FALSE_MASK = new FloatMaskMax(false); @@ -832,7 +830,7 @@ public FloatSpecies vspecies() { @Override @ForceInline public FloatVectorMax toVector() { - return (FloatVectorMax) toBitsVector().castShape(vspecies(), 0); + return (FloatVectorMax) toBitsVector().castShape(VSPECIES, 0); } @Override @@ -843,7 +841,7 @@ IntVectorMax toBitsVector() { @Override IntVectorMax toBitsVector0() { - return ((IntVectorMax) vspecies().asIntegral().dummyVector()).vectorFactory(indices()); + return ((IntVectorMax) VSPECIES.asIntegral().dummyVector()).vectorFactory(indices()); } @Override @@ -868,7 +866,7 @@ public void intoMemorySegment(MemorySegment ms, long offset, ByteOrder bo) { @ForceInline public final FloatMaskMax laneIsValid() { return (FloatMaskMax) toBitsVector().compare(VectorOperators.GE, 0) - .cast(vspecies()); + .cast(VSPECIES); } @ForceInline @@ -876,7 +874,7 @@ public final FloatMaskMax laneIsValid() { public final FloatShuffleMax rearrange(VectorShuffle shuffle) { FloatShuffleMax concreteShuffle = (FloatShuffleMax) shuffle; return (FloatShuffleMax) toBitsVector().rearrange(concreteShuffle.cast(IntVector.SPECIES_MAX)) - .toShuffle(vspecies(), false); + .toShuffle(VSPECIES, false); } @ForceInline @@ -889,7 +887,7 @@ public final FloatShuffleMax wrapIndexes() { v = (IntVectorMax) v.blend(v.lanewise(VectorOperators.ADD, length()), v.compare(VectorOperators.LT, 0)); } - return (FloatShuffleMax) v.toShuffle(vspecies(), false); + return (FloatShuffleMax) v.toShuffle(VSPECIES, false); } private static int[] prepare(int[] indices, int offset) { 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 445c4dfb006..37b7e3eeae4 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 @@ -49,7 +49,8 @@ * {@code int} values. */ @SuppressWarnings("cast") // warning: redundant cast -public abstract class IntVector extends AbstractVector { +public abstract sealed class IntVector extends AbstractVector + permits IntVector64, IntVector128, IntVector256, IntVector512, IntVectorMax { IntVector(int[] vec) { super(vec); diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector128.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector128.java index 04b10386127..f64328e2a1e 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector128.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector128.java @@ -25,7 +25,6 @@ package jdk.incubator.vector; import java.lang.foreign.MemorySegment; -import java.lang.foreign.ValueLayout; import java.nio.ByteOrder; import java.util.Arrays; import java.util.Objects; @@ -35,9 +34,8 @@ import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; -import static jdk.internal.vm.vector.VectorSupport.*; - import static jdk.incubator.vector.VectorOperators.*; +import static jdk.internal.vm.vector.VectorSupport.*; // -- This file was mechanically generated: Do not edit! -- // @@ -373,7 +371,7 @@ final VectorShuffle bitsToShuffle(AbstractSpecies dsp) { @Override @ForceInline public final IntShuffle128 toShuffle() { - return (IntShuffle128) toShuffle(vspecies(), false); + return (IntShuffle128) toShuffle(VSPECIES, false); } // Specialized unary testing @@ -624,7 +622,7 @@ boolean[] getBits() { @Override IntMask128 uOp(MUnOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); for (int i = 0; i < res.length; i++) { res[i] = f.apply(i, bits[i]); @@ -634,7 +632,7 @@ IntMask128 uOp(MUnOp f) { @Override IntMask128 bOp(VectorMask m, MBinOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); boolean[] mbits = ((IntMask128)m).getBits(); for (int i = 0; i < res.length; i++) { @@ -784,16 +782,16 @@ public boolean laneIsSet(int i) { @ForceInline public boolean anyTrue() { return VectorSupport.test(BT_ne, IntMask128.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> anyTrueHelper(((IntMask128)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> anyTrueHelper(((IntMask128)m).getBits())); } @Override @ForceInline public boolean allTrue() { return VectorSupport.test(BT_overflow, IntMask128.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> allTrueHelper(((IntMask128)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> allTrueHelper(((IntMask128)m).getBits())); } @ForceInline @@ -801,7 +799,7 @@ this, vspecies().maskAll(true), static IntMask128 maskAll(boolean bit) { return VectorSupport.fromBitsCoerced(IntMask128.class, LANEBITS_TYPE_ORDINAL, VLENGTH, (bit ? -1 : 0), MODE_BROADCAST, null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + (v, _) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final IntMask128 TRUE_MASK = new IntMask128(true); private static final IntMask128 FALSE_MASK = new IntMask128(false); @@ -861,7 +859,7 @@ IntVector128 toBitsVector() { @Override IntVector128 toBitsVector0() { - return ((IntVector128) vspecies().asIntegral().dummyVector()).vectorFactory(indices()); + return ((IntVector128) VSPECIES.asIntegral().dummyVector()).vectorFactory(indices()); } @Override @@ -886,7 +884,7 @@ public void intoMemorySegment(MemorySegment ms, long offset, ByteOrder bo) { @ForceInline public final IntMask128 laneIsValid() { return (IntMask128) toBitsVector().compare(VectorOperators.GE, 0) - .cast(vspecies()); + .cast(VSPECIES); } @ForceInline @@ -894,7 +892,7 @@ public final IntMask128 laneIsValid() { public final IntShuffle128 rearrange(VectorShuffle shuffle) { IntShuffle128 concreteShuffle = (IntShuffle128) shuffle; return (IntShuffle128) toBitsVector().rearrange(concreteShuffle) - .toShuffle(vspecies(), false); + .toShuffle(VSPECIES, false); } @ForceInline @@ -907,7 +905,7 @@ public final IntShuffle128 wrapIndexes() { v = (IntVector128) v.blend(v.lanewise(VectorOperators.ADD, length()), v.compare(VectorOperators.LT, 0)); } - return (IntShuffle128) v.toShuffle(vspecies(), false); + return (IntShuffle128) v.toShuffle(VSPECIES, false); } private static int[] prepare(int[] indices, int offset) { diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector256.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector256.java index 20d9df1cd60..58a1667d2ac 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector256.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector256.java @@ -25,7 +25,6 @@ package jdk.incubator.vector; import java.lang.foreign.MemorySegment; -import java.lang.foreign.ValueLayout; import java.nio.ByteOrder; import java.util.Arrays; import java.util.Objects; @@ -35,9 +34,8 @@ import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; -import static jdk.internal.vm.vector.VectorSupport.*; - import static jdk.incubator.vector.VectorOperators.*; +import static jdk.internal.vm.vector.VectorSupport.*; // -- This file was mechanically generated: Do not edit! -- // @@ -373,7 +371,7 @@ final VectorShuffle bitsToShuffle(AbstractSpecies dsp) { @Override @ForceInline public final IntShuffle256 toShuffle() { - return (IntShuffle256) toShuffle(vspecies(), false); + return (IntShuffle256) toShuffle(VSPECIES, false); } // Specialized unary testing @@ -632,7 +630,7 @@ boolean[] getBits() { @Override IntMask256 uOp(MUnOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); for (int i = 0; i < res.length; i++) { res[i] = f.apply(i, bits[i]); @@ -642,7 +640,7 @@ IntMask256 uOp(MUnOp f) { @Override IntMask256 bOp(VectorMask m, MBinOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); boolean[] mbits = ((IntMask256)m).getBits(); for (int i = 0; i < res.length; i++) { @@ -792,16 +790,16 @@ public boolean laneIsSet(int i) { @ForceInline public boolean anyTrue() { return VectorSupport.test(BT_ne, IntMask256.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> anyTrueHelper(((IntMask256)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> anyTrueHelper(((IntMask256)m).getBits())); } @Override @ForceInline public boolean allTrue() { return VectorSupport.test(BT_overflow, IntMask256.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> allTrueHelper(((IntMask256)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> allTrueHelper(((IntMask256)m).getBits())); } @ForceInline @@ -809,7 +807,7 @@ this, vspecies().maskAll(true), static IntMask256 maskAll(boolean bit) { return VectorSupport.fromBitsCoerced(IntMask256.class, LANEBITS_TYPE_ORDINAL, VLENGTH, (bit ? -1 : 0), MODE_BROADCAST, null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + (v, _) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final IntMask256 TRUE_MASK = new IntMask256(true); private static final IntMask256 FALSE_MASK = new IntMask256(false); @@ -869,7 +867,7 @@ IntVector256 toBitsVector() { @Override IntVector256 toBitsVector0() { - return ((IntVector256) vspecies().asIntegral().dummyVector()).vectorFactory(indices()); + return ((IntVector256) VSPECIES.asIntegral().dummyVector()).vectorFactory(indices()); } @Override @@ -894,7 +892,7 @@ public void intoMemorySegment(MemorySegment ms, long offset, ByteOrder bo) { @ForceInline public final IntMask256 laneIsValid() { return (IntMask256) toBitsVector().compare(VectorOperators.GE, 0) - .cast(vspecies()); + .cast(VSPECIES); } @ForceInline @@ -902,7 +900,7 @@ public final IntMask256 laneIsValid() { public final IntShuffle256 rearrange(VectorShuffle shuffle) { IntShuffle256 concreteShuffle = (IntShuffle256) shuffle; return (IntShuffle256) toBitsVector().rearrange(concreteShuffle) - .toShuffle(vspecies(), false); + .toShuffle(VSPECIES, false); } @ForceInline @@ -915,7 +913,7 @@ public final IntShuffle256 wrapIndexes() { v = (IntVector256) v.blend(v.lanewise(VectorOperators.ADD, length()), v.compare(VectorOperators.LT, 0)); } - return (IntShuffle256) v.toShuffle(vspecies(), false); + return (IntShuffle256) v.toShuffle(VSPECIES, false); } private static int[] prepare(int[] indices, int offset) { diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector512.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector512.java index 4f3a16e2777..ac48e589a05 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector512.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector512.java @@ -25,7 +25,6 @@ package jdk.incubator.vector; import java.lang.foreign.MemorySegment; -import java.lang.foreign.ValueLayout; import java.nio.ByteOrder; import java.util.Arrays; import java.util.Objects; @@ -35,9 +34,8 @@ import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; -import static jdk.internal.vm.vector.VectorSupport.*; - import static jdk.incubator.vector.VectorOperators.*; +import static jdk.internal.vm.vector.VectorSupport.*; // -- This file was mechanically generated: Do not edit! -- // @@ -373,7 +371,7 @@ final VectorShuffle bitsToShuffle(AbstractSpecies dsp) { @Override @ForceInline public final IntShuffle512 toShuffle() { - return (IntShuffle512) toShuffle(vspecies(), false); + return (IntShuffle512) toShuffle(VSPECIES, false); } // Specialized unary testing @@ -648,7 +646,7 @@ boolean[] getBits() { @Override IntMask512 uOp(MUnOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); for (int i = 0; i < res.length; i++) { res[i] = f.apply(i, bits[i]); @@ -658,7 +656,7 @@ IntMask512 uOp(MUnOp f) { @Override IntMask512 bOp(VectorMask m, MBinOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); boolean[] mbits = ((IntMask512)m).getBits(); for (int i = 0; i < res.length; i++) { @@ -808,16 +806,16 @@ public boolean laneIsSet(int i) { @ForceInline public boolean anyTrue() { return VectorSupport.test(BT_ne, IntMask512.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> anyTrueHelper(((IntMask512)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> anyTrueHelper(((IntMask512)m).getBits())); } @Override @ForceInline public boolean allTrue() { return VectorSupport.test(BT_overflow, IntMask512.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> allTrueHelper(((IntMask512)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> allTrueHelper(((IntMask512)m).getBits())); } @ForceInline @@ -825,7 +823,7 @@ this, vspecies().maskAll(true), static IntMask512 maskAll(boolean bit) { return VectorSupport.fromBitsCoerced(IntMask512.class, LANEBITS_TYPE_ORDINAL, VLENGTH, (bit ? -1 : 0), MODE_BROADCAST, null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + (v, _) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final IntMask512 TRUE_MASK = new IntMask512(true); private static final IntMask512 FALSE_MASK = new IntMask512(false); @@ -885,7 +883,7 @@ IntVector512 toBitsVector() { @Override IntVector512 toBitsVector0() { - return ((IntVector512) vspecies().asIntegral().dummyVector()).vectorFactory(indices()); + return ((IntVector512) VSPECIES.asIntegral().dummyVector()).vectorFactory(indices()); } @Override @@ -910,7 +908,7 @@ public void intoMemorySegment(MemorySegment ms, long offset, ByteOrder bo) { @ForceInline public final IntMask512 laneIsValid() { return (IntMask512) toBitsVector().compare(VectorOperators.GE, 0) - .cast(vspecies()); + .cast(VSPECIES); } @ForceInline @@ -918,7 +916,7 @@ public final IntMask512 laneIsValid() { public final IntShuffle512 rearrange(VectorShuffle shuffle) { IntShuffle512 concreteShuffle = (IntShuffle512) shuffle; return (IntShuffle512) toBitsVector().rearrange(concreteShuffle) - .toShuffle(vspecies(), false); + .toShuffle(VSPECIES, false); } @ForceInline @@ -931,7 +929,7 @@ public final IntShuffle512 wrapIndexes() { v = (IntVector512) v.blend(v.lanewise(VectorOperators.ADD, length()), v.compare(VectorOperators.LT, 0)); } - return (IntShuffle512) v.toShuffle(vspecies(), false); + return (IntShuffle512) v.toShuffle(VSPECIES, false); } private static int[] prepare(int[] indices, int offset) { diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector64.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector64.java index dd51669943b..25329aa81aa 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector64.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector64.java @@ -25,7 +25,6 @@ package jdk.incubator.vector; import java.lang.foreign.MemorySegment; -import java.lang.foreign.ValueLayout; import java.nio.ByteOrder; import java.util.Arrays; import java.util.Objects; @@ -35,9 +34,8 @@ import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; -import static jdk.internal.vm.vector.VectorSupport.*; - import static jdk.incubator.vector.VectorOperators.*; +import static jdk.internal.vm.vector.VectorSupport.*; // -- This file was mechanically generated: Do not edit! -- // @@ -373,7 +371,7 @@ final VectorShuffle bitsToShuffle(AbstractSpecies dsp) { @Override @ForceInline public final IntShuffle64 toShuffle() { - return (IntShuffle64) toShuffle(vspecies(), false); + return (IntShuffle64) toShuffle(VSPECIES, false); } // Specialized unary testing @@ -620,7 +618,7 @@ boolean[] getBits() { @Override IntMask64 uOp(MUnOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); for (int i = 0; i < res.length; i++) { res[i] = f.apply(i, bits[i]); @@ -630,7 +628,7 @@ IntMask64 uOp(MUnOp f) { @Override IntMask64 bOp(VectorMask m, MBinOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); boolean[] mbits = ((IntMask64)m).getBits(); for (int i = 0; i < res.length; i++) { @@ -780,16 +778,16 @@ public boolean laneIsSet(int i) { @ForceInline public boolean anyTrue() { return VectorSupport.test(BT_ne, IntMask64.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> anyTrueHelper(((IntMask64)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> anyTrueHelper(((IntMask64)m).getBits())); } @Override @ForceInline public boolean allTrue() { return VectorSupport.test(BT_overflow, IntMask64.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> allTrueHelper(((IntMask64)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> allTrueHelper(((IntMask64)m).getBits())); } @ForceInline @@ -797,7 +795,7 @@ this, vspecies().maskAll(true), static IntMask64 maskAll(boolean bit) { return VectorSupport.fromBitsCoerced(IntMask64.class, LANEBITS_TYPE_ORDINAL, VLENGTH, (bit ? -1 : 0), MODE_BROADCAST, null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + (v, _) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final IntMask64 TRUE_MASK = new IntMask64(true); private static final IntMask64 FALSE_MASK = new IntMask64(false); @@ -857,7 +855,7 @@ IntVector64 toBitsVector() { @Override IntVector64 toBitsVector0() { - return ((IntVector64) vspecies().asIntegral().dummyVector()).vectorFactory(indices()); + return ((IntVector64) VSPECIES.asIntegral().dummyVector()).vectorFactory(indices()); } @Override @@ -882,7 +880,7 @@ public void intoMemorySegment(MemorySegment ms, long offset, ByteOrder bo) { @ForceInline public final IntMask64 laneIsValid() { return (IntMask64) toBitsVector().compare(VectorOperators.GE, 0) - .cast(vspecies()); + .cast(VSPECIES); } @ForceInline @@ -890,7 +888,7 @@ public final IntMask64 laneIsValid() { public final IntShuffle64 rearrange(VectorShuffle shuffle) { IntShuffle64 concreteShuffle = (IntShuffle64) shuffle; return (IntShuffle64) toBitsVector().rearrange(concreteShuffle) - .toShuffle(vspecies(), false); + .toShuffle(VSPECIES, false); } @ForceInline @@ -903,7 +901,7 @@ public final IntShuffle64 wrapIndexes() { v = (IntVector64) v.blend(v.lanewise(VectorOperators.ADD, length()), v.compare(VectorOperators.LT, 0)); } - return (IntShuffle64) v.toShuffle(vspecies(), false); + return (IntShuffle64) v.toShuffle(VSPECIES, false); } private static int[] prepare(int[] indices, int offset) { diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVectorMax.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVectorMax.java index 0b785b01aec..348fda59381 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVectorMax.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVectorMax.java @@ -25,7 +25,6 @@ package jdk.incubator.vector; import java.lang.foreign.MemorySegment; -import java.lang.foreign.ValueLayout; import java.nio.ByteOrder; import java.util.Arrays; import java.util.Objects; @@ -35,9 +34,8 @@ import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; -import static jdk.internal.vm.vector.VectorSupport.*; - import static jdk.incubator.vector.VectorOperators.*; +import static jdk.internal.vm.vector.VectorSupport.*; // -- This file was mechanically generated: Do not edit! -- // @@ -373,7 +371,7 @@ final VectorShuffle bitsToShuffle(AbstractSpecies dsp) { @Override @ForceInline public final IntShuffleMax toShuffle() { - return (IntShuffleMax) toShuffle(vspecies(), false); + return (IntShuffleMax) toShuffle(VSPECIES, false); } // Specialized unary testing @@ -618,7 +616,7 @@ boolean[] getBits() { @Override IntMaskMax uOp(MUnOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); for (int i = 0; i < res.length; i++) { res[i] = f.apply(i, bits[i]); @@ -628,7 +626,7 @@ IntMaskMax uOp(MUnOp f) { @Override IntMaskMax bOp(VectorMask m, MBinOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); boolean[] mbits = ((IntMaskMax)m).getBits(); for (int i = 0; i < res.length; i++) { @@ -778,16 +776,16 @@ public boolean laneIsSet(int i) { @ForceInline public boolean anyTrue() { return VectorSupport.test(BT_ne, IntMaskMax.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> anyTrueHelper(((IntMaskMax)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> anyTrueHelper(((IntMaskMax)m).getBits())); } @Override @ForceInline public boolean allTrue() { return VectorSupport.test(BT_overflow, IntMaskMax.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> allTrueHelper(((IntMaskMax)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> allTrueHelper(((IntMaskMax)m).getBits())); } @ForceInline @@ -795,7 +793,7 @@ this, vspecies().maskAll(true), static IntMaskMax maskAll(boolean bit) { return VectorSupport.fromBitsCoerced(IntMaskMax.class, LANEBITS_TYPE_ORDINAL, VLENGTH, (bit ? -1 : 0), MODE_BROADCAST, null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + (v, _) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final IntMaskMax TRUE_MASK = new IntMaskMax(true); private static final IntMaskMax FALSE_MASK = new IntMaskMax(false); @@ -866,7 +864,7 @@ IntVectorMax toBitsVector() { @Override IntVectorMax toBitsVector0() { - return ((IntVectorMax) vspecies().asIntegral().dummyVector()).vectorFactory(indices()); + return ((IntVectorMax) VSPECIES.asIntegral().dummyVector()).vectorFactory(indices()); } @Override @@ -891,7 +889,7 @@ public void intoMemorySegment(MemorySegment ms, long offset, ByteOrder bo) { @ForceInline public final IntMaskMax laneIsValid() { return (IntMaskMax) toBitsVector().compare(VectorOperators.GE, 0) - .cast(vspecies()); + .cast(VSPECIES); } @ForceInline @@ -899,7 +897,7 @@ public final IntMaskMax laneIsValid() { public final IntShuffleMax rearrange(VectorShuffle shuffle) { IntShuffleMax concreteShuffle = (IntShuffleMax) shuffle; return (IntShuffleMax) toBitsVector().rearrange(concreteShuffle) - .toShuffle(vspecies(), false); + .toShuffle(VSPECIES, false); } @ForceInline @@ -912,7 +910,7 @@ public final IntShuffleMax wrapIndexes() { v = (IntVectorMax) v.blend(v.lanewise(VectorOperators.ADD, length()), v.compare(VectorOperators.LT, 0)); } - return (IntShuffleMax) v.toShuffle(vspecies(), false); + return (IntShuffleMax) v.toShuffle(VSPECIES, false); } private static int[] prepare(int[] indices, int offset) { 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 7ba0af6c139..36300cf892b 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 @@ -49,7 +49,8 @@ * {@code long} values. */ @SuppressWarnings("cast") // warning: redundant cast -public abstract class LongVector extends AbstractVector { +public abstract sealed class LongVector extends AbstractVector + permits LongVector64, LongVector128, LongVector256, LongVector512, LongVectorMax { LongVector(long[] vec) { super(vec); diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector128.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector128.java index 594c82ca1fc..7ce60b2efe0 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector128.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector128.java @@ -35,9 +35,8 @@ import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; -import static jdk.internal.vm.vector.VectorSupport.*; - import static jdk.incubator.vector.VectorOperators.*; +import static jdk.internal.vm.vector.VectorSupport.*; // -- This file was mechanically generated: Do not edit! -- // @@ -368,7 +367,7 @@ final VectorShuffle bitsToShuffle(AbstractSpecies dsp) { @Override @ForceInline public final LongShuffle128 toShuffle() { - return (LongShuffle128) toShuffle(vspecies(), false); + return (LongShuffle128) toShuffle(VSPECIES, false); } // Specialized unary testing @@ -610,7 +609,7 @@ boolean[] getBits() { @Override LongMask128 uOp(MUnOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); for (int i = 0; i < res.length; i++) { res[i] = f.apply(i, bits[i]); @@ -620,7 +619,7 @@ LongMask128 uOp(MUnOp f) { @Override LongMask128 bOp(VectorMask m, MBinOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); boolean[] mbits = ((LongMask128)m).getBits(); for (int i = 0; i < res.length; i++) { @@ -770,16 +769,16 @@ public boolean laneIsSet(int i) { @ForceInline public boolean anyTrue() { return VectorSupport.test(BT_ne, LongMask128.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> anyTrueHelper(((LongMask128)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> anyTrueHelper(((LongMask128)m).getBits())); } @Override @ForceInline public boolean allTrue() { return VectorSupport.test(BT_overflow, LongMask128.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> allTrueHelper(((LongMask128)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> allTrueHelper(((LongMask128)m).getBits())); } @ForceInline @@ -787,7 +786,7 @@ this, vspecies().maskAll(true), static LongMask128 maskAll(boolean bit) { return VectorSupport.fromBitsCoerced(LongMask128.class, LANEBITS_TYPE_ORDINAL, VLENGTH, (bit ? -1 : 0), MODE_BROADCAST, null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + (v, _) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final LongMask128 TRUE_MASK = new LongMask128(true); private static final LongMask128 FALSE_MASK = new LongMask128(false); @@ -847,7 +846,7 @@ LongVector128 toBitsVector() { @Override LongVector128 toBitsVector0() { - return ((LongVector128) vspecies().asIntegral().dummyVector()).vectorFactory(indices()); + return ((LongVector128) VSPECIES.asIntegral().dummyVector()).vectorFactory(indices()); } @Override @@ -921,7 +920,7 @@ public void intoMemorySegment(MemorySegment ms, long offset, ByteOrder bo) { @ForceInline public final LongMask128 laneIsValid() { return (LongMask128) toBitsVector().compare(VectorOperators.GE, 0) - .cast(vspecies()); + .cast(VSPECIES); } @ForceInline @@ -929,7 +928,7 @@ public final LongMask128 laneIsValid() { public final LongShuffle128 rearrange(VectorShuffle shuffle) { LongShuffle128 concreteShuffle = (LongShuffle128) shuffle; return (LongShuffle128) toBitsVector().rearrange(concreteShuffle) - .toShuffle(vspecies(), false); + .toShuffle(VSPECIES, false); } @ForceInline @@ -942,7 +941,7 @@ public final LongShuffle128 wrapIndexes() { v = (LongVector128) v.blend(v.lanewise(VectorOperators.ADD, length()), v.compare(VectorOperators.LT, 0)); } - return (LongShuffle128) v.toShuffle(vspecies(), false); + return (LongShuffle128) v.toShuffle(VSPECIES, false); } private static long[] prepare(int[] indices, int offset) { diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector256.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector256.java index c3d1ff4c276..110a54c547f 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector256.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector256.java @@ -35,9 +35,8 @@ import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; -import static jdk.internal.vm.vector.VectorSupport.*; - import static jdk.incubator.vector.VectorOperators.*; +import static jdk.internal.vm.vector.VectorSupport.*; // -- This file was mechanically generated: Do not edit! -- // @@ -368,7 +367,7 @@ final VectorShuffle bitsToShuffle(AbstractSpecies dsp) { @Override @ForceInline public final LongShuffle256 toShuffle() { - return (LongShuffle256) toShuffle(vspecies(), false); + return (LongShuffle256) toShuffle(VSPECIES, false); } // Specialized unary testing @@ -614,7 +613,7 @@ boolean[] getBits() { @Override LongMask256 uOp(MUnOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); for (int i = 0; i < res.length; i++) { res[i] = f.apply(i, bits[i]); @@ -624,7 +623,7 @@ LongMask256 uOp(MUnOp f) { @Override LongMask256 bOp(VectorMask m, MBinOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); boolean[] mbits = ((LongMask256)m).getBits(); for (int i = 0; i < res.length; i++) { @@ -774,16 +773,16 @@ public boolean laneIsSet(int i) { @ForceInline public boolean anyTrue() { return VectorSupport.test(BT_ne, LongMask256.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> anyTrueHelper(((LongMask256)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> anyTrueHelper(((LongMask256)m).getBits())); } @Override @ForceInline public boolean allTrue() { return VectorSupport.test(BT_overflow, LongMask256.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> allTrueHelper(((LongMask256)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> allTrueHelper(((LongMask256)m).getBits())); } @ForceInline @@ -791,7 +790,7 @@ this, vspecies().maskAll(true), static LongMask256 maskAll(boolean bit) { return VectorSupport.fromBitsCoerced(LongMask256.class, LANEBITS_TYPE_ORDINAL, VLENGTH, (bit ? -1 : 0), MODE_BROADCAST, null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + (v, _) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final LongMask256 TRUE_MASK = new LongMask256(true); private static final LongMask256 FALSE_MASK = new LongMask256(false); @@ -851,7 +850,7 @@ LongVector256 toBitsVector() { @Override LongVector256 toBitsVector0() { - return ((LongVector256) vspecies().asIntegral().dummyVector()).vectorFactory(indices()); + return ((LongVector256) VSPECIES.asIntegral().dummyVector()).vectorFactory(indices()); } @Override @@ -925,7 +924,7 @@ public void intoMemorySegment(MemorySegment ms, long offset, ByteOrder bo) { @ForceInline public final LongMask256 laneIsValid() { return (LongMask256) toBitsVector().compare(VectorOperators.GE, 0) - .cast(vspecies()); + .cast(VSPECIES); } @ForceInline @@ -933,7 +932,7 @@ public final LongMask256 laneIsValid() { public final LongShuffle256 rearrange(VectorShuffle shuffle) { LongShuffle256 concreteShuffle = (LongShuffle256) shuffle; return (LongShuffle256) toBitsVector().rearrange(concreteShuffle) - .toShuffle(vspecies(), false); + .toShuffle(VSPECIES, false); } @ForceInline @@ -946,7 +945,7 @@ public final LongShuffle256 wrapIndexes() { v = (LongVector256) v.blend(v.lanewise(VectorOperators.ADD, length()), v.compare(VectorOperators.LT, 0)); } - return (LongShuffle256) v.toShuffle(vspecies(), false); + return (LongShuffle256) v.toShuffle(VSPECIES, false); } private static long[] prepare(int[] indices, int offset) { diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector512.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector512.java index b8c95967a99..3502f209c3b 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector512.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector512.java @@ -35,9 +35,8 @@ import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; -import static jdk.internal.vm.vector.VectorSupport.*; - import static jdk.incubator.vector.VectorOperators.*; +import static jdk.internal.vm.vector.VectorSupport.*; // -- This file was mechanically generated: Do not edit! -- // @@ -368,7 +367,7 @@ final VectorShuffle bitsToShuffle(AbstractSpecies dsp) { @Override @ForceInline public final LongShuffle512 toShuffle() { - return (LongShuffle512) toShuffle(vspecies(), false); + return (LongShuffle512) toShuffle(VSPECIES, false); } // Specialized unary testing @@ -622,7 +621,7 @@ boolean[] getBits() { @Override LongMask512 uOp(MUnOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); for (int i = 0; i < res.length; i++) { res[i] = f.apply(i, bits[i]); @@ -632,7 +631,7 @@ LongMask512 uOp(MUnOp f) { @Override LongMask512 bOp(VectorMask m, MBinOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); boolean[] mbits = ((LongMask512)m).getBits(); for (int i = 0; i < res.length; i++) { @@ -782,16 +781,16 @@ public boolean laneIsSet(int i) { @ForceInline public boolean anyTrue() { return VectorSupport.test(BT_ne, LongMask512.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> anyTrueHelper(((LongMask512)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> anyTrueHelper(((LongMask512)m).getBits())); } @Override @ForceInline public boolean allTrue() { return VectorSupport.test(BT_overflow, LongMask512.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> allTrueHelper(((LongMask512)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> allTrueHelper(((LongMask512)m).getBits())); } @ForceInline @@ -799,7 +798,7 @@ this, vspecies().maskAll(true), static LongMask512 maskAll(boolean bit) { return VectorSupport.fromBitsCoerced(LongMask512.class, LANEBITS_TYPE_ORDINAL, VLENGTH, (bit ? -1 : 0), MODE_BROADCAST, null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + (v, _) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final LongMask512 TRUE_MASK = new LongMask512(true); private static final LongMask512 FALSE_MASK = new LongMask512(false); @@ -859,7 +858,7 @@ LongVector512 toBitsVector() { @Override LongVector512 toBitsVector0() { - return ((LongVector512) vspecies().asIntegral().dummyVector()).vectorFactory(indices()); + return ((LongVector512) VSPECIES.asIntegral().dummyVector()).vectorFactory(indices()); } @Override @@ -933,7 +932,7 @@ public void intoMemorySegment(MemorySegment ms, long offset, ByteOrder bo) { @ForceInline public final LongMask512 laneIsValid() { return (LongMask512) toBitsVector().compare(VectorOperators.GE, 0) - .cast(vspecies()); + .cast(VSPECIES); } @ForceInline @@ -941,7 +940,7 @@ public final LongMask512 laneIsValid() { public final LongShuffle512 rearrange(VectorShuffle shuffle) { LongShuffle512 concreteShuffle = (LongShuffle512) shuffle; return (LongShuffle512) toBitsVector().rearrange(concreteShuffle) - .toShuffle(vspecies(), false); + .toShuffle(VSPECIES, false); } @ForceInline @@ -954,7 +953,7 @@ public final LongShuffle512 wrapIndexes() { v = (LongVector512) v.blend(v.lanewise(VectorOperators.ADD, length()), v.compare(VectorOperators.LT, 0)); } - return (LongShuffle512) v.toShuffle(vspecies(), false); + return (LongShuffle512) v.toShuffle(VSPECIES, false); } private static long[] prepare(int[] indices, int offset) { diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector64.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector64.java index 3c9b525f6d0..2a2fe4329a8 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector64.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector64.java @@ -35,9 +35,8 @@ import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; -import static jdk.internal.vm.vector.VectorSupport.*; - import static jdk.incubator.vector.VectorOperators.*; +import static jdk.internal.vm.vector.VectorSupport.*; // -- This file was mechanically generated: Do not edit! -- // @@ -368,7 +367,7 @@ final VectorShuffle bitsToShuffle(AbstractSpecies dsp) { @Override @ForceInline public final LongShuffle64 toShuffle() { - return (LongShuffle64) toShuffle(vspecies(), false); + return (LongShuffle64) toShuffle(VSPECIES, false); } // Specialized unary testing @@ -608,7 +607,7 @@ boolean[] getBits() { @Override LongMask64 uOp(MUnOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); for (int i = 0; i < res.length; i++) { res[i] = f.apply(i, bits[i]); @@ -618,7 +617,7 @@ LongMask64 uOp(MUnOp f) { @Override LongMask64 bOp(VectorMask m, MBinOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); boolean[] mbits = ((LongMask64)m).getBits(); for (int i = 0; i < res.length; i++) { @@ -768,16 +767,16 @@ public boolean laneIsSet(int i) { @ForceInline public boolean anyTrue() { return VectorSupport.test(BT_ne, LongMask64.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> anyTrueHelper(((LongMask64)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> anyTrueHelper(((LongMask64)m).getBits())); } @Override @ForceInline public boolean allTrue() { return VectorSupport.test(BT_overflow, LongMask64.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> allTrueHelper(((LongMask64)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> allTrueHelper(((LongMask64)m).getBits())); } @ForceInline @@ -785,7 +784,7 @@ this, vspecies().maskAll(true), static LongMask64 maskAll(boolean bit) { return VectorSupport.fromBitsCoerced(LongMask64.class, LANEBITS_TYPE_ORDINAL, VLENGTH, (bit ? -1 : 0), MODE_BROADCAST, null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + (v, _) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final LongMask64 TRUE_MASK = new LongMask64(true); private static final LongMask64 FALSE_MASK = new LongMask64(false); @@ -845,7 +844,7 @@ LongVector64 toBitsVector() { @Override LongVector64 toBitsVector0() { - return ((LongVector64) vspecies().asIntegral().dummyVector()).vectorFactory(indices()); + return ((LongVector64) VSPECIES.asIntegral().dummyVector()).vectorFactory(indices()); } @Override @@ -919,7 +918,7 @@ public void intoMemorySegment(MemorySegment ms, long offset, ByteOrder bo) { @ForceInline public final LongMask64 laneIsValid() { return (LongMask64) toBitsVector().compare(VectorOperators.GE, 0) - .cast(vspecies()); + .cast(VSPECIES); } @ForceInline @@ -927,7 +926,7 @@ public final LongMask64 laneIsValid() { public final LongShuffle64 rearrange(VectorShuffle shuffle) { LongShuffle64 concreteShuffle = (LongShuffle64) shuffle; return (LongShuffle64) toBitsVector().rearrange(concreteShuffle) - .toShuffle(vspecies(), false); + .toShuffle(VSPECIES, false); } @ForceInline @@ -940,7 +939,7 @@ public final LongShuffle64 wrapIndexes() { v = (LongVector64) v.blend(v.lanewise(VectorOperators.ADD, length()), v.compare(VectorOperators.LT, 0)); } - return (LongShuffle64) v.toShuffle(vspecies(), false); + return (LongShuffle64) v.toShuffle(VSPECIES, false); } private static long[] prepare(int[] indices, int offset) { diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVectorMax.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVectorMax.java index 4752959f884..157c58e20e8 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVectorMax.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVectorMax.java @@ -35,9 +35,8 @@ import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; -import static jdk.internal.vm.vector.VectorSupport.*; - import static jdk.incubator.vector.VectorOperators.*; +import static jdk.internal.vm.vector.VectorSupport.*; // -- This file was mechanically generated: Do not edit! -- // @@ -368,7 +367,7 @@ final VectorShuffle bitsToShuffle(AbstractSpecies dsp) { @Override @ForceInline public final LongShuffleMax toShuffle() { - return (LongShuffleMax) toShuffle(vspecies(), false); + return (LongShuffleMax) toShuffle(VSPECIES, false); } // Specialized unary testing @@ -608,7 +607,7 @@ boolean[] getBits() { @Override LongMaskMax uOp(MUnOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); for (int i = 0; i < res.length; i++) { res[i] = f.apply(i, bits[i]); @@ -618,7 +617,7 @@ LongMaskMax uOp(MUnOp f) { @Override LongMaskMax bOp(VectorMask m, MBinOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); boolean[] mbits = ((LongMaskMax)m).getBits(); for (int i = 0; i < res.length; i++) { @@ -768,16 +767,16 @@ public boolean laneIsSet(int i) { @ForceInline public boolean anyTrue() { return VectorSupport.test(BT_ne, LongMaskMax.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> anyTrueHelper(((LongMaskMax)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> anyTrueHelper(((LongMaskMax)m).getBits())); } @Override @ForceInline public boolean allTrue() { return VectorSupport.test(BT_overflow, LongMaskMax.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> allTrueHelper(((LongMaskMax)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> allTrueHelper(((LongMaskMax)m).getBits())); } @ForceInline @@ -785,7 +784,7 @@ this, vspecies().maskAll(true), static LongMaskMax maskAll(boolean bit) { return VectorSupport.fromBitsCoerced(LongMaskMax.class, LANEBITS_TYPE_ORDINAL, VLENGTH, (bit ? -1 : 0), MODE_BROADCAST, null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + (v, _) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final LongMaskMax TRUE_MASK = new LongMaskMax(true); private static final LongMaskMax FALSE_MASK = new LongMaskMax(false); @@ -845,7 +844,7 @@ LongVectorMax toBitsVector() { @Override LongVectorMax toBitsVector0() { - return ((LongVectorMax) vspecies().asIntegral().dummyVector()).vectorFactory(indices()); + return ((LongVectorMax) VSPECIES.asIntegral().dummyVector()).vectorFactory(indices()); } @Override @@ -919,7 +918,7 @@ public void intoMemorySegment(MemorySegment ms, long offset, ByteOrder bo) { @ForceInline public final LongMaskMax laneIsValid() { return (LongMaskMax) toBitsVector().compare(VectorOperators.GE, 0) - .cast(vspecies()); + .cast(VSPECIES); } @ForceInline @@ -927,7 +926,7 @@ public final LongMaskMax laneIsValid() { public final LongShuffleMax rearrange(VectorShuffle shuffle) { LongShuffleMax concreteShuffle = (LongShuffleMax) shuffle; return (LongShuffleMax) toBitsVector().rearrange(concreteShuffle) - .toShuffle(vspecies(), false); + .toShuffle(VSPECIES, false); } @ForceInline @@ -940,7 +939,7 @@ public final LongShuffleMax wrapIndexes() { v = (LongVectorMax) v.blend(v.lanewise(VectorOperators.ADD, length()), v.compare(VectorOperators.LT, 0)); } - return (LongShuffleMax) v.toShuffle(vspecies(), false); + return (LongShuffleMax) v.toShuffle(VSPECIES, false); } private static long[] prepare(int[] indices, int offset) { 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 7ba465706e8..21bc80a12bc 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 @@ -49,7 +49,8 @@ * {@code short} values. */ @SuppressWarnings("cast") // warning: redundant cast -public abstract class ShortVector extends AbstractVector { +public abstract sealed class ShortVector extends AbstractVector + permits ShortVector64, ShortVector128, ShortVector256, ShortVector512, ShortVectorMax { ShortVector(short[] vec) { super(vec); diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector128.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector128.java index 89ec97c6be0..22bbfce0928 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector128.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector128.java @@ -25,7 +25,6 @@ package jdk.incubator.vector; import java.lang.foreign.MemorySegment; -import java.lang.foreign.ValueLayout; import java.nio.ByteOrder; import java.util.Arrays; import java.util.Objects; @@ -35,9 +34,8 @@ import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; -import static jdk.internal.vm.vector.VectorSupport.*; - import static jdk.incubator.vector.VectorOperators.*; +import static jdk.internal.vm.vector.VectorSupport.*; // -- This file was mechanically generated: Do not edit! -- // @@ -373,7 +371,7 @@ final VectorShuffle bitsToShuffle(AbstractSpecies dsp) { @Override @ForceInline public final ShortShuffle128 toShuffle() { - return (ShortShuffle128) toShuffle(vspecies(), false); + return (ShortShuffle128) toShuffle(VSPECIES, false); } // Specialized unary testing @@ -632,7 +630,7 @@ boolean[] getBits() { @Override ShortMask128 uOp(MUnOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); for (int i = 0; i < res.length; i++) { res[i] = f.apply(i, bits[i]); @@ -642,7 +640,7 @@ ShortMask128 uOp(MUnOp f) { @Override ShortMask128 bOp(VectorMask m, MBinOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); boolean[] mbits = ((ShortMask128)m).getBits(); for (int i = 0; i < res.length; i++) { @@ -792,16 +790,16 @@ public boolean laneIsSet(int i) { @ForceInline public boolean anyTrue() { return VectorSupport.test(BT_ne, ShortMask128.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> anyTrueHelper(((ShortMask128)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> anyTrueHelper(((ShortMask128)m).getBits())); } @Override @ForceInline public boolean allTrue() { return VectorSupport.test(BT_overflow, ShortMask128.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> allTrueHelper(((ShortMask128)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> allTrueHelper(((ShortMask128)m).getBits())); } @ForceInline @@ -809,7 +807,7 @@ this, vspecies().maskAll(true), static ShortMask128 maskAll(boolean bit) { return VectorSupport.fromBitsCoerced(ShortMask128.class, LANEBITS_TYPE_ORDINAL, VLENGTH, (bit ? -1 : 0), MODE_BROADCAST, null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + (v, _) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final ShortMask128 TRUE_MASK = new ShortMask128(true); private static final ShortMask128 FALSE_MASK = new ShortMask128(false); @@ -869,7 +867,7 @@ ShortVector128 toBitsVector() { @Override ShortVector128 toBitsVector0() { - return ((ShortVector128) vspecies().asIntegral().dummyVector()).vectorFactory(indices()); + return ((ShortVector128) VSPECIES.asIntegral().dummyVector()).vectorFactory(indices()); } @Override @@ -908,7 +906,7 @@ public void intoMemorySegment(MemorySegment ms, long offset, ByteOrder bo) { @ForceInline public final ShortMask128 laneIsValid() { return (ShortMask128) toBitsVector().compare(VectorOperators.GE, 0) - .cast(vspecies()); + .cast(VSPECIES); } @ForceInline @@ -916,7 +914,7 @@ public final ShortMask128 laneIsValid() { public final ShortShuffle128 rearrange(VectorShuffle shuffle) { ShortShuffle128 concreteShuffle = (ShortShuffle128) shuffle; return (ShortShuffle128) toBitsVector().rearrange(concreteShuffle) - .toShuffle(vspecies(), false); + .toShuffle(VSPECIES, false); } @ForceInline @@ -929,7 +927,7 @@ public final ShortShuffle128 wrapIndexes() { v = (ShortVector128) v.blend(v.lanewise(VectorOperators.ADD, length()), v.compare(VectorOperators.LT, 0)); } - return (ShortShuffle128) v.toShuffle(vspecies(), false); + return (ShortShuffle128) v.toShuffle(VSPECIES, false); } private static short[] prepare(int[] indices, int offset) { diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector256.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector256.java index 0f5751c27d8..6011695bf54 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector256.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector256.java @@ -25,7 +25,6 @@ package jdk.incubator.vector; import java.lang.foreign.MemorySegment; -import java.lang.foreign.ValueLayout; import java.nio.ByteOrder; import java.util.Arrays; import java.util.Objects; @@ -35,9 +34,8 @@ import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; -import static jdk.internal.vm.vector.VectorSupport.*; - import static jdk.incubator.vector.VectorOperators.*; +import static jdk.internal.vm.vector.VectorSupport.*; // -- This file was mechanically generated: Do not edit! -- // @@ -373,7 +371,7 @@ final VectorShuffle bitsToShuffle(AbstractSpecies dsp) { @Override @ForceInline public final ShortShuffle256 toShuffle() { - return (ShortShuffle256) toShuffle(vspecies(), false); + return (ShortShuffle256) toShuffle(VSPECIES, false); } // Specialized unary testing @@ -648,7 +646,7 @@ boolean[] getBits() { @Override ShortMask256 uOp(MUnOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); for (int i = 0; i < res.length; i++) { res[i] = f.apply(i, bits[i]); @@ -658,7 +656,7 @@ ShortMask256 uOp(MUnOp f) { @Override ShortMask256 bOp(VectorMask m, MBinOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); boolean[] mbits = ((ShortMask256)m).getBits(); for (int i = 0; i < res.length; i++) { @@ -808,16 +806,16 @@ public boolean laneIsSet(int i) { @ForceInline public boolean anyTrue() { return VectorSupport.test(BT_ne, ShortMask256.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> anyTrueHelper(((ShortMask256)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> anyTrueHelper(((ShortMask256)m).getBits())); } @Override @ForceInline public boolean allTrue() { return VectorSupport.test(BT_overflow, ShortMask256.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> allTrueHelper(((ShortMask256)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> allTrueHelper(((ShortMask256)m).getBits())); } @ForceInline @@ -825,7 +823,7 @@ this, vspecies().maskAll(true), static ShortMask256 maskAll(boolean bit) { return VectorSupport.fromBitsCoerced(ShortMask256.class, LANEBITS_TYPE_ORDINAL, VLENGTH, (bit ? -1 : 0), MODE_BROADCAST, null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + (v, _) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final ShortMask256 TRUE_MASK = new ShortMask256(true); private static final ShortMask256 FALSE_MASK = new ShortMask256(false); @@ -885,7 +883,7 @@ ShortVector256 toBitsVector() { @Override ShortVector256 toBitsVector0() { - return ((ShortVector256) vspecies().asIntegral().dummyVector()).vectorFactory(indices()); + return ((ShortVector256) VSPECIES.asIntegral().dummyVector()).vectorFactory(indices()); } @Override @@ -924,7 +922,7 @@ public void intoMemorySegment(MemorySegment ms, long offset, ByteOrder bo) { @ForceInline public final ShortMask256 laneIsValid() { return (ShortMask256) toBitsVector().compare(VectorOperators.GE, 0) - .cast(vspecies()); + .cast(VSPECIES); } @ForceInline @@ -932,7 +930,7 @@ public final ShortMask256 laneIsValid() { public final ShortShuffle256 rearrange(VectorShuffle shuffle) { ShortShuffle256 concreteShuffle = (ShortShuffle256) shuffle; return (ShortShuffle256) toBitsVector().rearrange(concreteShuffle) - .toShuffle(vspecies(), false); + .toShuffle(VSPECIES, false); } @ForceInline @@ -945,7 +943,7 @@ public final ShortShuffle256 wrapIndexes() { v = (ShortVector256) v.blend(v.lanewise(VectorOperators.ADD, length()), v.compare(VectorOperators.LT, 0)); } - return (ShortShuffle256) v.toShuffle(vspecies(), false); + return (ShortShuffle256) v.toShuffle(VSPECIES, false); } private static short[] prepare(int[] indices, int offset) { diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector512.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector512.java index 3d38dfd88fd..e6101d2e6be 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector512.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector512.java @@ -25,7 +25,6 @@ package jdk.incubator.vector; import java.lang.foreign.MemorySegment; -import java.lang.foreign.ValueLayout; import java.nio.ByteOrder; import java.util.Arrays; import java.util.Objects; @@ -35,9 +34,8 @@ import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; -import static jdk.internal.vm.vector.VectorSupport.*; - import static jdk.incubator.vector.VectorOperators.*; +import static jdk.internal.vm.vector.VectorSupport.*; // -- This file was mechanically generated: Do not edit! -- // @@ -373,7 +371,7 @@ final VectorShuffle bitsToShuffle(AbstractSpecies dsp) { @Override @ForceInline public final ShortShuffle512 toShuffle() { - return (ShortShuffle512) toShuffle(vspecies(), false); + return (ShortShuffle512) toShuffle(VSPECIES, false); } // Specialized unary testing @@ -680,7 +678,7 @@ boolean[] getBits() { @Override ShortMask512 uOp(MUnOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); for (int i = 0; i < res.length; i++) { res[i] = f.apply(i, bits[i]); @@ -690,7 +688,7 @@ ShortMask512 uOp(MUnOp f) { @Override ShortMask512 bOp(VectorMask m, MBinOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); boolean[] mbits = ((ShortMask512)m).getBits(); for (int i = 0; i < res.length; i++) { @@ -840,16 +838,16 @@ public boolean laneIsSet(int i) { @ForceInline public boolean anyTrue() { return VectorSupport.test(BT_ne, ShortMask512.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> anyTrueHelper(((ShortMask512)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> anyTrueHelper(((ShortMask512)m).getBits())); } @Override @ForceInline public boolean allTrue() { return VectorSupport.test(BT_overflow, ShortMask512.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> allTrueHelper(((ShortMask512)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> allTrueHelper(((ShortMask512)m).getBits())); } @ForceInline @@ -857,7 +855,7 @@ this, vspecies().maskAll(true), static ShortMask512 maskAll(boolean bit) { return VectorSupport.fromBitsCoerced(ShortMask512.class, LANEBITS_TYPE_ORDINAL, VLENGTH, (bit ? -1 : 0), MODE_BROADCAST, null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + (v, _) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final ShortMask512 TRUE_MASK = new ShortMask512(true); private static final ShortMask512 FALSE_MASK = new ShortMask512(false); @@ -917,7 +915,7 @@ ShortVector512 toBitsVector() { @Override ShortVector512 toBitsVector0() { - return ((ShortVector512) vspecies().asIntegral().dummyVector()).vectorFactory(indices()); + return ((ShortVector512) VSPECIES.asIntegral().dummyVector()).vectorFactory(indices()); } @Override @@ -956,7 +954,7 @@ public void intoMemorySegment(MemorySegment ms, long offset, ByteOrder bo) { @ForceInline public final ShortMask512 laneIsValid() { return (ShortMask512) toBitsVector().compare(VectorOperators.GE, 0) - .cast(vspecies()); + .cast(VSPECIES); } @ForceInline @@ -964,7 +962,7 @@ public final ShortMask512 laneIsValid() { public final ShortShuffle512 rearrange(VectorShuffle shuffle) { ShortShuffle512 concreteShuffle = (ShortShuffle512) shuffle; return (ShortShuffle512) toBitsVector().rearrange(concreteShuffle) - .toShuffle(vspecies(), false); + .toShuffle(VSPECIES, false); } @ForceInline @@ -977,7 +975,7 @@ public final ShortShuffle512 wrapIndexes() { v = (ShortVector512) v.blend(v.lanewise(VectorOperators.ADD, length()), v.compare(VectorOperators.LT, 0)); } - return (ShortShuffle512) v.toShuffle(vspecies(), false); + return (ShortShuffle512) v.toShuffle(VSPECIES, false); } private static short[] prepare(int[] indices, int offset) { diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector64.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector64.java index b319d98f784..31af959b4a8 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector64.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector64.java @@ -25,7 +25,6 @@ package jdk.incubator.vector; import java.lang.foreign.MemorySegment; -import java.lang.foreign.ValueLayout; import java.nio.ByteOrder; import java.util.Arrays; import java.util.Objects; @@ -35,9 +34,8 @@ import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; -import static jdk.internal.vm.vector.VectorSupport.*; - import static jdk.incubator.vector.VectorOperators.*; +import static jdk.internal.vm.vector.VectorSupport.*; // -- This file was mechanically generated: Do not edit! -- // @@ -373,7 +371,7 @@ final VectorShuffle bitsToShuffle(AbstractSpecies dsp) { @Override @ForceInline public final ShortShuffle64 toShuffle() { - return (ShortShuffle64) toShuffle(vspecies(), false); + return (ShortShuffle64) toShuffle(VSPECIES, false); } // Specialized unary testing @@ -624,7 +622,7 @@ boolean[] getBits() { @Override ShortMask64 uOp(MUnOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); for (int i = 0; i < res.length; i++) { res[i] = f.apply(i, bits[i]); @@ -634,7 +632,7 @@ ShortMask64 uOp(MUnOp f) { @Override ShortMask64 bOp(VectorMask m, MBinOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); boolean[] mbits = ((ShortMask64)m).getBits(); for (int i = 0; i < res.length; i++) { @@ -784,16 +782,16 @@ public boolean laneIsSet(int i) { @ForceInline public boolean anyTrue() { return VectorSupport.test(BT_ne, ShortMask64.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> anyTrueHelper(((ShortMask64)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> anyTrueHelper(((ShortMask64)m).getBits())); } @Override @ForceInline public boolean allTrue() { return VectorSupport.test(BT_overflow, ShortMask64.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> allTrueHelper(((ShortMask64)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> allTrueHelper(((ShortMask64)m).getBits())); } @ForceInline @@ -801,7 +799,7 @@ this, vspecies().maskAll(true), static ShortMask64 maskAll(boolean bit) { return VectorSupport.fromBitsCoerced(ShortMask64.class, LANEBITS_TYPE_ORDINAL, VLENGTH, (bit ? -1 : 0), MODE_BROADCAST, null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + (v, _) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final ShortMask64 TRUE_MASK = new ShortMask64(true); private static final ShortMask64 FALSE_MASK = new ShortMask64(false); @@ -861,7 +859,7 @@ ShortVector64 toBitsVector() { @Override ShortVector64 toBitsVector0() { - return ((ShortVector64) vspecies().asIntegral().dummyVector()).vectorFactory(indices()); + return ((ShortVector64) VSPECIES.asIntegral().dummyVector()).vectorFactory(indices()); } @Override @@ -900,7 +898,7 @@ public void intoMemorySegment(MemorySegment ms, long offset, ByteOrder bo) { @ForceInline public final ShortMask64 laneIsValid() { return (ShortMask64) toBitsVector().compare(VectorOperators.GE, 0) - .cast(vspecies()); + .cast(VSPECIES); } @ForceInline @@ -908,7 +906,7 @@ public final ShortMask64 laneIsValid() { public final ShortShuffle64 rearrange(VectorShuffle shuffle) { ShortShuffle64 concreteShuffle = (ShortShuffle64) shuffle; return (ShortShuffle64) toBitsVector().rearrange(concreteShuffle) - .toShuffle(vspecies(), false); + .toShuffle(VSPECIES, false); } @ForceInline @@ -921,7 +919,7 @@ public final ShortShuffle64 wrapIndexes() { v = (ShortVector64) v.blend(v.lanewise(VectorOperators.ADD, length()), v.compare(VectorOperators.LT, 0)); } - return (ShortShuffle64) v.toShuffle(vspecies(), false); + return (ShortShuffle64) v.toShuffle(VSPECIES, false); } private static short[] prepare(int[] indices, int offset) { diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVectorMax.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVectorMax.java index 69b298857c9..fe0359c4711 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVectorMax.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVectorMax.java @@ -25,7 +25,6 @@ package jdk.incubator.vector; import java.lang.foreign.MemorySegment; -import java.lang.foreign.ValueLayout; import java.nio.ByteOrder; import java.util.Arrays; import java.util.Objects; @@ -35,9 +34,8 @@ import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; -import static jdk.internal.vm.vector.VectorSupport.*; - import static jdk.incubator.vector.VectorOperators.*; +import static jdk.internal.vm.vector.VectorSupport.*; // -- This file was mechanically generated: Do not edit! -- // @@ -373,7 +371,7 @@ final VectorShuffle bitsToShuffle(AbstractSpecies dsp) { @Override @ForceInline public final ShortShuffleMax toShuffle() { - return (ShortShuffleMax) toShuffle(vspecies(), false); + return (ShortShuffleMax) toShuffle(VSPECIES, false); } // Specialized unary testing @@ -618,7 +616,7 @@ boolean[] getBits() { @Override ShortMaskMax uOp(MUnOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); for (int i = 0; i < res.length; i++) { res[i] = f.apply(i, bits[i]); @@ -628,7 +626,7 @@ ShortMaskMax uOp(MUnOp f) { @Override ShortMaskMax bOp(VectorMask m, MBinOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); boolean[] mbits = ((ShortMaskMax)m).getBits(); for (int i = 0; i < res.length; i++) { @@ -778,16 +776,16 @@ public boolean laneIsSet(int i) { @ForceInline public boolean anyTrue() { return VectorSupport.test(BT_ne, ShortMaskMax.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> anyTrueHelper(((ShortMaskMax)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> anyTrueHelper(((ShortMaskMax)m).getBits())); } @Override @ForceInline public boolean allTrue() { return VectorSupport.test(BT_overflow, ShortMaskMax.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> allTrueHelper(((ShortMaskMax)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> allTrueHelper(((ShortMaskMax)m).getBits())); } @ForceInline @@ -795,7 +793,7 @@ this, vspecies().maskAll(true), static ShortMaskMax maskAll(boolean bit) { return VectorSupport.fromBitsCoerced(ShortMaskMax.class, LANEBITS_TYPE_ORDINAL, VLENGTH, (bit ? -1 : 0), MODE_BROADCAST, null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + (v, _) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final ShortMaskMax TRUE_MASK = new ShortMaskMax(true); private static final ShortMaskMax FALSE_MASK = new ShortMaskMax(false); @@ -855,7 +853,7 @@ ShortVectorMax toBitsVector() { @Override ShortVectorMax toBitsVector0() { - return ((ShortVectorMax) vspecies().asIntegral().dummyVector()).vectorFactory(indices()); + return ((ShortVectorMax) VSPECIES.asIntegral().dummyVector()).vectorFactory(indices()); } @Override @@ -894,7 +892,7 @@ public void intoMemorySegment(MemorySegment ms, long offset, ByteOrder bo) { @ForceInline public final ShortMaskMax laneIsValid() { return (ShortMaskMax) toBitsVector().compare(VectorOperators.GE, 0) - .cast(vspecies()); + .cast(VSPECIES); } @ForceInline @@ -902,7 +900,7 @@ public final ShortMaskMax laneIsValid() { public final ShortShuffleMax rearrange(VectorShuffle shuffle) { ShortShuffleMax concreteShuffle = (ShortShuffleMax) shuffle; return (ShortShuffleMax) toBitsVector().rearrange(concreteShuffle) - .toShuffle(vspecies(), false); + .toShuffle(VSPECIES, false); } @ForceInline @@ -915,7 +913,7 @@ public final ShortShuffleMax wrapIndexes() { v = (ShortVectorMax) v.blend(v.lanewise(VectorOperators.ADD, length()), v.compare(VectorOperators.LT, 0)); } - return (ShortShuffleMax) v.toShuffle(vspecies(), false); + return (ShortShuffleMax) v.toShuffle(VSPECIES, false); } private static short[] prepare(int[] indices, int offset) { diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Util.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Util.java index 8562d4b5d7a..133195fa54d 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Util.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Util.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ */ package jdk.incubator.vector; -/*package-private*/ class Util { +/*package-private*/ final class Util { public static void requires(boolean cond, String message) { if (!cond) { throw new InternalError(message); diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Vector.java index 68b4a35067c..85b3bbca269 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Vector.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1170,9 +1170,10 @@ * @param the boxed version of {@code ETYPE}, * the element type of a vector * + * @sealedGraph */ @SuppressWarnings("exports") -public abstract class Vector extends jdk.internal.vm.vector.VectorSupport.Vector { +public abstract sealed class Vector extends jdk.internal.vm.vector.VectorSupport.Vector permits AbstractVector { // This type is sealed within its package. // Users cannot roll their own vector types. diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/VectorIntrinsics.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/VectorIntrinsics.java index 266a843083a..f0115371d48 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/VectorIntrinsics.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/VectorIntrinsics.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,7 @@ import java.util.Objects; -/*non-public*/ class VectorIntrinsics { +/*non-public*/ final class VectorIntrinsics { static final int VECTOR_ACCESS_OOB_CHECK = Integer.getInteger("jdk.incubator.vector.VECTOR_ACCESS_OOB_CHECK", 2); diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/VectorMask.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/VectorMask.java index 13ee9e27e0d..607b194946b 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/VectorMask.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/VectorMask.java @@ -131,7 +131,7 @@ * the element type of a vector */ @SuppressWarnings("exports") -public abstract class VectorMask extends jdk.internal.vm.vector.VectorSupport.VectorMask { +public abstract sealed class VectorMask extends jdk.internal.vm.vector.VectorSupport.VectorMask permits AbstractMask { VectorMask(boolean[] bits) { super(bits); } /** diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/VectorMathLibrary.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/VectorMathLibrary.java index 1c1cfcc78c7..823cebd85a9 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/VectorMathLibrary.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/VectorMathLibrary.java @@ -42,7 +42,7 @@ * A wrapper for native vector math libraries bundled with the JDK (SVML and SLEEF). * Binds vector operations to native implementations provided by the libraries. */ -/*package-private*/ class VectorMathLibrary { +/*package-private*/ final class VectorMathLibrary { private static final SymbolLookup LOOKUP = SymbolLookup.loaderLookup(); interface Library { diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/VectorOperators.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/VectorOperators.java index 84009c55ac9..2f2d33ab130 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/VectorOperators.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/VectorOperators.java @@ -24,13 +24,12 @@ */ package jdk.incubator.vector; -import java.util.function.IntFunction; -import java.util.HashMap; import java.util.ArrayList; +import java.util.HashMap; +import java.util.function.IntFunction; import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.annotation.Stable; - import jdk.internal.vm.vector.VectorSupport; import static jdk.internal.vm.vector.Utils.isNonCapturingLambda; @@ -115,7 +114,7 @@ * operations on individual lane values. * */ -public abstract class VectorOperators { +public final class VectorOperators { private VectorOperators() { } /** @@ -131,12 +130,9 @@ private VectorOperators() { } * @see VectorOperators.Test Test * @see VectorOperators.Conversion Conversion * - * @apiNote - * User code should not implement this interface. A future release of - * this type may restrict implementations to be members of the same - * package. + * @sealedGraph */ - public interface Operator { + public sealed interface Operator { /** * Returns the symbolic name of this operator, * as a constant in {@link VectorOperators}. @@ -235,13 +231,8 @@ public interface Operator { * usable in expressions like {@code w = v0.}{@link * Vector#lanewise(VectorOperators.Unary) * lanewise}{@code (NEG)}. - * - * @apiNote - * User code should not implement this interface. A future release of - * this type may restrict implementations to be members of the same - * package. */ - public interface Unary extends Operator { + public sealed interface Unary extends Operator { } /** @@ -252,12 +243,9 @@ public interface Unary extends Operator { * Vector#lanewise(VectorOperators.Binary,Vector) * lanewise}{@code (ADD, v1)}. * - * @apiNote - * User code should not implement this interface. A future release of - * this type may restrict implementations to be members of the same - * package. + * @sealedGraph */ - public interface Binary extends Operator { + public sealed interface Binary extends Operator { } /** @@ -267,13 +255,8 @@ public interface Binary extends Operator { * usable in expressions like {@code w = v0.}{@link * Vector#lanewise(VectorOperators.Ternary,Vector,Vector) * lanewise}{@code (FMA, v1, v2)}. - * - * @apiNote - * User code should not implement this interface. A future release of - * this type may restrict implementations to be members of the same - * package. */ - public interface Ternary extends Operator { + public sealed interface Ternary extends Operator { } /** @@ -283,13 +266,8 @@ public interface Ternary extends Operator { * usable in expressions like {@code e = v0.}{@link * IntVector#reduceLanes(VectorOperators.Associative) * reduceLanes}{@code (ADD)}. - * - * @apiNote - * User code should not implement this interface. A future release of - * this type may restrict implementations to be members of the same - * package. */ - public interface Associative extends Binary { + public sealed interface Associative extends Binary { } /** @@ -299,13 +277,8 @@ public interface Associative extends Binary { * usable in expressions like {@code m = v0.}{@link * FloatVector#test(VectorOperators.Test) * test}{@code (IS_FINITE)}. - * - * @apiNote - * User code should not implement this interface. A future release of - * this type may restrict implementations to be members of the same - * package. */ - public interface Test extends Operator { + public sealed interface Test extends Operator { } /** @@ -315,13 +288,8 @@ public interface Test extends Operator { * usable in expressions like {@code m = v0.}{@link * Vector#compare(VectorOperators.Comparison,Vector) * compare}{@code (LT, v1)}. - * - * @apiNote - * User code should not implement this interface. A future release of - * this type may restrict implementations to be members of the same - * package. */ - public interface Comparison extends Operator { + public sealed interface Comparison extends Operator { } /** @@ -336,13 +304,8 @@ public interface Comparison extends Operator { * domain type (the input lane type) * @param the boxed element type for the conversion * range type (the output lane type) - * - * @apiNote - * User code should not implement this interface. A future release of - * this type may restrict implementations to be members of the same - * package. */ - public interface Conversion extends Operator { + public sealed interface Conversion extends Operator { /** * The domain of this conversion, a primitive type. * @return the domain of this conversion @@ -831,7 +794,7 @@ private static Comparison compare(String name, String opName, int opCode, int fl kind, dom, ran); } - private abstract static class OperatorImpl implements Operator { + private abstract static sealed class OperatorImpl implements Operator { private final String symName; private final String opName; private final int opInfo; @@ -956,35 +919,35 @@ boolean compatibleWith(LaneType type) { } } - private static class UnaryImpl extends OperatorImpl implements Unary { + private static final class UnaryImpl extends OperatorImpl implements Unary { private UnaryImpl(String symName, String opName, int opInfo) { super(symName, opName, opInfo); assert((opInfo & VO_ARITY_MASK) == VO_UNARY); } } - private static class BinaryImpl extends OperatorImpl implements Binary { + private static sealed class BinaryImpl extends OperatorImpl implements Binary permits AssociativeImpl { private BinaryImpl(String symName, String opName, int opInfo) { super(symName, opName, opInfo); assert((opInfo & VO_ARITY_MASK) == VO_BINARY); } } - private static class TernaryImpl extends OperatorImpl implements Ternary { + private static final class TernaryImpl extends OperatorImpl implements Ternary { private TernaryImpl(String symName, String opName, int opInfo) { super(symName, opName, opInfo); assert((opInfo & VO_ARITY_MASK) == VO_TERNARY); } } - private static class AssociativeImpl extends BinaryImpl implements Associative { + private static final class AssociativeImpl extends BinaryImpl implements Associative { private AssociativeImpl(String symName, String opName, int opInfo) { super(symName, opName, opInfo); } } /*package-private*/ - static + static final class ConversionImpl extends OperatorImpl implements Conversion { private ConversionImpl(String symName, String opName, int opInfo, @@ -1260,7 +1223,7 @@ private String genCode(String opcs) { } } - private static class TestImpl extends OperatorImpl implements Test { + private static final class TestImpl extends OperatorImpl implements Test { private TestImpl(String symName, String opName, int opInfo) { super(symName, opName, opInfo); assert((opInfo & VO_ARITY_MASK) == VO_UNARY); @@ -1272,7 +1235,7 @@ public Class rangeType() { } } - private static class ComparisonImpl extends OperatorImpl implements Comparison { + private static final class ComparisonImpl extends OperatorImpl implements Comparison { private ComparisonImpl(String symName, String opName, int opInfo) { super(symName, opName, opInfo); assert((opInfo & VO_ARITY_MASK) == VO_BINARY); diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/VectorShuffle.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/VectorShuffle.java index 9cde9d2315c..5da38a25e16 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/VectorShuffle.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/VectorShuffle.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -136,7 +136,7 @@ * the element type of a vector */ @SuppressWarnings("exports") -public abstract class VectorShuffle extends jdk.internal.vm.vector.VectorSupport.VectorShuffle { +public abstract sealed class VectorShuffle extends jdk.internal.vm.vector.VectorSupport.VectorShuffle permits AbstractShuffle { VectorShuffle(Object indices) { super(indices); } diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/VectorSpecies.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/VectorSpecies.java index e80bbf231ea..4c3ef3f471d 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/VectorSpecies.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/VectorSpecies.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,11 +36,6 @@ * of element type ({@code ETYPE}) * and {@link VectorShape shape}. * - * @apiNote - * User code should not implement this interface. A future release of - * this type may restrict implementations to be members of the same - * package. - * * @implNote * The string representation of an instance of this interface will * be of the form "Species[ETYPE, VLENGTH, SHAPE]", where {@code @@ -57,7 +52,7 @@ * @param the boxed version of {@code ETYPE}, * the element type of a vector */ -public interface VectorSpecies { +public sealed interface VectorSpecies permits AbstractSpecies { /** * Returns the primitive element type of vectors of this * species. 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 95fe8ca35db..b3c5bfac302 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 @@ -49,7 +49,8 @@ import static jdk.incubator.vector.VectorOperators.*; * {@code $type$} values. */ @SuppressWarnings("cast") // warning: redundant cast -public abstract class $abstractvectortype$ extends AbstractVector<$Boxtype$> { +public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtype$> + permits $Type$Vector64, $Type$Vector128, $Type$Vector256, $Type$Vector512, $Type$VectorMax { $abstractvectortype$($type$[] vec) { super(vec); diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-VectorBits.java.template b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-VectorBits.java.template index 35041a0b70f..d66d22cab19 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-VectorBits.java.template +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-VectorBits.java.template @@ -25,7 +25,9 @@ package jdk.incubator.vector; import java.lang.foreign.MemorySegment; +#if[longOrDouble] import java.lang.foreign.ValueLayout; +#end[longOrDouble] import java.nio.ByteOrder; import java.util.Arrays; import java.util.Objects; @@ -35,9 +37,8 @@ import jdk.internal.ValueBased; import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; -import static jdk.internal.vm.vector.VectorSupport.*; - import static jdk.incubator.vector.VectorOperators.*; +import static jdk.internal.vm.vector.VectorSupport.*; #warn This file is preprocessed before being compiled @@ -389,7 +390,7 @@ final class $vectortype$ extends $abstractvectortype$ { @Override @ForceInline public final $shuffletype$ toShuffle() { - return ($shuffletype$) toShuffle(vspecies(), false); + return ($shuffletype$) toShuffle(VSPECIES, false); } // Specialized unary testing @@ -905,7 +906,7 @@ final class $vectortype$ extends $abstractvectortype$ { @Override $masktype$ uOp(MUnOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); for (int i = 0; i < res.length; i++) { res[i] = f.apply(i, bits[i]); @@ -915,7 +916,7 @@ final class $vectortype$ extends $abstractvectortype$ { @Override $masktype$ bOp(VectorMask<$Boxtype$> m, MBinOp f) { - boolean[] res = new boolean[vspecies().laneCount()]; + boolean[] res = new boolean[VSPECIES.laneCount()]; boolean[] bits = getBits(); boolean[] mbits = (($masktype$)m).getBits(); for (int i = 0; i < res.length; i++) { @@ -1065,16 +1066,16 @@ final class $vectortype$ extends $abstractvectortype$ { @ForceInline public boolean anyTrue() { return VectorSupport.test(BT_ne, $masktype$.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> anyTrueHelper((($masktype$)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> anyTrueHelper((($masktype$)m).getBits())); } @Override @ForceInline public boolean allTrue() { return VectorSupport.test(BT_overflow, $masktype$.class, LANEBITS_TYPE_ORDINAL, VLENGTH, - this, vspecies().maskAll(true), - (m, __) -> allTrueHelper((($masktype$)m).getBits())); + this, VSPECIES.maskAll(true), + (m, _) -> allTrueHelper((($masktype$)m).getBits())); } @ForceInline @@ -1082,7 +1083,7 @@ final class $vectortype$ extends $abstractvectortype$ { static $masktype$ maskAll(boolean bit) { return VectorSupport.fromBitsCoerced($masktype$.class, LANEBITS_TYPE_ORDINAL, VLENGTH, (bit ? -1 : 0), MODE_BROADCAST, null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + (v, _) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final $masktype$ TRUE_MASK = new $masktype$(true); private static final $masktype$ FALSE_MASK = new $masktype$(false); @@ -1147,7 +1148,7 @@ final class $vectortype$ extends $abstractvectortype$ { @Override @ForceInline public $vectortype$ toVector() { - return ($vectortype$) toBitsVector().castShape(vspecies(), 0); + return ($vectortype$) toBitsVector().castShape(VSPECIES, 0); } #else[FP] @Override @@ -1165,7 +1166,7 @@ final class $vectortype$ extends $abstractvectortype$ { @Override $bitsvectortype$ toBitsVector0() { - return (($bitsvectortype$) vspecies().asIntegral().dummyVector()).vectorFactory(indices()); + return (($bitsvectortype$) VSPECIES.asIntegral().dummyVector()).vectorFactory(indices()); } @Override @@ -1301,7 +1302,7 @@ final class $vectortype$ extends $abstractvectortype$ { @ForceInline public final $masktype$ laneIsValid() { return ($masktype$) toBitsVector().compare(VectorOperators.GE, 0) - .cast(vspecies()); + .cast(VSPECIES); } @ForceInline @@ -1310,10 +1311,10 @@ final class $vectortype$ extends $abstractvectortype$ { $shuffletype$ concreteShuffle = ($shuffletype$) shuffle; #if[FP] return ($shuffletype$) toBitsVector().rearrange(concreteShuffle.cast($Bitstype$Vector.SPECIES_$BITS$)) - .toShuffle(vspecies(), false); + .toShuffle(VSPECIES, false); #else[FP] return ($shuffletype$) toBitsVector().rearrange(concreteShuffle) - .toShuffle(vspecies(), false); + .toShuffle(VSPECIES, false); #end[FP] } @@ -1327,7 +1328,7 @@ final class $vectortype$ extends $abstractvectortype$ { v = ($bitsvectortype$) v.blend(v.lanewise(VectorOperators.ADD, length()), v.compare(VectorOperators.LT, 0)); } - return ($shuffletype$) v.toShuffle(vspecies(), false); + return ($shuffletype$) v.toShuffle(VSPECIES, false); } private static $bitstype$[] prepare(int[] indices, int offset) { From 5164fbc9f841bec1ad4fb33b11a3ad11489d49d8 Mon Sep 17 00:00:00 2001 From: Rui Li Date: Thu, 26 Mar 2026 23:47:12 +0000 Subject: [PATCH 023/116] 8374191: Shenandoah: Consider an assert in get_object_age Reviewed-by: wkemper --- src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp index 02f2beaf4e0..6d77cccaa6a 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp @@ -344,6 +344,8 @@ uint ShenandoahHeap::get_object_age(oop obj) { } if (w.has_monitor()) { w = w.monitor()->header(); + } else { + assert(!w.has_displaced_mark_helper(), "Mark word should not be displaced"); } assert(w.age() <= markWord::max_age, "Impossible!"); return w.age(); From 1a9965555477ee2a6cb65e91ef54ed608e4bee66 Mon Sep 17 00:00:00 2001 From: Mohamed Issa Date: Fri, 27 Mar 2026 04:56:30 +0000 Subject: [PATCH 024/116] 8378295: Update scalar AVX10 floating point min/max definitions Reviewed-by: sviswanathan, mhaessig, jbhateja, sparasa --- src/hotspot/cpu/x86/assembler_x86.cpp | 156 +++++---- src/hotspot/cpu/x86/assembler_x86.hpp | 34 +- src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp | 77 ++++- src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp | 26 +- src/hotspot/cpu/x86/macroAssembler_x86.cpp | 46 ++- src/hotspot/cpu/x86/macroAssembler_x86.hpp | 22 +- src/hotspot/cpu/x86/x86.ad | 311 +++++++++--------- .../math/TestFpMinMaxReductions.java | 32 +- .../compiler/lib/ir_framework/IRNode.java | 36 +- .../vector/Float16OperationsBenchmark.java | 38 ++- .../bench/vm/compiler/FpMinMaxIntrinsics.java | 169 +++++++++- 11 files changed, 626 insertions(+), 321 deletions(-) diff --git a/src/hotspot/cpu/x86/assembler_x86.cpp b/src/hotspot/cpu/x86/assembler_x86.cpp index 38a28a6ec49..a4f2968f0d1 100644 --- a/src/hotspot/cpu/x86/assembler_x86.cpp +++ b/src/hotspot/cpu/x86/assembler_x86.cpp @@ -3472,7 +3472,7 @@ void Assembler::vmovdqu(XMMRegister dst, XMMRegister src) { emit_int16(0x6F, (0xC0 | encode)); } -void Assembler::vmovw(XMMRegister dst, Register src) { +void Assembler::evmovw(XMMRegister dst, Register src) { assert(VM_Version::supports_avx512_fp16(), "requires AVX512-FP16"); InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); attributes.set_is_evex_instruction(); @@ -3480,7 +3480,7 @@ void Assembler::vmovw(XMMRegister dst, Register src) { emit_int16(0x6E, (0xC0 | encode)); } -void Assembler::vmovw(Register dst, XMMRegister src) { +void Assembler::evmovw(Register dst, XMMRegister src) { assert(VM_Version::supports_avx512_fp16(), "requires AVX512-FP16"); InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); attributes.set_is_evex_instruction(); @@ -3488,6 +3488,36 @@ void Assembler::vmovw(Register dst, XMMRegister src) { emit_int16(0x7E, (0xC0 | encode)); } +void Assembler::evmovw(XMMRegister dst, Address src) { + assert(VM_Version::supports_avx10_2(), ""); + InstructionMark im(this); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); + attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_16bit); + attributes.set_is_evex_instruction(); + vex_prefix(src, 0, dst->encoding(), VEX_SIMD_F3, VEX_OPCODE_MAP5, &attributes); + emit_int8(0x6E); + emit_operand(dst, src, 0); +} + +void Assembler::evmovw(Address dst, XMMRegister src) { + assert(VM_Version::supports_avx10_2(), ""); + InstructionMark im(this); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); + attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_16bit); + attributes.set_is_evex_instruction(); + vex_prefix(dst, 0, src->encoding(), VEX_SIMD_F3, VEX_OPCODE_MAP5, &attributes); + emit_int8(0x7E); + emit_operand(src, dst, 0); +} + +void Assembler::evmovw(XMMRegister dst, XMMRegister src) { + assert(VM_Version::supports_avx10_2(), ""); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); + attributes.set_is_evex_instruction(); + int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_F3, VEX_OPCODE_MAP5, &attributes); + emit_int16(0x6E, (0xC0 | encode)); +} + void Assembler::vmovdqu(XMMRegister dst, Address src) { assert(UseAVX > 0, ""); InstructionMark im(this); @@ -7310,6 +7340,42 @@ void Assembler::etzcntq(Register dst, Address src, bool no_flags) { emit_operand(dst, src, 0); } +void Assembler::evucomish(XMMRegister dst, Address src) { + InstructionMark im(this); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); + attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_16bit); + attributes.set_is_evex_instruction(); + vex_prefix(src, 0, dst->encoding(), VEX_SIMD_NONE, VEX_OPCODE_MAP5, &attributes); + emit_int8(0x2E); + emit_operand(dst, src, 0); +} + +void Assembler::evucomish(XMMRegister dst, XMMRegister src) { + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); + attributes.set_is_evex_instruction(); + int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_NONE, VEX_OPCODE_MAP5, &attributes); + emit_int16(0x2E, (0xC0 | encode)); +} + +void Assembler::evucomxsh(XMMRegister dst, Address src) { + assert(VM_Version::supports_avx10_2(), ""); + InstructionMark im(this); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); + attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_16bit); + attributes.set_is_evex_instruction(); + vex_prefix(src, 0, dst->encoding(), VEX_SIMD_F3, VEX_OPCODE_MAP5, &attributes); + emit_int8(0x2E); + emit_operand(dst, src, 0); +} + +void Assembler::evucomxsh(XMMRegister dst, XMMRegister src) { + assert(VM_Version::supports_avx10_2(), ""); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); + attributes.set_is_evex_instruction(); + int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_F3, VEX_OPCODE_MAP5, &attributes); + emit_int16(0x2E, (0xC0 | encode)); +} + void Assembler::ucomisd(XMMRegister dst, Address src) { InstructionMark im(this); InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); @@ -7327,7 +7393,7 @@ void Assembler::ucomisd(XMMRegister dst, XMMRegister src) { emit_int16(0x2E, (0xC0 | encode)); } -void Assembler::vucomxsd(XMMRegister dst, Address src) { +void Assembler::evucomxsd(XMMRegister dst, Address src) { assert(VM_Version::supports_avx10_2(), ""); InstructionMark im(this); InstructionAttr attributes(AVX_128bit, /* rex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); @@ -7338,7 +7404,7 @@ void Assembler::vucomxsd(XMMRegister dst, Address src) { emit_operand(dst, src, 0); } -void Assembler::vucomxsd(XMMRegister dst, XMMRegister src) { +void Assembler::evucomxsd(XMMRegister dst, XMMRegister src) { assert(VM_Version::supports_avx10_2(), ""); InstructionAttr attributes(AVX_128bit, /* rex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); attributes.set_is_evex_instruction(); @@ -7361,7 +7427,7 @@ void Assembler::ucomiss(XMMRegister dst, XMMRegister src) { emit_int16(0x2E, (0xC0 | encode)); } -void Assembler::vucomxss(XMMRegister dst, Address src) { +void Assembler::evucomxss(XMMRegister dst, Address src) { assert(VM_Version::supports_avx10_2(), ""); InstructionMark im(this); InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); @@ -7372,7 +7438,7 @@ void Assembler::vucomxss(XMMRegister dst, Address src) { emit_operand(dst, src, 0); } -void Assembler::vucomxss(XMMRegister dst, XMMRegister src) { +void Assembler::evucomxss(XMMRegister dst, XMMRegister src) { assert(VM_Version::supports_avx10_2(), ""); InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); attributes.set_is_evex_instruction(); @@ -8411,30 +8477,6 @@ void Assembler::vmulsh(XMMRegister dst, XMMRegister nds, XMMRegister src) { emit_int16(0x59, (0xC0 | encode)); } -void Assembler::vmaxsh(XMMRegister dst, XMMRegister nds, XMMRegister src) { - assert(VM_Version::supports_avx512_fp16(), "requires AVX512-FP16"); - InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); - attributes.set_is_evex_instruction(); - int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_F3, VEX_OPCODE_MAP5, &attributes); - emit_int16(0x5F, (0xC0 | encode)); -} - -void Assembler::eminmaxsh(XMMRegister dst, XMMRegister nds, XMMRegister src, int imm8) { - assert(VM_Version::supports_avx10_2(), ""); - InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); - attributes.set_is_evex_instruction(); - int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3A, &attributes); - emit_int24(0x53, (0xC0 | encode), imm8); -} - -void Assembler::vminsh(XMMRegister dst, XMMRegister nds, XMMRegister src) { - assert(VM_Version::supports_avx512_fp16(), "requires AVX512-FP16"); - InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); - attributes.set_is_evex_instruction(); - int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_F3, VEX_OPCODE_MAP5, &attributes); - emit_int16(0x5D, (0xC0 | encode)); -} - void Assembler::vsqrtsh(XMMRegister dst, XMMRegister src) { assert(VM_Version::supports_avx512_fp16(), "requires AVX512-FP16"); InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); @@ -13369,48 +13411,38 @@ bool Assembler::is_demotable(bool no_flags, int dst_enc, int nds_enc) { return (!no_flags && dst_enc == nds_enc); } -void Assembler::vmaxss(XMMRegister dst, XMMRegister nds, XMMRegister src) { - assert(VM_Version::supports_avx(), ""); - InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); - int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_F3, VEX_OPCODE_0F, &attributes); - emit_int16(0x5F, (0xC0 | encode)); -} - -void Assembler::vmaxsd(XMMRegister dst, XMMRegister nds, XMMRegister src) { - assert(VM_Version::supports_avx(), ""); - InstructionAttr attributes(AVX_128bit, /* vex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); - attributes.set_rex_vex_w_reverted(); - int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_F2, VEX_OPCODE_0F, &attributes); - emit_int16(0x5F, (0xC0 | encode)); -} - -void Assembler::vminss(XMMRegister dst, XMMRegister nds, XMMRegister src) { - assert(VM_Version::supports_avx(), ""); - InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); - int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_F3, VEX_OPCODE_0F, &attributes); - emit_int16(0x5D, (0xC0 | encode)); +void Assembler::evminmaxsh(XMMRegister dst, KRegister mask, XMMRegister nds, XMMRegister src, bool merge, int imm8) { + assert(VM_Version::supports_avx10_2(), ""); + InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + 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(), nds->encoding(), src->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3A, &attributes); + emit_int24(0x53, (0xC0 | encode), imm8); } -void Assembler::eminmaxss(XMMRegister dst, XMMRegister nds, XMMRegister src, int imm8) { +void Assembler::evminmaxss(XMMRegister dst, KRegister mask, XMMRegister nds, XMMRegister src, bool merge, int imm8) { assert(VM_Version::supports_avx10_2(), ""); - InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); 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(), nds->encoding(), src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); emit_int24(0x53, (0xC0 | encode), imm8); } -void Assembler::vminsd(XMMRegister dst, XMMRegister nds, XMMRegister src) { - assert(VM_Version::supports_avx(), ""); - InstructionAttr attributes(AVX_128bit, /* vex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); - attributes.set_rex_vex_w_reverted(); - int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_F2, VEX_OPCODE_0F, &attributes); - emit_int16(0x5D, (0xC0 | encode)); -} - -void Assembler::eminmaxsd(XMMRegister dst, XMMRegister nds, XMMRegister src, int imm8) { +void Assembler::evminmaxsd(XMMRegister dst, KRegister mask, XMMRegister nds, XMMRegister src, bool merge, int imm8) { assert(VM_Version::supports_avx10_2(), ""); - InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); 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(), nds->encoding(), src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); emit_int24(0x53, (0xC0 | encode), imm8); } diff --git a/src/hotspot/cpu/x86/assembler_x86.hpp b/src/hotspot/cpu/x86/assembler_x86.hpp index 57a5e25d7a6..98684752b0c 100644 --- a/src/hotspot/cpu/x86/assembler_x86.hpp +++ b/src/hotspot/cpu/x86/assembler_x86.hpp @@ -1694,8 +1694,11 @@ class Assembler : public AbstractAssembler { void movsbl(Register dst, Address src); void movsbl(Register dst, Register src); - void vmovw(XMMRegister dst, Register src); - void vmovw(Register dst, XMMRegister src); + void evmovw(XMMRegister dst, Register src); + void evmovw(Register dst, XMMRegister src); + void evmovw(XMMRegister dst, Address src); + void evmovw(Address dst, XMMRegister src); + void evmovw(XMMRegister dst, XMMRegister src); void movsbq(Register dst, Address src); void movsbq(Register dst, Register src); @@ -2329,17 +2332,23 @@ class Assembler : public AbstractAssembler { void tzcntq(Register dst, Address src); void etzcntq(Register dst, Address src, bool no_flags); + // Unordered Compare Scalar Half-Precision Floating-Point Values and set EFLAGS + void evucomish(XMMRegister dst, Address src); + void evucomish(XMMRegister dst, XMMRegister src); + void evucomxsh(XMMRegister dst, Address src); + void evucomxsh(XMMRegister dst, XMMRegister src); + // Unordered Compare Scalar Double-Precision Floating-Point Values and set EFLAGS void ucomisd(XMMRegister dst, Address src); void ucomisd(XMMRegister dst, XMMRegister src); - void vucomxsd(XMMRegister dst, Address src); - void vucomxsd(XMMRegister dst, XMMRegister src); + void evucomxsd(XMMRegister dst, Address src); + void evucomxsd(XMMRegister dst, XMMRegister src); // Unordered Compare Scalar Single-Precision Floating-Point Values and set EFLAGS void ucomiss(XMMRegister dst, Address src); void ucomiss(XMMRegister dst, XMMRegister src); - void vucomxss(XMMRegister dst, Address src); - void vucomxss(XMMRegister dst, XMMRegister src); + void evucomxss(XMMRegister dst, Address src); + void evucomxss(XMMRegister dst, XMMRegister src); void xabort(int8_t imm8); @@ -2417,11 +2426,6 @@ class Assembler : public AbstractAssembler { void vsubss(XMMRegister dst, XMMRegister nds, Address src); void vsubss(XMMRegister dst, XMMRegister nds, XMMRegister src); - void vmaxss(XMMRegister dst, XMMRegister nds, XMMRegister src); - void vmaxsd(XMMRegister dst, XMMRegister nds, XMMRegister src); - void vminss(XMMRegister dst, XMMRegister nds, XMMRegister src); - void vminsd(XMMRegister dst, XMMRegister nds, XMMRegister src); - void sarxl(Register dst, Register src1, Register src2); void sarxl(Register dst, Address src1, Register src2); void sarxq(Register dst, Register src1, Register src2); @@ -2552,8 +2556,6 @@ class Assembler : public AbstractAssembler { void vsubsh(XMMRegister dst, XMMRegister nds, XMMRegister src); void vmulsh(XMMRegister dst, XMMRegister nds, XMMRegister src); void vdivsh(XMMRegister dst, XMMRegister nds, XMMRegister src); - void vmaxsh(XMMRegister dst, XMMRegister nds, XMMRegister src); - void vminsh(XMMRegister dst, XMMRegister nds, XMMRegister src); void vsqrtsh(XMMRegister dst, XMMRegister src); void vfmadd132sh(XMMRegister dst, XMMRegister src1, XMMRegister src2); @@ -2790,9 +2792,9 @@ class Assembler : public AbstractAssembler { void vminpd(XMMRegister dst, XMMRegister src1, XMMRegister src2, int vector_len); // AVX10.2 floating point minmax instructions - void eminmaxsh(XMMRegister dst, XMMRegister nds, XMMRegister src, int imm8); - void eminmaxss(XMMRegister dst, XMMRegister nds, XMMRegister src, int imm8); - void eminmaxsd(XMMRegister dst, XMMRegister nds, XMMRegister src, int imm8); + void evminmaxsh(XMMRegister dst, KRegister mask, XMMRegister nds, XMMRegister src, bool merge, int imm8); + void evminmaxss(XMMRegister dst, KRegister mask, XMMRegister nds, XMMRegister src, bool merge, int imm8); + void evminmaxsd(XMMRegister dst, KRegister mask, XMMRegister nds, XMMRegister src, bool merge, int imm8); void evminmaxph(XMMRegister dst, KRegister mask, XMMRegister nds, XMMRegister src, bool merge, int imm8, int vector_len); void evminmaxph(XMMRegister dst, KRegister mask, XMMRegister nds, Address src, bool merge, int imm8, int vector_len); void evminmaxps(XMMRegister dst, KRegister mask, XMMRegister nds, XMMRegister src, bool merge, int imm8, int vector_len); diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp index 5b5fb02967c..c1df726b5ba 100644 --- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp @@ -1037,8 +1037,8 @@ void C2_MacroAssembler::evminmax_fp(int opcode, BasicType elem_bt, } } -void C2_MacroAssembler::vminmax_fp(int opc, BasicType elem_bt, XMMRegister dst, KRegister mask, - XMMRegister src1, XMMRegister src2, int vlen_enc) { +void C2_MacroAssembler::vminmax_fp_avx10_2(int opc, BasicType elem_bt, XMMRegister dst, KRegister mask, + XMMRegister src1, XMMRegister src2, int vlen_enc) { assert(opc == Op_MinV || opc == Op_MinReductionV || opc == Op_MaxV || opc == Op_MaxReductionV, "sanity"); @@ -1052,6 +1052,21 @@ void C2_MacroAssembler::vminmax_fp(int opc, BasicType elem_bt, XMMRegister dst, } } +void C2_MacroAssembler::sminmax_fp_avx10_2(int opc, BasicType elem_bt, XMMRegister dst, KRegister mask, + XMMRegister src1, XMMRegister src2) { + assert(opc == Op_MinF || opc == Op_MaxF || + opc == Op_MinD || opc == Op_MaxD, "sanity"); + + int imm8 = (opc == Op_MinF || opc == Op_MinD) ? AVX10_2_MINMAX_MIN_COMPARE_SIGN + : AVX10_2_MINMAX_MAX_COMPARE_SIGN; + if (elem_bt == T_FLOAT) { + evminmaxss(dst, mask, src1, src2, true, imm8); + } else { + assert(elem_bt == T_DOUBLE, ""); + evminmaxsd(dst, mask, src1, src2, true, imm8); + } +} + // Float/Double signum void C2_MacroAssembler::signum_fp(int opcode, XMMRegister dst, XMMRegister zero, XMMRegister one) { assert(opcode == Op_SignumF || opcode == Op_SignumD, "sanity"); @@ -1063,7 +1078,7 @@ void C2_MacroAssembler::signum_fp(int opcode, XMMRegister dst, XMMRegister zero, // If other floating point comparison instructions used, ZF=1 for equal and unordered cases if (opcode == Op_SignumF) { if (VM_Version::supports_avx10_2()) { - vucomxss(dst, zero); + evucomxss(dst, zero); jcc(Assembler::negative, DONE_LABEL); } else { ucomiss(dst, zero); @@ -1074,7 +1089,7 @@ void C2_MacroAssembler::signum_fp(int opcode, XMMRegister dst, XMMRegister zero, xorps(dst, ExternalAddress(StubRoutines::x86::vector_float_sign_flip()), noreg); } else if (opcode == Op_SignumD) { if (VM_Version::supports_avx10_2()) { - vucomxsd(dst, zero); + evucomxsd(dst, zero); jcc(Assembler::negative, DONE_LABEL); } else { ucomisd(dst, zero); @@ -2400,7 +2415,7 @@ void C2_MacroAssembler::reduceFloatMinMax(int opcode, int vlen, bool is_dst_vali } if (VM_Version::supports_avx10_2()) { - vminmax_fp(opcode, T_FLOAT, wdst, k0, wtmp, wsrc, vlen_enc); + vminmax_fp_avx10_2(opcode, T_FLOAT, wdst, k0, wtmp, wsrc, vlen_enc); } else { vminmax_fp(opcode, T_FLOAT, wdst, wtmp, wsrc, tmp, atmp, btmp, vlen_enc); } @@ -2409,7 +2424,7 @@ void C2_MacroAssembler::reduceFloatMinMax(int opcode, int vlen, bool is_dst_vali } if (is_dst_valid) { if (VM_Version::supports_avx10_2()) { - vminmax_fp(opcode, T_FLOAT, dst, k0, wdst, dst, Assembler::AVX_128bit); + vminmax_fp_avx10_2(opcode, T_FLOAT, dst, k0, wdst, dst, Assembler::AVX_128bit); } else { vminmax_fp(opcode, T_FLOAT, dst, wdst, dst, tmp, atmp, btmp, Assembler::AVX_128bit); } @@ -2440,7 +2455,7 @@ void C2_MacroAssembler::reduceDoubleMinMax(int opcode, int vlen, bool is_dst_val } if (VM_Version::supports_avx10_2()) { - vminmax_fp(opcode, T_DOUBLE, wdst, k0, wtmp, wsrc, vlen_enc); + vminmax_fp_avx10_2(opcode, T_DOUBLE, wdst, k0, wtmp, wsrc, vlen_enc); } else { vminmax_fp(opcode, T_DOUBLE, wdst, wtmp, wsrc, tmp, atmp, btmp, vlen_enc); } @@ -2451,7 +2466,7 @@ void C2_MacroAssembler::reduceDoubleMinMax(int opcode, int vlen, bool is_dst_val if (is_dst_valid) { if (VM_Version::supports_avx10_2()) { - vminmax_fp(opcode, T_DOUBLE, dst, k0, wdst, dst, Assembler::AVX_128bit); + vminmax_fp_avx10_2(opcode, T_DOUBLE, dst, k0, wdst, dst, Assembler::AVX_128bit); } else { vminmax_fp(opcode, T_DOUBLE, dst, wdst, dst, tmp, atmp, btmp, Assembler::AVX_128bit); } @@ -7061,13 +7076,25 @@ void C2_MacroAssembler::evfp16ph(int opcode, XMMRegister dst, XMMRegister src1, } } -void C2_MacroAssembler::scalar_max_min_fp16(int opcode, XMMRegister dst, XMMRegister src1, XMMRegister src2, - KRegister ktmp, XMMRegister xtmp1, XMMRegister xtmp2) { - vector_max_min_fp16(opcode, dst, src1, src2, ktmp, xtmp1, xtmp2, Assembler::AVX_128bit); +void C2_MacroAssembler::sminmax_fp16(int opcode, XMMRegister dst, XMMRegister src1, XMMRegister src2, + KRegister ktmp, XMMRegister xtmp1, XMMRegister xtmp2) { + vminmax_fp16(opcode, dst, src1, src2, ktmp, xtmp1, xtmp2, Assembler::AVX_128bit); } -void C2_MacroAssembler::vector_max_min_fp16(int opcode, XMMRegister dst, XMMRegister src1, XMMRegister src2, - KRegister ktmp, XMMRegister xtmp1, XMMRegister xtmp2, int vlen_enc) { +void C2_MacroAssembler::sminmax_fp16_avx10_2(int opcode, XMMRegister dst, XMMRegister src1, XMMRegister src2, + KRegister ktmp) { + if (opcode == Op_MaxHF) { + // dst = max(src1, src2) + evminmaxsh(dst, ktmp, src1, src2, true, AVX10_2_MINMAX_MAX_COMPARE_SIGN); + } else { + assert(opcode == Op_MinHF, ""); + // dst = min(src1, src2) + evminmaxsh(dst, ktmp, src1, src2, true, AVX10_2_MINMAX_MIN_COMPARE_SIGN); + } +} + +void C2_MacroAssembler::vminmax_fp16(int opcode, XMMRegister dst, XMMRegister src1, XMMRegister src2, + KRegister ktmp, XMMRegister xtmp1, XMMRegister xtmp2, int vlen_enc) { if (opcode == Op_MaxVHF || opcode == Op_MaxHF) { // Move sign bits of src2 to mask register. evpmovw2m(ktmp, src2, vlen_enc); @@ -7110,3 +7137,27 @@ void C2_MacroAssembler::vector_max_min_fp16(int opcode, XMMRegister dst, XMMRegi Assembler::evmovdquw(dst, ktmp, xtmp1, true, vlen_enc); } } + +void C2_MacroAssembler::vminmax_fp16_avx10_2(int opcode, XMMRegister dst, XMMRegister src1, XMMRegister src2, + KRegister ktmp, int vlen_enc) { + if (opcode == Op_MaxVHF) { + // dst = max(src1, src2) + evminmaxph(dst, ktmp, src1, src2, true, AVX10_2_MINMAX_MAX_COMPARE_SIGN, vlen_enc); + } else { + assert(opcode == Op_MinVHF, ""); + // dst = min(src1, src2) + evminmaxph(dst, ktmp, src1, src2, true, AVX10_2_MINMAX_MIN_COMPARE_SIGN, vlen_enc); + } +} + +void C2_MacroAssembler::vminmax_fp16_avx10_2(int opcode, XMMRegister dst, XMMRegister src1, Address src2, + KRegister ktmp, int vlen_enc) { + if (opcode == Op_MaxVHF) { + // dst = max(src1, src2) + evminmaxph(dst, ktmp, src1, src2, true, AVX10_2_MINMAX_MAX_COMPARE_SIGN, vlen_enc); + } else { + assert(opcode == Op_MinVHF, ""); + // dst = min(src1, src2) + evminmaxph(dst, ktmp, src1, src2, true, AVX10_2_MINMAX_MIN_COMPARE_SIGN, vlen_enc); + } +} diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp index 6d8b0ceaebe..4e77f8a5f6f 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, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -67,8 +67,11 @@ XMMRegister tmp, XMMRegister atmp, XMMRegister btmp, int vlen_enc); - void vminmax_fp(int opc, BasicType elem_bt, XMMRegister dst, KRegister mask, - XMMRegister src1, XMMRegister src2, int vlen_enc); + void vminmax_fp_avx10_2(int opc, BasicType elem_bt, XMMRegister dst, KRegister mask, + XMMRegister src1, XMMRegister src2, int vlen_enc); + + void sminmax_fp_avx10_2(int opc, BasicType elem_bt, XMMRegister dst, KRegister mask, + XMMRegister src1, XMMRegister src2); void vpuminmaxq(int opcode, XMMRegister dst, XMMRegister src1, XMMRegister src2, XMMRegister xtmp1, XMMRegister xtmp2, int vlen_enc); @@ -576,11 +579,20 @@ void evfp16ph(int opcode, XMMRegister dst, XMMRegister src1, Address src2, int vlen_enc); - void vector_max_min_fp16(int opcode, XMMRegister dst, XMMRegister src1, XMMRegister src2, - KRegister ktmp, XMMRegister xtmp1, XMMRegister xtmp2, int vlen_enc); + void vminmax_fp16(int opcode, XMMRegister dst, XMMRegister src1, XMMRegister src2, + KRegister ktmp, XMMRegister xtmp1, XMMRegister xtmp2, int vlen_enc); + + void vminmax_fp16_avx10_2(int opcode, XMMRegister dst, XMMRegister src1, XMMRegister src2, + KRegister ktmp, int vlen_enc); + + void vminmax_fp16_avx10_2(int opcode, XMMRegister dst, XMMRegister src1, Address src2, + KRegister ktmp, int vlen_enc); + + void sminmax_fp16(int opcode, XMMRegister dst, XMMRegister src1, XMMRegister src2, + KRegister ktmp, XMMRegister xtmp1, XMMRegister xtmp2); - void scalar_max_min_fp16(int opcode, XMMRegister dst, XMMRegister src1, XMMRegister src2, - KRegister ktmp, XMMRegister xtmp1, XMMRegister xtmp2); + void sminmax_fp16_avx10_2(int opcode, XMMRegister dst, XMMRegister src1, XMMRegister src2, + KRegister ktmp); void reconstruct_frame_pointer(Register rtmp); diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.cpp b/src/hotspot/cpu/x86/macroAssembler_x86.cpp index a0f08145d55..356bf8af5c0 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp @@ -1958,6 +1958,16 @@ void MacroAssembler::movflt(XMMRegister dst, AddressLiteral src, Register rscrat } } +void MacroAssembler::movhlf(XMMRegister dst, XMMRegister src, Register rscratch) { + if (VM_Version::supports_avx10_2()) { + evmovw(dst, src); + } else { + assert(rscratch != noreg, "missing"); + evmovw(rscratch, src); + evmovw(dst, rscratch); + } +} + void MacroAssembler::mov64(Register dst, int64_t imm64) { if (is_uimm32(imm64)) { movl(dst, checked_cast(imm64)); @@ -2661,14 +2671,14 @@ void MacroAssembler::ucomisd(XMMRegister dst, AddressLiteral src, Register rscra } } -void MacroAssembler::vucomxsd(XMMRegister dst, AddressLiteral src, Register rscratch) { +void MacroAssembler::evucomxsd(XMMRegister dst, AddressLiteral src, Register rscratch) { assert(rscratch != noreg || always_reachable(src), "missing"); if (reachable(src)) { - Assembler::vucomxsd(dst, as_Address(src)); + Assembler::evucomxsd(dst, as_Address(src)); } else { lea(rscratch, src); - Assembler::vucomxsd(dst, Address(rscratch, 0)); + Assembler::evucomxsd(dst, Address(rscratch, 0)); } } @@ -2683,14 +2693,36 @@ void MacroAssembler::ucomiss(XMMRegister dst, AddressLiteral src, Register rscra } } -void MacroAssembler::vucomxss(XMMRegister dst, AddressLiteral src, Register rscratch) { +void MacroAssembler::evucomxss(XMMRegister dst, AddressLiteral src, Register rscratch) { + assert(rscratch != noreg || always_reachable(src), "missing"); + + if (reachable(src)) { + Assembler::evucomxss(dst, as_Address(src)); + } else { + lea(rscratch, src); + Assembler::evucomxss(dst, Address(rscratch, 0)); + } +} + +void MacroAssembler::evucomish(XMMRegister dst, AddressLiteral src, Register rscratch) { assert(rscratch != noreg || always_reachable(src), "missing"); if (reachable(src)) { - Assembler::vucomxss(dst, as_Address(src)); + Assembler::evucomish(dst, as_Address(src)); } else { lea(rscratch, src); - Assembler::vucomxss(dst, Address(rscratch, 0)); + Assembler::evucomish(dst, Address(rscratch, 0)); + } +} + +void MacroAssembler::evucomxsh(XMMRegister dst, AddressLiteral src, Register rscratch) { + assert(rscratch != noreg || always_reachable(src), "missing"); + + if (reachable(src)) { + Assembler::evucomxsh(dst, as_Address(src)); + } else { + lea(rscratch, src); + Assembler::evucomxsh(dst, Address(rscratch, 0)); } } @@ -9163,7 +9195,7 @@ void MacroAssembler::evpmaxs(BasicType type, XMMRegister dst, KRegister mask, XM case T_FLOAT: evminmaxps(dst, mask, nds, src, merge, AVX10_2_MINMAX_MAX_COMPARE_SIGN, vector_len); break; case T_DOUBLE: - evminmaxps(dst, mask, nds, src, merge, AVX10_2_MINMAX_MAX_COMPARE_SIGN, vector_len); break; + evminmaxpd(dst, mask, nds, src, merge, AVX10_2_MINMAX_MAX_COMPARE_SIGN, vector_len); break; default: fatal("Unexpected type argument %s", type2name(type)); break; } diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.hpp b/src/hotspot/cpu/x86/macroAssembler_x86.hpp index 3bdd1e4477a..021d2943ee8 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.hpp @@ -162,6 +162,8 @@ class MacroAssembler: public Assembler { void incrementq(AddressLiteral dst, Register rscratch = noreg); + void movhlf(XMMRegister dst, XMMRegister src, Register rscratch = noreg); + // Support optimal SSE move instructions. void movflt(XMMRegister dst, XMMRegister src) { if (dst-> encoding() == src->encoding()) return; @@ -1308,21 +1310,29 @@ class MacroAssembler: public Assembler { void subss(XMMRegister dst, Address src) { Assembler::subss(dst, src); } void subss(XMMRegister dst, AddressLiteral src, Register rscratch = noreg); + void evucomish(XMMRegister dst, XMMRegister src) { Assembler::evucomish(dst, src); } + void evucomish(XMMRegister dst, Address src) { Assembler::evucomish(dst, src); } + void evucomish(XMMRegister dst, AddressLiteral src, Register rscratch = noreg); + + void evucomxsh(XMMRegister dst, XMMRegister src) { Assembler::evucomxsh(dst, src); } + void evucomxsh(XMMRegister dst, Address src) { Assembler::evucomxsh(dst, src); } + void evucomxsh(XMMRegister dst, AddressLiteral src, Register rscratch = noreg); + void ucomiss(XMMRegister dst, XMMRegister src) { Assembler::ucomiss(dst, src); } void ucomiss(XMMRegister dst, Address src) { Assembler::ucomiss(dst, src); } void ucomiss(XMMRegister dst, AddressLiteral src, Register rscratch = noreg); - void vucomxss(XMMRegister dst, XMMRegister src) { Assembler::vucomxss(dst, src); } - void vucomxss(XMMRegister dst, Address src) { Assembler::vucomxss(dst, src); } - void vucomxss(XMMRegister dst, AddressLiteral src, Register rscratch = noreg); + void evucomxss(XMMRegister dst, XMMRegister src) { Assembler::evucomxss(dst, src); } + void evucomxss(XMMRegister dst, Address src) { Assembler::evucomxss(dst, src); } + void evucomxss(XMMRegister dst, AddressLiteral src, Register rscratch = noreg); void ucomisd(XMMRegister dst, XMMRegister src) { Assembler::ucomisd(dst, src); } void ucomisd(XMMRegister dst, Address src) { Assembler::ucomisd(dst, src); } void ucomisd(XMMRegister dst, AddressLiteral src, Register rscratch = noreg); - void vucomxsd(XMMRegister dst, XMMRegister src) { Assembler::vucomxsd(dst, src); } - void vucomxsd(XMMRegister dst, Address src) { Assembler::vucomxsd(dst, src); } - void vucomxsd(XMMRegister dst, AddressLiteral src, Register rscratch = noreg); + void evucomxsd(XMMRegister dst, XMMRegister src) { Assembler::evucomxsd(dst, src); } + void evucomxsd(XMMRegister dst, Address src) { Assembler::evucomxsd(dst, src); } + void evucomxsd(XMMRegister dst, AddressLiteral src, Register rscratch = noreg); // Bitwise Logical XOR of Packed Double-Precision Floating-Point Values void xorpd(XMMRegister dst, XMMRegister src); diff --git a/src/hotspot/cpu/x86/x86.ad b/src/hotspot/cpu/x86/x86.ad index f31d64f3d7e..d7014141234 100644 --- a/src/hotspot/cpu/x86/x86.ad +++ b/src/hotspot/cpu/x86/x86.ad @@ -1708,84 +1708,99 @@ static void emit_cmpfp3(MacroAssembler* masm, Register dst) { __ bind(done); } -// Math.min() # Math.max() -// -------------------------- -// ucomis[s/d] # -// ja -> b # a -// jp -> NaN # NaN -// jb -> a # b -// je # -// |-jz -> a | b # a & b -// | -> a # +enum FP_PREC { + fp_prec_hlf, + fp_prec_flt, + fp_prec_dbl +}; + +static inline void emit_fp_ucom(MacroAssembler* masm, enum FP_PREC pt, + XMMRegister p, XMMRegister q) { + if (pt == fp_prec_hlf) { + __ evucomish(p, q); + } else if (pt == fp_prec_flt) { + __ ucomiss(p, q); + } else { + __ ucomisd(p, q); + } +} + +static inline void movfp(MacroAssembler* masm, enum FP_PREC pt, + XMMRegister dst, XMMRegister src, Register scratch) { + if (pt == fp_prec_hlf) { + __ movhlf(dst, src, scratch); + } else if (pt == fp_prec_flt) { + __ movflt(dst, src); + } else { + __ movdbl(dst, src); + } +} + +// Math.min() # Math.max() +// ----------------------------- +// (v)ucomis[h/s/d] # +// ja -> b # a +// jp -> NaN # NaN +// jb -> a # b +// je # +// |-jz -> a | b # a & b +// | -> a # static void emit_fp_min_max(MacroAssembler* masm, XMMRegister dst, XMMRegister a, XMMRegister b, XMMRegister xmmt, Register rt, - bool min, bool single) { + bool min, enum FP_PREC pt) { Label nan, zero, below, above, done; - if (single) - __ ucomiss(a, b); - else - __ ucomisd(a, b); + emit_fp_ucom(masm, pt, a, b); - if (dst->encoding() != (min ? b : a)->encoding()) + if (dst->encoding() != (min ? b : a)->encoding()) { __ jccb(Assembler::above, above); // CF=0 & ZF=0 - else + } else { __ jccb(Assembler::above, done); + } __ jccb(Assembler::parity, nan); // PF=1 __ jccb(Assembler::below, below); // CF=1 // equal __ vpxor(xmmt, xmmt, xmmt, Assembler::AVX_128bit); - if (single) { - __ ucomiss(a, xmmt); - __ jccb(Assembler::equal, zero); + emit_fp_ucom(masm, pt, a, xmmt); - __ movflt(dst, a); - __ jmp(done); - } - else { - __ ucomisd(a, xmmt); - __ jccb(Assembler::equal, zero); + __ jccb(Assembler::equal, zero); + movfp(masm, pt, dst, a, rt); - __ movdbl(dst, a); - __ jmp(done); - } + __ jmp(done); __ bind(zero); - if (min) + if (min) { __ vpor(dst, a, b, Assembler::AVX_128bit); - else + } else { __ vpand(dst, a, b, Assembler::AVX_128bit); + } __ jmp(done); __ bind(above); - if (single) - __ movflt(dst, min ? b : a); - else - __ movdbl(dst, min ? b : a); + movfp(masm, pt, dst, min ? b : a, rt); __ jmp(done); __ bind(nan); - if (single) { + if (pt == fp_prec_hlf) { + __ movl(rt, 0x00007e00); // Float16.NaN + __ evmovw(dst, rt); + } else if (pt == fp_prec_flt) { __ movl(rt, 0x7fc00000); // Float.NaN __ movdl(dst, rt); - } - else { + } else { __ mov64(rt, 0x7ff8000000000000L); // Double.NaN __ movdq(dst, rt); } __ jmp(done); __ bind(below); - if (single) - __ movflt(dst, min ? a : b); - else - __ movdbl(dst, min ? a : b); + movfp(masm, pt, dst, min ? a : b, rt); __ bind(done); } @@ -7345,146 +7360,140 @@ instruct loadAOTRCAddress(rRegP dst, immAOTRuntimeConstantsAddress con) ins_pipe(ialu_reg_fat); %} +// min = java.lang.Math.min(float a, float b) // max = java.lang.Math.max(float a, float b) -instruct maxF_reg_avx10_2(regF dst, regF a, regF b) %{ - predicate(VM_Version::supports_avx10_2()); +instruct minmaxF_reg_avx10_2(regF dst, regF a, regF b) +%{ + predicate(VM_Version::supports_avx10_2() && !VLoopReductions::is_reduction(n)); match(Set dst (MaxF a b)); - format %{ "maxF $dst, $a, $b" %} - ins_encode %{ - __ eminmaxss($dst$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, AVX10_2_MINMAX_MAX_COMPARE_SIGN); - %} - ins_pipe( pipe_slow ); -%} + match(Set dst (MinF a b)); -// max = java.lang.Math.max(float a, float b) -instruct maxF_reg(legRegF dst, legRegF a, legRegF b, legRegF tmp, legRegF atmp, legRegF btmp) %{ - predicate(!VM_Version::supports_avx10_2() && UseAVX > 0 && !VLoopReductions::is_reduction(n)); - match(Set dst (MaxF a b)); - effect(USE a, USE b, TEMP tmp, TEMP atmp, TEMP btmp); - format %{ "maxF $dst, $a, $b \t! using $tmp, $atmp and $btmp as TEMP" %} + format %{ "minmaxF $dst, $a, $b" %} ins_encode %{ - __ vminmax_fp(Op_MaxV, T_FLOAT, $dst$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, $tmp$$XMMRegister, $atmp$$XMMRegister, $btmp$$XMMRegister, Assembler::AVX_128bit); + int opcode = this->ideal_Opcode(); + __ sminmax_fp_avx10_2(opcode, T_FLOAT, $dst$$XMMRegister, k0, $a$$XMMRegister, $b$$XMMRegister); %} ins_pipe( pipe_slow ); %} -instruct maxF_reduction_reg(legRegF dst, legRegF a, legRegF b, legRegF xtmp, rRegI rtmp, rFlagsReg cr) %{ - predicate(!VM_Version::supports_avx10_2() && UseAVX > 0 && VLoopReductions::is_reduction(n)); +instruct minmaxF_reduction_reg_avx10_2(regF dst, regF a, regF b, regF xtmp, rRegI rtmp, rFlagsReg cr) +%{ + predicate(VM_Version::supports_avx10_2() && VLoopReductions::is_reduction(n)); match(Set dst (MaxF a b)); + match(Set dst (MinF a b)); effect(USE a, USE b, TEMP xtmp, TEMP rtmp, KILL cr); - format %{ "maxF_reduction $dst, $a, $b \t!using $xtmp and $rtmp as TEMP" %} + format %{ "minmaxF_reduction $dst, $a, $b \t! using $xtmp and $rtmp as TEMP" %} ins_encode %{ + int opcode = this->ideal_Opcode(); + bool min = (opcode == Op_MinF) ? true : false; emit_fp_min_max(masm, $dst$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, $xtmp$$XMMRegister, $rtmp$$Register, - false /*min*/, true /*single*/); - %} - ins_pipe( pipe_slow ); -%} - -// max = java.lang.Math.max(double a, double b) -instruct maxD_reg_avx10_2(regD dst, regD a, regD b) %{ - predicate(VM_Version::supports_avx10_2()); - match(Set dst (MaxD a b)); - format %{ "maxD $dst, $a, $b" %} - ins_encode %{ - __ eminmaxsd($dst$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, AVX10_2_MINMAX_MAX_COMPARE_SIGN); + min, fp_prec_flt /*pt*/); %} ins_pipe( pipe_slow ); %} -// max = java.lang.Math.max(double a, double b) -instruct maxD_reg(legRegD dst, legRegD a, legRegD b, legRegD tmp, legRegD atmp, legRegD btmp) %{ +// min = java.lang.Math.min(float a, float b) +// max = java.lang.Math.max(float a, float b) +instruct minmaxF_reg(legRegF dst, legRegF a, legRegF b, legRegF tmp, legRegF atmp, legRegF btmp) +%{ predicate(!VM_Version::supports_avx10_2() && UseAVX > 0 && !VLoopReductions::is_reduction(n)); - match(Set dst (MaxD a b)); - effect(USE a, USE b, TEMP atmp, TEMP btmp, TEMP tmp); - format %{ "maxD $dst, $a, $b \t! using $tmp, $atmp and $btmp as TEMP" %} + match(Set dst (MaxF a b)); + match(Set dst (MinF a b)); + effect(USE a, USE b, TEMP tmp, TEMP atmp, TEMP btmp); + + format %{ "minmaxF $dst, $a, $b \t! using $tmp, $atmp and $btmp as TEMP" %} ins_encode %{ - __ vminmax_fp(Op_MaxV, T_DOUBLE, $dst$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, $tmp$$XMMRegister, $atmp$$XMMRegister, $btmp$$XMMRegister, Assembler::AVX_128bit); + int opcode = this->ideal_Opcode(); + int param_opcode = (opcode == Op_MinF) ? Op_MinV : Op_MaxV; + __ vminmax_fp(param_opcode, T_FLOAT, $dst$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, $tmp$$XMMRegister, + $atmp$$XMMRegister, $btmp$$XMMRegister, Assembler::AVX_128bit); %} ins_pipe( pipe_slow ); %} -instruct maxD_reduction_reg(legRegD dst, legRegD a, legRegD b, legRegD xtmp, rRegL rtmp, rFlagsReg cr) %{ +instruct minmaxF_reduction_reg(legRegF dst, legRegF a, legRegF b, legRegF xtmp, rRegI rtmp, rFlagsReg cr) +%{ predicate(!VM_Version::supports_avx10_2() && UseAVX > 0 && VLoopReductions::is_reduction(n)); - match(Set dst (MaxD a b)); + match(Set dst (MaxF a b)); + match(Set dst (MinF a b)); effect(USE a, USE b, TEMP xtmp, TEMP rtmp, KILL cr); - format %{ "maxD_reduction $dst, $a, $b \t! using $xtmp and $rtmp as TEMP" %} + format %{ "minmaxF_reduction $dst, $a, $b \t!using $xtmp and $rtmp as TEMP" %} ins_encode %{ + int opcode = this->ideal_Opcode(); + bool min = (opcode == Op_MinF) ? true : false; emit_fp_min_max(masm, $dst$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, $xtmp$$XMMRegister, $rtmp$$Register, - false /*min*/, false /*single*/); + min, fp_prec_flt /*pt*/); %} ins_pipe( pipe_slow ); %} -// max = java.lang.Math.min(float a, float b) -instruct minF_reg_avx10_2(regF dst, regF a, regF b) %{ - predicate(VM_Version::supports_avx10_2()); - match(Set dst (MinF a b)); - format %{ "minF $dst, $a, $b" %} - ins_encode %{ - __ eminmaxss($dst$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, AVX10_2_MINMAX_MIN_COMPARE_SIGN); - %} - ins_pipe( pipe_slow ); -%} +// min = java.lang.Math.min(double a, double b) +// max = java.lang.Math.max(double a, double b) +instruct minmaxD_reg_avx10_2(regD dst, regD a, regD b) +%{ + predicate(VM_Version::supports_avx10_2() && !VLoopReductions::is_reduction(n)); + match(Set dst (MaxD a b)); + match(Set dst (MinD a b)); -// min = java.lang.Math.min(float a, float b) -instruct minF_reg(legRegF dst, legRegF a, legRegF b, legRegF tmp, legRegF atmp, legRegF btmp) %{ - predicate(!VM_Version::supports_avx10_2() && UseAVX > 0 && !VLoopReductions::is_reduction(n)); - match(Set dst (MinF a b)); - effect(USE a, USE b, TEMP tmp, TEMP atmp, TEMP btmp); - format %{ "minF $dst, $a, $b \t! using $tmp, $atmp and $btmp as TEMP" %} + format %{ "minmaxD $dst, $a, $b" %} ins_encode %{ - __ vminmax_fp(Op_MinV, T_FLOAT, $dst$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, $tmp$$XMMRegister, $atmp$$XMMRegister, $btmp$$XMMRegister, Assembler::AVX_128bit); + int opcode = this->ideal_Opcode(); + __ sminmax_fp_avx10_2(opcode, T_DOUBLE, $dst$$XMMRegister, k0, $a$$XMMRegister, $b$$XMMRegister); %} ins_pipe( pipe_slow ); %} -instruct minF_reduction_reg(legRegF dst, legRegF a, legRegF b, legRegF xtmp, rRegI rtmp, rFlagsReg cr) %{ - predicate(!VM_Version::supports_avx10_2() && UseAVX > 0 && VLoopReductions::is_reduction(n)); - match(Set dst (MinF a b)); +instruct minmaxD_reduction_reg_avx10_2(regD dst, regD a, regD b, regD xtmp, rRegI rtmp, rFlagsReg cr) +%{ + predicate(VM_Version::supports_avx10_2() && VLoopReductions::is_reduction(n)); + match(Set dst (MaxD a b)); + match(Set dst (MinD a b)); effect(USE a, USE b, TEMP xtmp, TEMP rtmp, KILL cr); - format %{ "minF_reduction $dst, $a, $b \t! using $xtmp and $rtmp as TEMP" %} + format %{ "minmaxD_reduction $dst, $a, $b \t! using $xtmp and $rtmp as TEMP" %} ins_encode %{ + int opcode = this->ideal_Opcode(); + bool min = (opcode == Op_MinD) ? true : false; emit_fp_min_max(masm, $dst$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, $xtmp$$XMMRegister, $rtmp$$Register, - true /*min*/, true /*single*/); - %} - ins_pipe( pipe_slow ); -%} - -// max = java.lang.Math.min(double a, double b) -instruct minD_reg_avx10_2(regD dst, regD a, regD b) %{ - predicate(VM_Version::supports_avx10_2()); - match(Set dst (MinD a b)); - format %{ "minD $dst, $a, $b" %} - ins_encode %{ - __ eminmaxsd($dst$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, AVX10_2_MINMAX_MIN_COMPARE_SIGN); + min, fp_prec_dbl /*pt*/); %} ins_pipe( pipe_slow ); %} // min = java.lang.Math.min(double a, double b) -instruct minD_reg(legRegD dst, legRegD a, legRegD b, legRegD tmp, legRegD atmp, legRegD btmp) %{ +// max = java.lang.Math.max(double a, double b) +instruct minmaxD_reg(legRegD dst, legRegD a, legRegD b, legRegD tmp, legRegD atmp, legRegD btmp) +%{ predicate(!VM_Version::supports_avx10_2() && UseAVX > 0 && !VLoopReductions::is_reduction(n)); + match(Set dst (MaxD a b)); match(Set dst (MinD a b)); - effect(USE a, USE b, TEMP tmp, TEMP atmp, TEMP btmp); - format %{ "minD $dst, $a, $b \t! using $tmp, $atmp and $btmp as TEMP" %} + effect(USE a, USE b, TEMP atmp, TEMP btmp, TEMP tmp); + + format %{ "minmaxD $dst, $a, $b \t! using $tmp, $atmp and $btmp as TEMP" %} ins_encode %{ - __ vminmax_fp(Op_MinV, T_DOUBLE, $dst$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, $tmp$$XMMRegister, $atmp$$XMMRegister, $btmp$$XMMRegister, Assembler::AVX_128bit); + int opcode = this->ideal_Opcode(); + int param_opcode = (opcode == Op_MinD) ? Op_MinV : Op_MaxV; + __ vminmax_fp(param_opcode, T_DOUBLE, $dst$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, $tmp$$XMMRegister, + $atmp$$XMMRegister, $btmp$$XMMRegister, Assembler::AVX_128bit); %} ins_pipe( pipe_slow ); %} -instruct minD_reduction_reg(legRegD dst, legRegD a, legRegD b, legRegD xtmp, rRegL rtmp, rFlagsReg cr) %{ +instruct minmaxD_reduction_reg(legRegD dst, legRegD a, legRegD b, legRegD xtmp, rRegL rtmp, rFlagsReg cr) +%{ predicate(!VM_Version::supports_avx10_2() && UseAVX > 0 && VLoopReductions::is_reduction(n)); + match(Set dst (MaxD a b)); match(Set dst (MinD a b)); effect(USE a, USE b, TEMP xtmp, TEMP rtmp, KILL cr); - format %{ "maxD_reduction $dst, $a, $b \t! using $xtmp and $rtmp as TEMP" %} + format %{ "minmaxD_reduction $dst, $a, $b \t! using $xtmp and $rtmp as TEMP" %} ins_encode %{ + int opcode = this->ideal_Opcode(); + bool min = (opcode == Op_MinD) ? true : false; emit_fp_min_max(masm, $dst$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, $xtmp$$XMMRegister, $rtmp$$Register, - true /*min*/, false /*single*/); + min, fp_prec_dbl /*pt*/); %} ins_pipe( pipe_slow ); %} @@ -14394,9 +14403,9 @@ instruct cmpF_cc_regCFE(rFlagsRegUCFE cr, regF src1, regF src2) %{ match(Set cr (CmpF src1 src2)); ins_cost(100); - format %{ "vucomxss $src1, $src2" %} + format %{ "evucomxss $src1, $src2" %} ins_encode %{ - __ vucomxss($src1$$XMMRegister, $src2$$XMMRegister); + __ evucomxss($src1$$XMMRegister, $src2$$XMMRegister); %} ins_pipe(pipe_slow); %} @@ -14416,9 +14425,9 @@ instruct cmpF_cc_memCFE(rFlagsRegUCFE cr, regF src1, memory src2) %{ match(Set cr (CmpF src1 (LoadF src2))); ins_cost(100); - format %{ "vucomxss $src1, $src2" %} + format %{ "evucomxss $src1, $src2" %} ins_encode %{ - __ vucomxss($src1$$XMMRegister, $src2$$Address); + __ evucomxss($src1$$XMMRegister, $src2$$Address); %} ins_pipe(pipe_slow); %} @@ -14438,9 +14447,9 @@ instruct cmpF_cc_immCFE(rFlagsRegUCFE cr, regF src, immF con) %{ match(Set cr (CmpF src con)); ins_cost(100); - format %{ "vucomxss $src, [$constantaddress]\t# load from constant table: float=$con" %} + format %{ "evucomxss $src, [$constantaddress]\t# load from constant table: float=$con" %} ins_encode %{ - __ vucomxss($src$$XMMRegister, $constantaddress($con)); + __ evucomxss($src$$XMMRegister, $constantaddress($con)); %} ins_pipe(pipe_slow); %} @@ -14479,9 +14488,9 @@ instruct cmpD_cc_regCFE(rFlagsRegUCFE cr, regD src1, regD src2) %{ match(Set cr (CmpD src1 src2)); ins_cost(100); - format %{ "vucomxsd $src1, $src2 test" %} + format %{ "evucomxsd $src1, $src2 test" %} ins_encode %{ - __ vucomxsd($src1$$XMMRegister, $src2$$XMMRegister); + __ evucomxsd($src1$$XMMRegister, $src2$$XMMRegister); %} ins_pipe(pipe_slow); %} @@ -14501,9 +14510,9 @@ instruct cmpD_cc_memCFE(rFlagsRegUCFE cr, regD src1, memory src2) %{ match(Set cr (CmpD src1 (LoadD src2))); ins_cost(100); - format %{ "vucomxsd $src1, $src2" %} + format %{ "evucomxsd $src1, $src2" %} ins_encode %{ - __ vucomxsd($src1$$XMMRegister, $src2$$Address); + __ evucomxsd($src1$$XMMRegister, $src2$$Address); %} ins_pipe(pipe_slow); %} @@ -14522,9 +14531,9 @@ instruct cmpD_cc_immCFE(rFlagsRegUCFE cr, regD src, immD con) %{ match(Set cr (CmpD src con)); ins_cost(100); - format %{ "vucomxsd $src, [$constantaddress]\t# load from constant table: double=$con" %} + format %{ "evucomxsd $src, [$constantaddress]\t# load from constant table: double=$con" %} ins_encode %{ - __ vucomxsd($src$$XMMRegister, $constantaddress($con)); + __ evucomxsd($src$$XMMRegister, $constantaddress($con)); %} ins_pipe(pipe_slow); %} @@ -18832,7 +18841,7 @@ instruct ReplHF_reg(vec dst, regF src, rRegI rtmp) %{ format %{ "replicateHF $dst, $src \t! using $rtmp as TEMP" %} ins_encode %{ int vlen_enc = vector_length_encoding(this); - __ vmovw($rtmp$$Register, $src$$XMMRegister); + __ evmovw($rtmp$$Register, $src$$XMMRegister); __ evpbroadcastw($dst$$XMMRegister, $rtmp$$Register, vlen_enc); %} ins_pipe( pipe_slow ); @@ -20947,7 +20956,7 @@ instruct minmaxFP_reg_avx10_2(vec dst, vec a, vec b) %{ int vlen_enc = vector_length_encoding(this); int opcode = this->ideal_Opcode(); BasicType elem_bt = Matcher::vector_element_basic_type(this); - __ vminmax_fp(opcode, elem_bt, $dst$$XMMRegister, k0, $a$$XMMRegister, $b$$XMMRegister, vlen_enc); + __ vminmax_fp_avx10_2(opcode, elem_bt, $dst$$XMMRegister, k0, $a$$XMMRegister, $b$$XMMRegister, vlen_enc); %} ins_pipe( pipe_slow ); %} @@ -25291,9 +25300,9 @@ instruct vector_selectfrom_twovectors_reg_evex(vec index, vec src1, vec src2) instruct reinterpretS2HF(regF dst, rRegI src) %{ match(Set dst (ReinterpretS2HF src)); - format %{ "vmovw $dst, $src" %} + format %{ "evmovw $dst, $src" %} ins_encode %{ - __ vmovw($dst$$XMMRegister, $src$$Register); + __ evmovw($dst$$XMMRegister, $src$$Register); %} ins_pipe(pipe_slow); %} @@ -25301,9 +25310,9 @@ instruct reinterpretS2HF(regF dst, rRegI src) instruct reinterpretHF2S(rRegI dst, regF src) %{ match(Set dst (ReinterpretHF2S src)); - format %{ "vmovw $dst, $src" %} + format %{ "evmovw $dst, $src" %} ins_encode %{ - __ vmovw($dst$$Register, $src$$XMMRegister); + __ evmovw($dst$$Register, $src$$XMMRegister); %} ins_pipe(pipe_slow); %} @@ -25357,10 +25366,11 @@ instruct scalar_minmax_HF_reg_avx10_2(regF dst, regF src1, regF src2) predicate(VM_Version::supports_avx10_2()); match(Set dst (MaxHF src1 src2)); match(Set dst (MinHF src1 src2)); + format %{ "scalar_min_max_fp16 $dst, $src1, $src2" %} ins_encode %{ - int function = this->ideal_Opcode() == Op_MinHF ? AVX10_2_MINMAX_MIN_COMPARE_SIGN : AVX10_2_MINMAX_MAX_COMPARE_SIGN; - __ eminmaxsh($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, function); + int opcode = this->ideal_Opcode(); + __ sminmax_fp16_avx10_2(opcode, $dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, k0); %} ins_pipe( pipe_slow ); %} @@ -25371,11 +25381,12 @@ instruct scalar_minmax_HF_reg(regF dst, regF src1, regF src2, kReg ktmp, regF xt match(Set dst (MaxHF src1 src2)); match(Set dst (MinHF src1 src2)); effect(TEMP_DEF dst, TEMP ktmp, TEMP xtmp1, TEMP xtmp2); + format %{ "scalar_min_max_fp16 $dst, $src1, $src2\t using $ktmp, $xtmp1 and $xtmp2 as TEMP" %} ins_encode %{ int opcode = this->ideal_Opcode(); - __ scalar_max_min_fp16(opcode, $dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, $ktmp$$KRegister, - $xtmp1$$XMMRegister, $xtmp2$$XMMRegister); + __ sminmax_fp16(opcode, $dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, $ktmp$$KRegister, + $xtmp1$$XMMRegister, $xtmp2$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -25475,8 +25486,9 @@ instruct vector_minmax_HF_mem_avx10_2(vec dst, vec src1, memory src2) format %{ "vector_min_max_fp16_mem $dst, $src1, $src2" %} ins_encode %{ int vlen_enc = vector_length_encoding(this); - int function = this->ideal_Opcode() == Op_MinVHF ? AVX10_2_MINMAX_MIN_COMPARE_SIGN : AVX10_2_MINMAX_MAX_COMPARE_SIGN; - __ evminmaxph($dst$$XMMRegister, k0, $src1$$XMMRegister, $src2$$Address, true, function, vlen_enc); + int opcode = this->ideal_Opcode(); + __ vminmax_fp16_avx10_2(opcode, $dst$$XMMRegister, $src1$$XMMRegister, $src2$$Address, + k0, vlen_enc); %} ins_pipe( pipe_slow ); %} @@ -25489,8 +25501,9 @@ instruct vector_minmax_HF_reg_avx10_2(vec dst, vec src1, vec src2) format %{ "vector_min_max_fp16 $dst, $src1, $src2" %} ins_encode %{ int vlen_enc = vector_length_encoding(this); - int function = this->ideal_Opcode() == Op_MinVHF ? AVX10_2_MINMAX_MIN_COMPARE_SIGN : AVX10_2_MINMAX_MAX_COMPARE_SIGN; - __ evminmaxph($dst$$XMMRegister, k0, $src1$$XMMRegister, $src2$$XMMRegister, true, function, vlen_enc); + int opcode = this->ideal_Opcode(); + __ vminmax_fp16_avx10_2(opcode, $dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, + k0, vlen_enc); %} ins_pipe( pipe_slow ); %} @@ -25505,8 +25518,8 @@ instruct vector_minmax_HF_reg(vec dst, vec src1, vec src2, kReg ktmp, vec xtmp1, ins_encode %{ int vlen_enc = vector_length_encoding(this); int opcode = this->ideal_Opcode(); - __ vector_max_min_fp16(opcode, $dst$$XMMRegister, $src2$$XMMRegister, $src1$$XMMRegister, $ktmp$$KRegister, - $xtmp1$$XMMRegister, $xtmp2$$XMMRegister, vlen_enc); + __ vminmax_fp16(opcode, $dst$$XMMRegister, $src2$$XMMRegister, $src1$$XMMRegister, $ktmp$$KRegister, + $xtmp1$$XMMRegister, $xtmp2$$XMMRegister, vlen_enc); %} ins_pipe( pipe_slow ); %} diff --git a/test/hotspot/jtreg/compiler/intrinsics/math/TestFpMinMaxReductions.java b/test/hotspot/jtreg/compiler/intrinsics/math/TestFpMinMaxReductions.java index ff0277b33f7..5f516890dbe 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/math/TestFpMinMaxReductions.java +++ b/test/hotspot/jtreg/compiler/intrinsics/math/TestFpMinMaxReductions.java @@ -55,21 +55,21 @@ public static void main(String[] args) throws Exception { } @Test - @IR(counts = {IRNode.MIN_F_REG, "1"}, - failOn = {IRNode.MIN_F_REDUCTION_REG}) + @IR(counts = {IRNode.MINMAX_F_REG, "1"}, + failOn = {IRNode.MINMAX_F_REDUCTION_REG}) private static float testFloatMin() { return Math.min(floatInput1, floatInput2); } @Test - @IR(counts = {IRNode.MAX_F_REG, "1"}, - failOn = {IRNode.MAX_F_REDUCTION_REG}) + @IR(counts = {IRNode.MINMAX_F_REG, "1"}, + failOn = {IRNode.MINMAX_F_REDUCTION_REG}) private static float testFloatMax() { return Math.max(floatInput1, floatInput2); } @Test - @IR(counts = {IRNode.MIN_F_REDUCTION_REG, ">= 1"}) + @IR(counts = {IRNode.MINMAX_F_REDUCTION_REG, ">= 1"}) private static float testFloatMinReduction() { float fmin = Float.POSITIVE_INFINITY; for (int i = 0; i < floatArray.length; i++) { @@ -79,7 +79,7 @@ private static float testFloatMinReduction() { } @Test - @IR(counts = {IRNode.MIN_F_REDUCTION_REG, ">= 1"}) + @IR(counts = {IRNode.MINMAX_F_REDUCTION_REG, ">= 1"}) private static float testFloatMinReductionPartiallyUnrolled() { float fmin = Float.POSITIVE_INFINITY; for (int i = 0; i < floatArray.length / 2; i++) { @@ -90,7 +90,7 @@ private static float testFloatMinReductionPartiallyUnrolled() { } @Test - @IR(counts = {IRNode.MIN_F_REDUCTION_REG, ">= 1"}) + @IR(counts = {IRNode.MINMAX_F_REDUCTION_REG, ">= 1"}) private static float testFloatMinReductionNonCounted() { float fmin = Float.POSITIVE_INFINITY; for (int i = 0; i < floatArray.length; i += stride) { @@ -100,7 +100,7 @@ private static float testFloatMinReductionNonCounted() { } @Test - @IR(counts = {IRNode.MIN_F_REDUCTION_REG, ">= 1"}) + @IR(counts = {IRNode.MINMAX_F_REDUCTION_REG, ">= 1"}) private static float testFloatMinReductionGlobalAccumulator() { acc = Float.POSITIVE_INFINITY; for (int i = 0; i < floatArray.length; i++) { @@ -110,7 +110,7 @@ private static float testFloatMinReductionGlobalAccumulator() { } @Test - @IR(counts = {IRNode.MIN_F_REDUCTION_REG, ">= 1"}) + @IR(counts = {IRNode.MINMAX_F_REDUCTION_REG, ">= 1"}) private static float testFloatMinReductionInOuterLoop() { float fmin = Float.POSITIVE_INFINITY; int count = 0; @@ -124,7 +124,7 @@ private static float testFloatMinReductionInOuterLoop() { } @Test - @IR(counts = {IRNode.MAX_F_REDUCTION_REG, ">= 1"}) + @IR(counts = {IRNode.MINMAX_F_REDUCTION_REG, ">= 1"}) private static float testFloatMaxReduction() { float fmax = Float.NEGATIVE_INFINITY; for (int i = 0; i < floatArray.length; i++) { @@ -134,21 +134,21 @@ private static float testFloatMaxReduction() { } @Test - @IR(counts = {IRNode.MIN_D_REG, "1"}, - failOn = {IRNode.MIN_D_REDUCTION_REG}) + @IR(counts = {IRNode.MINMAX_D_REG, "1"}, + failOn = {IRNode.MINMAX_D_REDUCTION_REG}) private static double testDoubleMin() { return Math.min(doubleInput1, doubleInput2); } @Test - @IR(counts = {IRNode.MAX_D_REG, "1"}, - failOn = {IRNode.MAX_D_REDUCTION_REG}) + @IR(counts = {IRNode.MINMAX_D_REG, "1"}, + failOn = {IRNode.MINMAX_D_REDUCTION_REG}) private static double testDoubleMax() { return Math.max(doubleInput1, doubleInput2); } @Test - @IR(counts = {IRNode.MIN_D_REDUCTION_REG, ">= 1"}) + @IR(counts = {IRNode.MINMAX_D_REDUCTION_REG, ">= 1"}) private static double testDoubleMinReduction() { double fmin = Double.POSITIVE_INFINITY; for (int i = 0; i < doubleArray.length; i++) { @@ -158,7 +158,7 @@ private static double testDoubleMinReduction() { } @Test - @IR(counts = {IRNode.MAX_D_REDUCTION_REG, ">= 1"}) + @IR(counts = {IRNode.MINMAX_D_REDUCTION_REG, ">= 1"}) private static double testDoubleMaxReduction() { double fmax = Double.NEGATIVE_INFINITY; for (int i = 0; i < doubleArray.length; i++) { diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java index 8885d1283df..0753a0b04bc 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java @@ -1203,31 +1203,11 @@ public class IRNode { beforeMatchingNameRegex(MAX_D, "MaxD"); } - public static final String MAX_D_REDUCTION_REG = PREFIX + "MAX_D_REDUCTION_REG" + POSTFIX; - static { - machOnlyNameRegex(MAX_D_REDUCTION_REG, "maxD_reduction_reg"); - } - - public static final String MAX_D_REG = PREFIX + "MAX_D_REG" + POSTFIX; - static { - machOnlyNameRegex(MAX_D_REG, "maxD_reg"); - } - public static final String MAX_F = PREFIX + "MAX_F" + POSTFIX; static { beforeMatchingNameRegex(MAX_F, "MaxF"); } - public static final String MAX_F_REDUCTION_REG = PREFIX + "MAX_F_REDUCTION_REG" + POSTFIX; - static { - machOnlyNameRegex(MAX_F_REDUCTION_REG, "maxF_reduction_reg"); - } - - public static final String MAX_F_REG = PREFIX + "MAX_F_REG" + POSTFIX; - static { - machOnlyNameRegex(MAX_F_REG, "maxF_reg"); - } - public static final String MAX_I = PREFIX + "MAX_I" + POSTFIX; static { beforeMatchingNameRegex(MAX_I, "MaxI"); @@ -1309,14 +1289,14 @@ public class IRNode { beforeMatchingNameRegex(MIN_D, "MinD"); } - public static final String MIN_D_REDUCTION_REG = PREFIX + "MIN_D_REDUCTION_REG" + POSTFIX; + public static final String MINMAX_D_REDUCTION_REG = PREFIX + "MINMAX_D_REDUCTION_REG" + POSTFIX; static { - machOnlyNameRegex(MIN_D_REDUCTION_REG, "minD_reduction_reg"); + machOnlyNameRegex(MINMAX_D_REDUCTION_REG, "minmaxD_reduction_reg"); } - public static final String MIN_D_REG = PREFIX + "MIN_D_REG" + POSTFIX; + public static final String MINMAX_D_REG = PREFIX + "MINMAX_D_REG" + POSTFIX; static { - machOnlyNameRegex(MIN_D_REG, "minD_reg"); + machOnlyNameRegex(MINMAX_D_REG, "minmaxD_reg"); } public static final String MIN_F = PREFIX + "MIN_F" + POSTFIX; @@ -1324,14 +1304,14 @@ public class IRNode { beforeMatchingNameRegex(MIN_F, "MinF"); } - public static final String MIN_F_REDUCTION_REG = PREFIX + "MIN_F_REDUCTION_REG" + POSTFIX; + public static final String MINMAX_F_REDUCTION_REG = PREFIX + "MINMAX_F_REDUCTION_REG" + POSTFIX; static { - machOnlyNameRegex(MIN_F_REDUCTION_REG, "minF_reduction_reg"); + machOnlyNameRegex(MINMAX_F_REDUCTION_REG, "minmaxF_reduction_reg"); } - public static final String MIN_F_REG = PREFIX + "MIN_F_REG" + POSTFIX; + public static final String MINMAX_F_REG = PREFIX + "MINMAX_F_REG" + POSTFIX; static { - machOnlyNameRegex(MIN_F_REG, "minF_reg"); + machOnlyNameRegex(MINMAX_F_REG, "minmaxF_reg"); } public static final String MIN_I = PREFIX + "MIN_I" + POSTFIX; diff --git a/test/micro/org/openjdk/bench/jdk/incubator/vector/Float16OperationsBenchmark.java b/test/micro/org/openjdk/bench/jdk/incubator/vector/Float16OperationsBenchmark.java index cbfe9958924..92c0b58005f 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/vector/Float16OperationsBenchmark.java +++ b/test/micro/org/openjdk/bench/jdk/incubator/vector/Float16OperationsBenchmark.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ import org.openjdk.jmh.annotations.*; import static jdk.incubator.vector.Float16.*; import static java.lang.Float.*; +import java.util.Random; @OutputTimeUnit(TimeUnit.MILLISECONDS) @State(Scope.Thread) @@ -45,11 +46,20 @@ public class Float16OperationsBenchmark { short [] vector5; boolean [] vectorPredicate; + private int c0, c1, c2, s1, s2; + + Random r; + static final short f16_one = Float.floatToFloat16(1.0f); static final short f16_two = Float.floatToFloat16(2.0f); @Setup(Level.Trial) public void BmSetup() { + r = new Random(); + + c1 = s1 = step(); + c2 = vectorDim - (s2 = step()); + rexp = new int[vectorDim]; vectorRes = new short[vectorDim]; vector1 = new short[vectorDim]; @@ -84,6 +94,16 @@ public void BmSetup() { ); } + private int step() { + return (r.nextInt() & 0xf) + 1; + } + + private void inc() { + c1 = c1 + s1 < vectorDim ? c1 + s1 : (s1 = step()); + c2 = c2 - s2 > 0 ? c2 - s2 : vectorDim - (s2 = step()); + c0 = Math.abs(c2 - c1); + } + @Benchmark public void addBenchmark() { for (int i = 0; i < vectorDim; i++) { @@ -200,6 +220,14 @@ public void maxBenchmark() { } } + @Benchmark + public void maxScalarBenchmark() { + for (int i = 0; i < vectorDim; i++) { + inc(); // Ensures no auto-vectorization + vectorRes[c0] = float16ToRawShortBits(max(shortBitsToFloat16(vector1[c1]), shortBitsToFloat16(vector2[c2]))); + } + } + @Benchmark public void minBenchmark() { for (int i = 0; i < vectorDim; i++) { @@ -207,6 +235,14 @@ public void minBenchmark() { } } + @Benchmark + public void minScalarBenchmark() { + for (int i = 0; i < vectorDim; i++) { + inc(); // Ensures no auto-vectorization + vectorRes[c0] = float16ToRawShortBits(min(shortBitsToFloat16(vector1[c1]), shortBitsToFloat16(vector2[c2]))); + } + } + @Benchmark public void sqrtBenchmark() { for (int i = 0; i < vectorDim; i++) { diff --git a/test/micro/org/openjdk/bench/vm/compiler/FpMinMaxIntrinsics.java b/test/micro/org/openjdk/bench/vm/compiler/FpMinMaxIntrinsics.java index 27ae2214157..62c33f5fafe 100644 --- a/test/micro/org/openjdk/bench/vm/compiler/FpMinMaxIntrinsics.java +++ b/test/micro/org/openjdk/bench/vm/compiler/FpMinMaxIntrinsics.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,14 +45,15 @@ public class FpMinMaxIntrinsics { private Random r = new Random(); private static int stride = 1; - private static float acc; + private static float f_acc; + private static double d_acc; @Setup public void init() { c1 = s1 = step(); c2 = COUNT - (s2 = step()); - for (int i=0; i Date: Fri, 27 Mar 2026 07:13:56 +0000 Subject: [PATCH 025/116] 8380872: Remove lingering comments about the removed stack locking Reviewed-by: aboldtch, dholmes --- src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp | 2 +- src/hotspot/share/oops/markWord.hpp | 1 - src/hotspot/share/runtime/objectMonitor.hpp | 6 ++---- src/hotspot/share/runtime/synchronizer.cpp | 13 +++++-------- src/hotspot/share/runtime/vmOperations.cpp | 3 --- 5 files changed, 8 insertions(+), 17 deletions(-) diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp index c1df726b5ba..23b9a77844d 100644 --- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp @@ -152,7 +152,7 @@ inline Assembler::AvxVectorLen C2_MacroAssembler::vector_length_encoding(int vle // Because the transitions from emitted code to the runtime // monitorenter/exit helper stubs are so slow it's critical that -// we inline both the stack-locking fast path and the inflated fast path. +// we inline both the lock-stack fast path and the inflated fast path. // // See also: cmpFastLock and cmpFastUnlock. // diff --git a/src/hotspot/share/oops/markWord.hpp b/src/hotspot/share/oops/markWord.hpp index c54a9f1bf5d..4583e6bd3a1 100644 --- a/src/hotspot/share/oops/markWord.hpp +++ b/src/hotspot/share/oops/markWord.hpp @@ -54,7 +54,6 @@ // // - the two lock bits are used to describe three states: locked/unlocked and monitor. // -// [ptr | 00] locked ptr points to real header on stack (stack-locking in use) // [header | 00] locked locked regular object header (fast-locking in use) // [header | 01] unlocked regular object header // [ptr | 10] monitor inflated lock (header is swapped out, UseObjectMonitorTable == false) diff --git a/src/hotspot/share/runtime/objectMonitor.hpp b/src/hotspot/share/runtime/objectMonitor.hpp index 842aa1b374e..3ab7b8ea519 100644 --- a/src/hotspot/share/runtime/objectMonitor.hpp +++ b/src/hotspot/share/runtime/objectMonitor.hpp @@ -89,10 +89,8 @@ class ObjectWaiter : public CHeapObj { } }; -// The ObjectMonitor class implements the heavyweight version of a -// JavaMonitor. The lightweight BasicLock/stack lock version has been -// inflated into an ObjectMonitor. This inflation is typically due to -// contention or use of Object.wait(). +// The ObjectMonitor class implements the heavyweight version of a JavaMonitor. +// This inflation is typically due to contention or use of Object.wait(). // // WARNING: This is a very sensitive and fragile class. DO NOT make any // changes unless you are fully aware of the underlying semantics. diff --git a/src/hotspot/share/runtime/synchronizer.cpp b/src/hotspot/share/runtime/synchronizer.cpp index e3293f94eeb..fa178dcb5a1 100644 --- a/src/hotspot/share/runtime/synchronizer.cpp +++ b/src/hotspot/share/runtime/synchronizer.cpp @@ -830,8 +830,7 @@ void ObjectSynchronizer::owned_monitors_iterate_filtered(MonitorClosure* closure }); } -// Iterate ObjectMonitors where the owner == thread; this does NOT include -// ObjectMonitors where owner is set to a stack-lock address in thread. +// Iterate ObjectMonitors where the owner == thread. void ObjectSynchronizer::owned_monitors_iterate(MonitorClosure* closure, JavaThread* thread) { int64_t key = ObjectMonitor::owner_id_from(thread); auto thread_filter = [&](ObjectMonitor* monitor) { return monitor->owner() == key; }; @@ -1964,12 +1963,10 @@ ObjectMonitor* ObjectSynchronizer::inflate_into_object_header(oop object, Object const markWord mark = object->mark_acquire(); // The mark can be in one of the following states: - // * inflated - Just return if using stack-locking. - // If using fast-locking and the ObjectMonitor owner - // is anonymous and the locking_thread owns the - // object lock, then we make the locking_thread - // the ObjectMonitor owner and remove the lock from - // the locking_thread's lock stack. + // * inflated - If the ObjectMonitor owner is anonymous and the + // locking_thread owns the object lock, then we make the + // locking_thread the ObjectMonitor owner and remove the + // lock from the locking_thread's lock stack. // * fast-locked - Coerce it to inflated from fast-locked. // * unlocked - Aggressively inflate the object. diff --git a/src/hotspot/share/runtime/vmOperations.cpp b/src/hotspot/share/runtime/vmOperations.cpp index ef480f04c57..c4a77ce3275 100644 --- a/src/hotspot/share/runtime/vmOperations.cpp +++ b/src/hotspot/share/runtime/vmOperations.cpp @@ -276,9 +276,6 @@ void VM_ThreadDump::doit_epilogue() { } // Hash table of int64_t to a list of ObjectMonitor* owned by the JavaThread. -// The JavaThread's owner key is either a JavaThread* or a stack lock -// address in the JavaThread so we use "int64_t". -// class ObjectMonitorsDump : public MonitorClosure, public ObjectMonitorsView { private: static unsigned int ptr_hash(int64_t const& s1) { From cee1e040b3729309e0f9515c4852670226e5ca88 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Fri, 27 Mar 2026 07:56:55 +0000 Subject: [PATCH 026/116] 8380541: G1: Add g1CollectorState.inline.hpp file Reviewed-by: ayang, stefank --- src/hotspot/share/gc/g1/g1CollectedHeap.cpp | 2 +- .../share/gc/g1/g1CollectedHeap.inline.hpp | 1 - src/hotspot/share/gc/g1/g1CollectionSet.cpp | 2 +- src/hotspot/share/gc/g1/g1CollectorState.cpp | 36 ++--- src/hotspot/share/gc/g1/g1CollectorState.hpp | 80 ++++------- .../share/gc/g1/g1CollectorState.inline.hpp | 128 ++++++++++++++++++ src/hotspot/share/gc/g1/g1ConcurrentMark.cpp | 2 +- .../share/gc/g1/g1FullGCCompactTask.cpp | 2 +- src/hotspot/share/gc/g1/g1HeapVerifier.cpp | 1 + src/hotspot/share/gc/g1/g1PeriodicGCTask.cpp | 1 + src/hotspot/share/gc/g1/g1Policy.cpp | 12 ++ src/hotspot/share/gc/g1/g1Policy.hpp | 11 +- src/hotspot/share/gc/g1/g1RemSet.cpp | 1 + src/hotspot/share/gc/g1/g1RootClosures.cpp | 1 + src/hotspot/share/gc/g1/g1RootProcessor.cpp | 3 +- src/hotspot/share/gc/g1/g1Trace.cpp | 1 + src/hotspot/share/gc/g1/g1VMOperations.cpp | 1 + src/hotspot/share/gc/g1/g1YoungCollector.cpp | 2 +- .../g1/g1YoungGCAllocationFailureInjector.cpp | 1 + .../gc/g1/g1YoungGCPostEvacuateTasks.cpp | 2 +- src/hotspot/share/prims/whitebox.cpp | 1 + 21 files changed, 193 insertions(+), 98 deletions(-) create mode 100644 src/hotspot/share/gc/g1/g1CollectorState.inline.hpp diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index be9ecf19123..e6dd91df84b 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -34,7 +34,7 @@ #include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1CollectionSet.hpp" #include "gc/g1/g1CollectionSetCandidates.hpp" -#include "gc/g1/g1CollectorState.hpp" +#include "gc/g1/g1CollectorState.inline.hpp" #include "gc/g1/g1ConcurrentMarkThread.inline.hpp" #include "gc/g1/g1ConcurrentRefine.hpp" #include "gc/g1/g1ConcurrentRefineThread.hpp" diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.inline.hpp b/src/hotspot/share/gc/g1/g1CollectedHeap.inline.hpp index 90e87607b87..bad9ac18eec 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.inline.hpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.inline.hpp @@ -28,7 +28,6 @@ #include "gc/g1/g1CollectedHeap.hpp" #include "gc/g1/g1BarrierSet.hpp" -#include "gc/g1/g1CollectorState.hpp" #include "gc/g1/g1ConcurrentMark.inline.hpp" #include "gc/g1/g1EvacFailureRegions.hpp" #include "gc/g1/g1EvacStats.inline.hpp" diff --git a/src/hotspot/share/gc/g1/g1CollectionSet.cpp b/src/hotspot/share/gc/g1/g1CollectionSet.cpp index 978925d88cb..b3bcf6094ab 100644 --- a/src/hotspot/share/gc/g1/g1CollectionSet.cpp +++ b/src/hotspot/share/gc/g1/g1CollectionSet.cpp @@ -26,7 +26,7 @@ #include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1CollectionSet.inline.hpp" #include "gc/g1/g1CollectionSetCandidates.inline.hpp" -#include "gc/g1/g1CollectorState.hpp" +#include "gc/g1/g1CollectorState.inline.hpp" #include "gc/g1/g1HeapRegion.inline.hpp" #include "gc/g1/g1HeapRegionRemSet.inline.hpp" #include "gc/g1/g1HeapRegionSet.hpp" diff --git a/src/hotspot/share/gc/g1/g1CollectorState.cpp b/src/hotspot/share/gc/g1/g1CollectorState.cpp index 2b550f36904..76de9c65cc8 100644 --- a/src/hotspot/share/gc/g1/g1CollectorState.cpp +++ b/src/hotspot/share/gc/g1/g1CollectorState.cpp @@ -22,42 +22,32 @@ * */ -#include "gc/g1/g1CollectedHeap.inline.hpp" -#include "gc/g1/g1CollectorState.hpp" -#include "gc/g1/g1ConcurrentMarkThread.inline.hpp" +#include "gc/g1/g1CollectorState.inline.hpp" #include "runtime/safepoint.hpp" +#include "utilities/debug.hpp" G1CollectorState::Pause G1CollectorState::gc_pause_type(bool concurrent_operation_is_full_mark) const { assert(SafepointSynchronize::is_at_safepoint(), "must be"); switch (_phase) { case Phase::YoungNormal: return Pause::Normal; - case Phase::YoungPrepareMixed: return Pause::PrepareMixed; case Phase::YoungConcurrentStart: return concurrent_operation_is_full_mark ? Pause::ConcurrentStartFull : Pause::ConcurrentStartUndo; + case Phase::YoungPrepareMixed: return Pause::PrepareMixed; case Phase::Mixed: return Pause::Mixed; case Phase::FullGC: return Pause::Full; default: ShouldNotReachHere(); } } -bool G1CollectorState::is_in_concurrent_cycle() const { - G1ConcurrentMark* cm = G1CollectedHeap::heap()->concurrent_mark(); - return cm->is_in_concurrent_cycle(); +const char* G1CollectorState::to_string(Pause type) { + static const char* pause_strings[] = { "Normal", + "Concurrent Start", // Do not distinguish between the different + "Concurrent Start", // Concurrent Start pauses. + "Prepare Mixed", + "Cleanup", + "Remark", + "Mixed", + "Full" }; + return pause_strings[static_cast(type)]; } - -bool G1CollectorState::is_in_marking() const { - G1ConcurrentMark* cm = G1CollectedHeap::heap()->concurrent_mark(); - return cm->is_in_marking(); -} - -bool G1CollectorState::is_in_mark_or_rebuild() const { - G1ConcurrentMark* cm = G1CollectedHeap::heap()->concurrent_mark(); - return is_in_marking() || cm->is_in_rebuild_or_scrub(); -} - -bool G1CollectorState::is_in_reset_for_next_cycle() const { - G1ConcurrentMark* cm = G1CollectedHeap::heap()->concurrent_mark(); - return cm->is_in_reset_for_next_cycle(); -} - diff --git a/src/hotspot/share/gc/g1/g1CollectorState.hpp b/src/hotspot/share/gc/g1/g1CollectorState.hpp index 64c848959ae..42aaeab03b2 100644 --- a/src/hotspot/share/gc/g1/g1CollectorState.hpp +++ b/src/hotspot/share/gc/g1/g1CollectorState.hpp @@ -67,26 +67,25 @@ class G1CollectorState { _initiate_conc_mark_if_possible(false) { } // Phase setters - void set_in_normal_young_gc() { _phase = Phase::YoungNormal; } - void set_in_space_reclamation_phase() { _phase = Phase::Mixed; } - void set_in_full_gc() { _phase = Phase::FullGC; } + inline void set_in_normal_young_gc(); + inline void set_in_space_reclamation_phase(); + inline void set_in_full_gc(); - // Pause setters - void set_in_concurrent_start_gc() { _phase = Phase::YoungConcurrentStart; _initiate_conc_mark_if_possible = false; } - void set_in_prepare_mixed_gc() { _phase = Phase::YoungPrepareMixed; } + inline void set_in_concurrent_start_gc(); + inline void set_in_prepare_mixed_gc(); - void set_initiate_conc_mark_if_possible(bool v) { _initiate_conc_mark_if_possible = v; } + inline void set_initiate_conc_mark_if_possible(bool v); // Phase getters - bool is_in_young_only_phase() const { return _phase == Phase::YoungNormal || _phase == Phase::YoungConcurrentStart || _phase == Phase::YoungPrepareMixed; } - bool is_in_mixed_phase() const { return _phase == Phase::Mixed; } + inline bool is_in_young_only_phase() const; + inline bool is_in_mixed_phase() const; // Specific pauses - bool is_in_concurrent_start_gc() const { return _phase == Phase::YoungConcurrentStart; } - bool is_in_prepare_mixed_gc() const { return _phase == Phase::YoungPrepareMixed; } - bool is_in_full_gc() const { return _phase == Phase::FullGC; } + inline bool is_in_concurrent_start_gc() const; + inline bool is_in_prepare_mixed_gc() const; + inline bool is_in_full_gc() const; - bool initiate_conc_mark_if_possible() const { return _initiate_conc_mark_if_possible; } + inline bool initiate_conc_mark_if_possible() const; bool is_in_concurrent_cycle() const; bool is_in_marking() const; @@ -107,50 +106,17 @@ class G1CollectorState { // Calculate GC Pause Type from internal state. Pause gc_pause_type(bool concurrent_operation_is_full_mark) const; - static const char* to_string(Pause type) { - static const char* pause_strings[] = { "Normal", - "Concurrent Start", // Do not distinguish between the different - "Concurrent Start", // Concurrent Start pauses. - "Prepare Mixed", - "Cleanup", - "Remark", - "Mixed", - "Full" }; - return pause_strings[static_cast(type)]; - } - - static void assert_is_young_pause(Pause type) { - assert(type != Pause::Full, "must be"); - assert(type != Pause::Remark, "must be"); - assert(type != Pause::Cleanup, "must be"); - } - - static bool is_young_only_pause(Pause type) { - assert_is_young_pause(type); - return type == Pause::ConcurrentStartUndo || - type == Pause::ConcurrentStartFull || - type == Pause::PrepareMixed || - type == Pause::Normal; - } - - static bool is_mixed_pause(Pause type) { - assert_is_young_pause(type); - return type == Pause::Mixed; - } - - static bool is_prepare_mixed_pause(Pause type) { - assert_is_young_pause(type); - return type == Pause::PrepareMixed; - } - - static bool is_concurrent_start_pause(Pause type) { - assert_is_young_pause(type); - return type == Pause::ConcurrentStartFull || type == Pause::ConcurrentStartUndo; - } - - static bool is_concurrent_cycle_pause(Pause type) { - return type == Pause::Cleanup || type == Pause::Remark; - } + static const char* to_string(Pause type); + + // Pause kind queries + inline static void assert_is_young_pause(Pause type); + + inline static bool is_young_only_pause(Pause type); + inline static bool is_concurrent_start_pause(Pause type); + inline static bool is_prepare_mixed_pause(Pause type); + inline static bool is_mixed_pause(Pause type); + + inline static bool is_concurrent_cycle_pause(Pause type); }; ENUMERATOR_RANGE(G1CollectorState::Pause, G1CollectorState::Pause::Normal, G1CollectorState::Pause::Full) diff --git a/src/hotspot/share/gc/g1/g1CollectorState.inline.hpp b/src/hotspot/share/gc/g1/g1CollectorState.inline.hpp new file mode 100644 index 00000000000..0c6c9c879c3 --- /dev/null +++ b/src/hotspot/share/gc/g1/g1CollectorState.inline.hpp @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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_G1COLLECTORSTATE_INLINE_HPP +#define SHARE_GC_G1_G1COLLECTORSTATE_INLINE_HPP + +#include "gc/g1/g1CollectorState.hpp" + +#include "gc/g1/g1CollectedHeap.hpp" +#include "gc/g1/g1ConcurrentMark.inline.hpp" + +inline void G1CollectorState::set_in_normal_young_gc() { + _phase = Phase::YoungNormal; +} +inline void G1CollectorState::set_in_space_reclamation_phase() { + _phase = Phase::Mixed; +} +inline void G1CollectorState::set_in_full_gc() { + _phase = Phase::FullGC; +} + +inline void G1CollectorState::set_in_concurrent_start_gc() { + _phase = Phase::YoungConcurrentStart; + _initiate_conc_mark_if_possible = false; +} +inline void G1CollectorState::set_in_prepare_mixed_gc() { + _phase = Phase::YoungPrepareMixed; +} + +inline void G1CollectorState::set_initiate_conc_mark_if_possible(bool v) { + _initiate_conc_mark_if_possible = v; +} + +inline bool G1CollectorState::is_in_young_only_phase() const { + return _phase == Phase::YoungNormal || + _phase == Phase::YoungConcurrentStart || + _phase == Phase::YoungPrepareMixed; +} +inline bool G1CollectorState::is_in_mixed_phase() const { + return _phase == Phase::Mixed; +} + +inline bool G1CollectorState::is_in_prepare_mixed_gc() const { + return _phase == Phase::YoungPrepareMixed; +} +inline bool G1CollectorState::is_in_full_gc() const { + return _phase == Phase::FullGC; +} +inline bool G1CollectorState::is_in_concurrent_start_gc() const { + return _phase == Phase::YoungConcurrentStart; +} + +inline bool G1CollectorState::initiate_conc_mark_if_possible() const { + return _initiate_conc_mark_if_possible; +} + +inline bool G1CollectorState::is_in_concurrent_cycle() const { + G1ConcurrentMark* cm = G1CollectedHeap::heap()->concurrent_mark(); + return cm->is_in_concurrent_cycle(); +} +inline bool G1CollectorState::is_in_marking() const { + G1ConcurrentMark* cm = G1CollectedHeap::heap()->concurrent_mark(); + return cm->is_in_marking(); +} +inline bool G1CollectorState::is_in_mark_or_rebuild() const { + G1ConcurrentMark* cm = G1CollectedHeap::heap()->concurrent_mark(); + return is_in_marking() || cm->is_in_rebuild_or_scrub(); +} +inline bool G1CollectorState::is_in_reset_for_next_cycle() const { + G1ConcurrentMark* cm = G1CollectedHeap::heap()->concurrent_mark(); + return cm->is_in_reset_for_next_cycle(); +} + +inline void G1CollectorState::assert_is_young_pause(Pause type) { + assert(type != Pause::Full, "must be"); + assert(type != Pause::Remark, "must be"); + assert(type != Pause::Cleanup, "must be"); +} + +inline bool G1CollectorState::is_young_only_pause(Pause type) { + assert_is_young_pause(type); + return type == Pause::ConcurrentStartUndo || + type == Pause::ConcurrentStartFull || + type == Pause::PrepareMixed || + type == Pause::Normal; +} + +inline bool G1CollectorState::is_mixed_pause(Pause type) { + assert_is_young_pause(type); + return type == Pause::Mixed; +} + +inline bool G1CollectorState::is_prepare_mixed_pause(Pause type) { + assert_is_young_pause(type); + return type == Pause::PrepareMixed; +} + +inline bool G1CollectorState::is_concurrent_start_pause(Pause type) { + assert_is_young_pause(type); + return type == Pause::ConcurrentStartFull || type == Pause::ConcurrentStartUndo; +} + +inline bool G1CollectorState::is_concurrent_cycle_pause(Pause type) { + return type == Pause::Cleanup || type == Pause::Remark; +} + +#endif // SHARE_GC_G1_G1COLLECTORSTATE_INLINE_HPP diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp index 8fd355615d0..1caa8dbdd06 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp @@ -30,7 +30,7 @@ #include "gc/g1/g1CardSetMemory.hpp" #include "gc/g1/g1CardTableClaimTable.inline.hpp" #include "gc/g1/g1CollectedHeap.inline.hpp" -#include "gc/g1/g1CollectorState.hpp" +#include "gc/g1/g1CollectorState.inline.hpp" #include "gc/g1/g1ConcurrentMark.inline.hpp" #include "gc/g1/g1ConcurrentMarkRemarkTasks.hpp" #include "gc/g1/g1ConcurrentMarkThread.inline.hpp" diff --git a/src/hotspot/share/gc/g1/g1FullGCCompactTask.cpp b/src/hotspot/share/gc/g1/g1FullGCCompactTask.cpp index 5dbf70f36b3..93d8da0d842 100644 --- a/src/hotspot/share/gc/g1/g1FullGCCompactTask.cpp +++ b/src/hotspot/share/gc/g1/g1FullGCCompactTask.cpp @@ -22,7 +22,7 @@ * */ -#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" diff --git a/src/hotspot/share/gc/g1/g1HeapVerifier.cpp b/src/hotspot/share/gc/g1/g1HeapVerifier.cpp index dd7a8aa117d..714a2473a08 100644 --- a/src/hotspot/share/gc/g1/g1HeapVerifier.cpp +++ b/src/hotspot/share/gc/g1/g1HeapVerifier.cpp @@ -25,6 +25,7 @@ #include "code/nmethod.hpp" #include "gc/g1/g1Allocator.inline.hpp" #include "gc/g1/g1CollectedHeap.inline.hpp" +#include "gc/g1/g1CollectorState.inline.hpp" #include "gc/g1/g1ConcurrentMarkThread.hpp" #include "gc/g1/g1HeapRegion.inline.hpp" #include "gc/g1/g1HeapRegionRemSet.hpp" diff --git a/src/hotspot/share/gc/g1/g1PeriodicGCTask.cpp b/src/hotspot/share/gc/g1/g1PeriodicGCTask.cpp index ee11bbd961f..b5ff4272764 100644 --- a/src/hotspot/share/gc/g1/g1PeriodicGCTask.cpp +++ b/src/hotspot/share/gc/g1/g1PeriodicGCTask.cpp @@ -23,6 +23,7 @@ */ #include "gc/g1/g1CollectedHeap.inline.hpp" +#include "gc/g1/g1CollectorState.inline.hpp" #include "gc/g1/g1ConcurrentMark.inline.hpp" #include "gc/g1/g1ConcurrentMarkThread.inline.hpp" #include "gc/g1/g1GCCounters.hpp" diff --git a/src/hotspot/share/gc/g1/g1Policy.cpp b/src/hotspot/share/gc/g1/g1Policy.cpp index 05caff1257a..0145f1e6e1d 100644 --- a/src/hotspot/share/gc/g1/g1Policy.cpp +++ b/src/hotspot/share/gc/g1/g1Policy.cpp @@ -28,6 +28,7 @@ #include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1CollectionSet.hpp" #include "gc/g1/g1CollectionSetCandidates.inline.hpp" +#include "gc/g1/g1CollectorState.inline.hpp" #include "gc/g1/g1ConcurrentMark.hpp" #include "gc/g1/g1ConcurrentMarkThread.inline.hpp" #include "gc/g1/g1ConcurrentRefine.hpp" @@ -1133,6 +1134,17 @@ double G1Policy::predict_eden_copy_time_ms(uint count, size_t* bytes_to_copy) co return _analytics->predict_object_copy_time_ms(expected_bytes, collector_state()->is_in_young_only_phase()); } +bool G1Policy::should_update_surv_rate_group_predictors() { + return collector_state()->is_in_young_only_phase() && !collector_state()->is_in_mark_or_rebuild(); +} + +void G1Policy::cset_regions_freed() { + bool update = should_update_surv_rate_group_predictors(); + + _eden_surv_rate_group->all_surviving_words_recorded(predictor(), update); + _survivor_surv_rate_group->all_surviving_words_recorded(predictor(), update); +} + double G1Policy::predict_region_copy_time_ms(G1HeapRegion* hr, bool for_young_only_phase) const { size_t const bytes_to_copy = predict_bytes_to_copy(hr); return _analytics->predict_object_copy_time_ms(bytes_to_copy, for_young_only_phase); diff --git a/src/hotspot/share/gc/g1/g1Policy.hpp b/src/hotspot/share/gc/g1/g1Policy.hpp index 585e26441d5..bcc3bceda49 100644 --- a/src/hotspot/share/gc/g1/g1Policy.hpp +++ b/src/hotspot/share/gc/g1/g1Policy.hpp @@ -114,9 +114,7 @@ class G1Policy: public CHeapObj { G1ConcurrentStartToMixedTimeTracker _concurrent_start_to_mixed; - bool should_update_surv_rate_group_predictors() { - return collector_state()->is_in_young_only_phase() && !collector_state()->is_in_mark_or_rebuild(); - } + bool should_update_surv_rate_group_predictors(); double pending_cards_processing_time() const; public: @@ -160,12 +158,7 @@ class G1Policy: public CHeapObj { // bytes_to_copy is non-null. double predict_eden_copy_time_ms(uint count, size_t* bytes_to_copy = nullptr) const; - void cset_regions_freed() { - bool update = should_update_surv_rate_group_predictors(); - - _eden_surv_rate_group->all_surviving_words_recorded(predictor(), update); - _survivor_surv_rate_group->all_surviving_words_recorded(predictor(), update); - } + void cset_regions_freed(); G1MMUTracker* mmu_tracker() { return _mmu_tracker; diff --git a/src/hotspot/share/gc/g1/g1RemSet.cpp b/src/hotspot/share/gc/g1/g1RemSet.cpp index 4b4a8a68c30..9f9f0ecdf3a 100644 --- a/src/hotspot/share/gc/g1/g1RemSet.cpp +++ b/src/hotspot/share/gc/g1/g1RemSet.cpp @@ -31,6 +31,7 @@ #include "gc/g1/g1CardTableEntryClosure.hpp" #include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1CollectionSet.inline.hpp" +#include "gc/g1/g1CollectorState.inline.hpp" #include "gc/g1/g1ConcurrentRefine.hpp" #include "gc/g1/g1ConcurrentRefineSweepTask.hpp" #include "gc/g1/g1FromCardCache.hpp" diff --git a/src/hotspot/share/gc/g1/g1RootClosures.cpp b/src/hotspot/share/gc/g1/g1RootClosures.cpp index 2d5150c27aa..16c47cddea1 100644 --- a/src/hotspot/share/gc/g1/g1RootClosures.cpp +++ b/src/hotspot/share/gc/g1/g1RootClosures.cpp @@ -22,6 +22,7 @@ * */ +#include "gc/g1/g1CollectorState.inline.hpp" #include "gc/g1/g1OopClosures.inline.hpp" #include "gc/g1/g1RootClosures.hpp" #include "gc/g1/g1SharedClosures.hpp" diff --git a/src/hotspot/share/gc/g1/g1RootProcessor.cpp b/src/hotspot/share/gc/g1/g1RootProcessor.cpp index dac237cb277..a534eefb428 100644 --- a/src/hotspot/share/gc/g1/g1RootProcessor.cpp +++ b/src/hotspot/share/gc/g1/g1RootProcessor.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,6 @@ #include "code/codeCache.hpp" #include "gc/g1/g1BarrierSet.hpp" #include "gc/g1/g1CollectedHeap.inline.hpp" -#include "gc/g1/g1CollectorState.hpp" #include "gc/g1/g1GCParPhaseTimesTracker.hpp" #include "gc/g1/g1GCPhaseTimes.hpp" #include "gc/g1/g1HeapRegion.inline.hpp" diff --git a/src/hotspot/share/gc/g1/g1Trace.cpp b/src/hotspot/share/gc/g1/g1Trace.cpp index 242a97ca4e3..d6eadda5d50 100644 --- a/src/hotspot/share/gc/g1/g1Trace.cpp +++ b/src/hotspot/share/gc/g1/g1Trace.cpp @@ -22,6 +22,7 @@ * */ +#include "gc/g1/g1CollectorState.inline.hpp" #include "gc/g1/g1EvacInfo.hpp" #include "gc/g1/g1HeapRegionTraceType.hpp" #include "gc/g1/g1Trace.hpp" diff --git a/src/hotspot/share/gc/g1/g1VMOperations.cpp b/src/hotspot/share/gc/g1/g1VMOperations.cpp index f98f0b078f3..b0c6b680b78 100644 --- a/src/hotspot/share/gc/g1/g1VMOperations.cpp +++ b/src/hotspot/share/gc/g1/g1VMOperations.cpp @@ -23,6 +23,7 @@ */ #include "gc/g1/g1CollectedHeap.inline.hpp" +#include "gc/g1/g1CollectorState.inline.hpp" #include "gc/g1/g1ConcurrentMarkThread.inline.hpp" #include "gc/g1/g1Policy.hpp" #include "gc/g1/g1Trace.hpp" diff --git a/src/hotspot/share/gc/g1/g1YoungCollector.cpp b/src/hotspot/share/gc/g1/g1YoungCollector.cpp index 04ccac5ff05..a4938416f25 100644 --- a/src/hotspot/share/gc/g1/g1YoungCollector.cpp +++ b/src/hotspot/share/gc/g1/g1YoungCollector.cpp @@ -31,7 +31,7 @@ #include "gc/g1/g1CardSetMemory.hpp" #include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1CollectionSetCandidates.inline.hpp" -#include "gc/g1/g1CollectorState.hpp" +#include "gc/g1/g1CollectorState.inline.hpp" #include "gc/g1/g1ConcurrentMark.hpp" #include "gc/g1/g1EvacFailureRegions.inline.hpp" #include "gc/g1/g1EvacInfo.hpp" diff --git a/src/hotspot/share/gc/g1/g1YoungGCAllocationFailureInjector.cpp b/src/hotspot/share/gc/g1/g1YoungGCAllocationFailureInjector.cpp index 2291a755cd3..2b33a85da29 100644 --- a/src/hotspot/share/gc/g1/g1YoungGCAllocationFailureInjector.cpp +++ b/src/hotspot/share/gc/g1/g1YoungGCAllocationFailureInjector.cpp @@ -23,6 +23,7 @@ */ #include "gc/g1/g1CollectedHeap.inline.hpp" +#include "gc/g1/g1CollectorState.inline.hpp" #include "gc/g1/g1YoungGCAllocationFailureInjector.inline.hpp" #include "gc/shared/gc_globals.hpp" diff --git a/src/hotspot/share/gc/g1/g1YoungGCPostEvacuateTasks.cpp b/src/hotspot/share/gc/g1/g1YoungGCPostEvacuateTasks.cpp index 3d49b8f025b..14282383e29 100644 --- a/src/hotspot/share/gc/g1/g1YoungGCPostEvacuateTasks.cpp +++ b/src/hotspot/share/gc/g1/g1YoungGCPostEvacuateTasks.cpp @@ -29,7 +29,7 @@ #include "gc/g1/g1CardTableEntryClosure.hpp" #include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1CollectionSetCandidates.inline.hpp" -#include "gc/g1/g1CollectorState.hpp" +#include "gc/g1/g1CollectorState.inline.hpp" #include "gc/g1/g1ConcurrentMark.inline.hpp" #include "gc/g1/g1EvacFailureRegions.inline.hpp" #include "gc/g1/g1EvacInfo.hpp" diff --git a/src/hotspot/share/prims/whitebox.cpp b/src/hotspot/share/prims/whitebox.cpp index a13d0ba47c8..f50e6ddb3db 100644 --- a/src/hotspot/share/prims/whitebox.cpp +++ b/src/hotspot/share/prims/whitebox.cpp @@ -107,6 +107,7 @@ #if INCLUDE_G1GC #include "gc/g1/g1Arguments.hpp" #include "gc/g1/g1CollectedHeap.inline.hpp" +#include "gc/g1/g1CollectorState.inline.hpp" #include "gc/g1/g1ConcurrentMark.hpp" #include "gc/g1/g1ConcurrentMarkThread.inline.hpp" #include "gc/g1/g1HeapRegionManager.hpp" From 53c864a881d2183d3664a6a5a56480bd99fffe45 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Fri, 27 Mar 2026 08:18:47 +0000 Subject: [PATCH 027/116] 8380960: "Foreign function access" discussion links to wrong downcallHandle overload Reviewed-by: mcimadamore --- .../share/classes/java/lang/foreign/package-info.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/java.base/share/classes/java/lang/foreign/package-info.java b/src/java.base/share/classes/java/lang/foreign/package-info.java index 438d42ae7d1..2070f0c70a8 100644 --- a/src/java.base/share/classes/java/lang/foreign/package-info.java +++ b/src/java.base/share/classes/java/lang/foreign/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -114,7 +114,7 @@ * and we use it to {@linkplain java.lang.foreign.SymbolLookup#findOrThrow(java.lang.String) look up} * the {@code strlen} function in the standard C library; a downcall method handle * targeting said function is subsequently - * {@linkplain java.lang.foreign.Linker#downcallHandle(FunctionDescriptor, Linker.Option...) obtained}. + * {@linkplain java.lang.foreign.Linker#downcallHandle(MemorySegment, FunctionDescriptor, Linker.Option...) obtained}. * To complete the linking successfully, we must provide a * {@link java.lang.foreign.FunctionDescriptor} instance, describing the signature of the * {@code strlen} function. From this information, the linker will uniquely determine From c0e500ad996dd7174f6f37481f2da48dc6d98f56 Mon Sep 17 00:00:00 2001 From: Anton Seoane Ampudia Date: Fri, 27 Mar 2026 09:44:37 +0000 Subject: [PATCH 028/116] 8379794: C2: UBSAN runtime error: shift exponent 64 is too large for 64-bit type 'long unsigned int' Reviewed-by: rcastanedalo, qamai, dlong --- src/hotspot/cpu/x86/x86.ad | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/hotspot/cpu/x86/x86.ad b/src/hotspot/cpu/x86/x86.ad index d7014141234..eaa88d900c7 100644 --- a/src/hotspot/cpu/x86/x86.ad +++ b/src/hotspot/cpu/x86/x86.ad @@ -23972,8 +23972,12 @@ instruct vmask_gen_imm(kReg dst, immL len, rRegL temp) %{ format %{ "vector_mask_gen $len \t! vector mask generator" %} effect(TEMP temp); ins_encode %{ - __ mov64($temp$$Register, (0xFFFFFFFFFFFFFFFFUL >> (64 -$len$$constant))); - __ kmovql($dst$$KRegister, $temp$$Register); + if ($len$$constant > 0) { + __ mov64($temp$$Register, right_n_bits($len$$constant)); + __ kmovql($dst$$KRegister, $temp$$Register); + } else { + __ kxorql($dst$$KRegister, $dst$$KRegister, $dst$$KRegister); + } %} ins_pipe( pipe_slow ); %} From cca8c23871f1669fdd002652a20a6b7935704e30 Mon Sep 17 00:00:00 2001 From: Serhiy Sachkov Date: Fri, 27 Mar 2026 10:36:34 +0000 Subject: [PATCH 029/116] 8380999: Update IPSupport by adding diagnoseConfigurationIssue() method Reviewed-by: dfuchs --- test/lib/jdk/test/lib/net/IPSupport.java | 25 ++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/test/lib/jdk/test/lib/net/IPSupport.java b/test/lib/jdk/test/lib/net/IPSupport.java index 31255e20c6a..4a77c3a9bae 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, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,7 @@ import java.net.ProtocolFamily; import java.net.StandardProtocolFamily; import java.nio.channels.SocketChannel; +import java.util.Optional; import jtreg.SkippedException; @@ -124,13 +125,33 @@ public static final boolean currentConfigurationIsValid() { * is non-operational */ public static void throwSkippedExceptionIfNonOperational() throws SkippedException { + Optional configurationIssue = diagnoseConfigurationIssue(); + configurationIssue.map(SkippedException::new).ifPresent(x -> { + throw x; + }); + } + + /** + * Checks that the platform supports the ability to create a + * minimally-operational socket whose protocol is either one of IPv4 + * or IPv6. + * + *

A minimally-operation socket is one that can be created and + * bound to an IP-specific loopback address. IP support is + * considered non-operational if a socket cannot be bound to either + * one of, an IPv4 loopback address, or the IPv6 loopback address. + * + * @return Optinal with config issue or empty Optinal if no issue found + */ + public static Optional diagnoseConfigurationIssue(){ if (!currentConfigurationIsValid()) { ByteArrayOutputStream os = new ByteArrayOutputStream(); PrintStream ps = new PrintStream(os); ps.println("Invalid networking configuration"); printPlatformSupport(ps); - throw new SkippedException(os.toString()); + return Optional.of(os.toString()); } + return Optional.empty(); } /** From b242eef3123a936f53ea76b28b2f6350e52afa94 Mon Sep 17 00:00:00 2001 From: Ivan Walulya Date: Fri, 27 Mar 2026 11:20:05 +0000 Subject: [PATCH 030/116] 8380656: G1: Refactor G1IHOPControl Co-authored-by: Thomas Schatzl Reviewed-by: ayang, tschatzl --- .../g1ConcurrentStartToMixedTimeTracker.hpp | 8 +- src/hotspot/share/gc/g1/g1IHOPControl.cpp | 117 ++++++++++-------- src/hotspot/share/gc/g1/g1IHOPControl.hpp | 43 ++++--- src/hotspot/share/gc/g1/g1Policy.cpp | 14 +-- .../gtest/gc/g1/test_g1IHOPControl.cpp | 38 +++--- 5 files changed, 122 insertions(+), 98 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1ConcurrentStartToMixedTimeTracker.hpp b/src/hotspot/share/gc/g1/g1ConcurrentStartToMixedTimeTracker.hpp index 57372e695c8..f8bad4bdcd7 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentStartToMixedTimeTracker.hpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentStartToMixedTimeTracker.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,7 @@ // Used to track time from the end of concurrent start to the first mixed GC. // After calling the concurrent start/mixed gc notifications, the result can be -// obtained in last_marking_time() once, after which the tracking resets. +// obtained in get_and_reset_last_marking_time() once, after which the tracking resets. // Any pauses recorded by add_pause() will be subtracted from that results. class G1ConcurrentStartToMixedTimeTracker { private: @@ -60,7 +60,7 @@ class G1ConcurrentStartToMixedTimeTracker { } } - double last_marking_time() { + double get_and_reset_last_marking_time() { assert(has_result(), "Do not have all measurements yet."); double result = (_mixed_start_time - _concurrent_start_end_time) - _total_pause_time; reset(); @@ -80,6 +80,8 @@ class G1ConcurrentStartToMixedTimeTracker { } } + bool is_active() const { return _active; } + // Returns whether we have a result that can be retrieved. bool has_result() const { return _mixed_start_time > 0.0 && _concurrent_start_end_time > 0.0; } }; diff --git a/src/hotspot/share/gc/g1/g1IHOPControl.cpp b/src/hotspot/share/gc/g1/g1IHOPControl.cpp index 43698e9f12b..1e1c52477f9 100644 --- a/src/hotspot/share/gc/g1/g1IHOPControl.cpp +++ b/src/hotspot/share/gc/g1/g1IHOPControl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,18 +38,18 @@ double G1IHOPControl::predict(const TruncatedSeq* seq) const { bool G1IHOPControl::have_enough_data_for_prediction() const { assert(_is_adaptive, "precondition"); - return ((size_t)_marking_times_s.num() >= G1AdaptiveIHOPNumInitialSamples) && - ((size_t)_allocation_rate_s.num() >= G1AdaptiveIHOPNumInitialSamples); + return ((size_t)_marking_start_to_mixed_time_s.num() >= G1AdaptiveIHOPNumInitialSamples) && + ((size_t)_old_gen_alloc_rate.num() >= G1AdaptiveIHOPNumInitialSamples); } -double G1IHOPControl::last_marking_length_s() const { - return _marking_times_s.last(); +double G1IHOPControl::last_marking_start_to_mixed_time_s() const { + return _marking_start_to_mixed_time_s.last(); } -size_t G1IHOPControl::actual_target_threshold() const { +size_t G1IHOPControl::effective_target_occupancy() const { assert(_is_adaptive, "precondition"); - // The actual target threshold takes the heap reserve and the expected waste in + // The effective target occupancy takes the heap reserve and the expected waste in // free space into account. // _heap_reserve is that part of the total heap capacity that is reserved for // eventual promotion failure. @@ -79,9 +79,9 @@ G1IHOPControl::G1IHOPControl(double ihop_percent, _last_allocation_time_s(0.0), _old_gen_alloc_tracker(old_gen_alloc_tracker), _predictor(predictor), - _marking_times_s(10, 0.05), - _allocation_rate_s(10, 0.05), - _last_unrestrained_young_size(0) { + _marking_start_to_mixed_time_s(10, 0.05), + _old_gen_alloc_rate(10, 0.05), + _expected_young_gen_at_first_mixed_gc(0) { assert(_initial_ihop_percent >= 0.0 && _initial_ihop_percent <= 100.0, "IHOP percent out of range: %.3f", ihop_percent); assert(!_is_adaptive || _predictor != nullptr, "precondition"); @@ -98,85 +98,104 @@ void G1IHOPControl::report_statistics(G1NewTracer* new_tracer, size_t non_young_ send_trace_event(new_tracer, non_young_occupancy); } -void G1IHOPControl::update_allocation_info(double allocation_time_s, size_t additional_buffer_size) { +void G1IHOPControl::update_allocation_info(double allocation_time_s, size_t expected_young_gen_size) { assert(allocation_time_s > 0, "Invalid allocation time: %.3f", allocation_time_s); _last_allocation_time_s = allocation_time_s; double alloc_rate = _old_gen_alloc_tracker->last_period_old_gen_growth() / allocation_time_s; - _allocation_rate_s.add(alloc_rate); - _last_unrestrained_young_size = additional_buffer_size; + _old_gen_alloc_rate.add(alloc_rate); + _expected_young_gen_at_first_mixed_gc = expected_young_gen_size; } -void G1IHOPControl::update_marking_length(double marking_length_s) { - assert(marking_length_s >= 0.0, "Invalid marking length: %.3f", marking_length_s); - _marking_times_s.add(marking_length_s); +void G1IHOPControl::add_marking_start_to_mixed_length(double length_s) { + assert(length_s >= 0.0, "Invalid marking length: %.3f", length_s); + _marking_start_to_mixed_time_s.add(length_s); } -size_t G1IHOPControl::get_conc_mark_start_threshold() { +// Determine the old generation occupancy threshold at which to start +// concurrent marking such that reclamation (first Mixed GC) begins +// before the heap reaches a critical occupancy level. +size_t G1IHOPControl::old_gen_threshold_for_conc_mark_start() { guarantee(_target_occupancy > 0, "Target occupancy must be initialized"); if (!_is_adaptive || !have_enough_data_for_prediction()) { return (size_t)(_initial_ihop_percent * _target_occupancy / 100.0); } - double pred_marking_time = predict(&_marking_times_s); - double pred_rate = predict(&_allocation_rate_s); - size_t pred_bytes = (size_t)(pred_marking_time * pred_rate); - size_t predicted_needed = pred_bytes + _last_unrestrained_young_size; - size_t internal_threshold = actual_target_threshold(); - - return predicted_needed < internal_threshold - ? internal_threshold - predicted_needed + // During the time between marking start and the first Mixed GC, + // additional memory will be consumed: + // - Old gen grows due to allocations: + // old_gen_alloc_bytes = old_gen_alloc_rate * marking_start_to_mixed_time + // - Young gen will occupy a certain size at the first Mixed GC: + // expected_young_gen_at_first_mixed_gc + double marking_start_to_mixed_time = predict(&_marking_start_to_mixed_time_s); + double old_gen_alloc_rate = predict(&_old_gen_alloc_rate); + size_t old_gen_alloc_bytes = (size_t)(marking_start_to_mixed_time * old_gen_alloc_rate); + + // Therefore, the total heap occupancy at the first Mixed GC is: + // current_old_gen + old_gen_growth + expected_young_gen_at_first_mixed_gc + // + // To ensure this does not exceed the target_heap_occupancy, we work + // backwards to compute the old gen occupancy at which marking must start: + // mark_start_threshold = target_heap_occupancy - + // (old_gen_growth + expected_young_gen_at_first_mixed_gc) + + size_t predicted_needed = old_gen_alloc_bytes + _expected_young_gen_at_first_mixed_gc; + size_t target_heap_occupancy = effective_target_occupancy(); + + return predicted_needed < target_heap_occupancy + ? target_heap_occupancy - predicted_needed : 0; } void G1IHOPControl::print_log(size_t non_young_occupancy) { assert(_target_occupancy > 0, "Target occupancy still not updated yet."); - size_t cur_conc_mark_start_threshold = get_conc_mark_start_threshold(); - log_debug(gc, ihop)("Basic information (value update), threshold: %zuB (%1.2f), target occupancy: %zuB, non-young occupancy: %zuB, " - "recent allocation size: %zuB, recent allocation duration: %1.2fms, recent old gen allocation rate: %1.2fB/s, recent marking phase length: %1.2fms", - cur_conc_mark_start_threshold, - percent_of(cur_conc_mark_start_threshold, _target_occupancy), + size_t old_gen_mark_start_threshold = old_gen_threshold_for_conc_mark_start(); + log_debug(gc, ihop)("Basic information (value update), old-gen threshold: %zuB (%1.2f%%), target occupancy: %zuB, old-gen occupancy: %zuB (%1.2f%%), " + "recent old-gen allocation size: %zuB, recent allocation duration: %1.2fms, recent old-gen allocation rate: %1.2fB/s, recent marking phase length: %1.2fms", + old_gen_mark_start_threshold, + percent_of(old_gen_mark_start_threshold, _target_occupancy), _target_occupancy, non_young_occupancy, + percent_of(non_young_occupancy, _target_occupancy), _old_gen_alloc_tracker->last_period_old_gen_bytes(), _last_allocation_time_s * 1000.0, _last_allocation_time_s > 0.0 ? _old_gen_alloc_tracker->last_period_old_gen_bytes() / _last_allocation_time_s : 0.0, - last_marking_length_s() * 1000.0); + last_marking_start_to_mixed_time_s() * 1000.0); if (!_is_adaptive) { return; } - size_t actual_threshold = actual_target_threshold(); - log_debug(gc, ihop)("Adaptive IHOP information (value update), threshold: %zuB (%1.2f), internal target threshold: %zuB, " - "non-young occupancy: %zuB, additional buffer size: %zuB, predicted old gen allocation rate: %1.2fB/s, " - "predicted marking phase length: %1.2fms, prediction active: %s", - cur_conc_mark_start_threshold, - percent_of(cur_conc_mark_start_threshold, actual_threshold), - actual_threshold, + size_t effective_target = effective_target_occupancy(); + log_debug(gc, ihop)("Adaptive IHOP information (value update), prediction active: %s, old-gen threshold: %zuB (%1.2f%%), internal target occupancy: %zuB, " + "old-gen occupancy: %zuB, additional buffer size: %zuB, predicted old-gen allocation rate: %1.2fB/s, " + "predicted marking phase length: %1.2fms", + BOOL_TO_STR(have_enough_data_for_prediction()), + old_gen_mark_start_threshold, + percent_of(old_gen_mark_start_threshold, effective_target), + effective_target, non_young_occupancy, - _last_unrestrained_young_size, - predict(&_allocation_rate_s), - predict(&_marking_times_s) * 1000.0, - have_enough_data_for_prediction() ? "true" : "false"); + _expected_young_gen_at_first_mixed_gc, + predict(&_old_gen_alloc_rate), + predict(&_marking_start_to_mixed_time_s) * 1000.0); } void G1IHOPControl::send_trace_event(G1NewTracer* tracer, size_t non_young_occupancy) { assert(_target_occupancy > 0, "Target occupancy still not updated yet."); - tracer->report_basic_ihop_statistics(get_conc_mark_start_threshold(), + tracer->report_basic_ihop_statistics(old_gen_threshold_for_conc_mark_start(), _target_occupancy, non_young_occupancy, _old_gen_alloc_tracker->last_period_old_gen_bytes(), _last_allocation_time_s, - last_marking_length_s()); + last_marking_start_to_mixed_time_s()); if (_is_adaptive) { - tracer->report_adaptive_ihop_statistics(get_conc_mark_start_threshold(), - actual_target_threshold(), + tracer->report_adaptive_ihop_statistics(old_gen_threshold_for_conc_mark_start(), + effective_target_occupancy(), non_young_occupancy, - _last_unrestrained_young_size, - predict(&_allocation_rate_s), - predict(&_marking_times_s), + _expected_young_gen_at_first_mixed_gc, + predict(&_old_gen_alloc_rate), + predict(&_marking_start_to_mixed_time_s), have_enough_data_for_prediction()); } } diff --git a/src/hotspot/share/gc/g1/g1IHOPControl.hpp b/src/hotspot/share/gc/g1/g1IHOPControl.hpp index 24061c026d1..ff209012f02 100644 --- a/src/hotspot/share/gc/g1/g1IHOPControl.hpp +++ b/src/hotspot/share/gc/g1/g1IHOPControl.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -58,8 +58,11 @@ class G1IHOPControl : public CHeapObj { const G1OldGenAllocationTracker* _old_gen_alloc_tracker; const G1Predictions* _predictor; - TruncatedSeq _marking_times_s; - TruncatedSeq _allocation_rate_s; + // Wall-clock time in seconds from marking start to the first mixed GC, + // excluding GC Pause time. + TruncatedSeq _marking_start_to_mixed_time_s; + // Old generation allocation rate in bytes per second. + TruncatedSeq _old_gen_alloc_rate; // The most recent unrestrained size of the young gen. This is used as an additional // factor in the calculation of the threshold, as the threshold is based on @@ -68,18 +71,18 @@ class G1IHOPControl : public CHeapObj { // Since we cannot know what young gen sizes are used in the future, we will just // use the current one. We expect that this one will be one with a fairly large size, // as there is no marking or mixed gc that could impact its size too much. - size_t _last_unrestrained_young_size; + size_t _expected_young_gen_at_first_mixed_gc; // Get a new prediction bounded below by zero from the given sequence. double predict(const TruncatedSeq* seq) const; bool have_enough_data_for_prediction() const; - double last_marking_length_s() const; + double last_marking_start_to_mixed_time_s() const; - // The "actual" target threshold the algorithm wants to keep during and at the - // end of marking. This is typically lower than the requested threshold, as the + // The "effective" target occupancy the algorithm wants to keep until the start + // of Mixed GCs. This is typically lower than the target occupancy, as the // algorithm needs to consider restrictions by the environment. - size_t actual_target_threshold() const; + size_t effective_target_occupancy() const; void print_log(size_t non_young_occupancy); void send_trace_event(G1NewTracer* tracer, size_t non_young_occupancy); @@ -95,22 +98,24 @@ class G1IHOPControl : public CHeapObj { // Adjust target occupancy. void update_target_occupancy(size_t new_target_occupancy); - // Update information about time during which allocations in the Java heap occurred, - // how large these allocations were in bytes, and an additional buffer. - // The allocations should contain any amount of space made unusable for further - // allocation, e.g. any waste caused by TLAB allocation, space at the end of - // humongous objects that can not be used for allocation, etc. - // Together with the target occupancy, this additional buffer should contain the - // difference between old gen size and total heap size at the start of reclamation, - // and space required for that reclamation. - void update_allocation_info(double allocation_time_s, size_t additional_buffer_size); + void update_target_after_marking_phase(); + + // Update allocation rate information and current expected young gen size for the + // first mixed gc needed for the predictor. Allocation rate is given as the + // separately passed in allocation increment and the time passed (mutator time) + // for the latest allocation increment here. Allocation size is the memory needed + // during the mutator before and the first mixed gc pause itself. + // Contents include young gen at that point, and the memory required for evacuating + // the collection set in that first mixed gc (including waste caused by PLAB + // allocation etc.). + void update_allocation_info(double allocation_time_s, size_t expected_young_gen_size); // Update the time spent in the mutator beginning from the end of concurrent start to // the first mixed gc. - void update_marking_length(double marking_length_s); + void add_marking_start_to_mixed_length(double length_s); // Get the current non-young occupancy at which concurrent marking should start. - size_t get_conc_mark_start_threshold(); + size_t old_gen_threshold_for_conc_mark_start(); void report_statistics(G1NewTracer* tracer, size_t non_young_occupancy); }; diff --git a/src/hotspot/share/gc/g1/g1Policy.cpp b/src/hotspot/share/gc/g1/g1Policy.cpp index 0145f1e6e1d..24a82113d20 100644 --- a/src/hotspot/share/gc/g1/g1Policy.cpp +++ b/src/hotspot/share/gc/g1/g1Policy.cpp @@ -738,15 +738,15 @@ bool G1Policy::need_to_start_conc_mark(const char* source, size_t allocation_wor return false; } - size_t marking_initiating_used_threshold = _ihop_control->get_conc_mark_start_threshold(); + size_t marking_initiating_old_gen_threshold = _ihop_control->old_gen_threshold_for_conc_mark_start(); size_t non_young_occupancy = _g1h->non_young_occupancy_after_allocation(allocation_word_size); bool result = false; - if (non_young_occupancy > marking_initiating_used_threshold) { + if (non_young_occupancy > marking_initiating_old_gen_threshold) { result = collector_state()->is_in_young_only_phase(); log_debug(gc, ergo, ihop)("%s non-young occupancy: %zuB allocation request: %zuB threshold: %zuB (%1.2f) source: %s", result ? "Request concurrent cycle initiation (occupancy higher than threshold)" : "Do not request concurrent cycle initiation (still doing mixed collections)", - non_young_occupancy, allocation_word_size * HeapWordSize, marking_initiating_used_threshold, (double) marking_initiating_used_threshold / _g1h->capacity() * 100, source); + non_young_occupancy, allocation_word_size * HeapWordSize, marking_initiating_old_gen_threshold, (double) marking_initiating_old_gen_threshold / _g1h->capacity() * 100, source); } return result; } @@ -972,8 +972,7 @@ void G1Policy::record_young_collection_end(bool concurrent_operation_is_full_mar update_young_length_bounds(); _old_gen_alloc_tracker.reset_after_gc(_g1h->humongous_regions_count() * G1HeapRegion::GrainBytes); - if (update_ihop_prediction(app_time_ms / 1000.0, - G1CollectorState::is_young_only_pause(this_pause))) { + if (update_ihop_prediction(app_time_ms / 1000.0, is_young_only_pause)) { _ihop_control->report_statistics(_g1h->gc_tracer_stw(), _g1h->non_young_occupancy_after_allocation(allocation_word_size)); } } else { @@ -1030,14 +1029,13 @@ bool G1Policy::update_ihop_prediction(double mutator_time_s, bool report = false; - double marking_to_mixed_time = -1.0; if (!this_gc_was_young_only && _concurrent_start_to_mixed.has_result()) { - marking_to_mixed_time = _concurrent_start_to_mixed.last_marking_time(); + double marking_to_mixed_time = _concurrent_start_to_mixed.get_and_reset_last_marking_time(); assert(marking_to_mixed_time > 0.0, "Concurrent start to mixed time must be larger than zero but is %.3f", marking_to_mixed_time); if (marking_to_mixed_time > min_valid_time) { - _ihop_control->update_marking_length(marking_to_mixed_time); + _ihop_control->add_marking_start_to_mixed_length(marking_to_mixed_time); report = true; } } diff --git a/test/hotspot/gtest/gc/g1/test_g1IHOPControl.cpp b/test/hotspot/gtest/gc/g1/test_g1IHOPControl.cpp index ff661fde00d..0ee0889b6e5 100644 --- a/test/hotspot/gtest/gc/g1/test_g1IHOPControl.cpp +++ b/test/hotspot/gtest/gc/g1/test_g1IHOPControl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,7 +40,7 @@ static void test_update(G1IHOPControl* ctrl, test_update_allocation_tracker(alloc_tracker, alloc_amount); for (int i = 0; i < 100; i++) { ctrl->update_allocation_info(alloc_time, young_size); - ctrl->update_marking_length(mark_time); + ctrl->add_marking_start_to_mixed_length(mark_time); } } @@ -57,7 +57,7 @@ static void test_update_humongous(G1IHOPControl* ctrl, alloc_tracker->reset_after_gc(humongous_bytes_after_last_gc); for (int i = 0; i < 100; i++) { ctrl->update_allocation_info(alloc_time, young_size); - ctrl->update_marking_length(mark_time); + ctrl->add_marking_start_to_mixed_length(mark_time); } } @@ -74,26 +74,26 @@ TEST_VM(G1IHOPControl, static_simple) { G1IHOPControl ctrl(initial_ihop, &alloc_tracker, is_adaptive, nullptr, 0, 0); ctrl.update_target_occupancy(100); - size_t threshold = ctrl.get_conc_mark_start_threshold(); + size_t threshold = ctrl.old_gen_threshold_for_conc_mark_start(); EXPECT_EQ(initial_ihop, threshold); test_update_allocation_tracker(&alloc_tracker, 100); ctrl.update_allocation_info(100.0, 100); - threshold = ctrl.get_conc_mark_start_threshold(); + threshold = ctrl.old_gen_threshold_for_conc_mark_start(); EXPECT_EQ(initial_ihop, threshold); - ctrl.update_marking_length(1000.0); - threshold = ctrl.get_conc_mark_start_threshold(); + ctrl.add_marking_start_to_mixed_length(1000.0); + threshold = ctrl.old_gen_threshold_for_conc_mark_start(); EXPECT_EQ(initial_ihop, threshold); // Whatever we pass, the IHOP value must stay the same. test_update(&ctrl, &alloc_tracker, 2, 10, 10, 3); - threshold = ctrl.get_conc_mark_start_threshold(); + threshold = ctrl.old_gen_threshold_for_conc_mark_start(); EXPECT_EQ(initial_ihop, threshold); test_update(&ctrl, &alloc_tracker, 12, 10, 10, 3); - threshold = ctrl.get_conc_mark_start_threshold(); + threshold = ctrl.old_gen_threshold_for_conc_mark_start(); EXPECT_EQ(initial_ihop, threshold); } @@ -126,23 +126,23 @@ TEST_VM(G1IHOPControl, adaptive_simple) { - (young_size + alloc_amount1 / alloc_time1 * marking_time1); size_t threshold; - threshold = ctrl.get_conc_mark_start_threshold(); + threshold = ctrl.old_gen_threshold_for_conc_mark_start(); EXPECT_EQ(initial_threshold, threshold); for (size_t i = 0; i < G1AdaptiveIHOPNumInitialSamples - 1; i++) { test_update_allocation_tracker(&alloc_tracker, alloc_amount1); ctrl.update_allocation_info(alloc_time1, young_size); - ctrl.update_marking_length(marking_time1); + ctrl.add_marking_start_to_mixed_length(marking_time1); // Not enough data yet. - threshold = ctrl.get_conc_mark_start_threshold(); + threshold = ctrl.old_gen_threshold_for_conc_mark_start(); ASSERT_EQ(initial_threshold, threshold) << "on step " << i; } test_update(&ctrl, &alloc_tracker, alloc_time1, alloc_amount1, young_size, marking_time1); - threshold = ctrl.get_conc_mark_start_threshold(); + threshold = ctrl.old_gen_threshold_for_conc_mark_start(); EXPECT_EQ(settled_ihop1, threshold); @@ -155,7 +155,7 @@ TEST_VM(G1IHOPControl, adaptive_simple) { test_update(&ctrl, &alloc_tracker, alloc_time2, alloc_amount2, young_size, marking_time2); - threshold = ctrl.get_conc_mark_start_threshold(); + threshold = ctrl.old_gen_threshold_for_conc_mark_start(); EXPECT_LT(threshold, settled_ihop1); @@ -166,14 +166,14 @@ TEST_VM(G1IHOPControl, adaptive_simple) { const size_t settled_ihop3 = 0; test_update(&ctrl, &alloc_tracker, alloc_time3, alloc_amount3, young_size, marking_time3); - threshold = ctrl.get_conc_mark_start_threshold(); + threshold = ctrl.old_gen_threshold_for_conc_mark_start(); EXPECT_EQ(settled_ihop3, threshold); // And back to some arbitrary value. test_update(&ctrl, &alloc_tracker, alloc_time2, alloc_amount2, young_size, marking_time2); - threshold = ctrl.get_conc_mark_start_threshold(); + threshold = ctrl.old_gen_threshold_for_conc_mark_start(); EXPECT_GT(threshold, settled_ihop3); } @@ -205,7 +205,7 @@ TEST_VM(G1IHOPControl, adaptive_humongous) { humongous_bytes_after_last_gc, young_size, marking_time); // Test threshold size_t threshold; - threshold = ctrl.get_conc_mark_start_threshold(); + threshold = ctrl.old_gen_threshold_for_conc_mark_start(); // Adjusted allocated bytes: // Total bytes: humongous_bytes // Freed hum bytes: humongous_bytes - humongous_bytes_after_last_gc @@ -219,7 +219,7 @@ TEST_VM(G1IHOPControl, adaptive_humongous) { ctrl2.update_target_occupancy(target_size); test_update_humongous(&ctrl2, &alloc_tracker, duration, old_bytes, humongous_bytes, humongous_bytes_after_gc, young_size, marking_time); - threshold = ctrl2.get_conc_mark_start_threshold(); + threshold = ctrl2.old_gen_threshold_for_conc_mark_start(); // Adjusted allocated bytes: // Total bytes: old_bytes + humongous_bytes // Freed hum bytes: humongous_bytes - (humongous_bytes_after_gc - humongous_bytes_after_last_gc) @@ -235,7 +235,7 @@ TEST_VM(G1IHOPControl, adaptive_humongous) { ctrl3.update_target_occupancy(target_size); test_update_humongous(&ctrl3, &alloc_tracker, duration, old_bytes, humongous_bytes, humongous_bytes_after_gc, young_size, marking_time); - threshold = ctrl3.get_conc_mark_start_threshold(); + threshold = ctrl3.old_gen_threshold_for_conc_mark_start(); // Adjusted allocated bytes: // All humongous are cleaned up since humongous_bytes_after_gc < humongous_bytes_after_last_gc // Total bytes: old_bytes + humongous_bytes From 299452402551d5387eb41ad799ce6a05c05237b9 Mon Sep 17 00:00:00 2001 From: Yasumasa Suenaga Date: Fri, 27 Mar 2026 13:26:49 +0000 Subject: [PATCH 031/116] 8380956: HexFormat shoud have @ValueBased Reviewed-by: rriggs, stuefe, liach --- src/java.base/share/classes/java/util/HexFormat.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/java.base/share/classes/java/util/HexFormat.java b/src/java.base/share/classes/java/util/HexFormat.java index aebb8b9af52..7d9fe08108d 100644 --- a/src/java.base/share/classes/java/util/HexFormat.java +++ b/src/java.base/share/classes/java/util/HexFormat.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2024, Alibaba Group Holding Limited. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -26,6 +26,7 @@ package java.util; +import jdk.internal.ValueBased; import jdk.internal.access.JavaLangAccess; import jdk.internal.access.SharedSecrets; import jdk.internal.util.HexDigits; @@ -134,7 +135,7 @@ * @since 17 */ - +@ValueBased public final class HexFormat { // Access to create strings from a byte array. From 426547d2c8df1d6b9b494eb28d0fbbdfe58c8821 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Fri, 27 Mar 2026 14:56:54 +0000 Subject: [PATCH 032/116] 8380968: classfile package doc mentions nonexistent UtfEntry Reviewed-by: liach --- .../classes/java/lang/classfile/package-info.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/java.base/share/classes/java/lang/classfile/package-info.java b/src/java.base/share/classes/java/lang/classfile/package-info.java index 460f6699e7b..8bf5559df0a 100644 --- a/src/java.base/share/classes/java/lang/classfile/package-info.java +++ b/src/java.base/share/classes/java/lang/classfile/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -493,9 +493,9 @@ * * {@snippet lang="text" : * ClassElement = - * FieldModel*(UtfEntry name, Utf8Entry descriptor) - * | MethodModel*(UtfEntry name, Utf8Entry descriptor) - * | ModuleAttribute?(int flags, ModuleEntry moduleName, UtfEntry moduleVersion, + * FieldModel*(Utf8Entry name, Utf8Entry descriptor) + * | MethodModel*(Utf8Entry name, Utf8Entry descriptor) + * | ModuleAttribute?(int flags, ModuleEntry moduleName, Utf8Entry moduleVersion, * List requires, List opens, * List exports, List provides, * List uses) @@ -588,7 +588,7 @@ * | LabelTarget(Label label) * | LineNumber(int line) * | ExceptionCatch(Label tryStart, Label tryEnd, Label handler, ClassEntry exception) - * | LocalVariable(int slot, UtfEntry name, Utf8Entry type, Label startScope, Label endScope) + * | LocalVariable(int slot, Utf8Entry name, Utf8Entry type, Label startScope, Label endScope) * | LocalVariableType(int slot, Utf8Entry name, Utf8Entry type, Label startScope, Label endScope) * | CharacterRange(int rangeStart, int rangeEnd, int flags, Label startScope, Label endScope) * } From 1ed1bb8ccbc7ba0cbb54f4354c64d39b3ea64d90 Mon Sep 17 00:00:00 2001 From: Daisuke Yamazaki Date: Fri, 27 Mar 2026 15:52:13 +0000 Subject: [PATCH 033/116] 8379818: Refactor java/nio/file/Files/StreamLinesTest.java to use JUnit Reviewed-by: bpb --- .../java/nio/file/Files/StreamLinesTest.java | 63 ++++++++----------- 1 file changed, 25 insertions(+), 38 deletions(-) diff --git a/test/jdk/java/nio/file/Files/StreamLinesTest.java b/test/jdk/java/nio/file/Files/StreamLinesTest.java index 402b114ae0b..7812a4ceb89 100644 --- a/test/jdk/java/nio/file/Files/StreamLinesTest.java +++ b/test/jdk/java/nio/file/Files/StreamLinesTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,18 +23,15 @@ /* @test * @bug 8072773 - * @library /test/lib /lib/testlibrary/bootlib - * @build java.base/java.util.stream.OpTestCase - * jdk.test.lib.RandomFactory - * @run testng/othervm StreamLinesTest + * @library /test/lib + * @build jdk.test.lib.RandomFactory + * @run junit/othervm StreamLinesTest * @summary Tests streams returned from Files.lines, primarily focused on * testing the file-channel-based stream stream with supported * character sets * @key randomness */ -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import java.io.BufferedReader; import java.io.BufferedWriter; @@ -50,13 +47,16 @@ import java.util.List; import java.util.Random; import java.util.function.IntFunction; -import java.util.function.Supplier; -import java.util.stream.OpTestCase; import java.util.stream.Stream; -import java.util.stream.TestData; import jdk.test.lib.RandomFactory; -public class StreamLinesTest extends OpTestCase { +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class StreamLinesTest { enum LineSeparator { NONE(""), @@ -120,16 +120,15 @@ static List readAllLines(Path path, Charset cs) throws IOException { } } - static Object[] of(String description, IntFunction lineGenerator, + static Arguments of(String description, IntFunction lineGenerator, IntFunction separatorGenerator, int n, Charset cs) { - return new Object[]{description, lineGenerator, separatorGenerator, n, cs}; + return Arguments.argumentSet(description, lineGenerator, separatorGenerator, n, cs); } private static final Random random = RandomFactory.getRandom(); - @DataProvider - public static Object[][] lines() { - List l = new ArrayList<>(); + static Stream lines() { + List l = new ArrayList<>(); // Include the three supported optimal-line charsets and one // which does not @@ -175,38 +174,26 @@ public static Object[][] lines() { 1024, charset)); } - return l.toArray(new Object[][]{}); + return l.stream(); } - @Test(dataProvider = "lines") - public void test(String description, - IntFunction lineGenerator, IntFunction separatorGenerator, + @ParameterizedTest + @MethodSource("lines") + public void test(IntFunction lineGenerator, IntFunction separatorGenerator, int lines, Charset cs) throws IOException { Path p = generateTempFileWithLines(lineGenerator, separatorGenerator, lines, cs, false); - Supplier> ss = () -> { - try { - return Files.lines(p, cs); - } - catch (IOException e) { - throw new RuntimeException(e); - } - }; - // Test without a separator at the end List expected = readAllLines(p, cs); - withData(TestData.Factory.ofSupplier("Lines with no separator at end", ss)) - .stream(s -> s) - .expectedResult(expected) - .exercise(); + try (Stream s = Files.lines(p, cs)) { + assertEquals(expected, s.toList()); + } // Test with a separator at the end writeLineSeparator(p, separatorGenerator, lines, cs); expected = readAllLines(p, cs); - withData(TestData.Factory.ofSupplier("Lines with separator at end", ss)) - .stream(s -> s) - .expectedResult(expected) - .exercise(); + try (Stream s = Files.lines(p, cs)) { + assertEquals(expected, s.toList()); + } } - } From ba700f105a1b65db8e905faa146884407ee13257 Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Fri, 27 Mar 2026 16:16:09 +0000 Subject: [PATCH 034/116] 8381059: Add class name to deoptimization events and -Xlog:deoptimization=debug output Reviewed-by: dlong, aseoane --- src/hotspot/share/runtime/deoptimization.cpp | 53 ++++++++++++++------ 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/src/hotspot/share/runtime/deoptimization.cpp b/src/hotspot/share/runtime/deoptimization.cpp index 5fbe2842a2b..cfdcf52a5eb 100644 --- a/src/hotspot/share/runtime/deoptimization.cpp +++ b/src/hotspot/share/runtime/deoptimization.cpp @@ -2021,7 +2021,7 @@ static void post_deoptimization_event(nmethod* nm, #endif // INCLUDE_JFR static void log_deopt(nmethod* nm, Method* tm, intptr_t pc, frame& fr, int trap_bci, - const char* reason_name, const char* reason_action) { + const char* reason_name, const char* reason_action, const char* class_name) { LogTarget(Debug, deoptimization) lt; if (lt.is_enabled()) { LogStream ls(lt); @@ -2035,6 +2035,9 @@ static void log_deopt(nmethod* nm, Method* tm, intptr_t pc, frame& fr, int trap_ } ls.print("%s ", reason_name); ls.print("%s ", reason_action); + if (class_name != nullptr) { + ls.print("%s ", class_name); + } ls.print_cr("pc=" INTPTR_FORMAT " relative_pc=" INTPTR_FORMAT, pc, fr.pc() - nm->code_begin()); } @@ -2135,6 +2138,17 @@ JRT_ENTRY(void, Deoptimization::uncommon_trap_inner(JavaThread* current, jint tr MethodData* trap_mdo = get_method_data(current, profiled_method, create_if_missing); + Symbol* class_name = nullptr; + bool unresolved = false; + if (unloaded_class_index >= 0) { + constantPoolHandle constants (current, trap_method->constants()); + if (constants->tag_at(unloaded_class_index).is_unresolved_klass()) { + class_name = constants->klass_name_at(unloaded_class_index); + unresolved = true; + } else if (constants->tag_at(unloaded_class_index).is_symbol()) { + class_name = constants->symbol_at(unloaded_class_index); + } + } { // Log Deoptimization event for JFR, UL and event system Method* tm = trap_method(); const char* reason_name = trap_reason_name(reason); @@ -2142,10 +2156,24 @@ JRT_ENTRY(void, Deoptimization::uncommon_trap_inner(JavaThread* current, jint tr intptr_t pc = p2i(fr.pc()); JFR_ONLY(post_deoptimization_event(nm, tm, trap_bci, trap_bc, reason, action);) - log_deopt(nm, tm, pc, fr, trap_bci, reason_name, reason_action); - Events::log_deopt_message(current, "Uncommon trap: reason=%s action=%s pc=" INTPTR_FORMAT " method=%s @ %d %s", + + ResourceMark rm; + + const char* class_name_str = nullptr; + const char* class_name_msg = nullptr; + stringStream st, stm; + if (class_name != nullptr) { + class_name->print_symbol_on(&st); + class_name_str = st.freeze(); + stm.print("class=%s ", class_name_str); + class_name_msg = stm.freeze(); + } else { + class_name_msg = ""; + } + log_deopt(nm, tm, pc, fr, trap_bci, reason_name, reason_action, class_name_str); + Events::log_deopt_message(current, "Uncommon trap: reason=%s action=%s pc=" INTPTR_FORMAT " method=%s @ %d %s%s", reason_name, reason_action, pc, - tm->name_and_sig_as_C_string(), trap_bci, nm->compiler_name()); + tm->name_and_sig_as_C_string(), trap_bci, class_name_msg, nm->compiler_name()); } // Print a bunch of diagnostics, if requested. @@ -2173,20 +2201,13 @@ JRT_ENTRY(void, Deoptimization::uncommon_trap_inner(JavaThread* current, jint tr #endif nm->log_identity(xtty); } - Symbol* class_name = nullptr; - bool unresolved = false; - if (unloaded_class_index >= 0) { - constantPoolHandle constants (current, trap_method->constants()); - if (constants->tag_at(unloaded_class_index).is_unresolved_klass()) { - class_name = constants->klass_name_at(unloaded_class_index); - unresolved = true; - if (xtty != nullptr) + if (class_name != nullptr) { + if (xtty != nullptr) { + if (unresolved) { xtty->print(" unresolved='1'"); - } else if (constants->tag_at(unloaded_class_index).is_symbol()) { - class_name = constants->symbol_at(unloaded_class_index); - } - if (xtty != nullptr) + } xtty->name(class_name); + } } if (xtty != nullptr && trap_mdo != nullptr && (int)reason < (int)MethodData::_trap_hist_limit) { // Dump the relevant MDO state. From a4d160e64614fa2f61a57b3eedb333fb665723f5 Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Fri, 27 Mar 2026 16:19:22 +0000 Subject: [PATCH 035/116] 8380828: AOTCodeReader::fix_relocations() should be called before ICache::invalidate_range() is called Reviewed-by: adinn, asmehra --- src/hotspot/share/code/aotCodeCache.cpp | 63 +++++++++++++++---------- src/hotspot/share/code/aotCodeCache.hpp | 17 +++++-- src/hotspot/share/code/codeBlob.cpp | 56 ++++++++++------------ src/hotspot/share/code/codeBlob.hpp | 19 ++++---- 4 files changed, 83 insertions(+), 72 deletions(-) diff --git a/src/hotspot/share/code/aotCodeCache.cpp b/src/hotspot/share/code/aotCodeCache.cpp index 4ad5e12d808..030e2684bfc 100644 --- a/src/hotspot/share/code/aotCodeCache.cpp +++ b/src/hotspot/share/code/aotCodeCache.cpp @@ -539,6 +539,9 @@ AOTCodeReader::AOTCodeReader(AOTCodeCache* cache, AOTCodeEntry* entry) { _load_buffer = cache->cache_buffer(); _read_position = 0; _lookup_failed = false; + _name = nullptr; + _reloc_data = nullptr; + _oop_maps = nullptr; } void AOTCodeReader::set_read_position(uint pos) { @@ -903,8 +906,16 @@ bool AOTCodeCache::store_code_blob(CodeBlob& blob, AOTCodeEntry::Kind entry_kind has_oop_maps = true; } + if (!cache->write_relocations(blob)) { + if (!cache->failed()) { + // We may miss an address in AOT table - skip this code blob. + cache->set_write_position(entry_position); + } + return false; + } + #ifndef PRODUCT - // Write asm remarks + // Write asm remarks after relocation info if (!cache->write_asm_remarks(blob)) { return false; } @@ -913,14 +924,6 @@ bool AOTCodeCache::store_code_blob(CodeBlob& blob, AOTCodeEntry::Kind entry_kind } #endif /* PRODUCT */ - if (!cache->write_relocations(blob)) { - if (!cache->failed()) { - // We may miss an address in AOT table - skip this code blob. - cache->set_write_position(entry_position); - } - return false; - } - uint entry_size = cache->_write_position - entry_position; AOTCodeEntry* entry = new(cache) AOTCodeEntry(entry_kind, encode_id(entry_kind, id), entry_position, entry_size, name_offset, name_size, @@ -982,39 +985,28 @@ CodeBlob* AOTCodeReader::compile_code_blob(const char* name) { set_lookup_failed(); // Skip this blob return nullptr; } + _name = stored_name; // Read archived code blob uint offset = entry_position + _entry->blob_offset(); CodeBlob* archived_blob = (CodeBlob*)addr(offset); offset += archived_blob->size(); - address reloc_data = (address)addr(offset); + _reloc_data = (address)addr(offset); offset += archived_blob->relocation_size(); set_read_position(offset); - ImmutableOopMapSet* oop_maps = nullptr; if (_entry->has_oop_maps()) { - oop_maps = read_oop_map_set(); + _oop_maps = read_oop_map_set(); } - CodeBlob* code_blob = CodeBlob::create(archived_blob, - stored_name, - reloc_data, - oop_maps - ); + // CodeBlob::restore() calls AOTCodeReader::restore() + CodeBlob* code_blob = CodeBlob::create(archived_blob, this); + if (code_blob == nullptr) { // no space left in CodeCache return nullptr; } -#ifndef PRODUCT - code_blob->asm_remarks().init(); - read_asm_remarks(code_blob->asm_remarks()); - code_blob->dbg_strings().init(); - read_dbg_strings(code_blob->dbg_strings()); -#endif // PRODUCT - - fix_relocations(code_blob); - #ifdef ASSERT LogStreamHandle(Trace, aot, codecache, stubs) log; if (log.is_enabled()) { @@ -1025,6 +1017,25 @@ CodeBlob* AOTCodeReader::compile_code_blob(const char* name) { return code_blob; } +void AOTCodeReader::restore(CodeBlob* code_blob) { + precond(AOTCodeCache::is_on_for_use()); + precond(_name != nullptr); + precond(_reloc_data != nullptr); + + code_blob->set_name(_name); + code_blob->restore_mutable_data(_reloc_data); + code_blob->set_oop_maps(_oop_maps); + + fix_relocations(code_blob); + +#ifndef PRODUCT + code_blob->asm_remarks().init(); + read_asm_remarks(code_blob->asm_remarks()); + code_blob->dbg_strings().init(); + read_dbg_strings(code_blob->dbg_strings()); +#endif // PRODUCT +} + // ------------ process code and data -------------- // Can't use -1. It is valid value for jump to iteself destination diff --git a/src/hotspot/share/code/aotCodeCache.hpp b/src/hotspot/share/code/aotCodeCache.hpp index 7996388faa6..b0d39ff3e08 100644 --- a/src/hotspot/share/code/aotCodeCache.hpp +++ b/src/hotspot/share/code/aotCodeCache.hpp @@ -402,11 +402,13 @@ class AOTCodeReader { void clear_lookup_failed() { _lookup_failed = false; } bool lookup_failed() const { return _lookup_failed; } - AOTCodeEntry* aot_code_entry() { return (AOTCodeEntry*)_entry; } -public: - AOTCodeReader(AOTCodeCache* cache, AOTCodeEntry* entry); + // Values used by restore(code_blob). + // They should be set before calling it. + const char* _name; + address _reloc_data; + ImmutableOopMapSet* _oop_maps; - CodeBlob* compile_code_blob(const char* name); + AOTCodeEntry* aot_code_entry() { return (AOTCodeEntry*)_entry; } ImmutableOopMapSet* read_oop_map_set(); @@ -415,6 +417,13 @@ class AOTCodeReader { void read_asm_remarks(AsmRemarks& asm_remarks); void read_dbg_strings(DbgStrings& dbg_strings); #endif // PRODUCT + +public: + AOTCodeReader(AOTCodeCache* cache, AOTCodeEntry* entry); + + CodeBlob* compile_code_blob(const char* name); + + void restore(CodeBlob* code_blob); }; // code cache internal runtime constants area used by AOT code diff --git a/src/hotspot/share/code/codeBlob.cpp b/src/hotspot/share/code/codeBlob.cpp index fcc0b42a461..5b68ce48c87 100644 --- a/src/hotspot/share/code/codeBlob.cpp +++ b/src/hotspot/share/code/codeBlob.cpp @@ -22,6 +22,7 @@ * */ +#include "code/aotCodeCache.hpp" #include "code/codeBlob.hpp" #include "code/codeCache.hpp" #include "code/relocInfo.hpp" @@ -188,22 +189,6 @@ CodeBlob::CodeBlob(const char* name, CodeBlobKind kind, int size, uint16_t heade assert(_mutable_data == blob_end(), "sanity"); } -void CodeBlob::restore_mutable_data(address reloc_data) { - // Relocation data is now stored as part of the mutable data area; allocate it before copy relocations - if (_mutable_data_size > 0) { - _mutable_data = (address)os::malloc(_mutable_data_size, mtCode); - if (_mutable_data == nullptr) { - vm_exit_out_of_memory(_mutable_data_size, OOM_MALLOC_ERROR, "codebuffer: no space for mutable data"); - } - } else { - _mutable_data = blob_end(); // default value - } - if (_relocation_size > 0) { - assert(_mutable_data_size > 0, "relocation is part of mutable data section"); - memcpy((address)relocation_begin(), reloc_data, relocation_size()); - } -} - void CodeBlob::purge() { assert(_mutable_data != nullptr, "should never be null"); if (_mutable_data != blob_end()) { @@ -240,6 +225,23 @@ void CodeBlob::print_code_on(outputStream* st) { Disassembler::decode(this, st); } +#if INCLUDE_CDS +void CodeBlob::restore_mutable_data(address reloc_data) { + // Relocation data is now stored as part of the mutable data area; allocate it before copy relocations + if (_mutable_data_size > 0) { + _mutable_data = (address)os::malloc(_mutable_data_size, mtCode); + if (_mutable_data == nullptr) { + vm_exit_out_of_memory(_mutable_data_size, OOM_MALLOC_ERROR, "codebuffer: no space for mutable data"); + } + } else { + _mutable_data = blob_end(); // default value + } + if (_relocation_size > 0) { + assert(_mutable_data_size > 0, "relocation is part of mutable data section"); + memcpy((address)relocation_begin(), reloc_data, relocation_size()); + } +} + void CodeBlob::prepare_for_archiving_impl() { set_name(nullptr); _oop_maps = nullptr; @@ -269,24 +271,15 @@ void CodeBlob::post_restore() { vptr(_kind)->post_restore(this); } -CodeBlob* CodeBlob::restore(address code_cache_buffer, - const char* name, - address archived_reloc_data, - ImmutableOopMapSet* archived_oop_maps) +CodeBlob* CodeBlob::restore(address code_cache_buffer, AOTCodeReader* reader) { copy_to(code_cache_buffer); CodeBlob* code_blob = (CodeBlob*)code_cache_buffer; - code_blob->set_name(name); - code_blob->restore_mutable_data(archived_reloc_data); - code_blob->set_oop_maps(archived_oop_maps); + reader->restore(code_blob); return code_blob; } -CodeBlob* CodeBlob::create(CodeBlob* archived_blob, - const char* name, - address archived_reloc_data, - ImmutableOopMapSet* archived_oop_maps - ) +CodeBlob* CodeBlob::create(CodeBlob* archived_blob, AOTCodeReader* reader) { ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock @@ -298,10 +291,7 @@ CodeBlob* CodeBlob::create(CodeBlob* archived_blob, MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); address code_cache_buffer = (address)CodeCache::allocate(size, CodeBlobType::NonNMethod); if (code_cache_buffer != nullptr) { - blob = archived_blob->restore(code_cache_buffer, - name, - archived_reloc_data, - archived_oop_maps); + blob = archived_blob->restore(code_cache_buffer, reader); assert(blob != nullptr, "sanity check"); // Flush the code block @@ -315,6 +305,8 @@ CodeBlob* CodeBlob::create(CodeBlob* archived_blob, return blob; } +#endif // INCLUDE_CDS + //----------------------------------------------------------------------------------------- // Creates a RuntimeBlob from a CodeBuffer and copy code and relocation info. diff --git a/src/hotspot/share/code/codeBlob.hpp b/src/hotspot/share/code/codeBlob.hpp index 0469b6c71b1..1f9cf0adcc3 100644 --- a/src/hotspot/share/code/codeBlob.hpp +++ b/src/hotspot/share/code/codeBlob.hpp @@ -34,6 +34,7 @@ #include "utilities/align.hpp" #include "utilities/macros.hpp" +class AOTCodeReader; class ImmutableOopMap; class ImmutableOopMapSet; class JNIHandleBlock; @@ -107,9 +108,6 @@ class CodeBlob { friend class VMStructs; friend class JVMCIVMStructs; -private: - void restore_mutable_data(address reloc_data); - protected: // order fields from large to small to minimize padding between fields ImmutableOopMapSet* _oop_maps; // OopMap for this CodeBlob @@ -169,8 +167,8 @@ class CodeBlob { void operator delete(void* p) { } - void prepare_for_archiving_impl(); - void post_restore_impl(); + void prepare_for_archiving_impl() NOT_CDS_RETURN; + void post_restore_impl() NOT_CDS_RETURN; public: @@ -304,6 +302,9 @@ class CodeBlob { void use_strings(DbgStrings &strings) { _dbg_strings.share(strings); } #endif +#if INCLUDE_CDS + void restore_mutable_data(address reloc_data); + void copy_to(address buffer) { memcpy(buffer, this, this->size()); } @@ -314,11 +315,9 @@ class CodeBlob { // methods to restore a blob from AOT code cache into the CodeCache void post_restore(); - CodeBlob* restore(address code_cache_buffer, const char* name, address archived_reloc_data, ImmutableOopMapSet* archived_oop_maps); - static CodeBlob* create(CodeBlob* archived_blob, - const char* name, - address archived_reloc_data, - ImmutableOopMapSet* archived_oop_maps); + CodeBlob* restore(address code_cache_buffer, AOTCodeReader* reader); + static CodeBlob* create(CodeBlob* archived_blob, AOTCodeReader* reader); +#endif }; //---------------------------------------------------------------------------------------------------- From 28e96d76b0c7a792cc88bb9183e9cb6a83fcaba2 Mon Sep 17 00:00:00 2001 From: William Kemper Date: Fri, 27 Mar 2026 17:57:30 +0000 Subject: [PATCH 036/116] 8377976: GenShen: Explicit GC requests must clear concurrent gc request cancellation Reviewed-by: kdnilsen --- .../shenandoah/shenandoahGenerationalControlThread.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp index ec33e671053..064f43ffd6b 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp @@ -121,10 +121,11 @@ void ShenandoahGenerationalControlThread::check_for_request(ShenandoahGCRequest& assert(request.generation != nullptr, "Must know which generation to use for degenerated cycle"); } } else { - if (request.cause == GCCause::_shenandoah_concurrent_gc) { - // This is a regulator request. It is also possible that the regulator "canceled" an old mark, - // so we can clear that here. This clear operation will only clear the cancellation if it is - // a regulator request. + if (request.cause == GCCause::_shenandoah_concurrent_gc || ShenandoahCollectorPolicy::is_explicit_gc(request.cause)) { + // This is a regulator request or an explicit gc request. Note that an explicit gc request is allowed to + // "upgrade" a regulator request. It is possible that the regulator "canceled" an old mark, so we must + // clear that cancellation here or the explicit gc cycle will erroneously detect it as a cancellation. + // This clear operation will only clear the cancellation if it was set by regulator request. _heap->clear_cancellation(GCCause::_shenandoah_concurrent_gc); } request.generation = _requested_generation; From 79668b007db71921938d7639ba15f8ce44682f4f Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Fri, 27 Mar 2026 18:13:38 +0000 Subject: [PATCH 037/116] 8380710: nmethod::finalize_relocations() should be called before ICache::invalidate_range() is called Reviewed-by: adinn, dlong --- src/hotspot/share/asm/codeBuffer.cpp | 4 ---- src/hotspot/share/code/codeBlob.cpp | 4 ++++ src/hotspot/share/code/nmethod.cpp | 6 ++++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/hotspot/share/asm/codeBuffer.cpp b/src/hotspot/share/asm/codeBuffer.cpp index ba525588f32..c6078c0ceee 100644 --- a/src/hotspot/share/asm/codeBuffer.cpp +++ b/src/hotspot/share/asm/codeBuffer.cpp @@ -32,7 +32,6 @@ #include "oops/methodCounters.hpp" #include "oops/methodData.hpp" #include "oops/oop.inline.hpp" -#include "runtime/icache.hpp" #include "runtime/safepointVerifiers.hpp" #include "utilities/align.hpp" #include "utilities/copy.hpp" @@ -745,9 +744,6 @@ void CodeBuffer::copy_code_to(CodeBlob* dest_blob) { // Done moving code bytes; were they the right size? assert((int)align_up(dest.total_content_size(), oopSize) == dest_blob->content_size(), "sanity"); - - // Flush generated code - ICache::invalidate_range(dest_blob->code_begin(), dest_blob->code_size()); } // Move all my code into another code buffer. Consult applicable diff --git a/src/hotspot/share/code/codeBlob.cpp b/src/hotspot/share/code/codeBlob.cpp index 5b68ce48c87..9961381c31d 100644 --- a/src/hotspot/share/code/codeBlob.cpp +++ b/src/hotspot/share/code/codeBlob.cpp @@ -40,6 +40,7 @@ #include "prims/forte.hpp" #include "prims/jvmtiExport.hpp" #include "runtime/handles.inline.hpp" +#include "runtime/icache.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/javaFrameAnchor.hpp" #include "runtime/jniHandles.inline.hpp" @@ -324,6 +325,9 @@ RuntimeBlob::RuntimeBlob( align_up(cb->total_relocation_size(), oopSize)) { cb->copy_code_and_locs_to(this); + + // Flush generated code + ICache::invalidate_range(code_begin(), code_size()); } void RuntimeBlob::free(RuntimeBlob* blob) { diff --git a/src/hotspot/share/code/nmethod.cpp b/src/hotspot/share/code/nmethod.cpp index 5a6ed8ab3ed..0e2aa208854 100644 --- a/src/hotspot/share/code/nmethod.cpp +++ b/src/hotspot/share/code/nmethod.cpp @@ -66,6 +66,7 @@ #include "runtime/flags/flagSetting.hpp" #include "runtime/frame.inline.hpp" #include "runtime/handles.inline.hpp" +#include "runtime/icache.hpp" #include "runtime/jniHandles.inline.hpp" #include "runtime/orderAccess.hpp" #include "runtime/os.hpp" @@ -1253,6 +1254,9 @@ void nmethod::post_init() { finalize_relocations(); + // Flush generated code + ICache::invalidate_range(code_begin(), code_size()); + Universe::heap()->register_nmethod(this); DEBUG_ONLY(Universe::heap()->verify_nmethod(this)); @@ -1584,8 +1588,6 @@ nmethod* nmethod::relocate(CodeBlobType code_blob_type) { // Attempt to start using the copy if (nm_copy->make_in_use()) { - ICache::invalidate_range(nm_copy->code_begin(), nm_copy->code_size()); - methodHandle mh(Thread::current(), nm_copy->method()); nm_copy->method()->set_code(mh, nm_copy); From 7ffc4a4fb4cc520c4f469865645764045e72cb26 Mon Sep 17 00:00:00 2001 From: Phil Race Date: Fri, 27 Mar 2026 19:23:39 +0000 Subject: [PATCH 038/116] 8381019: Remove AppContext usage from AccessBridge Reviewed-by: serb, kizune --- .../accessibility/AccessibleContext.java | 19 +--- .../share/classes/module-info.java | 3 +- .../share/classes/sun/awt/AWTAccessor.java | 2 - .../accessibility/internal/AccessBridge.java | 89 +++---------------- 4 files changed, 13 insertions(+), 100 deletions(-) diff --git a/src/java.desktop/share/classes/javax/accessibility/AccessibleContext.java b/src/java.desktop/share/classes/javax/accessibility/AccessibleContext.java index 096ca3aef44..e7fc58b0825 100644 --- a/src/java.desktop/share/classes/javax/accessibility/AccessibleContext.java +++ b/src/java.desktop/share/classes/javax/accessibility/AccessibleContext.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,7 +34,6 @@ import java.util.Locale; import sun.awt.AWTAccessor; -import sun.awt.AppContext; /** * {@code AccessibleContext} represents the minimum information all accessible @@ -84,24 +83,8 @@ public abstract class AccessibleContext { */ protected AccessibleContext() {} - /** - * The {@code AppContext} that should be used to dispatch events for this - * {@code AccessibleContext}. - */ - private volatile AppContext targetAppContext; - static { AWTAccessor.setAccessibleContextAccessor(new AWTAccessor.AccessibleContextAccessor() { - @Override - public void setAppContext(AccessibleContext accessibleContext, AppContext appContext) { - accessibleContext.targetAppContext = appContext; - } - - @Override - public AppContext getAppContext(AccessibleContext accessibleContext) { - return accessibleContext.targetAppContext; - } - @Override public Object getNativeAXResource(AccessibleContext accessibleContext) { return accessibleContext.nativeAXResource; diff --git a/src/java.desktop/share/classes/module-info.java b/src/java.desktop/share/classes/module-info.java index 6d34d934194..57392f71321 100644 --- a/src/java.desktop/share/classes/module-info.java +++ b/src/java.desktop/share/classes/module-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -115,7 +115,6 @@ // qualified exports may be inserted at build time // see make/GensrcModuleInfo.gmk exports sun.awt to - jdk.accessibility, jdk.unsupported.desktop; exports java.awt.dnd.peer to jdk.unsupported.desktop; diff --git a/src/java.desktop/share/classes/sun/awt/AWTAccessor.java b/src/java.desktop/share/classes/sun/awt/AWTAccessor.java index f98118171b4..143d7e6198c 100644 --- a/src/java.desktop/share/classes/sun/awt/AWTAccessor.java +++ b/src/java.desktop/share/classes/sun/awt/AWTAccessor.java @@ -755,8 +755,6 @@ public interface SystemColorAccessor { * An accessor object for the AccessibleContext class */ public interface AccessibleContextAccessor { - void setAppContext(AccessibleContext accessibleContext, AppContext appContext); - AppContext getAppContext(AccessibleContext accessibleContext); Object getNativeAXResource(AccessibleContext accessibleContext); void setNativeAXResource(AccessibleContext accessibleContext, Object value); } 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 c932d0f73ff..718acf6a6b8 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -120,9 +120,6 @@ import com.sun.java.accessibility.util.EventQueueMonitor; import com.sun.java.accessibility.util.SwingEventMonitor; import com.sun.java.accessibility.util.Translator; -import sun.awt.AWTAccessor; -import sun.awt.AppContext; -import sun.awt.SunToolkit; /* * Note: This class has to be public. It's loaded from the VM like this: @@ -5292,7 +5289,6 @@ public void propertyChange(PropertyChangeEvent e) { ac = a.getAccessibleContext(); } if (ac != null) { - InvocationUtils.registerAccessibleContext(ac, AppContext.getAppContext()); accessBridge.debugString("[INFO]: AccessibleContext: " + ac); String propertyName = e.getPropertyName(); @@ -5385,11 +5381,9 @@ public void propertyChange(PropertyChangeEvent e) { if (e.getOldValue() instanceof AccessibleContext) { oldAC = (AccessibleContext) e.getOldValue(); - InvocationUtils.registerAccessibleContext(oldAC, AppContext.getAppContext()); } if (e.getNewValue() instanceof AccessibleContext) { newAC = (AccessibleContext) e.getNewValue(); - InvocationUtils.registerAccessibleContext(newAC, AppContext.getAppContext()); } accessBridge.debugString("[INFO]: - about to call propertyChildChange() old AC: " + oldAC + "new AC: " + newAC); accessBridge.propertyChildChange(e, ac, oldAC, newAC); @@ -5455,8 +5449,6 @@ private void handleActiveDescendentEvent(PropertyChangeEvent e, prevAC = newAC; accessBridge.debugString("[INFO]: - about to call propertyActiveDescendentChange() AC: " + ac + " old AC: " + oldAC + "new AC: " + newAC); - InvocationUtils.registerAccessibleContext(oldAC, AppContext.getAppContext()); - InvocationUtils.registerAccessibleContext(newAC, AppContext.getAppContext()); accessBridge.propertyActiveDescendentChange(e, ac, oldAC, newAC); } @@ -5493,14 +5485,12 @@ private void processFocusGained() { // selected. The menu itself is selected. FocusEvent e = new FocusEvent(penult, FocusEvent.FOCUS_GAINED); AccessibleContext context = penult.getAccessibleContext(); - InvocationUtils.registerAccessibleContext(context, SunToolkit.targetToAppContext(penult)); accessBridge.focusGained(e, context); } else if (penult instanceof JPopupMenu) { // This is a popup with an item selected FocusEvent e = new FocusEvent(last, FocusEvent.FOCUS_GAINED); AccessibleContext focusedAC = last.getAccessibleContext(); - InvocationUtils.registerAccessibleContext(focusedAC, SunToolkit.targetToAppContext(last)); accessBridge.debugString("[INFO]: - about to call focusGained() AC: " + focusedAC); accessBridge.focusGained(e, focusedAC); } @@ -5511,7 +5501,6 @@ private void processFocusGained() { FocusEvent e = new FocusEvent(focusOwner, FocusEvent.FOCUS_GAINED); AccessibleContext focusedAC = focusOwner.getAccessibleContext(); - InvocationUtils.registerAccessibleContext(focusedAC, SunToolkit.targetToAppContext(focusOwner)); accessBridge.debugString("[INFO]: - about to call focusGained() AC: " + focusedAC); accessBridge.focusGained(e, focusedAC); } @@ -5524,7 +5513,6 @@ public void focusLost(FocusEvent e) { if (a != null) { accessBridge.debugString("[INFO]: - about to call focusLost() AC: " + a.getAccessibleContext()); AccessibleContext context = a.getAccessibleContext(); - InvocationUtils.registerAccessibleContext(context, AppContext.getAppContext()); accessBridge.focusLost(e, context); } } @@ -5538,7 +5526,6 @@ public void caretUpdate(CaretEvent e) { Accessible a = Translator.getAccessible(e.getSource()); if (a != null) { AccessibleContext context = a.getAccessibleContext(); - InvocationUtils.registerAccessibleContext(context, AppContext.getAppContext()); accessBridge.caretUpdate(e, context); } } @@ -5553,7 +5540,6 @@ public void mouseClicked(MouseEvent e) { Accessible a = Translator.getAccessible(e.getSource()); if (a != null) { AccessibleContext context = a.getAccessibleContext(); - InvocationUtils.registerAccessibleContext(context, AppContext.getAppContext()); accessBridge.mouseClicked(e, context); } } @@ -5564,7 +5550,6 @@ public void mouseEntered(MouseEvent e) { Accessible a = Translator.getAccessible(e.getSource()); if (a != null) { AccessibleContext context = a.getAccessibleContext(); - InvocationUtils.registerAccessibleContext(context, AppContext.getAppContext()); accessBridge.mouseEntered(e, context); } } @@ -5575,7 +5560,6 @@ public void mouseExited(MouseEvent e) { Accessible a = Translator.getAccessible(e.getSource()); if (a != null) { AccessibleContext context = a.getAccessibleContext(); - InvocationUtils.registerAccessibleContext(context, AppContext.getAppContext()); accessBridge.mouseExited(e, context); } } @@ -5586,7 +5570,6 @@ public void mousePressed(MouseEvent e) { Accessible a = Translator.getAccessible(e.getSource()); if (a != null) { AccessibleContext context = a.getAccessibleContext(); - InvocationUtils.registerAccessibleContext(context, AppContext.getAppContext()); accessBridge.mousePressed(e, context); } } @@ -5597,7 +5580,6 @@ public void mouseReleased(MouseEvent e) { Accessible a = Translator.getAccessible(e.getSource()); if (a != null) { AccessibleContext context = a.getAccessibleContext(); - InvocationUtils.registerAccessibleContext(context, AppContext.getAppContext()); accessBridge.mouseReleased(e, context); } } @@ -5611,7 +5593,6 @@ public void menuCanceled(MenuEvent e) { Accessible a = Translator.getAccessible(e.getSource()); if (a != null) { AccessibleContext context = a.getAccessibleContext(); - InvocationUtils.registerAccessibleContext(context, AppContext.getAppContext()); accessBridge.menuCanceled(e, context); } } @@ -5622,7 +5603,6 @@ public void menuDeselected(MenuEvent e) { Accessible a = Translator.getAccessible(e.getSource()); if (a != null) { AccessibleContext context = a.getAccessibleContext(); - InvocationUtils.registerAccessibleContext(context, AppContext.getAppContext()); accessBridge.menuDeselected(e, context); } } @@ -5633,7 +5613,6 @@ public void menuSelected(MenuEvent e) { Accessible a = Translator.getAccessible(e.getSource()); if (a != null) { AccessibleContext context = a.getAccessibleContext(); - InvocationUtils.registerAccessibleContext(context, AppContext.getAppContext()); accessBridge.menuSelected(e, context); } } @@ -5644,7 +5623,6 @@ public void popupMenuCanceled(PopupMenuEvent e) { Accessible a = Translator.getAccessible(e.getSource()); if (a != null) { AccessibleContext context = a.getAccessibleContext(); - InvocationUtils.registerAccessibleContext(context, AppContext.getAppContext()); accessBridge.popupMenuCanceled(e, context); } } @@ -5655,7 +5633,6 @@ public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { Accessible a = Translator.getAccessible(e.getSource()); if (a != null) { AccessibleContext context = a.getAccessibleContext(); - InvocationUtils.registerAccessibleContext(context, AppContext.getAppContext()); accessBridge.popupMenuWillBecomeInvisible(e, context); } } @@ -5666,7 +5643,6 @@ public void popupMenuWillBecomeVisible(PopupMenuEvent e) { Accessible a = Translator.getAccessible(e.getSource()); if (a != null) { AccessibleContext context = a.getAccessibleContext(); - InvocationUtils.registerAccessibleContext(context, AppContext.getAppContext()); accessBridge.popupMenuWillBecomeVisible(e, context); } } @@ -7227,8 +7203,7 @@ public boolean doAccessibleAction(int i) { private static class InvocationUtils { /** - * Invokes a {@code Callable} in the {@code AppContext} of the given {@code Accessible} - * and waits for it to finish blocking the caller thread. + * Invokes a {@code Callable} and waits for it to finish blocking the caller thread. * * @param callable the {@code Callable} to invoke * @param accessibleTable the {@code AccessibleExtendedTable} which would be used to find the right context @@ -7246,8 +7221,7 @@ public static T invokeAndWait(final Callable callable, } /** - * Invokes a {@code Callable} in the {@code AppContext} of the given {@code Accessible} - * and waits for it to finish blocking the caller thread. + * Invokes a {@code Callable} and waits for it to finish blocking the caller thread. * * @param callable the {@code Callable} to invoke * @param accessible the {@code Accessible} which would be used to find the right context @@ -7269,8 +7243,7 @@ public static T invokeAndWait(final Callable callable, } /** - * Invokes a {@code Callable} in the {@code AppContext} of the given {@code Component} - * and waits for it to finish blocking the caller thread. + * Invokes a {@code Callable} and waits for it to finish blocking the caller thread. * * @param callable the {@code Callable} to invoke * @param component the {@code Component} which would be used to find the right context @@ -7281,12 +7254,11 @@ public static T invokeAndWait(final Callable callable, */ public static T invokeAndWait(final Callable callable, final Component component) { - return invokeAndWait(callable, SunToolkit.targetToAppContext(component)); + return invokeAndWait(callable); } /** - * Invokes a {@code Callable} in the {@code AppContext} mapped to the given {@code AccessibleContext} - * and waits for it to finish blocking the caller thread. + * Invokes a {@code Callable} and waits for it to finish blocking the caller thread. * * @param callable the {@code Callable} to invoke * @param accessibleContext the {@code AccessibleContext} which would be used to determine the right @@ -7297,45 +7269,26 @@ public static T invokeAndWait(final Callable callable, */ public static T invokeAndWait(final Callable callable, final AccessibleContext accessibleContext) { - AppContext targetContext = AWTAccessor.getAccessibleContextAccessor() - .getAppContext(accessibleContext); - if (targetContext != null) { - return invokeAndWait(callable, targetContext); - } else { - // Normally this should not happen, unmapped context provided and - // the target AppContext is unknown. - - // Try to recover in case the context is a translator. - if (accessibleContext instanceof Translator) { - Object source = ((Translator)accessibleContext).getSource(); - if (source instanceof Component) { - return invokeAndWait(callable, (Component)source); - } - } - } - throw new RuntimeException("Unmapped AccessibleContext used to dispatch event: " + accessibleContext); + return invokeAndWait(callable); } - private static T invokeAndWait(final Callable callable, - final AppContext targetAppContext) { + private static T invokeAndWait(final Callable callable) { final CallableWrapper wrapper = new CallableWrapper(callable); try { - invokeAndWait(wrapper, targetAppContext); + invokeAndWait(wrapper); T result = wrapper.getResult(); - updateAppContextMap(result, targetAppContext); return result; } catch (final Exception e) { throw new RuntimeException(e); } } - private static void invokeAndWait(final Runnable runnable, - final AppContext appContext) + private static void invokeAndWait(final Runnable runnable) throws InterruptedException, InvocationTargetException { - EventQueue eq = SunToolkit.getSystemEventQueueImplPP(appContext); Object lock = new Object(); Toolkit source = Toolkit.getDefaultToolkit(); + EventQueue eq = source.getSystemEventQueue(); InvocationEvent event = new InvocationEvent(source, runnable, lock, true); synchronized (lock) { @@ -7349,26 +7302,6 @@ private static void invokeAndWait(final Runnable runnable, } } - /** - * Maps the {@code AccessibleContext} to the {@code AppContext} which should be used - * to dispatch events related to the {@code AccessibleContext} - * @param accessibleContext the {@code AccessibleContext} for the mapping - * @param targetContext the {@code AppContext} for the mapping - */ - public static void registerAccessibleContext(final AccessibleContext accessibleContext, - final AppContext targetContext) { - if (accessibleContext != null) { - AWTAccessor.getAccessibleContextAccessor().setAppContext(accessibleContext, targetContext); - } - } - - private static void updateAppContextMap(final T accessibleContext, - final AppContext targetContext) { - if (accessibleContext instanceof AccessibleContext) { - registerAccessibleContext((AccessibleContext)accessibleContext, targetContext); - } - } - private static class CallableWrapper implements Runnable { private final Callable callable; private volatile T object; From 7e4ac140d9faad938bda3e60a00cc5e8ed0fe7d7 Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Fri, 27 Mar 2026 19:55:32 +0000 Subject: [PATCH 039/116] 8380686: GenerateOopMap logging crashes in rewriter Reviewed-by: matsaave, phubner --- .../share/interpreter/bytecodeTracer.cpp | 30 +++++++------ .../jtreg/runtime/interpreter/JsrLogging.jasm | 43 +++++++++++++++++++ .../runtime/interpreter/JsrLoggingTest.java | 40 +++++++++++++++++ 3 files changed, 99 insertions(+), 14 deletions(-) create mode 100644 test/hotspot/jtreg/runtime/interpreter/JsrLogging.jasm create mode 100644 test/hotspot/jtreg/runtime/interpreter/JsrLoggingTest.java diff --git a/src/hotspot/share/interpreter/bytecodeTracer.cpp b/src/hotspot/share/interpreter/bytecodeTracer.cpp index 2610a8a2bd6..4578a3eec4e 100644 --- a/src/hotspot/share/interpreter/bytecodeTracer.cpp +++ b/src/hotspot/share/interpreter/bytecodeTracer.cpp @@ -52,9 +52,9 @@ class BytecodePrinter { Bytecodes::Code _code; address _next_pc; // current decoding position int _flags; - bool _is_linked; + bool _use_cp_cache; - bool is_linked() const { return _is_linked; } + bool use_cp_cache() const { return _use_cp_cache; } void align() { _next_pc = align_up(_next_pc, sizeof(jint)); } int get_byte() { return *(jbyte*) _next_pc++; } // signed int get_index_u1() { return *(address)_next_pc++; } // returns 0x00 - 0xff as an int @@ -69,7 +69,7 @@ class BytecodePrinter { bool is_wide() const { return _is_wide; } Bytecodes::Code raw_code() const { return Bytecodes::Code(_code); } ConstantPool* constants() const { return method()->constants(); } - ConstantPoolCache* cpcache() const { assert(is_linked(), "must be"); return constants()->cache(); } + ConstantPoolCache* cpcache() const { assert(use_cp_cache(), "must be"); return constants()->cache(); } void print_constant(int i, outputStream* st); void print_cpcache_entry(int cpc_index, outputStream* st); @@ -94,8 +94,9 @@ class BytecodePrinter { ResourceMark rm; bool method_changed = _current_method != method(); _current_method = method(); - _is_linked = method->method_holder()->is_linked(); - assert(_is_linked, "this function must be called on methods that are already executing"); + _use_cp_cache = method->constants()->cache() != nullptr; + assert(method->method_holder()->is_linked(), + "this function must be called on methods that are already executing"); if (method_changed) { // Note 1: This code will not work as expected with true MT/MP. @@ -150,7 +151,8 @@ class BytecodePrinter { // BytecodeStream, which will skip wide bytecodes. void trace(const methodHandle& method, address bcp, outputStream* st) { _current_method = method(); - _is_linked = method->method_holder()->is_linked(); + // This may be called during linking after bytecodes are rewritten to point to the cpCache. + _use_cp_cache = method->constants()->cache() != nullptr; ResourceMark rm; Bytecodes::Code code = Bytecodes::code_at(method(), bcp); // Set is_wide @@ -301,7 +303,7 @@ void BytecodePrinter::print_invokedynamic(int indy_index, int cp_index, outputSt if (ClassPrinter::has_mode(_flags, ClassPrinter::PRINT_DYNAMIC)) { print_bsm(cp_index, st); - if (is_linked()) { + if (use_cp_cache()) { ResolvedIndyEntry* indy_entry = constants()->resolved_indy_entry_at(indy_index); st->print(" ResolvedIndyEntry: "); indy_entry->print_on(st); @@ -365,7 +367,7 @@ void BytecodePrinter::print_attributes(int bci, outputStream* st) { { int cp_index; if (Bytecodes::uses_cp_cache(raw_code())) { - assert(is_linked(), "fast ldc bytecode must be in linked classes"); + assert(use_cp_cache(), "fast ldc bytecode must be in linked classes"); int obj_index = get_index_u1(); cp_index = constants()->object_to_cp_index(obj_index); } else { @@ -380,7 +382,7 @@ void BytecodePrinter::print_attributes(int bci, outputStream* st) { { int cp_index; if (Bytecodes::uses_cp_cache(raw_code())) { - assert(is_linked(), "fast ldc bytecode must be in linked classes"); + assert(use_cp_cache(), "fast ldc bytecode must be in linked classes"); int obj_index = get_native_index_u2(); cp_index = constants()->object_to_cp_index(obj_index); } else { @@ -510,7 +512,7 @@ void BytecodePrinter::print_attributes(int bci, outputStream* st) { case Bytecodes::_getfield: { int cp_index; - if (is_linked()) { + if (use_cp_cache()) { int field_index = get_native_index_u2(); cp_index = cpcache()->resolved_field_entry_at(field_index)->constant_pool_index(); } else { @@ -525,7 +527,7 @@ void BytecodePrinter::print_attributes(int bci, outputStream* st) { case Bytecodes::_invokestatic: { int cp_index; - if (is_linked()) { + if (use_cp_cache()) { int method_index = get_native_index_u2(); ResolvedMethodEntry* method_entry = cpcache()->resolved_method_entry_at(method_index); cp_index = method_entry->constant_pool_index(); @@ -533,7 +535,7 @@ void BytecodePrinter::print_attributes(int bci, outputStream* st) { if (raw_code() == Bytecodes::_invokehandle && ClassPrinter::has_mode(_flags, ClassPrinter::PRINT_METHOD_HANDLE)) { - assert(is_linked(), "invokehandle is only in rewritten methods"); + assert(use_cp_cache(), "invokehandle is only in rewritten methods"); method_entry->print_on(st); if (method_entry->has_appendix()) { st->print(" appendix: "); @@ -550,7 +552,7 @@ void BytecodePrinter::print_attributes(int bci, outputStream* st) { case Bytecodes::_invokeinterface: { int cp_index; - if (is_linked()) { + if (use_cp_cache()) { int method_index = get_native_index_u2(); cp_index = cpcache()->resolved_method_entry_at(method_index)->constant_pool_index(); } else { @@ -566,7 +568,7 @@ void BytecodePrinter::print_attributes(int bci, outputStream* st) { { int indy_index; int cp_index; - if (is_linked()) { + if (use_cp_cache()) { indy_index = get_native_index_u4(); cp_index = constants()->resolved_indy_entry_at(indy_index)->constant_pool_index(); } else { diff --git a/test/hotspot/jtreg/runtime/interpreter/JsrLogging.jasm b/test/hotspot/jtreg/runtime/interpreter/JsrLogging.jasm new file mode 100644 index 00000000000..ac1d0fffa49 --- /dev/null +++ b/test/hotspot/jtreg/runtime/interpreter/JsrLogging.jasm @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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. + * + */ + +public super class JsrLogging version 49:0 +{ + static Field i:I; + + public static Method test:"()V" + stack 3 locals 1 + { + nop; + jsr LABEL; + bipush 66; + LABEL: + bipush 55; + putstatic Field i:"I"; + getstatic Field java/lang/System.out:"Ljava/io/PrintStream;"; + ldc String "hello"; + invokevirtual Method java/io/PrintStream.println:"(Ljava/lang/String;)V"; + return; + } +} diff --git a/test/hotspot/jtreg/runtime/interpreter/JsrLoggingTest.java b/test/hotspot/jtreg/runtime/interpreter/JsrLoggingTest.java new file mode 100644 index 00000000000..36a8f7e9b76 --- /dev/null +++ b/test/hotspot/jtreg/runtime/interpreter/JsrLoggingTest.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 8380686 + * @summary Ensure logging works while processing jsr while linking. + * @library /test/lib + * @compile JsrLogging.jasm + * @run main/othervm -Xlog:generateoopmap=debug JsrLoggingTest + */ + +public class JsrLoggingTest { + public static void main(String[] args) { + for (int i = 0; i < 10; ++i) { + JsrLogging.test(); + } + System.out.println("PASSED"); + } +} From ac242550fea72a3c37e61014f5204f72e27e2cbd Mon Sep 17 00:00:00 2001 From: Jeremy Wood Date: Sat, 28 Mar 2026 09:33:31 +0000 Subject: [PATCH 040/116] 8379347: VoiceOver Doesn't Correctly Identify JToggleButtons as "toggle buttons" Reviewed-by: honkar, kizune, prr --- .../awt/a11y/CheckboxAccessibility.m | 14 +++- .../awt/a11y/CommonComponentAccessibility.m | 1 + .../8379347/VoiceOverToggleButtonRole.java | 69 +++++++++++++++++++ 3 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 test/jdk/javax/accessibility/8379347/VoiceOverToggleButtonRole.java diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CheckboxAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CheckboxAccessibility.m index f2dbf60d92d..a5faf255440 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CheckboxAccessibility.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CheckboxAccessibility.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,6 +36,18 @@ - (NSAccessibilityRole _Nonnull)accessibilityRole return NSAccessibilityCheckBoxRole; } +- (NSAccessibilitySubrole _Nullable)accessibilitySubrole +{ + JNIEnv *env = [ThreadUtilities getJNIEnv]; + if (env != NULL) { + NSString *javaRole = [self javaRole]; + if ([javaRole isEqualToString:@"togglebutton"]) { + return NSAccessibilityToggleSubrole; + } + } + return [super accessibilitySubrole]; +} + - (id _Nonnull) accessibilityValue { AWT_ASSERT_APPKIT_THREAD; 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 0f0a395c597..45e8f981f50 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 @@ -136,6 +136,7 @@ + (void) initializeRolesMap { [rolesMap setObject:@"StaticTextAccessibility" forKey:@"label"]; [rolesMap setObject:@"RadiobuttonAccessibility" forKey:@"radiobutton"]; [rolesMap setObject:@"CheckboxAccessibility" forKey:@"checkbox"]; + [rolesMap setObject:@"CheckboxAccessibility" forKey:@"togglebutton"]; [rolesMap setObject:@"SliderAccessibility" forKey:@"slider"]; [rolesMap setObject:@"ScrollAreaAccessibility" forKey:@"scrollpane"]; [rolesMap setObject:@"ScrollBarAccessibility" forKey:@"scrollbar"]; diff --git a/test/jdk/javax/accessibility/8379347/VoiceOverToggleButtonRole.java b/test/jdk/javax/accessibility/8379347/VoiceOverToggleButtonRole.java new file mode 100644 index 00000000000..31264f69dd8 --- /dev/null +++ b/test/jdk/javax/accessibility/8379347/VoiceOverToggleButtonRole.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.swing.JToggleButton; +import javax.swing.JFrame; + +/* + * @test + * @key headful + * @bug 8379347 + * @summary manual test for VoiceOver reading JToggleButtons correctly + * @requires os.family == "mac" + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual VoiceOverToggleButtonRole + */ + +public class VoiceOverToggleButtonRole { + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + INSTRUCTIONS (Mac-only): + 1. Open VoiceOver + 2. Move the VoiceOver cursor over the JToggleButton. + 3. Observe how VoiceOver identifies the toggle button. + + Expected behavior: VoiceOver should identify it as a + "toggle button" initially. (VO does still say "to select + or deselect this checkbox", though.) + + If you select the link using "Accessibility Inspector": + it should identify its subrole as AXToggle. + """; + + PassFailJFrame.builder() + .title("VoiceOverToggleButtonRole Instruction") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(VoiceOverToggleButtonRole::createUI) + .build() + .awaitAndCheck(); + } + + private static JFrame createUI() { + JFrame frame = new JFrame(); + frame.getContentPane().add(new JToggleButton("JToggleButton")); + frame.pack(); + return frame; + } +} From 6520c95a79ee2e5a249827c49c75b0db48d63209 Mon Sep 17 00:00:00 2001 From: Andrew Dinn Date: Sat, 28 Mar 2026 17:36:58 +0000 Subject: [PATCH 041/116] 8380771: Add missing CodeBlob Vptr implementations Reviewed-by: kvn, asmehra --- src/hotspot/share/code/codeBlob.cpp | 30 +++++------ src/hotspot/share/code/codeBlob.hpp | 77 +++++++++++++++++++++++++---- 2 files changed, 84 insertions(+), 23 deletions(-) diff --git a/src/hotspot/share/code/codeBlob.cpp b/src/hotspot/share/code/codeBlob.cpp index 9961381c31d..a7d939e590d 100644 --- a/src/hotspot/share/code/codeBlob.cpp +++ b/src/hotspot/share/code/codeBlob.cpp @@ -79,8 +79,10 @@ const BufferBlob::Vptr BufferBlob::_vpntr; const RuntimeStub::Vptr RuntimeStub::_vpntr; const SingletonBlob::Vptr SingletonBlob::_vpntr; const DeoptimizationBlob::Vptr DeoptimizationBlob::_vpntr; +const SafepointBlob::Vptr SafepointBlob::_vpntr; #ifdef COMPILER2 const ExceptionBlob::Vptr ExceptionBlob::_vpntr; +const UncommonTrapBlob::Vptr UncommonTrapBlob::_vpntr; #endif // COMPILER2 const UpcallStub::Vptr UpcallStub::_vpntr; @@ -386,7 +388,7 @@ void RuntimeBlob::trace_new_stub(RuntimeBlob* stub, const char* name1, const cha // Implementation of BufferBlob BufferBlob::BufferBlob(const char* name, CodeBlobKind kind, int size, uint16_t header_size) -: RuntimeBlob(name, kind, size, header_size) + : RuntimeBlob(name, kind, size, header_size) {} BufferBlob* BufferBlob::create(const char* name, uint buffer_size) { @@ -621,8 +623,8 @@ DeoptimizationBlob::DeoptimizationBlob( int unpack_with_reexecution_offset, int frame_size ) -: SingletonBlob("DeoptimizationBlob", CodeBlobKind::Deoptimization, cb, - size, sizeof(DeoptimizationBlob), frame_size, oop_maps) + : SingletonBlob("DeoptimizationBlob", CodeBlobKind::Deoptimization, cb, + size, sizeof(DeoptimizationBlob), frame_size, oop_maps) { _unpack_offset = unpack_offset; _unpack_with_exception = unpack_with_exception_offset; @@ -671,8 +673,8 @@ UncommonTrapBlob::UncommonTrapBlob( OopMapSet* oop_maps, int frame_size ) -: SingletonBlob("UncommonTrapBlob", CodeBlobKind::UncommonTrap, cb, - size, sizeof(UncommonTrapBlob), frame_size, oop_maps) + : SingletonBlob("UncommonTrapBlob", CodeBlobKind::UncommonTrap, cb, + size, sizeof(UncommonTrapBlob), frame_size, oop_maps) {} @@ -703,8 +705,8 @@ ExceptionBlob::ExceptionBlob( OopMapSet* oop_maps, int frame_size ) -: SingletonBlob("ExceptionBlob", CodeBlobKind::Exception, cb, - size, sizeof(ExceptionBlob), frame_size, oop_maps) + : SingletonBlob("ExceptionBlob", CodeBlobKind::Exception, cb, + size, sizeof(ExceptionBlob), frame_size, oop_maps) {} @@ -737,8 +739,8 @@ SafepointBlob::SafepointBlob( OopMapSet* oop_maps, int frame_size ) -: SingletonBlob("SafepointBlob", CodeBlobKind::Safepoint, cb, - size, sizeof(SafepointBlob), frame_size, oop_maps) + : SingletonBlob(cb->name(), CodeBlobKind::Safepoint, cb, + size, sizeof(SafepointBlob), frame_size, oop_maps) {} @@ -755,7 +757,7 @@ SafepointBlob* SafepointBlob::create( blob = new (size) SafepointBlob(cb, size, oop_maps, frame_size); } - trace_new_stub(blob, "SafepointBlob"); + trace_new_stub(blob, "SafepointBlob - ", blob->name()); return blob; } @@ -895,7 +897,7 @@ void CodeBlob::dump_for_addr(address addr, outputStream* st, bool verbose) const } } if (is_nmethod()) { - nmethod* nm = (nmethod*)this; + nmethod* nm = as_nmethod(); ResourceMark rm; st->print(INTPTR_FORMAT " is at entry_point+%d in (nmethod*)" INTPTR_FORMAT, p2i(addr), (int)(addr - nm->entry_point()), p2i(nm)); @@ -931,7 +933,7 @@ void RuntimeStub::print_on_impl(outputStream* st) const { RuntimeBlob::print_on_impl(st); st->print("Runtime Stub (" INTPTR_FORMAT "): ", p2i(this)); st->print_cr("%s", name()); - Disassembler::decode((RuntimeBlob*)this, st); + Disassembler::decode((CodeBlob*)this, st); } void RuntimeStub::print_value_on_impl(outputStream* st) const { @@ -942,7 +944,7 @@ void SingletonBlob::print_on_impl(outputStream* st) const { ttyLocker ttyl; RuntimeBlob::print_on_impl(st); st->print_cr("%s", name()); - Disassembler::decode((RuntimeBlob*)this, st); + Disassembler::decode((CodeBlob*)this, st); } void SingletonBlob::print_value_on_impl(outputStream* st) const { @@ -960,7 +962,7 @@ void UpcallStub::print_on_impl(outputStream* st) const { oop recv = JNIHandles::resolve(_receiver); st->print("Receiver MH="); recv->print_on(st); - Disassembler::decode((RuntimeBlob*)this, st); + Disassembler::decode((CodeBlob*)this, st); } void UpcallStub::print_value_on_impl(outputStream* st) const { diff --git a/src/hotspot/share/code/codeBlob.hpp b/src/hotspot/share/code/codeBlob.hpp index 1f9cf0adcc3..6a1686b80e2 100644 --- a/src/hotspot/share/code/codeBlob.hpp +++ b/src/hotspot/share/code/codeBlob.hpp @@ -98,7 +98,9 @@ enum class CodeBlobKind : u1 { class UpcallStub; // for as_upcall_stub() class RuntimeStub; // for as_runtime_stub() class JavaFrameAnchor; // for UpcallStub::jfa_for_frame +class BufferBlob; class AdapterBlob; +class SingletonBlob; class ExceptionBlob; class DeoptimizationBlob; class SafepointBlob; @@ -185,8 +187,19 @@ class CodeBlob { // Typing bool is_nmethod() const { return _kind == CodeBlobKind::Nmethod; } - bool is_buffer_blob() const { return _kind == CodeBlobKind::Buffer; } + // we may want to check for an actual buffer blob or subtype instance + bool is_buffer_blob(bool strict=true) const { + if (strict) { + return _kind == CodeBlobKind::Buffer; + } else { + return (_kind == CodeBlobKind::Buffer || + _kind == CodeBlobKind::Adapter || + _kind == CodeBlobKind::Vtable || + _kind == CodeBlobKind::MHAdapter); + } + } bool is_runtime_stub() const { return _kind == CodeBlobKind::RuntimeStub; } + // singleton blobs are never directly implemented bool is_deoptimization_stub() const { return _kind == CodeBlobKind::Deoptimization; } #ifdef COMPILER2 bool is_uncommon_trap_stub() const { return _kind == CodeBlobKind::UncommonTrap; } @@ -196,6 +209,12 @@ class CodeBlob { bool is_exception_stub() const { return false; } #endif bool is_safepoint_stub() const { return _kind == CodeBlobKind::Safepoint; } + bool is_singleton_blob() const { + return (is_deoptimization_stub() || + is_uncommon_trap_stub() || + is_exception_stub() || + is_safepoint_stub()); + } bool is_adapter_blob() const { return _kind == CodeBlobKind::Adapter; } bool is_vtable_blob() const { return _kind == CodeBlobKind::Vtable; } bool is_method_handles_adapter_blob() const { return _kind == CodeBlobKind::MHAdapter; } @@ -205,8 +224,12 @@ class CodeBlob { nmethod* as_nmethod_or_null() const { return is_nmethod() ? (nmethod*) this : nullptr; } nmethod* as_nmethod() const { assert(is_nmethod(), "must be nmethod"); return (nmethod*) this; } CodeBlob* as_codeblob() const { return (CodeBlob*) this; } + // we may want to force an actual buffer blob or subtype instance + BufferBlob* as_buffer_blob(bool strict = true) const { assert(is_buffer_blob(), "must be %sbuffer blob", (strict ? "strict " : "")); return (BufferBlob*) this; } AdapterBlob* as_adapter_blob() const { assert(is_adapter_blob(), "must be adapter blob"); return (AdapterBlob*) this; } ExceptionBlob* as_exception_blob() const { assert(is_exception_stub(), "must be exception stub"); return (ExceptionBlob*) this; } + // this will always return a subtype instance + SingletonBlob* as_singleton_blob() const { assert(is_singleton_blob(), "must be singleton blob"); return (SingletonBlob*) this; } DeoptimizationBlob* as_deoptimization_blob() const { assert(is_deoptimization_stub(), "must be deopt stub"); return (DeoptimizationBlob*) this; } SafepointBlob* as_safepoint_blob() const { assert(is_safepoint_stub(), "must be safepoint stub"); return (SafepointBlob*) this; } UpcallStub* as_upcall_stub() const { assert(is_upcall_stub(), "must be upcall stub"); return (UpcallStub*) this; } @@ -387,10 +410,10 @@ class BufferBlob: public RuntimeBlob { class Vptr : public RuntimeBlob::Vptr { void print_on(const CodeBlob* instance, outputStream* st) const override { - ((const BufferBlob*)instance)->print_on_impl(st); + instance->as_buffer_blob(false)->print_on_impl(st); } void print_value_on(const CodeBlob* instance, outputStream* st) const override { - ((const BufferBlob*)instance)->print_value_on_impl(st); + instance->as_buffer_blob(false)->print_value_on_impl(st); } }; @@ -486,10 +509,17 @@ class RuntimeStub: public RuntimeBlob { address entry_point() const { return code_begin(); } + void post_restore_impl() { + trace_new_stub(this, "RuntimeStub - ", name()); + } + void print_on_impl(outputStream* st) const; void print_value_on_impl(outputStream* st) const; class Vptr : public RuntimeBlob::Vptr { + void post_restore(CodeBlob* instance) const override { + instance->as_runtime_stub()->post_restore_impl(); + } void print_on(const CodeBlob* instance, outputStream* st) const override { instance->as_runtime_stub()->print_on_impl(st); } @@ -531,10 +561,10 @@ class SingletonBlob: public RuntimeBlob { class Vptr : public RuntimeBlob::Vptr { void print_on(const CodeBlob* instance, outputStream* st) const override { - ((const SingletonBlob*)instance)->print_on_impl(st); + instance->as_singleton_blob()->print_on_impl(st); } void print_value_on(const CodeBlob* instance, outputStream* st) const override { - ((const SingletonBlob*)instance)->print_value_on_impl(st); + instance->as_singleton_blob()->print_value_on_impl(st); } }; @@ -605,20 +635,28 @@ class DeoptimizationBlob: public SingletonBlob { _uncommon_trap_offset = offset; assert(contains(code_begin() + _uncommon_trap_offset), "must be PC inside codeblob"); } - address uncommon_trap() const { return code_begin() + _uncommon_trap_offset; } + address uncommon_trap() const { return (EnableJVMCI ? code_begin() + _uncommon_trap_offset : nullptr); } void set_implicit_exception_uncommon_trap_offset(int offset) { _implicit_exception_uncommon_trap_offset = offset; assert(contains(code_begin() + _implicit_exception_uncommon_trap_offset), "must be PC inside codeblob"); } - address implicit_exception_uncommon_trap() const { return code_begin() + _implicit_exception_uncommon_trap_offset; } + address implicit_exception_uncommon_trap() const { return (EnableJVMCI ? code_begin() + _implicit_exception_uncommon_trap_offset : nullptr); } #endif // INCLUDE_JVMCI + void post_restore_impl() { + trace_new_stub(this, "DeoptimizationBlob"); + } + void print_value_on_impl(outputStream* st) const; class Vptr : public SingletonBlob::Vptr { + void post_restore(CodeBlob* instance) const override { + instance->as_deoptimization_blob()->post_restore_impl(); + } + void print_value_on(const CodeBlob* instance, outputStream* st) const override { - ((const DeoptimizationBlob*)instance)->print_value_on_impl(st); + instance->as_deoptimization_blob()->print_value_on_impl(st); } }; @@ -648,6 +686,16 @@ class UncommonTrapBlob: public SingletonBlob { OopMapSet* oop_maps, int frame_size ); + void post_restore_impl() { + trace_new_stub(this, "UncommonTrapBlob"); + } + class Vptr : public SingletonBlob::Vptr { + void post_restore(CodeBlob* instance) const override { + instance->as_uncommon_trap_blob()->post_restore_impl(); + } + }; + + static const Vptr _vpntr; }; @@ -678,7 +726,7 @@ class ExceptionBlob: public SingletonBlob { class Vptr : public SingletonBlob::Vptr { void post_restore(CodeBlob* instance) const override { - ((ExceptionBlob*)instance)->post_restore_impl(); + instance->as_exception_blob()->post_restore_impl(); } }; @@ -708,6 +756,17 @@ class SafepointBlob: public SingletonBlob { OopMapSet* oop_maps, int frame_size ); + + void post_restore_impl() { + trace_new_stub(this, "SafepointBlob - ", name()); + } + class Vptr : public SingletonBlob::Vptr { + void post_restore(CodeBlob* instance) const override { + instance->as_safepoint_blob()->post_restore_impl(); + } + }; + + static const Vptr _vpntr; }; //---------------------------------------------------------------------------------------------------- From 66a34be54a43c110f8dd577775fc213ed912faa7 Mon Sep 17 00:00:00 2001 From: Jaikiran Pai Date: Sun, 29 Mar 2026 02:01:46 +0000 Subject: [PATCH 042/116] 8273874: LdapClient can trigger memory leak Reviewed-by: dfuchs --- .../classes/com/sun/jndi/ldap/Connection.java | 9 +- .../classes/com/sun/jndi/ldap/EventQueue.java | 9 +- .../sun/jndi/ldap/NamingEventNotifier.java | 6 +- test/jdk/com/sun/jndi/ldap/LdapTCCLTest.java | 323 ++++++++++++++++++ 4 files changed, 336 insertions(+), 11 deletions(-) create mode 100644 test/jdk/com/sun/jndi/ldap/LdapTCCLTest.java diff --git a/src/java.naming/share/classes/com/sun/jndi/ldap/Connection.java b/src/java.naming/share/classes/com/sun/jndi/ldap/Connection.java index dcb739a8697..1e0a924f12c 100644 --- a/src/java.naming/share/classes/com/sun/jndi/ldap/Connection.java +++ b/src/java.naming/share/classes/com/sun/jndi/ldap/Connection.java @@ -57,6 +57,8 @@ import javax.net.ssl.SSLPeerUnverifiedException; import javax.security.sasl.SaslException; +import jdk.internal.misc.InnocuousThread; + /** * A thread that creates a connection to an LDAP server. * After the connection, the thread reads from the connection. @@ -112,9 +114,6 @@ * for v2. * %%% made public for access by LdapSasl %%% * - * @author Vincent Ryan - * @author Rosanna Lee - * @author Jagane Sundar */ public final class Connection implements Runnable { @@ -254,7 +253,7 @@ void setBound() { throw ce; } - worker = new Thread(this); + worker = InnocuousThread.newSystemThread("LDAP Connection", this); worker.setDaemon(true); worker.start(); } @@ -912,7 +911,7 @@ private void pauseReader() throws IOException { // //////////////////////////////////////////////////////////////////////////// - + @Override public void run() { byte inbuf[]; // Buffer for reading incoming bytes int inMsgId; // Message id of incoming response diff --git a/src/java.naming/share/classes/com/sun/jndi/ldap/EventQueue.java b/src/java.naming/share/classes/com/sun/jndi/ldap/EventQueue.java index 4f1cb9ec6a7..7d45d058c68 100644 --- a/src/java.naming/share/classes/com/sun/jndi/ldap/EventQueue.java +++ b/src/java.naming/share/classes/com/sun/jndi/ldap/EventQueue.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,13 +36,13 @@ import javax.naming.ldap.UnsolicitedNotificationEvent; import javax.naming.ldap.UnsolicitedNotificationListener; +import jdk.internal.misc.InnocuousThread; + /** * Package private class used by EventSupport to dispatch events. * This class implements an event queue, and a dispatcher thread that * dequeues and dispatches events from the queue. * - * Pieces stolen from sun.misc.Queue. - * * @author Bill Shannon (from javax.mail.event) * @author Rosanna Lee (modified for JNDI-related events) */ @@ -71,7 +71,7 @@ private static class QueueElement { // package private EventQueue() { - qThread = new Thread(this); + qThread = InnocuousThread.newSystemThread("LDAP Event Dispatcher", this); qThread.setDaemon(true); // not a user thread qThread.start(); } @@ -141,6 +141,7 @@ private QueueElement dequeue() throws InterruptedException { /** * Pull events off the queue and dispatch them. */ + @Override public void run() { QueueElement qe; diff --git a/src/java.naming/share/classes/com/sun/jndi/ldap/NamingEventNotifier.java b/src/java.naming/share/classes/com/sun/jndi/ldap/NamingEventNotifier.java index 40a8173b768..0e30c1c1d38 100644 --- a/src/java.naming/share/classes/com/sun/jndi/ldap/NamingEventNotifier.java +++ b/src/java.naming/share/classes/com/sun/jndi/ldap/NamingEventNotifier.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,6 +33,7 @@ import java.util.Vector; import com.sun.jndi.toolkit.ctx.Continuation; +import jdk.internal.misc.InnocuousThread; /** * Gathers information to generate events by using the Persistent Search @@ -86,7 +87,7 @@ final class NamingEventNotifier implements Runnable { namingListeners = new Vector<>(); namingListeners.addElement(firstListener); - worker = new Thread(this); + worker = InnocuousThread.newSystemThread("LDAP Event Notifier", this); worker.setDaemon(true); // not a user thread worker.start(); } @@ -111,6 +112,7 @@ boolean hasNamingListeners() { * For each result, create the appropriate NamingEvent and * queue to be dispatched to listeners. */ + @Override public void run() { try { Continuation cont = new Continuation(); diff --git a/test/jdk/com/sun/jndi/ldap/LdapTCCLTest.java b/test/jdk/com/sun/jndi/ldap/LdapTCCLTest.java new file mode 100644 index 00000000000..21f355442d7 --- /dev/null +++ b/test/jdk/com/sun/jndi/ldap/LdapTCCLTest.java @@ -0,0 +1,323 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.net.Socket; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Collection; +import java.util.Collections; +import java.util.Hashtable; + +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.event.EventContext; +import javax.naming.event.NamingEvent; +import javax.naming.event.NamingExceptionEvent; +import javax.naming.event.ObjectChangeListener; + +import jdk.test.lib.net.URIBuilder; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import static java.nio.charset.StandardCharsets.US_ASCII; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.fail; + +/* + * @test + * @bug 8273874 + * @summary Verify that the system threads that LdapContext creates for its internal + * use do not hold on to the application specific context classloaders + * @comment The test uses ThreadGroup.enumerate() to find live threads and check their + * context classsloader, ThreadGroup of virtual threads don't enumerate threads, + * so we skip this test when the main thread is a virtual thread. + * @requires test.thread.factory != "Virtual" + * @library lib/ /test/lib + * @build BaseLdapServer + * LdapMessage + * jdk.test.lib.net.URIBuilder + * @run junit ${test.main.class} + */ +class LdapTCCLTest { + + private static final String LOOKUP_NAME = "CN=duke"; + + private static final byte BER_TYPE_LDAP_SEQUENCE = 0x30; + private static final byte BER_TYPE_INTEGER = 0x02; + private static final byte BER_TYPE_OCTET_STRING = 0x04; + private static final byte BER_TYPE_ENUM = 0x0a; + private static final byte BER_TYPE_LDAP_SEARCH_RESULT_ENTRY_OP = 0x64; + private static final byte BER_TYPE_LDAP_SEARCH_RESULT_DONE_OP = 0x65; + private static final byte LDAP_SEARCH_RESULT_DONE_SUCCESS = 0x00; + + private static Server server; + private static Hashtable envProps; + + @BeforeAll + static void beforeAll() throws Exception { + server = new Server(); + server.start(); + System.err.println("server started at " + server.getInetAddress() + + ":" + server.getPort()); + + final Hashtable props = new Hashtable<>(); + props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); + final String providerUrl = URIBuilder.newBuilder() + .scheme("ldap") + .host(server.getInetAddress().getHostAddress()) + .port(server.getPort()) + .build().toString(); + props.put(Context.PROVIDER_URL, providerUrl); + // explicitly set LDAP version to 3 to prevent LDAP BIND requests + // during LdapCtx instantiation + props.put("java.naming.ldap.version", "3"); + + envProps = props; + } + + @AfterAll + static void afterAll() throws Exception { + if (server != null) { + System.err.println("stopping server " + server.getInetAddress() + + ":" + server.getPort()); + server.close(); + } + } + + /* + * Sets a test specific Thread context classloader and then creates a InitialContext + * backed by a LdapCtxFactory and looks up an arbitrary name. The test then verifies + * that none of the live Threads (including any created for the internal LDAP connection + * management) have their context classloader set to the test specific classloader. + */ + @Test + void testLdapCtxCreation() throws Exception { + try (final URLClassLoader urlc = new URLClassLoader(new URL[0])) { + final ClassLoader previous = Thread.currentThread().getContextClassLoader(); + Context ctx = null; + try { + // switch the TCCL to a test specific one + Thread.currentThread().setContextClassLoader(urlc); + + // create the LDAP Context and initiate a lookup() + // to allow for the underlying LDAP connection management + // infrastructure to create the necessary Thread(s) + ctx = new InitialContext(envProps); + + System.err.println("issuing ldap request against " + + envProps.get(Context.PROVIDER_URL) + " using context " + ctx); + final Object result = ctx.lookup(LOOKUP_NAME); + System.err.println("lookup returned " + result); + assertNotNull(result, "Context.lookup() returned null"); + + // verify that none of the live Thread(s) other than the current Thread + // have their TCCL set to the one set by the test. i.e. verify that the + // context classloader hasn't leaked into Thread(s) that may have been + // created by the LDAP connection management code. + assertTCCL(urlc, Collections.singleton(Thread.currentThread())); + } finally { + if (ctx != null) { + ctx.close(); + } + Thread.currentThread().setContextClassLoader(previous); + } + } + } + + /* + * Sets a test specific Thread context classloader and then creates a InitialContext + * backed by a LdapCtxFactory and adds a NamingListener. The test then verifies + * that none of the live Threads (including any newly created ones during the + * NamingListener registration) have their context classloader set to the test + * specific classloader. + */ + @Test + void testAddNamingListener() throws Exception { + try (final URLClassLoader urlc = new URLClassLoader(new URL[0])) { + final ClassLoader previous = Thread.currentThread().getContextClassLoader(); + EventContext ctx = null; + try { + // switch the TCCL to a test specific one + Thread.currentThread().setContextClassLoader(urlc); + + ctx = (EventContext) (new InitialContext(envProps).lookup(LOOKUP_NAME)); + // add a NamingListener to exercise the Thread creation in the internals + // of LdapCtx + ctx.addNamingListener(LOOKUP_NAME, EventContext.OBJECT_SCOPE, new Listener()); + // verify that none of the live Thread(s) other than the current Thread + // have their TCCL set to the one set by the test. i.e. verify that the + // context classloader hasn't leaked into Thread(s) that may have been + // created by the LDAP naming listener code. + assertTCCL(urlc, Collections.singleton(Thread.currentThread())); + } finally { + if (ctx != null) { + ctx.close(); + } + Thread.currentThread().setContextClassLoader(previous); + } + } + } + + /* + * Verifies that none of the live threads have their context classloader set to + * the given "notExpected" classloader. + */ + private static void assertTCCL(final ClassLoader notExpected, + final Collection threadsToIgnore) { + ThreadGroup topMostThreadGroup = Thread.currentThread().getThreadGroup(); + assertNotNull(topMostThreadGroup, + "ThreadGroup for current thread " + Thread.currentThread() + " was null"); + while (topMostThreadGroup.getParent() != null) { + topMostThreadGroup = topMostThreadGroup.getParent(); + } + // recursively enumerate the threads in the top most thread group + final Thread[] threads = new Thread[1024]; + final int numThreads = topMostThreadGroup.enumerate(threads); + // verify the threads + int numFailedThreads = 0; + final StringBuilder diagnosticMsg = new StringBuilder(); + for (int i = 0; i < numThreads; i++) { + final Thread t = threads[i]; + if (threadsToIgnore.contains(t)) { + continue; // skip verification of the thread + } + System.err.println("verifying " + t); + if (t.getContextClassLoader() == notExpected) { + // Thread has an unexpected context classloader + numFailedThreads++; + // for debugging track the stacktrace of the thread + // that failed the check + diagnosticMsg.append("FAILED - ").append(t) + .append(" is using unexpected context classloader: ") + .append(notExpected) + .append(", its current activity is:\n"); + for (StackTraceElement ste : t.getStackTrace()) { + diagnosticMsg.append("\t").append(ste).append("\n"); + } + } + } + if (numFailedThreads > 0) { + // for debugging print out the stacktrace of the + // Thread(s) that failed the check + System.err.println(diagnosticMsg); + fail(numFailedThreads + " Thread(s) had unexpected context classloader " + + notExpected); + } + } + + private static final class Server extends BaseLdapServer { + + private Server() throws IOException { + super(); + } + + // handles and responds to the incoming LDAP request + @Override + protected void handleRequest(final Socket socket, + final LdapMessage request, + final OutputStream out) throws IOException { + switch (request.getOperation()) { + case SEARCH_REQUEST: { + System.err.println("responding to SEARCH_REQUEST with id: " + + request.getMessageID() + " on socket " + socket); + // write out a search response + final byte[] rsp = makeSearchResponse((byte) request.getMessageID(), LOOKUP_NAME); + out.write(rsp); + out.flush(); + System.err.println("wrote response for message: " + request.getMessageID()); + break; + } + default: { + throw new IOException("unexpected operation type: " + request.getOperation() + + ", request: " + request); + } + } + } + + // constructs and returns a byte[] response containing the following (in that order): + // - Search Result Entry + // - Search Result Done + private static byte[] makeSearchResponse(final byte msgId, final String dn) + throws IOException { + final ByteArrayOutputStream bout = new ByteArrayOutputStream(); + final byte msgIdLen = 1; + + // write the BER elements + // each BER element is 3 parts: + // Type, length, value + + // Search Result Entry BER element (refer to LDAPv3 wire format for details) + bout.write(BER_TYPE_LDAP_SEQUENCE); + bout.write(dn.length() + 9); + bout.write(new byte[]{BER_TYPE_INTEGER, msgIdLen, msgId}); + bout.write(BER_TYPE_LDAP_SEARCH_RESULT_ENTRY_OP); + bout.write(dn.length() + 2); + bout.write(BER_TYPE_OCTET_STRING); + bout.write(dn.length()); + bout.write(dn.getBytes(US_ASCII)); + bout.write(BER_TYPE_LDAP_SEQUENCE); + // 0 length for the LDAP sequence, implying no attributes in this Search Result Entry + bout.write(0); + + bout.write(makeSearchResultDone(msgId)); + + return bout.toByteArray(); + } + + // Search Result Done BER element (refer to LDAPv3 wire format for details) + private static byte[] makeSearchResultDone(final byte msgId) throws IOException { + final ByteArrayOutputStream bout = new ByteArrayOutputStream(); + final byte msgIdLen = 1; + final String matchedDN = ""; + bout.write(BER_TYPE_LDAP_SEQUENCE); + bout.write(matchedDN.length() + 12); + bout.write(new byte[]{BER_TYPE_INTEGER, msgIdLen, msgId}); + bout.write(BER_TYPE_LDAP_SEARCH_RESULT_DONE_OP); + bout.write(7); + bout.write(new byte[]{BER_TYPE_ENUM, 1, LDAP_SEARCH_RESULT_DONE_SUCCESS}); + // the matched DN + bout.write(BER_TYPE_OCTET_STRING); + bout.write(matchedDN.length()); + bout.write(matchedDN.getBytes(US_ASCII)); + // 0 length implies no diagnostic message + bout.write(new byte[]{BER_TYPE_OCTET_STRING, 0}); + return bout.toByteArray(); + } + } + + private static final class Listener implements ObjectChangeListener { + + @Override + public void namingExceptionThrown(final NamingExceptionEvent evt) { + System.err.println("namingExceptionThrown() called for " + evt); + } + + @Override + public void objectChanged(final NamingEvent evt) { + System.err.println("objectChanged() called for " + evt); + } + } +} From eb96bfb2a538e60f4ff0c682100931d3cf8da8d2 Mon Sep 17 00:00:00 2001 From: jonghoonpark Date: Mon, 30 Mar 2026 02:58:19 +0000 Subject: [PATCH 043/116] 8379873: Remove undefined debugging declarations in os_windows.cpp Reviewed-by: dholmes, ayang --- src/hotspot/os/windows/os_windows.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index 18d047348cb..9d8fb45f0d1 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -2528,12 +2528,6 @@ LONG Handle_Exception(struct _EXCEPTION_POINTERS* exceptionInfo, return EXCEPTION_CONTINUE_EXECUTION; } - -// Used for PostMortemDump -extern "C" void safepoints(); -extern "C" void find(int x); -extern "C" void events(); - // According to Windows API documentation, an illegal instruction sequence should generate // the 0xC000001C exception code. However, real world experience shows that occasionnaly // the execution of an illegal instruction can generate the exception code 0xC000001E. This From 7527da081b777f280144af5841874729a671e9c5 Mon Sep 17 00:00:00 2001 From: Trupti Patil Date: Mon, 30 Mar 2026 04:40:26 +0000 Subject: [PATCH 044/116] 8377534: Test java/awt/print/PrinterJob/PrintNullString.java fails with FAILURE: No IAE for empty iterator, int Reviewed-by: aivanov, prr --- .../awt/print/PrinterJob/PrintNullString.java | 20 ++++++------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/test/jdk/java/awt/print/PrinterJob/PrintNullString.java b/test/jdk/java/awt/print/PrinterJob/PrintNullString.java index 2bcee65fe9b..8feb50602f7 100644 --- a/test/jdk/java/awt/print/PrinterJob/PrintNullString.java +++ b/test/jdk/java/awt/print/PrinterJob/PrintNullString.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,7 +37,7 @@ /* * @test - * @bug 4223328 + * @bug 4223328 4138921 * @summary Printer graphics must throw expected exceptions * @key printer * @run main PrintNullString @@ -106,12 +106,8 @@ public int print(Graphics g, PageFormat pgFmt, int pgIndex) { g2d.drawString("caught expected NPE for null iterator, int", 20, 120); } - try { - g2d.drawString(emptyIterator, 20, 140); - throw new RuntimeException("FAILURE: No IAE for empty iterator, int"); - } catch (IllegalArgumentException e) { - g2d.drawString("caught expected IAE for empty iterator, int", 20, 140); - } + g2d.drawString(emptyIterator, 20, 140); + g2d.drawString("OK for empty iterator, int", 20, 140); // API 4: null & empty drawString(Iterator, float, int); try { @@ -121,12 +117,8 @@ public int print(Graphics g, PageFormat pgFmt, int pgIndex) { g2d.drawString("caught expected NPE for null iterator, float", 20, 160); } - try { - g2d.drawString(emptyIterator, 20.0f, 180.0f); - throw new RuntimeException("FAILURE: No IAE for empty iterator, float"); - } catch (IllegalArgumentException e) { - g2d.drawString("caught expected IAE for empty iterator, float", 20, 180); - } + g2d.drawString(emptyIterator, 20.0f, 180.0f); + g2d.drawString("OK for empty iterator, float", 20.0f, 100.f); return PAGE_EXISTS; } From ca3fe721ba23a1304089b71c1b58940f16a0d053 Mon Sep 17 00:00:00 2001 From: Thomas Stuefe Date: Mon, 30 Mar 2026 04:54:17 +0000 Subject: [PATCH 045/116] 8357089: Remove VFORK launch mechanism from Process implementation (linux) Reviewed-by: rriggs, andrew --- .../unix/classes/java/lang/ProcessImpl.java | 37 ++-- .../unix/native/libjava/ProcessImpl_md.c | 159 ++++-------------- src/java.base/unix/native/libjava/childproc.c | 52 +----- src/java.base/unix/native/libjava/childproc.h | 1 - test/jdk/java/lang/ProcessBuilder/Basic.java | 10 -- .../ConcNativeForkTest.java | 10 -- .../ProcessBuilder/FDLeakTest/FDLeakTest.java | 8 - .../ProcessBuilder/NonPipelineLeaksFD.java | 8 - .../PipesCloseOnExecTest.java | 10 -- .../lang/ProcessBuilder/RejectVFORKMode.java | 59 +++++++ .../TestChildSignalDisposition.java | 11 +- 11 files changed, 113 insertions(+), 252 deletions(-) create mode 100644 test/jdk/java/lang/ProcessBuilder/RejectVFORKMode.java diff --git a/src/java.base/unix/classes/java/lang/ProcessImpl.java b/src/java.base/unix/classes/java/lang/ProcessImpl.java index 00b51fb3389..d9a4547848f 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, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -82,8 +82,7 @@ final class ProcessImpl extends Process { private static enum LaunchMechanism { // order IS important! FORK, - POSIX_SPAWN, - VFORK + POSIX_SPAWN } /** @@ -98,29 +97,16 @@ private static LaunchMechanism launchMechanism() { try { // Should be value of a LaunchMechanism enum - LaunchMechanism lm = LaunchMechanism.valueOf(s.toUpperCase(Locale.ROOT)); - switch (OperatingSystem.current()) { - case LINUX: { - // All options are valid for Linux, but VFORK is deprecated and results - // in a warning - if (lm == LaunchMechanism.VFORK) { - System.err.println("VFORK MODE DEPRECATED"); - System.err.println(""" - The VFORK launch mechanism has been deprecated for being dangerous. - It will be removed in a future java version. Either remove the - jdk.lang.Process.launchMechanism property (preferred) or use FORK mode - instead (-Djdk.lang.Process.launchMechanism=FORK). - """); - } - return lm; - } - case AIX: - case MACOS: - if (lm != LaunchMechanism.VFORK) { - return lm; // All but VFORK are valid - } - break; + String launchMechanism = s.toUpperCase(Locale.ROOT); + if (launchMechanism.equals("VFORK") && OperatingSystem.isLinux()) { + launchMechanism = "FORK"; + System.err.println(String.format(""" + The VFORK launch mechanism has been removed. Switching to %s instead. + Please remove the jdk.lang.Process.launchMechanism property (preferred) + or use FORK mode instead (-Djdk.lang.Process.launchMechanism=FORK).%n + """, launchMechanism)); } + return LaunchMechanism.valueOf(launchMechanism); } catch (IllegalArgumentException e) { } @@ -266,7 +252,6 @@ static Process start(String[] cmdarray, *

      *   1 - fork(2) and exec(2)
      *   2 - posix_spawn(3P)
-     *   3 - vfork(2) and exec(2)
      * 
* @param fds an array of three file descriptors. * Indexes 0, 1, and 2 correspond to standard input, diff --git a/src/java.base/unix/native/libjava/ProcessImpl_md.c b/src/java.base/unix/native/libjava/ProcessImpl_md.c index f7d91166e76..69af948d2da 100644 --- a/src/java.base/unix/native/libjava/ProcessImpl_md.c +++ b/src/java.base/unix/native/libjava/ProcessImpl_md.c @@ -60,51 +60,33 @@ * changing paths... * - then exec(2) the target binary * - * There are three ways to fork off: - * - * A) fork(2). Portable and safe (no side effects) but may fail with ENOMEM on - * all Unices when invoked from a VM with a high memory footprint. On Unices - * with strict no-overcommit policy this problem is most visible. - * - * This is because forking the VM will first create a child process with - * theoretically the same memory footprint as the parent - even if you plan - * to follow up with exec'ing a tiny binary. In reality techniques like - * copy-on-write etc mitigate the problem somewhat but we still run the risk - * of hitting system limits. - * - * For a Linux centric description of this problem, see the documentation on - * /proc/sys/vm/overcommit_memory in Linux proc(5). - * - * B) vfork(2): Portable and fast but very unsafe. It bypasses the memory - * problems related to fork(2) by starting the child in the memory image of - * the parent. Things that can go wrong include: - * - Programming errors in the child process before the exec(2) call may - * trash memory in the parent process, most commonly the stack of the - * thread invoking vfork. - * - Signals received by the child before the exec(2) call may be at best - * misdirected to the parent, at worst immediately kill child and parent. - * - * This is mitigated by very strict rules about what one is allowed to do in - * the child process between vfork(2) and exec(2), which is basically nothing. - * However, we always broke this rule by doing the pre-exec work between - * vfork(2) and exec(2). - * - * Also note that vfork(2) has been deprecated by the OpenGroup, presumably - * because of its many dangers. - * - * C) clone(2): This is a Linux specific call which gives the caller fine - * grained control about how exactly the process fork is executed. It is - * powerful, but Linux-specific. - * - * Aside from these three possibilities there is a forth option: posix_spawn(3). - * Where fork/vfork/clone all fork off the process and leave pre-exec work and - * calling exec(2) to the user, posix_spawn(3) offers the user fork+exec-like - * functionality in one package, similar to CreateProcess() on Windows. - * - * It is not a system call in itself, but usually a wrapper implemented within - * the libc in terms of one of (fork|vfork|clone)+exec - so whether or not it - * has advantages over calling the naked (fork|vfork|clone) functions depends - * on how posix_spawn(3) is implemented. + * On the OS-side are three ways to fork off, but we only use two of them: + * + * A) fork(2). Portable and safe (no side effects) but could fail on very ancient + * Unices that don't employ COW on fork(2). The modern platforms we support + * (Linux, MacOS, AIX) all do. It may have a small performance penalty compared + * to modern posix_spawn(3) implementations - see below. + * fork(2) can be used by specifying -Djdk.lang.Process.launchMechanism=FORK when starting + * the (parent process) JVM. + * + * B) vfork(2): Portable and fast but very unsafe. For details, see JDK-8357090. + * We supported this mode in older releases but removed support for it in JDK 27. + * Modern posix_spawn(3) implementations use techniques similar to vfork(2), but + * in a much safer way + * + * C) posix_spawn(3): Where fork/vfork/clone all fork off the process and leave + * pre-exec work and calling exec(2) to the user, posix_spawn(3) offers the user + * fork+exec-like functionality in one package, similar to CreateProcess() on Windows. + * It is not a system call, but a wrapper implemented in user-space libc in terms + * of one of (fork|vfork|clone)+exec - so whether or not it has advantages over calling + * the naked (fork|vfork|clone) functions depends on how posix_spawn(3) is implemented. + * Modern posix_spawn(3) implementations, on Linux, use clone(2) with CLONE_VM | CLONE_VFORK, + * giving us the best ratio between performance and safety. + * Note however, that posix_spawn(3) can be buggy, depending on the libc implementation. + * E.g., on MacOS, it is still fully not POSIX-compliant. Therefore, we need to retain the + * FORK mode as a backup. + * Posix_spawn mode is used by default, but can be explicitly enabled using + * -Djdk.lang.Process.launchMechanism=POSIX_SPAWN when starting the (parent process) JVM. * * Note that when using posix_spawn(3), we exec twice: first a tiny binary called * the jspawnhelper, then in the jspawnhelper we do the pre-exec work and exec a @@ -117,58 +99,14 @@ * --- Linux-specific --- * * How does glibc implement posix_spawn? - * (see: sysdeps/posix/spawni.c for glibc < 2.24, - * sysdeps/unix/sysv/linux/spawni.c for glibc >= 2.24): - * - * 1) Before glibc 2.4 (released 2006), posix_spawn(3) used just fork(2)/exec(2). - * This would be bad for the JDK since we would risk the known memory issues with - * fork(2). But since this only affects glibc variants which have long been - * phased out by modern distributions, this is irrelevant. - * - * 2) Between glibc 2.4 and glibc 2.23, posix_spawn uses either fork(2) or - * vfork(2) depending on how exactly the user called posix_spawn(3): - * - * - * The child process is created using vfork(2) instead of fork(2) when - * either of the following is true: - * - * * the spawn-flags element of the attributes object pointed to by - * attrp contains the GNU-specific flag POSIX_SPAWN_USEVFORK; or - * - * * file_actions is NULL and the spawn-flags element of the attributes - * object pointed to by attrp does not contain - * POSIX_SPAWN_SETSIGMASK, POSIX_SPAWN_SETSIGDEF, - * POSIX_SPAWN_SETSCHEDPARAM, POSIX_SPAWN_SETSCHEDULER, - * POSIX_SPAWN_SETPGROUP, or POSIX_SPAWN_RESETIDS. - * - * - * Due to the way the JDK calls posix_spawn(3), it would therefore call vfork(2). - * So we would avoid the fork(2) memory problems. However, there still remains the - * risk associated with vfork(2). But it is smaller than were we to call vfork(2) - * directly since we use the jspawnhelper, moving all pre-exec work off to after - * the first exec, thereby reducing the vulnerable time window. - * - * 3) Since glibc >= 2.24, glibc uses clone+exec: - * - * new_pid = CLONE (__spawni_child, STACK (stack, stack_size), stack_size, - * CLONE_VM | CLONE_VFORK | SIGCHLD, &args); * - * This is even better than (2): + * Before glibc 2.4 (released 2006), posix_spawn(3) used just fork(2)/exec(2). From + * glibc 2.4 up to and including 2.23, it used either fork(2) or vfork(2). None of these + * versions still matter. * - * CLONE_VM means we run in the parent's memory image, as with (2) - * CLONE_VFORK means parent waits until we exec, as with (2) - * - * However, error possibilities are further reduced since: - * - posix_spawn(3) passes a separate stack for the child to run on, eliminating - * the danger of trashing the forking thread's stack in the parent process. - * - posix_spawn(3) takes care to temporarily block all incoming signals to the - * child process until the first exec(2) has been called, - * - * TL;DR - * Calling posix_spawn(3) for glibc - * (2) < 2.24 is not perfect but still better than using plain vfork(2), since - * the chance of an error happening is greatly reduced - * (3) >= 2.24 is the best option - portable, fast and as safe as possible. + * Since glibc >= 2.24, glibc uses clone+exec with CLONE_VM | CLONE_VFORK to emulate vfork + * performance but without the inherent dangers (we run inside the parent's memory image + * and stop the parent for as long as it takes the child process to exec). * * --- * @@ -180,7 +118,6 @@ * * * - * * Based on the above analysis, we are currently defaulting to posix_spawn() * on all Unices including Linux. */ @@ -489,28 +426,6 @@ static int copystrings(char *buf, int offset, const char * const *arg) { __attribute_noinline__ #endif -/* vfork(2) is deprecated on Darwin */ -#ifndef __APPLE__ -static pid_t -vforkChild(ChildStuff *c) { - volatile pid_t resultPid; - - /* - * We separate the call to vfork into a separate function to make - * very sure to keep stack of child from corrupting stack of parent, - * as suggested by the scary gcc warning: - * warning: variable 'foo' might be clobbered by 'longjmp' or 'vfork' - */ - resultPid = vfork(); - - if (resultPid == 0) { - childProcess(c); - } - assert(resultPid != 0); /* childProcess never returns */ - return resultPid; -} -#endif - static pid_t forkChild(ChildStuff *c) { pid_t resultPid; @@ -734,11 +649,6 @@ spawnChild(JNIEnv *env, jobject process, ChildStuff *c, const char *helperpath) static pid_t startChild(JNIEnv *env, jobject process, ChildStuff *c, const char *helperpath) { switch (c->mode) { -/* vfork(2) is deprecated on Darwin*/ - #ifndef __APPLE__ - case MODE_VFORK: - return vforkChild(c); - #endif case MODE_FORK: return forkChild(c); case MODE_POSIX_SPAWN: @@ -872,9 +782,6 @@ Java_java_lang_ProcessImpl_forkAndExec(JNIEnv *env, if (resultPid < 0) { char * failMessage = "unknown"; switch (c->mode) { - case MODE_VFORK: - failMessage = "vfork failed"; - break; case MODE_FORK: failMessage = "fork failed"; break; diff --git a/src/java.base/unix/native/libjava/childproc.c b/src/java.base/unix/native/libjava/childproc.c index 83ee782482f..6bc15dfb40c 100644 --- a/src/java.base/unix/native/libjava/childproc.c +++ b/src/java.base/unix/native/libjava/childproc.c @@ -271,31 +271,6 @@ initVectorFromBlock(const char**vector, const char* block, int count) vector[count] = NULL; } -/** - * Exec FILE as a traditional Bourne shell script (i.e. one without #!). - * If we could do it over again, we would probably not support such an ancient - * misfeature, but compatibility wins over sanity. The original support for - * this was imported accidentally from execvp(). - */ -static void -execve_as_traditional_shell_script(const char *file, - const char *argv[], - const char *const envp[]) -{ - /* Use the extra word of space provided for us in argv by caller. */ - const char *argv0 = argv[0]; - const char *const *end = argv; - while (*end != NULL) - ++end; - memmove(argv+2, argv+1, (end-argv) * sizeof(*end)); - argv[0] = "/bin/sh"; - argv[1] = file; - execve(argv[0], (char **) argv, (char **) envp); - /* Can't even exec /bin/sh? Big trouble, but let's soldier on... */ - memmove(argv+1, argv+2, (end-argv) * sizeof(*end)); - argv[0] = argv0; -} - /** * Like execve(2), except that in case of ENOEXEC, FILE is assumed to * be a shell script and the system default shell is invoked to run it. @@ -305,16 +280,9 @@ execve_with_shell_fallback(int mode, const char *file, const char *argv[], const char *const envp[]) { - if (mode == MODE_VFORK) { - /* shared address space; be very careful. */ - execve(file, (char **) argv, (char **) envp); - if (errno == ENOEXEC) - execve_as_traditional_shell_script(file, argv, envp); - } else { - /* unshared address space; we can mutate environ. */ - environ = (char **) envp; - execvp(file, (char **) argv); - } + /* unshared address space; we can mutate environ. */ + environ = (char **) envp; + execvp(file, (char **) argv); } /** @@ -430,7 +398,7 @@ childProcess(void *arg) #endif /* File descriptor setup for non-Posix-spawn mode */ - if (p->mode != MODE_POSIX_SPAWN) { + if (p->mode == MODE_FORK) { /* Close the parent sides of the pipes. Closing pipe fds here is redundant, since markDescriptorsCloseOnExec() @@ -482,7 +450,7 @@ childProcess(void *arg) /* We moved the fail pipe fd */ fail_pipe_fd = FAIL_FILENO; - } /* end: FORK/VFORK mode */ + } /* end: FORK mode */ assert(fail_pipe_fd == FAIL_FILENO); @@ -508,12 +476,10 @@ childProcess(void *arg) goto WhyCantJohnnyExec; } - // Reset any mask signals from parent, but not in VFORK mode - if (p->mode != MODE_VFORK) { - sigset_t unblock_signals; - sigemptyset(&unblock_signals); - sigprocmask(SIG_SETMASK, &unblock_signals, NULL); - } + // Reset any mask signals from parent + sigset_t unblock_signals; + sigemptyset(&unblock_signals); + sigprocmask(SIG_SETMASK, &unblock_signals, NULL); // Children should be started with default signal disposition for SIGPIPE if (signal(SIGPIPE, SIG_DFL) == SIG_ERR) { diff --git a/src/java.base/unix/native/libjava/childproc.h b/src/java.base/unix/native/libjava/childproc.h index 27414e60137..0b02df7f3dd 100644 --- a/src/java.base/unix/native/libjava/childproc.h +++ b/src/java.base/unix/native/libjava/childproc.h @@ -81,7 +81,6 @@ extern char **environ; */ #define MODE_FORK 1 #define MODE_POSIX_SPAWN 2 -#define MODE_VFORK 3 typedef struct _ChildStuff { diff --git a/test/jdk/java/lang/ProcessBuilder/Basic.java b/test/jdk/java/lang/ProcessBuilder/Basic.java index 70d6101c1a5..b150690ef48 100644 --- a/test/jdk/java/lang/ProcessBuilder/Basic.java +++ b/test/jdk/java/lang/ProcessBuilder/Basic.java @@ -50,16 +50,6 @@ * @run main/othervm/native/timeout=360 -Djdk.lang.Process.launchMechanism=fork Basic */ -/* - * @test id=VFORK - * @modules java.base/java.lang:open - * java.base/java.io:open - * java.base/jdk.internal.misc - * @requires (os.family == "linux") - * @library /test/lib - * @run main/othervm/timeout=300 -Djdk.lang.Process.launchMechanism=vfork Basic - */ - import java.lang.ProcessBuilder.Redirect; import java.lang.ProcessHandle; import static java.lang.ProcessBuilder.Redirect.*; diff --git a/test/jdk/java/lang/ProcessBuilder/ConcNativeForkTest/ConcNativeForkTest.java b/test/jdk/java/lang/ProcessBuilder/ConcNativeForkTest/ConcNativeForkTest.java index f02e4991302..904a0e12f98 100644 --- a/test/jdk/java/lang/ProcessBuilder/ConcNativeForkTest/ConcNativeForkTest.java +++ b/test/jdk/java/lang/ProcessBuilder/ConcNativeForkTest/ConcNativeForkTest.java @@ -42,16 +42,6 @@ * @run main/othervm/manual -Djdk.lang.Process.launchMechanism=FORK ConcNativeForkTest */ -/* - * @test id=VFORK - * @bug 8377907 - * @summary Test that demonstrates the hanging-parent-on-native-concurrent-forks problem - * @requires os.family == "linux" - * @requires vm.flagless - * @library /test/lib - * @run main/othervm/manual -Djdk.lang.Process.launchMechanism=VFORK ConcNativeForkTest - */ - public class ConcNativeForkTest { // How this works: diff --git a/test/jdk/java/lang/ProcessBuilder/FDLeakTest/FDLeakTest.java b/test/jdk/java/lang/ProcessBuilder/FDLeakTest/FDLeakTest.java index aee85e2335f..02c60395f17 100644 --- a/test/jdk/java/lang/ProcessBuilder/FDLeakTest/FDLeakTest.java +++ b/test/jdk/java/lang/ProcessBuilder/FDLeakTest/FDLeakTest.java @@ -38,14 +38,6 @@ * @run main/othervm/native -Djdk.lang.Process.launchMechanism=fork -agentlib:FDLeaker FDLeakTest */ -/** - * @test id=vfork - * @summary Check that we don't leak FDs to child processes - * @requires os.family == "linux" - * @library /test/lib - * @run main/othervm/native -Djdk.lang.Process.launchMechanism=vfork -agentlib:FDLeaker FDLeakTest - */ - import jdk.test.lib.process.ProcessTools; public class FDLeakTest { // This test has two native parts: diff --git a/test/jdk/java/lang/ProcessBuilder/NonPipelineLeaksFD.java b/test/jdk/java/lang/ProcessBuilder/NonPipelineLeaksFD.java index be2c4af3bbe..e43255d8c52 100644 --- a/test/jdk/java/lang/ProcessBuilder/NonPipelineLeaksFD.java +++ b/test/jdk/java/lang/ProcessBuilder/NonPipelineLeaksFD.java @@ -32,14 +32,6 @@ * @run main/othervm -Djdk.lang.Process.launchMechanism=fork NonPipelineLeaksFD */ -/* - * @test id=VFORK - * @summary Check that we don't accumulate leaked FDs in the parent process - * @requires os.family == "linux" - * @library /test/lib - * @run main/othervm -Djdk.lang.Process.launchMechanism=vfork NonPipelineLeaksFD - */ - /* * @test id=POSIX_SPAWN * @summary Check that we don't accumulate leaked FDs in the parent process diff --git a/test/jdk/java/lang/ProcessBuilder/PipesCloseOnExecTest/PipesCloseOnExecTest.java b/test/jdk/java/lang/ProcessBuilder/PipesCloseOnExecTest/PipesCloseOnExecTest.java index 1e988f0496c..8390caae59a 100644 --- a/test/jdk/java/lang/ProcessBuilder/PipesCloseOnExecTest/PipesCloseOnExecTest.java +++ b/test/jdk/java/lang/ProcessBuilder/PipesCloseOnExecTest/PipesCloseOnExecTest.java @@ -32,16 +32,6 @@ * @run main/othervm/native -Djdk.lang.Process.launchMechanism=FORK PipesCloseOnExecTest */ -/* - * @test id=VFORK - * @bug 8377907 - * @summary Check that we don't open pipes without CLOEXCEC - * @requires os.family == "linux" - * @requires vm.flagless - * @library /test/lib - * @run main/othervm/native -Djdk.lang.Process.launchMechanism=VFORK PipesCloseOnExecTest - */ - /* * @test id=POSIX_SPAWN * @bug 8377907 diff --git a/test/jdk/java/lang/ProcessBuilder/RejectVFORKMode.java b/test/jdk/java/lang/ProcessBuilder/RejectVFORKMode.java new file mode 100644 index 00000000000..db8387821f5 --- /dev/null +++ b/test/jdk/java/lang/ProcessBuilder/RejectVFORKMode.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2026, 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 + * 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 8357089 + * @summary Check that specifying VFORK correctly falls back to FORK with a clear warning to stderr. + * @requires (os.family == "linux") + * @library /test/lib + * @run main RejectVFORKMode GRANDPARENT + */ + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +public class RejectVFORKMode { + public static void main(String[] args) throws Exception { + + switch (args[0]) { + case "PARENT" -> { + ProcessBuilder pb = new ProcessBuilder("sh", "-c", "echo 'Child Process'; exit 12;"); + // This should result in a (written to this process' stderr) warning about VFORK mode. + // But child should have been started successfully. + OutputAnalyzer outputAnalyzer = ProcessTools.executeCommand(pb); + outputAnalyzer.shouldHaveExitValue(12); + outputAnalyzer.shouldContain("Child Process"); + System.exit(0); + } + case "GRANDPARENT" -> { + ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-Djdk.lang.Process.launchMechanism=VFORK", RejectVFORKMode.class.getName(), "PARENT"); + OutputAnalyzer outputAnalyzer = ProcessTools.executeCommand(pb); + outputAnalyzer.shouldHaveExitValue(0); + outputAnalyzer.shouldContain("The VFORK launch mechanism has been removed. Switching to FORK instead."); + } + default -> throw new RuntimeException("Bad arg"); + } + } +} diff --git a/test/jdk/java/lang/ProcessBuilder/childSignalDisposition/TestChildSignalDisposition.java b/test/jdk/java/lang/ProcessBuilder/childSignalDisposition/TestChildSignalDisposition.java index 50fe054ee34..80b63b765da 100644 --- a/test/jdk/java/lang/ProcessBuilder/childSignalDisposition/TestChildSignalDisposition.java +++ b/test/jdk/java/lang/ProcessBuilder/childSignalDisposition/TestChildSignalDisposition.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,15 +39,6 @@ * @run main/othervm/native -Djdk.lang.Process.launchMechanism=fork -agentlib:ChangeSignalDisposition TestChildSignalDisposition */ -/** - * @test id=vfork - * @bug 8364611 - * @summary Check that childs start with SIG_DFL as SIGPIPE disposition - * @requires os.family == "linux" - * @library /test/lib - * @run main/othervm/native -Djdk.lang.Process.launchMechanism=vfork -agentlib:ChangeSignalDisposition TestChildSignalDisposition - */ - import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; public class TestChildSignalDisposition { From 61df7cc8b91365e487591ec8402e797a25790a79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20H=C3=A4ssig?= Date: Mon, 30 Mar 2026 06:27:30 +0000 Subject: [PATCH 046/116] 8380988: C2: Unexpected node in SuperWord truncation: UModI/UDivI Reviewed-by: epeter, jkarthikeyan --- src/hotspot/share/opto/superword.cpp | 2 + .../vectorization/TestSubwordTruncation.java | 46 ++++++++++++++++++- 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/opto/superword.cpp b/src/hotspot/share/opto/superword.cpp index d878b2b1d3d..53845a94c1c 100644 --- a/src/hotspot/share/opto/superword.cpp +++ b/src/hotspot/share/opto/superword.cpp @@ -2500,7 +2500,9 @@ static bool can_subword_truncate(Node* in, const Type* type) { switch (opc) { case Op_AbsI: case Op_DivI: + case Op_UDivI: case Op_ModI: + case Op_UModI: case Op_MinI: case Op_MaxI: case Op_CMoveI: diff --git a/test/hotspot/jtreg/compiler/vectorization/TestSubwordTruncation.java b/test/hotspot/jtreg/compiler/vectorization/TestSubwordTruncation.java index 2f6296e41d2..0a80a59efd4 100644 --- a/test/hotspot/jtreg/compiler/vectorization/TestSubwordTruncation.java +++ b/test/hotspot/jtreg/compiler/vectorization/TestSubwordTruncation.java @@ -29,7 +29,7 @@ /* * @test - * @bug 8350177 8362171 8369881 8342095 + * @bug 8350177 8362171 8369881 8342095 8380988 * @summary Ensure that truncation of subword vectors produces correct results * @library /test/lib / * @run driver compiler.vectorization.TestSubwordTruncation @@ -448,6 +448,50 @@ public void testMod() { } } + @Test + @IR(counts = { IRNode.UMOD_I, ">0" }) + @Arguments(setup = "setupByteArray") + public Object[] testUMod(final byte[] in) { + int n = G.next().intValue(); + for (int i = 1; i < SIZE; i++) { + in[i] = (byte) Integer.remainderUnsigned(n, i); + } + + return new Object[] { Integer.valueOf(n), in }; + } + + @Check(test = "testUMod") + public void checkTestUMod(Object[] vals) { + int n = (Integer) vals[0]; + byte[] res = (byte[]) vals[1]; + for (int i = 1; i < SIZE; i++) { + byte val = (byte) Integer.remainderUnsigned(n, i); + Asserts.assertEQ(res[i], val); + } + } + + @Test + @IR(counts = { IRNode.UDIV_I, ">0" }) + @Arguments(setup = "setupByteArray") + public Object[] testUDiv(final byte[] in) { + int n = G.next().intValue(); + for (int i = 1; i < SIZE; i++) { + in[i] = (byte) Integer.divideUnsigned(n, i); + } + + return new Object[] { Integer.valueOf(n), in }; + } + + @Check(test = "testUDiv") + public void checkTestUDiv(Object[] vals) { + int n = (Integer) vals[0]; + byte[] res = (byte[]) vals[1]; + for (int i = 1; i < SIZE; i++) { + byte val = (byte) Integer.divideUnsigned(n, i); + Asserts.assertEQ(res[i], val); + } + } + @Test @IR(counts = { IRNode.CMP_LT_MASK, ">0" }) @Arguments(setup = "setupByteArray") From bbbd5b9984c909773227123ad31b1dd8336df0d9 Mon Sep 17 00:00:00 2001 From: Stefan Johansson Date: Mon, 30 Mar 2026 06:29:43 +0000 Subject: [PATCH 047/116] 8380773: Extend ContainerMemoryUsageEvent to include host memory usage Reviewed-by: mgronlun, tkiriyama, sgehwolf --- src/hotspot/share/jfr/jni/jfrJniMethod.cpp | 9 +++++++++ src/hotspot/share/jfr/jni/jfrJniMethod.hpp | 2 ++ src/hotspot/share/jfr/jni/jfrJniMethodRegistration.cpp | 1 + .../jdk/jfr/events/ContainerMemoryUsageEvent.java | 5 +++++ .../share/classes/jdk/jfr/internal/JDKEvents.java | 1 + src/jdk.jfr/share/classes/jdk/jfr/internal/JVM.java | 6 ++++++ test/hotspot/jtreg/containers/docker/TestJFREvents.java | 4 +++- 7 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/jfr/jni/jfrJniMethod.cpp b/src/hotspot/share/jfr/jni/jfrJniMethod.cpp index 885484020bd..0183bf634f6 100644 --- a/src/hotspot/share/jfr/jni/jfrJniMethod.cpp +++ b/src/hotspot/share/jfr/jni/jfrJniMethod.cpp @@ -410,6 +410,15 @@ JVM_ENTRY_NO_ENV(jlong, jfr_host_total_swap_memory(JNIEnv* env, jclass jvm)) return static_cast(total_swap_space); JVM_END +JVM_ENTRY_NO_ENV(jlong, jfr_host_memory_usage(JNIEnv* env, jclass jvm)) + physical_memory_size_type memory_usage = 0; + if (!os::Machine::used_memory(memory_usage)) { + // Return -1 to signal failure to get memory usage. + return static_cast(-1); + } + return static_cast(memory_usage); +JVM_END + JVM_ENTRY_NO_ENV(void, jfr_emit_data_loss(JNIEnv* env, jclass jvm, jlong bytes)) EventDataLoss::commit(bytes, min_jlong); JVM_END diff --git a/src/hotspot/share/jfr/jni/jfrJniMethod.hpp b/src/hotspot/share/jfr/jni/jfrJniMethod.hpp index 9769df57bd3..bcdaf7a99b7 100644 --- a/src/hotspot/share/jfr/jni/jfrJniMethod.hpp +++ b/src/hotspot/share/jfr/jni/jfrJniMethod.hpp @@ -163,6 +163,8 @@ jlong JNICALL jfr_host_total_memory(JNIEnv* env, jclass jvm); jlong JNICALL jfr_host_total_swap_memory(JNIEnv* env, jclass jvm); +jlong JNICALL jfr_host_memory_usage(JNIEnv* env, jclass jvm); + void JNICALL jfr_emit_data_loss(JNIEnv* env, jclass jvm, jlong bytes); jlong JNICALL jfr_register_stack_filter(JNIEnv* env, jclass jvm, jobjectArray classes, jobjectArray methods); diff --git a/src/hotspot/share/jfr/jni/jfrJniMethodRegistration.cpp b/src/hotspot/share/jfr/jni/jfrJniMethodRegistration.cpp index 2979f5c5c2d..0813289e840 100644 --- a/src/hotspot/share/jfr/jni/jfrJniMethodRegistration.cpp +++ b/src/hotspot/share/jfr/jni/jfrJniMethodRegistration.cpp @@ -101,6 +101,7 @@ JfrJniMethodRegistration::JfrJniMethodRegistration(JNIEnv* env) { (char*)"isContainerized", (char*)"()Z", (void*) jfr_is_containerized, (char*)"hostTotalMemory", (char*)"()J", (void*) jfr_host_total_memory, (char*)"hostTotalSwapMemory", (char*)"()J", (void*) jfr_host_total_swap_memory, + (char*)"hostMemoryUsage", (char*)"()J", (void*) jfr_host_memory_usage, (char*)"emitDataLoss", (char*)"(J)V", (void*)jfr_emit_data_loss, (char*)"registerStackFilter", (char*)"([Ljava/lang/String;[Ljava/lang/String;)J", (void*)jfr_register_stack_filter, (char*)"unregisterStackFilter", (char*)"(J)V", (void*)jfr_unregister_stack_filter, diff --git a/src/jdk.jfr/share/classes/jdk/jfr/events/ContainerMemoryUsageEvent.java b/src/jdk.jfr/share/classes/jdk/jfr/events/ContainerMemoryUsageEvent.java index 285952d0c66..9a83877a967 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/events/ContainerMemoryUsageEvent.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/events/ContainerMemoryUsageEvent.java @@ -50,4 +50,9 @@ public final class ContainerMemoryUsageEvent extends AbstractPeriodicEvent { @Description("Amount of physical memory and swap space, in bytes, that is currently allocated in the current container") @DataAmount public long swapMemoryUsage; + + @Label("Host Memory Usage") + @Description("Amount of physical memory, in bytes, that is currently allocated in the host system") + @DataAmount + public long hostMemoryUsage; } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/JDKEvents.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/JDKEvents.java index 53d40c1e5e1..79bc614545e 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/JDKEvents.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/JDKEvents.java @@ -181,6 +181,7 @@ private static void emitContainerMemoryUsage() { event.memoryFailCount = containerMetrics.getMemoryFailCount(); event.memoryUsage = containerMetrics.getMemoryUsage(); event.swapMemoryUsage = containerMetrics.getMemoryAndSwapUsage(); + event.hostMemoryUsage = JVM.hostMemoryUsage(); event.commit(); } } 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 24c92e81a4c..2aa7dfd6e97 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/JVM.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/JVM.java @@ -657,6 +657,12 @@ public final class JVM { */ public static native long hostTotalSwapMemory(); + /** + * Returns the amount of memory used in the host system whether or not this + * JVM runs in a container. + */ + public static native long hostMemoryUsage(); + /** * Emit a jdk.DataLoss event for the specified amount of bytes. * diff --git a/test/hotspot/jtreg/containers/docker/TestJFREvents.java b/test/hotspot/jtreg/containers/docker/TestJFREvents.java index d46c422723b..c3112310479 100644 --- a/test/hotspot/jtreg/containers/docker/TestJFREvents.java +++ b/test/hotspot/jtreg/containers/docker/TestJFREvents.java @@ -162,6 +162,7 @@ private static void testMemoryUsage() throws Exception { String memoryFailCountFld = "memoryFailCount"; String memoryUsageFld = "memoryUsage"; String swapMemoryUsageFld = "swapMemoryUsage"; + String hostMemoryUsageFld = "hostMemoryUsage"; DockerTestUtils.dockerRunJava( commonDockerOpts() @@ -169,7 +170,8 @@ private static void testMemoryUsage() throws Exception { .shouldHaveExitValue(0) .shouldContain(memoryFailCountFld) .shouldContain(memoryUsageFld) - .shouldContain(swapMemoryUsageFld); + .shouldContain(swapMemoryUsageFld) + .shouldContain(hostMemoryUsageFld); } private static void testIOUsage() throws Exception { From 0885a0c4c548532e87533467315b48465c8b6e20 Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Mon, 30 Mar 2026 06:35:55 +0000 Subject: [PATCH 048/116] 4696824: In Metal and other L&F Button.focusInputMap, CheckBox.focusInputMap ... are same Reviewed-by: tr, prr --- .../swing/plaf/motif/MotifLookAndFeel.java | 27 +++++----------- .../swing/plaf/metal/MetalLookAndFeel.java | 32 ++++++++----------- 2 files changed, 21 insertions(+), 38 deletions(-) diff --git a/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifLookAndFeel.java b/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifLookAndFeel.java index d254443b8d1..5263d248f45 100644 --- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifLookAndFeel.java +++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifLookAndFeel.java @@ -537,6 +537,10 @@ public Object createValue(UIDefaults table) { @SuppressWarnings("deprecation") final int metaMask = KeyEvent.META_MASK; + Object commonInputMap = new UIDefaults.LazyInputMap(new Object[] { + "SPACE", "pressed", + "released SPACE", "released" + }); Object[] defaults = { "Desktop.background", table.get("desktop"), @@ -593,20 +597,13 @@ public Object createValue(UIDefaults table) { "Button.foreground", table.get("controlText"), "Button.select", table.get("controlLightShadow"), "Button.font", dialogPlain12, - "Button.focusInputMap", new UIDefaults.LazyInputMap(new Object[] { - "SPACE", "pressed", - "released SPACE", "released" - }), + "Button.focusInputMap", commonInputMap, "CheckBox.textIconGap", 8, "CheckBox.margin", new InsetsUIResource(4, 2, 4, 2), "CheckBox.icon", checkBoxIcon, "CheckBox.focus", table.get("activeCaptionBorder"), - "CheckBox.focusInputMap", - new UIDefaults.LazyInputMap(new Object[] { - "SPACE", "pressed", - "released SPACE", "released" - }), + "CheckBox.focusInputMap", commonInputMap, "RadioButton.margin", new InsetsUIResource(4, 2, 4, 2), "RadioButton.textIconGap", 8, @@ -615,22 +612,14 @@ public Object createValue(UIDefaults table) { "RadioButton.icon", radioButtonIcon, "RadioButton.focus", table.get("activeCaptionBorder"), "RadioButton.icon", radioButtonIcon, - "RadioButton.focusInputMap", - new UIDefaults.LazyInputMap(new Object[] { - "SPACE", "pressed", - "released SPACE", "released" - }), + "RadioButton.focusInputMap", commonInputMap, "ToggleButton.border", toggleButtonBorder, "ToggleButton.background", table.get("control"), "ToggleButton.foreground", table.get("controlText"), "ToggleButton.focus", table.get("controlText"), "ToggleButton.select", table.get("controlLightShadow"), - "ToggleButton.focusInputMap", - new UIDefaults.LazyInputMap(new Object[] { - "SPACE", "pressed", - "released SPACE", "released" - }), + "ToggleButton.focusInputMap", commonInputMap, // Menus "Menu.border", menuMarginBorder, diff --git a/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalLookAndFeel.java b/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalLookAndFeel.java index 7c56c681423..461c597cc5f 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalLookAndFeel.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalLookAndFeel.java @@ -706,6 +706,11 @@ protected void initComponentDefaults(UIDefaults table) { // DEFAULTS TABLE // + Object commonInputMap = new UIDefaults.LazyInputMap(new Object[] { + "SPACE", "pressed", + "released SPACE", "released" + }); + Object[] defaults = { // *** Auditory Feedback "AuditoryCues.defaultCueList", defaultCueList, @@ -791,6 +796,8 @@ protected void initComponentDefaults(UIDefaults table) { }), + + // Buttons "Button.defaultButtonFollowsFocus", Boolean.FALSE, "Button.disabledText", inactiveControlTextColor, @@ -798,10 +805,8 @@ protected void initComponentDefaults(UIDefaults table) { "Button.border", buttonBorder, "Button.font", controlTextValue, "Button.focus", focusColor, - "Button.focusInputMap", new UIDefaults.LazyInputMap(new Object[] { - "SPACE", "pressed", - "released SPACE", "released" - }), + "Button.focusInputMap", commonInputMap, + // Button default margin is (2, 14, 2, 14), defined in // BasicLookAndFeel via "Button.margin" UI property. @@ -810,11 +815,8 @@ protected void initComponentDefaults(UIDefaults table) { "CheckBox.font", controlTextValue, "CheckBox.focus", focusColor, "CheckBox.icon",(LazyValue) t -> MetalIconFactory.getCheckBoxIcon(), - "CheckBox.focusInputMap", - new UIDefaults.LazyInputMap(new Object[] { - "SPACE", "pressed", - "released SPACE", "released" - }), + "CheckBox.focusInputMap", commonInputMap, + // margin is 2 all the way around, BasicBorders.RadioButtonBorder // (checkbox uses RadioButtonBorder) is 2 all the way around too. "CheckBox.totalInsets", new Insets(4, 4, 4, 4), @@ -824,11 +826,7 @@ protected void initComponentDefaults(UIDefaults table) { "RadioButton.icon",(LazyValue) t -> MetalIconFactory.getRadioButtonIcon(), "RadioButton.font", controlTextValue, "RadioButton.focus", focusColor, - "RadioButton.focusInputMap", - new UIDefaults.LazyInputMap(new Object[] { - "SPACE", "pressed", - "released SPACE", "released" - }), + "RadioButton.focusInputMap", commonInputMap, // margin is 2 all the way around, BasicBorders.RadioButtonBorder // is 2 all the way around too. "RadioButton.totalInsets", new Insets(4, 4, 4, 4), @@ -838,11 +836,7 @@ protected void initComponentDefaults(UIDefaults table) { "ToggleButton.focus", focusColor, "ToggleButton.border", toggleButtonBorder, "ToggleButton.font", controlTextValue, - "ToggleButton.focusInputMap", - new UIDefaults.LazyInputMap(new Object[] { - "SPACE", "pressed", - "released SPACE", "released" - }), + "ToggleButton.focusInputMap", commonInputMap, // File View From 45f9039513d08923e019b50ae5007d9339b9731f Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Mon, 30 Mar 2026 06:48:49 +0000 Subject: [PATCH 049/116] 8380030: [AIX] unify dladdr between hotspot and libawt Reviewed-by: dholmes, stuefe, erikj --- make/common/modules/LauncherCommon.gmk | 10 +-- src/hotspot/os/aix/porting_aix.cpp | 6 +- src/hotspot/os/posix/include/jvm_md.h | 15 +++- .../aix/native/libawt/porting_aix.c | 87 ------------------- .../aix/native/libawt/porting_aix.h | 40 --------- .../unix/native/libawt/awt/awt_LoadLibrary.c | 4 +- 6 files changed, 26 insertions(+), 136 deletions(-) delete mode 100644 src/java.desktop/aix/native/libawt/porting_aix.c delete mode 100644 src/java.desktop/aix/native/libawt/porting_aix.h diff --git a/make/common/modules/LauncherCommon.gmk b/make/common/modules/LauncherCommon.gmk index 859494861b2..8d45142ef4a 100644 --- a/make/common/modules/LauncherCommon.gmk +++ b/make/common/modules/LauncherCommon.gmk @@ -36,16 +36,16 @@ include $(TOPDIR)/make/ToolsJdk.gmk LAUNCHER_SRC := $(TOPDIR)/src/java.base/share/native/launcher -ifeq ($(call isTargetOs, aix), true) - ADD_PLATFORM_INCLUDE_DIR := -I$(TOPDIR)/src/java.base/aix/native/include -endif - LAUNCHER_CFLAGS += -I$(TOPDIR)/src/java.base/share/native/launcher \ -I$(TOPDIR)/src/java.base/share/native/libjli \ - $(ADD_PLATFORM_INCLUDE_DIR) \ -I$(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libjli \ -I$(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS)/native/libjli \ # + +ifeq ($(call isTargetOs, aix), true) + LAUNCHER_CFLAGS += -I$(TOPDIR)/src/java.base/aix/native/include +endif + MACOSX_PLIST_DIR := $(TOPDIR)/src/java.base/macosx/native/launcher JAVA_MANIFEST := $(TOPDIR)/src/java.base/windows/native/launcher/java.manifest diff --git a/src/hotspot/os/aix/porting_aix.cpp b/src/hotspot/os/aix/porting_aix.cpp index b3f878fbfdd..f0527136d90 100644 --- a/src/hotspot/os/aix/porting_aix.cpp +++ b/src/hotspot/os/aix/porting_aix.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2024 SAP SE. All rights reserved. + * Copyright (c) 2012, 2026 SAP SE. All rights reserved. * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -426,6 +426,10 @@ int dladdr(void* addr, Dl_info* info) { } +int JVM_dladdr(void* addr, Dl_info* info) { + return dladdr(addr, info); +} + ///////////////////////////////////////////////////////////////////////////// // Native callstack dumping diff --git a/src/hotspot/os/posix/include/jvm_md.h b/src/hotspot/os/posix/include/jvm_md.h index eb8e1f0d7e9..061ef17aaae 100644 --- a/src/hotspot/os/posix/include/jvm_md.h +++ b/src/hotspot/os/posix/include/jvm_md.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -62,6 +62,19 @@ #define JVM_X_OK X_OK #define JVM_F_OK F_OK +#if defined(AIX) +#include "jni_md.h" +#include "dl_info.h" + +#ifdef __cplusplus +extern "C" { +#endif +JNIEXPORT int JVM_dladdr(void* addr, Dl_info* info); +#ifdef __cplusplus +} +#endif +#endif + /* * File I/O */ diff --git a/src/java.desktop/aix/native/libawt/porting_aix.c b/src/java.desktop/aix/native/libawt/porting_aix.c deleted file mode 100644 index d8688c212d7..00000000000 --- a/src/java.desktop/aix/native/libawt/porting_aix.c +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2012, 2026 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 - * 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. - * - */ - -#include -#include -#include -#include - -#include "porting_aix.h" - -static unsigned char dladdr_buffer[0x8000]; - -static void fill_dll_info(void) { - int rc = loadquery(L_GETINFO,dladdr_buffer, sizeof(dladdr_buffer)); - if (rc == -1) { - fprintf(stderr, "loadquery failed (%d %s)", errno, strerror(errno)); - fflush(stderr); - } -} - -static int dladdr_dont_reload(void* addr, Dl_info* info) { - const struct ld_info* p = (struct ld_info*) dladdr_buffer; - memset((void *)info, 0, sizeof(Dl_info)); - for (;;) { - if (addr >= p->ldinfo_textorg && - (char*)addr < (char*)(p->ldinfo_textorg) + p->ldinfo_textsize) { - info->dli_fname = p->ldinfo_filename; - return 1; - } - if (!p->ldinfo_next) { - break; - } - p = (struct ld_info*)(((char*)p) + p->ldinfo_next); - } - return 0; -} - -#ifdef __cplusplus -extern "C" -#endif -int dladdr(void *addr, Dl_info *info) { - static int loaded = 0; - if (!loaded) { - fill_dll_info(); - loaded = 1; - } - if (!addr) { - return 0; - } - /* Address could be AIX function descriptor? */ - void* const addr0 = *( (void**) addr ); - int rc = dladdr_dont_reload(addr, info); - if (rc == 0) { - rc = dladdr_dont_reload(addr0, info); - if (rc == 0) { - fill_dll_info(); /* refill, maybe loadquery info is outdated */ - rc = dladdr_dont_reload(addr, info); - if (rc == 0) { - rc = dladdr_dont_reload(addr0, info); - } - } - } - return rc; -} diff --git a/src/java.desktop/aix/native/libawt/porting_aix.h b/src/java.desktop/aix/native/libawt/porting_aix.h deleted file mode 100644 index 04d11590915..00000000000 --- a/src/java.desktop/aix/native/libawt/porting_aix.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2012, 2026 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 - * 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. - * - */ - -/* - * Aix' own version of dladdr(). - * This function tries to mimic dladdr(3) on Linux - * (see http://linux.die.net/man/3/dladdr) - * dladdr(3) is not POSIX but a GNU extension, and is not available on AIX. - * - */ - -#include "dl_info.h" - -#ifdef __cplusplus -extern "C" -#endif -int dladdr(void *addr, Dl_info *info); diff --git a/src/java.desktop/unix/native/libawt/awt/awt_LoadLibrary.c b/src/java.desktop/unix/native/libawt/awt/awt_LoadLibrary.c index cd07c347c9e..af50fdbb5c0 100644 --- a/src/java.desktop/unix/native/libawt/awt/awt_LoadLibrary.c +++ b/src/java.desktop/unix/native/libawt/awt/awt_LoadLibrary.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,7 +36,7 @@ #include #ifdef AIX -#include "porting_aix.h" /* For the 'dladdr' function. */ +#define dladdr JVM_dladdr #endif #ifdef DEBUG From cd9724565d295e125484fb2933c0479ceabbaabe Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Mon, 30 Mar 2026 08:37:25 +0000 Subject: [PATCH 050/116] 8381205: GHA: Upgrade Node.js 20 to 24 Reviewed-by: erikj --- .github/actions/build-jtreg/action.yml | 6 +++--- .github/actions/do-build/action.yml | 4 ++-- .github/actions/get-bootjdk/action.yml | 2 +- .github/actions/get-bundles/action.yml | 6 +++--- .github/actions/get-gtest/action.yml | 2 +- .github/actions/get-jtreg/action.yml | 2 +- .github/actions/get-msys2/action.yml | 2 +- .github/actions/upload-bundles/action.yml | 2 +- .github/workflows/build-alpine-linux.yml | 2 +- .github/workflows/build-cross-compile.yml | 4 ++-- .github/workflows/build-linux.yml | 2 +- .github/workflows/build-macos.yml | 2 +- .github/workflows/build-windows.yml | 2 +- .github/workflows/main.yml | 2 +- .github/workflows/test.yml | 6 +++--- 15 files changed, 23 insertions(+), 23 deletions(-) diff --git a/.github/actions/build-jtreg/action.yml b/.github/actions/build-jtreg/action.yml index a9c046e9dd9..334812e8341 100644 --- a/.github/actions/build-jtreg/action.yml +++ b/.github/actions/build-jtreg/action.yml @@ -37,13 +37,13 @@ runs: - name: 'Check cache for already built JTReg' id: get-cached - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: jtreg/installed key: jtreg-${{ steps.version.outputs.value }} - name: 'Checkout the JTReg source' - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: repository: openjdk/jtreg ref: jtreg-${{ steps.version.outputs.value }} @@ -61,7 +61,7 @@ runs: if: (steps.get-cached.outputs.cache-hit != 'true') - name: 'Upload JTReg artifact' - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: bundles-jtreg-${{ steps.version.outputs.value }} path: jtreg/installed diff --git a/.github/actions/do-build/action.yml b/.github/actions/do-build/action.yml index 6f2c2ce0218..6f6bbdabb68 100644 --- a/.github/actions/do-build/action.yml +++ b/.github/actions/do-build/action.yml @@ -66,7 +66,7 @@ runs: shell: bash - name: 'Upload build logs' - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: failure-logs-${{ inputs.platform }}${{ inputs.debug-suffix }} path: failure-logs @@ -74,7 +74,7 @@ runs: # This is the best way I found to abort the job with an error message - name: 'Notify about build failures' - uses: actions/github-script@v7 + uses: actions/github-script@v8 with: script: core.setFailed('Build failed. See summary for details.') if: steps.check.outputs.failure == 'true' diff --git a/.github/actions/get-bootjdk/action.yml b/.github/actions/get-bootjdk/action.yml index 312fb642c82..d531358b7dd 100644 --- a/.github/actions/get-bootjdk/action.yml +++ b/.github/actions/get-bootjdk/action.yml @@ -65,7 +65,7 @@ runs: - name: 'Check cache for BootJDK' id: get-cached-bootjdk - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: bootjdk/jdk key: boot-jdk-${{ inputs.platform }}-${{ steps.sha256.outputs.value }} diff --git a/.github/actions/get-bundles/action.yml b/.github/actions/get-bundles/action.yml index a356aa9fd8d..55fa0e842d2 100644 --- a/.github/actions/get-bundles/action.yml +++ b/.github/actions/get-bundles/action.yml @@ -54,14 +54,14 @@ runs: steps: - name: 'Download bundles artifact' id: download-bundles - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 with: name: bundles-${{ inputs.platform }}${{ inputs.debug-suffix }} path: bundles continue-on-error: true - name: 'Download bundles artifact (retry)' - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 with: name: bundles-${{ inputs.platform }}${{ inputs.debug-suffix }} path: bundles @@ -69,7 +69,7 @@ runs: - name: 'Download static bundles artifact' id: download-static-bundles - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 with: name: bundles-${{ inputs.platform }}${{ inputs.debug-suffix }}${{ inputs.static-suffix }} path: bundles diff --git a/.github/actions/get-gtest/action.yml b/.github/actions/get-gtest/action.yml index 7a329460a6e..bc53fa2a3b1 100644 --- a/.github/actions/get-gtest/action.yml +++ b/.github/actions/get-gtest/action.yml @@ -40,7 +40,7 @@ runs: var: GTEST_VERSION - name: 'Checkout GTest source' - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: repository: google/googletest ref: 'v${{ steps.version.outputs.value }}' diff --git a/.github/actions/get-jtreg/action.yml b/.github/actions/get-jtreg/action.yml index 36c895fc59d..8c75ae10c7f 100644 --- a/.github/actions/get-jtreg/action.yml +++ b/.github/actions/get-jtreg/action.yml @@ -41,7 +41,7 @@ runs: - name: 'Download JTReg artifact' id: download-jtreg - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 with: name: bundles-jtreg-${{ steps.version.outputs.value }} path: jtreg/installed diff --git a/.github/actions/get-msys2/action.yml b/.github/actions/get-msys2/action.yml index 308230ebf2e..7351a120ac4 100644 --- a/.github/actions/get-msys2/action.yml +++ b/.github/actions/get-msys2/action.yml @@ -31,7 +31,7 @@ runs: steps: - name: 'Install MSYS2' id: msys2 - uses: msys2/setup-msys2@v2.28.0 + uses: msys2/setup-msys2@v2.31.0 with: install: 'autoconf tar unzip zip make' path-type: minimal diff --git a/.github/actions/upload-bundles/action.yml b/.github/actions/upload-bundles/action.yml index 78fb0a94bfd..94308002ea7 100644 --- a/.github/actions/upload-bundles/action.yml +++ b/.github/actions/upload-bundles/action.yml @@ -87,7 +87,7 @@ runs: shell: bash - name: 'Upload bundles artifact' - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: bundles-${{ inputs.platform }}${{ inputs.debug-suffix }}${{ inputs.static-suffix }}${{ inputs.bundle-suffix }} path: bundles diff --git a/.github/workflows/build-alpine-linux.yml b/.github/workflows/build-alpine-linux.yml index c39962fa07f..6863da9016e 100644 --- a/.github/workflows/build-alpine-linux.yml +++ b/.github/workflows/build-alpine-linux.yml @@ -74,7 +74,7 @@ jobs: steps: - name: 'Checkout the JDK source' - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: 'Install toolchain and dependencies' run: | diff --git a/.github/workflows/build-cross-compile.yml b/.github/workflows/build-cross-compile.yml index a0642d469aa..99b6c40606c 100644 --- a/.github/workflows/build-cross-compile.yml +++ b/.github/workflows/build-cross-compile.yml @@ -94,7 +94,7 @@ jobs: steps: - name: 'Checkout the JDK source' - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: 'Get the BootJDK' id: bootjdk @@ -122,7 +122,7 @@ jobs: - name: 'Check cache for sysroot' id: get-cached-sysroot - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: sysroot key: sysroot-${{ matrix.debian-arch }}-${{ hashFiles('./.github/workflows/build-cross-compile.yml') }} diff --git a/.github/workflows/build-linux.yml b/.github/workflows/build-linux.yml index 791b53a3f04..c501670439e 100644 --- a/.github/workflows/build-linux.yml +++ b/.github/workflows/build-linux.yml @@ -84,7 +84,7 @@ jobs: steps: - name: 'Checkout the JDK source' - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: 'Get the BootJDK' id: bootjdk diff --git a/.github/workflows/build-macos.yml b/.github/workflows/build-macos.yml index 484e616fad7..435576f4afd 100644 --- a/.github/workflows/build-macos.yml +++ b/.github/workflows/build-macos.yml @@ -75,7 +75,7 @@ jobs: steps: - name: 'Checkout the JDK source' - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: 'Get the BootJDK' id: bootjdk diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index 4dafc016a99..3bb50a137ec 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -83,7 +83,7 @@ jobs: steps: - name: 'Checkout the JDK source' - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: 'Get MSYS2' uses: ./.github/actions/get-msys2 diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 85ec75f343c..20be196b128 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -75,7 +75,7 @@ jobs: steps: - name: 'Checkout the scripts' - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: sparse-checkout: | .github diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8f33454305e..b240b42fb97 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -128,7 +128,7 @@ jobs: steps: - name: 'Checkout the JDK source' - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: 'Get MSYS2' uses: ./.github/actions/get-msys2 @@ -239,7 +239,7 @@ jobs: if: always() - name: 'Upload test results' - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: path: results name: ${{ steps.package.outputs.artifact-name }} @@ -247,7 +247,7 @@ jobs: # This is the best way I found to abort the job with an error message - name: 'Notify about test failures' - uses: actions/github-script@v7 + uses: actions/github-script@v8 with: script: core.setFailed('${{ steps.run-tests.outputs.error-message }}') if: steps.run-tests.outputs.failure == 'true' From 29e1ee2eccd59e665827e0d42c490261002cf99e Mon Sep 17 00:00:00 2001 From: Martin Doerr Date: Mon, 30 Mar 2026 08:58:21 +0000 Subject: [PATCH 051/116] 8380565: PPC64: deoptimization stub should save vector registers Co-authored-by: Richard Reingruber Reviewed-by: rrich, dbriemann --- src/hotspot/cpu/ppc/registerMap_ppc.cpp | 46 ++ src/hotspot/cpu/ppc/registerMap_ppc.hpp | 8 +- src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp | 27 +- src/hotspot/cpu/ppc/vm_version_ppc.cpp | 3 +- .../vectorapi/TestVectorReallocation.java | 414 ++++++++++++++++++ 5 files changed, 483 insertions(+), 15 deletions(-) create mode 100644 src/hotspot/cpu/ppc/registerMap_ppc.cpp create mode 100644 test/hotspot/jtreg/compiler/vectorapi/TestVectorReallocation.java diff --git a/src/hotspot/cpu/ppc/registerMap_ppc.cpp b/src/hotspot/cpu/ppc/registerMap_ppc.cpp new file mode 100644 index 00000000000..2e7f8af89d3 --- /dev/null +++ b/src/hotspot/cpu/ppc/registerMap_ppc.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2026 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 + * 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 "runtime/registerMap.hpp" + +address RegisterMap::pd_location(VMReg base_reg, int slot_idx) const { + if (base_reg->is_VectorRegister()) { + // Not all physical slots belonging to a VectorRegister have corresponding + // valid VMReg locations in the RegisterMap. + // (See RegisterSaver::push_frame_reg_args_and_save_live_registers.) + // However, the slots are always saved to the stack in a contiguous region + // of memory so we can calculate the address of the upper slots by + // offsetting from the base address. + assert(base_reg->is_concrete(), "must pass base reg"); + address base_location = location(base_reg, nullptr); + if (base_location != nullptr) { + intptr_t offset_in_bytes = slot_idx * VMRegImpl::stack_slot_size; + return base_location + offset_in_bytes; + } else { + return nullptr; + } + } else { + return location(base_reg->next(slot_idx), nullptr); + } +} diff --git a/src/hotspot/cpu/ppc/registerMap_ppc.hpp b/src/hotspot/cpu/ppc/registerMap_ppc.hpp index 01eb642107c..607c712d10f 100644 --- a/src/hotspot/cpu/ppc/registerMap_ppc.hpp +++ b/src/hotspot/cpu/ppc/registerMap_ppc.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2013 SAP SE. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2026 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 @@ -35,9 +35,7 @@ // Since there is none, we just return null. address pd_location(VMReg reg) const { return nullptr; } - address pd_location(VMReg base_reg, int slot_idx) const { - return location(base_reg->next(slot_idx), nullptr); - } + address pd_location(VMReg base_reg, int slot_idx) const; // no PD state to clear or copy: void pd_clear() {} diff --git a/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp b/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp index 5260ed978ff..53644210415 100644 --- a/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp +++ b/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp @@ -102,7 +102,7 @@ class RegisterSaver { // During deoptimization only the result registers need to be restored // all the other values have already been extracted. - static void restore_result_registers(MacroAssembler* masm, int frame_size_in_bytes); + static void restore_result_registers(MacroAssembler* masm, int frame_size_in_bytes, bool save_vectors); // Constants and data structures: @@ -349,7 +349,7 @@ OopMap* RegisterSaver::push_frame_reg_args_and_save_live_registers(MacroAssemble } // Note that generate_oop_map in the following loop is only used for the - // polling_page_vectors_safepoint_handler_blob. + // polling_page_vectors_safepoint_handler_blob and the deopt_blob. // The order in which the vector contents are stored depends on Endianess and // the utilized instructions (PowerArchitecturePPC64). assert(is_aligned(offset, StackAlignmentInBytes), "should be"); @@ -361,6 +361,7 @@ OopMap* RegisterSaver::push_frame_reg_args_and_save_live_registers(MacroAssemble __ stxvp(as_VectorRegister(reg_num).to_vsr(), offset, R1_SP); // Note: The contents were read in the same order (see loadV16_Power9 node in ppc.ad). + // RegisterMap::pd_location only uses the first VMReg for each VectorRegister. if (generate_oop_map) { map->set_callee_saved(VMRegImpl::stack2reg(offset >> 2), RegisterSaver_LiveVecRegs[i LITTLE_ENDIAN_ONLY(+1) ].vmreg); @@ -380,6 +381,7 @@ OopMap* RegisterSaver::push_frame_reg_args_and_save_live_registers(MacroAssemble __ stxvd2x(as_VectorRegister(reg_num)->to_vsr(), R31, R1_SP); } // Note: The contents were read in the same order (see loadV16_Power8 / loadV16_Power9 node in ppc.ad). + // RegisterMap::pd_location only uses the first VMReg for each VectorRegister. if (generate_oop_map) { VMReg vsr = RegisterSaver_LiveVecRegs[i].vmreg; map->set_callee_saved(VMRegImpl::stack2reg(offset >> 2), vsr); @@ -566,10 +568,14 @@ void RegisterSaver::restore_argument_registers_and_pop_frame(MacroAssembler*masm } // Restore the registers that might be holding a result. -void RegisterSaver::restore_result_registers(MacroAssembler* masm, int frame_size_in_bytes) { +void RegisterSaver::restore_result_registers(MacroAssembler* masm, int frame_size_in_bytes, bool save_vectors) { const int regstosave_num = sizeof(RegisterSaver_LiveRegs) / sizeof(RegisterSaver::LiveRegType); - const int register_save_size = regstosave_num * reg_size; // VS registers not relevant here. + const int vecregstosave_num = save_vectors ? (sizeof(RegisterSaver_LiveVecRegs) / + sizeof(RegisterSaver::LiveRegType)) + : 0; + const int register_save_size = regstosave_num * reg_size + vecregstosave_num * vec_reg_size; + const int register_save_offset = frame_size_in_bytes - register_save_size; // restore all result registers (ints and floats) @@ -598,7 +604,7 @@ void RegisterSaver::restore_result_registers(MacroAssembler* masm, int frame_siz offset += reg_size; } - assert(offset == frame_size_in_bytes, "consistency check"); + assert(offset == frame_size_in_bytes - (save_vectors ? vecregstosave_num * vec_reg_size : 0), "consistency check"); } // Is vector's size (in bytes) bigger than a size saved by default? @@ -2909,7 +2915,8 @@ void SharedRuntime::generate_deopt_blob() { map = RegisterSaver::push_frame_reg_args_and_save_live_registers(masm, &first_frame_size_in_bytes, /*generate_oop_map=*/ true, - RegisterSaver::return_pc_is_lr); + RegisterSaver::return_pc_is_lr, + /*save_vectors*/ SuperwordUseVSX); assert(map != nullptr, "OopMap must have been created"); __ li(exec_mode_reg, Deoptimization::Unpack_deopt); @@ -2943,7 +2950,8 @@ void SharedRuntime::generate_deopt_blob() { RegisterSaver::push_frame_reg_args_and_save_live_registers(masm, &first_frame_size_in_bytes, /*generate_oop_map=*/ false, - RegisterSaver::return_pc_is_pre_saved); + RegisterSaver::return_pc_is_pre_saved, + /*save_vectors*/ SuperwordUseVSX); // Deopt during an exception. Save exec mode for unpack_frames. __ li(exec_mode_reg, Deoptimization::Unpack_exception); @@ -2958,7 +2966,8 @@ void SharedRuntime::generate_deopt_blob() { RegisterSaver::push_frame_reg_args_and_save_live_registers(masm, &first_frame_size_in_bytes, /*generate_oop_map=*/ false, - RegisterSaver::return_pc_is_pre_saved); + RegisterSaver::return_pc_is_pre_saved, + /*save_vectors*/ SuperwordUseVSX); __ li(exec_mode_reg, Deoptimization::Unpack_reexecute); #endif @@ -2984,7 +2993,7 @@ void SharedRuntime::generate_deopt_blob() { // Restore only the result registers that have been saved // by save_volatile_registers(...). - RegisterSaver::restore_result_registers(masm, first_frame_size_in_bytes); + RegisterSaver::restore_result_registers(masm, first_frame_size_in_bytes, /*save_vectors*/ SuperwordUseVSX); // reload the exec mode from the UnrollBlock (it might have changed) __ lwz(exec_mode_reg, in_bytes(Deoptimization::UnrollBlock::unpack_kind_offset()), unroll_block_reg); diff --git a/src/hotspot/cpu/ppc/vm_version_ppc.cpp b/src/hotspot/cpu/ppc/vm_version_ppc.cpp index e471f5a6e4f..0b69ef7d25a 100644 --- a/src/hotspot/cpu/ppc/vm_version_ppc.cpp +++ b/src/hotspot/cpu/ppc/vm_version_ppc.cpp @@ -25,6 +25,7 @@ #include "asm/assembler.inline.hpp" #include "asm/macroAssembler.inline.hpp" +#include "compiler/compilerDefinitions.inline.hpp" #include "compiler/disassembler.hpp" #include "jvm.h" #include "memory/resourceArea.hpp" @@ -105,7 +106,7 @@ void VM_Version::initialize() { if (PowerArchitecturePPC64 >= 9) { // Performance is good since Power9. - if (FLAG_IS_DEFAULT(SuperwordUseVSX)) { + if (FLAG_IS_DEFAULT(SuperwordUseVSX) && CompilerConfig::is_c2_enabled()) { FLAG_SET_ERGO(SuperwordUseVSX, true); } } diff --git a/test/hotspot/jtreg/compiler/vectorapi/TestVectorReallocation.java b/test/hotspot/jtreg/compiler/vectorapi/TestVectorReallocation.java new file mode 100644 index 00000000000..1bdc6ea726d --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorapi/TestVectorReallocation.java @@ -0,0 +1,414 @@ +/* + * Copyright (c) 2026 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 + * 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.Arrays; + +import compiler.lib.ir_framework.*; + +import jdk.incubator.vector.ByteVector; +import jdk.incubator.vector.ShortVector; +import jdk.incubator.vector.IntVector; +import jdk.incubator.vector.LongVector; +import jdk.incubator.vector.FloatVector; +import jdk.incubator.vector.DoubleVector; +import jdk.incubator.vector.VectorSpecies; + +import static jdk.test.lib.Asserts.*; + +/** + * @test + * @bug 8380565 + * @library /test/lib / + * @summary Test deoptimization involving vector reallocation + * @modules jdk.incubator.vector + * @requires vm.opt.final.MaxVectorSize == null | vm.opt.final.MaxVectorSize >= 16 + * + * @run driver compiler.vectorapi.TestVectorReallocation + */ + +public class TestVectorReallocation { + + private static final VectorSpecies B_SPECIES = ByteVector.SPECIES_PREFERRED; + private static final VectorSpecies S_SPECIES = ShortVector.SPECIES_PREFERRED; + private static final VectorSpecies I_SPECIES = IntVector.SPECIES_PREFERRED; + private static final VectorSpecies L_SPECIES = LongVector.SPECIES_PREFERRED; + private static final VectorSpecies F_SPECIES = FloatVector.SPECIES_PREFERRED; + private static final VectorSpecies D_SPECIES = DoubleVector.SPECIES_PREFERRED; + private static final int B_LENGTH = B_SPECIES.length(); + private static final int S_LENGTH = S_SPECIES.length(); + private static final int I_LENGTH = I_SPECIES.length(); + private static final int L_LENGTH = L_SPECIES.length(); + private static final int F_LENGTH = F_SPECIES.length(); + private static final int D_LENGTH = D_SPECIES.length(); + + // The input arrays for the @Test methods match the length of the preferred species for each type + private static byte[] b_a; + private static short[] s_a; + private static int[] i_a; + private static long[] l_a; + private static float[] f_a; + private static double[] d_a; + + // The output arrays for the @Test methods + private static byte[] b_r; + private static short[] s_r; + private static int[] i_r; + private static long[] l_r; + private static float[] f_r; + private static double[] d_r; + + public static void main(String[] args) { + TestFramework.runWithFlags("--add-modules=jdk.incubator.vector"); + } + + // The test methods annotated with @Test are warmed up by the framework. The calls are indirect + // through the runner methods annotated with @Run. Note that each @Test method has its own instance of + // the test class TestVectorReallocation as receiver of the calls. + // + // The @Test methods just copy the elements of the input array (0, 1, 2, 3, ...) to the output array + // by means of a vector add operation. The added value is computed but actually always zero. The + // computation is done in a loop with a virtual call that is inlined based on class hierarchy analysis + // when the method gets compiled. + // + // The final call after warmup of the now compiled @Test method is performed concurrently in a second + // thread. Before the variable `loopIterations` is set very high such that the loop runs practically + // infinitely. While the loop is running, a class with an overridden version of the method `value` + // (called in the loop) is loaded. This invalidates the result of the class hierarchy analysis that + // there is just one implementation of the method and causes deoptimization where the vector `v0` used + // in the @Test method is reallocated from a register to the java heap. Finally it is verified that + // input and ouput arrays are equal. + // + // NB: each @Test needs its own Zero class for the desired result of the class hierarchy analysis. + + volatile boolean enteredLoop; + volatile long loopIterations; + + void sharedRunner(RunInfo runInfo, Runnable test, Runnable loadOverridingClass, Runnable verify) { + enteredLoop = false; + if (runInfo.isWarmUp()) { + loopIterations = 100; + test.run(); + } else { + loopIterations = 1L << 60; // basically infinite + Thread t = Thread.ofPlatform().start(test); + waitUntilLoopEntered(); + loadOverridingClass.run(); // invalidates inlining causing deoptimization/reallocation of v0 + loopIterations = 0; + waitUntilLoopLeft(); + joinThread(t); + verify.run(); // verify that input and ouput arrays are equal + } + } + + ///////////////////////////////////////////////////////////////////////////////////// + // byte + + static class ByteZero { + volatile byte zero; + byte value() { + return zero; + } + } + volatile ByteZero byteZero = new ByteZero(); + + @Run(test = "byteIdentityWithReallocation") + void byteIdentityWithReallocation_runner(RunInfo runInfo) { + sharedRunner(runInfo, () -> byteIdentityWithReallocation(), () -> { + // Loading the class with the overridden method will cause deoptimization and reallocation of v0 + byteZero = new ByteZero() { + @Override + byte value() { + return super.value(); // override but doing the same + } + }; + }, + () -> assertTrue(Arrays.equals(b_a, b_r), "Input/Output arrays differ")); + } + + @Test + @IR(counts = {IRNode.ADD_VB, " >0 "}) + void byteIdentityWithReallocation() { + ByteVector v0 = ByteVector.fromArray(B_SPECIES, b_a, 0); + byte zeroSum = 0; + enteredLoop = true; + for (long i = 0; i < loopIterations; i++) { + zeroSum += byteZero.value(); // inlined based on class hierarchy analysis + } + v0.add(zeroSum).intoArray(b_r, 0); + enteredLoop = false; + } + + ///////////////////////////////////////////////////////////////////////////////////// + // short + + static class ShortZero { + volatile short zero; + short value() { + return zero; + } + } + volatile ShortZero shortZero = new ShortZero(); + + @Run(test = "shortIdentityWithReallocation") + void shortIdentityWithReallocation_runner(RunInfo runInfo) { + sharedRunner(runInfo, () -> shortIdentityWithReallocation(), () -> { + // Loading the class with the overridden method will cause deoptimization and reallocation of v0 + shortZero = new ShortZero() { + @Override + short value() { + return super.value(); // override but doing the same + } + }; + }, + () -> assertTrue(Arrays.equals(s_a, s_r), "Input/Output arrays differ")); + } + + @Test + @IR(counts = {IRNode.ADD_VS, " >0 "}) + void shortIdentityWithReallocation() { + ShortVector v0 = ShortVector.fromArray(S_SPECIES, s_a, 0); + short zeroSum = 0; + enteredLoop = true; + for (long i = 0; i < loopIterations; i++) { + zeroSum += shortZero.value(); // inlined based on class hierarchy analysis + } + v0.add(zeroSum).intoArray(s_r, 0); + enteredLoop = false; + } + + ///////////////////////////////////////////////////////////////////////////////////// + // int + + static class IntZero { + volatile int zero; + int value() { + return zero; + } + } + volatile IntZero intZero = new IntZero(); + + @Run(test = "intIdentityWithReallocation") + void intIdentityWithReallocation_runner(RunInfo runInfo) { + sharedRunner(runInfo, () -> intIdentityWithReallocation(), () -> { + // Loading the class with the overridden method will cause deoptimization and reallocation of v0 + intZero = new IntZero() { + @Override + int value() { + return super.value(); // override but doing the same + } + }; + }, + () -> assertTrue(Arrays.equals(i_a, i_r), "Input/Output arrays differ")); + } + + @Test + @IR(counts = {IRNode.ADD_VI, " >0 "}) + void intIdentityWithReallocation() { + IntVector v0 = IntVector.fromArray(I_SPECIES, i_a, 0); + int zeroSum = 0; + enteredLoop = true; + for (long i = 0; i < loopIterations; i++) { + zeroSum += intZero.value(); // inlined based on class hierarchy analysis + } + v0.add(zeroSum).intoArray(i_r, 0); + enteredLoop = false; + } + + ///////////////////////////////////////////////////////////////////////////////////// + // long + + static class LongZero { + volatile long zero; + long value() { + return zero; + } + } + volatile LongZero longZero = new LongZero(); + + @Run(test = "longIdentityWithReallocation") + void longIdentityWithReallocation_runner(RunInfo runInfo) { + sharedRunner(runInfo, () -> longIdentityWithReallocation(), () -> { + // Loading the class with the overridden method will cause deoptimization and reallocation of v0 + longZero = new LongZero() { + @Override + long value() { + return super.value(); // override but doing the same + } + }; + }, + () -> assertTrue(Arrays.equals(l_a, l_r), "Input/Output arrays differ")); + } + + @Test + @IR(counts = {IRNode.ADD_VL, " >0 "}) + void longIdentityWithReallocation() { + LongVector v0 = LongVector.fromArray(L_SPECIES, l_a, 0); + long zeroSum = 0; + enteredLoop = true; + for (long i = 0; i < loopIterations; i++) { + zeroSum += longZero.value(); // inlined based on class hierarchy analysis + } + v0.add(zeroSum).intoArray(l_r, 0); + enteredLoop = false; + } + + ///////////////////////////////////////////////////////////////////////////////////// + // float + + static class FloatZero { + volatile float zero; + float value() { + return zero; + } + } + volatile FloatZero floatZero = new FloatZero(); + + @Run(test = "floatIdentityWithReallocation") + void floatIdentityWithReallocation_runner(RunInfo runInfo) { + sharedRunner(runInfo, () -> floatIdentityWithReallocation(), () -> { + // Loading the class with the overridden method will cause deoptimization and reallocation of v0 + floatZero = new FloatZero() { + @Override + float value() { + return super.value(); // override but doing the same + } + }; + }, + () -> assertTrue(Arrays.equals(f_a, f_r), "Input/Output arrays differ")); + } + + @Test + @IR(counts = {IRNode.ADD_VF, " >0 "}) + void floatIdentityWithReallocation() { + FloatVector v0 = FloatVector.fromArray(F_SPECIES, f_a, 0); + float zeroSum = 0; + enteredLoop = true; + for (long i = 0; i < loopIterations; i++) { + zeroSum += floatZero.value(); // inlined based on class hierarchy analysis + } + v0.add(zeroSum).intoArray(f_r, 0); + enteredLoop = false; + } + + ///////////////////////////////////////////////////////////////////////////////////// + // double + + static class DoubleZero { + volatile double zero; + double value() { + return zero; + } + } + volatile DoubleZero doubleZero = new DoubleZero(); + + @Run(test = "doubleIdentityWithReallocation") + void doubleIdentityWithReallocation_runner(RunInfo runInfo) { + sharedRunner(runInfo, () -> doubleIdentityWithReallocation(), () -> { + // Loading the class with the overridden method will cause deoptimization and reallocation of v0 + doubleZero = new DoubleZero() { + @Override + double value() { + return super.value(); // override but doing the same + } + }; + }, + () -> assertTrue(Arrays.equals(d_a, d_r), "Input/Output arrays differ")); + } + + @Test + @IR(counts = {IRNode.ADD_VD, " >0 "}) + void doubleIdentityWithReallocation() { + DoubleVector v0 = DoubleVector.fromArray(D_SPECIES, d_a, 0); + double zeroSum = 0; + enteredLoop = true; + for (long i = 0; i < loopIterations; i++) { + zeroSum += doubleZero.value(); // inlined based on class hierarchy analysis + } + v0.add(zeroSum).intoArray(d_r, 0); + enteredLoop = false; + } + + ///////////////////////////////////////////////////////////////////////////////////// + + private void waitUntilLoopEntered() { + while (!enteredLoop) { + sleep(10); + } + } + + private void waitUntilLoopLeft() { + while (enteredLoop) { + sleep(10); + } + } + + private static void sleep(int ms) { + try { + Thread.sleep(ms); + } catch (InterruptedException e) { /* ignore */ } + } + + private static void joinThread(Thread t) { + try { + t.join(); + } catch (InterruptedException e) { /* ignore */ } + } + + static { + b_a = new byte[B_LENGTH]; + s_a = new short[S_LENGTH]; + i_a = new int[I_LENGTH]; + l_a = new long[L_LENGTH]; + f_a = new float[F_LENGTH]; + d_a = new double[D_LENGTH]; + + b_r = new byte[B_LENGTH]; + s_r = new short[S_LENGTH]; + i_r = new int[I_LENGTH]; + l_r = new long[L_LENGTH]; + f_r = new float[F_LENGTH]; + d_r = new double[D_LENGTH]; + + for (int i = 0; i < b_a.length ; i++) { + b_a[i] = (byte)i; + } + for (int i = 0; i < s_a.length ; i++) { + s_a[i] = (short)i; + } + for (int i = 0; i < i_a.length ; i++) { + i_a[i] = i; + } + for (int i = 0; i < l_a.length ; i++) { + l_a[i] = i; + } + for (int i = 0; i < f_a.length ; i++) { + f_a[i] = i; + } + for (int i = 0; i < d_a.length ; i++) { + d_a[i] = i; + } + } +} From 4d7c13950954950201834e9d4afebdd36a522a81 Mon Sep 17 00:00:00 2001 From: Casper Norrbin Date: Mon, 30 Mar 2026 09:28:51 +0000 Subject: [PATCH 052/116] 8379415: Contended classes can leave unused alignment padding Reviewed-by: coleenp, fparain, lfoltan, liach --- .../share/classfile/fieldLayoutBuilder.cpp | 24 +- .../share/classfile/fieldLayoutBuilder.hpp | 4 +- .../runtime/contended/MixedPrimitives.java | 356 ++++++++++++++++++ 3 files changed, 376 insertions(+), 8 deletions(-) create mode 100644 test/hotspot/jtreg/runtime/contended/MixedPrimitives.java diff --git a/src/hotspot/share/classfile/fieldLayoutBuilder.cpp b/src/hotspot/share/classfile/fieldLayoutBuilder.cpp index a87e12edc96..8a9f5946091 100644 --- a/src/hotspot/share/classfile/fieldLayoutBuilder.cpp +++ b/src/hotspot/share/classfile/fieldLayoutBuilder.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -596,11 +596,13 @@ void FieldLayoutBuilder::regular_field_sorting() { } } -void FieldLayoutBuilder::insert_contended_padding(LayoutRawBlock* slot) { +LayoutRawBlock* FieldLayoutBuilder::insert_contended_padding(LayoutRawBlock* slot) { + LayoutRawBlock* padding = nullptr; if (ContendedPaddingWidth > 0) { - LayoutRawBlock* padding = new LayoutRawBlock(LayoutRawBlock::PADDING, ContendedPaddingWidth); + padding = new LayoutRawBlock(LayoutRawBlock::PADDING, ContendedPaddingWidth); _layout->insert(slot, padding); } + return padding; } // Computation of regular classes layout is an evolution of the previous default layout @@ -620,10 +622,14 @@ void FieldLayoutBuilder::compute_regular_layout() { regular_field_sorting(); if (_is_contended) { - _layout->set_start(_layout->last_block()); // insertion is currently easy because the current strategy doesn't try to fill holes // in super classes layouts => the _start block is by consequence the _last_block - insert_contended_padding(_layout->start()); + _layout->set_start(_layout->last_block()); + LayoutRawBlock* padding = insert_contended_padding(_layout->start()); + if (padding != nullptr) { + // Setting the padding block as start ensures we do not insert past it. + _layout->set_start(padding); + } need_tail_padding = true; } @@ -639,7 +645,13 @@ void FieldLayoutBuilder::compute_regular_layout() { for (int i = 0; i < _contended_groups.length(); i++) { FieldGroup* cg = _contended_groups.at(i); LayoutRawBlock* start = _layout->last_block(); - insert_contended_padding(start); + LayoutRawBlock* padding = insert_contended_padding(start); + + // Do not insert fields past the padding block. + if (padding != nullptr) { + start = padding; + } + _layout->add(cg->primitive_fields(), start); _layout->add(cg->oop_fields(), start); need_tail_padding = true; diff --git a/src/hotspot/share/classfile/fieldLayoutBuilder.hpp b/src/hotspot/share/classfile/fieldLayoutBuilder.hpp index 82bbaefc623..eab0b7d08a9 100644 --- a/src/hotspot/share/classfile/fieldLayoutBuilder.hpp +++ b/src/hotspot/share/classfile/fieldLayoutBuilder.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -250,7 +250,7 @@ class FieldLayoutBuilder : public ResourceObj { void build_layout(); void compute_regular_layout(); - void insert_contended_padding(LayoutRawBlock* slot); + LayoutRawBlock* insert_contended_padding(LayoutRawBlock* slot); private: void prologue(); diff --git a/test/hotspot/jtreg/runtime/contended/MixedPrimitives.java b/test/hotspot/jtreg/runtime/contended/MixedPrimitives.java new file mode 100644 index 00000000000..a7165578831 --- /dev/null +++ b/test/hotspot/jtreg/runtime/contended/MixedPrimitives.java @@ -0,0 +1,356 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.Class; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import jdk.internal.misc.Unsafe; +import jdk.internal.vm.annotation.Contended; + +/* + * @test + * @summary \@Contended with different sized primitive types + * @modules java.base/jdk.internal.misc + * @modules java.base/jdk.internal.vm.annotation + * @run main/othervm -XX:-RestrictContended MixedPrimitives + */ +public class MixedPrimitives { + + private static final Unsafe U = Unsafe.getUnsafe(); + private static final int ADDRESS_SIZE; + private static final int HEADER_SIZE; + + static { + // When running with CompressedOops on 64-bit platform, the address size + // reported by Unsafe is still 8, while the real reference fields are 4 bytes long. + // Try to guess the reference field size with this naive trick. + try { + long off1 = U.objectFieldOffset(CompressedOopsClass.class.getField("obj1")); + long off2 = U.objectFieldOffset(CompressedOopsClass.class.getField("obj2")); + ADDRESS_SIZE = (int) Math.abs(off2 - off1); + HEADER_SIZE = (int) Math.min(off1, off2); + } catch (NoSuchFieldException e) { + throw new ExceptionInInitializerError(e); + } + } + + static class CompressedOopsClass { + public Object obj1; + public Object obj2; + } + + public static boolean arePaddedPairwise(Class klass, String field1, String field2) throws Exception { + Field f1 = klass.getDeclaredField(field1); + Field f2 = klass.getDeclaredField(field2); + + if (isStatic(f1) != isStatic(f2)) { + return true; // these guys are in naturally disjoint locations + } + + int diff = offset(f1) - offset(f2); + if (diff < 0) { + // f1 is first + return (offset(f2) - (offset(f1) + getSize(f1))) > 64; + } else { + // f2 is first + return (offset(f1) - (offset(f2) + getSize(f2))) > 64; + } + } + + public static boolean isPadded(Class klass, String field1) throws Exception { + Field f1 = klass.getDeclaredField(field1); + + if (isStatic(f1)) { + return offset(f1) > 128 + 64; + } + + return offset(f1) > 64; + } + + public static boolean sameLayout(Class klass1, Class klass2) throws Exception { + try { + for (Field f1 : klass1.getDeclaredFields()) { + Field f2 = klass2.getDeclaredField(f1.getName()); + if (offset(f1) != offset(f2)) { + return false; + } + } + + for (Field f2 : klass1.getDeclaredFields()) { + Field f1 = klass2.getDeclaredField(f2.getName()); + if (offset(f1) != offset(f2)) { + return false; + } + } + } catch (Exception e) { + System.err.println("Failed getting layout from class: " + e.getMessage()); + return false; + } + + return true; + } + + public static boolean isStatic(Field field) { + return Modifier.isStatic(field.getModifiers()); + } + + public static int offset(Field field) { + if (isStatic(field)) { + return (int) U.staticFieldOffset(field); + } else { + return (int) U.objectFieldOffset(field); + } + } + + public static int getSize(Field field) { + Class type = field.getType(); + if (type == byte.class) { return 1; } + if (type == boolean.class) { return 1; } + if (type == short.class) { return 2; } + if (type == char.class) { return 2; } + if (type == int.class) { return 4; } + if (type == float.class) { return 4; } + if (type == long.class) { return 8; } + if (type == double.class) { return 8; } + return ADDRESS_SIZE; + } + + public static void main(String[] args) throws Exception { + int failures = 0; + + failures += Test1.checkLayout(); + failures += Test2.checkLayout(); + failures += Test3.checkLayout(); + failures += Test4.checkLayout(); + failures += Test5.checkLayout(); + failures += Test6.checkLayout(); + failures += Test7.checkLayout(); + failures += Test8.checkLayout(); + failures += Test9.checkLayout(); + + if (!sameLayout(Test4.class, Test7.class)) { + System.err.println("Test4 and Test7 have different layouts"); + failures += 1; + } + + if (!sameLayout(Test5.class, Test6.class)) { + System.err.println("Test5 and Test6 have different layouts"); + failures += 1; + } + + if (!sameLayout(Test8.class, Test9.class)) { + System.err.println("Test8 and Test9 have different layouts"); + failures += 1; + } + + System.out.println(failures == 0 ? "Test PASSES" : "Test FAILS"); + if (failures > 0) { + throw new Error("Test failed. Incurred " + failures + " failures."); + } + } + + // naturally packed + public static class Test1 { + private long long1; + private int int1; + private short short1; + + public static int checkLayout() throws Exception { + if (arePaddedPairwise(Test1.class, "long1", "int1") || + arePaddedPairwise(Test1.class, "long1", "short1") || + arePaddedPairwise(Test1.class, "int1", "short1") || + isPadded(Test1.class, "long1") || + isPadded(Test1.class, "int1") || + isPadded(Test1.class, "short1")) { + System.err.println("Test1 failed"); + return 1; + } + return 0; + } + } + + // long1 is padded + public static class Test2 { + @Contended private long long1; + private int int1; + private short short1; + + public static int checkLayout() throws Exception { + if (!arePaddedPairwise(Test2.class, "long1", "int1") || + !arePaddedPairwise(Test2.class, "long1", "short1") || + arePaddedPairwise(Test2.class, "int1", "short1") || + !isPadded(Test2.class, "long1") || + isPadded(Test2.class, "int1") || + isPadded(Test2.class, "short1")) { + System.err.println("Test2 failed"); + return 1; + } + return 0; + } + } + + // both fields are padded + public static class Test3 { + @Contended private long long1; + @Contended private int int1; + @Contended private short short1; + + public static int checkLayout() throws Exception { + if (!arePaddedPairwise(Test3.class, "long1", "int1") || + !arePaddedPairwise(Test3.class, "long1", "short1") || + !arePaddedPairwise(Test3.class, "int1", "short1") || + !isPadded(Test3.class, "long1") || + !isPadded(Test3.class, "int1") || + !isPadded(Test3.class, "short1")) { + System.err.println("Test3 failed"); + return 1; + } + return 0; + } + } + + // fields are padded in the singular group + public static class Test4 { + @Contended("sameGroup") private long long1; + @Contended("sameGroup") private int int1; + @Contended("sameGroup") private short short1; + + public static int checkLayout() throws Exception { + if (arePaddedPairwise(Test4.class, "long1", "int1") || + arePaddedPairwise(Test4.class, "long1", "short1") || + arePaddedPairwise(Test4.class, "int1", "short1") || + !isPadded(Test4.class, "long1") || + !isPadded(Test4.class, "int1") || + !isPadded(Test4.class, "short1")) { + System.err.println("Test4 failed"); + return 1; + } + return 0; + } + } + + // fields are padded in disjoint groups + public static class Test5 { + @Contended("diffGroup1") private long long1; + @Contended("diffGroup2") private int int1; + @Contended("diffGroup3") private short short1; + + public static int checkLayout() throws Exception { + if (!arePaddedPairwise(Test5.class, "long1", "int1") || + !arePaddedPairwise(Test5.class, "long1", "short1") || + !arePaddedPairwise(Test5.class, "int1", "short1") || + !isPadded(Test5.class, "long1") || + !isPadded(Test5.class, "int1") || + !isPadded(Test5.class, "short1")) { + System.err.println("Test5 failed"); + return 1; + } + return 0; + } + } + + // fields are padded in disjoint groups + public static class Test6 { + @Contended private long long1; + @Contended("diffGroup2") private int int1; + @Contended("diffGroup3") private short short1; + + public static int checkLayout() throws Exception { + if (!arePaddedPairwise(Test6.class, "long1", "int1") || + !arePaddedPairwise(Test6.class, "long1", "short1") || + !arePaddedPairwise(Test6.class, "int1", "short1") || + !isPadded(Test6.class, "long1") || + !isPadded(Test6.class, "int1") || + !isPadded(Test6.class, "short1")) { + System.err.println("Test6 failed"); + return 1; + } + return 0; + } + } + + // fields are padded in the singular group + @Contended + public static class Test7 { + private long long1; + private int int1; + private short short1; + + public static int checkLayout() throws Exception { + if (arePaddedPairwise(Test7.class, "long1", "int1") || + arePaddedPairwise(Test7.class, "long1", "short1") || + arePaddedPairwise(Test7.class, "int1", "short1") || + !isPadded(Test7.class, "long1") || + !isPadded(Test7.class, "int1") || + !isPadded(Test7.class, "short1")) { + System.err.println("Test7 failed"); + return 1; + } + return 0; + } + } + + // all fields are padded as the group, and one field is padded specifically + @Contended + public static class Test8 { + @Contended private long long1; + private int int1; + private short short1; + + public static int checkLayout() throws Exception { + if (!arePaddedPairwise(Test8.class, "long1", "int1") || + !arePaddedPairwise(Test8.class, "long1", "short1") || + arePaddedPairwise(Test8.class, "int1", "short1") || + !isPadded(Test8.class, "long1") || + !isPadded(Test8.class, "int1") || + !isPadded(Test8.class, "short1")) { + System.err.println("Test8 failed"); + return 1; + } + return 0; + } + } + + // all fields are padded as the group, and one field is padded specifically + @Contended + public static class Test9 { + @Contended("group") private long long1; + private int int1; + private short short1; + + public static int checkLayout() throws Exception { + if (!arePaddedPairwise(Test9.class, "long1", "int1") || + !arePaddedPairwise(Test9.class, "long1", "short1") || + arePaddedPairwise(Test9.class, "int1", "short1") || + !isPadded(Test9.class, "long1") || + !isPadded(Test9.class, "int1") || + !isPadded(Test9.class, "short1")) { + System.err.println("Test9 failed"); + return 1; + } + return 0; + } + } + +} + From 3eaeb9b1ad82d165798a986a2d9378d52af0ca38 Mon Sep 17 00:00:00 2001 From: Christian Hagedorn Date: Mon, 30 Mar 2026 10:25:58 +0000 Subject: [PATCH 053/116] 8380945: [IR Framework] Test VM is finished before TestFrameworkSocket is ready to accept connection Reviewed-by: mchevalier, thartmann --- .../ir_framework/driver/TestVMProcess.java | 1 + .../shared/TestFrameworkSocket.java | 49 +++++++++++++++---- 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/TestVMProcess.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/TestVMProcess.java index 00a9b93d124..bfffbdbec7e 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/TestVMProcess.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/TestVMProcess.java @@ -68,6 +68,7 @@ public TestVMProcess(List additionalFlags, Class testClass, Set(); TestFrameworkSocket socket = new TestFrameworkSocket(); try (socket) { + socket.start(); prepareTestVMFlags(additionalFlags, socket, testClass, helperClasses, defaultWarmup, allowNotCompilable, testClassesOnBootClassPath); start(); diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/shared/TestFrameworkSocket.java b/test/hotspot/jtreg/compiler/lib/ir_framework/shared/TestFrameworkSocket.java index 77d560952f1..44063a4bd43 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/shared/TestFrameworkSocket.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/shared/TestFrameworkSocket.java @@ -42,9 +42,13 @@ public class TestFrameworkSocket implements AutoCloseable { private final int serverSocketPort; private final ServerSocket serverSocket; - private boolean running; - private final ExecutorService executor; - private Future javaFuture; + private final ExecutorService acceptExecutor; + private final ExecutorService clientExecutor; + + // Make these volatile such that the main thread can observe an update written by the worker threads in the executor + // services to avoid stale values. + private volatile boolean running; + private volatile Future javaFuture; public TestFrameworkSocket() { try { @@ -54,29 +58,53 @@ public TestFrameworkSocket() { throw new TestFrameworkException("Failed to create TestFramework server socket", e); } serverSocketPort = serverSocket.getLocalPort(); - executor = Executors.newCachedThreadPool(); + acceptExecutor = Executors.newSingleThreadExecutor(); + clientExecutor = Executors.newCachedThreadPool(); if (TestFramework.VERBOSE) { System.out.println("TestFramework server socket uses port " + serverSocketPort); } - start(); } public String getPortPropertyFlag() { return "-D" + SERVER_PORT_PROPERTY + "=" + serverSocketPort; } - private void start() { + public void start() { running = true; - executor.submit(this::acceptLoop); + CountDownLatch calledAcceptLoopLatch = new CountDownLatch(1); + startAcceptLoop(calledAcceptLoopLatch); + } + + private void startAcceptLoop(CountDownLatch calledAcceptLoopLatch) { + acceptExecutor.submit(() -> acceptLoop(calledAcceptLoopLatch)); + waitUntilAcceptLoopRuns(calledAcceptLoopLatch); + } + + private void waitUntilAcceptLoopRuns(CountDownLatch calledAcceptLoopLatch) { + try { + if (!calledAcceptLoopLatch.await(10, TimeUnit.SECONDS)) { + throw new IllegalStateException("acceptLoop did not start in time"); + } + } catch (Exception e) { + throw new TestFrameworkException("Could not start TestFrameworkSocket", e); + } } /** * Main loop to wait for new client connections and handling them upon connection request. */ - private void acceptLoop() { + private void acceptLoop(CountDownLatch calledAcceptLoopLatch) { + calledAcceptLoopLatch.countDown(); while (running) { try { acceptNewClientConnection(); + } catch (SocketException e) { + if (!running || serverSocket.isClosed()) { + // Normal shutdown + return; + } + running = false; + throw new TestFrameworkException("Server socket error", e); } catch (TestFrameworkException e) { running = false; throw e; @@ -101,7 +129,7 @@ private void acceptNewClientConnection() throws IOException { * over that connection. */ private void submitTask(Socket client, BufferedReader reader) { - javaFuture = executor.submit(new TestVmMessageReader(client, reader)); + javaFuture = clientExecutor.submit(new TestVmMessageReader(client, reader)); } @Override @@ -112,7 +140,8 @@ public void close() { } catch (IOException e) { throw new TestFrameworkException("Could not close socket", e); } - executor.shutdown(); + acceptExecutor.shutdown(); + clientExecutor.shutdown(); } public TestVMData testVmData(String hotspotPidFileName, boolean allowNotCompilable) { From 6b9887b4f518c5b26d6a9700b7ae0dea8b140164 Mon Sep 17 00:00:00 2001 From: Yasumasa Suenaga Date: Mon, 30 Mar 2026 11:53:03 +0000 Subject: [PATCH 054/116] 8378902: Test compiler/vectorapi/TestVectorLibraryUnaryOpAndBinaryOp.java failed Reviewed-by: mbaesken, thartmann --- .../TestVectorLibraryUnaryOpAndBinaryOp.java | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/test/hotspot/jtreg/compiler/vectorapi/TestVectorLibraryUnaryOpAndBinaryOp.java b/test/hotspot/jtreg/compiler/vectorapi/TestVectorLibraryUnaryOpAndBinaryOp.java index f7837e1abfa..731c87e69f7 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/TestVectorLibraryUnaryOpAndBinaryOp.java +++ b/test/hotspot/jtreg/compiler/vectorapi/TestVectorLibraryUnaryOpAndBinaryOp.java @@ -26,12 +26,13 @@ import compiler.lib.ir_framework.*; import jdk.incubator.vector.*; +import jtreg.SkippedException; /** * @test - * @bug 8378312 + * @bug 8378312 8378902 * @library /test/lib / - * @summary VectorAPI: libraryUnaryOp and libraryBinaryOp should be intrinsified. + * @summary VectorAPI: libraryUnaryOp and libraryBinaryOp should be intrinsified. This test would be run on SVML/SLEEF supported platforms only. * @modules jdk.incubator.vector * * @run driver compiler.vectorapi.TestVectorLibraryUnaryOpAndBinaryOp @@ -53,7 +54,24 @@ public static void testBinary() { vec.lanewise(VectorOperators.HYPOT, 1.0f); } + private static void checkVectorMathLib() { + try { + // Check jsvml first + System.loadLibrary("jsvml"); + } catch (UnsatisfiedLinkError _) { + try { + // Check sleef if jsvml not found + System.loadLibrary("sleef"); + } catch (UnsatisfiedLinkError _) { + // This test is run on unsupported platform - should be skipped + throw new SkippedException("SVML / SLEEF not found"); + } + } + } + public static void main(String[] args) { + checkVectorMathLib(); + TestFramework testFramework = new TestFramework(); testFramework.addFlags("--add-modules=jdk.incubator.vector") .start(); From 7e0a1499ee5743cb8b36ad0150fa3a538b368e27 Mon Sep 17 00:00:00 2001 From: Koushik Thirupattur Date: Mon, 30 Mar 2026 12:50:42 +0000 Subject: [PATCH 055/116] 8345954: Revisit Class Initializers and Locking in X509TrustManagerImpl Reviewed-by: weijun --- .../sun/security/provider/X509Factory.java | 83 +++++++++++-------- 1 file changed, 49 insertions(+), 34 deletions(-) diff --git a/src/java.base/share/classes/sun/security/provider/X509Factory.java b/src/java.base/share/classes/sun/security/provider/X509Factory.java index f732c7c0455..4be83d629bb 100644 --- a/src/java.base/share/classes/sun/security/provider/X509Factory.java +++ b/src/java.base/share/classes/sun/security/provider/X509Factory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -112,9 +112,10 @@ public static X509CertImpl cachedGetX509Cert(byte[] encoding) if (cert != null) { return cert; } - cert = new X509CertImpl(encoding); - addToCache(certCache, cert.getEncodedInternal(), cert); - return cert; + // Build outside lock + X509CertImpl newCert = new X509CertImpl(encoding); + byte[] enc = newCert.getEncodedInternal(); + return addIfNotPresent(certCache, enc, newCert); } /** @@ -156,7 +157,7 @@ private static int readFully(InputStream in, ByteArrayOutputStream bout, * @throws CertificateException if failures occur while obtaining the DER * encoding for certificate data. */ - public static synchronized X509CertImpl intern(X509Certificate c) + public static X509CertImpl intern(X509Certificate c) throws CertificateException { if (c == null) { return null; @@ -168,18 +169,23 @@ public static synchronized X509CertImpl intern(X509Certificate c) } else { encoding = c.getEncoded(); } - X509CertImpl newC = getFromCache(certCache, encoding); - if (newC != null) { - return newC; + // First check under per-cache lock + X509CertImpl cached = getFromCache(certCache, encoding); + if (cached != null) { + return cached; } + + // Build outside lock + X509CertImpl newC; + byte[] enc; if (isImpl) { - newC = (X509CertImpl)c; + newC = (X509CertImpl) c; + enc = encoding; } else { newC = new X509CertImpl(encoding); - encoding = newC.getEncodedInternal(); + enc = newC.getEncodedInternal(); } - addToCache(certCache, encoding, newC); - return newC; + return addIfNotPresent(certCache, enc, newC); } /** @@ -192,7 +198,7 @@ public static synchronized X509CertImpl intern(X509Certificate c) * @throws CRLException if failures occur while obtaining the DER * encoding for CRL data. */ - public static synchronized X509CRLImpl intern(X509CRL c) + public static X509CRLImpl intern(X509CRL c) throws CRLException { if (c == null) { return null; @@ -204,39 +210,47 @@ public static synchronized X509CRLImpl intern(X509CRL c) } else { encoding = c.getEncoded(); } - X509CRLImpl newC = getFromCache(crlCache, encoding); - if (newC != null) { - return newC; + X509CRLImpl cached = getFromCache(crlCache, encoding); + if (cached != null) { + return cached; } + + X509CRLImpl newC; + byte[] enc; if (isImpl) { - newC = (X509CRLImpl)c; + newC = (X509CRLImpl) c; + enc = encoding; } else { newC = new X509CRLImpl(encoding); - encoding = newC.getEncodedInternal(); + enc = newC.getEncodedInternal(); } - addToCache(crlCache, encoding, newC); - return newC; + return addIfNotPresent(crlCache, enc, newC); } /** * Get the X509CertImpl or X509CRLImpl from the cache. */ - private static synchronized V getFromCache(Cache cache, - byte[] encoding) { - Object key = new Cache.EqualByteArray(encoding); - return cache.get(key); + private static V getFromCache(Cache cache, byte[] encoding) { + return cache.get(new Cache.EqualByteArray(encoding)); } /** * Add the X509CertImpl or X509CRLImpl to the cache. */ - private static synchronized void addToCache(Cache cache, - byte[] encoding, V value) { + private static V addIfNotPresent(Cache cache, byte[] encoding, V value) { if (encoding.length > ENC_MAX_LENGTH) { - return; + return value; } Object key = new Cache.EqualByteArray(encoding); - cache.put(key, value); + // Synchronize only to make the "check + insert" decision atomic. + synchronized (cache) { + V existing = cache.get(key); + if (existing != null) { + return existing; + } + cache.put(key, value); + return value; + } } /** @@ -389,13 +403,14 @@ public CRL engineGenerateCRL(InputStream is) try { byte[] encoding = readOneBlock(is); if (encoding != null) { - X509CRLImpl crl = getFromCache(crlCache, encoding); - if (crl != null) { - return crl; + X509CRLImpl cached = getFromCache(crlCache, encoding); + if (cached != null) { + return cached; } - crl = new X509CRLImpl(encoding); - addToCache(crlCache, crl.getEncodedInternal(), crl); - return crl; + // Build outside lock + X509CRLImpl crl = new X509CRLImpl(encoding); + byte[] enc = crl.getEncodedInternal(); + return addIfNotPresent(crlCache, enc, crl); } else { throw new IOException("Empty input"); } From d58fb1e290cb8a28a04900e132ae09002ae62937 Mon Sep 17 00:00:00 2001 From: Daisuke Yamazaki Date: Mon, 30 Mar 2026 12:58:07 +0000 Subject: [PATCH 056/116] 8374202: Simplify significand normalization in BigDecimal(double, MathContext) constructor Reviewed-by: rgiulietti --- src/java.base/share/classes/java/math/BigDecimal.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/java.base/share/classes/java/math/BigDecimal.java b/src/java.base/share/classes/java/math/BigDecimal.java index 14d81d30c3d..6e651b4fde2 100644 --- a/src/java.base/share/classes/java/math/BigDecimal.java +++ b/src/java.base/share/classes/java/math/BigDecimal.java @@ -1026,12 +1026,11 @@ public BigDecimal(double val, MathContext mc) { return; } // Normalize - while ((significand & 1) == 0) { // i.e., significand is even - significand >>= 1; - exponent++; - } - int scl = 0; + int nTrailingZeros = Long.numberOfTrailingZeros(significand); + significand >>= nTrailingZeros; + exponent += nTrailingZeros; // Calculate intVal and scale + int scl = 0; BigInteger rb; long compactVal = sign * significand; if (exponent == 0) { From 40e6069ff0558b1d5d0e520df7f23e59369867db Mon Sep 17 00:00:00 2001 From: Dusan Balek Date: Mon, 30 Mar 2026 13:06:06 +0000 Subject: [PATCH 057/116] =?UTF-8?q?8371873:=20javac:=20U+001A=20(SUB=20/?= =?UTF-8?q?=20control-Z)=20after=20the=20last=20token=20makes=20the=20rest?= =?UTF-8?q?=20of=20the=20file=20silently=20ignored,=20which=20contradicts?= =?UTF-8?q?=20JLS=20=C2=A73.3=E2=80=93=C2=A73.5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: jlahoda --- .../sun/tools/javac/parser/JavaTokenizer.java | 4 +- .../tools/javac/lexer/AsciiSubCharTest.java | 116 ++++++++++++++++++ 2 files changed, 118 insertions(+), 2 deletions(-) create mode 100644 test/langtools/tools/javac/lexer/AsciiSubCharTest.java diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java index babe372e7dc..55f2f76e358 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1000,7 +1000,7 @@ public Token readToken() { scanIdent(); } else if (digit(pos, 10) >= 0) { scanNumber(pos, 10); - } else if (is((char)EOI) || !isAvailable()) { + } else if (is((char)EOI) && position() + 1 == length() || !isAvailable()) { tk = TokenKind.EOF; pos = position(); } else { diff --git a/test/langtools/tools/javac/lexer/AsciiSubCharTest.java b/test/langtools/tools/javac/lexer/AsciiSubCharTest.java new file mode 100644 index 00000000000..0c96b744d72 --- /dev/null +++ b/test/langtools/tools/javac/lexer/AsciiSubCharTest.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 8371873 + * @summary Check for proper handling of trailing ASCII SUB character + * @library /tools/lib + * @modules + * jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + * @build toolbox.ToolBox toolbox.JavacTask + * @run junit AsciiSubCharTest + */ + +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.*; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInfo; + +import toolbox.JavacTask; +import toolbox.Task; +import toolbox.ToolBox; + +public class AsciiSubCharTest { + + ToolBox tb = new ToolBox(); + Path base; + + @Test + public void testTrailingAsciiSubIsIgnored() throws Exception { + Path classes = base.resolve("classes"); + Files.createDirectories(classes); + new JavacTask(tb) + .options("-d", classes.toString()) + .sources(""" + public class Test { + void main(String... args) { IO.println("\u001A"); } + } + \u001A""") + .run() + .writeAll(); + } + + @Test + public void testMultipleTrailingAsciiSubAreReported() throws Exception { + Path classes = base.resolve("classes"); + Files.createDirectories(classes); + List out = new JavacTask(tb) + .options("-d", classes.toString(), "-XDrawDiagnostics", "-nowarn") + .sources(""" + public class Test { + void main(String... args) { IO.println("\u001A"); } + } + \u001A\u001A""") + .run(Task.Expect.FAIL) + .writeAll() + .getOutputLines(Task.OutputKind.DIRECT); + tb.checkEqual(out, List.of( + "Test.java:4:1: compiler.err.illegal.char: \\u001a", + "Test.java:4:2: compiler.err.premature.eof", + "2 errors")); + } + + @Test + public void test8371873() throws Exception { + Path classes = base.resolve("classes"); + Files.createDirectories(classes); + List out = new JavacTask(tb) + .options("-d", classes.toString(), "-XDrawDiagnostics", "-nowarn") + .sources(""" + public class Test { + void main(String... args) { IO.println("\u001A"); } + } + \u001A\u0001""") + .run(Task.Expect.FAIL) + .writeAll() + .getOutputLines(Task.OutputKind.DIRECT); + tb.checkEqual(out, List.of( + "Test.java:4:1: compiler.err.illegal.char: \\u001a", + "Test.java:4:2: compiler.err.illegal.char: \\u0001", + "Test.java:4:3: compiler.err.premature.eof", + "3 errors")); + } + + @BeforeEach + public void setUp(TestInfo info) { + base = Paths.get(".") + .resolve(info.getTestMethod() + .orElseThrow() + .getName()); + } +} From 2449dc2e807c3a4708a89e52bb16434d4a85d3d2 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Mon, 30 Mar 2026 13:06:40 +0000 Subject: [PATCH 058/116] 8377004: Java Launcher incorrectly allows inheriting a package-private main from another package Reviewed-by: jpai, alanb --- .../jdk/internal/misc/MethodFinder.java | 19 +- test/jdk/tools/launcher/InstanceMainTest.java | 224 +++++++++++++++++- test/jdk/tools/launcher/MethodFinderTest.java | 196 +++++++++++++++ 3 files changed, 423 insertions(+), 16 deletions(-) create mode 100644 test/jdk/tools/launcher/MethodFinderTest.java diff --git a/src/java.base/share/classes/jdk/internal/misc/MethodFinder.java b/src/java.base/share/classes/jdk/internal/misc/MethodFinder.java index 60895b8115a..1ee608f2caf 100644 --- a/src/java.base/share/classes/jdk/internal/misc/MethodFinder.java +++ b/src/java.base/share/classes/jdk/internal/misc/MethodFinder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * 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 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import java.util.Objects; import jdk.internal.access.JavaLangAccess; import jdk.internal.access.SharedSecrets; @@ -88,21 +89,27 @@ public static Method findMainMethod(Class cls) { mainMethod = JLA.findMethod(cls, false, "main", String[].class); } - if (mainMethod == null || !isValidMainMethod(mainMethod)) { + if (mainMethod == null || !isValidMainMethod(cls, mainMethod)) { mainMethod = JLA.findMethod(cls, false, "main"); } - if (mainMethod == null || !isValidMainMethod(mainMethod)) { + if (mainMethod == null || !isValidMainMethod(cls, mainMethod)) { return null; } return mainMethod; } - private static boolean isValidMainMethod(Method mainMethodCandidate) { + private static boolean isValidMainMethod(Class initialClass, Method mainMethodCandidate) { return mainMethodCandidate.getReturnType() == void.class && - !Modifier.isPrivate(mainMethodCandidate.getModifiers()); - + !Modifier.isPrivate(mainMethodCandidate.getModifiers()) && + (Modifier.isPublic(mainMethodCandidate.getModifiers()) || + Modifier.isProtected(mainMethodCandidate.getModifiers()) || + isInSameRuntimePackage(initialClass, mainMethodCandidate.getDeclaringClass())); } + private static boolean isInSameRuntimePackage(Class c1, Class c2) { + return Objects.equals(c1.getPackageName(), c2.getPackageName()) && + c1.getClassLoader() == c2.getClassLoader(); + } } diff --git a/test/jdk/tools/launcher/InstanceMainTest.java b/test/jdk/tools/launcher/InstanceMainTest.java index 273d56a86bd..3a2f8fe90c1 100644 --- a/test/jdk/tools/launcher/InstanceMainTest.java +++ b/test/jdk/tools/launcher/InstanceMainTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * 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,11 +28,12 @@ /** * @test - * @bug 8329420 + * @bug 8329420 8377004 * @summary test execution priority and behavior of main methods * @run main/timeout=480 InstanceMainTest */ public class InstanceMainTest extends TestHelper { + private static String JAVA_VERSION = System.getProperty("java.specification.version"); private static final String[] SOURCES = new String[] { // static dominating with args @@ -227,11 +228,7 @@ public void main() { private static void testExecutionOrder() throws Exception { for (TestCase testCase : EXECUTION_ORDER) { performTest(testCase.sourceCode, testCase.enablePreview(), tr -> { - if (!Objects.equals(testCase.expectedOutput, tr.testOutput)) { - throw new AssertionError("Unexpected output, " + - "expected: " + testCase.expectedOutput + - ", actual: " + tr.testOutput); - } + assertEquals(testCase.expectedOutput, tr.testOutput); }); } } @@ -350,20 +347,227 @@ private static void testExecutionErrors() throws Exception { private static void performTest(String source, boolean enablePreview, Consumer validator) throws Exception { Path mainClass = Path.of("MainClass.java"); Files.writeString(mainClass, source); - var version = System.getProperty("java.specification.version"); var previewRuntime = enablePreview ? "--enable-preview" : "-DtestNoPreview"; var previewCompile = enablePreview ? "--enable-preview" : "-XDtestNoPreview"; - var trSource = doExec(javaCmd, previewRuntime, "--source", version, "MainClass.java"); + var trSource = doExec(javaCmd, previewRuntime, "--source", JAVA_VERSION, "MainClass.java"); validator.accept(trSource); - compile(previewCompile, "--source", version, "MainClass.java"); + compile(previewCompile, "--source", JAVA_VERSION, "MainClass.java"); String cp = mainClass.toAbsolutePath().getParent().toString(); var trCompile = doExec(javaCmd, previewRuntime, "--class-path", cp, "MainClass"); validator.accept(trCompile); } + private static void testInheritance() throws Exception { + Path testInheritance = Path.of("testInheritance"); + Path src = testInheritance.resolve("src"); + Path classes = testInheritance.resolve("classes"); + Path mainClass = src.resolve("Main.java"); + Path libClass = src.resolve("p").resolve("Lib.java"); + + Files.createDirectories(libClass.getParent()); + + Files.writeString(mainClass, + """ + import p.Lib; + + public class Main extends Lib { + public void main() { + System.err.println("Main!"); + } + } + """); + + { + Files.writeString(libClass, + """ + package p; + public class Lib { + void main(String... args) { + System.err.println("Lib!"); + } + } + """); + compile("--release", JAVA_VERSION, "-d", classes.toString(), mainClass.toString(), libClass.toString()); + var tr = doExec(javaCmd, "--class-path", classes.toString(), "Main"); + assertEquals(List.of("Main!"), tr.testOutput); + } + + { + Files.writeString(libClass, + """ + package p; + public class Lib { + protected void main(String... args) { + System.err.println("Lib!"); + } + } + """); + compile("--release", JAVA_VERSION, "-d", classes.toString(), mainClass.toString(), libClass.toString()); + var tr = doExec(javaCmd, "--class-path", classes.toString(), "Main"); + assertEquals(List.of("Lib!"), tr.testOutput); + } + + { + Files.writeString(libClass, + """ + package p; + public class Lib { + public void main(String... args) { + System.err.println("Lib!"); + } + } + """); + compile("--release", JAVA_VERSION, "-d", classes.toString(), mainClass.toString(), libClass.toString()); + var tr = doExec(javaCmd, "--class-path", classes.toString(), "Main"); + assertEquals(List.of("Lib!"), tr.testOutput); + } + + { + Files.writeString(mainClass, + """ + package p; + + public class Main extends Lib { + public void main() { + System.err.println("Main!"); + } + } + """); + + Files.writeString(libClass, + """ + package p; + public class Lib { + void main(String... args) { + System.err.println("Lib!"); + } + } + """); + compile("--release", JAVA_VERSION, "-d", classes.toString(), mainClass.toString(), libClass.toString()); + var tr = doExec(javaCmd, "--class-path", classes.toString(), "p.Main"); + assertEquals(List.of("Lib!"), tr.testOutput); + } + + { + Files.writeString(mainClass, + """ + package p; + + public class Main implements Lib { + public void main() { + System.err.println("Main!"); + } + } + """); + + Files.writeString(libClass, + """ + package p; + public interface Lib { + public default void main(String... args) { + System.err.println("Lib!"); + } + } + """); + compile("--release", JAVA_VERSION, "-d", classes.toString(), mainClass.toString(), libClass.toString()); + var tr = doExec(javaCmd, "--class-path", classes.toString(), "p.Main"); + assertEquals(List.of("Lib!"), tr.testOutput); + } + + { + Files.writeString(mainClass, + """ + package p; + + public class Main implements Lib { + public void main() { + System.err.println("Main!"); + } + } + """); + + Files.writeString(libClass, + """ + package p; + public interface Lib { + public static void main(String... args) { + System.err.println("Lib!"); + } + } + """); + compile("--release", JAVA_VERSION, "-d", classes.toString(), mainClass.toString(), libClass.toString()); + var tr = doExec(javaCmd, "--class-path", classes.toString(), "p.Main"); + assertEquals(List.of("Main!"), tr.testOutput); + } + + { + Files.writeString(mainClass, + """ + package p; + + public class Main extends AbstractClass implements Lib { + } + abstract class AbstractClass { + public void main(String... args) { + System.err.println("Correct."); + } + } + """); + + Files.writeString(libClass, + """ + package p; + public interface Lib { + default void main(String... args) { + System.err.println("Incorrect!"); + } + } + """); + compile("--release", JAVA_VERSION, "-d", classes.toString(), mainClass.toString(), libClass.toString()); + var tr = doExec(javaCmd, "--class-path", classes.toString(), "p.Main"); + assertEquals(List.of("Correct."), tr.testOutput); + } + + { + Files.writeString(mainClass, + """ + package p; + + public class Main extends AbstractClass implements Lib { + } + abstract class AbstractClass { + public void main() { + System.err.println("Incorrect!"); + } + } + """); + + Files.writeString(libClass, + """ + package p; + public interface Lib { + default void main(String... args) { + System.err.println("Correct."); + } + } + """); + compile("--release", JAVA_VERSION, "-d", classes.toString(), mainClass.toString(), libClass.toString()); + var tr = doExec(javaCmd, "--class-path", classes.toString(), "p.Main"); + assertEquals(List.of("Correct."), tr.testOutput); + } + } + + private static void assertEquals(List expected, List actual) { + if (!Objects.equals(expected, actual)) { + throw new AssertionError("Unexpected output, " + + "expected: " + expected + + ", actual: " + actual); + } + } public static void main(String... args) throws Exception { testMethodOrder(); testExecutionOrder(); testExecutionErrors(); + testInheritance(); } } diff --git a/test/jdk/tools/launcher/MethodFinderTest.java b/test/jdk/tools/launcher/MethodFinderTest.java new file mode 100644 index 00000000000..6e1e68d8225 --- /dev/null +++ b/test/jdk/tools/launcher/MethodFinderTest.java @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 8377004 + * @summary Whitebox test for MethodFinder + * @modules java.base/jdk.internal.misc + * jdk.compiler + * jdk.zipfs + * @run junit MethodFinderTest + */ + +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.Files; +import java.nio.file.Path; +import jdk.internal.misc.MethodFinder; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +public class MethodFinderTest { + + private static final String JAVA_VERSION = System.getProperty("java.specification.version"); + + @Test + public void testDistinctClassLoaders() throws Exception { + Path base = Path.of("testDistinctClassLoaders"); + Path libSrc = base.resolve("libSrc"); + Path libClasses = base.resolve("libClasses"); + Path libJava = libSrc.resolve("p").resolve("Lib.java"); + + Files.createDirectories(libJava.getParent()); + + Files.writeString(libJava, + """ + package p; + public class Lib { + void main(String... args) { + System.err.println("Lib!"); + } + } + """); + + TestHelper.compile("--release", JAVA_VERSION, "-d", libClasses.toString(), libJava.toString()); + + Path mainSrc = base.resolve("mainSrc"); + Path mainClasses = base.resolve("mainClasses"); + Path mainJava = mainSrc.resolve("p").resolve("Main.java"); + + Files.createDirectories(mainJava.getParent()); + + Files.writeString(mainJava, + """ + package p; + + public class Main extends Lib { + public void main() { + System.err.println("Main!"); + } + } + """); + + TestHelper.compile("--release", JAVA_VERSION, "--class-path", libClasses.toString(), "-d", mainClasses.toString(), mainJava.toString()); + + { + ClassLoader cl = new URLClassLoader(new URL[] { + libClasses.toUri().toURL(), + mainClasses.toUri().toURL() + }); + Class mainClass = cl.loadClass("p.Main"); + Method mainMethod = MethodFinder.findMainMethod(mainClass); + + //p.Main and p.Lib are in the same runtime package: + assertEquals("p.Lib", mainMethod.getDeclaringClass().getName()); + } + + { + ClassLoader libCl = new URLClassLoader(new URL[] { + libClasses.toUri().toURL(), + }); + ClassLoader mainCl = new URLClassLoader(new URL[] { + mainClasses.toUri().toURL() + }, libCl); + Class mainClass = mainCl.loadClass("p.Main"); + Method mainMethod = MethodFinder.findMainMethod(mainClass); + + //p.Main and p.Lib are in the different runtime packages: + assertEquals("p.Main", mainMethod.getDeclaringClass().getName()); + } + } + + @Test + public void testWrongEquals() throws Exception { + Path base = Path.of("testDistinctClassLoaders"); + Path libSrc = base.resolve("libSrc"); + Path libClasses = base.resolve("libClasses"); + Path libJava = libSrc.resolve("p").resolve("Lib.java"); + + Files.createDirectories(libJava.getParent()); + + Files.writeString(libJava, + """ + package p; + public class Lib { + void main(String... args) { + System.err.println("Lib!"); + } + } + """); + + TestHelper.compile("--release", JAVA_VERSION, "-d", libClasses.toString(), libJava.toString()); + + Path mainSrc = base.resolve("mainSrc"); + Path mainClasses = base.resolve("mainClasses"); + Path mainJava = mainSrc.resolve("p").resolve("Main.java"); + + Files.createDirectories(mainJava.getParent()); + + Files.writeString(mainJava, + """ + package p; + + public class Main extends Lib { + public void main() { + System.err.println("Main!"); + } + } + """); + + TestHelper.compile("--release", JAVA_VERSION, "--class-path", libClasses.toString(), "-d", mainClasses.toString(), mainJava.toString()); + + { + ClassLoader cl = new URLClassLoader(new URL[] { + libClasses.toUri().toURL(), + mainClasses.toUri().toURL() + }); + Class mainClass = cl.loadClass("p.Main"); + Method mainMethod = MethodFinder.findMainMethod(mainClass); + + //p.Main and p.Lib are in the same runtime package: + assertEquals("p.Lib", mainMethod.getDeclaringClass().getName()); + } + + { + class WrongEquals extends URLClassLoader { + + public WrongEquals(URL[] urls) { + super(urls); + } + + public WrongEquals(URL[] urls, ClassLoader parent) { + super(urls, parent); + } + + @Override + public boolean equals(Object obj) { + return obj instanceof WrongEquals; + } + } + ClassLoader libCl = new WrongEquals(new URL[] { + libClasses.toUri().toURL(), + }); + ClassLoader mainCl = new WrongEquals(new URL[] { + mainClasses.toUri().toURL() + }, libCl); + Class mainClass = mainCl.loadClass("p.Main"); + Method mainMethod = MethodFinder.findMainMethod(mainClass); + + //p.Main and p.Lib are in the different runtime packages: + assertEquals("p.Main", mainMethod.getDeclaringClass().getName()); + } + } +} From 88d4f1f7ce9662155f35197157abe341ba13c673 Mon Sep 17 00:00:00 2001 From: Liam Miller-Cushon Date: Mon, 30 Mar 2026 13:09:18 +0000 Subject: [PATCH 059/116] 8380795: Consider omitting type annotations from method arguments in diagnostics Co-authored-by: Liz Looney Reviewed-by: vromero --- .../com/sun/tools/javac/code/Printer.java | 43 +++++++++-------- .../failures/MethodArguments.java | 47 +++++++++++++++++++ .../failures/MethodArguments.out | 8 ++++ .../typeAnnotations/failures/p/A.java | 30 ++++++++++++ .../typeAnnotations/failures/p/B.java | 41 ++++++++++++++++ 5 files changed, 150 insertions(+), 19 deletions(-) create mode 100644 test/langtools/tools/javac/annotations/typeAnnotations/failures/MethodArguments.java create mode 100644 test/langtools/tools/javac/annotations/typeAnnotations/failures/MethodArguments.out create mode 100644 test/langtools/tools/javac/annotations/typeAnnotations/failures/p/A.java create mode 100644 test/langtools/tools/javac/annotations/typeAnnotations/failures/p/B.java diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Printer.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Printer.java index d9781f19c5d..acd8a35a894 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Printer.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Printer.java @@ -53,6 +53,7 @@ public abstract class Printer implements Type.Visitor, Symbol.Vi List seenCaptured = List.nil(); static final int PRIME = 997; // largest prime less than 1000 + private boolean printingMethodArgs; protected Printer() { } @@ -195,6 +196,9 @@ private String printAnnotations(Type t) { } private String printAnnotations(Type t, boolean prefix) { + if (printingMethodArgs) { + return ""; + } StringBuilder sb = new StringBuilder(); List annos = t.getAnnotationMirrors(); if (!annos.isEmpty()) { @@ -337,27 +341,28 @@ protected String className(ClassType t, boolean longform, Locale locale) { * @return localized string representation */ protected String printMethodArgs(List args, boolean varArgs, Locale locale) { - if (!varArgs) { - return visitTypes(args, locale); - } else { - StringBuilder buf = new StringBuilder(); - while (args.tail.nonEmpty()) { - buf.append(visit(args.head, locale)); - args = args.tail; - buf.append(','); - } - if (args.head.hasTag(TypeTag.ARRAY)) { - buf.append(visit(((ArrayType) args.head).elemtype, locale)); - if (args.head.getAnnotationMirrors().nonEmpty()) { - buf.append(' '); - buf.append(args.head.getAnnotationMirrors()); - buf.append(' '); - } - buf.append("..."); + boolean prev = printingMethodArgs; + printingMethodArgs = true; + try { + if (!varArgs) { + return visitTypes(args, locale); } else { - buf.append(visit(args.head, locale)); + StringBuilder buf = new StringBuilder(); + while (args.tail.nonEmpty()) { + buf.append(visit(args.head, locale)); + args = args.tail; + buf.append(','); + } + if (args.head.hasTag(TypeTag.ARRAY)) { + buf.append(visit(((ArrayType) args.head).elemtype, locale)); + buf.append("..."); + } else { + buf.append(visit(args.head, locale)); + } + return buf.toString(); } - return buf.toString(); + } finally { + printingMethodArgs = prev; } } diff --git a/test/langtools/tools/javac/annotations/typeAnnotations/failures/MethodArguments.java b/test/langtools/tools/javac/annotations/typeAnnotations/failures/MethodArguments.java new file mode 100644 index 00000000000..e539721855b --- /dev/null +++ b/test/langtools/tools/javac/annotations/typeAnnotations/failures/MethodArguments.java @@ -0,0 +1,47 @@ +/* + * @test /nodynamiccopyright/ + * @summary Omit type-use annotations from diagnostics + * @compile/fail/ref=MethodArguments.out -XDrawDiagnostics MethodArguments.java p/A.java p/B.java + */ + +import java.util.List; +import p.A; +import p.B; + +public final class MethodArguments { + public static void main(String[] args) { + // error non-static.cant.be.ref: + // non-static ... cannot be referenced from a static context + B.one("bar"); + + B b = new B(); + + // error ref.ambiguous: + // reference to ... is ambiguous + // ... + // both ... and ... match + b.one(null); + + // error report.access: + // ... has private access in ... + b.two("foo"); + // ... has protected access in ... + b.three("foo"); + + // error not.def.public.cant.access: + // ... is not public in ... cannot be accessed from outside package + b.four("foo"); + } + + void five(@A String s) { + } + + void five(@A String s) { + } + + void six(List<@A String> s) { + } + + void six(List<@A String> s) { + } +} diff --git a/test/langtools/tools/javac/annotations/typeAnnotations/failures/MethodArguments.out b/test/langtools/tools/javac/annotations/typeAnnotations/failures/MethodArguments.out new file mode 100644 index 00000000000..b4ecee21403 --- /dev/null +++ b/test/langtools/tools/javac/annotations/typeAnnotations/failures/MethodArguments.out @@ -0,0 +1,8 @@ +MethodArguments.java:39:8: compiler.err.already.defined: kindname.method, five(java.lang.String), kindname.class, MethodArguments +MethodArguments.java:45:8: compiler.err.already.defined: kindname.method, six(java.util.List), kindname.class, MethodArguments +MethodArguments.java:15:6: compiler.err.non-static.cant.be.ref: kindname.method, one(java.lang.String) +MethodArguments.java:23:6: compiler.err.ref.ambiguous: one, kindname.method, one(java.lang.String), p.B, kindname.method, one(java.lang.Integer), p.B +MethodArguments.java:27:6: compiler.err.report.access: two(java.lang.String), private, p.B +MethodArguments.java:29:6: compiler.err.report.access: three(java.lang.String), protected, p.B +MethodArguments.java:33:6: compiler.err.not.def.public.cant.access: four(java.lang.String), p.B +7 errors diff --git a/test/langtools/tools/javac/annotations/typeAnnotations/failures/p/A.java b/test/langtools/tools/javac/annotations/typeAnnotations/failures/p/A.java new file mode 100644 index 00000000000..9e3bb15dab5 --- /dev/null +++ b/test/langtools/tools/javac/annotations/typeAnnotations/failures/p/A.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2026, 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. + */ + +package p; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; + +@Target(ElementType.TYPE_USE) +public @interface A {} diff --git a/test/langtools/tools/javac/annotations/typeAnnotations/failures/p/B.java b/test/langtools/tools/javac/annotations/typeAnnotations/failures/p/B.java new file mode 100644 index 00000000000..4dfe16b312d --- /dev/null +++ b/test/langtools/tools/javac/annotations/typeAnnotations/failures/p/B.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2026, 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. + */ + +package p; + +public class B { + public void one(@A String s) { + } + + public void one(@A Integer i) { + } + + private void two(@A String s) { + } + + protected void three(@A String s) { + } + + void four(@A String s) { + } +} From 783f8f1adc4ea3ef7fd4c5ca5473aad76dfc7ed1 Mon Sep 17 00:00:00 2001 From: Christian Hagedorn Date: Mon, 30 Mar 2026 14:06:05 +0000 Subject: [PATCH 060/116] 8381320: Problemlist compiler/vectorapi/TestVectorReallocation.java Reviewed-by: thartmann --- 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 3b871d9f4b6..7580ce4d165 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -56,6 +56,7 @@ compiler/c2/irTests/TestDuplicateBackedge.java 8318904 generic-all compiler/codecache/jmx/PoolsIndependenceTest.java 8264632 macosx-all +compiler/vectorapi/TestVectorReallocation.java 8381315 generic-x64 compiler/vectorapi/reshape/TestVectorReinterpret.java 8320897,8348519 aix-ppc64,linux-ppc64le,linux-s390x compiler/vectorapi/VectorRebracket128Test.java 8330538 generic-all From ab83702428d8d73335aa57f2d6a27797b8afa687 Mon Sep 17 00:00:00 2001 From: Matias Saavedra Silva Date: Mon, 30 Mar 2026 16:43:00 +0000 Subject: [PATCH 061/116] 8366020: Assert that java code is not executed during the AOT assembly phase Co-authored-by: Ioi Lam Reviewed-by: kvn, coleenp, iklam --- src/hotspot/share/cds/aotClassInitializer.cpp | 33 +++++++++++++++++++ test/lib/jdk/test/lib/cds/CDSTestUtils.java | 2 +- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/cds/aotClassInitializer.cpp b/src/hotspot/share/cds/aotClassInitializer.cpp index 41fdeb537cc..9ef96282aeb 100644 --- a/src/hotspot/share/cds/aotClassInitializer.cpp +++ b/src/hotspot/share/cds/aotClassInitializer.cpp @@ -59,6 +59,39 @@ bool AOTClassInitializer::can_archive_initialized_mirror(InstanceKlass* ik) { return false; } +#ifdef ASSERT + // If code in ik is executed, then ik must be in the state of being_initialized or + // fully_initialized. + // + // Check that no user code is executed during the assembly phase. Otherwise the user + // code may introduce undesirable environment dependencies into the heap image. + // If any of these two flags are set, we allow user code to be executed + // in the assembly phase. Note that these flags are strictly for the purpose + // of testing HotSpot and are not available in product builds. + if (AOTInitTestClass == nullptr && ArchiveHeapTestClass == nullptr) { + if (ik->defined_by_boot_loader()) { + // We allow boot classes to be AOT-initialized, except for classes from + // -Xbootclasspath (cp index >= 1) be AOT-initialized, as such classes may be + // provided by the user application. + assert(ik->shared_classpath_index() <= 0, + "only boot classed loaded from the modules image can be AOT-initialized"); + } else { + assert(ik->defined_by_platform_loader() || ik->defined_by_app_loader(), + "cannot AOT-initialized classed loaded by other loaders"); + + // Hidden classes from platform/app loaders need to be AOT-initialized to + // support AOT-linking of lambdas. These hidden classes are generated by the + // VM and do not contain user code. + if (!ik->is_hidden()) { + // OK: ik is an interface used by a lambda. When AOT-linking lambdas, we only + // support interfaces that are not interface_needs_clinit_execution_as_super(). + // See AOTConstantPoolResolver::check_lambda_metafactory_signature(). + assert(ik->is_interface() && !ik->interface_needs_clinit_execution_as_super(), "cannot execute Java code in assembly phase"); + } + } + } +#endif // ASSERT + // About "static field that may hold a different value" errors: // // Automatic selection for aot-inited classes diff --git a/test/lib/jdk/test/lib/cds/CDSTestUtils.java b/test/lib/jdk/test/lib/cds/CDSTestUtils.java index 1c51a693907..59e4a1bbbde 100644 --- a/test/lib/jdk/test/lib/cds/CDSTestUtils.java +++ b/test/lib/jdk/test/lib/cds/CDSTestUtils.java @@ -324,7 +324,7 @@ public static OutputAnalyzer createArchiveAndCheck(String... cliPrefix) public static void checkCommonExecExceptions(OutputAnalyzer output, Exception e) throws Exception { if (output.getStdout().contains("https://bugreport.java.com/bugreport/crash.jsp")) { - throw new RuntimeException("Hotspot crashed"); + throw new RuntimeException(getCrashMessage(output.getStdout())); } if (output.getStdout().contains("TEST FAILED")) { throw new RuntimeException("Test Failed"); From 73501b274faef43829ea8e2ec89706c72fcd2e68 Mon Sep 17 00:00:00 2001 From: Justin Lu Date: Mon, 30 Mar 2026 16:49:09 +0000 Subject: [PATCH 062/116] 8380848: jdk/nio/zipfs/ZipFSTester.java fails after JDK-8378884 Reviewed-by: lancea, syan --- test/jdk/jdk/nio/zipfs/ZipFSTester.java | 46 +++++++++++++++---------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/test/jdk/jdk/nio/zipfs/ZipFSTester.java b/test/jdk/jdk/nio/zipfs/ZipFSTester.java index 84135fd0d7d..9d70350272f 100644 --- a/test/jdk/jdk/nio/zipfs/ZipFSTester.java +++ b/test/jdk/jdk/nio/zipfs/ZipFSTester.java @@ -21,6 +21,7 @@ * questions. */ +import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -97,14 +98,21 @@ public class ZipFSTester { // create JAR file for test, actual contents don't matter static Path jarFile; + static String[] jarContents = new String[]{ + "META-INF/MANIFEST.MF", + "dir1/foo", + "dir2/bar", + "dir1/dir3/fooo" + }; @BeforeAll static void setup() throws Exception { - jarFile = Utils.createJarFile("tester.jar", - "META-INF/MANIFEST.MF", - "dir1/foo", - "dir2/bar", - "dir1/dir3/fooo"); + jarFile = Utils.createJarFile("tester.jar", jarContents); + } + + @AfterAll + static void cleanup() throws IOException { + Files.deleteIfExists(jarFile); } @Test @@ -583,19 +591,18 @@ void testStreamChannel() throws Exception { // test file stamp @Test void testTime() throws Exception { + var jar = Utils.createJarFile(System.currentTimeMillis() + ".jar", jarContents); BasicFileAttributes attrs = Files - .getFileAttributeView(jarFile, BasicFileAttributeView.class) + .getFileAttributeView(jar, BasicFileAttributeView.class) .readAttributes(); // create a new filesystem, copy this file into it - Map env = new HashMap(); - env.put("create", "true"); Path fsPath = getTempPath(); - try (FileSystem fs = newZipFileSystem(fsPath, env)) { + try (FileSystem fs = FileSystems.newFileSystem(fsPath, Map.of("create", "true"))) { System.out.println("test copy with timestamps..."); // copyin - Path dst = getPathWithParents(fs, "me"); - Files.copy(jarFile, dst, COPY_ATTRIBUTES); - checkEqual(jarFile, dst); + Path dst = fs.getPath("me"); + Files.copy(jar, dst, COPY_ATTRIBUTES); + checkEqual(jar, dst); System.out.println("mtime: " + attrs.lastModifiedTime()); System.out.println("ctime: " + attrs.creationTime()); System.out.println("atime: " + attrs.lastAccessTime()); @@ -608,14 +615,15 @@ void testTime() throws Exception { System.out.println("atime: " + dstAttrs.lastAccessTime()); // 1-second granularity - assertFalse(attrs.lastModifiedTime().to(TimeUnit.SECONDS) != - dstAttrs.lastModifiedTime().to(TimeUnit.SECONDS) || - attrs.lastAccessTime().to(TimeUnit.SECONDS) != - dstAttrs.lastAccessTime().to(TimeUnit.SECONDS) || - attrs.creationTime().to(TimeUnit.SECONDS) != - dstAttrs.creationTime().to(TimeUnit.SECONDS), "Timestamp Copy Failed!"); + assertEquals(attrs.lastModifiedTime().to(TimeUnit.SECONDS), + dstAttrs.lastModifiedTime().to(TimeUnit.SECONDS), "Last modified time incorrect"); + assertEquals(attrs.lastAccessTime().to(TimeUnit.SECONDS), + dstAttrs.lastAccessTime().to(TimeUnit.SECONDS), "Last access time incorrect"); + assertEquals(attrs.creationTime().to(TimeUnit.SECONDS), + dstAttrs.creationTime().to(TimeUnit.SECONDS), "Last creation time incorrect"); } finally { - Files.delete(fsPath); + Files.deleteIfExists(fsPath); + Files.deleteIfExists(jar); } } From 0c4156d599868992cce34605bc5bd1b9a072b502 Mon Sep 17 00:00:00 2001 From: Alexander Matveev Date: Mon, 30 Mar 2026 22:02:48 +0000 Subject: [PATCH 063/116] 8380634: [macos] Remove macOS version restrictions on start with zero and limit to three components Reviewed-by: asemenyuk --- .../jpackage/internal/CFBundleVersion.java | 25 +++++-------------- .../resources/MacResources.properties | 4 +-- .../resources/MacResources_de.properties | 2 -- .../resources/MacResources_ja.properties | 2 -- .../resources/MacResources_zh_CN.properties | 2 -- .../internal/PlatformVersionTest.java | 10 ++------ .../cli/OptionsValidationFailTest.excludes | 2 -- .../tools/jpackage/share/AppVersionTest.java | 22 +++++++++++++--- test/jdk/tools/jpackage/share/ErrorTest.java | 6 ----- 9 files changed, 27 insertions(+), 48 deletions(-) diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/CFBundleVersion.java b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/CFBundleVersion.java index 17c310dbe56..30b79b563da 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/CFBundleVersion.java +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/CFBundleVersion.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,6 @@ */ package jdk.jpackage.internal; -import java.math.BigInteger; import jdk.jpackage.internal.model.DottedVersion; @@ -33,25 +32,13 @@ final class CFBundleVersion { * Parse the given string as OSX CFBundleVersion. * CFBundleVersion (String - iOS, OS X) specifies the build version number of * the bundle, which identifies an iteration (released or unreleased) of the - * bundle. The build version number should be a string comprised of at most three - * non-negative, period-separated integers with the first integer being greater - * than zero. + * bundle. The build version number should be a string comprised of non-negative, + * period-separated integers. macOS will ignore anything after 3 components, but + * it acceptable to have more then 3 components. + * * @throws IllegalArgumentException */ static DottedVersion of(String value) { - DottedVersion ver = DottedVersion.greedy(value); - - BigInteger[] components = ver.getComponents(); - if (components.length > 3) { - throw new IllegalArgumentException(I18N.getString( - "message.version-string-too-many-components")); - } - - if (BigInteger.ZERO.equals(components[0])) { - throw new IllegalArgumentException(I18N.getString( - "message.version-string-first-number-not-zero")); - } - - return ver; + return DottedVersion.greedy(value); } } diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources.properties b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources.properties index 2ed1f740805..f181bbf79af 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources.properties +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources.properties @@ -23,7 +23,7 @@ # questions. # # -error.invalid-cfbundle-version.advice=Set a compatible 'app-version' value. Valid versions are one to three integers separated by dots. +error.invalid-cfbundle-version.advice=Set a compatible 'app-version' value. Valid version is a string comprised of non-negative, period-separated integers. error.certificate.outside-validity-period=The certificate "{0}" is outside its validity period error.cert.not.found=No certificate found matching [{0}] using keychain [{1}] error.multiple.certs.found=Multiple certificates matching name [{0}] found in keychain [{1}] @@ -56,8 +56,6 @@ resource.launchd-plist-file=launchd plist file message.bundle-name-too-long-warning={0} is set to ''{1}'', which is longer than 16 characters. For a better Mac experience consider shortening it. message.preparing-info-plist=Preparing Info.plist: {0}. message.icon-not-icns= The specified icon "{0}" is not an ICNS file and will not be used. The default icon will be used in it's place. -message.version-string-too-many-components='app-version' may have between 1 and 3 numbers: 1, 1.2, 1.2.3. -message.version-string-first-number-not-zero=The first number in an app-version cannot be zero or negative. message.keychain.error=Unable to get keychain list. message.derived-bundle-identifier=Derived bundle identifier: {0} message.preparing-dmg-setup=Preparing dmg setup: {0}. diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_de.properties b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_de.properties index 367f3216f85..02e8c029ec6 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_de.properties +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_de.properties @@ -54,8 +54,6 @@ resource.launchd-plist-file=launchd-PLIST-Datei message.bundle-name-too-long-warning={0} ist auf "{1}" gesetzt. Dies ist länger als 16 Zeichen. Kürzen Sie den Wert, um die Mac-Nutzungserfahrung zu verbessern. message.preparing-info-plist=Info.plist wird vorbereitet: {0}. message.icon-not-icns= Das angegebene Symbol "{0}" ist keine ICNS-Datei und wird nicht verwendet. Stattdessen wird das Standardsymbol verwendet. -message.version-string-too-many-components="app-version" darf ein bis drei Zahlen aufweisen: 1, 1.2, 1.2.3. -message.version-string-first-number-not-zero=Die erste Zahl in app-version darf nicht null oder negativ sein. message.keychain.error=Schlüsselbundliste kann nicht abgerufen werden. message.invalid-identifier=Ungültige Mac-Bundle-ID [{0}]. message.invalid-identifier.advice=Geben Sie die ID mit "--mac-package-identifier" an. diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_ja.properties b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_ja.properties index ba2497d30dd..c9de142d796 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_ja.properties +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_ja.properties @@ -54,8 +54,6 @@ resource.launchd-plist-file=launchd plistファイル message.bundle-name-too-long-warning={0}が16文字を超える''{1}''に設定されています。Macでの操作性をより良くするために短くすることを検討してください。 message.preparing-info-plist=Info.plistを準備しています: {0}。 message.icon-not-icns= 指定したアイコン"{0}"はICNSファイルではなく、使用されません。デフォルト・アイコンがその位置に使用されます。 -message.version-string-too-many-components='app-version'には、1、1.2、1.2.3など1から3の数字を使用できます。 -message.version-string-first-number-not-zero=pp-versionの最初の数字は、ゼロまたは負の値にできません。 message.keychain.error=キーチェーン・リストを取得できません。 message.invalid-identifier=macバンドル識別子[{0}]が無効です。 message.invalid-identifier.advice="--mac-package-identifier"で識別子を指定してください。 diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_zh_CN.properties b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_zh_CN.properties index f855a31caae..9a925859af5 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_zh_CN.properties +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_zh_CN.properties @@ -54,8 +54,6 @@ resource.launchd-plist-file=launchd plist 文件 message.bundle-name-too-long-warning={0}已设置为 ''{1}'', 其长度超过了 16 个字符。为了获得更好的 Mac 体验, 请考虑将其缩短。 message.preparing-info-plist=正在准备 Info.plist: {0}。 message.icon-not-icns= 指定的图标 "{0}" 不是 ICNS 文件, 不会使用。将使用默认图标代替。 -message.version-string-too-many-components='app-version' 可以包含 1 到 3 个数字:1、1.2、1.2.3。 -message.version-string-first-number-not-zero=app-version 中的第一个数字不能为零或负数。 message.keychain.error=无法获取密钥链列表。 message.invalid-identifier=mac 包标识符 [{0}] 无效。 message.invalid-identifier.advice=请使用 "--mac-package-identifier" 指定标识符。 diff --git a/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/PlatformVersionTest.java b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/PlatformVersionTest.java index 5e3e27caced..60933214c59 100644 --- a/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/PlatformVersionTest.java +++ b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/PlatformVersionTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -62,17 +62,11 @@ public void testInvalidMsiProductVersion(String version) { } @ParameterizedTest - @ValueSource(strings = {"1", "1.2", "1.2.3"}) + @ValueSource(strings = {"0", "0.1", "1", "1.2", "1.2.3", "1.2.3.4"}) public void testValidCfBundleVersion(String version) { testImpl(PlatformVersion.MAC_CFBUNDLE_VERSION_CLASS, version, true); } - @ParameterizedTest - @ValueSource(strings = {"0", "0.1", "1.2.3.4"}) - public void testInvalidCfBundleVersion(String version) { - testImpl(PlatformVersion.MAC_CFBUNDLE_VERSION_CLASS, version, false); - } - private static void testImpl(PlatformVersion parser, String version, boolean valid) { assumeTrue(parser.parser != null); if (valid) { diff --git a/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/cli/OptionsValidationFailTest.excludes b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/cli/OptionsValidationFailTest.excludes index a7a65402b9c..52da229afa7 100644 --- a/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/cli/OptionsValidationFailTest.excludes +++ b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/cli/OptionsValidationFailTest.excludes @@ -1,5 +1,3 @@ -ErrorTest.test(IMAGE; app-desc=Hello; args-add=[--app-version, 0.2]; errors=[message.error-header+[message.version-string-first-number-not-zero], message.advice-header+[error.invalid-cfbundle-version.advice]]) -ErrorTest.test(IMAGE; app-desc=Hello; args-add=[--app-version, 1.2.3.4]; errors=[message.error-header+[message.version-string-too-many-components], message.advice-header+[error.invalid-cfbundle-version.advice]]) ErrorTest.test(IMAGE; app-desc=Hello; args-add=[--app-version, 1.]; errors=[message.error-header+[error.version-string-zero-length-component, 1.], message.advice-header+[error.invalid-cfbundle-version.advice]]) ErrorTest.test(IMAGE; app-desc=Hello; args-add=[--app-version, 1.]; errors=[message.error-header+[error.version-string-zero-length-component, 1.]]) ErrorTest.test(IMAGE; app-desc=Hello; args-add=[--app-version, 1.b.3]; errors=[message.error-header+[error.version-string-invalid-component, 1.b.3, b.3], message.advice-header+[error.invalid-cfbundle-version.advice]]) diff --git a/test/jdk/tools/jpackage/share/AppVersionTest.java b/test/jdk/tools/jpackage/share/AppVersionTest.java index 598ee1551b3..2dab3c7387b 100644 --- a/test/jdk/tools/jpackage/share/AppVersionTest.java +++ b/test/jdk/tools/jpackage/share/AppVersionTest.java @@ -47,6 +47,7 @@ import java.util.function.Consumer; import java.util.function.Predicate; import jdk.internal.util.OperatingSystem; +import jdk.jpackage.internal.model.DottedVersion; import jdk.jpackage.internal.util.MacBundle; import jdk.jpackage.internal.util.RuntimeReleaseFile; import jdk.jpackage.internal.util.Slot; @@ -173,6 +174,16 @@ public static Collection testApp() { AppTestSpec.create(builder, testCases::add); } + if (TKit.isOSX()) { + // Ensure "0.1" is a valid version on macOS. + AppTestSpec.create("Hello", TestSpec.build() + .versionFromCmdline("0.1"), testCases::add); + + // Ensure "1.2.3.4.5" is a valid version on macOS. + AppTestSpec.create("Hello", TestSpec.build() + .versionFromCmdline("1.2.3.4.5"), testCases::add); + } + return testCases.stream().map(v -> { return new Object[] {v}; }).toList(); @@ -484,10 +495,13 @@ void validateVersion(ConfigurationTarget cfg) { : cmd.pathToUnpackedPackageFile(cmd.appInstallationDirectory()); var plist = MacHelper.readPListFromAppImage(bundleRoot); var expectedVersion = expected.get(cmd.packageType()).version(); - for (var prop : List.of("CFBundleVersion", "CFBundleShortVersionString")) { - TKit.assertEquals(expectedVersion, plist.queryValue(prop), - String.format("Check the value of '%s' property in [%s] bundle", prop, bundleRoot)); - } + TKit.assertEquals(expectedVersion, plist.queryValue("CFBundleVersion"), + String.format("Check the value of '%s' property in [%s] bundle", + "CFBundleVersion", bundleRoot)); + TKit.assertEquals(DottedVersion.lazy(expectedVersion).trim(3).toComponentsString(), + plist.queryValue("CFBundleShortVersionString"), + String.format("Check the value of '%s' property in [%s] bundle", + "CFBundleShortVersionString", bundleRoot)); }); } } diff --git a/test/jdk/tools/jpackage/share/ErrorTest.java b/test/jdk/tools/jpackage/share/ErrorTest.java index ed5865024fa..ba0f5663d45 100644 --- a/test/jdk/tools/jpackage/share/ErrorTest.java +++ b/test/jdk/tools/jpackage/share/ErrorTest.java @@ -1002,12 +1002,6 @@ public static Collection testMac() { final List testCases = new ArrayList<>(); testCases.addAll(Stream.of( - testSpec().addArgs("--app-version", "0.2") - .error("message.version-string-first-number-not-zero") - .advice("error.invalid-cfbundle-version.advice"), - testSpec().addArgs("--app-version", "1.2.3.4") - .error("message.version-string-too-many-components") - .advice("error.invalid-cfbundle-version.advice"), testSpec().invalidTypeArg("--mac-installer-sign-identity", "foo"), testSpec().type(PackageType.MAC_DMG).invalidTypeArg("--mac-installer-sign-identity", "foo"), testSpec().invalidTypeArg("--mac-dmg-content", "foo"), From 6350c3641e2a6cbb15aaaf2f62ebd2007eca3954 Mon Sep 17 00:00:00 2001 From: Ioi Lam Date: Mon, 30 Mar 2026 23:14:13 +0000 Subject: [PATCH 064/116] 8377703: Assert that all AOT heap objects have valid classes Reviewed-by: kvn, eosterlund --- src/hotspot/share/cds/archiveUtils.hpp | 38 +++++++++++++++++++++++++- src/hotspot/share/cds/heapShared.cpp | 25 +++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/cds/archiveUtils.hpp b/src/hotspot/share/cds/archiveUtils.hpp index 84ad8e6bdf3..42455adedd0 100644 --- a/src/hotspot/share/cds/archiveUtils.hpp +++ b/src/hotspot/share/cds/archiveUtils.hpp @@ -36,6 +36,8 @@ #include "runtime/semaphore.hpp" #include "utilities/bitMap.hpp" #include "utilities/exceptions.hpp" +#include "utilities/growableArray.hpp" +#include "utilities/hashTable.hpp" #include "utilities/macros.hpp" class BootstrapInfo; @@ -44,7 +46,6 @@ class ReservedSpace; class VirtualSpace; template class Array; -template class GrowableArray; // ArchivePtrMarker is used to mark the location of pointers embedded in a CDS archive. E.g., when an // InstanceKlass k is dumped, we mark the location of the k->_name pointer by effectively calling @@ -401,4 +402,39 @@ class ArchiveWorkers : public StackObj { void run_task(ArchiveWorkerTask* task); }; +// A utility class for writing an array of unique items into the +// AOT cache. For determinism, the order of the array is the same +// as calls to add(). I.e., if items are added in the order +// of A, B, A, C, B, D, then the array will be written as {A, B, C, D} +template +class ArchivableTable : public AnyObj { + using Table = HashTable; + Table* _seen_items; + GrowableArray* _ordered_array; +public: + ArchivableTable() { + _seen_items = new (mtClassShared)Table(); + _ordered_array = new (mtClassShared)GrowableArray(128, mtClassShared); + } + + ~ArchivableTable() { + delete _seen_items; + delete _ordered_array; + } + + void add(T t) { + bool created; + _seen_items->put_if_absent(t, &created); + if (created) { + _ordered_array->append(t); + } + } + + Array* write_ordered_array() { + return ArchiveUtils::archive_array(_ordered_array); + } +}; + +using ArchivableKlassTable = ArchivableTable; + #endif // SHARE_CDS_ARCHIVEUTILS_HPP diff --git a/src/hotspot/share/cds/heapShared.cpp b/src/hotspot/share/cds/heapShared.cpp index 3d10e7e1f88..f721b4b370c 100644 --- a/src/hotspot/share/cds/heapShared.cpp +++ b/src/hotspot/share/cds/heapShared.cpp @@ -112,6 +112,11 @@ static Klass* _test_class = nullptr; static const ArchivedKlassSubGraphInfoRecord* _test_class_record = nullptr; #endif +#ifdef ASSERT +// All classes that have at least one instance in the cached heap. +static ArchivableKlassTable* _dumptime_classes_with_cached_oops = nullptr; +static Array* _runtime_classes_with_cached_oops = nullptr; +#endif // // If you add new entries to the following tables, you should know what you're doing! @@ -391,6 +396,21 @@ void HeapShared::initialize_streaming() { } void HeapShared::enable_gc() { +#ifdef ASSERT + // At this point, a GC may start and will be able to see some or all + // of the cached oops. The class of each oop seen by the GC must have + // already been loaded. One function with such a requirement is + // ClaimMetadataVisitingOopIterateClosure::do_klass(). + if (is_archived_heap_in_use()) { + Array* klasses = _runtime_classes_with_cached_oops; + + for (int i = 0; i < klasses->length(); i++) { + assert(klasses->at(i)->class_loader_data() != nullptr, + "class of cached oop must have been loaded"); + } + } +#endif + if (AOTStreamedHeapLoader::is_in_use()) { AOTStreamedHeapLoader::enable_gc(); } @@ -567,6 +587,7 @@ bool HeapShared::archive_object(oop obj, oop referrer, KlassSubGraphInfo* subgra AOTArtifactFinder::add_cached_class(obj->klass()); AOTOopChecker::check(obj); // Make sure contents of this oop are safe. count_allocation(obj->size()); + DEBUG_ONLY(_dumptime_classes_with_cached_oops->add(obj->klass())); if (HeapShared::is_writing_streaming_mode()) { AOTStreamedHeapWriter::add_source_obj(obj); @@ -686,6 +707,7 @@ void HeapShared::init_dumping() { _scratch_objects_table = new (mtClass)MetaspaceObjToOopHandleTable(); _pending_roots = new GrowableArrayCHeap(500); _pending_roots->append(nullptr); // root index 0 represents a null oop + DEBUG_ONLY(_dumptime_classes_with_cached_oops = new (mtClassShared)ArchivableKlassTable()); } void HeapShared::init_scratch_objects_for_basic_type_mirrors(TRAPS) { @@ -967,6 +989,8 @@ void HeapShared::write_heap(AOTMappedHeapInfo* mapped_heap_info, AOTStreamedHeap ArchiveBuilder::OtherROAllocMark mark; write_subgraph_info_table(); + DEBUG_ONLY(_runtime_classes_with_cached_oops = _dumptime_classes_with_cached_oops->write_ordered_array()); + delete _pending_roots; _pending_roots = nullptr; @@ -1278,6 +1302,7 @@ void HeapShared::serialize_tables(SerializeClosure* soc) { _run_time_subgraph_info_table.serialize_header(soc); soc->do_ptr(&_run_time_special_subgraph); + DEBUG_ONLY(soc->do_ptr(&_runtime_classes_with_cached_oops)); } static void verify_the_heap(Klass* k, const char* which) { From 6649eee753760d192ee6be10d0e7b0ca09179bff Mon Sep 17 00:00:00 2001 From: Alexey Semenyuk Date: Tue, 31 Mar 2026 00:03:46 +0000 Subject: [PATCH 065/116] 8381367: [lworld] tools/jpackage/share/AppVersionTest.java timed out while reporting errors Reviewed-by: almatvee --- .../tools/jpackage/helpers/jdk/jpackage/test/MacHelper.java | 6 +++--- test/jdk/tools/jpackage/share/AppVersionTest.java | 5 +---- 2 files changed, 4 insertions(+), 7 deletions(-) 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 1372058d440..4e0d57631b9 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacHelper.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacHelper.java @@ -557,10 +557,10 @@ private static Path createRuntimeBundle(JPackageCommand.RuntimeImageType type, O final var unpackedRuntimeBundleDir = runtimeBundleWorkDir.resolve("unpacked"); - // Preferably create a DMG bundle, fallback to PKG if DMG packaging is disabled. + // Preferably create a PKG bundle, fallback to DMG if PKG packaging is disabled. new PackageTest().forTypes(Stream.of( - PackageType.MAC_DMG, - PackageType.MAC_PKG + PackageType.MAC_PKG, + PackageType.MAC_DMG ).filter(PackageType::isEnabled).findFirst().orElseThrow(PackageType::throwSkippedExceptionIfNativePackagingUnavailable)) .addInitializer(cmd -> { cmd.useToolProvider(true) diff --git a/test/jdk/tools/jpackage/share/AppVersionTest.java b/test/jdk/tools/jpackage/share/AppVersionTest.java index 2dab3c7387b..2ef7f95398e 100644 --- a/test/jdk/tools/jpackage/share/AppVersionTest.java +++ b/test/jdk/tools/jpackage/share/AppVersionTest.java @@ -71,7 +71,7 @@ * @library /test/jdk/tools/jpackage/helpers * @build jdk.jpackage.test.* * @compile -Xlint:all -Werror AppVersionTest.java - * @run main/othervm/timeout=1440 -Xmx512m jdk.jpackage.test.Main + * @run main/othervm/timeout=2880 -Xmx512m jdk.jpackage.test.Main * --jpt-run=AppVersionTest */ @@ -1003,9 +1003,6 @@ private Path createRuntime(RuntimeType type, Optional releaseFileVersion }); yield MacBundle.fromPath(predefinedRuntimeDir).orElseThrow().homeDir(); } - default -> { - throw new AssertionError(); - } }; releaseFileVersion.ifPresent(ver -> { From 2eec71a500e8df02f5abc7d1e65bdf06da5a2efc Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Tue, 31 Mar 2026 01:19:46 +0000 Subject: [PATCH 066/116] 8380422: Fix Formatting issues missed in JDK-8380125 Reviewed-by: dnguyen, serb --- .../classes/javax/swing/AbstractButton.java | 2 +- .../swing/ActionPropertyChangeListener.java | 2 +- .../classes/javax/swing/AncestorNotifier.java | 2 +- .../share/classes/javax/swing/ArrayTable.java | 8 +- .../share/classes/javax/swing/JComboBox.java | 4 +- .../share/classes/javax/swing/JList.java | 2 +- .../share/classes/javax/swing/JTextField.java | 4 +- .../share/classes/javax/swing/JTree.java | 2 +- .../classes/javax/swing/KeyboardManager.java | 2 +- .../share/classes/javax/swing/UIDefaults.java | 4 +- .../swing/plaf/basic/BasicComboPopup.java | 76 +++++++++---------- .../javax/swing/plaf/basic/BasicListUI.java | 2 +- .../swing/plaf/basic/BasicMenuBarUI.java | 8 +- .../swing/plaf/basic/BasicPopupMenuUI.java | 2 +- .../swing/plaf/basic/BasicSpinnerUI.java | 2 +- .../swing/plaf/basic/BasicTabbedPaneUI.java | 26 +++---- .../swing/plaf/basic/BasicToolBarUI.java | 2 +- .../javax/swing/plaf/basic/BasicTreeUI.java | 2 +- .../plaf/nimbus/AbstractRegionPainter.java | 2 +- .../swing/plaf/nimbus/NimbusLookAndFeel.java | 2 +- .../swing/plaf/nimbus/SynthPainterImpl.java | 2 +- .../swing/plaf/synth/SynthComboBoxUI.java | 2 +- .../swing/plaf/synth/SynthScrollPaneUI.java | 2 +- .../classes/javax/swing/text/TextAction.java | 2 +- .../swing/tree/DefaultTreeCellEditor.java | 2 +- 25 files changed, 83 insertions(+), 83 deletions(-) diff --git a/src/java.desktop/share/classes/javax/swing/AbstractButton.java b/src/java.desktop/share/classes/javax/swing/AbstractButton.java index a1961acce29..ad5f0eba3de 100644 --- a/src/java.desktop/share/classes/javax/swing/AbstractButton.java +++ b/src/java.desktop/share/classes/javax/swing/AbstractButton.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/src/java.desktop/share/classes/javax/swing/ActionPropertyChangeListener.java b/src/java.desktop/share/classes/javax/swing/ActionPropertyChangeListener.java index 19b9152a1b5..7d33e936b7b 100644 --- a/src/java.desktop/share/classes/javax/swing/ActionPropertyChangeListener.java +++ b/src/java.desktop/share/classes/javax/swing/ActionPropertyChangeListener.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/src/java.desktop/share/classes/javax/swing/AncestorNotifier.java b/src/java.desktop/share/classes/javax/swing/AncestorNotifier.java index a3ed463d2d5..3606bdc9c0b 100644 --- a/src/java.desktop/share/classes/javax/swing/AncestorNotifier.java +++ b/src/java.desktop/share/classes/javax/swing/AncestorNotifier.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/src/java.desktop/share/classes/javax/swing/ArrayTable.java b/src/java.desktop/share/classes/javax/swing/ArrayTable.java index 282bd3454ca..4941264c0fe 100644 --- a/src/java.desktop/share/classes/javax/swing/ArrayTable.java +++ b/src/java.desktop/share/classes/javax/swing/ArrayTable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -148,7 +148,7 @@ public Object get(Object key) { if (table != null) { if (isArray()) { Object[] array = (Object[])table; - for (int i = 0; i[] getClassArray(Object[] args) { Class[] types = null; if (args != null) { types = new Class[args.length]; - for (int i = 0; i< args.length; i++) { + for (int i = 0; i < args.length; i++) { /* PENDING(ges): At present only the primitive types used are handled correctly; this should eventually handle all primitive types */ diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicComboPopup.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicComboPopup.java index 42791772c2d..d825dd73e9c 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicComboPopup.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicComboPopup.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -243,8 +243,8 @@ public void show() { public void hide() { MenuSelectionManager manager = MenuSelectionManager.defaultManager(); MenuElement [] selection = manager.getSelectedPath(); - for ( int i = 0 ; i < selection.length ; i++ ) { - if ( selection[i] == this ) { + for (int i = 0 ; i < selection.length; i++ ) { + if (selection[i] == this) { manager.clearSelectedPath(); break; } @@ -924,7 +924,7 @@ public void mousePressed(MouseEvent e) { if (!SwingUtilities.isLeftMouseButton(e) || !comboBox.isEnabled() || !comboBox.isShowing()) return; - if ( comboBox.isEditable() ) { + if (comboBox.isEditable()) { Component comp = comboBox.getEditor().getEditorComponent(); if ((!(comp instanceof JComponent)) || ((JComponent)comp).isRequestFocusEnabled()) { comp.requestFocus(FocusEvent.Cause.MOUSE_EVENT); @@ -957,12 +957,12 @@ public void mouseReleased(MouseEvent e) { Component source = (Component)e.getSource(); Dimension size = source.getSize(); Rectangle bounds = new Rectangle( 0, 0, size.width, size.height); - if ( !bounds.contains( e.getPoint() ) ) { + if (!bounds.contains(e.getPoint())) { MouseEvent newEvent = convertMouseEvent( e ); Point location = newEvent.getPoint(); Rectangle r = new Rectangle(); list.computeVisibleRect( r ); - if ( r.contains( location ) ) { + if (r.contains(location)) { if (comboBox.getSelectedIndex() == list.getSelectedIndex()) { comboBox.getEditor().setItem(list.getSelectedValue()); } @@ -989,7 +989,7 @@ public void mouseMoved(MouseEvent anEvent) { Point location = anEvent.getPoint(); Rectangle r = new Rectangle(); list.computeVisibleRect( r ); - if ( r.contains( location ) ) { + if (r.contains(location)) { updateListBoxSelectionForEvent( anEvent, false ); } } @@ -999,34 +999,34 @@ public void mouseDragged( MouseEvent e ) { if (e.getSource() == list) { return; } - if ( isVisible() ) { + if (isVisible()) { MouseEvent newEvent = convertMouseEvent( e ); Rectangle r = new Rectangle(); list.computeVisibleRect( r ); - if ( newEvent.getPoint().y >= r.y && newEvent.getPoint().y <= r.y + r.height - 1 ) { + if (newEvent.getPoint().y >= r.y && newEvent.getPoint().y <= r.y + r.height - 1) { hasEntered = true; - if ( isAutoScrolling ) { + if (isAutoScrolling) { stopAutoScrolling(); } Point location = newEvent.getPoint(); - if ( r.contains( location ) ) { + if (r.contains(location)) { updateListBoxSelectionForEvent( newEvent, false ); } } else { - if ( hasEntered ) { + if (hasEntered) { int directionToScroll = newEvent.getPoint().y < r.y ? SCROLL_UP : SCROLL_DOWN; - if ( isAutoScrolling && scrollDirection != directionToScroll ) { + if (isAutoScrolling && scrollDirection != directionToScroll) { stopAutoScrolling(); startAutoScrolling( directionToScroll ); } - else if ( !isAutoScrolling ) { + else if (!isAutoScrolling) { startAutoScrolling( directionToScroll ); } } else { - if ( e.getPoint().y < 0 ) { + if (e.getPoint().y < 0) { hasEntered = true; startAutoScrolling( SCROLL_UP ); } @@ -1043,7 +1043,7 @@ public void propertyChange(PropertyChangeEvent e) { JComboBox comboBox = (JComboBox)e.getSource(); String propertyName = e.getPropertyName(); - if ( propertyName == "model" ) { + if (propertyName == "model") { @SuppressWarnings("unchecked") ComboBoxModel oldModel = (ComboBoxModel)e.getOldValue(); @SuppressWarnings("unchecked") @@ -1053,13 +1053,13 @@ public void propertyChange(PropertyChangeEvent e) { list.setModel(newModel); - if ( isVisible() ) { + if (isVisible()) { hide(); } } - else if ( propertyName == "renderer" ) { + else if (propertyName == "renderer") { list.setCellRenderer( comboBox.getRenderer() ); - if ( isVisible() ) { + if (isVisible()) { hide(); } } @@ -1067,18 +1067,18 @@ else if (propertyName == "componentOrientation") { // Pass along the new component orientation // to the list and the scroller - ComponentOrientation o =(ComponentOrientation)e.getNewValue(); + ComponentOrientation o = (ComponentOrientation)e.getNewValue(); JList list = getList(); - if (list != null && list.getComponentOrientation()!=o) { + if (list != null && list.getComponentOrientation() != o) { list.setComponentOrientation(o); } - if (scroller != null && scroller.getComponentOrientation()!=o) { + if (scroller != null && scroller.getComponentOrientation() != o) { scroller.setComponentOrientation(o); } - if (o!=getComponentOrientation()) { + if (o != getComponentOrientation()) { setComponentOrientation(o); } } @@ -1134,13 +1134,13 @@ public boolean isFocusTraversable() { protected void startAutoScrolling( int direction ) { // XXX - should be a private method within InvocationMouseMotionHandler // if possible. - if ( isAutoScrolling ) { + if (isAutoScrolling) { autoscrollTimer.stop(); } isAutoScrolling = true; - if ( direction == SCROLL_UP ) { + if (direction == SCROLL_UP) { scrollDirection = SCROLL_UP; Point convertedPoint = SwingUtilities.convertPoint( scroller, new Point( 1, 1 ), list ); int top = list.locationToIndex( convertedPoint ); @@ -1149,7 +1149,7 @@ protected void startAutoScrolling( int direction ) { autoscrollTimer = new Timer( 100, new AutoScrollActionHandler( SCROLL_UP) ); } - else if ( direction == SCROLL_DOWN ) { + else if (direction == SCROLL_DOWN) { scrollDirection = SCROLL_DOWN; Dimension size = scroller.getSize(); Point convertedPoint = SwingUtilities.convertPoint( scroller, @@ -1171,7 +1171,7 @@ else if ( direction == SCROLL_DOWN ) { protected void stopAutoScrolling() { isAutoScrolling = false; - if ( autoscrollTimer != null ) { + if (autoscrollTimer != null) { autoscrollTimer.stop(); autoscrollTimer = null; } @@ -1183,7 +1183,7 @@ protected void stopAutoScrolling() { */ protected void autoScrollUp() { int index = list.getSelectedIndex(); - if ( index > 0 ) { + if (index > 0) { list.setSelectedIndex( index - 1 ); list.ensureIndexIsVisible( index - 1 ); } @@ -1196,7 +1196,7 @@ protected void autoScrollUp() { protected void autoScrollDown() { int index = list.getSelectedIndex(); int lastItem = list.getModel().getSize() - 1; - if ( index < lastItem ) { + if (index < lastItem) { list.setSelectedIndex( index + 1 ); list.ensureIndexIsVisible( index + 1 ); } @@ -1234,7 +1234,7 @@ public AccessibleContext getAccessibleContext() { * @param e a mouse event */ protected void delegateFocus( MouseEvent e ) { - if ( comboBox.isEditable() ) { + if (comboBox.isEditable()) { Component comp = comboBox.getEditor().getEditorComponent(); if ((!(comp instanceof JComponent)) || ((JComponent)comp).isRequestFocusEnabled()) { if (e != null) { @@ -1258,7 +1258,7 @@ else if (comboBox.isRequestFocusEnabled()) { * visible. */ protected void togglePopup() { - if ( isVisible() ) { + if (isVisible()) { hide(); } else { @@ -1274,7 +1274,7 @@ protected void togglePopup() { * @param selectedIndex the index to set the list */ private void setListSelection(int selectedIndex) { - if ( selectedIndex == -1 ) { + if (selectedIndex == -1) { list.clearSelection(); } else { @@ -1325,7 +1325,7 @@ protected int getPopupHeightForRowCount(int maxRowCount) { ListCellRenderer renderer = list.getCellRenderer(); Object value = null; - for ( int i = 0; i < minRowCount; ++i ) { + for (int i = 0; i < minRowCount; ++i) { value = list.getModel().getElementAt( i ); Component c = renderer.getListCellRendererComponent( list, value, i, false, false ); height += c.getPreferredSize().height; @@ -1439,18 +1439,18 @@ protected void updateListBoxSelectionForEvent(MouseEvent anEvent,boolean shouldS // XXX - only seems to be called from this class. shouldScroll flag is // never true Point location = anEvent.getPoint(); - if ( list == null ) + if (list == null) return; int index = list.locationToIndex(location); - if ( index == -1 ) { - if ( location.y < 0 ) + if (index == -1) { + if (location.y < 0) index = 0; else index = comboBox.getModel().getSize() - 1; } - if ( list.getSelectedIndex() != index ) { + if (list.getSelectedIndex() != index) { list.setSelectedIndex(index); - if ( shouldScroll ) + if (shouldScroll) list.ensureIndexIsVisible(index); } } diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicListUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicListUI.java index ab5fdb12c5a..37bcbec2156 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicListUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicListUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuBarUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuBarUI.java index b7310b56aef..a9abaee0129 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuBarUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuBarUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -237,10 +237,10 @@ private class Handler implements ChangeListener, ContainerListener { // ChangeListener // public void stateChanged(ChangeEvent e) { - int i,c; - for(i=0,c = menuBar.getMenuCount() ; i < c ; i++) { + final int c = menuBar.getMenuCount(); + for (int i = 0; i < c; i++) { JMenu menu = menuBar.getMenu(i); - if(menu != null && menu.isSelected()) { + if (menu != null && menu.isSelected()) { menuBar.getSelectionModel().setSelectedIndex(i); break; } diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicPopupMenuUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicPopupMenuUI.java index b72a2d8a140..a3ffb034b4b 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicPopupMenuUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicPopupMenuUI.java @@ -908,7 +908,7 @@ public void eventDispatched(AWTEvent ev) { } boolean isInPopup(Component src) { - for (Component c=src; c != null; c=c.getParent()) { + for (Component c = src; c != null; c = c.getParent()) { if (c instanceof Window) { break; } else if (c instanceof JPopupMenu) { diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicSpinnerUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicSpinnerUI.java index 7080fa3aac1..b523f8c7bd3 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicSpinnerUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicSpinnerUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it 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 6e0d0101b9c..de23dbab29a 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, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -504,7 +504,7 @@ protected void installListeners() { tabPane.addFocusListener(focusListener); } tabPane.addContainerListener(getHandler()); - if (tabPane.getTabCount()>0) { + if (tabPane.getTabCount() > 0) { Boolean htmlDisabled = (Boolean) tabPane.getClientProperty("html.disable"); if (!(Boolean.TRUE.equals(htmlDisabled))) { @@ -949,8 +949,8 @@ protected void paintTabArea(Graphics g, int tabPlacement, int selectedIndex) { // Paint tabRuns of tabs from back to front for (int i = runCount - 1; i >= 0; i--) { int start = tabRuns[i]; - int next = tabRuns[(i == runCount - 1)? 0 : i + 1]; - int end = (next != 0? next - 1: tabCount - 1); + int next = tabRuns[(i == runCount - 1) ? 0 : i + 1]; + int end = (next != 0 ? next - 1 : tabCount - 1); for (int j = start; j <= end; j++) { if (j != selectedIndex && rects[j].intersects(clipRect)) { paintTab(g, tabPlacement, rects, j, iconRect, textRect); @@ -1118,7 +1118,7 @@ private void paintCroppedTabEdge(Graphics g) { int xx = x; g.setColor(shadow); while(xx <= x+rects[tabIndex].width) { - for (int i=0; i < xCropLen.length; i+=2) { + for (int i = 0; i < xCropLen.length; i += 2) { g.drawLine(xx+yCropLen[i],y-xCropLen[i], xx+yCropLen[i+1]-1,y-xCropLen[i+1]); } @@ -1133,7 +1133,7 @@ private void paintCroppedTabEdge(Graphics g) { int yy = y; g.setColor(shadow); while(yy <= y+rects[tabIndex].height) { - for (int i=0; i < xCropLen.length; i+=2) { + for (int i = 0; i < xCropLen.length; i += 2) { g.drawLine(x-xCropLen[i],yy+yCropLen[i], x-xCropLen[i+1],yy+yCropLen[i+1]-1); } @@ -1549,7 +1549,7 @@ else if ( selectedColor == null || selectedIndex == -1 ) { protected void paintContentBorderTopEdge(Graphics g, int tabPlacement, int selectedIndex, int x, int y, int w, int h) { - Rectangle selRect = selectedIndex < 0? null : + Rectangle selRect = selectedIndex < 0 ? null : getTabBounds(selectedIndex, calcRect); g.setColor(lightHighlight); @@ -1588,7 +1588,7 @@ protected void paintContentBorderTopEdge(Graphics g, int tabPlacement, protected void paintContentBorderLeftEdge(Graphics g, int tabPlacement, int selectedIndex, int x, int y, int w, int h) { - Rectangle selRect = selectedIndex < 0? null : + Rectangle selRect = selectedIndex < 0 ? null : getTabBounds(selectedIndex, calcRect); g.setColor(lightHighlight); @@ -1624,7 +1624,7 @@ protected void paintContentBorderLeftEdge(Graphics g, int tabPlacement, protected void paintContentBorderBottomEdge(Graphics g, int tabPlacement, int selectedIndex, int x, int y, int w, int h) { - Rectangle selRect = selectedIndex < 0? null : + Rectangle selRect = selectedIndex < 0 ? null : getTabBounds(selectedIndex, calcRect); g.setColor(shadow); @@ -1667,7 +1667,7 @@ protected void paintContentBorderBottomEdge(Graphics g, int tabPlacement, protected void paintContentBorderRightEdge(Graphics g, int tabPlacement, int selectedIndex, int x, int y, int w, int h) { - Rectangle selRect = selectedIndex < 0? null : + Rectangle selRect = selectedIndex < 0 ? null : getTabBounds(selectedIndex, calcRect); g.setColor(shadow); @@ -4090,7 +4090,7 @@ private void updateHtmlViews(int index, boolean inserted) { setHtmlView(v, inserted, index); } } else { // Not HTML - if (htmlViews != null) { // Add placeholder + if (htmlViews != null) { // Add placeholder setHtmlView(null, inserted, index); } // else nada! } @@ -4336,8 +4336,8 @@ public void focusLost(FocusEvent e) { private Vector createHTMLVector() { Vector htmlViews = new Vector(); int count = tabPane.getTabCount(); - if (count>0) { - for (int i=0 ; i 0) { + for (int i = 0 ; i < count; i++) { String title = tabPane.getTitleAt(i); if (BasicHTML.isHTMLString(title)) { htmlViews.addElement(BasicHTML.createHTMLView(tabPane, title)); 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 1bcd4a9be8d..9c07b6a03d1 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it 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 096fe7cc5f7..19a25005be9 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/src/java.desktop/share/classes/javax/swing/plaf/nimbus/AbstractRegionPainter.java b/src/java.desktop/share/classes/javax/swing/plaf/nimbus/AbstractRegionPainter.java index cfcc014940a..d06406d69d6 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/nimbus/AbstractRegionPainter.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/nimbus/AbstractRegionPainter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/src/java.desktop/share/classes/javax/swing/plaf/nimbus/NimbusLookAndFeel.java b/src/java.desktop/share/classes/javax/swing/plaf/nimbus/NimbusLookAndFeel.java index 05fa3bbc9b6..7ef7beb5d1c 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/nimbus/NimbusLookAndFeel.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/nimbus/NimbusLookAndFeel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/src/java.desktop/share/classes/javax/swing/plaf/nimbus/SynthPainterImpl.java b/src/java.desktop/share/classes/javax/swing/plaf/nimbus/SynthPainterImpl.java index 1842073588b..fd761ac4730 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/nimbus/SynthPainterImpl.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/nimbus/SynthPainterImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthComboBoxUI.java b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthComboBoxUI.java index ad10e70a837..0c373483153 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthComboBoxUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthComboBoxUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthScrollPaneUI.java b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthScrollPaneUI.java index 0c3a17fbdbb..c07feb8b56d 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthScrollPaneUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthScrollPaneUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/src/java.desktop/share/classes/javax/swing/text/TextAction.java b/src/java.desktop/share/classes/javax/swing/text/TextAction.java index d05f7e24a6b..00da7bad93e 100644 --- a/src/java.desktop/share/classes/javax/swing/text/TextAction.java +++ b/src/java.desktop/share/classes/javax/swing/text/TextAction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/src/java.desktop/share/classes/javax/swing/tree/DefaultTreeCellEditor.java b/src/java.desktop/share/classes/javax/swing/tree/DefaultTreeCellEditor.java index 3f3721dd30a..7595638dc66 100644 --- a/src/java.desktop/share/classes/javax/swing/tree/DefaultTreeCellEditor.java +++ b/src/java.desktop/share/classes/javax/swing/tree/DefaultTreeCellEditor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it From 5fec4ed37a7acb42e290ba8d60565b20603195aa Mon Sep 17 00:00:00 2001 From: Chen Liang Date: Tue, 31 Mar 2026 03:46:23 +0000 Subject: [PATCH 067/116] 8379679: java/foreign/TestConcurrentClose.java awaitTermination times out on Windows debug builds Reviewed-by: alanb --- .../jdk/java/foreign/TestConcurrentClose.java | 38 +++++++++---------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/test/jdk/java/foreign/TestConcurrentClose.java b/test/jdk/java/foreign/TestConcurrentClose.java index 82bb2492acf..74f0ca2a877 100644 --- a/test/jdk/java/foreign/TestConcurrentClose.java +++ b/test/jdk/java/foreign/TestConcurrentClose.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,13 +49,11 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; import static java.lang.foreign.ValueLayout.JAVA_BYTE; import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertTrue; public class TestConcurrentClose { static final WhiteBox WB = WhiteBox.getWhiteBox(); @@ -72,7 +70,6 @@ public class TestConcurrentClose { static final int ITERATIONS = 5; static final int SEGMENT_SIZE = 10_000; - static final int MAX_EXECUTOR_WAIT_SECONDS = 60; static final int NUM_ACCESSORS = 50; static final AtomicLong start = new AtomicLong(); @@ -82,25 +79,24 @@ public class TestConcurrentClose { public void testHandshake() throws InterruptedException { for (int it = 0; it < ITERATIONS; it++) { System.out.println("ITERATION " + it + " - starting"); - ExecutorService accessExecutor = Executors.newCachedThreadPool(); - start.set(System.currentTimeMillis()); - started.set(false); - CountDownLatch startClosureLatch = new CountDownLatch(1); - - for (int i = 0; i < NUM_ACCESSORS ; i++) { - Arena arena = Arena.ofShared(); - MemorySegment segment = arena.allocate(SEGMENT_SIZE, 1); - accessExecutor.execute(new SegmentAccessor(i, segment)); - accessExecutor.execute(new Closer(i, startClosureLatch, arena)); - } + try (ExecutorService accessExecutor = Executors.newCachedThreadPool()) { + start.set(System.currentTimeMillis()); + started.set(false); + CountDownLatch startClosureLatch = new CountDownLatch(1); + + for (int i = 0; i < NUM_ACCESSORS; i++) { + Arena arena = Arena.ofShared(); + MemorySegment segment = arena.allocate(SEGMENT_SIZE, 1); + accessExecutor.execute(new SegmentAccessor(i, segment)); + accessExecutor.execute(new Closer(i, startClosureLatch, arena)); + } - awaitCompilation(); + awaitCompilation(); - long closeDelay = System.currentTimeMillis() - start.get(); - System.out.println("Starting closers after delay of " + closeDelay + " millis"); - startClosureLatch.countDown(); - accessExecutor.shutdown(); - assertTrue(accessExecutor.awaitTermination(MAX_EXECUTOR_WAIT_SECONDS, TimeUnit.SECONDS)); + long closeDelay = System.currentTimeMillis() - start.get(); + System.out.println("Starting closers after delay of " + closeDelay + " millis"); + startClosureLatch.countDown(); + } long finishDelay = System.currentTimeMillis() - start.get(); System.out.println("ITERATION " + it + " - finished, after " + finishDelay + "milis"); } From 3aab51828582a48a9c7ee2729284fea8763050c6 Mon Sep 17 00:00:00 2001 From: Kirill Shirokov Date: Tue, 31 Mar 2026 05:07:04 +0000 Subject: [PATCH 068/116] 8380074: Reflection::areNestMates should be used by Class::isNestmateOf Reviewed-by: liach, dholmes --- src/java.base/share/classes/java/lang/Class.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java.base/share/classes/java/lang/Class.java b/src/java.base/share/classes/java/lang/Class.java index 8a2f722f3dd..f15291827d5 100644 --- a/src/java.base/share/classes/java/lang/Class.java +++ b/src/java.base/share/classes/java/lang/Class.java @@ -3841,7 +3841,7 @@ public boolean isNestmateOf(Class c) { return false; } - return getNestHost() == c.getNestHost(); + return Reflection.areNestMates(this, c); } private native Class[] getNestMembers0(); From 77cfead6fe84e254133681ee22d81fa190e0e371 Mon Sep 17 00:00:00 2001 From: Jayathirth D V Date: Tue, 31 Mar 2026 05:32:33 +0000 Subject: [PATCH 069/116] 8380959: Update Libpng to 1.6.56 Reviewed-by: erikj, aivanov, honkar, prr --- .../java.desktop/lib/ClientLibraries.gmk | 3 +- src/java.desktop/share/legal/libpng.md | 5 +- .../native/libsplashscreen/libpng/CHANGES | 31 ++++++++ .../native/libsplashscreen/libpng/README | 2 +- .../share/native/libsplashscreen/libpng/png.c | 16 ++-- .../share/native/libsplashscreen/libpng/png.h | 16 ++-- .../native/libsplashscreen/libpng/pngconf.h | 2 +- .../libsplashscreen/libpng/pnglibconf.h | 2 +- .../native/libsplashscreen/libpng/pngpriv.h | 4 +- .../native/libsplashscreen/libpng/pngread.c | 68 +++++++++-------- .../native/libsplashscreen/libpng/pngrtran.c | 30 +++++++- .../native/libsplashscreen/libpng/pngrutil.c | 42 ++++------- .../native/libsplashscreen/libpng/pngset.c | 73 ++++++++++++------- .../native/libsplashscreen/libpng/pngstruct.h | 6 +- .../native/libsplashscreen/libpng/pngtrans.c | 40 ++++++++-- 15 files changed, 218 insertions(+), 122 deletions(-) diff --git a/make/modules/java.desktop/lib/ClientLibraries.gmk b/make/modules/java.desktop/lib/ClientLibraries.gmk index 13a74ab409f..3e37fe79643 100644 --- a/make/modules/java.desktop/lib/ClientLibraries.gmk +++ b/make/modules/java.desktop/lib/ClientLibraries.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2026, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -257,6 +257,7 @@ ifeq ($(ENABLE_HEADLESS_ONLY), false) DISABLED_WARNINGS_microsoft_dgif_lib.c := 4018 4267, \ DISABLED_WARNINGS_microsoft_splashscreen_impl.c := 4018 4267 4244, \ DISABLED_WARNINGS_microsoft_splashscreen_png.c := 4267, \ + DISABLED_WARNINGS_microsoft_pngread.c := 4146, \ DISABLED_WARNINGS_microsoft_splashscreen_sys.c := 4267 4244, \ LDFLAGS := $(ICONV_LDFLAGS), \ LDFLAGS_windows := -delayload:user32.dll, \ diff --git a/src/java.desktop/share/legal/libpng.md b/src/java.desktop/share/legal/libpng.md index a2ffcca1974..034de22bf25 100644 --- a/src/java.desktop/share/legal/libpng.md +++ b/src/java.desktop/share/legal/libpng.md @@ -1,4 +1,4 @@ -## libpng v1.6.55 +## libpng v1.6.56 ### libpng License
@@ -168,6 +168,7 @@ Authors, for copyright and licensing purposes.
  * Glenn Randers-Pehrson
  * Greg Roelofs
  * Guy Eric Schalnat
+ * Halil Oktay
  * James Yu
  * John Bowler
  * Joshua Inscoe
@@ -187,12 +188,14 @@ Authors, for copyright and licensing purposes.
  * Sam Bushell
  * Samuel Williams
  * Simon-Pierre Cadieux
+ * Taegu Ha (하태구)
  * Tim Wegner
  * Tobias Stoeckmann
  * Tom Lane
  * Tom Tanner
  * Vadim Barkov
  * Willem van Schaik
+ * Yuelin Wang (王跃林)
  * Zhijie Liang
  * Apple Inc.
     - Zixu Wang (王子旭)
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/CHANGES b/src/java.desktop/share/native/libsplashscreen/libpng/CHANGES
index af9fcff6eb3..673d4d50420 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/CHANGES
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/CHANGES
@@ -6337,6 +6337,37 @@ Version 1.6.55 [February 9, 2026]
   Resolved an oss-fuzz build issue involving nalloc.
     (Contributed by Philippe Antoine.)
 
+Version 1.6.56 [March 25, 2026]
+  Fixed CVE-2026-33416 (high severity):
+    Use-after-free via pointer aliasing in `png_set_tRNS` and `png_set_PLTE`.
+    (Reported by Halil Oktay and Ryo Shimada;
+    fixed by Halil Oktay and Cosmin Truta.)
+  Fixed CVE-2026-33636 (high severity):
+    Out-of-bounds read/write in the palette expansion on ARM Neon.
+    (Reported by Taegu Ha; fixed by Taegu Ha and Cosmin Truta.)
+  Fixed uninitialized reads beyond `num_trans` in `trans_alpha` buffers.
+    (Contributed by Halil Oktay.)
+  Fixed stale `info_ptr->palette` after in-place gamma and background
+    transforms.
+  Fixed wrong channel indices in `png_image_read_and_map` RGB_ALPHA path.
+    (Contributed by Yuelin Wang.)
+  Fixed wrong background color in colormap read.
+    (Contributed by Yuelin Wang.)
+  Fixed dead loop in sPLT write.
+    (Contributed by Yuelin Wang.)
+  Added missing null pointer checks in four public API functions.
+    (Contributed by Yuelin Wang.)
+  Validated shift bit depths in `png_set_shift` to prevent infinite loop.
+    (Contributed by Yuelin Wang.)
+  Avoided undefined behavior in library and tests.
+  Deprecated the hardly-ever-tested POINTER_INDEXING config option.
+  Added negative-stride test coverage for the simplified API.
+  Fixed memory leaks and API misuse in oss-fuzz.
+    (Contributed by Owen Sanzas.)
+  Implemented various fixes and improvements in oss-fuzz.
+    (Contributed by Bob Friesenhahn and Philippe Antoine.)
+  Performed various refactorings and cleanups.
+
 Send comments/corrections/commendations to png-mng-implement at lists.sf.net.
 Subscription is required; visit
 
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/README b/src/java.desktop/share/native/libsplashscreen/libpng/README
index 6e0d1e33137..d0b085f7933 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/README
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/README
@@ -1,4 +1,4 @@
-README for libpng version 1.6.55
+README for libpng version 1.6.56
 ================================
 
 See the note about version numbers near the top of `png.h`.
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/png.c b/src/java.desktop/share/native/libsplashscreen/libpng/png.c
index 955fda8dd7e..fd095b515b9 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/png.c
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/png.c
@@ -42,7 +42,7 @@
 #include "pngpriv.h"
 
 /* Generate a compiler error if there is an old png.h in the search path. */
-typedef png_libpng_version_1_6_55 Your_png_h_is_not_version_1_6_55;
+typedef png_libpng_version_1_6_56 Your_png_h_is_not_version_1_6_56;
 
 /* Sanity check the chunks definitions - PNG_KNOWN_CHUNKS from pngpriv.h and the
  * corresponding macro definitions.  This causes a compile time failure if
@@ -849,7 +849,7 @@ png_get_copyright(png_const_structrp png_ptr)
    return PNG_STRING_COPYRIGHT
 #else
    return PNG_STRING_NEWLINE \
-      "libpng version 1.6.55" PNG_STRING_NEWLINE \
+      "libpng version 1.6.56" PNG_STRING_NEWLINE \
       "Copyright (c) 2018-2026 Cosmin Truta" PNG_STRING_NEWLINE \
       "Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson" \
       PNG_STRING_NEWLINE \
@@ -1199,7 +1199,7 @@ png_xy_from_XYZ(png_xy *xy, const png_XYZ *XYZ)
       return 1;
 
    /* The reference white is simply the sum of the end-point (X,Y,Z) vectors so
-    * the fillowing calculates (X+Y+Z) of the reference white (media white,
+    * the following calculates (X+Y+Z) of the reference white (media white,
     * encoding white) itself:
     */
    d = dblue;
@@ -1244,9 +1244,9 @@ png_XYZ_from_xy(png_XYZ *XYZ, const png_xy *xy)
     * (-0.0770) because the PNG spec itself requires the xy values to be
     * unsigned.  whitey is also required to be 5 or more to avoid overflow.
     *
-    * Instead the upper limits have been relaxed to accomodate ACES AP1 where
+    * Instead the upper limits have been relaxed to accommodate ACES AP1 where
     * redz ends up as -600 (-0.006).  ProPhotoRGB was already "in range."
-    * The new limit accomodates the AP0 and AP1 ranges for z but not AP0 redy.
+    * The new limit accommodates the AP0 and AP1 ranges for z but not AP0 redy.
     */
    const png_fixed_point fpLimit = PNG_FP_1+(PNG_FP_1/10);
    if (xy->redx   < 0 || xy->redx > fpLimit) return 1;
@@ -1357,7 +1357,7 @@ png_XYZ_from_xy(png_XYZ *XYZ, const png_xy *xy)
     *    red-scale + green-scale + blue-scale = 1/white-y = white-scale
     *
     * So now we have a Cramer's rule solution where the determinants are just
-    * 3x3 - far more tractible.  Unfortunately 3x3 determinants still involve
+    * 3x3 - far more tractable.  Unfortunately 3x3 determinants still involve
     * multiplication of three coefficients so we can't guarantee to avoid
     * overflow in the libpng fixed point representation.  Using Cramer's rule in
     * floating point is probably a good choice here, but it's not an option for
@@ -1726,7 +1726,7 @@ png_icc_check_header(png_const_structrp png_ptr, png_const_charp name,
     * into R, G and B channels.
     *
     * Previously it was suggested that an RGB profile on grayscale data could be
-    * handled.  However it it is clear that using an RGB profile in this context
+    * handled.  However it is clear that using an RGB profile in this context
     * must be an error - there is no specification of what it means.  Thus it is
     * almost certainly more correct to ignore the profile.
     */
@@ -2944,7 +2944,7 @@ png_gamma_significant(png_fixed_point gamma_val)
     *
     *    2.2/(2+51/256) == 1.00035524
     *
-    * I.e. vanishly small (<4E-4) but still detectable in 16-bit linear (+/-
+    * I.e. vanishingly small (<4E-4) but still detectable in 16-bit linear (+/-
     * 23).  Note that the Adobe choice seems to be something intended to give an
     * exact number with 8 binary fractional digits - it is the closest to 2.2
     * that is possible a base 2 .8p representation.
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/png.h b/src/java.desktop/share/native/libsplashscreen/libpng/png.h
index e95c0444399..56ec204cd1a 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/png.h
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/png.h
@@ -29,7 +29,7 @@
  * However, the following notice accompanied the original version of this
  * file and, per its terms, should not be removed:
  *
- * libpng version 1.6.55
+ * libpng version 1.6.56
  *
  * Copyright (c) 2018-2026 Cosmin Truta
  * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
@@ -43,7 +43,7 @@
  *   libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger
  *   libpng versions 0.97, January 1998, through 1.6.35, July 2018:
  *     Glenn Randers-Pehrson
- *   libpng versions 1.6.36, December 2018, through 1.6.55, February 2026:
+ *   libpng versions 1.6.36, December 2018, through 1.6.56, March 2026:
  *     Cosmin Truta
  *   See also "Contributing Authors", below.
  */
@@ -267,7 +267,7 @@
  *    ...
  *    1.5.30                  15    10530  15.so.15.30[.0]
  *    ...
- *    1.6.55                  16    10655  16.so.16.55[.0]
+ *    1.6.56                  16    10656  16.so.16.56[.0]
  *
  *    Henceforth the source version will match the shared-library major and
  *    minor numbers; the shared-library major version number will be used for
@@ -303,7 +303,7 @@
  */
 
 /* Version information for png.h - this should match the version in png.c */
-#define PNG_LIBPNG_VER_STRING "1.6.55"
+#define PNG_LIBPNG_VER_STRING "1.6.56"
 #define PNG_HEADER_VERSION_STRING " libpng version " PNG_LIBPNG_VER_STRING "\n"
 
 /* The versions of shared library builds should stay in sync, going forward */
@@ -314,7 +314,7 @@
 /* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */
 #define PNG_LIBPNG_VER_MAJOR   1
 #define PNG_LIBPNG_VER_MINOR   6
-#define PNG_LIBPNG_VER_RELEASE 55
+#define PNG_LIBPNG_VER_RELEASE 56
 
 /* This should be zero for a public release, or non-zero for a
  * development version.
@@ -345,7 +345,7 @@
  * From version 1.0.1 it is:
  * XXYYZZ, where XX=major, YY=minor, ZZ=release
  */
-#define PNG_LIBPNG_VER 10655 /* 1.6.55 */
+#define PNG_LIBPNG_VER 10656 /* 1.6.56 */
 
 /* Library configuration: these options cannot be changed after
  * the library has been built.
@@ -455,7 +455,7 @@ extern "C" {
 /* This triggers a compiler error in png.c, if png.c and png.h
  * do not agree upon the version number.
  */
-typedef char *png_libpng_version_1_6_55;
+typedef char *png_libpng_version_1_6_56;
 
 /* Basic control structions.  Read libpng-manual.txt or libpng.3 for more info.
  *
@@ -2370,7 +2370,7 @@ PNG_EXPORT(162, int, png_get_text,
 #endif
 
 /* Note while png_set_text() will accept a structure whose text,
- * language, and  translated keywords are NULL pointers, the structure
+ * language, and translated keywords are NULL pointers, the structure
  * returned by png_get_text will always contain regular
  * zero-terminated C strings.  They might be empty strings but
  * they will never be NULL pointers.
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngconf.h b/src/java.desktop/share/native/libsplashscreen/libpng/pngconf.h
index b957f8b5061..5772e6ebb1c 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngconf.h
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngconf.h
@@ -29,7 +29,7 @@
  * However, the following notice accompanied the original version of this
  * file and, per its terms, should not be removed:
  *
- * libpng version 1.6.55
+ * libpng version 1.6.56
  *
  * Copyright (c) 2018-2026 Cosmin Truta
  * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pnglibconf.h b/src/java.desktop/share/native/libsplashscreen/libpng/pnglibconf.h
index ae1ab462072..4a7e51d112d 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/pnglibconf.h
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/pnglibconf.h
@@ -31,7 +31,7 @@
  * However, the following notice accompanied the original version of this
  * file and, per its terms, should not be removed:
  */
-/* libpng version 1.6.55 */
+/* libpng version 1.6.56 */
 
 /* Copyright (c) 2018-2026 Cosmin Truta */
 /* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson */
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngpriv.h b/src/java.desktop/share/native/libsplashscreen/libpng/pngpriv.h
index ee91f58d4ba..086a2f76ee6 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngpriv.h
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngpriv.h
@@ -986,7 +986,7 @@
  *
  * At present these index values are not exported (not part of the public API)
  * so can be changed at will.  For convenience the names are in lexical sort
- * order but with the critical chunks at the start in the order of occurence in
+ * order but with the critical chunks at the start in the order of occurrence in
  * a PNG.
  *
  * PNG_INFO_ values do not exist for every one of these chunk handles; for
@@ -2115,7 +2115,7 @@ PNG_INTERNAL_FUNCTION(void, png_ascii_from_fixed,
  * not valid it will be the index of a character in the supposed number.
  *
  * The format of a number is defined in the PNG extensions specification
- * and this API is strictly conformant to that spec, not anyone elses!
+ * and this API is strictly conformant to that spec, not anyone else's!
  *
  * The format as a regular expression is:
  *
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngread.c b/src/java.desktop/share/native/libsplashscreen/libpng/pngread.c
index 79fd9ad6a82..70df18926f5 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngread.c
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngread.c
@@ -720,7 +720,7 @@ png_read_end(png_structrp png_ptr, png_inforp info_ptr)
       png_read_finish_IDAT(png_ptr);
 
 #ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED
-   /* Report invalid palette index; added at libng-1.5.10 */
+   /* Report invalid palette index; added at libpng-1.5.10 */
    if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
        png_ptr->num_palette_max >= png_ptr->num_palette)
       png_benign_error(png_ptr, "Read palette index exceeding num_palette");
@@ -808,21 +808,19 @@ png_read_destroy(png_structrp png_ptr)
    png_ptr->quantize_index = NULL;
 #endif
 
-   if ((png_ptr->free_me & PNG_FREE_PLTE) != 0)
-   {
-      png_zfree(png_ptr, png_ptr->palette);
-      png_ptr->palette = NULL;
-   }
-   png_ptr->free_me &= ~PNG_FREE_PLTE;
+   /* png_ptr->palette is always independently allocated (not aliased
+    * with info_ptr->palette), so free it unconditionally.
+    */
+   png_free(png_ptr, png_ptr->palette);
+   png_ptr->palette = NULL;
 
 #if defined(PNG_tRNS_SUPPORTED) || \
     defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
-   if ((png_ptr->free_me & PNG_FREE_TRNS) != 0)
-   {
-      png_free(png_ptr, png_ptr->trans_alpha);
-      png_ptr->trans_alpha = NULL;
-   }
-   png_ptr->free_me &= ~PNG_FREE_TRNS;
+   /* png_ptr->trans_alpha is always independently allocated (not aliased
+    * with info_ptr->trans_alpha), so free it unconditionally.
+    */
+   png_free(png_ptr, png_ptr->trans_alpha);
+   png_ptr->trans_alpha = NULL;
 #endif
 
    inflateEnd(&png_ptr->zstream);
@@ -1285,7 +1283,7 @@ png_image_is_not_sRGB(png_const_structrp png_ptr)
     * png_struct::chromaticities always exists since the simplified API
     * requires rgb-to-gray.  The mDCV, cICP and cHRM chunks may all set it to
     * a non-sRGB value, so it needs to be checked but **only** if one of
-    * those chunks occured in the file.
+    * those chunks occurred in the file.
     */
    /* Highest priority: check to be safe. */
    if (png_has_chunk(png_ptr, cICP) || png_has_chunk(png_ptr, mDCV))
@@ -2625,7 +2623,7 @@ png_image_read_colormap(png_voidp argument)
                   {
                      r = back_r;
                      g = back_g;
-                     b = back_g;
+                     b = back_b;
                   }
 
                   /* Compare the newly-created color-map entry with the one the
@@ -2903,9 +2901,9 @@ png_image_read_and_map(png_voidp argument)
          {
             png_bytep inrow = png_voidcast(png_bytep, display->local_row);
             png_bytep outrow = first_row + y * row_step;
-            png_const_bytep end_row = outrow + width;
+            png_const_bytep row_end = outrow + width;
 
-            /* Read read the libpng data into the temporary buffer. */
+            /* Read the libpng data into the temporary buffer. */
             png_read_row(png_ptr, inrow, NULL);
 
             /* Now process the row according to the processing option, note
@@ -2916,7 +2914,7 @@ png_image_read_and_map(png_voidp argument)
             switch (proc)
             {
                case PNG_CMAP_GA:
-                  for (; outrow < end_row; outrow += stepx)
+                  for (; outrow < row_end; outrow += stepx)
                   {
                      /* The data is always in the PNG order */
                      unsigned int gray = *inrow++;
@@ -2945,7 +2943,7 @@ png_image_read_and_map(png_voidp argument)
                   break;
 
                case PNG_CMAP_TRANS:
-                  for (; outrow < end_row; outrow += stepx)
+                  for (; outrow < row_end; outrow += stepx)
                   {
                      png_byte gray = *inrow++;
                      png_byte alpha = *inrow++;
@@ -2962,7 +2960,7 @@ png_image_read_and_map(png_voidp argument)
                   break;
 
                case PNG_CMAP_RGB:
-                  for (; outrow < end_row; outrow += stepx)
+                  for (; outrow < row_end; outrow += stepx)
                   {
                      *outrow = PNG_RGB_INDEX(inrow[0], inrow[1], inrow[2]);
                      inrow += 3;
@@ -2970,7 +2968,7 @@ png_image_read_and_map(png_voidp argument)
                   break;
 
                case PNG_CMAP_RGB_ALPHA:
-                  for (; outrow < end_row; outrow += stepx)
+                  for (; outrow < row_end; outrow += stepx)
                   {
                      unsigned int alpha = inrow[3];
 
@@ -3007,10 +3005,10 @@ png_image_read_and_map(png_voidp argument)
                          */
                         if (inrow[0] & 0x80) back_i += 9; /* red */
                         if (inrow[0] & 0x40) back_i += 9;
-                        if (inrow[0] & 0x80) back_i += 3; /* green */
-                        if (inrow[0] & 0x40) back_i += 3;
-                        if (inrow[0] & 0x80) back_i += 1; /* blue */
-                        if (inrow[0] & 0x40) back_i += 1;
+                        if (inrow[1] & 0x80) back_i += 3; /* green */
+                        if (inrow[1] & 0x40) back_i += 3;
+                        if (inrow[2] & 0x80) back_i += 1; /* blue */
+                        if (inrow[2] & 0x40) back_i += 1;
 
                         *outrow = (png_byte)back_i;
                      }
@@ -3277,18 +3275,18 @@ png_image_read_composite(png_voidp argument)
          {
             png_bytep inrow = png_voidcast(png_bytep, display->local_row);
             png_bytep outrow;
-            png_const_bytep end_row;
+            png_const_bytep row_end;
 
             /* Read the row, which is packed: */
             png_read_row(png_ptr, inrow, NULL);
 
             outrow = png_voidcast(png_bytep, display->first_row);
             outrow += y * row_step;
-            end_row = outrow + width * channels;
+            row_end = outrow + width * channels;
 
             /* Now do the composition on each pixel in this row. */
             outrow += startx;
-            for (; outrow < end_row; outrow += stepx)
+            for (; outrow < row_end; outrow += stepx)
             {
                png_byte alpha = inrow[channels];
 
@@ -3461,14 +3459,14 @@ png_image_read_background(png_voidp argument)
                      png_bytep inrow = png_voidcast(png_bytep,
                          display->local_row);
                      png_bytep outrow = first_row + y * row_step;
-                     png_const_bytep end_row = outrow + width;
+                     png_const_bytep row_end = outrow + width;
 
                      /* Read the row, which is packed: */
                      png_read_row(png_ptr, inrow, NULL);
 
                      /* Now do the composition on each pixel in this row. */
                      outrow += startx;
-                     for (; outrow < end_row; outrow += stepx)
+                     for (; outrow < row_end; outrow += stepx)
                      {
                         png_byte alpha = inrow[1];
 
@@ -3506,14 +3504,14 @@ png_image_read_background(png_voidp argument)
                      png_bytep inrow = png_voidcast(png_bytep,
                          display->local_row);
                      png_bytep outrow = first_row + y * row_step;
-                     png_const_bytep end_row = outrow + width;
+                     png_const_bytep row_end = outrow + width;
 
                      /* Read the row, which is packed: */
                      png_read_row(png_ptr, inrow, NULL);
 
                      /* Now do the composition on each pixel in this row. */
                      outrow += startx;
-                     for (; outrow < end_row; outrow += stepx)
+                     for (; outrow < row_end; outrow += stepx)
                      {
                         png_byte alpha = inrow[1];
 
@@ -3596,7 +3594,7 @@ png_image_read_background(png_voidp argument)
                {
                   png_const_uint_16p inrow;
                   png_uint_16p outrow = first_row + y * row_step;
-                  png_uint_16p end_row = outrow + width * outchannels;
+                  png_uint_16p row_end = outrow + width * outchannels;
 
                   /* Read the row, which is packed: */
                   png_read_row(png_ptr, png_voidcast(png_bytep,
@@ -3606,7 +3604,7 @@ png_image_read_background(png_voidp argument)
                   /* Now do the pre-multiplication on each pixel in this row.
                    */
                   outrow += startx;
-                  for (; outrow < end_row; outrow += stepx)
+                  for (; outrow < row_end; outrow += stepx)
                   {
                      png_uint_32 component = inrow[0];
                      png_uint_16 alpha = inrow[1];
@@ -4142,7 +4140,7 @@ png_image_finish_read(png_imagep image, png_const_colorp background,
             row_stride = (png_int_32)/*SAFE*/png_row_stride;
 
          if (row_stride < 0)
-            check = (png_uint_32)(-row_stride);
+            check = -(png_uint_32)row_stride;
 
          else
             check = (png_uint_32)row_stride;
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngrtran.c b/src/java.desktop/share/native/libsplashscreen/libpng/pngrtran.c
index fcce80da1cb..f0972ba9bef 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngrtran.c
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngrtran.c
@@ -259,7 +259,7 @@ png_set_strip_alpha(png_structrp png_ptr)
  *
  * Terminology (assuming power law, "gamma", encodings):
  *    "screen" gamma: a power law imposed by the output device when digital
- *    samples are converted to visible light output.  The EOTF - volage to
+ *    samples are converted to visible light output.  The EOTF - voltage to
  *    luminance on output.
  *
  *    "file" gamma: a power law used to encode luminance levels from the input
@@ -524,6 +524,9 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette,
    if (png_rtran_ok(png_ptr, 0) == 0)
       return;
 
+   if (palette == NULL)
+      return;
+
    png_ptr->transformations |= PNG_QUANTIZE;
 
    if (full_quantize == 0)
@@ -840,7 +843,13 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette,
    }
    if (png_ptr->palette == NULL)
    {
-      png_ptr->palette = palette;
+      /* Allocate an owned copy rather than aliasing the caller's pointer,
+       * so that png_read_destroy can free png_ptr->palette unconditionally.
+       */
+      png_ptr->palette = png_voidcast(png_colorp, png_calloc(png_ptr,
+          PNG_MAX_PALETTE_LENGTH * (sizeof (png_color))));
+      memcpy(png_ptr->palette, palette, (unsigned int)num_palette *
+          (sizeof (png_color)));
    }
    png_ptr->num_palette = (png_uint_16)num_palette;
 
@@ -1393,7 +1402,7 @@ png_resolve_file_gamma(png_const_structrp png_ptr)
    if (file_gamma != 0)
       return file_gamma;
 
-   /* If png_reciprocal oveflows it returns 0 which indicates to the caller that
+   /* If png_reciprocal overflows, it returns 0, indicating to the caller that
     * there is no usable file gamma.  (The checks added to png_set_gamma and
     * png_set_alpha_mode should prevent a screen_gamma which would overflow.)
     */
@@ -2090,6 +2099,21 @@ png_read_transform_info(png_structrp png_ptr, png_inforp info_ptr)
 {
    png_debug(1, "in png_read_transform_info");
 
+   if (png_ptr->transformations != 0)
+   {
+      if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
+          info_ptr->palette != NULL && png_ptr->palette != NULL)
+      {
+         /* Sync info_ptr->palette with png_ptr->palette.
+          * The function png_init_read_transformations may have modified
+          * png_ptr->palette in place (e.g. for gamma correction or for
+          * background compositing).
+          */
+         memcpy(info_ptr->palette, png_ptr->palette,
+             PNG_MAX_PALETTE_LENGTH * (sizeof (png_color)));
+      }
+   }
+
 #ifdef PNG_READ_EXPAND_SUPPORTED
    if ((png_ptr->transformations & PNG_EXPAND) != 0)
    {
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngrutil.c b/src/java.desktop/share/native/libsplashscreen/libpng/pngrutil.c
index 01bb0c8bedc..4712dfd418a 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngrutil.c
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngrutil.c
@@ -465,7 +465,7 @@ png_inflate_claim(png_structrp png_ptr, png_uint_32 owner)
     * be gained by using this when it is known *if* the zlib stream itself does
     * not record the number; however, this is an illusion: the original writer
     * of the PNG may have selected a lower window size, and we really must
-    * follow that because, for systems with with limited capabilities, we
+    * follow that because, for systems with limited capabilities, we
     * would otherwise reject the application's attempts to use a smaller window
     * size (zlib doesn't have an interface to say "this or lower"!).
     *
@@ -1035,7 +1035,7 @@ png_handle_PLTE(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
     * in the case of an 8-bit display with a decoder which controls the palette.
     *
     * The alternative here is to ignore the error and store the palette anyway;
-    * destroying the tRNS will definately cause problems.
+    * destroying the tRNS will definitely cause problems.
     *
     * NOTE: the case of PNG_COLOR_TYPE_PALETTE need not be considered because
     * the png_handle_ routines for the three 'after PLTE' chunks tRNS, bKGD and
@@ -1082,19 +1082,6 @@ png_handle_PLTE(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
       /* A valid PLTE chunk has been read */
       png_ptr->mode |= PNG_HAVE_PLTE;
 
-      /* TODO: png_set_PLTE has the side effect of setting png_ptr->palette to
-       * its own copy of the palette.  This has the side effect that when
-       * png_start_row is called (this happens after any call to
-       * png_read_update_info) the info_ptr palette gets changed.  This is
-       * extremely unexpected and confusing.
-       *
-       * REVIEW: there have been consistent bugs in the past about gamma and
-       * similar transforms to colour mapped images being useless because the
-       * modified palette cannot be accessed because of the above.
-       *
-       * CONSIDER: Fix this by not sharing the palette in this way.  But does
-       * this completely fix the problem?
-       */
       png_set_PLTE(png_ptr, info_ptr, palette, num);
       return handled_ok;
    }
@@ -1296,7 +1283,7 @@ png_handle_cHRM(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
 
    /* png_set_cHRM may complain about some of the values but this doesn't matter
     * because it was a cHRM and it did have vaguely (if, perhaps, ridiculous)
-    * values.  Ridiculousity will be checked if the values are used later.
+    * values.  Ridiculosity will be checked if the values are used later.
     */
    png_set_cHRM_fixed(png_ptr, info_ptr, xy.whitex, xy.whitey, xy.redx, xy.redy,
          xy.greenx, xy.greeny, xy.bluex, xy.bluey);
@@ -1593,7 +1580,8 @@ static png_handle_result_code /* PRIVATE */
 png_handle_sPLT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
 /* Note: this does not properly handle chunks that are > 64K under DOS */
 {
-   png_bytep entry_start, buffer;
+   png_bytep buffer;
+   png_bytep entry_start;
    png_sPLT_t new_palette;
    png_sPLT_entryp pp;
    png_uint_32 data_length;
@@ -1800,10 +1788,6 @@ png_handle_tRNS(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
       return handled_error;
    }
 
-   /* TODO: this is a horrible side effect in the palette case because the
-    * png_struct ends up with a pointer to the tRNS buffer owned by the
-    * png_info.  Fix this.
-    */
    png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans,
        &(png_ptr->trans_color));
    return handled_ok;
@@ -2062,7 +2046,7 @@ png_handle_eXIf(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
       return handled_error;
 
    /* PNGv3: the code used to check the byte order mark at the start for MM or
-    * II, however PNGv3 states that the the first 4 bytes should be checked.
+    * II, however PNGv3 states that the first 4 bytes should be checked.
     * The caller ensures that there are four bytes available.
     */
    {
@@ -2184,9 +2168,13 @@ png_handle_oFFs(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
 static png_handle_result_code /* PRIVATE */
 png_handle_pCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
 {
+   png_bytep buffer;
+   png_bytep buf;
+   png_bytep endptr;
    png_int_32 X0, X1;
-   png_byte type, nparams;
-   png_bytep buffer, buf, units, endptr;
+   png_byte type;
+   png_byte nparams;
+   png_byte *units;
    png_charpp params;
    int i;
 
@@ -3040,7 +3028,7 @@ static const struct
    png_uint_32 max_length :12; /* Length min, max in bytes */
    png_uint_32 min_length :8;
       /* Length errors on critical chunks have special handling to preserve the
-       * existing behaviour in libpng 1.6.  Anciallary chunks are checked below
+       * existing behaviour in libpng 1.6.  Ancillary chunks are checked below
        * and produce a 'benign' error.
        */
    png_uint_32 pos_before :4; /* PNG_HAVE_ values chunk must precede */
@@ -3048,7 +3036,7 @@ static const struct
       /* NOTE: PLTE, tRNS and bKGD require special handling which depends on
        * the colour type of the base image.
        */
-   png_uint_32 multiple   :1; /* Multiple occurences permitted */
+   png_uint_32 multiple   :1; /* Multiple occurrences permitted */
       /* This is enabled for PLTE because PLTE may, in practice, be optional */
 }
 read_chunks[PNG_INDEX_unknown] =
@@ -3082,7 +3070,7 @@ read_chunks[PNG_INDEX_unknown] =
 #  define CDIHDR      13U,   13U,  hIHDR,     0,        0
 #  define CDPLTE  NoCheck,    0U,      0, hIHDR,        1
       /* PLTE errors are only critical for colour-map images, consequently the
-       * hander does all the checks.
+       * handler does all the checks.
        */
 #  define CDIDAT  NoCheck,    0U,  aIDAT, hIHDR,        1
 #  define CDIEND  NoCheck,    0U,      0, aIDAT,        0
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngset.c b/src/java.desktop/share/native/libsplashscreen/libpng/pngset.c
index 0b2844f1864..05d18cd06b7 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngset.c
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngset.c
@@ -29,7 +29,7 @@
  * However, the following notice accompanied the original version of this
  * file and, per its terms, should not be removed:
  *
- * Copyright (c) 2018-2025 Cosmin Truta
+ * Copyright (c) 2018-2026 Cosmin Truta
  * Copyright (c) 1998-2018 Glenn Randers-Pehrson
  * Copyright (c) 1996-1997 Andreas Dilger
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -362,7 +362,8 @@ png_set_eXIf_1(png_const_structrp png_ptr, png_inforp info_ptr,
    png_debug1(1, "in %s storage function", "eXIf");
 
    if (png_ptr == NULL || info_ptr == NULL ||
-       (png_ptr->mode & PNG_WROTE_eXIf) != 0)
+       (png_ptr->mode & PNG_WROTE_eXIf) != 0 ||
+       exif == NULL)
       return;
 
    new_exif = png_voidcast(png_bytep, png_malloc_warn(png_ptr, num_exif));
@@ -417,7 +418,7 @@ png_set_hIST(png_const_structrp png_ptr, png_inforp info_ptr,
 
    png_debug1(1, "in %s storage function", "hIST");
 
-   if (png_ptr == NULL || info_ptr == NULL)
+   if (png_ptr == NULL || info_ptr == NULL || hist == NULL)
       return;
 
    if (info_ptr->num_palette == 0 || info_ptr->num_palette
@@ -804,28 +805,38 @@ png_set_PLTE(png_structrp png_ptr, png_inforp info_ptr,
       png_error(png_ptr, "Invalid palette");
    }
 
-   /* It may not actually be necessary to set png_ptr->palette here;
-    * we do it for backward compatibility with the way the png_handle_tRNS
-    * function used to do the allocation.
-    *
-    * 1.6.0: the above statement appears to be incorrect; something has to set
-    * the palette inside png_struct on read.
-    */
    png_free_data(png_ptr, info_ptr, PNG_FREE_PLTE, 0);
 
    /* Changed in libpng-1.2.1 to allocate PNG_MAX_PALETTE_LENGTH instead
     * of num_palette entries, in case of an invalid PNG file or incorrect
     * call to png_set_PLTE() with too-large sample values.
+    *
+    * Allocate independent buffers for info_ptr and png_ptr so that the
+    * lifetime of png_ptr->palette is decoupled from the lifetime of
+    * info_ptr->palette.  Previously, these two pointers were aliased,
+    * which caused a use-after-free vulnerability if png_free_data freed
+    * info_ptr->palette while png_ptr->palette was still in use by the
+    * row transform functions (e.g. png_do_expand_palette).
+    *
+    * Both buffers are allocated with png_calloc to zero-fill, because
+    * the ARM NEON palette riffle reads all 256 entries unconditionally,
+    * regardless of num_palette.
     */
+   png_free(png_ptr, png_ptr->palette);
    png_ptr->palette = png_voidcast(png_colorp, png_calloc(png_ptr,
        PNG_MAX_PALETTE_LENGTH * (sizeof (png_color))));
+   info_ptr->palette = png_voidcast(png_colorp, png_calloc(png_ptr,
+       PNG_MAX_PALETTE_LENGTH * (sizeof (png_color))));
+   png_ptr->num_palette = info_ptr->num_palette = (png_uint_16)num_palette;
 
    if (num_palette > 0)
+   {
+      memcpy(info_ptr->palette, palette, (unsigned int)num_palette *
+          (sizeof (png_color)));
       memcpy(png_ptr->palette, palette, (unsigned int)num_palette *
           (sizeof (png_color)));
+   }
 
-   info_ptr->palette = png_ptr->palette;
-   info_ptr->num_palette = png_ptr->num_palette = (png_uint_16)num_palette;
    info_ptr->free_me |= PNG_FREE_PLTE;
    info_ptr->valid |= PNG_INFO_PLTE;
 }
@@ -1183,28 +1194,40 @@ png_set_tRNS(png_structrp png_ptr, png_inforp info_ptr,
 
    if (trans_alpha != NULL)
    {
-       /* It may not actually be necessary to set png_ptr->trans_alpha here;
-        * we do it for backward compatibility with the way the png_handle_tRNS
-        * function used to do the allocation.
-        *
-        * 1.6.0: The above statement is incorrect; png_handle_tRNS effectively
-        * relies on png_set_tRNS storing the information in png_struct
-        * (otherwise it won't be there for the code in pngrtran.c).
-        */
-
        png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0);
 
        if (num_trans > 0 && num_trans <= PNG_MAX_PALETTE_LENGTH)
        {
-         /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */
+          /* Allocate info_ptr's copy of the transparency data.
+           * Initialize all entries to fully opaque (0xff), then overwrite
+           * the first num_trans entries with the actual values.
+           */
           info_ptr->trans_alpha = png_voidcast(png_bytep,
               png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH));
+          memset(info_ptr->trans_alpha, 0xff, PNG_MAX_PALETTE_LENGTH);
           memcpy(info_ptr->trans_alpha, trans_alpha, (size_t)num_trans);
-
           info_ptr->free_me |= PNG_FREE_TRNS;
           info_ptr->valid |= PNG_INFO_tRNS;
+
+          /* Allocate an independent copy for png_struct, so that the
+           * lifetime of png_ptr->trans_alpha is decoupled from the
+           * lifetime of info_ptr->trans_alpha.  Previously these two
+           * pointers were aliased, which caused a use-after-free if
+           * png_free_data freed info_ptr->trans_alpha while
+           * png_ptr->trans_alpha was still in use by the row transform
+           * functions (e.g. png_do_expand_palette).
+           */
+          png_free(png_ptr, png_ptr->trans_alpha);
+          png_ptr->trans_alpha = png_voidcast(png_bytep,
+              png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH));
+          memset(png_ptr->trans_alpha, 0xff, PNG_MAX_PALETTE_LENGTH);
+          memcpy(png_ptr->trans_alpha, trans_alpha, (size_t)num_trans);
+       }
+       else
+       {
+          png_free(png_ptr, png_ptr->trans_alpha);
+          png_ptr->trans_alpha = NULL;
        }
-       png_ptr->trans_alpha = info_ptr->trans_alpha;
    }
 
    if (trans_color != NULL)
@@ -1902,7 +1925,7 @@ png_set_benign_errors(png_structrp png_ptr, int allowed)
 #endif /* BENIGN_ERRORS */
 
 #ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
-   /* Whether to report invalid palette index; added at libng-1.5.10.
+   /* Whether to report invalid palette index; added at libpng-1.5.10.
     * It is possible for an indexed (color-type==3) PNG file to contain
     * pixels with invalid (out-of-range) indexes if the PLTE chunk has
     * fewer entries than the image's bit-depth would allow. We recover
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngstruct.h b/src/java.desktop/share/native/libsplashscreen/libpng/pngstruct.h
index 8edb4bc393a..f02365e8d8e 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngstruct.h
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngstruct.h
@@ -29,7 +29,7 @@
  * However, the following notice accompanied the original version of this
  * file and, per its terms, should not be removed:
  *
- * Copyright (c) 2018-2025 Cosmin Truta
+ * Copyright (c) 2018-2026 Cosmin Truta
  * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
  * Copyright (c) 1996-1997 Andreas Dilger
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -135,7 +135,7 @@ typedef enum
  * TODO: C23: convert these macros to C23 inlines (which are static).
  */
 #define png_chunk_flag_from_index(i) (0x80000000U >> (31 - (i)))
-   /* The flag coresponding to the given png_index enum value.  This is defined
+   /* The flag corresponding to the given png_index enum value.  This is defined
     * for png_unknown as well (until it reaches the value 32) but this should
     * not be relied on.
     */
@@ -144,7 +144,7 @@ typedef enum
    (((png_ptr)->chunks & png_chunk_flag_from_index(i)) != 0)
    /* The chunk has been recorded in png_struct */
 
-#define png_file_add_chunk(pnt_ptr, i)\
+#define png_file_add_chunk(png_ptr, i)\
    ((void)((png_ptr)->chunks |= png_chunk_flag_from_index(i)))
    /* Record the chunk in the png_struct */
 
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngtrans.c b/src/java.desktop/share/native/libsplashscreen/libpng/pngtrans.c
index b9f6cb5d437..86ff2812e23 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngtrans.c
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngtrans.c
@@ -29,7 +29,7 @@
  * However, the following notice accompanied the original version of this
  * file and, per its terms, should not be removed:
  *
- * Copyright (c) 2018-2024 Cosmin Truta
+ * Copyright (c) 2018-2026 Cosmin Truta
  * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
  * Copyright (c) 1996-1997 Andreas Dilger
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -113,9 +113,38 @@ png_set_shift(png_structrp png_ptr, png_const_color_8p true_bits)
 {
    png_debug(1, "in png_set_shift");
 
-   if (png_ptr == NULL)
+   if (png_ptr == NULL || true_bits == NULL)
       return;
 
+   /* Check the shift values before passing them on to png_do_shift. */
+   {
+      png_byte bit_depth = png_ptr->bit_depth;
+      int invalid = 0;
+
+      if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
+      {
+         if (true_bits->red == 0 || true_bits->red > bit_depth ||
+             true_bits->green == 0 || true_bits->green > bit_depth ||
+             true_bits->blue == 0 || true_bits->blue > bit_depth)
+            invalid = 1;
+      }
+      else
+      {
+         if (true_bits->gray == 0 || true_bits->gray > bit_depth)
+            invalid = 1;
+      }
+
+      if ((png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0 &&
+          (true_bits->alpha == 0 || true_bits->alpha > bit_depth))
+         invalid = 1;
+
+      if (invalid)
+      {
+         png_app_error(png_ptr, "png_set_shift: invalid shift values");
+         return;
+      }
+   }
+
    png_ptr->transformations |= PNG_SHIFT;
    png_ptr->shift = *true_bits;
 }
@@ -486,10 +515,9 @@ png_do_packswap(png_row_infop row_info, png_bytep row)
 
    if (row_info->bit_depth < 8)
    {
+      png_const_bytep table;
       png_bytep rp;
-      png_const_bytep end, table;
-
-      end = row + row_info->rowbytes;
+      png_bytep row_end = row + row_info->rowbytes;
 
       if (row_info->bit_depth == 1)
          table = onebppswaptable;
@@ -503,7 +531,7 @@ png_do_packswap(png_row_infop row_info, png_bytep row)
       else
          return;
 
-      for (rp = row; rp < end; rp++)
+      for (rp = row; rp < row_end; rp++)
          *rp = table[*rp];
    }
 }

From ee0d6cd9aedc0d4c4232dccab310de188af4bebc Mon Sep 17 00:00:00 2001
From: Jatin Bhateja 
Date: Tue, 31 Mar 2026 05:52:16 +0000
Subject: [PATCH 070/116] 8378250: C2 VectorAPI : wrong result with MUL
 reduction at various AVX levels

Reviewed-by: epeter
---
 src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp |   9 +-
 .../vectorapi/TestMultiplyReductionByte.java  | 133 ++++++++++++++++++
 .../incubator/vector/ByteVector128Tests.java  |   4 +
 .../incubator/vector/ByteVector256Tests.java  |   4 +
 .../incubator/vector/ByteVector512Tests.java  |   4 +
 .../incubator/vector/ByteVector64Tests.java   |   4 +
 .../incubator/vector/ByteVectorMaxTests.java  |   4 +
 .../vector/DoubleVector128Tests.java          |   4 +
 .../vector/DoubleVector256Tests.java          |   4 +
 .../vector/DoubleVector512Tests.java          |   4 +
 .../incubator/vector/DoubleVector64Tests.java |   4 +
 .../vector/DoubleVectorMaxTests.java          |   4 +
 .../incubator/vector/FloatVector128Tests.java |   4 +
 .../incubator/vector/FloatVector256Tests.java |   4 +
 .../incubator/vector/FloatVector512Tests.java |   4 +
 .../incubator/vector/FloatVector64Tests.java  |   4 +
 .../incubator/vector/FloatVectorMaxTests.java |   4 +
 .../incubator/vector/IntVector128Tests.java   |   4 +
 .../incubator/vector/IntVector256Tests.java   |   4 +
 .../incubator/vector/IntVector512Tests.java   |   4 +
 .../incubator/vector/IntVector64Tests.java    |   4 +
 .../incubator/vector/IntVectorMaxTests.java   |   4 +
 .../incubator/vector/LongVector128Tests.java  |   4 +
 .../incubator/vector/LongVector256Tests.java  |   4 +
 .../incubator/vector/LongVector512Tests.java  |   4 +
 .../incubator/vector/LongVector64Tests.java   |   4 +
 .../incubator/vector/LongVectorMaxTests.java  |   4 +
 .../incubator/vector/ShortVector128Tests.java |   4 +
 .../incubator/vector/ShortVector256Tests.java |   4 +
 .../incubator/vector/ShortVector512Tests.java |   4 +
 .../incubator/vector/ShortVector64Tests.java  |   4 +
 .../incubator/vector/ShortVectorMaxTests.java |   4 +
 .../vector/templates/Unit-header.template     |   4 +
 33 files changed, 263 insertions(+), 3 deletions(-)
 create mode 100644 test/hotspot/jtreg/compiler/vectorapi/TestMultiplyReductionByte.java

diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp
index 23b9a77844d..f36c816dd5e 100644
--- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp
+++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp
@@ -2150,8 +2150,8 @@ void C2_MacroAssembler::mulreduce16B(int opcode, Register dst, Register src1, XM
   } else {
     pmovsxbw(vtmp2, src2);
     reduce8S(opcode, dst, src1, vtmp2, vtmp1, vtmp2);
-    pshufd(vtmp2, src2, 0x1);
-    pmovsxbw(vtmp2, src2);
+    pshufd(vtmp2, src2, 0xe);
+    pmovsxbw(vtmp2, vtmp2);
     reduce8S(opcode, dst, dst, vtmp2, vtmp1, vtmp2);
   }
 }
@@ -2160,7 +2160,7 @@ void C2_MacroAssembler::mulreduce32B(int opcode, Register dst, Register src1, XM
   if (UseAVX > 2 && VM_Version::supports_avx512bw()) {
     int vector_len = Assembler::AVX_512bit;
     vpmovsxbw(vtmp1, src2, vector_len);
-    reduce32S(opcode, dst, src1, vtmp1, vtmp1, vtmp2);
+    reduce32S(opcode, dst, src1, vtmp1, vtmp2, vtmp1);
   } else {
     assert(UseAVX >= 2,"Should not reach here.");
     mulreduce16B(opcode, dst, src1, src2, vtmp1, vtmp2);
@@ -2207,6 +2207,7 @@ void C2_MacroAssembler::reduce8S(int opcode, Register dst, Register src1, XMMReg
     }
     phaddw(vtmp1, src2);
   } else {
+    assert_different_registers(src2, vtmp1);
     pshufd(vtmp1, src2, 0xE);
     reduce_operation_128(T_SHORT, opcode, vtmp1, src2);
   }
@@ -2219,6 +2220,7 @@ void C2_MacroAssembler::reduce16S(int opcode, Register dst, Register src1, XMMRe
     vphaddw(vtmp2, src2, src2, vector_len);
     vpermq(vtmp2, vtmp2, 0xD8, vector_len);
   } else {
+    assert_different_registers(src2, vtmp2);
     vextracti128_high(vtmp2, src2);
     reduce_operation_128(T_SHORT, opcode, vtmp2, src2);
   }
@@ -2226,6 +2228,7 @@ void C2_MacroAssembler::reduce16S(int opcode, Register dst, Register src1, XMMRe
 }
 
 void C2_MacroAssembler::reduce32S(int opcode, Register dst, Register src1, XMMRegister src2, XMMRegister vtmp1, XMMRegister vtmp2) {
+  assert_different_registers(src2, vtmp1);
   int vector_len = Assembler::AVX_256bit;
   vextracti64x4_high(vtmp1, src2);
   reduce_operation_256(T_SHORT, opcode, vtmp1, vtmp1, src2);
diff --git a/test/hotspot/jtreg/compiler/vectorapi/TestMultiplyReductionByte.java b/test/hotspot/jtreg/compiler/vectorapi/TestMultiplyReductionByte.java
new file mode 100644
index 00000000000..13eafd8dc26
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/vectorapi/TestMultiplyReductionByte.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 compiler.lib.ir_framework.*;
+
+import java.util.Arrays;
+
+import jdk.incubator.vector.ByteVector;
+import jdk.incubator.vector.VectorOperators;
+
+import jdk.test.lib.Asserts;
+import jdk.test.lib.Utils;
+
+/**
+ * @test
+ * @bug 8378250
+ * @summary Verify correctness of byte vector MUL reduction across all species.
+ *          A register aliasing bug in mulreduce32B caused the upper half of
+ *          sign-extended data to overwrite the source, producing wrong results
+ *          when most lanes are 1 and a single lane differs.
+ * @library /test/lib /
+ * @modules jdk.incubator.vector
+ * @run driver ${test.main.class}
+ */
+public class TestMultiplyReductionByte {
+
+    static byte[] input = new byte[64];
+
+    static int pos = Utils.getRandomInstance().nextInt(input.length);
+
+    static {
+        Arrays.fill(input, (byte) 1);
+        input[pos] = -3;
+    }
+
+    @Test
+    @IR(counts = {IRNode.MUL_REDUCTION_VI, ">=1"},
+        applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"},
+        applyIf = {"MaxVectorSize", ">=8"})
+    static byte testMulReduce64() {
+        return ByteVector.fromArray(ByteVector.SPECIES_64, input, 0)
+                         .reduceLanes(VectorOperators.MUL);
+    }
+
+    @Run(test = "testMulReduce64")
+    static void runMulReduce64() {
+        input[pos] = 1;
+        pos = (pos + 1) % ByteVector.SPECIES_64.length();
+        input[pos] = -3;
+        byte result = testMulReduce64();
+        Asserts.assertEquals((byte) -3, result, "MUL reduction (64-bit), pos=" + pos);
+    }
+
+    @Test
+    @IR(counts = {IRNode.MUL_REDUCTION_VI, ">=1"},
+        applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"},
+        applyIf = {"MaxVectorSize", ">=16"})
+    static byte testMulReduce128() {
+        return ByteVector.fromArray(ByteVector.SPECIES_128, input, 0)
+                         .reduceLanes(VectorOperators.MUL);
+    }
+
+    @Run(test = "testMulReduce128")
+    static void runMulReduce128() {
+        input[pos] = 1;
+        pos = (pos + 1) % ByteVector.SPECIES_128.length();
+        input[pos] = -3;
+        byte result = testMulReduce128();
+        Asserts.assertEquals((byte) -3, result, "MUL reduction (128-bit), pos=" + pos);
+    }
+
+    @Test
+    @IR(counts = {IRNode.MUL_REDUCTION_VI, ">=1"},
+        applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true"},
+        applyIf = {"MaxVectorSize", ">=32"})
+    static byte testMulReduce256() {
+        return ByteVector.fromArray(ByteVector.SPECIES_256, input, 0)
+                         .reduceLanes(VectorOperators.MUL);
+    }
+
+    @Run(test = "testMulReduce256")
+    static void runMulReduce256() {
+        input[pos] = 1;
+        pos = (pos + 1) % ByteVector.SPECIES_256.length();
+        input[pos] = -3;
+        byte result = testMulReduce256();
+        Asserts.assertEquals((byte) -3, result, "MUL reduction (256-bit), pos=" + pos);
+    }
+
+    @Test
+    @IR(counts = {IRNode.MUL_REDUCTION_VI, ">=1"},
+        applyIfCPUFeatureOr = {"avx512f", "true", "asimd", "true"},
+        applyIf = {"MaxVectorSize", ">=64"})
+    static byte testMulReduce512() {
+        return ByteVector.fromArray(ByteVector.SPECIES_512, input, 0)
+                         .reduceLanes(VectorOperators.MUL);
+    }
+
+    @Run(test = "testMulReduce512")
+    static void runMulReduce512() {
+        input[pos] = 1;
+        pos = (pos + 1) % ByteVector.SPECIES_512.length();
+        input[pos] = -3;
+        byte result = testMulReduce512();
+        Asserts.assertEquals((byte) -3, result, "MUL reduction (512-bit), pos=" + pos);
+    }
+
+    public static void main(String[] args) {
+        TestFramework.runWithFlags("--add-modules=jdk.incubator.vector");
+    }
+}
diff --git a/test/jdk/jdk/incubator/vector/ByteVector128Tests.java b/test/jdk/jdk/incubator/vector/ByteVector128Tests.java
index ca6fa537ac4..b605182e496 100644
--- a/test/jdk/jdk/incubator/vector/ByteVector128Tests.java
+++ b/test/jdk/jdk/incubator/vector/ByteVector128Tests.java
@@ -1114,6 +1114,10 @@ static byte bits(byte e) {
                 return fill(s * BUFFER_REPS,
                             i -> (((byte)(i + 1) == 0) ? 1 : (byte)(i + 1)));
             }),
+            withToString("byte[smallOddValue(i)]", (int s) -> {
+                return fill(s * BUFFER_REPS,
+                            i -> (byte)(i % 7 == 0 ? -3 : (i % 3 == 0 ? -1 : 1)));
+            }),
             withToString("byte[cornerCaseValue(i)]", (int s) -> {
                 return fill(s * BUFFER_REPS,
                             i -> cornerCaseValue(i));
diff --git a/test/jdk/jdk/incubator/vector/ByteVector256Tests.java b/test/jdk/jdk/incubator/vector/ByteVector256Tests.java
index 5c32d4a7f74..bc05a0bd6ca 100644
--- a/test/jdk/jdk/incubator/vector/ByteVector256Tests.java
+++ b/test/jdk/jdk/incubator/vector/ByteVector256Tests.java
@@ -1114,6 +1114,10 @@ static byte bits(byte e) {
                 return fill(s * BUFFER_REPS,
                             i -> (((byte)(i + 1) == 0) ? 1 : (byte)(i + 1)));
             }),
+            withToString("byte[smallOddValue(i)]", (int s) -> {
+                return fill(s * BUFFER_REPS,
+                            i -> (byte)(i % 7 == 0 ? -3 : (i % 3 == 0 ? -1 : 1)));
+            }),
             withToString("byte[cornerCaseValue(i)]", (int s) -> {
                 return fill(s * BUFFER_REPS,
                             i -> cornerCaseValue(i));
diff --git a/test/jdk/jdk/incubator/vector/ByteVector512Tests.java b/test/jdk/jdk/incubator/vector/ByteVector512Tests.java
index 094f3bbebdc..45038c53824 100644
--- a/test/jdk/jdk/incubator/vector/ByteVector512Tests.java
+++ b/test/jdk/jdk/incubator/vector/ByteVector512Tests.java
@@ -1114,6 +1114,10 @@ static byte bits(byte e) {
                 return fill(s * BUFFER_REPS,
                             i -> (((byte)(i + 1) == 0) ? 1 : (byte)(i + 1)));
             }),
+            withToString("byte[smallOddValue(i)]", (int s) -> {
+                return fill(s * BUFFER_REPS,
+                            i -> (byte)(i % 7 == 0 ? -3 : (i % 3 == 0 ? -1 : 1)));
+            }),
             withToString("byte[cornerCaseValue(i)]", (int s) -> {
                 return fill(s * BUFFER_REPS,
                             i -> cornerCaseValue(i));
diff --git a/test/jdk/jdk/incubator/vector/ByteVector64Tests.java b/test/jdk/jdk/incubator/vector/ByteVector64Tests.java
index e8ff81678cd..b350d0a8ee0 100644
--- a/test/jdk/jdk/incubator/vector/ByteVector64Tests.java
+++ b/test/jdk/jdk/incubator/vector/ByteVector64Tests.java
@@ -1114,6 +1114,10 @@ static byte bits(byte e) {
                 return fill(s * BUFFER_REPS,
                             i -> (((byte)(i + 1) == 0) ? 1 : (byte)(i + 1)));
             }),
+            withToString("byte[smallOddValue(i)]", (int s) -> {
+                return fill(s * BUFFER_REPS,
+                            i -> (byte)(i % 7 == 0 ? -3 : (i % 3 == 0 ? -1 : 1)));
+            }),
             withToString("byte[cornerCaseValue(i)]", (int s) -> {
                 return fill(s * BUFFER_REPS,
                             i -> cornerCaseValue(i));
diff --git a/test/jdk/jdk/incubator/vector/ByteVectorMaxTests.java b/test/jdk/jdk/incubator/vector/ByteVectorMaxTests.java
index c53710c3fdd..ba2307f15b1 100644
--- a/test/jdk/jdk/incubator/vector/ByteVectorMaxTests.java
+++ b/test/jdk/jdk/incubator/vector/ByteVectorMaxTests.java
@@ -1120,6 +1120,10 @@ static byte bits(byte e) {
                 return fill(s * BUFFER_REPS,
                             i -> (((byte)(i + 1) == 0) ? 1 : (byte)(i + 1)));
             }),
+            withToString("byte[smallOddValue(i)]", (int s) -> {
+                return fill(s * BUFFER_REPS,
+                            i -> (byte)(i % 7 == 0 ? -3 : (i % 3 == 0 ? -1 : 1)));
+            }),
             withToString("byte[cornerCaseValue(i)]", (int s) -> {
                 return fill(s * BUFFER_REPS,
                             i -> cornerCaseValue(i));
diff --git a/test/jdk/jdk/incubator/vector/DoubleVector128Tests.java b/test/jdk/jdk/incubator/vector/DoubleVector128Tests.java
index 1457e5a51ca..7bec91b698b 100644
--- a/test/jdk/jdk/incubator/vector/DoubleVector128Tests.java
+++ b/test/jdk/jdk/incubator/vector/DoubleVector128Tests.java
@@ -1239,6 +1239,10 @@ static long bits(double e) {
                 return fill(s * BUFFER_REPS,
                             i -> (((double)(i + 1) == 0) ? 1 : (double)(i + 1)));
             }),
+            withToString("double[smallOddValue(i)]", (int s) -> {
+                return fill(s * BUFFER_REPS,
+                            i -> (double)(i % 7 == 0 ? -3 : (i % 3 == 0 ? -1 : 1)));
+            }),
             withToString("double[0.01 + (i / (i + 1))]", (int s) -> {
                 return fill(s * BUFFER_REPS,
                             i -> (double)0.01 + ((double)i / (i + 1)));
diff --git a/test/jdk/jdk/incubator/vector/DoubleVector256Tests.java b/test/jdk/jdk/incubator/vector/DoubleVector256Tests.java
index e417abe52e6..3da554e67e5 100644
--- a/test/jdk/jdk/incubator/vector/DoubleVector256Tests.java
+++ b/test/jdk/jdk/incubator/vector/DoubleVector256Tests.java
@@ -1239,6 +1239,10 @@ static long bits(double e) {
                 return fill(s * BUFFER_REPS,
                             i -> (((double)(i + 1) == 0) ? 1 : (double)(i + 1)));
             }),
+            withToString("double[smallOddValue(i)]", (int s) -> {
+                return fill(s * BUFFER_REPS,
+                            i -> (double)(i % 7 == 0 ? -3 : (i % 3 == 0 ? -1 : 1)));
+            }),
             withToString("double[0.01 + (i / (i + 1))]", (int s) -> {
                 return fill(s * BUFFER_REPS,
                             i -> (double)0.01 + ((double)i / (i + 1)));
diff --git a/test/jdk/jdk/incubator/vector/DoubleVector512Tests.java b/test/jdk/jdk/incubator/vector/DoubleVector512Tests.java
index d23b2bf1511..6c060714da8 100644
--- a/test/jdk/jdk/incubator/vector/DoubleVector512Tests.java
+++ b/test/jdk/jdk/incubator/vector/DoubleVector512Tests.java
@@ -1239,6 +1239,10 @@ static long bits(double e) {
                 return fill(s * BUFFER_REPS,
                             i -> (((double)(i + 1) == 0) ? 1 : (double)(i + 1)));
             }),
+            withToString("double[smallOddValue(i)]", (int s) -> {
+                return fill(s * BUFFER_REPS,
+                            i -> (double)(i % 7 == 0 ? -3 : (i % 3 == 0 ? -1 : 1)));
+            }),
             withToString("double[0.01 + (i / (i + 1))]", (int s) -> {
                 return fill(s * BUFFER_REPS,
                             i -> (double)0.01 + ((double)i / (i + 1)));
diff --git a/test/jdk/jdk/incubator/vector/DoubleVector64Tests.java b/test/jdk/jdk/incubator/vector/DoubleVector64Tests.java
index d2aff0b7ea5..9e34cbc3a31 100644
--- a/test/jdk/jdk/incubator/vector/DoubleVector64Tests.java
+++ b/test/jdk/jdk/incubator/vector/DoubleVector64Tests.java
@@ -1239,6 +1239,10 @@ static long bits(double e) {
                 return fill(s * BUFFER_REPS,
                             i -> (((double)(i + 1) == 0) ? 1 : (double)(i + 1)));
             }),
+            withToString("double[smallOddValue(i)]", (int s) -> {
+                return fill(s * BUFFER_REPS,
+                            i -> (double)(i % 7 == 0 ? -3 : (i % 3 == 0 ? -1 : 1)));
+            }),
             withToString("double[0.01 + (i / (i + 1))]", (int s) -> {
                 return fill(s * BUFFER_REPS,
                             i -> (double)0.01 + ((double)i / (i + 1)));
diff --git a/test/jdk/jdk/incubator/vector/DoubleVectorMaxTests.java b/test/jdk/jdk/incubator/vector/DoubleVectorMaxTests.java
index 2684ae2d0c6..74be9b42a8b 100644
--- a/test/jdk/jdk/incubator/vector/DoubleVectorMaxTests.java
+++ b/test/jdk/jdk/incubator/vector/DoubleVectorMaxTests.java
@@ -1245,6 +1245,10 @@ static long bits(double e) {
                 return fill(s * BUFFER_REPS,
                             i -> (((double)(i + 1) == 0) ? 1 : (double)(i + 1)));
             }),
+            withToString("double[smallOddValue(i)]", (int s) -> {
+                return fill(s * BUFFER_REPS,
+                            i -> (double)(i % 7 == 0 ? -3 : (i % 3 == 0 ? -1 : 1)));
+            }),
             withToString("double[0.01 + (i / (i + 1))]", (int s) -> {
                 return fill(s * BUFFER_REPS,
                             i -> (double)0.01 + ((double)i / (i + 1)));
diff --git a/test/jdk/jdk/incubator/vector/FloatVector128Tests.java b/test/jdk/jdk/incubator/vector/FloatVector128Tests.java
index 151ea17a886..eb4b686d41f 100644
--- a/test/jdk/jdk/incubator/vector/FloatVector128Tests.java
+++ b/test/jdk/jdk/incubator/vector/FloatVector128Tests.java
@@ -1256,6 +1256,10 @@ static int bits(float e) {
                 return fill(s * BUFFER_REPS,
                             i -> (((float)(i + 1) == 0) ? 1 : (float)(i + 1)));
             }),
+            withToString("float[smallOddValue(i)]", (int s) -> {
+                return fill(s * BUFFER_REPS,
+                            i -> (float)(i % 7 == 0 ? -3 : (i % 3 == 0 ? -1 : 1)));
+            }),
             withToString("float[0.01 + (i / (i + 1))]", (int s) -> {
                 return fill(s * BUFFER_REPS,
                             i -> (float)0.01 + ((float)i / (i + 1)));
diff --git a/test/jdk/jdk/incubator/vector/FloatVector256Tests.java b/test/jdk/jdk/incubator/vector/FloatVector256Tests.java
index 5315b69a5b6..f00bf19d383 100644
--- a/test/jdk/jdk/incubator/vector/FloatVector256Tests.java
+++ b/test/jdk/jdk/incubator/vector/FloatVector256Tests.java
@@ -1256,6 +1256,10 @@ static int bits(float e) {
                 return fill(s * BUFFER_REPS,
                             i -> (((float)(i + 1) == 0) ? 1 : (float)(i + 1)));
             }),
+            withToString("float[smallOddValue(i)]", (int s) -> {
+                return fill(s * BUFFER_REPS,
+                            i -> (float)(i % 7 == 0 ? -3 : (i % 3 == 0 ? -1 : 1)));
+            }),
             withToString("float[0.01 + (i / (i + 1))]", (int s) -> {
                 return fill(s * BUFFER_REPS,
                             i -> (float)0.01 + ((float)i / (i + 1)));
diff --git a/test/jdk/jdk/incubator/vector/FloatVector512Tests.java b/test/jdk/jdk/incubator/vector/FloatVector512Tests.java
index 6a958511439..573bcc59c63 100644
--- a/test/jdk/jdk/incubator/vector/FloatVector512Tests.java
+++ b/test/jdk/jdk/incubator/vector/FloatVector512Tests.java
@@ -1256,6 +1256,10 @@ static int bits(float e) {
                 return fill(s * BUFFER_REPS,
                             i -> (((float)(i + 1) == 0) ? 1 : (float)(i + 1)));
             }),
+            withToString("float[smallOddValue(i)]", (int s) -> {
+                return fill(s * BUFFER_REPS,
+                            i -> (float)(i % 7 == 0 ? -3 : (i % 3 == 0 ? -1 : 1)));
+            }),
             withToString("float[0.01 + (i / (i + 1))]", (int s) -> {
                 return fill(s * BUFFER_REPS,
                             i -> (float)0.01 + ((float)i / (i + 1)));
diff --git a/test/jdk/jdk/incubator/vector/FloatVector64Tests.java b/test/jdk/jdk/incubator/vector/FloatVector64Tests.java
index b06dff18194..8244ffabb51 100644
--- a/test/jdk/jdk/incubator/vector/FloatVector64Tests.java
+++ b/test/jdk/jdk/incubator/vector/FloatVector64Tests.java
@@ -1256,6 +1256,10 @@ static int bits(float e) {
                 return fill(s * BUFFER_REPS,
                             i -> (((float)(i + 1) == 0) ? 1 : (float)(i + 1)));
             }),
+            withToString("float[smallOddValue(i)]", (int s) -> {
+                return fill(s * BUFFER_REPS,
+                            i -> (float)(i % 7 == 0 ? -3 : (i % 3 == 0 ? -1 : 1)));
+            }),
             withToString("float[0.01 + (i / (i + 1))]", (int s) -> {
                 return fill(s * BUFFER_REPS,
                             i -> (float)0.01 + ((float)i / (i + 1)));
diff --git a/test/jdk/jdk/incubator/vector/FloatVectorMaxTests.java b/test/jdk/jdk/incubator/vector/FloatVectorMaxTests.java
index 9b84e852c1c..30c470e05f4 100644
--- a/test/jdk/jdk/incubator/vector/FloatVectorMaxTests.java
+++ b/test/jdk/jdk/incubator/vector/FloatVectorMaxTests.java
@@ -1262,6 +1262,10 @@ static int bits(float e) {
                 return fill(s * BUFFER_REPS,
                             i -> (((float)(i + 1) == 0) ? 1 : (float)(i + 1)));
             }),
+            withToString("float[smallOddValue(i)]", (int s) -> {
+                return fill(s * BUFFER_REPS,
+                            i -> (float)(i % 7 == 0 ? -3 : (i % 3 == 0 ? -1 : 1)));
+            }),
             withToString("float[0.01 + (i / (i + 1))]", (int s) -> {
                 return fill(s * BUFFER_REPS,
                             i -> (float)0.01 + ((float)i / (i + 1)));
diff --git a/test/jdk/jdk/incubator/vector/IntVector128Tests.java b/test/jdk/jdk/incubator/vector/IntVector128Tests.java
index d62f5d8df00..2b36a2802eb 100644
--- a/test/jdk/jdk/incubator/vector/IntVector128Tests.java
+++ b/test/jdk/jdk/incubator/vector/IntVector128Tests.java
@@ -1104,6 +1104,10 @@ static int bits(int e) {
                 return fill(s * BUFFER_REPS,
                             i -> (((int)(i + 1) == 0) ? 1 : (int)(i + 1)));
             }),
+            withToString("int[smallOddValue(i)]", (int s) -> {
+                return fill(s * BUFFER_REPS,
+                            i -> (int)(i % 7 == 0 ? -3 : (i % 3 == 0 ? -1 : 1)));
+            }),
             withToString("int[cornerCaseValue(i)]", (int s) -> {
                 return fill(s * BUFFER_REPS,
                             i -> cornerCaseValue(i));
diff --git a/test/jdk/jdk/incubator/vector/IntVector256Tests.java b/test/jdk/jdk/incubator/vector/IntVector256Tests.java
index bb2d1d717f4..9d4632b88dd 100644
--- a/test/jdk/jdk/incubator/vector/IntVector256Tests.java
+++ b/test/jdk/jdk/incubator/vector/IntVector256Tests.java
@@ -1104,6 +1104,10 @@ static int bits(int e) {
                 return fill(s * BUFFER_REPS,
                             i -> (((int)(i + 1) == 0) ? 1 : (int)(i + 1)));
             }),
+            withToString("int[smallOddValue(i)]", (int s) -> {
+                return fill(s * BUFFER_REPS,
+                            i -> (int)(i % 7 == 0 ? -3 : (i % 3 == 0 ? -1 : 1)));
+            }),
             withToString("int[cornerCaseValue(i)]", (int s) -> {
                 return fill(s * BUFFER_REPS,
                             i -> cornerCaseValue(i));
diff --git a/test/jdk/jdk/incubator/vector/IntVector512Tests.java b/test/jdk/jdk/incubator/vector/IntVector512Tests.java
index 5ceba4e88ec..aa3c3eccf5b 100644
--- a/test/jdk/jdk/incubator/vector/IntVector512Tests.java
+++ b/test/jdk/jdk/incubator/vector/IntVector512Tests.java
@@ -1104,6 +1104,10 @@ static int bits(int e) {
                 return fill(s * BUFFER_REPS,
                             i -> (((int)(i + 1) == 0) ? 1 : (int)(i + 1)));
             }),
+            withToString("int[smallOddValue(i)]", (int s) -> {
+                return fill(s * BUFFER_REPS,
+                            i -> (int)(i % 7 == 0 ? -3 : (i % 3 == 0 ? -1 : 1)));
+            }),
             withToString("int[cornerCaseValue(i)]", (int s) -> {
                 return fill(s * BUFFER_REPS,
                             i -> cornerCaseValue(i));
diff --git a/test/jdk/jdk/incubator/vector/IntVector64Tests.java b/test/jdk/jdk/incubator/vector/IntVector64Tests.java
index 9d3849a2c04..89247f9f932 100644
--- a/test/jdk/jdk/incubator/vector/IntVector64Tests.java
+++ b/test/jdk/jdk/incubator/vector/IntVector64Tests.java
@@ -1104,6 +1104,10 @@ static int bits(int e) {
                 return fill(s * BUFFER_REPS,
                             i -> (((int)(i + 1) == 0) ? 1 : (int)(i + 1)));
             }),
+            withToString("int[smallOddValue(i)]", (int s) -> {
+                return fill(s * BUFFER_REPS,
+                            i -> (int)(i % 7 == 0 ? -3 : (i % 3 == 0 ? -1 : 1)));
+            }),
             withToString("int[cornerCaseValue(i)]", (int s) -> {
                 return fill(s * BUFFER_REPS,
                             i -> cornerCaseValue(i));
diff --git a/test/jdk/jdk/incubator/vector/IntVectorMaxTests.java b/test/jdk/jdk/incubator/vector/IntVectorMaxTests.java
index 6c671a81bf1..3272dbbb3de 100644
--- a/test/jdk/jdk/incubator/vector/IntVectorMaxTests.java
+++ b/test/jdk/jdk/incubator/vector/IntVectorMaxTests.java
@@ -1110,6 +1110,10 @@ static int bits(int e) {
                 return fill(s * BUFFER_REPS,
                             i -> (((int)(i + 1) == 0) ? 1 : (int)(i + 1)));
             }),
+            withToString("int[smallOddValue(i)]", (int s) -> {
+                return fill(s * BUFFER_REPS,
+                            i -> (int)(i % 7 == 0 ? -3 : (i % 3 == 0 ? -1 : 1)));
+            }),
             withToString("int[cornerCaseValue(i)]", (int s) -> {
                 return fill(s * BUFFER_REPS,
                             i -> cornerCaseValue(i));
diff --git a/test/jdk/jdk/incubator/vector/LongVector128Tests.java b/test/jdk/jdk/incubator/vector/LongVector128Tests.java
index 49e2e1a0078..30f1ecc2bf4 100644
--- a/test/jdk/jdk/incubator/vector/LongVector128Tests.java
+++ b/test/jdk/jdk/incubator/vector/LongVector128Tests.java
@@ -1088,6 +1088,10 @@ static long bits(long e) {
                 return fill(s * BUFFER_REPS,
                             i -> (((long)(i + 1) == 0) ? 1 : (long)(i + 1)));
             }),
+            withToString("long[smallOddValue(i)]", (int s) -> {
+                return fill(s * BUFFER_REPS,
+                            i -> (long)(i % 7 == 0 ? -3 : (i % 3 == 0 ? -1 : 1)));
+            }),
             withToString("long[cornerCaseValue(i)]", (int s) -> {
                 return fill(s * BUFFER_REPS,
                             i -> cornerCaseValue(i));
diff --git a/test/jdk/jdk/incubator/vector/LongVector256Tests.java b/test/jdk/jdk/incubator/vector/LongVector256Tests.java
index 84c8da4e800..6dd2f359742 100644
--- a/test/jdk/jdk/incubator/vector/LongVector256Tests.java
+++ b/test/jdk/jdk/incubator/vector/LongVector256Tests.java
@@ -1088,6 +1088,10 @@ static long bits(long e) {
                 return fill(s * BUFFER_REPS,
                             i -> (((long)(i + 1) == 0) ? 1 : (long)(i + 1)));
             }),
+            withToString("long[smallOddValue(i)]", (int s) -> {
+                return fill(s * BUFFER_REPS,
+                            i -> (long)(i % 7 == 0 ? -3 : (i % 3 == 0 ? -1 : 1)));
+            }),
             withToString("long[cornerCaseValue(i)]", (int s) -> {
                 return fill(s * BUFFER_REPS,
                             i -> cornerCaseValue(i));
diff --git a/test/jdk/jdk/incubator/vector/LongVector512Tests.java b/test/jdk/jdk/incubator/vector/LongVector512Tests.java
index 00d8c4b010a..6347a1b53a2 100644
--- a/test/jdk/jdk/incubator/vector/LongVector512Tests.java
+++ b/test/jdk/jdk/incubator/vector/LongVector512Tests.java
@@ -1088,6 +1088,10 @@ static long bits(long e) {
                 return fill(s * BUFFER_REPS,
                             i -> (((long)(i + 1) == 0) ? 1 : (long)(i + 1)));
             }),
+            withToString("long[smallOddValue(i)]", (int s) -> {
+                return fill(s * BUFFER_REPS,
+                            i -> (long)(i % 7 == 0 ? -3 : (i % 3 == 0 ? -1 : 1)));
+            }),
             withToString("long[cornerCaseValue(i)]", (int s) -> {
                 return fill(s * BUFFER_REPS,
                             i -> cornerCaseValue(i));
diff --git a/test/jdk/jdk/incubator/vector/LongVector64Tests.java b/test/jdk/jdk/incubator/vector/LongVector64Tests.java
index d4cdfe54ad2..0518c17b75f 100644
--- a/test/jdk/jdk/incubator/vector/LongVector64Tests.java
+++ b/test/jdk/jdk/incubator/vector/LongVector64Tests.java
@@ -1088,6 +1088,10 @@ static long bits(long e) {
                 return fill(s * BUFFER_REPS,
                             i -> (((long)(i + 1) == 0) ? 1 : (long)(i + 1)));
             }),
+            withToString("long[smallOddValue(i)]", (int s) -> {
+                return fill(s * BUFFER_REPS,
+                            i -> (long)(i % 7 == 0 ? -3 : (i % 3 == 0 ? -1 : 1)));
+            }),
             withToString("long[cornerCaseValue(i)]", (int s) -> {
                 return fill(s * BUFFER_REPS,
                             i -> cornerCaseValue(i));
diff --git a/test/jdk/jdk/incubator/vector/LongVectorMaxTests.java b/test/jdk/jdk/incubator/vector/LongVectorMaxTests.java
index 597169b00f5..f5ab956b5a7 100644
--- a/test/jdk/jdk/incubator/vector/LongVectorMaxTests.java
+++ b/test/jdk/jdk/incubator/vector/LongVectorMaxTests.java
@@ -1094,6 +1094,10 @@ static long bits(long e) {
                 return fill(s * BUFFER_REPS,
                             i -> (((long)(i + 1) == 0) ? 1 : (long)(i + 1)));
             }),
+            withToString("long[smallOddValue(i)]", (int s) -> {
+                return fill(s * BUFFER_REPS,
+                            i -> (long)(i % 7 == 0 ? -3 : (i % 3 == 0 ? -1 : 1)));
+            }),
             withToString("long[cornerCaseValue(i)]", (int s) -> {
                 return fill(s * BUFFER_REPS,
                             i -> cornerCaseValue(i));
diff --git a/test/jdk/jdk/incubator/vector/ShortVector128Tests.java b/test/jdk/jdk/incubator/vector/ShortVector128Tests.java
index 85e7d715182..40de51c90ab 100644
--- a/test/jdk/jdk/incubator/vector/ShortVector128Tests.java
+++ b/test/jdk/jdk/incubator/vector/ShortVector128Tests.java
@@ -1104,6 +1104,10 @@ static short bits(short e) {
                 return fill(s * BUFFER_REPS,
                             i -> (((short)(i + 1) == 0) ? 1 : (short)(i + 1)));
             }),
+            withToString("short[smallOddValue(i)]", (int s) -> {
+                return fill(s * BUFFER_REPS,
+                            i -> (short)(i % 7 == 0 ? -3 : (i % 3 == 0 ? -1 : 1)));
+            }),
             withToString("short[cornerCaseValue(i)]", (int s) -> {
                 return fill(s * BUFFER_REPS,
                             i -> cornerCaseValue(i));
diff --git a/test/jdk/jdk/incubator/vector/ShortVector256Tests.java b/test/jdk/jdk/incubator/vector/ShortVector256Tests.java
index df379b64e3a..c28dd34c8ef 100644
--- a/test/jdk/jdk/incubator/vector/ShortVector256Tests.java
+++ b/test/jdk/jdk/incubator/vector/ShortVector256Tests.java
@@ -1104,6 +1104,10 @@ static short bits(short e) {
                 return fill(s * BUFFER_REPS,
                             i -> (((short)(i + 1) == 0) ? 1 : (short)(i + 1)));
             }),
+            withToString("short[smallOddValue(i)]", (int s) -> {
+                return fill(s * BUFFER_REPS,
+                            i -> (short)(i % 7 == 0 ? -3 : (i % 3 == 0 ? -1 : 1)));
+            }),
             withToString("short[cornerCaseValue(i)]", (int s) -> {
                 return fill(s * BUFFER_REPS,
                             i -> cornerCaseValue(i));
diff --git a/test/jdk/jdk/incubator/vector/ShortVector512Tests.java b/test/jdk/jdk/incubator/vector/ShortVector512Tests.java
index ae5804c3688..703ef7d358b 100644
--- a/test/jdk/jdk/incubator/vector/ShortVector512Tests.java
+++ b/test/jdk/jdk/incubator/vector/ShortVector512Tests.java
@@ -1104,6 +1104,10 @@ static short bits(short e) {
                 return fill(s * BUFFER_REPS,
                             i -> (((short)(i + 1) == 0) ? 1 : (short)(i + 1)));
             }),
+            withToString("short[smallOddValue(i)]", (int s) -> {
+                return fill(s * BUFFER_REPS,
+                            i -> (short)(i % 7 == 0 ? -3 : (i % 3 == 0 ? -1 : 1)));
+            }),
             withToString("short[cornerCaseValue(i)]", (int s) -> {
                 return fill(s * BUFFER_REPS,
                             i -> cornerCaseValue(i));
diff --git a/test/jdk/jdk/incubator/vector/ShortVector64Tests.java b/test/jdk/jdk/incubator/vector/ShortVector64Tests.java
index 5f84682f02f..ea6846498a3 100644
--- a/test/jdk/jdk/incubator/vector/ShortVector64Tests.java
+++ b/test/jdk/jdk/incubator/vector/ShortVector64Tests.java
@@ -1104,6 +1104,10 @@ static short bits(short e) {
                 return fill(s * BUFFER_REPS,
                             i -> (((short)(i + 1) == 0) ? 1 : (short)(i + 1)));
             }),
+            withToString("short[smallOddValue(i)]", (int s) -> {
+                return fill(s * BUFFER_REPS,
+                            i -> (short)(i % 7 == 0 ? -3 : (i % 3 == 0 ? -1 : 1)));
+            }),
             withToString("short[cornerCaseValue(i)]", (int s) -> {
                 return fill(s * BUFFER_REPS,
                             i -> cornerCaseValue(i));
diff --git a/test/jdk/jdk/incubator/vector/ShortVectorMaxTests.java b/test/jdk/jdk/incubator/vector/ShortVectorMaxTests.java
index 5451ad6c50e..6a85da12054 100644
--- a/test/jdk/jdk/incubator/vector/ShortVectorMaxTests.java
+++ b/test/jdk/jdk/incubator/vector/ShortVectorMaxTests.java
@@ -1110,6 +1110,10 @@ static short bits(short e) {
                 return fill(s * BUFFER_REPS,
                             i -> (((short)(i + 1) == 0) ? 1 : (short)(i + 1)));
             }),
+            withToString("short[smallOddValue(i)]", (int s) -> {
+                return fill(s * BUFFER_REPS,
+                            i -> (short)(i % 7 == 0 ? -3 : (i % 3 == 0 ? -1 : 1)));
+            }),
             withToString("short[cornerCaseValue(i)]", (int s) -> {
                 return fill(s * BUFFER_REPS,
                             i -> cornerCaseValue(i));
diff --git a/test/jdk/jdk/incubator/vector/templates/Unit-header.template b/test/jdk/jdk/incubator/vector/templates/Unit-header.template
index e1434dccb2b..b87012a2181 100644
--- a/test/jdk/jdk/incubator/vector/templates/Unit-header.template
+++ b/test/jdk/jdk/incubator/vector/templates/Unit-header.template
@@ -1375,6 +1375,10 @@ relativeError));
                 return fill(s * BUFFER_REPS,
                             i -> ((($type$)(i + 1) == 0) ? 1 : ($type$)(i + 1)));
             }),
+            withToString("$type$[smallOddValue(i)]", (int s) -> {
+                return fill(s * BUFFER_REPS,
+                            i -> ($type$)(i % 7 == 0 ? -3 : (i % 3 == 0 ? -1 : 1)));
+            }),
 #if[FP]
             withToString("$type$[0.01 + (i / (i + 1))]", (int s) -> {
                 return fill(s * BUFFER_REPS,

From 4a335f878c87b75a111252fafa80dbb96c52259a Mon Sep 17 00:00:00 2001
From: Alan Bateman 
Date: Tue, 31 Mar 2026 06:56:56 +0000
Subject: [PATCH 071/116] 8381002: Thread dump should convert longs to json
 numbers if possible

Reviewed-by: kevinw, amenkov, sspitsyn, lmesnik
---
 .../classes/jdk/internal/vm/ThreadDumper.java |  69 +++++--
 .../doc-files/threadDump.schema.json          |  36 ++--
 .../crypto/provider/Cipher/HPKE/KAT9180.java  |  14 +-
 .../DumpThreadsFormat1.java                   |  97 ++++++++++
 test/jdk/jdk/jfr/tool/TestPrintJSON.java      |   9 +-
 .../security/provider/acvp/ML_DSA_Test.java   |  28 +--
 .../security/provider/acvp/ML_KEM_Test.java   |  18 +-
 .../sun/security/provider/acvp/SHA_Test.java  |  26 +--
 test/lib/jdk/test/lib/json/JSONValue.java     | 183 ++++++++++++------
 .../jdk/test/lib/threaddump/ThreadDump.java   |  62 +++---
 10 files changed, 366 insertions(+), 176 deletions(-)
 create mode 100644 test/jdk/com/sun/management/HotSpotDiagnosticMXBean/DumpThreadsFormat1.java

diff --git a/src/java.base/share/classes/jdk/internal/vm/ThreadDumper.java b/src/java.base/share/classes/jdk/internal/vm/ThreadDumper.java
index 276c379a564..fa7d4bab076 100644
--- a/src/java.base/share/classes/jdk/internal/vm/ThreadDumper.java
+++ b/src/java.base/share/classes/jdk/internal/vm/ThreadDumper.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -250,18 +250,43 @@ public static void dumpThreadsToJson(OutputStream out) throws IOException {
         }
     }
 
+    /**
+     * JSON is schema-less and the thread dump format will evolve over time.
+     * {@code HotSpotDiagnosticMXBean.dumpThreads} links to a JSON file that documents
+     * the latest/current format. A system property can be used to generate the thread
+     * dump in older formats if necessary.
+     */
+    private static class JsonFormat {
+        private static final String JSON_FORMAT_VERSION_PROP =
+                "com.sun.management.HotSpotDiagnosticMXBean.dumpThreads.format";
+        static final int JSON_FORMAT_V1 = 1;
+        static final int JSON_FORMAT_V2 = 2;
+        private static final int JSON_FORMAT_LATEST = JSON_FORMAT_V2;
+        private static final int JSON_FORMAT;
+        static {
+            int ver = Integer.getInteger(JSON_FORMAT_VERSION_PROP, JSON_FORMAT_LATEST);
+            JSON_FORMAT = Math.clamp(ver, JSON_FORMAT_V1, JSON_FORMAT_LATEST);
+        }
+
+        static int formatVersion() {
+            return JSON_FORMAT;
+        }
+    }
+
     /**
      * Generate a thread dump to the given text stream in JSON format.
      * @throws UncheckedIOException if an I/O error occurs
      */
     private static void dumpThreadsToJson(TextWriter textWriter) {
-        var jsonWriter = new JsonWriter(textWriter);
-
+        int format = JsonFormat.formatVersion();
+        var jsonWriter = new JsonWriter(textWriter, (format == JsonFormat.JSON_FORMAT_V1));
         jsonWriter.startObject();  // top-level object
-
         jsonWriter.startObject("threadDump");
+        if (format > JsonFormat.JSON_FORMAT_V1) {
+            jsonWriter.writeProperty("formatVersion", format);
+        }
 
-        jsonWriter.writeProperty("processId", processId());
+        jsonWriter.writeLongProperty("processId", processId());
         jsonWriter.writeProperty("time", Instant.now());
         jsonWriter.writeProperty("runtimeVersion", Runtime.version());
 
@@ -284,7 +309,11 @@ private static void dumpThreads(ThreadContainer container, JsonWriter jsonWriter
         jsonWriter.writeProperty("parent", container.parent());
 
         Thread owner = container.owner();
-        jsonWriter.writeProperty("owner", (owner != null) ? owner.threadId() : null);
+        if (owner != null) {
+            jsonWriter.writeLongProperty("owner", owner.threadId());
+        } else {
+            jsonWriter.writeProperty("owner", null);  // owner is not optional
+        }
 
         long threadCount = 0;
         jsonWriter.startArray("threads");
@@ -301,7 +330,7 @@ private static void dumpThreads(ThreadContainer container, JsonWriter jsonWriter
         if (!ThreadContainers.trackAllThreads()) {
             threadCount = Long.max(threadCount, container.threadCount());
         }
-        jsonWriter.writeProperty("threadCount", threadCount);
+        jsonWriter.writeLongProperty("threadCount", threadCount);
 
         jsonWriter.endObject();
 
@@ -324,7 +353,7 @@ private static boolean dumpThread(Thread thread, JsonWriter jsonWriter) {
         StackTraceElement[] stackTrace = snapshot.stackTrace();
 
         jsonWriter.startObject();
-        jsonWriter.writeProperty("tid", thread.threadId());
+        jsonWriter.writeLongProperty("tid", thread.threadId());
         jsonWriter.writeProperty("time", now);
         if (thread.isVirtual()) {
             jsonWriter.writeProperty("virtual", Boolean.TRUE);
@@ -339,7 +368,7 @@ private static boolean dumpThread(Thread thread, JsonWriter jsonWriter) {
             jsonWriter.startObject("parkBlocker");
             jsonWriter.writeProperty("object", Objects.toIdentityString(parkBlocker));
             if (snapshot.parkBlockerOwner() instanceof Thread owner) {
-                jsonWriter.writeProperty("owner", owner.threadId());
+                jsonWriter.writeLongProperty("owner", owner.threadId());
             }
             jsonWriter.endObject();
         }
@@ -380,7 +409,7 @@ private static boolean dumpThread(Thread thread, JsonWriter jsonWriter) {
 
         // thread identifier of carrier, when mounted
         if (thread.isVirtual() && snapshot.carrierThread() instanceof Thread carrier) {
-            jsonWriter.writeProperty("carrier", carrier.threadId());
+            jsonWriter.writeLongProperty("carrier", carrier.threadId());
         }
 
         jsonWriter.endObject();
@@ -411,10 +440,12 @@ int getAndIncrementPropertyCount() {
             }
         }
         private final Deque stack = new ArrayDeque<>();
+        private final boolean generateLongsAsString;
         private final TextWriter writer;
 
-        JsonWriter(TextWriter writer) {
+        JsonWriter(TextWriter writer, boolean generateLongsAsString) {
             this.writer = writer;
+            this.generateLongsAsString = generateLongsAsString;
         }
 
         private void indent() {
@@ -461,6 +492,7 @@ private void endObject(boolean isArray) {
          */
         void writeProperty(String name, Object obj) {
             Node node = stack.peek();
+            assert node != null;
             if (node.getAndIncrementPropertyCount() > 0) {
                 writer.println(",");
             }
@@ -469,8 +501,6 @@ void writeProperty(String name, Object obj) {
                 writer.print("\"" + name + "\": ");
             }
             switch (obj) {
-                // Long may be larger than safe range of JSON integer value
-                case Long   _  -> writer.print("\"" + obj + "\"");
                 case Number _  -> writer.print(obj);
                 case Boolean _ -> writer.print(obj);
                 case null      -> writer.print("null");
@@ -478,6 +508,19 @@ void writeProperty(String name, Object obj) {
             }
         }
 
+        /**
+         * Write a property with a long value. If the value is outside the "interop"
+         * range of IEEE-754 double-precision floating point (64-bit) then it is
+         * written as a string.
+         */
+        void writeLongProperty(String name, long value) {
+            if (generateLongsAsString || value < -0x1FFFFFFFFFFFFFL || value > 0x1FFFFFFFFFFFFFL) {
+                writeProperty(name, Long.toString(value));
+            } else {
+                writeProperty(name, value);
+            }
+        }
+
         /**
          * Write an unnamed property.
          */
diff --git a/src/jdk.management/share/classes/com/sun/management/doc-files/threadDump.schema.json b/src/jdk.management/share/classes/com/sun/management/doc-files/threadDump.schema.json
index 1da3e3941ef..30161b0bb74 100644
--- a/src/jdk.management/share/classes/com/sun/management/doc-files/threadDump.schema.json
+++ b/src/jdk.management/share/classes/com/sun/management/doc-files/threadDump.schema.json
@@ -4,8 +4,12 @@
     "threadDump": {
       "type": "object",
       "properties": {
+        "formatVersion": {
+          "type": "integer",
+          "description": "Format version (2)."
+        },
         "processId": {
-          "type": "string",
+          "type": "integer",
           "description": "The native process id of the Java virtual machine."
         },
         "time": {
@@ -28,18 +32,12 @@
                   "description": "The container name. The container name is unique."
                 },
                 "parent": {
-                  "type": [
-                    "string",
-                    "null"
-                  ],
+                  "type": [ "string", "null" ],
                   "description": "The parent container name or null for the root container."
                 },
                 "owner": {
-                  "type": [
-                    "string",
-                    "null"
-                  ],
-                  "description": "The thread identifier of the owner thread if owned."
+                  "type": [ "integer", "null" ],
+                  "description": "The thread identifier of the owner thread or null if no owner."
                 },
                 "threads": {
                   "type": "array",
@@ -49,7 +47,7 @@
                       "type": "object",
                       "properties": {
                         "tid": {
-                          "type": "string",
+                          "type": "integer",
                           "description": "The thread identifier."
                         },
                         "time": {
@@ -69,9 +67,7 @@
                           "description": "true for a virtual thread."
                         },
                         "parkBlocker": {
-                          "type": [
-                            "object"
-                          ],
+                          "type": "object",
                           "properties": {
                             "object": {
                               "type": "string",
@@ -79,7 +75,7 @@
                             }
                           },
                           "owner": {
-                            "type": "string",
+                            "type": "integer",
                             "description": "The thread identifier of the owner when the parkBlocker is an AbstractOwnableSynchronizer."
                           },
                           "required": [
@@ -117,10 +113,7 @@
                               "locks": {
                                 "type": "array",
                                 "items": {
-                                  "type": [
-                                    "string",
-                                    "null"
-                                  ],
+                                  "type": [ "string", "null" ],
                                   "description": "The object for which the monitor is owned by the thread, null if eliminated."
                                 }
                               }
@@ -132,7 +125,7 @@
                           }
                         },
                         "carrier":  {
-                          "type": "string",
+                          "type": "integer",
                           "description": "The thread identifier of the carrier thread if mounted."
                         }
                       },
@@ -147,7 +140,7 @@
                   ]
                 },
                 "threadCount": {
-                  "type": "string",
+                  "type": "integer",
                   "description": "The number of threads in the thread container."
                 }
               },
@@ -162,6 +155,7 @@
         }
       },
       "required": [
+        "formatVersion",
         "processId",
         "time",
         "runtimeVersion",
diff --git a/test/jdk/com/sun/crypto/provider/Cipher/HPKE/KAT9180.java b/test/jdk/com/sun/crypto/provider/Cipher/HPKE/KAT9180.java
index 024d5f977a7..9b6fad6a90d 100644
--- a/test/jdk/com/sun/crypto/provider/Cipher/HPKE/KAT9180.java
+++ b/test/jdk/com/sun/crypto/provider/Cipher/HPKE/KAT9180.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -82,12 +82,12 @@ public static void main(String[] args) throws Exception {
         var c1 = Cipher.getInstance("HPKE");
         var c2 = Cipher.getInstance("HPKE");
         var ts = JSONValue.parse(new String(Files.readAllBytes(archivePath), StandardCharsets.UTF_8));
-        for (var tg : ts.asArray()) {
-            var mode = Integer.parseInt(tg.get("mode").asString());
+        for (var tg : ts.elements()) {
+            var mode = tg.get("mode").asInt();
             System.err.print('I');
-            var kem_id = Integer.parseInt(tg.get("kem_id").asString());
-            var kdf_id = Integer.parseInt(tg.get("kdf_id").asString());
-            var aead_id = Integer.parseInt(tg.get("aead_id").asString());
+            var kem_id = tg.get("kem_id").asInt();
+            var kdf_id = tg.get("kdf_id").asInt();
+            var aead_id = tg.get("aead_id").asInt();
             var ikmR = h.parseHex(tg.get("ikmR").asString());
             var ikmE = h.parseHex(tg.get("ikmE").asString());
             var info = h.parseHex(tg.get("info").asString());
@@ -117,7 +117,7 @@ public static void main(String[] args) throws Exception {
             if (enc != null) {
                 System.err.print('e');
                 var count = 0;
-                for (var p : enc.asArray()) {
+                for (var p : enc.elements()) {
                     var aad = h.parseHex(p.get("aad").asString());
                     var pt = h.parseHex(p.get("pt").asString());
                     var ct = h.parseHex(p.get("ct").asString());
diff --git a/test/jdk/com/sun/management/HotSpotDiagnosticMXBean/DumpThreadsFormat1.java b/test/jdk/com/sun/management/HotSpotDiagnosticMXBean/DumpThreadsFormat1.java
new file mode 100644
index 00000000000..5bc9ae2918f
--- /dev/null
+++ b/test/jdk/com/sun/management/HotSpotDiagnosticMXBean/DumpThreadsFormat1.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 8381169
+ * @summary Basic com.sun.management.HotSpotDiagnosticMXBean.dumpThreads generating a
+ *    format version 1 thread dump
+ * @modules jdk.management
+ * @library /test/lib
+ * @run junit/othervm -Dcom.sun.management.HotSpotDiagnosticMXBean.dumpThreads.format=1 ${test.main.class}
+ */
+
+import java.lang.management.ManagementFactory;
+import java.nio.file.Files;
+import java.nio.file.FileAlreadyExistsException;
+import java.nio.file.Path;
+import java.util.List;
+import com.sun.management.HotSpotDiagnosticMXBean;
+import com.sun.management.HotSpotDiagnosticMXBean.ThreadDumpFormat;
+import jdk.test.lib.json.JSONValue;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.BeforeAll;
+import static org.junit.jupiter.api.Assertions.*;
+
+class DumpThreadsFormat1 {
+    private static JSONValue threadDumpObj;
+
+    @BeforeAll
+    static void generateThreadDump() throws Exception {
+        Path dir = Path.of(".").toAbsolutePath();
+        Path file = Files.createTempFile(dir, "dump", ".json");
+        Files.delete(file);
+        var mbean = ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class);
+        mbean.dumpThreads(file.toString(), HotSpotDiagnosticMXBean.ThreadDumpFormat.JSON);
+        System.err.format("Dumped to %s%n", file.getFileName());
+        String json = Files.readString(file);
+        threadDumpObj = JSONValue.parse(json).get("threadDump");
+    }
+
+    /**
+     * Test that "formatVersion" is not present.
+     */
+    @Test
+    void testFormatVersion() {
+        threadDumpObj.getOrAbsent("formatVersion")
+                .ifPresent(_ -> { fail("formatVersion not expected"); });
+    }
+
+    /**
+     * Test "processId" is a string.
+     */
+    @Test
+    void testProcessId() {
+        String processId = "" + ProcessHandle.current().pid();
+        assertEquals(processId, threadDumpObj.get("processId").asString());
+    }
+
+    /**
+     * Test "tid" for current thread in root container is a string.
+     */
+    @Test
+    void testThreadId() throws Exception {
+        JSONValue rootContainerObj = threadDumpObj.get("threadContainers").element(0);
+        String name = rootContainerObj.get("container").asString();
+        assertEquals("", name);
+
+        String tid = "" + Thread.currentThread().threadId();
+        boolean found = rootContainerObj.get("threads")
+                .elements()
+                .stream()
+                .map(t -> t.get("tid").asString())
+                .anyMatch(tid::equals);
+        assertTrue(found, "Current thread not found");
+    }
+}
diff --git a/test/jdk/jdk/jfr/tool/TestPrintJSON.java b/test/jdk/jdk/jfr/tool/TestPrintJSON.java
index 3d79c75300f..2abbff68338 100644
--- a/test/jdk/jdk/jfr/tool/TestPrintJSON.java
+++ b/test/jdk/jdk/jfr/tool/TestPrintJSON.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,6 +28,7 @@
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 
 import jdk.jfr.Timespan;
 import jdk.jfr.Timestamp;
@@ -62,7 +63,7 @@ public static void main(String... args) throws Throwable {
 
         JSONValue o = JSONValue.parse(json);
         JSONValue recording = o.get("recording");
-        JSONArray jsonEvents = recording.get("events").asArray();
+        List jsonEvents = recording.get("events").elements();
         List events = RecordingFile.readAllEvents(recordingFile);
         Collections.sort(events, new EndTicksComparator());
         // Verify events are equal
@@ -79,7 +80,7 @@ public static void main(String... args) throws Throwable {
     private static void assertEquals(Object jsonObject, Object jfrObject) throws Exception {
         // Check object
         if (jfrObject instanceof RecordedObject) {
-            JSONValue values = ((JSONValue) jsonObject).get("values");
+            Map values = ((JSONValue) jsonObject).get("values").members();
             RecordedObject recObject = (RecordedObject) jfrObject;
             Asserts.assertEquals(values.size(), recObject.getFields().size());
             for (ValueDescriptor v : recObject.getFields()) {
@@ -102,7 +103,7 @@ private static void assertEquals(Object jsonObject, Object jfrObject) throws Exc
         // Check array
         if (jfrObject != null && jfrObject.getClass().isArray()) {
             Object[] jfrArray = (Object[]) jfrObject;
-            JSONArray jsArray = ((JSONArray) jsonObject);
+            List jsArray = ((JSONValue) jsonObject).elements();
             for (int i = 0; i < jfrArray.length; i++) {
                 assertEquals(jsArray.get(i), jfrArray[i]);
             }
diff --git a/test/jdk/sun/security/provider/acvp/ML_DSA_Test.java b/test/jdk/sun/security/provider/acvp/ML_DSA_Test.java
index f76f3d8b9a8..29b760e5d84 100644
--- a/test/jdk/sun/security/provider/acvp/ML_DSA_Test.java
+++ b/test/jdk/sun/security/provider/acvp/ML_DSA_Test.java
@@ -63,12 +63,12 @@ static void keyGenTest(JSONValue kat, Provider p) throws Exception {
         var f = p == null
                 ? KeyFactory.getInstance("ML-DSA")
                 : KeyFactory.getInstance("ML-DSA", p);
-        for (var t : kat.get("testGroups").asArray()) {
+        for (var t : kat.get("testGroups").elements()) {
             var pname = t.get("parameterSet").asString();
             var np = genParams(pname);
             System.out.println(">> " + pname);
-            for (var c : t.get("tests").asArray()) {
-                System.out.print(c.get("tcId").asString() + " ");
+            for (var c : t.get("tests").elements()) {
+                System.out.print(c.get("tcId").asInt() + " ");
                 var seed = toByteArray(c.get("seed").asString());
                 g.initialize(np, new FixedSecureRandom(seed));
                 var kp = g.generateKeyPair();
@@ -85,7 +85,7 @@ static void sigGenTest(JSONValue kat, Provider p) throws Exception {
         var s = p == null
                 ? Signature.getInstance("ML-DSA")
                 : Signature.getInstance("ML-DSA", p);
-        for (var t : kat.get("testGroups").asArray()) {
+        for (var t : kat.get("testGroups").elements()) {
             var pname = t.get("parameterSet").asString();
             System.out.println(">> " + pname + " sign");
             var det = t.get("deterministic").asBoolean();
@@ -97,14 +97,15 @@ static void sigGenTest(JSONValue kat, Provider p) throws Exception {
             if (t.get("externalMu").asBoolean()) {
                 continue; // Not supported
             }
-            for (var c : t.get("tests").asArray()) {
-                var cstr = c.get("context");
-                var ctxt = cstr == null ? new byte[0] : toByteArray(cstr.asString());
+            for (var c : t.get("tests").elements()) {
+                var ctxt =  c.getOrAbsent("context")
+                        .map(v -> toByteArray(v.asString()))
+                        .orElse(new byte[0]);
                 var hashAlg = c.get("hashAlg").asString();
                 if (!hashAlg.equals("none") || ctxt.length != 0) {
                     continue; // Not supported
                 }
-                System.out.print(Integer.parseInt(c.get("tcId").asString()) + " ");
+                System.out.print(c.get("tcId").asInt() + " ");
                 var sk = new PrivateKey() {
                     public String getAlgorithm() { return pname; }
                     public String getFormat() { return "RAW"; }
@@ -129,7 +130,7 @@ static void sigVerTest(JSONValue kat, Provider p) throws Exception {
         var s = p == null
                 ? Signature.getInstance("ML-DSA")
                 : Signature.getInstance("ML-DSA", p);
-        for (var t : kat.get("testGroups").asArray()) {
+        for (var t : kat.get("testGroups").elements()) {
             var pname = t.get("parameterSet").asString();
             System.out.println(">> " + pname + " verify");
 
@@ -143,14 +144,15 @@ static void sigVerTest(JSONValue kat, Provider p) throws Exception {
                 continue; // Not supported
             }
 
-            for (var c : t.get("tests").asArray()) {
-                var cstr = c.get("context");
-                var ctxt = cstr == null ? new byte[0] : toByteArray(cstr.asString());
+            for (var c : t.get("tests").elements()) {
+                var ctxt =  c.getOrAbsent("context")
+                        .map(v -> toByteArray(v.asString()))
+                        .orElse(new byte[0]);
                 var hashAlg = c.get("hashAlg").asString();
                 if (!hashAlg.equals("none") || ctxt.length != 0) {
                     continue; // Not supported
                 }
-                System.out.print(c.get("tcId").asString() + " ");
+                System.out.print(c.get("tcId").asInt() + " ");
                 var pk = new PublicKey() {
                     public String getAlgorithm() { return pname; }
                     public String getFormat() { return "RAW"; }
diff --git a/test/jdk/sun/security/provider/acvp/ML_KEM_Test.java b/test/jdk/sun/security/provider/acvp/ML_KEM_Test.java
index 35c1ce611da..5d969bc90ed 100644
--- a/test/jdk/sun/security/provider/acvp/ML_KEM_Test.java
+++ b/test/jdk/sun/security/provider/acvp/ML_KEM_Test.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -61,12 +61,12 @@ static void keyGenTest(JSONValue kat, Provider p) throws Exception {
         var f = p == null
                 ? KeyFactory.getInstance("ML-KEM")
                 : KeyFactory.getInstance("ML-KEM", p);
-        for (var t : kat.get("testGroups").asArray()) {
+        for (var t : kat.get("testGroups").elements()) {
             var pname = t.get("parameterSet").asString();
             var np = genParams(pname);
             System.out.println(">> " + pname);
-            for (var c : t.get("tests").asArray()) {
-                System.out.print(c.get("tcId").asString() + " ");
+            for (var c : t.get("tests").elements()) {
+                System.out.print(c.get("tcId").asInt() + " ");
                 var seed = toByteArray(c.get("d").asString() + c.get("z").asString());
                 g.initialize(np, new FixedSecureRandom(seed));
                 var kp = g.generateKeyPair();
@@ -84,13 +84,13 @@ static void encapDecapTest(JSONValue kat, Provider p) throws Exception {
         var g = p == null
                 ? KEM.getInstance("ML-KEM")
                 : KEM.getInstance("ML-KEM", p);
-        for (var t : kat.get("testGroups").asArray()) {
+        for (var t : kat.get("testGroups").elements()) {
             var pname = t.get("parameterSet").asString();
             var function = t.get("function").asString();
             System.out.println(">> " + pname + " " + function);
             if (function.equals("encapsulation")) {
-                for (var c : t.get("tests").asArray()) {
-                    System.out.print(c.get("tcId").asString() + " ");
+                for (var c : t.get("tests").elements()) {
+                    System.out.print(c.get("tcId").asInt() + " ");
                     var ek = new PublicKey() {
                         public String getAlgorithm() { return pname; }
                         public String getFormat() { return "RAW"; }
@@ -111,8 +111,8 @@ static void encapDecapTest(JSONValue kat, Provider p) throws Exception {
                     public String getFormat() { return "RAW"; }
                     public byte[] getEncoded() { return oct(toByteArray(t.get("dk").asString())); }
                 };
-                for (var c : t.get("tests").asArray()) {
-                    System.out.print(c.get("tcId").asString() + " ");
+                for (var c : t.get("tests").elements()) {
+                    System.out.print(c.get("tcId").asInt() + " ");
                     var d = g.newDecapsulator(dk);
                     var k = d.decapsulate(toByteArray(c.get("c").asString()));
                     Asserts.assertEqualsByteArray(toByteArray(c.get("k").asString()), k.getEncoded());
diff --git a/test/jdk/sun/security/provider/acvp/SHA_Test.java b/test/jdk/sun/security/provider/acvp/SHA_Test.java
index 4a64fb00c8c..9f68a583173 100644
--- a/test/jdk/sun/security/provider/acvp/SHA_Test.java
+++ b/test/jdk/sun/security/provider/acvp/SHA_Test.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -37,14 +37,14 @@ public static void run(JSONValue kat, Provider provider) throws Exception {
         if (alg.startsWith("SHA2-")) alg = "SHA-" + alg.substring(5);
         var md = provider == null ? MessageDigest.getInstance(alg)
                 : MessageDigest.getInstance(alg, provider);
-        for (var t : kat.get("testGroups").asArray()) {
+        for (var t : kat.get("testGroups").elements()) {
             var testType = t.get("testType").asString();
             switch (testType) {
                 case "AFT" -> {
-                    for (var c : t.get("tests").asArray()) {
-                        System.out.print(c.get("tcId").asString() + " ");
+                    for (var c : t.get("tests").elements()) {
+                        System.out.print(c.get("tcId").asInt() + " ");
                         var msg = toByteArray(c.get("msg").asString());
-                        var len = Integer.parseInt(c.get("len").asString());
+                        var len = c.get("len").asInt();
                         if (msg.length * 8 == len) {
                             Asserts.assertEqualsByteArray(
                                     toByteArray(c.get("md").asString()), md.digest(msg));
@@ -56,12 +56,12 @@ public static void run(JSONValue kat, Provider provider) throws Exception {
                 case "MCT" -> {
                     var mctVersion = t.get("mctVersion").asString();
                     var trunc = mctVersion.equals("alternate");
-                    for (var c : t.get("tests").asArray()) {
-                        System.out.print(c.get("tcId").asString() + " ");
+                    for (var c : t.get("tests").elements()) {
+                        System.out.print(c.get("tcId").asInt() + " ");
                         var SEED = toByteArray(c.get("msg").asString());
-                        var INITIAL_SEED_LENGTH = Integer.parseInt(c.get("len").asString());
+                        var INITIAL_SEED_LENGTH = c.get("len").asInt();
                         if (SEED.length * 8 == INITIAL_SEED_LENGTH) {
-                            for (var r : c.get("resultsArray").asArray()) {
+                            for (var r : c.get("resultsArray").elements()) {
                                 if (alg.startsWith("SHA3-")) {
                                     var MD = SEED;
                                     for (var i = 0; i < 1000; i++) {
@@ -99,12 +99,12 @@ public static void run(JSONValue kat, Provider provider) throws Exception {
                     }
                 }
                 case "LDT" -> {
-                    for (var c : t.get("tests").asArray()) {
-                        System.out.print(c.get("tcId").asString() + " ");
+                    for (var c : t.get("tests").elements()) {
+                        System.out.print(c.get("tcId").asInt() + " ");
                         var lm = c.get("largeMsg");
                         var ct = toByteArray(lm.get("content").asString());
-                        var flen = Long.parseLong(lm.get("fullLength").asString());
-                        var clen = Long.parseLong(lm.get("contentLength").asString());
+                        var flen = lm.get("fullLength").asLong();
+                        var clen = lm.get("contentLength").asLong();
                         var cc = 0L;
                         while (cc < flen) {
                             md.update(ct);
diff --git a/test/lib/jdk/test/lib/json/JSONValue.java b/test/lib/jdk/test/lib/json/JSONValue.java
index 72ed2fd917c..3ac6441b4c0 100644
--- a/test/lib/jdk/test/lib/json/JSONValue.java
+++ b/test/lib/jdk/test/lib/json/JSONValue.java
@@ -25,47 +25,55 @@
 import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Objects;
 import java.util.Optional;
 
-public interface JSONValue {
+public sealed interface JSONValue
+        permits JSONValue.JSONObject, JSONValue.JSONArray, JSONValue.JSONString,
+                JSONValue.JSONNumber, JSONValue.JSONBoolean, JSONValue.JSONNull {
 
     public final class JSONObject implements JSONValue {
-        private final Map value;
+        private final Map members;
 
-        public JSONObject(Map value) {
-            this.value = value;
+        private JSONObject(Map members) {
+            this.members = Map.copyOf(members);
         }
 
         @Override
-        public JSONObject asObject() {
-            return this;
+        public JSONValue get(String name) {
+            JSONValue v = members.get(name);
+            if (v == null) {
+                throw new NoSuchElementException("member " + name + " does not exist");
+            }
+            return v;
         }
 
-        public JSONValue get(String k) {
-            return value.get(k);
+        @Override
+        public Optional getOrAbsent(String name) {
+            return Optional.ofNullable(members.get(name));
         }
 
         @Override
-        public int size() {
-            return value.size();
+        public Map members() {
+            return members;
         }
 
         @Override
         public String toString() {
             var builder = new StringBuilder();
             builder.append("{");
-            for (var key : value.keySet()) {
+            for (String key : members.keySet()) {
                 builder.append("\"");
                 builder.append(key);
                 builder.append("\":");
-                builder.append(value.get(key).toString());
+                builder.append(members.get(key).toString());
                 builder.append(",");
             }
 
-            var end = builder.length() - 1;
+            int end = builder.length() - 1;
             if (builder.charAt(end) == ',') {
                 builder.deleteCharAt(end);
             }
@@ -73,13 +81,17 @@ public String toString() {
             builder.append("}");
             return builder.toString();
         }
+
+        public static JSONObject of(Map members) {
+            return new JSONObject(members);
+        }
     }
 
     public final class JSONString implements JSONValue {
         private final String value;
 
-        public JSONString(String value) {
-            this.value = value;
+        private JSONString(String value) {
+            this.value = Objects.requireNonNull(value);
         }
 
         @Override
@@ -129,26 +141,17 @@ public String toString() {
             builder.append("\"");
             return builder.toString();
         }
-    }
 
-    public final class JSONArray implements JSONValue, Iterable {
-        private final List values;
-
-        public JSONArray(List array) {
-            this.values = array;
-        }
-
-        @Override
-        public JSONArray asArray() {
-            return this;
+        public static JSONString of(String value) {
+            return new JSONString(value);
         }
+    }
 
-        public JSONValue get(int i) {
-            return values.get(i);
-        }
+    public final class JSONArray implements JSONValue {
+        private final List elements;
 
-        public int size() {
-            return values.size();
+        JSONArray(List elements) {
+            this.elements = List.copyOf(elements);
         }
 
         @Override
@@ -156,9 +159,10 @@ public String toString() {
             var builder = new StringBuilder();
 
             builder.append("[");
-            for (var i = 0; i < size(); i++) {
-                builder.append(get(i).toString());
-                if (i != (size() - 1)) {
+            int size = elements.size();
+            for (int i = 0; i < size; i++) {
+                builder.append(elements.get(i).toString());
+                if (i != (size - 1)) {
                     builder.append(",");
                 }
             }
@@ -167,13 +171,61 @@ public String toString() {
         }
 
         @Override
-        public Iterator iterator() {
-            return values.iterator();
+        public List elements() {
+            return elements;
         }
 
         @Override
-        public List elements() {
-            return List.copyOf(values);
+        public JSONValue element(int index) {
+            return elements.get(index);
+        }
+
+        public static JSONArray of(List elements) {
+            return new JSONArray(elements);
+        }
+    }
+
+    public final class JSONNumber implements JSONValue {
+        private final String value;
+
+        private JSONNumber(String value) {
+            this.value = Objects.requireNonNull(value);
+        }
+
+        @Override
+        public int asInt() {
+            return Integer.parseInt(value);
+        }
+
+        @Override
+        public long asLong() {
+            return Long.parseLong(value);
+        }
+
+        @Override
+        public double asDouble() {
+            return Double.parseDouble(value);
+        }
+
+        @Override
+        public String toString() {
+            return value;
+        }
+
+        public static JSONNumber of(String value) {
+            return new JSONNumber(value);
+        }
+
+        public static JSONNumber of(int value) {
+            return of(String.valueOf(value));
+        }
+
+        public static JSONNumber of(long value) {
+            return of(String.valueOf(value));
+        }
+
+        public static JSONNumber of(double value) {
+            return of(String.valueOf(value));
         }
     }
 
@@ -367,11 +419,10 @@ private JSONValue parseNumber() {
             var value = builder.toString();
             if (isInteger) {
                 new BigInteger(value);
-                return new JSONString(value);
             } else {
                 Double.parseDouble(value);
-                return new JSONString(value);
             }
+            return JSONNumber.of(value);
         }
 
         private JSONString parseString() {
@@ -422,7 +473,7 @@ private JSONString parseString() {
             }
 
             advance(); // step beyond closing "
-            return new JSONString(builder.toString());
+            return JSONString.of(builder.toString());
         }
 
         private JSONArray parseArray() {
@@ -445,7 +496,7 @@ private JSONArray parseArray() {
             }
 
             advance(); // step beyond closing ']'
-            return new JSONArray(list);
+            return JSONArray.of(list);
         }
 
         public JSONNull parseNull() {
@@ -486,7 +537,7 @@ public JSONObject parseObject() {
             }
 
             advance(); // step beyond '}'
-            return new JSONObject(map);
+            return JSONObject.of(map);
         }
 
         private boolean isDigit(char c) {
@@ -574,43 +625,51 @@ public JSONValue parse(String s) {
         }
     }
 
-    public static JSONValue parse(String s) {
+    static JSONValue parse(String s) {
         return new JSONParser().parse(s);
     }
 
-    default int size() {
-        throw new UnsupportedOperationException("Size operation unsupported");
+    default JSONValue get(String name) {
+        throw new UnsupportedOperationException("Unsupported conversion to object");
     }
 
-    default List elements() {
-        throw new UnsupportedOperationException("Unsupported conversion to array");
+    default Optional getOrAbsent(String name) {
+        throw new UnsupportedOperationException("Unsupported conversion to object");
     }
 
-    default String asString() {
-        throw new UnsupportedOperationException("Unsupported conversion to String");
+    default Optional valueOrNull() {
+        return Optional.of(this);
+    }
+
+    default Map members() {
+        throw new UnsupportedOperationException("Unsupported conversion to object");
     }
 
-    default JSONArray asArray() {
+    default List elements() {
         throw new UnsupportedOperationException("Unsupported conversion to array");
     }
 
-    default JSONObject asObject() {
-        throw new UnsupportedOperationException("Unsupported conversion to object");
+    default JSONValue element(int index) {
+        throw new UnsupportedOperationException("Unsupported conversion to array");
     }
 
-    default boolean asBoolean() {
-        throw new UnsupportedOperationException("Unsupported conversion to boolean");
+    default String asString() {
+        throw new UnsupportedOperationException("Unsupported conversion to string");
     }
 
-    default JSONValue get(String field) {
-        return asObject().get(field);
+    default int asInt() {
+        throw new UnsupportedOperationException("Unsupported conversion to number");
     }
 
-    default Optional getOrAbsent(String field) {
-        return Optional.ofNullable(get(field));
+    default long asLong() {
+        throw new UnsupportedOperationException("Unsupported conversion to number");
     }
 
-    default Optional valueOrNull() {
-        return Optional.of(this);
+    default double asDouble() {
+        throw new UnsupportedOperationException("Unsupported conversion to number");
+    }
+
+    default boolean asBoolean() {
+        throw new UnsupportedOperationException("Unsupported conversion to boolean");
     }
 }
diff --git a/test/lib/jdk/test/lib/threaddump/ThreadDump.java b/test/lib/jdk/test/lib/threaddump/ThreadDump.java
index 972d46675f4..77dd3dd8c03 100644
--- a/test/lib/jdk/test/lib/threaddump/ThreadDump.java
+++ b/test/lib/jdk/test/lib/threaddump/ThreadDump.java
@@ -50,9 +50,10 @@
  * 
{@code
  * {
  *   "threadDump": {
- *     "processId": "63406",
- *     "time": "2022-05-20T07:37:16.308017Z",
- *     "runtimeVersion": "19",
+ *     "formatVersion": 2,
+ *     "processId": 63406,
+ *     "time": "2026-03-25T09:20:08.591503Z",
+ *     "runtimeVersion": "27",
  *     "threadContainers": [
  *       {
  *         "container": "",
@@ -60,12 +61,12 @@
  *         "owner": null,
  *         "threads": [
  *          {
- *            "tid": "1",
+ *            "tid": 1,
  *            "name": "main",
  *            "stack": [...]
  *          },
  *          {
- *            "tid": "8",
+ *            "tid": 8,
  *            "name": "Reference Handler",
  *            "state": "RUNNABLE",
  *            "stack": [
@@ -80,21 +81,21 @@
  *          {"name": "Monitor Ctrl-Break"...},
  *          {"name": "Notification Thread"...}
  *         ],
- *         "threadCount": "7"
+ *         "threadCount": 7
  *       },
  *       {
  *         "container": "ForkJoinPool.commonPool\/jdk.internal.vm.SharedThreadContainer@56aac163",
  *         "parent": "",
  *         "owner": null,
  *         "threads": [...],
- *         "threadCount": "1"
+ *         "threadCount": 1
  *       },
  *       {
  *         "container": "java.util.concurrent.ThreadPoolExecutor@20322d26\/jdk.internal.vm.SharedThreadContainer@184f6be2",
  *         "parent": "",
  *         "owner": null,
  *         "threads": [...],
- *         "threadCount": "1"
+ *         "threadCount": 1
  *       }
  *     ]
  *   }
@@ -131,20 +132,6 @@ private ThreadDump(ThreadContainer rootThreadContainer,
         this.threadDumpObj = threadDumpObj;
     }
 
-    /**
-     * Assert that a JSONValue is a JSONString and parse the string as an int.
-     */
-    private static int parseStringAsInt(JSONValue valueObj) {
-        return Integer.parseInt(valueObj.asString());
-    }
-
-    /**
-     * Assert that a JSONValue is a JSONString and parse the string as a long.
-     */
-    private static long parseStringAsLong(JSONValue valueObj) {
-        return Long.parseLong(valueObj.asString());
-    }
-
     /**
      * Represents an element in the threadDump/threadContainers array.
      */
@@ -178,9 +165,9 @@ public String name() {
          * Return the thread identifier of the owner or empty OptionalLong if not owned.
          */
         public OptionalLong owner() {
-            return containerObj.get("owner")  // string or null
+            return containerObj.get("owner")  // number or null
                     .valueOrNull()
-                    .map(v -> OptionalLong.of(parseStringAsLong(v)))
+                    .map(v -> OptionalLong.of(v.asLong()))
                     .orElse(OptionalLong.empty());
         }
 
@@ -245,7 +232,7 @@ public static final class ThreadInfo {
         private final JSONValue threadObj;
 
         ThreadInfo(JSONValue threadObj) {
-            this.tid = parseStringAsLong(threadObj.get("tid"));
+            this.tid = threadObj.get("tid").asLong();
             this.threadObj = threadObj;
         }
 
@@ -293,7 +280,7 @@ public String parkBlocker() {
          */
         public OptionalLong parkBlockerOwner() {
             return threadObj.getOrAbsent("parkBlocker")
-                    .map(v -> OptionalLong.of(parseStringAsLong(v.get("owner"))))
+                    .map(v -> OptionalLong.of(v.get("owner").asLong()))
                     .orElse(OptionalLong.empty());
         }
 
@@ -334,7 +321,7 @@ public Map> ownedMonitors() {
                     .map(JSONValue::elements)
                     .orElse(List.of())
                     .forEach(e -> {
-                        int depth = parseStringAsInt(e.get("depth"));
+                        int depth = e.get("depth").asInt();
                         List locks = e.get("locks")
                                 .elements()
                                 .stream()
@@ -354,7 +341,7 @@ public Map> ownedMonitors() {
          */
         public OptionalLong carrier() {
             return threadObj.getOrAbsent("carrier")
-                    .map(s -> OptionalLong.of(parseStringAsLong(s)))
+                    .map(v -> OptionalLong.of(v.asLong()))
                     .orElse(OptionalLong.empty());
         }
 
@@ -389,8 +376,7 @@ public String toString() {
      * Returns the value of threadDump/processId.
      */
     public long processId() {
-        return parseStringAsLong(threadDumpObj.get("processId"));
-    }
+        return threadDumpObj.get("processId").asLong(); }
 
     /**
      * Returns the value of threadDump/time.
@@ -436,6 +422,10 @@ public Optional findThreadContainer(String name) {
      */
     public static ThreadDump parse(String json) {
         JSONValue threadDumpObj = JSONValue.parse(json).get("threadDump");
+        int formatVersion = threadDumpObj.get("formatVersion").asInt();
+        if (formatVersion != 2) {
+            fail("Format " + formatVersion + " not supported");
+        }
 
         // threadContainers array, preserve insertion order (parents are added before children)
         Map containerObjs = threadDumpObj.get("threadContainers")
@@ -444,7 +434,7 @@ public static ThreadDump parse(String json) {
                 .collect(Collectors.toMap(
                         c -> c.get("container").asString(),
                         Function.identity(),
-                        (a, b) -> { throw new RuntimeException("Duplicate container"); },
+                        (a, b) -> { fail("Duplicate container"); return null; },
                         LinkedHashMap::new
                 ));
 
@@ -456,7 +446,7 @@ public static ThreadDump parse(String json) {
             JSONValue parentObj = containerObj.get("parent");
             if (parentObj instanceof JSONValue.JSONNull) {
                 if (root != null) {
-                    throw new RuntimeException("More than one root container");
+                    fail("More than one root container");
                 }
                 root = new ThreadContainer(name, null, containerObj);
                 map.put(name, root);
@@ -464,7 +454,7 @@ public static ThreadDump parse(String json) {
                 String parentName = parentObj.asString();
                 ThreadContainer parent = map.get(parentName);
                 if (parent == null) {
-                    throw new RuntimeException("Thread container " + name + " found before " + parentName);
+                    fail("Thread container " + name + " found before " + parentName);
                 }
                 var container = new ThreadContainer(name, parent, containerObj);
                 parent.addChild(container);
@@ -472,9 +462,13 @@ public static ThreadDump parse(String json) {
             }
         }
         if (root == null) {
-            throw new RuntimeException("No root container");
+            fail("No root container");
         }
 
         return new ThreadDump(root, map, threadDumpObj);
     }
+
+    private static void fail(String message) {
+        throw new RuntimeException(message);
+    }
 }

From e582a3cb002868d27c48bcf029a01cc7733d0edb Mon Sep 17 00:00:00 2001
From: Martin Doerr 
Date: Tue, 31 Mar 2026 09:08:39 +0000
Subject: [PATCH 072/116] 8381315:
 compiler/vectorapi/TestVectorReallocation.java fails with -XX:UseAVX=1 after
 JDK-8380565

Reviewed-by: chagedorn, rrich
---
 test/hotspot/jtreg/ProblemList.txt                            | 1 -
 .../jtreg/compiler/vectorapi/TestVectorReallocation.java      | 4 ++--
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt
index 7580ce4d165..3b871d9f4b6 100644
--- a/test/hotspot/jtreg/ProblemList.txt
+++ b/test/hotspot/jtreg/ProblemList.txt
@@ -56,7 +56,6 @@ compiler/c2/irTests/TestDuplicateBackedge.java 8318904 generic-all
 
 compiler/codecache/jmx/PoolsIndependenceTest.java 8264632 macosx-all
 
-compiler/vectorapi/TestVectorReallocation.java 8381315 generic-x64
 compiler/vectorapi/reshape/TestVectorReinterpret.java 8320897,8348519 aix-ppc64,linux-ppc64le,linux-s390x
 compiler/vectorapi/VectorRebracket128Test.java 8330538 generic-all
 
diff --git a/test/hotspot/jtreg/compiler/vectorapi/TestVectorReallocation.java b/test/hotspot/jtreg/compiler/vectorapi/TestVectorReallocation.java
index 1bdc6ea726d..6b21b693d1e 100644
--- a/test/hotspot/jtreg/compiler/vectorapi/TestVectorReallocation.java
+++ b/test/hotspot/jtreg/compiler/vectorapi/TestVectorReallocation.java
@@ -301,7 +301,7 @@ float value() {
     }
 
     @Test
-    @IR(counts = {IRNode.ADD_VF, " >0 "})
+    @IR(counts = {IRNode.ADD_VF, IRNode.VECTOR_SIZE_ANY, " >0 "})
     void floatIdentityWithReallocation() {
         FloatVector v0 = FloatVector.fromArray(F_SPECIES, f_a, 0);
         float zeroSum = 0;
@@ -339,7 +339,7 @@ void doubleIdentityWithReallocation_runner(RunInfo runInfo) {
     }
 
     @Test
-    @IR(counts = {IRNode.ADD_VD, " >0 "})
+    @IR(counts = {IRNode.ADD_VD, IRNode.VECTOR_SIZE_ANY, " >0 "})
     void doubleIdentityWithReallocation() {
         DoubleVector v0 = DoubleVector.fromArray(D_SPECIES, d_a, 0);
         double zeroSum = 0;

From 6652d69fd551591518a3870691bc44ea597ea936 Mon Sep 17 00:00:00 2001
From: Kerem Kat 
Date: Tue, 31 Mar 2026 09:45:44 +0000
Subject: [PATCH 073/116] 8374497: C2: assert(verify(phase)) failed: missing
 Value() optimization with -XX:+StressReflectiveCode

Reviewed-by: dfenacci, snatarajan, qamai
---
 src/hotspot/share/opto/subtypenode.cpp        |  3 +-
 .../TestSubTypeCheckStressReflectiveCode.java | 42 +++++++++++++++++++
 2 files changed, 44 insertions(+), 1 deletion(-)
 create mode 100644 test/hotspot/jtreg/compiler/types/TestSubTypeCheckStressReflectiveCode.java

diff --git a/src/hotspot/share/opto/subtypenode.cpp b/src/hotspot/share/opto/subtypenode.cpp
index 69b7058d053..317b839fbd4 100644
--- a/src/hotspot/share/opto/subtypenode.cpp
+++ b/src/hotspot/share/opto/subtypenode.cpp
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved.
+ * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -177,7 +178,7 @@ bool SubTypeCheckNode::verify(PhaseGVN* phase) {
       return true;
     }
     const Type* cached_t = Value(phase); // cache the type to validate consistency
-    switch (C->static_subtype_check(superk, subk)) {
+    switch (C->static_subtype_check(superk, subk, false)) {
       case Compile::SSC_easy_test: {
         return verify_helper(phase, load_klass(phase), cached_t);
       }
diff --git a/test/hotspot/jtreg/compiler/types/TestSubTypeCheckStressReflectiveCode.java b/test/hotspot/jtreg/compiler/types/TestSubTypeCheckStressReflectiveCode.java
new file mode 100644
index 00000000000..5814a4a4b39
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/types/TestSubTypeCheckStressReflectiveCode.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8374497
+ * @summary SubTypeCheckNode::verify fails when StressReflectiveCode skips
+ *          static_subtype_check in verify() but not in sub()
+ * @run main/othervm -Xcomp -XX:CompileCommand=compileonly,*TimeZone::*
+ *                   -XX:+IgnoreUnrecognizedVMOptions -XX:+StressReflectiveCode
+ *                   ${test.main.class}
+ */
+
+package compiler.types;
+
+import java.util.TimeZone;
+
+public class TestSubTypeCheckStressReflectiveCode {
+    public static void main(String[] args) {
+        TimeZone.getDefault();
+    }
+}

From 46306d38ed4620480c66b6eded82985bdecb2218 Mon Sep 17 00:00:00 2001
From: Renjith Kannath Pariyangad 
Date: Tue, 31 Mar 2026 09:59:15 +0000
Subject: [PATCH 074/116] 8361493: RepaintManager.invalidComponents uses
 different equality when searching element

Co-authored-by: Alexey Ivanov 
Reviewed-by: aivanov, prr, serb, dmarkov
---
 .../classes/javax/swing/RepaintManager.java   |  8 +-
 .../RemoveInvalidComponentTest.java           | 96 +++++++++++++++++++
 2 files changed, 103 insertions(+), 1 deletion(-)
 create mode 100644 test/jdk/javax/swing/RepaintManager/RemoveInvalidComponentTest.java

diff --git a/src/java.desktop/share/classes/javax/swing/RepaintManager.java b/src/java.desktop/share/classes/javax/swing/RepaintManager.java
index b587cf2da84..ab21e555919 100644
--- a/src/java.desktop/share/classes/javax/swing/RepaintManager.java
+++ b/src/java.desktop/share/classes/javax/swing/RepaintManager.java
@@ -379,7 +379,13 @@ public synchronized void removeInvalidComponent(JComponent component) {
             return;
         }
         if (invalidComponents != null) {
-            invalidComponents.remove(component);
+            int n = invalidComponents.size();
+            for (int i = 0; i < n; i++) {
+                if (component == invalidComponents.get(i)) {
+                    invalidComponents.remove(i);
+                    break;
+                }
+            }
         }
     }
 
diff --git a/test/jdk/javax/swing/RepaintManager/RemoveInvalidComponentTest.java b/test/jdk/javax/swing/RepaintManager/RemoveInvalidComponentTest.java
new file mode 100644
index 00000000000..bd40bab4c43
--- /dev/null
+++ b/test/jdk/javax/swing/RepaintManager/RemoveInvalidComponentTest.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.RepaintManager;
+import javax.swing.SwingUtilities;
+
+/*
+ * @test
+ * @bug 8361493
+ * @key headful
+ * @summary Verifies that RepaintManager's removeInvalidComponent
+ *          remove wrong component
+ * @run main/othervm RemoveInvalidComponentTest
+ */
+public final class RemoveInvalidComponentTest {
+    private static volatile boolean isValidateCalled;
+
+    private static final class EqualLabel extends JLabel {
+
+        public EqualLabel(String text) {
+            super(text);
+        }
+
+        @Override
+        public void validate() {
+            System.out.println("validate called");
+            isValidateCalled = true;
+            super.validate();
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            return obj instanceof EqualLabel el
+                   && el.getText().equals(getText());
+        }
+
+        @Override
+        public boolean isValidateRoot() {
+            return true;
+        }
+    }
+
+    private static void runTest() {
+        final RepaintManager repaintManager = new RepaintManager();
+
+        JLabel label1 = new EqualLabel("label");
+        JLabel label2 = new EqualLabel("label");
+
+        if (!label1.equals(label2)) {
+            throw new RuntimeException("label1.equals(label2) returned false");
+        }
+
+        JFrame frame = new JFrame("RemoveInvalidComponentTest");
+
+        frame.add(label1);
+        frame.add(label2);
+
+        frame.setVisible(true);
+
+        repaintManager.addInvalidComponent(label1);
+        repaintManager.removeInvalidComponent(label2);
+        repaintManager.validateInvalidComponents();
+
+        frame.dispose();
+    }
+
+    public static void main(String[] args) throws Exception {
+        SwingUtilities.invokeAndWait(RemoveInvalidComponentTest::runTest);
+
+        if (!isValidateCalled) {
+            throw new RuntimeException("Label1 was removed from repaint manager");
+        }
+    }
+}

From f45b48ba9867984cb0247e378dff5d0c84b9e08a Mon Sep 17 00:00:00 2001
From: David Beaumont 
Date: Tue, 31 Mar 2026 10:00:03 +0000
Subject: [PATCH 075/116] 8380307: Refactor miscellaneous JAXP tests in
 javax/xml/jaxp/unittest to JUnit

Reviewed-by: liach, joehw
---
 .../parsers/ptests/FactoryConfErrorTest.java  |   3 -
 .../xml/transform/ptests/TransformTest.java   |   3 -
 .../validation/ptests/SchemaFactoryTest.java  |   4 -
 .../xml/jaxp/unittest/bcel/UtilityTest.java   |   9 +-
 .../catalog/CatalogFileInputTest.java         | 190 +++++------
 .../unittest/catalog/CatalogResolverTest.java |  51 +--
 .../unittest/catalog/CatalogReuseTest.java    |  56 ++--
 .../jaxp/unittest/catalog/CatalogSupport.java |  67 ++--
 .../unittest/catalog/CatalogSupport1.java     |  69 ++--
 .../unittest/catalog/CatalogSupport2.java     | 153 +++++----
 .../unittest/catalog/CatalogSupport3.java     | 151 +++++----
 .../unittest/catalog/CatalogSupport4.java     |  74 +++--
 .../unittest/catalog/CatalogSupport5.java     | 120 ++++---
 .../unittest/catalog/CatalogSupportBase.java  | 103 +++---
 .../jaxp/unittest/catalog/CatalogTest.java    | 273 ++++++++--------
 .../xml/jaxp/unittest/catalog/GroupTest.java  |  29 +-
 .../jaxp/unittest/datatype/Bug6320118.java    |  30 +-
 .../unittest/datatype/Bug6937951Test.java     |  18 +-
 .../unittest/datatype/Bug6937964Test.java     | 187 +++++------
 .../unittest/datatype/Bug7042647Test.java     |  18 +-
 .../datatype/DatatypeFactoryTest.java         |  68 ++--
 .../jaxp/unittest/datatype/DurationTest.java  | 264 +++++++---------
 .../unittest/datatype/FactoryFindTest.java    |  38 +--
 .../jaxp/unittest/datatype/HashCodeTest.java  |  53 ++--
 .../unittest/datatype/JDK8068839Test.java     |  13 +-
 .../datatype/XMLGregorianCalendarTest.java    | 111 +++----
 .../unittest/sax/Attributes2ImplTest.java     | 106 +++----
 .../xml/jaxp/unittest/sax/Bug6889654Test.java |  58 +---
 .../xml/jaxp/unittest/sax/Bug6925410Test.java |  35 +--
 .../xml/jaxp/unittest/sax/Bug6949607Test.java |  57 ++--
 .../xml/jaxp/unittest/sax/Bug6992561Test.java |  52 ++-
 .../xml/jaxp/unittest/sax/Bug7057778.xml      |   3 -
 .../xml/jaxp/unittest/sax/Bug7057778Test.java | 182 ++---------
 .../jaxp/unittest/sax/DeclarationTest.java    |  67 ++--
 .../unittest/sax/DefaultHandler2Test.java     | 296 +++++++-----------
 .../jaxp/unittest/sax/IssueTracker56Test.java |  99 ++----
 .../xml/jaxp/unittest/sax/NSSupportTest.java  |  93 +++---
 .../unittest/sax/SAXExceptionInitCause.java   |  74 +++--
 .../xml/jaxp/unittest/sax/SAXParserTest.java  |  58 ++--
 .../unittest/sax/SymbolTableResetTest.java    |  23 +-
 .../xml/jaxp/unittest/sax/XMLReaderTest.java  |  40 +--
 .../unittest/sbd/test/ExternalRefTest.java    |  21 +-
 42 files changed, 1477 insertions(+), 1942 deletions(-)
 delete mode 100644 test/jaxp/javax/xml/jaxp/unittest/sax/Bug7057778.xml

diff --git a/test/jaxp/javax/xml/jaxp/functional/javax/xml/parsers/ptests/FactoryConfErrorTest.java b/test/jaxp/javax/xml/jaxp/functional/javax/xml/parsers/ptests/FactoryConfErrorTest.java
index fe4288fc2b1..3ee91ff6555 100644
--- a/test/jaxp/javax/xml/jaxp/functional/javax/xml/parsers/ptests/FactoryConfErrorTest.java
+++ b/test/jaxp/javax/xml/jaxp/functional/javax/xml/parsers/ptests/FactoryConfErrorTest.java
@@ -26,8 +26,6 @@
 import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.parallel.Execution;
-import org.junit.jupiter.api.parallel.ExecutionMode;
 
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.FactoryConfigurationError;
@@ -44,7 +42,6 @@
  * @library /javax/xml/jaxp/libs
  * @run junit/othervm javax.xml.parsers.ptests.FactoryConfErrorTest
  */
-@Execution(ExecutionMode.SAME_THREAD)
 public class FactoryConfErrorTest {
 
     /**
diff --git a/test/jaxp/javax/xml/jaxp/functional/javax/xml/transform/ptests/TransformTest.java b/test/jaxp/javax/xml/jaxp/functional/javax/xml/transform/ptests/TransformTest.java
index 1d9600b330b..7ca7fc6c6d8 100644
--- a/test/jaxp/javax/xml/jaxp/functional/javax/xml/transform/ptests/TransformTest.java
+++ b/test/jaxp/javax/xml/jaxp/functional/javax/xml/transform/ptests/TransformTest.java
@@ -26,8 +26,6 @@
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.TestInstance;
 import org.junit.jupiter.api.TestInstance.Lifecycle;
-import org.junit.jupiter.api.parallel.Execution;
-import org.junit.jupiter.api.parallel.ExecutionMode;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.MethodSource;
 import org.w3c.dom.Document;
@@ -77,7 +75,6 @@
  * @summary Tests for variable combination of Transformer.transform(Source, Result)
  */
 @TestInstance(Lifecycle.PER_CLASS)
-@Execution(ExecutionMode.SAME_THREAD)
 public class TransformTest {
 
     /*
diff --git a/test/jaxp/javax/xml/jaxp/functional/javax/xml/validation/ptests/SchemaFactoryTest.java b/test/jaxp/javax/xml/jaxp/functional/javax/xml/validation/ptests/SchemaFactoryTest.java
index dc5acdfe1a3..e7ebdb973f3 100644
--- a/test/jaxp/javax/xml/jaxp/functional/javax/xml/validation/ptests/SchemaFactoryTest.java
+++ b/test/jaxp/javax/xml/jaxp/functional/javax/xml/validation/ptests/SchemaFactoryTest.java
@@ -22,13 +22,10 @@
  */
 package javax.xml.validation.ptests;
 
-import jaxp.library.JAXPDataProvider;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.TestInstance;
 import org.junit.jupiter.api.TestInstance.Lifecycle;
-import org.junit.jupiter.api.parallel.Execution;
-import org.junit.jupiter.api.parallel.ExecutionMode;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.MethodSource;
 import org.w3c.dom.Document;
@@ -78,7 +75,6 @@
  * @run junit/othervm javax.xml.validation.ptests.SchemaFactoryTest
  * @summary Class containing the test cases for SchemaFactory
  */
-@Execution(ExecutionMode.SAME_THREAD)
 @TestInstance(Lifecycle.PER_CLASS)
 public class SchemaFactoryTest {
 
diff --git a/test/jaxp/javax/xml/jaxp/unittest/bcel/UtilityTest.java b/test/jaxp/javax/xml/jaxp/unittest/bcel/UtilityTest.java
index 56545698778..020010628cf 100644
--- a/test/jaxp/javax/xml/jaxp/unittest/bcel/UtilityTest.java
+++ b/test/jaxp/javax/xml/jaxp/unittest/bcel/UtilityTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,14 +24,15 @@
 package bcel;
 
 import com.sun.org.apache.bcel.internal.classfile.Utility;
+import org.junit.jupiter.api.Test;
+
 import java.util.Base64;
-import org.testng.annotations.Test;
 
 /*
  * @test
  * @bug 8256919
  * @modules java.xml/com.sun.org.apache.bcel.internal.classfile
- * @run testng bcel.UtilityTest
+ * @run junit bcel.UtilityTest
  * @summary Tests the Utility.
  */
 public class UtilityTest {
@@ -42,7 +43,7 @@ public class UtilityTest {
      */
     @Test
     public void test() throws Exception {
-        /**
+        /*
          * public class Hello {
          *     public void hello(){
          *         System.out.println("Hello,world");
diff --git a/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogFileInputTest.java b/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogFileInputTest.java
index 9a19c0237d7..ece63b7e3f1 100644
--- a/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogFileInputTest.java
+++ b/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogFileInputTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,6 +23,24 @@
 
 package catalog;
 
+import com.sun.net.httpserver.HttpServer;
+import com.sun.net.httpserver.SimpleFileServer;
+import jdk.test.lib.net.URIBuilder;
+import jdk.test.lib.util.JarUtils;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInstance;
+import org.junit.jupiter.api.TestInstance.Lifecycle;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+import org.xml.sax.InputSource;
+
+import javax.xml.catalog.Catalog;
+import javax.xml.catalog.CatalogException;
+import javax.xml.catalog.CatalogFeatures;
+import javax.xml.catalog.CatalogManager;
+import javax.xml.catalog.CatalogResolver;
 import java.io.BufferedOutputStream;
 import java.io.BufferedReader;
 import java.io.BufferedWriter;
@@ -41,32 +59,18 @@
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 
-import javax.xml.catalog.Catalog;
-import javax.xml.catalog.CatalogException;
-import javax.xml.catalog.CatalogFeatures;
-import javax.xml.catalog.CatalogManager;
-import javax.xml.catalog.CatalogResolver;
-
 import static java.nio.file.StandardOpenOption.APPEND;
 import static java.nio.file.StandardOpenOption.CREATE;
-import static jaxp.library.JAXPTestUtilities.getSystemProperty;
-
-import com.sun.net.httpserver.HttpServer;
-import com.sun.net.httpserver.SimpleFileServer;
-import jdk.test.lib.net.URIBuilder;
-import jdk.test.lib.util.JarUtils;
-import org.testng.Assert;
-import org.testng.annotations.AfterClass;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
-import org.xml.sax.InputSource;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 
 /*
  * @test
  * @bug 8151154 8171243
  * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest /test/lib
- * @run testng/othervm catalog.CatalogFileInputTest
+ * @run junit/othervm catalog.CatalogFileInputTest
  * @summary Verifies that the Catalog API accepts valid URIs only;
  *          Verifies that the CatalogFeatures' builder throws
  *          IllegalArgumentException on invalid file inputs.
@@ -74,11 +78,12 @@
  *          JDK-8168968, it has to only run without SecurityManager
  *          because an ACE will be thrown for invalid path.
  */
+@TestInstance(Lifecycle.PER_CLASS)
 public class CatalogFileInputTest extends CatalogSupportBase {
 
     static final CatalogFeatures FEATURES = CatalogFeatures.builder().
             with(CatalogFeatures.Feature.PREFER, "system").build();
-    static String CLS_DIR = getSystemProperty("test.classes");
+    static String CLS_DIR = System.getProperty("test.classes");
     static String SRC_DIR = System.getProperty("test.src");
     static String JAR_CONTENT = "META-INF";
     final static String SCHEME_JARFILE = "jar:";
@@ -91,7 +96,7 @@ public class CatalogFileInputTest extends CatalogSupportBase {
     /*
      * Initializing fields
      */
-    @BeforeClass
+    @BeforeAll
     public void setUpClass() throws Exception {
         super.setUp();
         // set up HttpServer
@@ -107,7 +112,7 @@ public void setUpClass() throws Exception {
                 .build().toString() + REMOTE_FILE_LOCATION;
     }
 
-    @AfterClass
+    @AfterAll
     protected void tearDown() {
         if (httpserver != null) {
             httpserver.stop(0);
@@ -119,87 +124,86 @@ protected void tearDown() {
      * Verifies that the Catalog can be created with file system paths including JAR
      * and http URL, and used to resolve a systemId as expected.
      */
-    @Test(dataProvider = "acceptedURI")
-    public void testMatch(final String uri, final String sysId, final String pubId,
-            final String expectedId, final String msg) {
+    @ParameterizedTest
+    @MethodSource("acceptedURI")
+    public void testMatch(String uri, String sysId, String pubId, String expectedId, String msg) {
         CatalogResolver cr = CatalogManager.catalogResolver(FEATURES, URI.create(uri));
         InputSource is = cr.resolveEntity(pubId, sysId);
-        Assert.assertNotNull(is, msg);
-        Assert.assertEquals(expectedId, is.getSystemId(), msg);
+        assertNotNull(is, msg);
+        assertEquals(expectedId, is.getSystemId(), msg);
     }
 
-    @Test(dataProvider = "invalidCatalog")
-    public void testEmptyCatalog(final String uri, final String publicId, final String msg) {
+    @ParameterizedTest
+    @MethodSource("invalidCatalog")
+    public void testEmptyCatalog(String uri, String publicId, String msg) {
         Catalog c = CatalogManager.catalog(FEATURES, uri != null ? URI.create(uri) : null);
-        Assert.assertNull(c.matchSystem(publicId), msg);
+        assertNull(c.matchSystem(publicId), msg);
     }
 
-    @Test(dataProvider = "invalidCatalog", expectedExceptions = CatalogException.class)
-    public void testCatalogResolverWEmptyCatalog(final String uri, final String publicId, final String msg) {
+    @ParameterizedTest
+    @MethodSource("invalidCatalog")
+    public void testCatalogResolverWEmptyCatalog(String uri, String publicId, String msg) {
         CatalogResolver cr = CatalogManager.catalogResolver(
                 CatalogFeatures.builder().with(CatalogFeatures.Feature.RESOLVE, "strict").build(),
                 uri != null ? URI.create(uri) : null);
-        InputSource is = cr.resolveEntity(publicId, "");
+        assertThrows(CatalogException.class, () -> cr.resolveEntity(publicId, ""));
     }
 
-    @Test(dataProvider = "invalidCatalog")
-    public void testCatalogResolverWEmptyCatalog1(final String uri, final String publicId, final String msg) {
+    @ParameterizedTest
+    @MethodSource("invalidCatalog")
+    public void testCatalogResolverWEmptyCatalog1(String uri, String publicId, String msg) {
         CatalogResolver cr = CatalogManager.catalogResolver(
                 CatalogFeatures.builder().with(CatalogFeatures.Feature.RESOLVE, "continue").build(),
                 uri != null ? URI.create(uri) : null);
-        Assert.assertNull(cr.resolveEntity(publicId, ""), msg);
+        assertNull(cr.resolveEntity(publicId, ""), msg);
     }
 
-    @Test(dataProvider = "invalidInput", expectedExceptions = IllegalArgumentException.class)
-    public void testFileInput(final String file) {
-        CatalogFeatures features = CatalogFeatures.builder()
-            .with(CatalogFeatures.Feature.FILES, file)
-            .build();
+    @ParameterizedTest
+    @MethodSource("invalidInput")
+    public void testFileInput(String file) {
+        assertThrows(
+                IllegalArgumentException.class,
+                () -> CatalogFeatures.builder().with(CatalogFeatures.Feature.FILES, file));
     }
 
-    @Test(dataProvider = "invalidInput", expectedExceptions = IllegalArgumentException.class)
-    public void testInvalidUri(final String file) {
-        CatalogResolver cr = CatalogManager.catalogResolver(FEATURES, file != null ? URI.create(file) : null);
+    @ParameterizedTest
+    @MethodSource("invalidInput")
+    public void testInvalidUri(String file) {
+        URI uri = file != null ? URI.create(file) : null;
+        assertThrows(IllegalArgumentException.class, () -> CatalogManager.catalogResolver(FEATURES, uri));
     }
 
-    @Test(dataProvider = "invalidInput", expectedExceptions = IllegalArgumentException.class)
-    public void testInvalidUri1(final String file) {
-        Catalog c = CatalogManager.catalog(FEATURES, file != null ? URI.create(file) : null);
-        System.err.println("Catalog =" + c);
+    @ParameterizedTest
+    @MethodSource("invalidInput")
+    public void testInvalidUri1(String file) {
+        URI uri = file != null ? URI.create(file) : null;
+        assertThrows(IllegalArgumentException.class, () -> CatalogManager.catalog(FEATURES, uri));
     }
 
-
-    @Test(expectedExceptions = NullPointerException.class)
-    public void testNullFileInput() {
-        CatalogFeatures features = CatalogFeatures.builder()
-            .with(CatalogFeatures.Feature.FILES, null)
-            .build();
+    @Test
+    public void testNull() {
+        assertThrows(
+                NullPointerException.class,
+                () -> CatalogFeatures.builder().with(CatalogFeatures.Feature.FILES, null));
     }
 
-    @Test(expectedExceptions = NullPointerException.class)
+    @Test
     public void testNullUri() {
-        URI uri = null;
-        CatalogResolver cr = CatalogManager.catalogResolver(FEATURES, uri);
-    }
-
-    @Test(expectedExceptions = NullPointerException.class)
-    public void testNullUri1() {
-        URI uri = null;
-        Catalog c = CatalogManager.catalog(FEATURES, uri);
+        assertThrows(NullPointerException.class, () -> CatalogManager.catalogResolver(FEATURES, (URI) null));
+        assertThrows(NullPointerException.class, () -> CatalogManager.catalog(FEATURES, (URI) null));
     }
 
-    private String systemId = "http://www.sys00test.com/rewrite.dtd";
-    private String publicId = "PUB-404";
-    private String expected = "http://www.groupxmlbase.com/dtds/rewrite.dtd";
-    private String errMsg = "Relative rewriteSystem with xml:base at group level failed";
+    private static final String systemId = "http://www.sys00test.com/rewrite.dtd";
+    private static final String publicId = "PUB-404";
+    private static final String expected = "http://www.groupxmlbase.com/dtds/rewrite.dtd";
+    private static final String errMsg = "Relative rewriteSystem with xml:base at group level failed";
 
     /*
         DataProvider: used to verify CatalogResolver's resolveEntity function.
         Data columns:
         catalog, systemId, publicId, expectedUri, msg
      */
-    @DataProvider(name = "acceptedURI")
-    Object[][] getData() throws Exception {
+    Object[][] acceptedURI() throws IOException {
         String filename = "rewriteSystem_id.xml";
         String urlFile = getClass().getResource(filename).toExternalForm();
         String urlHttp = remoteFilePath + "/jax-ws-catalog.xml";
@@ -209,12 +213,7 @@ Object[][] getData() throws Exception {
         String xsd = jarPath.substring(0, jarPath.lastIndexOf("/")) + "/catalog/ws-addr.xsd";
 
         // create JAR file
-        try {
-            JarUtils.createJarFile(Paths.get(CLS_DIR + "/JDK8171243.jar"),
-                    Paths.get(SRC_DIR + "/jar"), JAR_CONTENT);
-        } catch (IOException ex) {
-            Assert.fail("Failed to create JAR: " + ex.getMessage());
-        }
+        JarUtils.createJarFile(Paths.get(CLS_DIR + "/JDK8171243.jar"), Paths.get(SRC_DIR + "/jar"), JAR_CONTENT);
 
         return new Object[][]{
             // URL
@@ -230,8 +229,7 @@ Object[][] getData() throws Exception {
      *  Note: the difference from invalidInput is that invalidInput is syntactically
      *  rejected with an IAE.
      */
-    @DataProvider(name = "invalidCatalog")
-    public Object[][] getInvalidCatalog() {
+    public Object[][] invalidCatalog() {
         String catalogUri = getClass().getResource("catalog_invalid.xml").toExternalForm();
         return new Object[][]{
             {catalogUri, "-//W3C//DTD XHTML 1.0 Strict//EN",
@@ -245,38 +243,24 @@ public Object[][] getInvalidCatalog() {
      *  DataProvider: a list of invalid inputs, expects IAE
      *  Note: exclude null since NPE would have been expected
      */
-    @DataProvider(name = "invalidInput")
-    public Object[][] getFiles() throws Exception {
+    public Object[][] invalidInput() throws Exception {
         String filename = "rewriteSystem_id.xml";
         copyFile(Paths.get(SRC_DIR + "/" + filename), Paths.get(filename));
         String absolutePath = getClass().getResource(filename).getFile();
 
-        return new Object[][]{
-            {""},
-            {"file:a/b\\c"},
-            {"c:/te:t"},
-            {"c:/te?t"},
-            {"c/te*t"},
-            {"in|valid.txt"},
-            {"shema:invalid.txt"},
-            // relative file path
-            {filename},
-            // absolute file path
-            {absolutePath}
-        };
-    }
-
-    /*
-       DataProvider: a list of invalid inputs
-     */
-    @DataProvider(name = "nullTest")
-    public Object[][] getNull() {
-        return new Object[][]{
-            {null},
+        return new Object[][] {
+                { "c:/te:t" },
+                { "c:/te?t" },
+                { "c/te*t" },
+                { "shema:invalid.txt" },
+                // relative file path
+                { filename },
+                // absolute file path
+                { absolutePath }
         };
     }
 
-    void copyFile(final Path src, final Path target) throws Exception {
+    private static void copyFile(final Path src, final Path target) throws Exception {
         try (InputStream in = Files.newInputStream(src);
                 BufferedReader reader
                 = new BufferedReader(new InputStreamReader(in));
diff --git a/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogResolverTest.java b/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogResolverTest.java
index 6ad23785b64..b4a2d20efcc 100644
--- a/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogResolverTest.java
+++ b/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogResolverTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,36 +22,41 @@
  */
 package catalog;
 
-import java.net.URI;
-import java.nio.file.Paths;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.TestInstance;
+import org.junit.jupiter.api.TestInstance.Lifecycle;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+import org.xml.sax.InputSource;
+
 import javax.xml.catalog.Catalog;
 import javax.xml.catalog.CatalogException;
 import javax.xml.catalog.CatalogFeatures;
 import javax.xml.catalog.CatalogManager;
 import javax.xml.catalog.CatalogResolver;
 import javax.xml.catalog.CatalogResolver.NotFoundAction;
-import org.testng.Assert;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
-import org.xml.sax.InputSource;
+import java.net.URI;
+import java.nio.file.Paths;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 
 /*
  * @test
  * @bug 8316996
  * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest
- * @run testng/othervm catalog.CatalogResolverTest
+ * @run junit/othervm catalog.CatalogResolverTest
  * @summary Tests CatalogResolver functions. See CatalogTest for existing basic
  * functional tests.
  */
+@TestInstance(Lifecycle.PER_CLASS)
 public class CatalogResolverTest extends CatalogSupportBase {
-    static final String KEY_FILES = "javax.xml.catalog.files";
     static final String SYSTEM_ID = "http://openjdk_java_net/xml/catalog/dtd/system.dtd";
 
     /*
      * Initializing fields
      */
-    @BeforeClass
+    @BeforeAll
     public void setUpClass() throws Exception {
         super.setUp();
     }
@@ -63,7 +68,6 @@ public void setUpClass() throws Exception {
         resolve property for the Catalog, resolve property for the CatalogResolver,
         system ID to be resolved, expected result, expected exception
      */
-    @DataProvider(name = "factoryMethodInput")
     public Object[][] getInputs() throws Exception {
 
         return new Object[][]{
@@ -80,7 +84,6 @@ public Object[][] getInputs() throws Exception {
          };
     }
 
-    @DataProvider(name = "NPETest")
     public Object[][] getNPETest() throws Exception {
         return new Object[][]{
             {null, null},
@@ -104,22 +107,22 @@ public Object[][] getNPETest() throws Exception {
      * @param expectedThrow the expected exception
      * @throws Exception if the test fails
      */
-    @Test(dataProvider = "factoryMethodInput")
+    @ParameterizedTest
+    @MethodSource("getInputs")
     public void testResolveProperty(String cResolve, NotFoundAction action,
             String systemId, String expectedResult, Class expectedThrow)
             throws Exception {
         Catalog c = getCatalog(cResolve);
 
         if (expectedThrow != null) {
-            Assert.assertThrows(expectedThrow,
-                () -> resolveRef(c, action, systemId));
+            assertThrows(expectedThrow, () -> resolveRef(c, action, systemId));
         } else {
-
             String sysId = resolveRef(c, action, systemId);
             System.out.println(sysId);
-            Assert.assertEquals(sysId,
-                    (expectedResult == null) ? null : Paths.get(filepath + expectedResult).toUri().toString().replace("///", "/"),
-                    "System ID match not right");
+            String expected = (expectedResult == null)
+                    ? null
+                    : Paths.get(filepath + expectedResult).toUri().toString().replace("///", "/");
+            assertEquals(expected, sysId, "System ID match not right");
         }
     }
 
@@ -127,9 +130,10 @@ public void testResolveProperty(String cResolve, NotFoundAction action,
      * Verifies that the catalogResolver method throws NullPointerException if
      * any of the parameters is null.
      */
-    @Test(dataProvider = "NPETest", expectedExceptions = NullPointerException.class)
+    @ParameterizedTest
+    @MethodSource("getNPETest")
     public void testCatalogProperty(Catalog c, NotFoundAction action) {
-        CatalogManager.catalogResolver(c, action);
+        assertThrows(NullPointerException.class, () -> CatalogManager.catalogResolver(c, action));
     }
 
     private String resolveRef(Catalog c, NotFoundAction action, String systemId) throws Exception {
@@ -140,9 +144,8 @@ private String resolveRef(Catalog c, NotFoundAction action, String systemId) thr
 
     private Catalog getCatalog(String cResolve) throws Exception {
         URI catalogFile = getClass().getResource("catalog.xml").toURI();
-        Catalog c = CatalogManager.catalog(
+        return CatalogManager.catalog(
                 CatalogFeatures.builder().with(CatalogFeatures.Feature.RESOLVE, cResolve).build(),
                 catalogFile);
-        return c;
     }
 }
diff --git a/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogReuseTest.java b/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogReuseTest.java
index 6bc563f3df3..fc4329fa198 100644
--- a/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogReuseTest.java
+++ b/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogReuseTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,22 +22,27 @@
  */
 package catalog;
 
-import java.net.URI;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.TestInstance;
+import org.junit.jupiter.api.TestInstance.Lifecycle;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+
 import javax.xml.catalog.Catalog;
 import javax.xml.catalog.CatalogFeatures;
 import javax.xml.catalog.CatalogManager;
-import org.testng.Assert;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
+import java.net.URI;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 /*
  * @test
  * @bug 8253569
  * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest
- * @run testng catalog.CatalogReuseTest
+ * @run junit catalog.CatalogReuseTest
  * @summary Verifies that a catalog can be reused.
  */
+@TestInstance(Lifecycle.PER_CLASS)
 public class CatalogReuseTest extends CatalogSupportBase {
     static final CatalogFeatures FEATURES_STRICT = CatalogFeatures.builder().
             with(CatalogFeatures.Feature.RESOLVE, "strict").build();
@@ -46,7 +51,6 @@ public class CatalogReuseTest extends CatalogSupportBase {
         DataProvider: reuses a catalog. The length of the URIs is in descending order.
         Data columns: catalog, uri, expected
      */
-    @DataProvider(name = "dataWithCatalogD")
     public Object[][] dataWithCatalogD() {
         Catalog c = getCatalog();
         return new Object[][]{
@@ -59,7 +63,6 @@ public Object[][] dataWithCatalogD() {
         DataProvider: reuses a catalog. The length of the URIs is in ascending order.
         Data columns: catalog, uri, expected
      */
-    @DataProvider(name = "dataWithCatalogA")
     public Object[][] dataWithCatalogA() {
         Catalog c = getCatalog();
         return new Object[][]{
@@ -72,18 +75,17 @@ public Object[][] dataWithCatalogA() {
         DataProvider: provides no catalog. A new catalog will be created for each test.
         Data columns: uri, expected
      */
-    @DataProvider(name = "dataWithoutCatalog")
     public Object[][] dataWithoutCatalog() {
-        return new Object[][]{
-            {"http://entailments/example.org/A/B/derived.ttl", "derived/A/B/derived.ttl"},
-            {"http://example.org/A/B.owl", "sources/A/B.owl"},
-         };
+        return new Object[][] {
+                { "http://entailments/example.org/A/B/derived.ttl", "derived/A/B/derived.ttl" },
+                { "http://example.org/A/B.owl", "sources/A/B.owl" },
+        };
     }
 
     /*
      * Initializing fields
      */
-    @BeforeClass
+    @BeforeAll
     public void setUpClass() throws Exception {
         super.setUp();
     }
@@ -91,36 +93,38 @@ public void setUpClass() throws Exception {
     /*
      * Verifies that a Catalog object can be reused, that no state data are
      * in the way of a subsequent matching attempt.
-    */
-    @Test(dataProvider = "dataWithCatalogD")
+     */
+    @ParameterizedTest
+    @MethodSource("dataWithCatalogD")
     public void testD(Catalog c, String uri, String expected) throws Exception {
         String m = c.matchURI(uri);
-        Assert.assertTrue(m.endsWith(expected), "Expected: " + expected);
+        assertTrue(m.endsWith(expected), "Expected: " + expected);
     }
 
     /*
      * Verifies that a Catalog object can be reused.
-    */
-    @Test(dataProvider = "dataWithCatalogA")
+     */
+    @ParameterizedTest
+    @MethodSource("dataWithCatalogA")
     public void testA(Catalog c, String uri, String expected) throws Exception {
         String m = c.matchURI(uri);
-        Assert.assertTrue(m.endsWith(expected), "Expected: " + expected);
+        assertTrue(m.endsWith(expected), "Expected: " + expected);
     }
 
     /*
      * Verifies that a match is found in a newly created Catalog.
-    */
-    @Test(dataProvider = "dataWithoutCatalog")
+     */
+    @ParameterizedTest
+    @MethodSource("dataWithoutCatalog")
     public void testNew(String uri, String expected) throws Exception {
         Catalog c = getCatalog();
         String m = c.matchURI(uri);
-        Assert.assertTrue(m.endsWith(expected), "Expected: " + expected);
+        assertTrue(m.endsWith(expected), "Expected: " + expected);
 
     }
 
     private Catalog getCatalog() {
         String uri = "file://" + slash + filepath + "/catalogReuse.xml";
-        Catalog c = CatalogManager.catalog(FEATURES_STRICT, uri != null? URI.create(uri) : null);
-        return c;
+        return CatalogManager.catalog(FEATURES_STRICT, URI.create(uri));
     }
 }
diff --git a/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogSupport.java b/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogSupport.java
index 4344bc1c623..1bd44d3c26b 100644
--- a/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogSupport.java
+++ b/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogSupport.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,8 +23,14 @@
 
 package catalog;
 
-import java.io.File;
-import java.io.StringReader;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.TestInstance;
+import org.junit.jupiter.api.TestInstance.Lifecycle;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+import org.w3c.dom.ls.LSResourceResolver;
+import org.xml.sax.InputSource;
+
 import javax.xml.stream.XMLResolver;
 import javax.xml.transform.Source;
 import javax.xml.transform.URIResolver;
@@ -32,17 +38,14 @@
 import javax.xml.transform.sax.SAXSource;
 import javax.xml.transform.stax.StAXSource;
 import javax.xml.transform.stream.StreamSource;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
-import org.w3c.dom.ls.LSResourceResolver;
-import org.xml.sax.InputSource;
+import java.io.File;
+import java.io.StringReader;
 
-/**
+/*
  * @test
  * @bug 8158084 8162438 8162442 8166220 8166398 8290740
  * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest
- * @run testng/othervm catalog.CatalogSupport
+ * @run junit/othervm catalog.CatalogSupport
  * @summary verifies the use of Catalog in SAX/DOM/StAX/Validation/Transform.
  * The two main scenarios for all processors are:
  * A custom resolver is used whether or not there's a Catalog;
@@ -51,12 +54,12 @@
 */
 
 /**
- * Support Catalog:
+ * 

Support Catalog:

* With this patch, the Catalog features are supported by all of the JAXP processors. * The support is enabled by default. Using Catalog is as simple as setting a * path to a catalog, through the API, or System property, or jaxp.properties. * - * Test notes: + *

Test notes:

* For all DataProviders, the 1st and 2nd columns determine whether to set USE_CATALOG * through the API and to use Catalog. When a custom resolver is specified, these * settings should not affect the operation, thus the tests are repeated for both @@ -64,11 +67,12 @@ * * @author huizhe.wang@oracle.com */ +@TestInstance(Lifecycle.PER_CLASS) public class CatalogSupport extends CatalogSupportBase { /* * Initializing fields */ - @BeforeClass + @BeforeAll public void setUpClass() throws Exception { setUp(); } @@ -76,7 +80,8 @@ public void setUpClass() throws Exception { /* Verifies the Catalog support on SAXParser. */ - @Test(dataProvider = "data_SAXA") + @ParameterizedTest + @MethodSource("getDataSAX") public void testSAXA(boolean setUseCatalog, boolean useCatalog, String catalog, String xml, MyHandler handler, String expected) throws Exception { testSAX(setUseCatalog, useCatalog, catalog, xml, handler, expected); @@ -85,7 +90,8 @@ public void testSAXA(boolean setUseCatalog, boolean useCatalog, String catalog, /* Verifies the Catalog support on XMLReader. */ - @Test(dataProvider = "data_SAXA") + @ParameterizedTest + @MethodSource("getDataSAX") public void testXMLReaderA(boolean setUseCatalog, boolean useCatalog, String catalog, String xml, MyHandler handler, String expected) throws Exception { testXMLReader(setUseCatalog, useCatalog, catalog, xml, handler, expected); @@ -94,7 +100,8 @@ public void testXMLReaderA(boolean setUseCatalog, boolean useCatalog, String cat /* Verifies the Catalog support on XInclude. */ - @Test(dataProvider = "data_XIA") + @ParameterizedTest + @MethodSource("getDataXI") public void testXIncludeA(boolean setUseCatalog, boolean useCatalog, String catalog, String xml, MyHandler handler, String expected) throws Exception { testXInclude(setUseCatalog, useCatalog, catalog, xml, handler, expected); @@ -104,7 +111,8 @@ public void testXIncludeA(boolean setUseCatalog, boolean useCatalog, String cata Verifies that the Catalog is used when the handler is null. The test shall run through without an Exception (that was thrown before the fix). */ - @Test(dataProvider = "data_XIA") + @ParameterizedTest + @MethodSource("getDataXI") public void testXIncludeA_NullHandler(boolean setUseCatalog, boolean useCatalog, String catalog, String xml, MyHandler handler, String expected) throws Exception { handler = null; @@ -114,7 +122,8 @@ public void testXIncludeA_NullHandler(boolean setUseCatalog, boolean useCatalog, /* Verifies the Catalog support on DOM parser. */ - @Test(dataProvider = "data_DOMA") + @ParameterizedTest + @MethodSource("getDataDOM") public void testDOMA(boolean setUseCatalog, boolean useCatalog, String catalog, String xml, MyHandler handler, String expected) throws Exception { testDOM(setUseCatalog, useCatalog, catalog, xml, handler, expected); @@ -123,7 +132,8 @@ public void testDOMA(boolean setUseCatalog, boolean useCatalog, String catalog, /* Verifies the Catalog support on XMLStreamReader. */ - @Test(dataProvider = "data_StAXA") + @ParameterizedTest + @MethodSource("getDataStAX") public void testStAXA(boolean setUseCatalog, boolean useCatalog, String catalog, String xml, XMLResolver resolver, String expected) throws Exception { testStAX(setUseCatalog, useCatalog, catalog, xml, resolver, expected); @@ -133,7 +143,8 @@ public void testStAXA(boolean setUseCatalog, boolean useCatalog, String catalog, Verifies the Catalog support on resolving DTD, xsd import and include in Schema files. */ - @Test(dataProvider = "data_SchemaA") + @ParameterizedTest + @MethodSource("getDataSchema") public void testValidationA(boolean setUseCatalog, boolean useCatalog, String catalog, String xsd, LSResourceResolver resolver) throws Exception { @@ -145,7 +156,8 @@ public void testValidationA(boolean setUseCatalog, boolean useCatalog, @bug 8158084 8162438 these tests also verifies the fix for 8162438 Verifies the Catalog support on the Schema Validator. */ - @Test(dataProvider = "data_ValidatorA") + @ParameterizedTest + @MethodSource("getDataValidator") public void testValidatorA(boolean setUseCatalog1, boolean setUseCatalog2, boolean useCatalog, Source source, LSResourceResolver resolver1, LSResourceResolver resolver2, String catalog1, String catalog2) @@ -158,7 +170,8 @@ public void testValidatorA(boolean setUseCatalog1, boolean setUseCatalog2, boole Verifies the Catalog support on resolving DTD, xsl import and include in XSL files. */ - @Test(dataProvider = "data_XSLA") + @ParameterizedTest + @MethodSource("getDataXSL") public void testXSLImportA(boolean setUseCatalog, boolean useCatalog, String catalog, SAXSource xsl, StreamSource xml, URIResolver resolver, String expected) throws Exception { @@ -171,7 +184,8 @@ public void testXSLImportA(boolean setUseCatalog, boolean useCatalog, String cat Verifies the Catalog support on resolving DTD, xsl import and include in XSL files. */ - @Test(dataProvider = "data_XSLA") + @ParameterizedTest + @MethodSource("getDataXSL") public void testXSLImportWTemplatesA(boolean setUseCatalog, boolean useCatalog, String catalog, SAXSource xsl, StreamSource xml, URIResolver resolver, String expected) throws Exception { @@ -182,7 +196,6 @@ public void testXSLImportWTemplatesA(boolean setUseCatalog, boolean useCatalog, DataProvider: for testing the SAX parser Data: set use_catalog, use_catalog, catalog file, xml file, handler, expected result string */ - @DataProvider(name = "data_SAXA") public Object[][] getDataSAX() { String[] systemIds = {"system.dtd"}; return new Object[][]{ @@ -198,7 +211,6 @@ public Object[][] getDataSAX() { DataProvider: for testing XInclude Data: set use_catalog, use_catalog, catalog file, xml file, handler, expected result string */ - @DataProvider(name = "data_XIA") public Object[][] getDataXI() { String[] systemIds = {"XI_simple.xml"}; InputSource[] returnValues = {new InputSource(xml_xIncludeSimple)}; @@ -214,7 +226,6 @@ public Object[][] getDataXI() { DataProvider: for testing DOM parser Data: set use_catalog, use_catalog, catalog file, xml file, handler, expected result string */ - @DataProvider(name = "data_DOMA") public Object[][] getDataDOM() { String[] systemIds = {"system.dtd"}; InputSource[] returnValues = {new InputSource(new StringReader(dtd_systemResolved))}; @@ -232,7 +243,6 @@ public Object[][] getDataDOM() { DataProvider: for testing the StAX parser Data: set use_catalog, use_catalog, catalog file, xml file, handler, expected result string */ - @DataProvider(name = "data_StAXA") public Object[][] getDataStAX() { return new Object[][]{ @@ -250,7 +260,6 @@ MyEntityHandler getMyEntityHandler(String elementName, String[] systemIds, Input DataProvider: for testing Schema validation Data: set use_catalog, use_catalog, catalog file, xsd file, a LSResourceResolver */ - @DataProvider(name = "data_SchemaA") public Object[][] getDataSchema() { String[] systemIds = {"pathto/XMLSchema.dtd", "datatypes.dtd"}; XmlInput[] returnValues = {new XmlInput(null, dtd_xmlSchema, null), new XmlInput(null, dtd_datatypes, null)}; @@ -285,7 +294,6 @@ public Object[][] getDataSchema() { DataProvider: for testing Schema Validator Data: source, resolver1, resolver2, catalog1, a catalog2 */ - @DataProvider(name = "data_ValidatorA") public Object[][] getDataValidator() { DOMSource ds = getDOMSource(xml_val_test, xml_val_test_id, false, true, xml_catalog); @@ -325,7 +333,6 @@ public Object[][] getDataValidator() { DataProvider: for testing XSL import and include Data: set use_catalog, use_catalog, catalog file, xsl file, xml file, a URIResolver, expected result */ - @DataProvider(name = "data_XSLA") public Object[][] getDataXSL() { // XSLInclude.xsl has one import XSLImport_html.xsl and two includes, // XSLInclude_header.xsl and XSLInclude_footer.xsl; diff --git a/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogSupport1.java b/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogSupport1.java index 2025e2d14d3..d8e7f8bb77e 100644 --- a/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogSupport1.java +++ b/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogSupport1.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,11 +23,14 @@ package catalog; -import static jaxp.library.JAXPTestUtilities.clearSystemProperty; -import static jaxp.library.JAXPTestUtilities.setSystemProperty; - -import java.io.File; -import java.io.StringReader; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.TestInstance.Lifecycle; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import org.w3c.dom.ls.LSResourceResolver; +import org.xml.sax.InputSource; import javax.xml.catalog.CatalogFeatures.Feature; import javax.xml.stream.XMLResolver; @@ -37,19 +40,14 @@ import javax.xml.transform.sax.SAXSource; import javax.xml.transform.stax.StAXSource; import javax.xml.transform.stream.StreamSource; - -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; -import org.w3c.dom.ls.LSResourceResolver; -import org.xml.sax.InputSource; +import java.io.File; +import java.io.StringReader; /* * @test * @bug 8158084 8162438 8162442 8166220 * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest - * @run testng/othervm catalog.CatalogSupport1 + * @run junit/othervm catalog.CatalogSupport1 * @summary extends CatalogSupport, verifies that the catalog file can be set * using the System property. */ @@ -60,25 +58,27 @@ * * @author huizhe.wang@oracle.com */ +@TestInstance(Lifecycle.PER_CLASS) public class CatalogSupport1 extends CatalogSupportBase { /* * Initializing fields */ - @BeforeClass + @BeforeAll public void setUpClass() throws Exception { setUp(); - setSystemProperty(Feature.FILES.getPropertyName(), xml_catalog); + System.setProperty(Feature.FILES.getPropertyName(), xml_catalog); } - @AfterClass + @AfterAll public void tearDownClass() throws Exception { - clearSystemProperty(Feature.FILES.getPropertyName()); + System.clearProperty(Feature.FILES.getPropertyName()); } /* Verifies the Catalog support on SAXParser. */ - @Test(dataProvider = "data_SAXC") + @ParameterizedTest + @MethodSource("getDataSAXC") public void testSAXC(boolean setUseCatalog, boolean useCatalog, String catalog, String xml, MyHandler handler, String expected) throws Exception { testSAX(setUseCatalog, useCatalog, catalog, xml, handler, expected); } @@ -86,7 +86,8 @@ public void testSAXC(boolean setUseCatalog, boolean useCatalog, String catalog, /* Verifies the Catalog support on XMLReader. */ - @Test(dataProvider = "data_SAXC") + @ParameterizedTest + @MethodSource("getDataSAXC") public void testXMLReaderC(boolean setUseCatalog, boolean useCatalog, String catalog, String xml, MyHandler handler, String expected) throws Exception { testXMLReader(setUseCatalog, useCatalog, catalog, xml, handler, expected); } @@ -94,7 +95,8 @@ public void testXMLReaderC(boolean setUseCatalog, boolean useCatalog, String cat /* Verifies the Catalog support on XInclude. */ - @Test(dataProvider = "data_XIC") + @ParameterizedTest + @MethodSource("getDataXIC") public void testXIncludeC(boolean setUseCatalog, boolean useCatalog, String catalog, String xml, MyHandler handler, String expected) throws Exception { testXInclude(setUseCatalog, useCatalog, catalog, xml, handler, expected); } @@ -102,7 +104,8 @@ public void testXIncludeC(boolean setUseCatalog, boolean useCatalog, String cata /* Verifies the Catalog support on DOM parser. */ - @Test(dataProvider = "data_DOMC") + @ParameterizedTest + @MethodSource("getDataDOMC") public void testDOMC(boolean setUseCatalog, boolean useCatalog, String catalog, String xml, MyHandler handler, String expected) throws Exception { testDOM(setUseCatalog, useCatalog, catalog, xml, handler, expected); } @@ -110,7 +113,8 @@ public void testDOMC(boolean setUseCatalog, boolean useCatalog, String catalog, /* Verifies the Catalog support on XMLStreamReader. */ - @Test(dataProvider = "data_StAXC") + @ParameterizedTest + @MethodSource("getDataStAX") public void testStAXC(boolean setUseCatalog, boolean useCatalog, String catalog, String xml, XMLResolver resolver, String expected) throws Exception { testStAX(setUseCatalog, useCatalog, catalog, xml, resolver, expected); @@ -120,7 +124,8 @@ public void testStAXC(boolean setUseCatalog, boolean useCatalog, String catalog, Verifies the Catalog support on resolving DTD, xsd import and include in Schema files. */ - @Test(dataProvider = "data_SchemaC") + @ParameterizedTest + @MethodSource("getDataSchemaC") public void testValidationC(boolean setUseCatalog, boolean useCatalog, String catalog, String xsd, LSResourceResolver resolver) throws Exception { @@ -131,7 +136,8 @@ public void testValidationC(boolean setUseCatalog, boolean useCatalog, String ca @bug 8158084 8162438 these tests also verifies the fix for 8162438 Verifies the Catalog support on the Schema Validator. */ - @Test(dataProvider = "data_ValidatorC") + @ParameterizedTest + @MethodSource("getDataValidator") public void testValidatorA(boolean setUseCatalog1, boolean setUseCatalog2, boolean useCatalog, Source source, LSResourceResolver resolver1, LSResourceResolver resolver2, String catalog1, String catalog2) @@ -144,7 +150,8 @@ public void testValidatorA(boolean setUseCatalog1, boolean setUseCatalog2, boole Verifies the Catalog support on resolving DTD, xsl import and include in XSL files. */ - @Test(dataProvider = "data_XSLC") + @ParameterizedTest + @MethodSource("getDataXSLC") public void testXSLImportC(boolean setUseCatalog, boolean useCatalog, String catalog, SAXSource xsl, StreamSource xml, URIResolver resolver, String expected) throws Exception { @@ -156,7 +163,8 @@ public void testXSLImportC(boolean setUseCatalog, boolean useCatalog, String cat Verifies the Catalog support on resolving DTD, xsl import and include in XSL files. */ - @Test(dataProvider = "data_XSLC") + @ParameterizedTest + @MethodSource("getDataXSLC") public void testXSLImportWTemplatesC(boolean setUseCatalog, boolean useCatalog, String catalog, SAXSource xsl, StreamSource xml, URIResolver resolver, String expected) throws Exception { testXSLImportWTemplates(setUseCatalog, useCatalog, catalog, xsl, xml, resolver, expected); @@ -166,7 +174,6 @@ public void testXSLImportWTemplatesC(boolean setUseCatalog, boolean useCatalog, DataProvider: for testing the SAX parser Data: set use_catalog, use_catalog, catalog file, xml file, handler, expected result string */ - @DataProvider(name = "data_SAXC") public Object[][] getDataSAXC() { return new Object[][]{ {false, true, null, xml_system, new MyHandler(elementInSystem), expectedWCatalog} @@ -178,7 +185,6 @@ public Object[][] getDataSAXC() { DataProvider: for testing XInclude Data: set use_catalog, use_catalog, catalog file, xml file, handler, expected result string */ - @DataProvider(name = "data_XIC") public Object[][] getDataXIC() { return new Object[][]{ {false, true, null, xml_xInclude, new MyHandler(elementInXISimple), contentInUIutf8Catalog}, @@ -189,7 +195,6 @@ public Object[][] getDataXIC() { DataProvider: for testing DOM parser Data: set use_catalog, use_catalog, catalog file, xml file, handler, expected result string */ - @DataProvider(name = "data_DOMC") public Object[][] getDataDOMC() { return new Object[][]{ {false, true, null, xml_system, new MyHandler(elementInSystem), expectedWCatalog} @@ -200,7 +205,6 @@ public Object[][] getDataDOMC() { DataProvider: for testing the StAX parser Data: set use_catalog, use_catalog, catalog file, xml file, handler, expected result string */ - @DataProvider(name = "data_StAXC") public Object[][] getDataStAX() { return new Object[][]{ @@ -212,7 +216,6 @@ public Object[][] getDataStAX() { DataProvider: for testing Schema validation Data: set use_catalog, use_catalog, catalog file, xsd file, a LSResourceResolver */ - @DataProvider(name = "data_SchemaC") public Object[][] getDataSchemaC() { return new Object[][]{ @@ -230,7 +233,6 @@ public Object[][] getDataSchemaC() { DataProvider: for testing Schema Validator Data: source, resolver1, resolver2, catalog1, a catalog2 */ - @DataProvider(name = "data_ValidatorC") public Object[][] getDataValidator() { DOMSource ds = getDOMSource(xml_val_test, xml_val_test_id, false, true, null); @@ -270,7 +272,6 @@ public Object[][] getDataValidator() { DataProvider: for testing XSL import and include Data: set use_catalog, use_catalog, catalog file, xsl file, xml file, a URIResolver, expected */ - @DataProvider(name = "data_XSLC") public Object[][] getDataXSLC() { SAXSource xslSourceDTD = new SAXSource(new InputSource(new StringReader(xsl_includeDTD))); StreamSource xmlSourceDTD = new StreamSource(new StringReader(xml_xslDTD)); diff --git a/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogSupport2.java b/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogSupport2.java index ecb88de1932..2346a8577b0 100644 --- a/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogSupport2.java +++ b/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogSupport2.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,13 +23,17 @@ package catalog; -import static jaxp.library.JAXPTestUtilities.clearSystemProperty; -import static jaxp.library.JAXPTestUtilities.getSystemProperty; -import static jaxp.library.JAXPTestUtilities.setSystemProperty; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.TestInstance.Lifecycle; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import org.w3c.dom.ls.LSResourceResolver; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; -import java.io.File; -import java.io.IOException; -import java.io.StringReader; import javax.xml.stream.XMLResolver; import javax.xml.stream.XMLStreamException; import javax.xml.transform.Source; @@ -39,21 +43,16 @@ import javax.xml.transform.sax.SAXSource; import javax.xml.transform.stax.StAXSource; import javax.xml.transform.stream.StreamSource; +import java.io.File; +import java.io.StringReader; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; -import org.w3c.dom.ls.LSResourceResolver; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; -import org.xml.sax.SAXParseException; +import static org.junit.jupiter.api.Assertions.assertThrows; /* * @test * @bug 8158084 8162438 8162442 8163535 8166220 8344800 * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest - * @run testng/othervm catalog.CatalogSupport2 + * @run junit/othervm catalog.CatalogSupport2 * @summary extends CatalogSupport tests, verifies that the use of the Catalog may * be disabled through the System property. */ @@ -65,108 +64,130 @@ * * @author huizhe.wang@oracle.com */ +@TestInstance(Lifecycle.PER_CLASS) public class CatalogSupport2 extends CatalogSupportBase { static final String TTIMEOUTREAD = "sun.net.client.defaultReadTimeout"; static final String TIMEOUTCONNECT = "sun.net.client.defaultConnectTimeout"; - static String timeoutRead = getSystemProperty(TTIMEOUTREAD); - static String timeoutConnect = getSystemProperty(TIMEOUTCONNECT); + static String timeoutRead = System.getProperty(TTIMEOUTREAD); + static String timeoutConnect = System.getProperty(TIMEOUTCONNECT); /* * Initializing fields */ - @BeforeClass + @BeforeAll public void setUpClass() throws Exception { setUp(); - setSystemProperty(SP_USE_CATALOG, "false"); - setSystemProperty(SP_ACCESS_EXTERNAL_DTD, "file"); - timeoutRead = getSystemProperty(TTIMEOUTREAD); - timeoutConnect = getSystemProperty(TIMEOUTCONNECT); - setSystemProperty(TTIMEOUTREAD, "1000"); - setSystemProperty(TIMEOUTCONNECT, "1000"); + System.setProperty(SP_USE_CATALOG, "false"); + System.setProperty(SP_ACCESS_EXTERNAL_DTD, "file"); + timeoutRead = System.getProperty(TTIMEOUTREAD); + timeoutConnect = System.getProperty(TIMEOUTCONNECT); + System.setProperty(TTIMEOUTREAD, "1000"); + System.setProperty(TIMEOUTCONNECT, "1000"); } - @AfterClass - public void tearDownClass() throws Exception { - clearSystemProperty(SP_USE_CATALOG); - clearSystemProperty(SP_ACCESS_EXTERNAL_DTD); - setSystemProperty(TIMEOUTCONNECT, "-1"); - setSystemProperty(TTIMEOUTREAD, "-1"); + @AfterAll + public void tearDownClass() { + System.clearProperty(SP_USE_CATALOG); + System.clearProperty(SP_ACCESS_EXTERNAL_DTD); + System.setProperty(TIMEOUTCONNECT, "-1"); + System.setProperty(TTIMEOUTREAD, "-1"); } /* Verifies the Catalog support on SAXParser. */ - @Test(dataProvider = "data_SAXC", expectedExceptions = SAXParseException.class) + @ParameterizedTest + @MethodSource("getDataSAXC") public void testSAXC(boolean setUseCatalog, boolean useCatalog, String catalog, String xml, MyHandler handler, String expected) throws Exception { - testSAX(setUseCatalog, useCatalog, catalog, xml, handler, expected); + assertThrows( + SAXParseException.class, + () -> testSAX(setUseCatalog, useCatalog, catalog, xml, handler, expected)); } /* Verifies the Catalog support on XMLReader. */ - @Test(dataProvider = "data_SAXC", expectedExceptions = SAXParseException.class) + @ParameterizedTest + @MethodSource("getDataSAXC") public void testXMLReaderC(boolean setUseCatalog, boolean useCatalog, String catalog, - String xml, MyHandler handler, String expected) throws Exception { - testXMLReader(setUseCatalog, useCatalog, catalog, xml, handler, expected); + String xml, MyHandler handler, String expected) throws Exception { + assertThrows( + SAXParseException.class, + () -> testXMLReader(setUseCatalog, useCatalog, catalog, xml, handler, expected)); } /* Verifies the Catalog support on XInclude. */ - @Test(dataProvider = "data_XIC", expectedExceptions = SAXParseException.class) + @ParameterizedTest + @MethodSource("getDataXIC") public void testXIncludeC(boolean setUseCatalog, boolean useCatalog, String catalog, - String xml, MyHandler handler, String expected) throws Exception { - testXInclude(setUseCatalog, useCatalog, catalog, xml, handler, expected); + String xml, MyHandler handler, String expected) throws Exception { + assertThrows( + SAXParseException.class, + () -> testXInclude(setUseCatalog, useCatalog, catalog, xml, handler, expected)); } /* Verifies the Catalog support on DOM parser. */ - @Test(dataProvider = "data_DOMC", expectedExceptions = SAXParseException.class) + @ParameterizedTest + @MethodSource("getDataDOMC") public void testDOMC(boolean setUseCatalog, boolean useCatalog, String catalog, - String xml, MyHandler handler, String expected) throws Exception { - testDOM(setUseCatalog, useCatalog, catalog, xml, handler, expected); + String xml, MyHandler handler, String expected) throws Exception { + assertThrows( + SAXParseException.class, + () -> testDOM(setUseCatalog, useCatalog, catalog, xml, handler, expected)); } /* Verifies the Catalog support on XMLStreamReader. */ - @Test(dataProvider = "data_StAXC", expectedExceptions = XMLStreamException.class) + @ParameterizedTest + @MethodSource("getDataStAX") public void testStAXC(boolean setUseCatalog, boolean useCatalog, String catalog, - String xml, XMLResolver resolver, String expected) throws Exception { - testStAXNegative(setUseCatalog, useCatalog, catalog, xml, resolver, expected); + String xml, XMLResolver resolver, String expected) throws Exception { + assertThrows( + XMLStreamException.class, + () -> testStAXNegative(setUseCatalog, useCatalog, catalog, xml, resolver, expected)); } /* Verifies the Catalog support on resolving DTD, xsd import and include in Schema files. */ - @Test(dataProvider = "data_SchemaC", expectedExceptions = SAXParseException.class) + @ParameterizedTest + @MethodSource("getDataSchemaC") public void testValidationC(boolean setUseCatalog, boolean useCatalog, String catalog, - String xsd, LSResourceResolver resolver) - throws Exception { - testValidation(setUseCatalog, useCatalog, catalog, xsd, resolver) ; + String xsd, LSResourceResolver resolver) { + assertThrows( + SAXParseException.class, + () -> testValidation(setUseCatalog, useCatalog, catalog, xsd, resolver)); } - @Test(dataProvider = "data_ValidatorC", expectedExceptions = {SAXException.class, IOException.class}) + @ParameterizedTest + @MethodSource("getDataValidator") public void testValidatorC(boolean setUseCatalog1, boolean setUseCatalog2, boolean useCatalog, - Source source, LSResourceResolver resolver1, LSResourceResolver resolver2, - String catalog1, String catalog2) - throws Exception { - testValidator(setUseCatalog1, setUseCatalog2, useCatalog, source, - resolver1, resolver2, catalog1, catalog2); + Source source, LSResourceResolver resolver1, LSResourceResolver resolver2, + String catalog1, String catalog2) { + assertThrows( + SAXException.class, + () -> testValidator(setUseCatalog1, setUseCatalog2, useCatalog, source, resolver1, resolver2, catalog1, catalog2)); } /* Verifies the Catalog support on resolving DTD, xsl import and include in XSL files. */ - @Test(dataProvider = "data_XSLC", expectedExceptions = TransformerException.class) + @ParameterizedTest + @MethodSource("getDataXSLC") public void testXSLImportC(boolean setUseCatalog, boolean useCatalog, String catalog, - SAXSource xsl, StreamSource xml, URIResolver resolver, String expected) throws Exception { + SAXSource xsl, StreamSource xml, URIResolver resolver, String expected) { - testXSLImport(setUseCatalog, useCatalog, catalog, xsl, xml, resolver, expected); + assertThrows( + TransformerException.class, + () -> testXSLImport(setUseCatalog, useCatalog, catalog, xsl, xml, resolver, expected)); } /* @@ -174,17 +195,19 @@ public void testXSLImportC(boolean setUseCatalog, boolean useCatalog, String cat Verifies the Catalog support on resolving DTD, xsl import and include in XSL files. */ - @Test(dataProvider = "data_XSLC", expectedExceptions = TransformerException.class) + @ParameterizedTest + @MethodSource("getDataXSLC") public void testXSLImportWTemplatesC(boolean setUseCatalog, boolean useCatalog, String catalog, - SAXSource xsl, StreamSource xml, URIResolver resolver, String expected) throws Exception { - testXSLImportWTemplates(setUseCatalog, useCatalog, catalog, xsl, xml, resolver, expected); + SAXSource xsl, StreamSource xml, URIResolver resolver, String expected) { + assertThrows( + TransformerException.class, + () -> testXSLImportWTemplates(setUseCatalog, useCatalog, catalog, xsl, xml, resolver, expected)); } /* DataProvider: for testing the SAX parser Data: set use_catalog, use_catalog, catalog file, xml file, handler, expected result string */ - @DataProvider(name = "data_SAXC") public Object[][] getDataSAXC() { return new Object[][]{ {false, true, xml_catalog, xml_system, new MyHandler(elementInSystem), expectedWCatalog} @@ -196,7 +219,6 @@ public Object[][] getDataSAXC() { DataProvider: for testing XInclude Data: set use_catalog, use_catalog, catalog file, xml file, handler, expected result string */ - @DataProvider(name = "data_XIC") public Object[][] getDataXIC() { return new Object[][]{ {false, true, xml_catalog, xml_xInclude, new MyHandler(elementInXISimple), contentInUIutf8Catalog}, @@ -207,7 +229,6 @@ public Object[][] getDataXIC() { DataProvider: for testing DOM parser Data: set use_catalog, use_catalog, catalog file, xml file, handler, expected result string */ - @DataProvider(name = "data_DOMC") public Object[][] getDataDOMC() { return new Object[][]{ {false, true, xml_catalog, xml_system, new MyHandler(elementInSystem), expectedWCatalog} @@ -218,7 +239,6 @@ public Object[][] getDataDOMC() { DataProvider: for testing the StAX parser Data: set use_catalog, use_catalog, catalog file, xml file, handler, expected result string */ - @DataProvider(name = "data_StAXC") public Object[][] getDataStAX() { return new Object[][]{ {false, true, xml_catalog, xml_system, null, "null"}, @@ -229,7 +249,6 @@ public Object[][] getDataStAX() { DataProvider: for testing Schema validation Data: set use_catalog, use_catalog, catalog file, xsd file, a LSResourceResolver */ - @DataProvider(name = "data_SchemaC") public Object[][] getDataSchemaC() { return new Object[][]{ @@ -247,7 +266,6 @@ public Object[][] getDataSchemaC() { DataProvider: for testing Schema Validator Data: source, resolver1, resolver2, catalog1, a catalog2 */ - @DataProvider(name = "data_ValidatorC") public Object[][] getDataValidator() { DOMSource ds = getDOMSource(xml_val_test, xml_val_test_id, true, true, xml_catalog); @@ -276,7 +294,6 @@ public Object[][] getDataValidator() { DataProvider: for testing XSL import and include Data: set use_catalog, use_catalog, catalog file, xsl file, xml file, a URIResolver, expected */ - @DataProvider(name = "data_XSLC") public Object[][] getDataXSLC() { SAXSource xslSourceDTD = new SAXSource(new InputSource(new StringReader(xsl_includeDTD))); StreamSource xmlSourceDTD = new StreamSource(new StringReader(xml_xslDTD)); diff --git a/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogSupport3.java b/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogSupport3.java index 4d44ce80fe6..cd06c2b6cba 100644 --- a/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogSupport3.java +++ b/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogSupport3.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,13 +23,17 @@ package catalog; -import static jaxp.library.JAXPTestUtilities.clearSystemProperty; -import static jaxp.library.JAXPTestUtilities.getSystemProperty; -import static jaxp.library.JAXPTestUtilities.setSystemProperty; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.TestInstance.Lifecycle; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import org.w3c.dom.ls.LSResourceResolver; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; -import java.io.File; -import java.io.IOException; -import java.io.StringReader; import javax.xml.stream.XMLResolver; import javax.xml.stream.XMLStreamException; import javax.xml.transform.Source; @@ -39,21 +43,16 @@ import javax.xml.transform.sax.SAXSource; import javax.xml.transform.stax.StAXSource; import javax.xml.transform.stream.StreamSource; +import java.io.File; +import java.io.StringReader; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; -import org.w3c.dom.ls.LSResourceResolver; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; -import org.xml.sax.SAXParseException; +import static org.junit.jupiter.api.Assertions.assertThrows; /* * @test * @bug 8158084 8162438 8162442 8163535 8166220 8344800 * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest - * @run testng/othervm catalog.CatalogSupport3 + * @run junit/othervm catalog.CatalogSupport3 * @summary extends CatalogSupport tests, verifies that the use of the Catalog may * be disabled through the API property. */ @@ -65,109 +64,131 @@ * * @author huizhe.wang@oracle.com */ +@TestInstance(Lifecycle.PER_CLASS) public class CatalogSupport3 extends CatalogSupportBase { static final String TTIMEOUTREAD = "sun.net.client.defaultReadTimeout"; static final String TIMEOUTCONNECT = "sun.net.client.defaultConnectTimeout"; - static String timeoutRead = getSystemProperty(TTIMEOUTREAD); - static String timeoutConnect = getSystemProperty(TIMEOUTCONNECT); + static String timeoutRead = System.getProperty(TTIMEOUTREAD); + static String timeoutConnect = System.getProperty(TIMEOUTCONNECT); /* * Initializing fields */ - @BeforeClass + @BeforeAll public void setUpClass() throws Exception { setUp(); - timeoutRead = getSystemProperty(TTIMEOUTREAD); - timeoutConnect = getSystemProperty(TIMEOUTCONNECT); - setSystemProperty(TTIMEOUTREAD, "1000"); - setSystemProperty(TIMEOUTCONNECT, "1000"); - setSystemProperty(SP_ACCESS_EXTERNAL_DTD, "file"); + timeoutRead = System.getProperty(TTIMEOUTREAD); + timeoutConnect = System.getProperty(TIMEOUTCONNECT); + System.setProperty(TTIMEOUTREAD, "1000"); + System.setProperty(TIMEOUTCONNECT, "1000"); + System.setProperty(SP_ACCESS_EXTERNAL_DTD, "file"); } - @AfterClass - public void tearDownClass() throws Exception { - setSystemProperty(TIMEOUTCONNECT, "-1"); - setSystemProperty(TTIMEOUTREAD, "-1"); - clearSystemProperty(SP_ACCESS_EXTERNAL_DTD); + @AfterAll + public void tearDownClass() { + System.setProperty(TIMEOUTCONNECT, "-1"); + System.setProperty(TTIMEOUTREAD, "-1"); + System.clearProperty(SP_ACCESS_EXTERNAL_DTD); } /* Verifies the Catalog support on SAXParser. */ - @Test(dataProvider = "data_SAXC", expectedExceptions = SAXParseException.class) + @ParameterizedTest + @MethodSource("getDataSAXC") public void testSAXC(boolean setUseCatalog, boolean useCatalog, String catalog, - String xml, MyHandler handler, String expected) throws Exception { - testSAX(setUseCatalog, useCatalog, catalog, xml, handler, expected); + String xml, MyHandler handler, String expected) { + assertThrows( + SAXParseException.class, + () -> testSAX(setUseCatalog, useCatalog, catalog, xml, handler, expected)); } /* Verifies the Catalog support on XMLReader. */ - @Test(dataProvider = "data_SAXC", expectedExceptions = SAXParseException.class) + @ParameterizedTest + @MethodSource("getDataSAXC") public void testXMLReaderC(boolean setUseCatalog, boolean useCatalog, String catalog, - String xml, MyHandler handler, String expected) throws Exception { - testXMLReader(setUseCatalog, useCatalog, catalog, xml, handler, expected); + String xml, MyHandler handler, String expected) { + assertThrows( + SAXParseException.class, + () -> testXMLReader(setUseCatalog, useCatalog, catalog, xml, handler, expected)); } /* Verifies the Catalog support on XInclude. */ - @Test(dataProvider = "data_XIC", expectedExceptions = SAXParseException.class) + @ParameterizedTest + @MethodSource("getDataXIC") public void testXIncludeC(boolean setUseCatalog, boolean useCatalog, String catalog, - String xml, MyHandler handler, String expected) throws Exception { - testXInclude(setUseCatalog, useCatalog, catalog, xml, handler, expected); + String xml, MyHandler handler, String expected) { + assertThrows( + SAXParseException.class, + () -> testXInclude(setUseCatalog, useCatalog, catalog, xml, handler, expected)); } /* Verifies the Catalog support on DOM parser. */ - @Test(dataProvider = "data_DOMC", expectedExceptions = SAXParseException.class) + @ParameterizedTest + @MethodSource("getDataDOMC") public void testDOMC(boolean setUseCatalog, boolean useCatalog, String catalog, - String xml, MyHandler handler, String expected) throws Exception { - testDOM(setUseCatalog, useCatalog, catalog, xml, handler, expected); + String xml, MyHandler handler, String expected) { + assertThrows( + SAXParseException.class, + () -> testDOM(setUseCatalog, useCatalog, catalog, xml, handler, expected)); } /* Verifies the Catalog support on XMLStreamReader. */ - @Test(dataProvider = "data_StAXC", expectedExceptions = XMLStreamException.class) + @ParameterizedTest + @MethodSource("getDataStAX") public void testStAXC(boolean setUseCatalog, boolean useCatalog, String catalog, - String xml, XMLResolver resolver, String expected) throws Exception { - testStAXNegative(setUseCatalog, useCatalog, catalog, xml, resolver, expected); + String xml, XMLResolver resolver, String expected) { + assertThrows( + XMLStreamException.class, + () -> testStAXNegative(setUseCatalog, useCatalog, catalog, xml, resolver, expected)); } /* Verifies the Catalog support on resolving DTD, xsd import and include in Schema files. */ - @Test(dataProvider = "data_SchemaC", expectedExceptions = SAXParseException.class) + @ParameterizedTest + @MethodSource("getDataSchemaC") public void testValidationC(boolean setUseCatalog, boolean useCatalog, String catalog, - String xsd, LSResourceResolver resolver) - throws Exception { - testValidation(setUseCatalog, useCatalog, catalog, xsd, resolver) ; + String xsd, LSResourceResolver resolver) { + assertThrows( + SAXParseException.class, + () -> testValidation(setUseCatalog, useCatalog, catalog, xsd, resolver)); } /* @bug 8158084 8162438 these tests also verifies the fix for 8162438 Verifies the Catalog support on the Schema Validator. */ - @Test(dataProvider = "data_ValidatorC", expectedExceptions = {SAXException.class, IOException.class}) + @ParameterizedTest + @MethodSource("getDataValidator") public void testValidatorC(boolean setUseCatalog1, boolean setUseCatalog2, boolean useCatalog, - Source source, LSResourceResolver resolver1, LSResourceResolver resolver2, - String catalog1, String catalog2) - throws Exception { - testValidator(setUseCatalog1, setUseCatalog2, useCatalog, source, - resolver1, resolver2, catalog1, catalog2); + Source source, LSResourceResolver resolver1, LSResourceResolver resolver2, + String catalog1, String catalog2) { + assertThrows( + SAXException.class, + () -> testValidator(setUseCatalog1, setUseCatalog2, useCatalog, source, resolver1, resolver2, catalog1, catalog2)); } /* Verifies the Catalog support on resolving DTD, xsl import and include in XSL files. */ - @Test(dataProvider = "data_XSLC", expectedExceptions = TransformerException.class) + @ParameterizedTest + @MethodSource("getDataXSLC") public void testXSLImportC(boolean setUseCatalog, boolean useCatalog, String catalog, SAXSource xsl, StreamSource xml, URIResolver resolver, String expected) throws Exception { - testXSLImport(setUseCatalog, useCatalog, catalog, xsl, xml, resolver, expected); + assertThrows( + TransformerException.class, + () -> testXSLImport(setUseCatalog, useCatalog, catalog, xsl, xml, resolver, expected)); } /* @@ -175,18 +196,20 @@ public void testXSLImportC(boolean setUseCatalog, boolean useCatalog, String cat Verifies the Catalog support on resolving DTD, xsl import and include in XSL files. */ - @Test(dataProvider = "data_XSLC", expectedExceptions = TransformerException.class) + @ParameterizedTest + @MethodSource("getDataXSLC") public void testXSLImportWTemplatesC(boolean setUseCatalog, boolean useCatalog, String catalog, - SAXSource xsl, StreamSource xml, - URIResolver resolver, String expected) throws Exception { - testXSLImportWTemplates(setUseCatalog, useCatalog, catalog, xsl, xml, resolver, expected); + SAXSource xsl, StreamSource xml, + URIResolver resolver, String expected) throws Exception { + assertThrows( + TransformerException.class, + () -> testXSLImportWTemplates(setUseCatalog, useCatalog, catalog, xsl, xml, resolver, expected)); } /* DataProvider: for testing the SAX parser Data: set use_catalog, use_catalog, catalog file, xml file, handler, expected result string */ - @DataProvider(name = "data_SAXC") public Object[][] getDataSAXC() { return new Object[][]{ {true, false, xml_catalog, xml_system, new MyHandler(elementInSystem), expectedWCatalog} @@ -198,7 +221,6 @@ public Object[][] getDataSAXC() { DataProvider: for testing XInclude Data: set use_catalog, use_catalog, catalog file, xml file, handler, expected result string */ - @DataProvider(name = "data_XIC") public Object[][] getDataXIC() { return new Object[][]{ {true, false, xml_catalog, xml_xInclude, new MyHandler(elementInXISimple), contentInUIutf8Catalog}, @@ -209,7 +231,6 @@ public Object[][] getDataXIC() { DataProvider: for testing DOM parser Data: set use_catalog, use_catalog, catalog file, xml file, handler, expected result string */ - @DataProvider(name = "data_DOMC") public Object[][] getDataDOMC() { return new Object[][]{ {true, false, xml_catalog, xml_system, new MyHandler(elementInSystem), expectedWCatalog} @@ -220,7 +241,6 @@ public Object[][] getDataDOMC() { DataProvider: for testing the StAX parser Data: set use_catalog, use_catalog, catalog file, xml file, handler, expected result string */ - @DataProvider(name = "data_StAXC") public Object[][] getDataStAX() { return new Object[][]{ {true, false, xml_catalog, xml_system, null, "null"}, @@ -231,7 +251,6 @@ public Object[][] getDataStAX() { DataProvider: for testing Schema validation Data: set use_catalog, use_catalog, catalog file, xsd file, a LSResourceResolver */ - @DataProvider(name = "data_SchemaC") public Object[][] getDataSchemaC() { return new Object[][]{ @@ -249,7 +268,6 @@ public Object[][] getDataSchemaC() { DataProvider: for testing Schema Validator Data: source, resolver1, resolver2, catalog1, a catalog2 */ - @DataProvider(name = "data_ValidatorC") public Object[][] getDataValidator() { DOMSource ds = getDOMSource(xml_val_test, xml_val_test_id, false, true, xml_catalog); @@ -287,7 +305,6 @@ public Object[][] getDataValidator() { DataProvider: for testing XSL import and include Data: set use_catalog, use_catalog, catalog file, xsl file, xml file, a URIResolver, expected */ - @DataProvider(name = "data_XSLC") public Object[][] getDataXSLC() { SAXSource xslSourceDTD = new SAXSource(new InputSource(new StringReader(xsl_includeDTD))); StreamSource xmlSourceDTD = new StreamSource(new StringReader(xml_xslDTD)); diff --git a/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogSupport4.java b/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogSupport4.java index 8d06cc61355..f666e198228 100644 --- a/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogSupport4.java +++ b/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogSupport4.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,11 +23,15 @@ package catalog; -import static jaxp.library.JAXPTestUtilities.clearSystemProperty; -import static jaxp.library.JAXPTestUtilities.setSystemProperty; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.TestInstance.Lifecycle; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import org.w3c.dom.ls.LSResourceResolver; +import org.xml.sax.InputSource; -import java.io.File; -import java.io.StringReader; import javax.xml.stream.XMLResolver; import javax.xml.transform.Source; import javax.xml.transform.URIResolver; @@ -35,19 +39,14 @@ import javax.xml.transform.sax.SAXSource; import javax.xml.transform.stax.StAXSource; import javax.xml.transform.stream.StreamSource; +import java.io.File; +import java.io.StringReader; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; -import org.w3c.dom.ls.LSResourceResolver; -import org.xml.sax.InputSource; - -/** +/* * @test * @bug 8158084 8162438 8162442 8166220 * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest - * @run testng/othervm catalog.CatalogSupport4 + * @run junit/othervm catalog.CatalogSupport4 * @summary verifies the overriding over of the USE_CATALOG feature. Extending * CatalogSupport tests, the USE_CATALOG is turned off system-wide, however, * a JAXP processor may decide to use Catalog by enabling it through the factory @@ -62,26 +61,28 @@ * * @author huizhe.wang@oracle.com */ +@TestInstance(Lifecycle.PER_CLASS) public class CatalogSupport4 extends CatalogSupportBase { /* * Initializing fields */ - @BeforeClass + @BeforeAll public void setUpClass() throws Exception { setUp(); //turn off USE_CATALOG system-wide - setSystemProperty(SP_USE_CATALOG, "false"); + System.setProperty(SP_USE_CATALOG, "false"); } - @AfterClass + @AfterAll public void tearDownClass() throws Exception { - clearSystemProperty(SP_USE_CATALOG); + System.clearProperty(SP_USE_CATALOG); } /* Verifies the Catalog support on SAXParser. */ - @Test(dataProvider = "data_SAXA") + @ParameterizedTest + @MethodSource("getDataSAX") public void testSAXA(boolean setUseCatalog, boolean useCatalog, String catalog, String xml, MyHandler handler, String expected) throws Exception { testSAX(setUseCatalog, useCatalog, catalog, xml, handler, expected); @@ -90,7 +91,8 @@ public void testSAXA(boolean setUseCatalog, boolean useCatalog, String catalog, /* Verifies the Catalog support on XMLReader. */ - @Test(dataProvider = "data_SAXA") + @ParameterizedTest + @MethodSource("getDataSAX") public void testXMLReaderA(boolean setUseCatalog, boolean useCatalog, String catalog, String xml, MyHandler handler, String expected) throws Exception { testXMLReader(setUseCatalog, useCatalog, catalog, xml, handler, expected); @@ -99,7 +101,8 @@ public void testXMLReaderA(boolean setUseCatalog, boolean useCatalog, String cat /* Verifies the Catalog support on XInclude. */ - @Test(dataProvider = "data_XIA") + @ParameterizedTest + @MethodSource("getDataXI") public void testXIncludeA(boolean setUseCatalog, boolean useCatalog, String catalog, String xml, MyHandler handler, String expected) throws Exception { testXInclude(setUseCatalog, useCatalog, catalog, xml, handler, expected); @@ -108,7 +111,8 @@ public void testXIncludeA(boolean setUseCatalog, boolean useCatalog, String cata /* Verifies the Catalog support on DOM parser. */ - @Test(dataProvider = "data_DOMA") + @ParameterizedTest + @MethodSource("getDataDOM") public void testDOMA(boolean setUseCatalog, boolean useCatalog, String catalog, String xml, MyHandler handler, String expected) throws Exception { testDOM(setUseCatalog, useCatalog, catalog, xml, handler, expected); @@ -117,7 +121,8 @@ public void testDOMA(boolean setUseCatalog, boolean useCatalog, String catalog, /* Verifies the Catalog support on XMLStreamReader. */ - @Test(dataProvider = "data_StAXA") + @ParameterizedTest + @MethodSource("getDataStAX") public void testStAXA(boolean setUseCatalog, boolean useCatalog, String catalog, String xml, XMLResolver resolver, String expected) throws Exception { testStAX(setUseCatalog, useCatalog, catalog, xml, resolver, expected); @@ -127,7 +132,8 @@ public void testStAXA(boolean setUseCatalog, boolean useCatalog, String catalog, Verifies the Catalog support on resolving DTD, xsd import and include in Schema files. */ - @Test(dataProvider = "data_SchemaA") + @ParameterizedTest + @MethodSource("getDataSchema") public void testValidationA(boolean setUseCatalog, boolean useCatalog, String catalog, String xsd, LSResourceResolver resolver) throws Exception { @@ -139,7 +145,8 @@ public void testValidationA(boolean setUseCatalog, boolean useCatalog, @bug 8158084 8162438 these tests also verifies the fix for 8162438 Verifies the Catalog support on the Schema Validator. */ - @Test(dataProvider = "data_ValidatorA") + @ParameterizedTest + @MethodSource("getDataValidator") public void testValidatorA(boolean setUseCatalog1, boolean setUseCatalog2, boolean useCatalog, Source source, LSResourceResolver resolver1, LSResourceResolver resolver2, String catalog1, String catalog2) @@ -152,7 +159,8 @@ public void testValidatorA(boolean setUseCatalog1, boolean setUseCatalog2, boole Verifies the Catalog support on resolving DTD, xsl import and include in XSL files. */ - @Test(dataProvider = "data_XSLA") + @ParameterizedTest + @MethodSource("getDataXSL") public void testXSLImportA(boolean setUseCatalog, boolean useCatalog, String catalog, SAXSource xsl, StreamSource xml, URIResolver resolver, String expected) throws Exception { @@ -165,7 +173,8 @@ public void testXSLImportA(boolean setUseCatalog, boolean useCatalog, String cat Verifies the Catalog support on resolving DTD, xsl import and include in XSL files. */ - @Test(dataProvider = "data_XSLA") + @ParameterizedTest + @MethodSource("getDataXSL") public void testXSLImportWTemplatesA(boolean setUseCatalog, boolean useCatalog, String catalog, SAXSource xsl, StreamSource xml, URIResolver resolver, String expected) throws Exception { @@ -176,7 +185,6 @@ public void testXSLImportWTemplatesA(boolean setUseCatalog, boolean useCatalog, DataProvider: for testing the SAX parser Data: set use_catalog, use_catalog, catalog file, xml file, handler, expected result string */ - @DataProvider(name = "data_SAXA") public Object[][] getDataSAX() { return new Object[][]{ {true, true, xml_catalog, xml_system, new MyHandler(elementInSystem), expectedWCatalog}, @@ -187,7 +195,6 @@ public Object[][] getDataSAX() { DataProvider: for testing XInclude Data: set use_catalog, use_catalog, catalog file, xml file, handler, expected result string */ - @DataProvider(name = "data_XIA") public Object[][] getDataXI() { return new Object[][]{ {true, true, xml_catalog, xml_xInclude, new MyHandler(elementInXISimple), contentInUIutf8Catalog}, @@ -198,7 +205,6 @@ public Object[][] getDataXI() { DataProvider: for testing DOM parser Data: set use_catalog, use_catalog, catalog file, xml file, handler, expected result string */ - @DataProvider(name = "data_DOMA") public Object[][] getDataDOM() { return new Object[][]{ {true, true, xml_catalog, xml_system, new MyHandler(elementInSystem), expectedWCatalog}, @@ -209,7 +215,6 @@ public Object[][] getDataDOM() { DataProvider: for testing the StAX parser Data: set use_catalog, use_catalog, catalog file, xml file, handler, expected result string */ - @DataProvider(name = "data_StAXA") public Object[][] getDataStAX() { return new Object[][]{ @@ -217,15 +222,10 @@ public Object[][] getDataStAX() { }; } - MyEntityHandler getMyEntityHandler(String elementName, String[] systemIds, InputSource... returnValues) { - return new MyEntityHandler(systemIds, returnValues, elementName); - } - /* DataProvider: for testing Schema validation Data: set use_catalog, use_catalog, catalog file, xsd file, a LSResourceResolver */ - @DataProvider(name = "data_SchemaA") public Object[][] getDataSchema() { return new Object[][]{ // for resolving DTD in xsd @@ -241,7 +241,6 @@ public Object[][] getDataSchema() { DataProvider: for testing Schema Validator Data: source, resolver1, resolver2, catalog1, a catalog2 */ - @DataProvider(name = "data_ValidatorA") public Object[][] getDataValidator() { DOMSource ds = getDOMSource(xml_val_test, xml_val_test_id, true, true, xml_catalog); @@ -270,7 +269,6 @@ public Object[][] getDataValidator() { DataProvider: for testing XSL import and include Data: set use_catalog, use_catalog, catalog file, xsl file, xml file, a URIResolver, expected result */ - @DataProvider(name = "data_XSLA") public Object[][] getDataXSL() { // XSLInclude.xsl has one import XSLImport_html.xsl and two includes, // XSLInclude_header.xsl and XSLInclude_footer.xsl; diff --git a/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogSupport5.java b/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogSupport5.java index 564848e2e1a..9a09fb9a45e 100644 --- a/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogSupport5.java +++ b/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogSupport5.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,8 +23,15 @@ package catalog; -import java.io.File; -import java.io.StringReader; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.TestInstance.Lifecycle; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import org.w3c.dom.ls.LSResourceResolver; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + import javax.xml.stream.XMLResolver; import javax.xml.stream.XMLStreamException; import javax.xml.transform.Source; @@ -34,19 +41,16 @@ import javax.xml.transform.sax.SAXSource; import javax.xml.transform.stax.StAXSource; import javax.xml.transform.stream.StreamSource; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; -import org.w3c.dom.ls.LSResourceResolver; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; +import java.io.File; +import java.io.StringReader; + +import static org.junit.jupiter.api.Assertions.assertThrows; /* * @test * @bug 8158084 8163232 8166220 * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest - * @run testng/othervm catalog.CatalogSupport5 + * @run junit/othervm catalog.CatalogSupport5 * @summary extends CatalogSupport tests, verifies that when errors occur, * relevant checked Exceptions are returned. */ @@ -58,12 +62,13 @@ * * @author huizhe.wang@oracle.com */ +@TestInstance(Lifecycle.PER_CLASS) public class CatalogSupport5 extends CatalogSupportBase { /* * Initializing fields */ - @BeforeClass + @BeforeAll public void setUpClass() throws Exception { setUp(); } @@ -72,77 +77,98 @@ public void setUpClass() throws Exception { /* Verifies the Catalog support on SAXParser. */ - @Test(dataProvider = "data_SAXC", expectedExceptions = SAXException.class) + @ParameterizedTest + @MethodSource("getDataSAXC") public void testSAXC(boolean setUseCatalog, boolean useCatalog, String catalog, String - xml, MyHandler handler, String expected) throws Exception { - testSAX(setUseCatalog, useCatalog, catalog, xml, handler, expected); + xml, MyHandler handler, String expected) { + assertThrows( + SAXException.class, + () -> testSAX(setUseCatalog, useCatalog, catalog, xml, handler, expected)); } /* Verifies the Catalog support on XMLReader. */ - @Test(dataProvider = "data_SAXC", expectedExceptions = SAXException.class) + @ParameterizedTest + @MethodSource("getDataSAXC") public void testXMLReaderC(boolean setUseCatalog, boolean useCatalog, String catalog, - String xml, MyHandler handler, String expected) throws Exception { - testXMLReader(setUseCatalog, useCatalog, catalog, xml, handler, expected); + String xml, MyHandler handler, String expected) { + assertThrows( + SAXException.class, + () -> testXMLReader(setUseCatalog, useCatalog, catalog, xml, handler, expected)); } /* Verifies the Catalog support on XInclude. */ - @Test(dataProvider = "data_XIC", expectedExceptions = SAXException.class) + @ParameterizedTest + @MethodSource("getDataXIC") public void testXIncludeC(boolean setUseCatalog, boolean useCatalog, String catalog, - String xml, MyHandler handler, String expected) throws Exception { - testXInclude(setUseCatalog, useCatalog, catalog, xml, handler, expected); + String xml, MyHandler handler, String expected) { + assertThrows( + SAXException.class, + () -> testXInclude(setUseCatalog, useCatalog, catalog, xml, handler, expected)); } /* Verifies the Catalog support on DOM parser. */ - @Test(dataProvider = "data_DOMC", expectedExceptions = SAXException.class) + @ParameterizedTest + @MethodSource("getDataDOMC") public void testDOMC(boolean setUseCatalog, boolean useCatalog, String catalog, - String xml, MyHandler handler, String expected) throws Exception { - testDOM(setUseCatalog, useCatalog, catalog, xml, handler, expected); + String xml, MyHandler handler, String expected) { + assertThrows( + SAXException.class, + () -> testDOM(setUseCatalog, useCatalog, catalog, xml, handler, expected)); } /* Verifies the Catalog support on XMLStreamReader. */ - @Test(dataProvider = "data_StAXC", expectedExceptions = XMLStreamException.class) + @ParameterizedTest + @MethodSource("getDataStAX") public void testStAXC(boolean setUseCatalog, boolean useCatalog, String catalog, - String xml, XMLResolver resolver, String expected) throws Exception { - testStAX(setUseCatalog, useCatalog, catalog, xml, resolver, expected); + String xml, XMLResolver resolver, String expected) { + assertThrows( + XMLStreamException.class, + () -> testStAX(setUseCatalog, useCatalog, catalog, xml, resolver, expected)); } /* Verifies the Catalog support on resolving DTD, xsd import and include in Schema files. */ - @Test(dataProvider = "data_SchemaC", expectedExceptions = SAXException.class) + @ParameterizedTest + @MethodSource("getDataSchemaC") public void testValidationC(boolean setUseCatalog, boolean useCatalog, String catalog, - String xsd, LSResourceResolver resolver) - throws Exception { - testValidation(setUseCatalog, useCatalog, catalog, xsd, resolver) ; + String xsd, LSResourceResolver resolver) { + assertThrows( + SAXException.class, + () -> testValidation(setUseCatalog, useCatalog, catalog, xsd, resolver)); } - @Test(dataProvider = "data_ValidatorC", expectedExceptions = SAXException.class) + @ParameterizedTest + @MethodSource("getDataValidator") public void testValidatorC(boolean setUseCatalog1, boolean setUseCatalog2, boolean useCatalog, - Source source, LSResourceResolver resolver1, LSResourceResolver resolver2, - String catalog1, String catalog2) - throws Exception { - testValidator(setUseCatalog1, setUseCatalog2, useCatalog, source, - resolver1, resolver2, catalog1, catalog2); + Source source, LSResourceResolver resolver1, LSResourceResolver resolver2, + String catalog1, String catalog2) { + assertThrows( + SAXException.class, + () -> testValidator(setUseCatalog1, setUseCatalog2, useCatalog, source, resolver1, resolver2, catalog1, catalog2)); } /* Verifies the Catalog support on resolving DTD, xsl import and include in XSL files. */ - @Test(dataProvider = "data_XSLC", expectedExceptions = TransformerException.class) + @ParameterizedTest + @MethodSource("getDataXSLC") public void testXSLImportC(boolean setUseCatalog, boolean useCatalog, String catalog, SAXSource xsl, StreamSource xml, URIResolver resolver, String expected) throws Exception { - testXSLImport(setUseCatalog, useCatalog, catalog, xsl, xml, resolver, expected); + assertThrows( + TransformerException.class, + () -> testXSLImport(setUseCatalog, useCatalog, catalog, xsl, xml, resolver, expected)); } /* @@ -150,17 +176,19 @@ public void testXSLImportC(boolean setUseCatalog, boolean useCatalog, String cat Verifies the Catalog support on resolving DTD, xsl import and include in XSL files. */ - @Test(dataProvider = "data_XSLC", expectedExceptions = TransformerException.class) + @ParameterizedTest + @MethodSource("getDataXSLC") public void testXSLImportWTemplatesC(boolean setUseCatalog, boolean useCatalog, String catalog, - SAXSource xsl, StreamSource xml, URIResolver resolver, String expected) throws Exception { - testXSLImportWTemplates(setUseCatalog, useCatalog, catalog, xsl, xml, resolver, expected); + SAXSource xsl, StreamSource xml, URIResolver resolver, String expected) throws Exception { + assertThrows( + TransformerException.class, + () -> testXSLImportWTemplates(setUseCatalog, useCatalog, catalog, xsl, xml, resolver, expected)); } /* DataProvider: for testing the SAX parser Data: set use_catalog, use_catalog, catalog file, xml file, handler, expected result string */ - @DataProvider(name = "data_SAXC") public Object[][] getDataSAXC() { return new Object[][]{ {false, true, xml_bogus_catalog, xml_system, new MyHandler(elementInSystem), expectedWCatalog} @@ -172,7 +200,6 @@ public Object[][] getDataSAXC() { DataProvider: for testing XInclude Data: set use_catalog, use_catalog, catalog file, xml file, handler, expected result string */ - @DataProvider(name = "data_XIC") public Object[][] getDataXIC() { return new Object[][]{ {false, true, xml_bogus_catalog, xml_xInclude, new MyHandler(elementInXISimple), contentInUIutf8Catalog}, @@ -183,7 +210,6 @@ public Object[][] getDataXIC() { DataProvider: for testing DOM parser Data: set use_catalog, use_catalog, catalog file, xml file, handler, expected result string */ - @DataProvider(name = "data_DOMC") public Object[][] getDataDOMC() { return new Object[][]{ {false, true, xml_bogus_catalog, xml_system, new MyHandler(elementInSystem), expectedWCatalog} @@ -194,7 +220,6 @@ public Object[][] getDataDOMC() { DataProvider: for testing the StAX parser Data: set use_catalog, use_catalog, catalog file, xml file, handler, expected result string */ - @DataProvider(name = "data_StAXC") public Object[][] getDataStAX() { return new Object[][]{ @@ -206,7 +231,6 @@ public Object[][] getDataStAX() { DataProvider: for testing Schema validation Data: set use_catalog, use_catalog, catalog file, xsd file, a LSResourceResolver */ - @DataProvider(name = "data_SchemaC") public Object[][] getDataSchemaC() { return new Object[][]{ @@ -224,7 +248,6 @@ public Object[][] getDataSchemaC() { Data: setUseCatalog1, setUseCatalog2, useCatalog, source, resolver1, resolver2, catalog1, catalog2 */ - @DataProvider(name = "data_ValidatorC") public Object[][] getDataValidator() { DOMSource ds = getDOMSource(xml_val_test, xml_val_test_id, true, true, xml_catalog); @@ -253,7 +276,6 @@ public Object[][] getDataValidator() { DataProvider: for testing XSL import and include Data: set use_catalog, use_catalog, catalog file, xsl file, xml file, a URIResolver, expected */ - @DataProvider(name = "data_XSLC") public Object[][] getDataXSLC() { SAXSource xslSourceDTD = new SAXSource(new InputSource(new StringReader(xsl_includeDTD))); StreamSource xmlSourceDTD = new StreamSource(new StringReader(xml_xslDTD)); diff --git a/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogSupportBase.java b/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogSupportBase.java index faa260b275e..52d0ccc8ce4 100644 --- a/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogSupportBase.java +++ b/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogSupportBase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,25 +23,17 @@ package catalog; -import static jaxp.library.JAXPTestUtilities.getSystemProperty; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.ls.LSInput; +import org.w3c.dom.ls.LSResourceResolver; +import org.xml.sax.Attributes; +import org.xml.sax.ErrorHandler; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; +import org.xml.sax.ext.DefaultHandler2; -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.io.Reader; -import java.io.StringReader; -import java.io.StringWriter; -import java.io.UnsupportedEncodingException; -import java.nio.file.Paths; -import java.security.CodeSource; -import java.security.Permission; -import java.security.PermissionCollection; -import java.security.Permissions; -import java.security.Policy; -import java.security.ProtectionDomain; import javax.xml.XMLConstants; import javax.xml.catalog.CatalogFeatures; import javax.xml.catalog.CatalogResolver; @@ -68,17 +60,26 @@ import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; import javax.xml.validation.Validator; -import org.testng.Assert; -import org.w3c.dom.Document; -import org.w3c.dom.Node; -import org.w3c.dom.ls.LSInput; -import org.w3c.dom.ls.LSResourceResolver; -import org.xml.sax.Attributes; -import org.xml.sax.ErrorHandler; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; -import org.xml.sax.XMLReader; -import org.xml.sax.ext.DefaultHandler2; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.io.StringReader; +import java.io.StringWriter; +import java.io.UnsupportedEncodingException; +import java.nio.file.Paths; +import java.security.CodeSource; +import java.security.Permission; +import java.security.PermissionCollection; +import java.security.Permissions; +import java.security.Policy; +import java.security.ProtectionDomain; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; /** * Base class: @@ -99,7 +100,7 @@ public class CatalogSupportBase { protected void setUp() { String file1 = getClass().getResource("CatalogSupport.xml").getFile(); - if (getSystemProperty("os.name").contains("Windows")) { + if (System.getProperty("os.name").contains("Windows")) { filepath = file1.substring(1, file1.lastIndexOf("/") + 1); slash = "/"; } else { @@ -285,7 +286,7 @@ public void testSAX(boolean setUseCatalog, boolean useCatalog, String catalog, SAXParser parser = getSAXParser(setUseCatalog, useCatalog, catalog); parser.parse(xml, handler); - Assert.assertEquals(handler.getResult().trim(), expected); + assertEquals(expected, handler.getResult().trim()); } /* @@ -298,7 +299,7 @@ public void testXMLReader(boolean setUseCatalog, boolean useCatalog, String cata reader.setContentHandler(handler); reader.setEntityResolver(handler); reader.parse(xml); - Assert.assertEquals(handler.getResult().trim(), expected); + assertEquals(expected, handler.getResult().trim()); } /* @@ -312,7 +313,7 @@ public void testXInclude(boolean setUseCatalog, boolean useCatalog, String catal // is thrown if handler == null. if (handler != null) { debugPrint("handler.result:" + handler.getResult()); - Assert.assertEquals(handler.getResult().trim(), expected); + assertEquals(expected, handler.getResult().trim()); } } @@ -327,7 +328,7 @@ public void testDOM(boolean setUseCatalog, boolean useCatalog, String catalog, Node node = doc.getElementsByTagName(elementInSystem).item(0); String result = node.getFirstChild().getTextContent(); - Assert.assertEquals(result.trim(), expected); + assertEquals(expected, result.trim()); } /* @@ -336,10 +337,10 @@ public void testDOM(boolean setUseCatalog, boolean useCatalog, String catalog, public void testStAX(boolean setUseCatalog, boolean useCatalog, String catalog, String xml, XMLResolver resolver, String expected) throws Exception { - XMLStreamReader streamReader = getStreamReader( - setUseCatalog, useCatalog, catalog, xml, resolver); - String text = getText(streamReader, XMLStreamConstants.CHARACTERS); - Assert.assertEquals(text.trim(), expected); + XMLStreamReader streamReader = getStreamReader( + setUseCatalog, useCatalog, catalog, xml, resolver); + String text = getText(streamReader, XMLStreamConstants.CHARACTERS); + assertEquals(expected, text.trim()); } /* @@ -349,10 +350,10 @@ public void testStAX(boolean setUseCatalog, boolean useCatalog, String catalog, public void testStAXNegative(boolean setUseCatalog, boolean useCatalog, String catalog, String xml, XMLResolver resolver, String expected) throws Exception { - XMLStreamReader streamReader = getStreamReader( - setUseCatalog, useCatalog, catalog, xml, resolver); - String text = getText(streamReader, XMLStreamConstants.ENTITY_REFERENCE); - Assert.assertEquals(text.trim(), expected); + XMLStreamReader streamReader = getStreamReader( + setUseCatalog, useCatalog, catalog, xml, resolver); + String text = getText(streamReader, XMLStreamConstants.ENTITY_REFERENCE); + assertEquals(expected, text.trim()); } /* @@ -381,7 +382,6 @@ public void testValidation(boolean setUseCatalog, boolean useCatalog, String cat } else { Schema schema = factory.newSchema(new StreamSource(new StringReader(xsd))); } - success("XMLSchema.dtd and datatypes.dtd are resolved."); } /** @@ -439,8 +439,7 @@ public void testXSLImport(boolean setUseCatalog, boolean useCatalog, String cata StringWriter out = new StringWriter(); transformer.transform(xml, new StreamResult(out)); - debugPrint("out:\n" + out.toString()); - Assert.assertTrue(out.toString().contains(expected), "testXSLImport"); + assertTrue(out.toString().contains(expected), "Output did not contain '" + expected + "':\n" + out); } /* @@ -455,7 +454,7 @@ public void testXSLImportWTemplates(boolean setUseCatalog, boolean useCatalog, Transformer transformer = factory.newTemplates(xsl).newTransformer(); StringWriter out = new StringWriter(); transformer.transform(xml, new StreamResult(out)); - Assert.assertTrue(out.toString().contains(expected), "testXSLImportWTemplates"); + assertTrue(out.toString().contains(expected), "Output did not contain '" + expected + "':\n" + out); } /** @@ -688,16 +687,6 @@ TransformerFactory getTransformerFactory(boolean setUseCatalog, boolean useCatal return factory; } - void fail(String msg) { - System.out.println("Test failed:"); - System.out.println(msg); - } - - void success(String msg) { - System.out.println("Test succeded:"); - System.out.println(msg); - } - void debugPrint(String msg) { if (debug) { System.out.println(msg); diff --git a/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogTest.java b/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogTest.java index 0c0e77bb952..1b2086f67b3 100644 --- a/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogTest.java +++ b/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,14 +22,19 @@ */ package catalog; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.StringReader; -import java.io.StringWriter; -import java.net.URI; -import java.nio.file.Paths; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.TestInstance.Lifecycle; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import org.xml.sax.Attributes; +import org.xml.sax.ErrorHandler; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; +import org.xml.sax.ext.DefaultHandler2; + import javax.xml.XMLConstants; import javax.xml.catalog.Catalog; import javax.xml.catalog.CatalogException; @@ -52,26 +57,29 @@ import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; import javax.xml.validation.Validator; -import static jaxp.library.JAXPTestUtilities.clearSystemProperty; -import static jaxp.library.JAXPTestUtilities.setSystemProperty; -import org.testng.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; -import org.xml.sax.Attributes; -import org.xml.sax.ErrorHandler; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; -import org.xml.sax.XMLReader; -import org.xml.sax.ext.DefaultHandler2; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.io.StringReader; +import java.io.StringWriter; +import java.net.URI; +import java.nio.file.Paths; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; /* * @test * @bug 8081248 8144966 8146606 8146237 8150969 8151162 8152527 8154220 8163232 * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest - * @run testng/othervm catalog.CatalogTest + * @run junit/othervm catalog.CatalogTest * @summary Tests basic Catalog functions. */ +@TestInstance(Lifecycle.PER_CLASS) public class CatalogTest extends CatalogSupportBase { static final String KEY_FILES = "javax.xml.catalog.files"; @@ -79,7 +87,7 @@ public class CatalogTest extends CatalogSupportBase { /* * Initializing fields */ - @BeforeClass + @BeforeAll public void setUpClass() throws Exception { super.setUp(); } @@ -98,8 +106,9 @@ public void setUpClass() throws Exception { /* * Verifies the support for org.xml.sax.EntityResolver. * Expected: the parser returns the expected string. - */ - @Test(dataProvider = "supportXMLResolver") + */ + @ParameterizedTest + @MethodSource("supportXMLResolver") public void supportEntityResolver(URI catalogFile, String xml, String expected) throws Exception { String xmlSource = getClass().getResource(xml).getFile(); @@ -108,14 +117,15 @@ public void supportEntityResolver(URI catalogFile, String xml, String expected) SAXParser parser = getSAXParser(false, true, null); parser.parse(xmlSource, handler); - Assert.assertEquals(handler.getResult().trim(), expected); + assertEquals(expected, handler.getResult().trim()); } /* * Verifies the support for javax.xml.stream.XMLResolver. * Expected: the parser returns the expected string. - */ - @Test(dataProvider = "supportXMLResolver") + */ + @ParameterizedTest + @MethodSource("supportXMLResolver") public void supportXMLResolver(URI catalogFile, String xml, String expected) throws Exception { String xmlSource = getClass().getResource(xml).getFile(); @@ -140,15 +150,16 @@ public void supportXMLResolver(URI catalogFile, String xml, String expected) thr } System.out.println(": expected [" + expected + "] <> actual [" + result.trim() + "]"); - Assert.assertEquals(result.trim(), expected); + assertEquals(expected, result.trim()); } /* * Verifies the support for org.w3c.dom.ls.LSResourceResolver by ShemaFactory. * Success: parsing goes through with no error * Fail: throws Exception if references are not resolved (by the CatalogResolver) - */ - @Test(dataProvider = "supportLSResourceResolver") + */ + @ParameterizedTest + @MethodSource("supportLSResourceResolver") public void supportLSResourceResolver(URI catalogFile, Source schemaSource) throws SAXException { CatalogResolver cr = CatalogManager.catalogResolver(CatalogFeatures.defaults(), catalogFile); @@ -163,8 +174,9 @@ public void supportLSResourceResolver(URI catalogFile, Source schemaSource) thro * Verifies the support for org.w3c.dom.ls.LSResourceResolver by Validator. * Success: parsing goes through with no error * Fail: throws Exception if references are not resolved (by the CatalogResolver) - */ - @Test(dataProvider = "supportLSResourceResolver1") + */ + @ParameterizedTest + @MethodSource("supportLSResourceResolver1") public void supportLSResourceResolver1(URI catalogFile, Source source) throws Exception { CatalogResolver cr = CatalogManager.catalogResolver(CatalogFeatures.defaults(), catalogFile); @@ -179,20 +191,21 @@ public void supportLSResourceResolver1(URI catalogFile, Source source) throws Ex * Verifies the support for javax.xml.transform.URIResolver. * Success: parsing goes through with no error * Fail: throws Exception if references are not resolved (by the CatalogResolver) - */ - @Test(dataProvider = "supportURIResolver") + */ + @ParameterizedTest + @MethodSource("supportURIResolver") public void supportURIResolver(URI catalogFile, Source xsl, Source xml, String expected) throws Exception { CatalogResolver cr = CatalogManager.catalogResolver(CatalogFeatures.defaults(), catalogFile); - TransformerFactory factory = TransformerFactory.newInstance(); - factory.setURIResolver(cr); - Transformer transformer = factory.newTransformer(xsl); - StringWriter out = new StringWriter(); - transformer.transform(xml, new StreamResult(out)); - if (expected != null) { - Assert.assertTrue(out.toString().contains(expected), "supportURIResolver"); - } + TransformerFactory factory = TransformerFactory.newInstance(); + factory.setURIResolver(cr); + Transformer transformer = factory.newTransformer(xsl); + StringWriter out = new StringWriter(); + transformer.transform(xml, new StreamResult(out)); + if (expected != null) { + assertTrue(out.toString().contains(expected), "supportURIResolver"); + } } /* @@ -200,7 +213,6 @@ public void supportURIResolver(URI catalogFile, Source xsl, Source xml, String e Data columns: catalog filepath, xml source file, expected result */ - @DataProvider(name = "supportXMLResolver") public Object[][] supportXMLResolver() throws Exception { URI catalogFile = getClass().getResource("catalog.xml").toURI(); URI catalogFileUri = getClass().getResource("catalog_uri.xml").toURI(); @@ -228,7 +240,6 @@ public Object[][] supportXMLResolver() throws Exception { Data columns: catalog filepath, schema source file */ - @DataProvider(name = "supportLSResourceResolver") public Object[][] supportLSResourceResolver() throws Exception { URI catalogFile = getClass().getResource("CatalogSupport.xml").toURI(); URI catalogFileUri = getClass().getResource("CatalogSupport_uri.xml").toURI(); @@ -252,7 +263,6 @@ public Object[][] supportLSResourceResolver() throws Exception { Data columns: catalog filepath, source file */ - @DataProvider(name = "supportLSResourceResolver1") public Object[][] supportLSResourceResolver1() throws Exception { URI catalogFile = getClass().getResource("CatalogSupport.xml").toURI(); URI catalogFileUri = getClass().getResource("CatalogSupport_uri.xml").toURI(); @@ -275,7 +285,6 @@ public Object[][] supportLSResourceResolver1() throws Exception { Data columns: catalog filepath, xsl source, xml source file */ - @DataProvider(name = "supportURIResolver") public Object[][] supportURIResolver() throws Exception { URI catalogFile = getClass().getResource("CatalogSupport.xml").toURI(); URI catalogFileUri = getClass().getResource("CatalogSupport_uri.xml").toURI(); @@ -303,10 +312,12 @@ public Object[][] supportURIResolver() throws Exception { * requires a system identifier on all external entities, so this value is * always specified. */ - @Test(expectedExceptions = NullPointerException.class) + @Test public void sysIdCantBeNull() { CatalogResolver catalogResolver = CatalogManager.catalogResolver(CatalogFeatures.defaults()); - InputSource is = catalogResolver.resolveEntity("-//FOO//DTD XML Dummy V0.0//EN", null); + assertThrows( + NullPointerException.class, + () -> catalogResolver.resolveEntity("-//FOO//DTD XML Dummy V0.0//EN", null)); } /* @@ -318,14 +329,15 @@ public void sysIdCantBeNull() { * copying the JCK test and its dataProvider. This test may be reused for * other cases in that test. */ - @Test(dataProvider = "resolveUri") + @ParameterizedTest + @MethodSource("getDataForUriResolver") public void testMatch1(String cFile, String href, String expectedFile, String expectedUri, String msg) throws Exception { URI catalogFile = getClass().getResource(cFile).toURI(); CatalogResolver cur = CatalogManager.catalogResolver(CatalogFeatures.defaults(), catalogFile); Source source = cur.resolve(href, null); - Assert.assertNotNull(source, "Source returned is null"); - Assert.assertEquals(expectedUri, source.getSystemId(), msg); + assertNotNull(source, "Source returned is null"); + assertEquals(expectedUri, source.getSystemId(), msg); } /* @@ -333,20 +345,21 @@ public void testMatch1(String cFile, String href, String expectedFile, * Verifies that the file input is validated properly. Valid input includes * multiple file paths separated by semicolon. */ - @Test(dataProvider = "hierarchyOfCatFilesData") + @ParameterizedTest + @MethodSource("getHierarchyOfCatFilesData") public void hierarchyOfCatFiles2(String systemId, String expectedUri) { String file1 = getClass().getResource("first_cat.xml").toExternalForm(); String file2 = getClass().getResource("second_cat.xml").toExternalForm(); String files = file1 + ";" + file2; try { - setSystemProperty(KEY_FILES, files); + System.setProperty(KEY_FILES, files); CatalogResolver catalogResolver = CatalogManager.catalogResolver(CatalogFeatures.defaults()); - String sysId = catalogResolver.resolveEntity(null, systemId).getSystemId(); - Assert.assertEquals(sysId, Paths.get(filepath + expectedUri).toUri().toString().replace("///", "/"), - "System ID match not right"); + String actualSysId = catalogResolver.resolveEntity(null, systemId).getSystemId(); + String expectedSysId = Paths.get(filepath + expectedUri).toUri().toString().replace("///", "/"); + assertEquals(expectedSysId, actualSysId, "System ID match not right"); } finally { - clearSystemProperty(KEY_FILES); + System.clearProperty(KEY_FILES); } } @@ -357,16 +370,17 @@ public void hierarchyOfCatFiles2(String systemId, String expectedUri) { * Verifies that the CatalogResolver resolves a publicId and/or systemId as * expected. */ - @Test(dataProvider = "resolveEntity") + @ParameterizedTest + @MethodSource("getDataForMatchingBothIds") public void testMatch1(String cfile, String prefer, String sysId, String pubId, String expectedUri, String expectedFile, String msg) throws Exception { URI catalogFile = getClass().getResource(cfile).toURI(); CatalogFeatures features = CatalogFeatures.builder().with(CatalogFeatures.Feature.PREFER, prefer).build(); CatalogResolver catalogResolver = CatalogManager.catalogResolver(features, catalogFile); InputSource is = catalogResolver.resolveEntity(pubId, sysId); - Assert.assertNotNull(is, msg); + assertNotNull(is, msg); String expected = (expectedUri == null) ? expectedFile : expectedUri; - Assert.assertEquals(expected, is.getSystemId(), msg); + assertEquals(expected, is.getSystemId(), msg); } /* @@ -374,7 +388,8 @@ public void testMatch1(String cfile, String prefer, String sysId, String pubId, * Verifies that the Catalog matches specified publicId or systemId and returns * results as expected. */ - @Test(dataProvider = "matchWithPrefer") + @ParameterizedTest + @MethodSource("getDataForMatch") public void matchWithPrefer(String prefer, String cfile, String publicId, String systemId, String expected) throws Exception { URI catalogFile = getClass().getResource(cfile).toURI(); @@ -387,7 +402,7 @@ public void matchWithPrefer(String prefer, String cfile, String publicId, } else { result = c.matchSystem(systemId); } - Assert.assertEquals(expected, result); + assertEquals(expected, result); } /* @@ -401,7 +416,8 @@ public void matchWithPrefer(String prefer, String cfile, String publicId, * attempts to resolve with a public entry if no matching * system entry is found. */ - @Test(dataProvider = "resolveWithPrefer") + @ParameterizedTest + @MethodSource("getDataForResolve") public void resolveWithPrefer(String prefer, String cfile, String publicId, String systemId, String expected) throws Exception { URI catalogFile = getClass().getResource(cfile).toURI(); @@ -411,7 +427,7 @@ public void resolveWithPrefer(String prefer, String cfile, String publicId, .build(); CatalogResolver catalogResolver = CatalogManager.catalogResolver(f, catalogFile); String result = catalogResolver.resolveEntity(publicId, systemId).getSystemId(); - Assert.assertEquals(expected, result); + assertEquals(expected, result); } /** @@ -420,7 +436,8 @@ public void resolveWithPrefer(String prefer, String cfile, String publicId, * over other settings, in which case, whether next and delegate Catalogs will * be loaded is determined by the defer attribute. */ - @Test(dataProvider = "invalidAltCatalogs", expectedExceptions = CatalogException.class) + @ParameterizedTest + @MethodSource("getInvalidAltCatalogs") public void testDeferAltCatalogs(String file) throws Exception { URI catalogFile = getClass().getResource(file).toURI(); CatalogFeatures features = CatalogFeatures.builder(). @@ -431,7 +448,7 @@ public void testDeferAltCatalogs(String file) throws Exception { the parent catalog will try to load the alt catalog, which will fail since it points to an invalid catalog. */ - Catalog catalog = CatalogManager.catalog(features, catalogFile); + assertThrows(CatalogException.class, () -> CatalogManager.catalog(features, catalogFile)); } @@ -443,22 +460,17 @@ public void testDeferAltCatalogs(String file) throws Exception { public void testJDK8146237() throws Exception { URI catalogFile = getClass().getResource("JDK8146237_catalog.xml").toURI(); - try { - CatalogFeatures features = CatalogFeatures.builder() - .with(CatalogFeatures.Feature.PREFER, "system") - .build(); - Catalog catalog = CatalogManager.catalog(features, catalogFile); - CatalogResolver catalogResolver = CatalogManager.catalogResolver(catalog); - String actualSystemId = catalogResolver.resolveEntity( - "-//FOO//DTD XML Dummy V0.0//EN", - "http://www.oracle.com/alt1sys.dtd") - .getSystemId(); - Assert.assertTrue(actualSystemId.contains("dummy.dtd"), - "Resulting id should contain dummy.dtd, indicating a match by publicId"); - - } catch (Exception e) { - Assert.fail(e.getMessage()); - } + CatalogFeatures features = CatalogFeatures.builder() + .with(CatalogFeatures.Feature.PREFER, "system") + .build(); + Catalog catalog = CatalogManager.catalog(features, catalogFile); + CatalogResolver catalogResolver = CatalogManager.catalogResolver(catalog); + String actualSystemId = catalogResolver.resolveEntity( + "-//FOO//DTD XML Dummy V0.0//EN", + "http://www.oracle.com/alt1sys.dtd") + .getSystemId(); + assertTrue(actualSystemId.contains("dummy.dtd"), + "Resulting id should contain dummy.dtd, indicating a match by publicId"); } /* @@ -469,14 +481,9 @@ public void testJDK8146237() throws Exception { public void testRewriteSystem() throws Exception { URI catalog = getClass().getResource("rewriteCatalog.xml").toURI(); - try { - CatalogResolver resolver = CatalogManager.catalogResolver(CatalogFeatures.defaults(), catalog); - String actualSystemId = resolver.resolveEntity(null, "http://remote.com/dtd/book.dtd").getSystemId(); - Assert.assertTrue(!actualSystemId.contains("//"), "result contains duplicate slashes"); - } catch (Exception e) { - Assert.fail(e.getMessage()); - } - + CatalogResolver resolver = CatalogManager.catalogResolver(CatalogFeatures.defaults(), catalog); + String actualSystemId = resolver.resolveEntity(null, "http://remote.com/dtd/book.dtd").getSystemId(); + assertFalse(actualSystemId.contains("//"), "result contains duplicate slashes"); } /* @@ -487,23 +494,18 @@ public void testRewriteSystem() throws Exception { public void testRewriteUri() throws Exception { URI catalog = getClass().getResource("rewriteCatalog.xml").toURI(); - try { - - CatalogResolver resolver = CatalogManager.catalogResolver(CatalogFeatures.defaults(), catalog); - String actualSystemId = resolver.resolve("http://remote.com/import/import.xsl", null).getSystemId(); - Assert.assertTrue(!actualSystemId.contains("//"), "result contains duplicate slashes"); - } catch (Exception e) { - Assert.fail(e.getMessage()); - } + CatalogResolver resolver = CatalogManager.catalogResolver(CatalogFeatures.defaults(), catalog); + String actualSystemId = resolver.resolve("http://remote.com/import/import.xsl", null).getSystemId(); + assertFalse(actualSystemId.contains("//"), "result contains duplicate slashes"); } /* @bug 8144966 Verifies that passing null as CatalogFeatures will result in a NPE. */ - @Test(expectedExceptions = NullPointerException.class) + @Test public void testFeatureNull() { - CatalogResolver resolver = CatalogManager.catalogResolver((CatalogFeatures)null, (URI)null); + assertThrows(NullPointerException.class, () -> CatalogManager.catalogResolver((CatalogFeatures) null, (URI) null)); } @@ -511,10 +513,11 @@ public void testFeatureNull() { @bug 8144966 Verifies that passing null as the URI will result in a NPE. */ - @Test(expectedExceptions = NullPointerException.class) + @Test public void testPathNull() { - URI uri = null; - CatalogResolver resolver = CatalogManager.catalogResolver(CatalogFeatures.defaults(), uri); + assertThrows( + NullPointerException.class, + () -> CatalogManager.catalogResolver(CatalogFeatures.defaults(), (URI) null)); } /* @@ -523,7 +526,8 @@ public void testPathNull() { is successful, the Handler shall return the value of the entity reference that matches the expected value. */ - @Test(dataProvider = "catalog") + @ParameterizedTest + @MethodSource("getCatalog") public void testCatalogResolver(String test, String expected, String catalogFile, String xml, SAXParser saxParser) throws Exception { URI catalog = null; @@ -531,18 +535,14 @@ public void testCatalogResolver(String test, String expected, String catalogFile catalog = getClass().getResource(catalogFile).toURI(); } String url = getClass().getResource(xml).getFile(); - try { - CatalogResolver cr = CatalogManager.catalogResolver(CatalogFeatures.defaults(), catalog); - XMLReader reader = saxParser.getXMLReader(); - reader.setEntityResolver(cr); - MyHandler handler = new MyHandler(saxParser); - reader.setContentHandler(handler); - reader.parse(url); - System.out.println(test + ": expected [" + expected + "] <> actual [" + handler.getResult() + "]"); - Assert.assertEquals(handler.getResult(), expected); - } catch (SAXException | IOException e) { - Assert.fail(e.getMessage()); - } + CatalogResolver cr = CatalogManager.catalogResolver(CatalogFeatures.defaults(), catalog); + XMLReader reader = saxParser.getXMLReader(); + reader.setEntityResolver(cr); + MyHandler handler = new MyHandler(saxParser); + reader.setContentHandler(handler); + reader.parse(url); + System.out.println(test + ": expected [" + expected + "] <> actual [" + handler.getResult() + "]"); + assertEquals(expected, handler.getResult()); } /* @@ -564,7 +564,7 @@ public void testInvalidCatalog() throws Exception { } catch (Exception e) { String msg = e.getMessage(); if (msg != null) { - Assert.assertTrue(msg.contains(expectedMsgId), + assertTrue(msg.contains(expectedMsgId), "Message shall contain the corrent message ID " + expectedMsgId); } } @@ -585,19 +585,15 @@ public void testIgnoreInvalidCatalog() { .build(); String test = "testInvalidCatalog"; - try { - CatalogResolver resolver = CatalogManager.catalogResolver(f); - String actualSystemId = resolver.resolveEntity( - null, - "http://remote/xml/dtd/sys/alice/docAlice.dtd") - .getSystemId(); - System.out.println("testIgnoreInvalidCatalog: expected [null]"); - System.out.println("testIgnoreInvalidCatalog: expected [null]"); - System.out.println("actual [" + actualSystemId + "]"); - Assert.assertEquals(actualSystemId, null); - } catch (Exception e) { - Assert.fail(e.getMessage()); - } + CatalogResolver resolver = CatalogManager.catalogResolver(f); + String actualSystemId = resolver.resolveEntity( + null, + "http://remote/xml/dtd/sys/alice/docAlice.dtd") + .getSystemId(); + System.out.println("testIgnoreInvalidCatalog: expected [null]"); + System.out.println("testIgnoreInvalidCatalog: expected [null]"); + System.out.println("actual [" + actualSystemId + "]"); + assertNull(actualSystemId); } @@ -608,7 +604,6 @@ public void testIgnoreInvalidCatalog() { This DataProvider is copied from JCK ResolveTests' dataMatch1 */ - @DataProvider(name = "resolveUri") public Object[][] getDataForUriResolver() { return new Object[][]{ {"uri.xml", @@ -623,7 +618,6 @@ public Object[][] getDataForUriResolver() { DataProvider: used to verify hierarchical catalogs. Refer to JCK test hierarchyOfCatFiles2. */ - @DataProvider(name = "hierarchyOfCatFilesData") public Object[][] getHierarchyOfCatFilesData() { return new Object[][]{ {"http://www.oracle.com/sequence.dtd", "first.dtd"}, @@ -637,7 +631,6 @@ public Object[][] getHierarchyOfCatFilesData() { Data columns: catalog, prefer, systemId, publicId, expectedUri, expectedFile, msg */ - @DataProvider(name = "resolveEntity") public Object[][] getDataForMatchingBothIds() { String expected = "http://www.groupxmlbase.com/dtds/rewrite.dtd"; return new Object[][]{ @@ -658,7 +651,6 @@ public Object[][] getDataForMatchingBothIds() { Data columns: prefer, catalog, publicId, systemId, expected result */ - @DataProvider(name = "matchWithPrefer") public Object[][] getDataForMatch() { return new Object[][]{ {"public", "pubOnly.xml", id, "", "http://local/base/dtd/public.dtd"}, @@ -682,7 +674,6 @@ public Object[][] getDataForMatch() { Data columns: prefer, catalog, publicId, systemId, expected result */ - @DataProvider(name = "resolveWithPrefer") public Object[][] getDataForResolve() { return new Object[][]{ {"system", "pubOnly.xml", id, "", "http://local/base/dtd/public.dtd"}, @@ -709,11 +700,10 @@ public Object[][] getDataForResolve() { DataProvider: catalogs that contain invalid next or delegate catalogs. The defer attribute is set to false. */ - @DataProvider(name = "invalidAltCatalogs") - public Object[][] getCatalogs() { - return new Object[][]{ - {"defer_false_2.xml"}, - {"defer_del_false.xml"} + public Object[][] getInvalidAltCatalogs() { + return new Object[][] { + { "defer_false_2.xml" }, + { "defer_del_false.xml" } }; } @@ -722,7 +712,6 @@ public Object[][] getCatalogs() { DataProvider: provides test name, expected string, the catalog, and XML document. */ - @DataProvider(name = "catalog") public Object[][] getCatalog() { return new Object[][]{ {"testSystem", "Test system entry", "catalog.xml", "system.xml", getParser()}, diff --git a/test/jaxp/javax/xml/jaxp/unittest/catalog/GroupTest.java b/test/jaxp/javax/xml/jaxp/unittest/catalog/GroupTest.java index 46aa46ee29f..6a5593db11b 100644 --- a/test/jaxp/javax/xml/jaxp/unittest/catalog/GroupTest.java +++ b/test/jaxp/javax/xml/jaxp/unittest/catalog/GroupTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,31 +22,36 @@ */ package catalog; -import java.net.URI; -import java.nio.file.Paths; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.TestInstance.Lifecycle; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + import javax.xml.catalog.CatalogFeatures; import javax.xml.catalog.CatalogManager; import javax.xml.catalog.CatalogResolver; import javax.xml.transform.Source; -import org.testng.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; +import java.net.URI; +import java.nio.file.Paths; + +import static org.junit.jupiter.api.Assertions.assertTrue; /* * @test * @bug 8215330 * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest - * @run testng catalog.GroupTest + * @run junit catalog.GroupTest * @summary Tests catalog with Group entries. */ +@TestInstance(Lifecycle.PER_CLASS) public class GroupTest extends CatalogSupportBase { String catalogGroup; /* * Initializing fields */ - @BeforeClass + @BeforeAll public void setUpClass() throws Exception { super.setUp(); catalogGroup = Paths.get(filepath + "GroupTest.xml").toUri().toASCIIString(); @@ -60,13 +65,14 @@ public void setUpClass() throws Exception { * @param expected the expected result string * @throws Exception */ - @Test(dataProvider = "data_group") + @ParameterizedTest + @MethodSource("getDataDOM") public void testGroup(String catalog, String uri, String expected) throws Exception { CatalogResolver resolver = CatalogManager.catalogResolver( CatalogFeatures.defaults(), URI.create(catalog)); Source src = resolver.resolve(uri, null); - Assert.assertTrue(src.getSystemId().endsWith(expected), "uriSuffix match"); + assertTrue(src.getSystemId().endsWith(expected), "uriSuffix match"); } @@ -74,7 +80,6 @@ public void testGroup(String catalog, String uri, String expected) throws Except DataProvider: for testing catalogs with group entries Data: catalog file, uri, expected result string */ - @DataProvider(name = "data_group") public Object[][] getDataDOM() { return new Object[][]{ {catalogGroup, "http://openjdk_java_net/xml/catalog/A/CommonFileA1.xml", "LocalFileA1.xml"}, diff --git a/test/jaxp/javax/xml/jaxp/unittest/datatype/Bug6320118.java b/test/jaxp/javax/xml/jaxp/unittest/datatype/Bug6320118.java index f22e95837bd..fa27d5102d4 100644 --- a/test/jaxp/javax/xml/jaxp/unittest/datatype/Bug6320118.java +++ b/test/jaxp/javax/xml/jaxp/unittest/datatype/Bug6320118.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,26 +23,28 @@ package datatype; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + import javax.xml.datatype.DatatypeConfigurationException; import javax.xml.datatype.DatatypeFactory; import javax.xml.datatype.XMLGregorianCalendar; -import org.testng.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; /* * @test * @bug 6320118 * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest - * @run testng/othervm datatype.Bug6320118 + * @run junit/othervm datatype.Bug6320118 * @summary Test xml datatype XMLGregorianCalendar. */ public class Bug6320118 { DatatypeFactory df; - @BeforeClass + @BeforeEach public void createDataTypeFactory() throws DatatypeConfigurationException { df = DatatypeFactory.newInstance(); } @@ -50,30 +52,30 @@ public void createDataTypeFactory() throws DatatypeConfigurationException { @Test public void test1() { XMLGregorianCalendar calendar = df.newXMLGregorianCalendar(1970, 1, 1, 24, 0, 0, 0, 0); - Assert.assertEquals(calendar.getYear(), 1970); - Assert.assertEquals(calendar.getMonth(), 1); - Assert.assertEquals(calendar.getDay(), 2); - Assert.assertEquals(calendar.getHour(), 0, "hour 24 needs to be treated as hour 0 of next day"); + assertEquals(1970, calendar.getYear()); + assertEquals(1, calendar.getMonth()); + assertEquals(2, calendar.getDay()); + assertEquals(0, calendar.getHour(), "hour 24 needs to be treated as hour 0 of next day"); } @Test public void test2() { XMLGregorianCalendar calendar = df.newXMLGregorianCalendarTime(24, 0, 0, 0); - Assert.assertEquals(calendar.getHour(), 0, "hour 24 needs to be treated as hour 0 of next day"); + assertEquals(0, calendar.getHour(), "hour 24 needs to be treated as hour 0 of next day"); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void test3() { XMLGregorianCalendar calendar = df.newXMLGregorianCalendar(); // Must fail as other params are not 0 but undefined - calendar.setHour(24); + assertThrows(IllegalArgumentException.class, () -> calendar.setHour(24)); } @Test public void test4() { XMLGregorianCalendar calendar = df.newXMLGregorianCalendar(); calendar.setTime(24, 0, 0, 0); - Assert.assertEquals(calendar.getHour(), 0, "hour 24 needs to be treated as hour 0 of next day"); + assertEquals(0, calendar.getHour(), "hour 24 needs to be treated as hour 0 of next day"); } } diff --git a/test/jaxp/javax/xml/jaxp/unittest/datatype/Bug6937951Test.java b/test/jaxp/javax/xml/jaxp/unittest/datatype/Bug6937951Test.java index d1e5aea93da..bc32bc0374d 100644 --- a/test/jaxp/javax/xml/jaxp/unittest/datatype/Bug6937951Test.java +++ b/test/jaxp/javax/xml/jaxp/unittest/datatype/Bug6937951Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,18 +23,19 @@ package datatype; +import org.junit.jupiter.api.Test; + import javax.xml.datatype.DatatypeConfigurationException; import javax.xml.datatype.DatatypeFactory; import javax.xml.datatype.XMLGregorianCalendar; -import org.testng.Assert; -import org.testng.annotations.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; /* * @test * @bug 6937951 * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest - * @run testng/othervm datatype.Bug6937951Test + * @run junit/othervm datatype.Bug6937951Test * @summary Test midnight is same as the start of the next day in XMLGregorianCalendar. */ public class Bug6937951Test { @@ -44,13 +45,10 @@ public void test() throws DatatypeConfigurationException { DatatypeFactory dtf = DatatypeFactory.newInstance(); XMLGregorianCalendar c1 = dtf.newXMLGregorianCalendar("1999-12-31T24:00:00"); XMLGregorianCalendar c2 = dtf.newXMLGregorianCalendar("2000-01-01T00:00:00"); - System.out.println("c1: " + c1.getYear() + "-" + c1.getMonth() + "-" + c1.getDay() + "T" + c1.getHour()); - System.out.println(c1.equals(c2) ? "pass" : "fail"); // fails - if (!c1.equals(c2)) - Assert.fail("hour 24 needs to be treated as equal to hour 0 of the next day"); - if (c1.getYear() != 2000 && c1.getHour() != 0) - Assert.fail("hour 24 needs to be treated as equal to hour 0 of the next day"); + assertEquals(2000, c1.getYear()); + assertEquals(0, c1.getHour()); + assertEquals(c1, c2, "hour 24 should treated as equal to hour 0 of the next day"); } } diff --git a/test/jaxp/javax/xml/jaxp/unittest/datatype/Bug6937964Test.java b/test/jaxp/javax/xml/jaxp/unittest/datatype/Bug6937964Test.java index 8aa5d6369a3..571ca1b97d3 100644 --- a/test/jaxp/javax/xml/jaxp/unittest/datatype/Bug6937964Test.java +++ b/test/jaxp/javax/xml/jaxp/unittest/datatype/Bug6937964Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,31 +23,29 @@ package datatype; -import java.math.BigDecimal; -import java.math.BigInteger; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; import javax.xml.datatype.DatatypeConfigurationException; import javax.xml.datatype.DatatypeConstants; import javax.xml.datatype.DatatypeFactory; import javax.xml.datatype.Duration; import javax.xml.namespace.QName; +import java.math.BigDecimal; +import java.math.BigInteger; -import org.testng.Assert; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; /* * @test * @bug 6937964 * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest - * @run testng/othervm datatype.Bug6937964Test + * @run junit/othervm datatype.Bug6937964Test * @summary Test Duration is normalized. */ public class Bug6937964Test { - /** - * Print debugging to System.err. - */ - private static final boolean DEBUG = false; /** * Constant to indicate expected lexical test failure. */ @@ -57,7 +55,7 @@ public class Bug6937964Test { public void test() throws DatatypeConfigurationException { DatatypeFactory dtf = DatatypeFactory.newInstance(); Duration d = dtf.newDurationYearMonth("P20Y15M"); - System.out.println(d.getYears() == 21 ? "pass" : "fail"); + assertEquals(21, d.getYears()); } @Test @@ -65,7 +63,7 @@ public void testNewDurationYearMonthLexicalRepresentation() throws DatatypeConfi DatatypeFactory dtf = DatatypeFactory.newInstance(); Duration d = dtf.newDurationYearMonth("P20Y15M"); int years = d.getYears(); - Assert.assertEquals(years, 21, "Return value should be normalized"); + assertEquals(21, years, "Return value should be normalized"); } @Test @@ -73,8 +71,7 @@ public void testNewDurationYearMonthMilliseconds() throws DatatypeConfigurationE DatatypeFactory dtf = DatatypeFactory.newInstance(); Duration d = dtf.newDurationYearMonth(671976000000L); int years = d.getYears(); - System.out.println("Years: " + years); - Assert.assertEquals(years, 21, "Return value should be normalized"); + assertEquals(21, years, "Return value should be normalized"); } @Test @@ -84,7 +81,7 @@ public void testNewDurationYearMonthBigInteger() throws DatatypeConfigurationExc BigInteger mon = new BigInteger("15"); Duration d = dtf.newDurationYearMonth(true, year, mon); int years = d.getYears(); - Assert.assertEquals(years, 21, "Return value should be normalized"); + assertEquals(21, years, "Return value should be normalized"); } @Test @@ -92,7 +89,7 @@ public void testNewDurationYearMonthInt() throws DatatypeConfigurationException DatatypeFactory dtf = DatatypeFactory.newInstance(); Duration d = dtf.newDurationYearMonth(true, 20, 15); int years = d.getYears(); - Assert.assertEquals(years, 21, "Return value should be normalized"); + assertEquals(21, years, "Return value should be normalized"); } @Test @@ -100,7 +97,7 @@ public void testNewDurationDayTimeLexicalRepresentation() throws DatatypeConfigu DatatypeFactory dtf = DatatypeFactory.newInstance(); Duration d = dtf.newDurationDayTime("P1DT23H59M65S"); int days = d.getDays(); - Assert.assertEquals(days, 2, "Return value should be normalized"); + assertEquals(2, days, "Return value should be normalized"); } @Test @@ -108,7 +105,7 @@ public void testNewDurationDayTimeMilliseconds() throws DatatypeConfigurationExc DatatypeFactory dtf = DatatypeFactory.newInstance(); Duration d = dtf.newDurationDayTime(172805000L); int days = d.getDays(); - Assert.assertEquals(days, 2, "Return value should be normalized"); + assertEquals(2, days, "Return value should be normalized"); } @Test @@ -120,8 +117,7 @@ public void testNewDurationDayTimeBigInteger() throws DatatypeConfigurationExcep BigInteger sec = new BigInteger("65"); Duration d = dtf.newDurationDayTime(true, day, hour, min, sec); int days = d.getDays(); - System.out.println("Days: " + days); - Assert.assertEquals(days, 2, "Return value should be normalized"); + assertEquals(2, days, "Return value should be normalized"); } @Test @@ -129,117 +125,88 @@ public void testNewDurationDayTimeInt() throws DatatypeConfigurationException { DatatypeFactory dtf = DatatypeFactory.newInstance(); Duration d = dtf.newDurationDayTime(true, 1, 23, 59, 65); int days = d.getDays(); - System.out.println("Days: " + days); - Assert.assertEquals(days, 2, "Return value should be normalized"); + assertEquals(2, days, "Return value should be normalized"); } - @DataProvider(name = "lexicalvalues") - public Object[][] actualAndExpectedLexicals() { - Object actualAndExpected [][] = { - {"P13M", "P1Y1M"}, - {"-P13M", "-P1Y1M"}, - {"P1Y", "P1Y"}, - {"-P1Y", "-P1Y"}, - {"P1Y25M", "P3Y1M"}, - {"-P1Y25M", "-P3Y1M"} + public static Object[][] lexicalvalues() { + return new Object[][] { + { "P13M", "P1Y1M" }, + { "-P13M", "-P1Y1M" }, + { "P1Y", "P1Y" }, + { "-P1Y", "-P1Y" }, + { "P1Y25M", "P3Y1M" }, + { "-P1Y25M", "-P3Y1M" } }; - return actualAndExpected; } - @Test(dataProvider = "lexicalvalues") - public void testNewDurationYearMonthLexicalRepresentation1(String actualLex, String expectedLex) { - /** - * Lexical test values to test. - */ - - DatatypeFactory datatypeFactory = null; - try { - datatypeFactory = DatatypeFactory.newInstance(); - } catch (DatatypeConfigurationException datatypeConfigurationException) { - Assert.fail(datatypeConfigurationException.toString()); - } - - if (DEBUG) { - System.err.println("DatatypeFactory created: " + datatypeFactory.toString()); - } - if (DEBUG) { - System.err.println("testing value: \"" + actualLex + "\", expecting: \"" + expectedLex + "\""); - } + @ParameterizedTest + @MethodSource("lexicalvalues") + public void testNewDurationYearMonthLexicalRepresentation1(String actualLex, String expectedLex) + throws DatatypeConfigurationException { + DatatypeFactory datatypeFactory = DatatypeFactory.newInstance(); try { Duration duration = datatypeFactory.newDurationYearMonth(actualLex); - if (DEBUG) { - System.err.println("Duration created: \"" + duration.toString() + "\""); - } - // was this expected to fail? - Assert.assertNotEquals(expectedLex, TEST_VALUE_FAIL, "the value \"" + actualLex + "\" is invalid " + - "yet it created the Duration \"" + duration.toString() + "\"" ); + assertNotEquals(TEST_VALUE_FAIL, expectedLex, "the value \"" + actualLex + "\" is invalid " + + "yet it created the Duration \"" + duration.toString() + "\""); // right XMLSchemaType? // TODO: enable test, it should pass, it fails with Exception(s) // for now due to a bug try { QName xmlSchemaType = duration.getXMLSchemaType(); - Assert.assertEquals(xmlSchemaType, DatatypeConstants.DURATION_YEARMONTH, "Duration created with " + + assertEquals(DatatypeConstants.DURATION_YEARMONTH, xmlSchemaType, "Duration created with " + "XMLSchemaType of\"" + xmlSchemaType + "\" was expected to be \"" - + DatatypeConstants.DURATION_YEARMONTH + "\" and has the value \"" + duration.toString() + "\""); - } catch (IllegalStateException illegalStateException) { - // TODO; this test really should pass - System.err.println("Please fix this bug that is being ignored, for now: " + illegalStateException.getMessage()); - } - - // does it have the right value? - Assert.assertEquals(duration.toString(), expectedLex, "Duration created with \"" + actualLex + - "\" was expected to be \"" + expectedLex + "\" and has the value \"" + duration.toString() + "\""); - // Duration created with correct value - } catch (Exception exception) { - if (DEBUG) { - System.err.println("Exception in creating duration: \"" + exception.toString() + "\""); - } - - // was this expected to succed? - Assert.assertEquals(TEST_VALUE_FAIL, expectedLex, "the value \"" + actualLex + "\" is valid yet " + - "it failed with \"" + exception.toString() + "\""); - // expected failure + + DatatypeConstants.DURATION_YEARMONTH + "\" and has the value \"" + duration + "\""); + } catch (IllegalStateException illegalStateException) { + // TODO; this test really should pass + System.err.println("Please fix this bug that is being ignored, for now: " + illegalStateException.getMessage()); } + + // does it have the right value? + assertEquals(expectedLex, duration.toString(), "Duration created with \"" + actualLex + + "\" was expected to be \"" + expectedLex + "\" and has the value \"" + duration + "\""); + // Duration created with correct value + } catch (Exception exception) { + // was this expected to succed? + assertEquals(TEST_VALUE_FAIL, expectedLex, "the value \"" + actualLex + "\" is valid yet " + + "it failed with \"" + exception + "\""); + // expected failure + } } - @DataProvider(name = "lexDayTime") - public Object[][] lexDayTimeData() { + public static Object[][] lexDayTimeData() { BigInteger one = new BigInteger("1"); BigInteger zero = new BigInteger("0"); BigDecimal bdZero = new BigDecimal("0"); BigDecimal bdOne = new BigDecimal("1"); - Object[][] values = { + return new Object[][] { // lex, isPositive, years, month, days, hours, minutes, seconds - { "P1D", Boolean.TRUE, null, null, one, zero, zero, bdZero }, { "PT1H", Boolean.TRUE, null, null, zero, one, zero, bdZero }, - { "PT1M", Boolean.TRUE, null, null, zero, zero, one, bdZero }, { "PT1.1S", Boolean.TRUE, null, null, zero, zero, zero, bdOne }, + { "P1D", Boolean.TRUE, null, null, one, zero, zero, bdZero }, + { "PT1H", Boolean.TRUE, null, null, zero, one, zero, bdZero }, + { "PT1M", Boolean.TRUE, null, null, zero, zero, one, bdZero }, + { "PT1.1S", Boolean.TRUE, null, null, zero, zero, zero, bdOne }, { "-PT1H1.1S", Boolean.FALSE, null, null, zero, one, zero, bdOne }, }; - return values; } /** * TCK test failure */ - @Test(dataProvider = "lexDayTime") + @ParameterizedTest + @MethodSource("lexDayTimeData") public void testNewDurationDayTime005(String lex, boolean isPositive, BigInteger year, BigInteger month, BigInteger days, - BigInteger hour, BigInteger minutes, BigDecimal seconds) { - StringBuffer result = new StringBuffer(); - DatatypeFactory df = null; - - try { - df = DatatypeFactory.newInstance(); - } catch (DatatypeConfigurationException e) { - Assert.fail(e.toString()); - } + BigInteger hour, BigInteger minutes, BigDecimal seconds) + throws DatatypeConfigurationException { + StringBuilder result = new StringBuilder(); + DatatypeFactory df = DatatypeFactory.newInstance(); Duration duration = null; try { duration = df.newDurationDayTime(isPositive, days, hour, minutes, seconds.toBigInteger()); } catch (IllegalArgumentException e) { - result.append("; unexpected " + e + " trying to create duration \'" + lex + "\'"); + result.append("; unexpected " + e + " trying to create duration '" + lex + "'"); } if (duration != null) { if ((duration.getSign() == 1) != isPositive) { @@ -248,43 +215,39 @@ public void testNewDurationDayTime005(String lex, boolean isPositive, BigInteger Number value = duration.getField(DatatypeConstants.YEARS); if ((value != null && year == null) || (value == null && year != null) || (value != null && !value.equals(year))) { - result.append("; " + lex + ": wrong value of the field " + DatatypeConstants.YEARS + ": \'" + value + "\'" + ", expected \'" - + year + "\'"); + result.append("; " + lex + ": wrong value of the field " + DatatypeConstants.YEARS + ": '" + value + "'" + ", expected '" + + year + "'"); } value = duration.getField(DatatypeConstants.MONTHS); if ((value != null && month == null) || (value == null && month != null) || (value != null && !value.equals(month))) { - result.append("; " + lex + ": wrong value of the field " + DatatypeConstants.MONTHS + ": \'" + value + "\'" + ", expected \'" - + month + "\'"); + result.append("; " + lex + ": wrong value of the field " + DatatypeConstants.MONTHS + ": '" + value + "'" + ", expected '" + + month + "'"); } value = duration.getField(DatatypeConstants.DAYS); if ((value != null && days == null) || (value == null && days != null) || (value != null && !value.equals(days))) { - result.append("; " + lex + ": wrong value of the field " + DatatypeConstants.DAYS + ": \'" + value + "\'" + ", expected \'" - + days + "\'"); + result.append("; " + lex + ": wrong value of the field " + DatatypeConstants.DAYS + ": '" + value + "'" + ", expected '" + + days + "'"); } value = duration.getField(DatatypeConstants.HOURS); if ((value != null && hour == null) || (value == null && hour != null) || (value != null && !value.equals(hour))) { - result.append("; " + lex + ": wrong value of the field " + DatatypeConstants.HOURS + ": \'" + value + "\'" + ", expected \'" - + hour + "\'"); + result.append("; " + lex + ": wrong value of the field " + DatatypeConstants.HOURS + ": '" + value + "'" + ", expected '" + + hour + "'"); } value = duration.getField(DatatypeConstants.MINUTES); if ((value != null && minutes == null) || (value == null && minutes != null) || (value != null && !value.equals(minutes))) { - result.append("; " + lex + ": wrong value of the field " + DatatypeConstants.MINUTES + ": \'" + value + "\'" + ", expected \'" - + minutes + "\'"); + result.append("; " + lex + ": wrong value of the field " + DatatypeConstants.MINUTES + ": '" + value + "'" + ", expected '" + + minutes + "'"); } value = duration.getField(DatatypeConstants.SECONDS); - if ((value != null && seconds == null) || (value == null && seconds != null) || (value != null && !value.equals(seconds))) { - result.append("; " + lex + ": wrong value of the field " + DatatypeConstants.SECONDS + ": \'" + value + "\'" + ", expected \'" - + seconds + "\'"); + if (value == null || !value.equals(seconds)) { + result.append("; " + lex + ": wrong value of the field " + DatatypeConstants.SECONDS + ": '" + value + "'" + ", expected '" + + seconds + "'"); } } - if(result.length() > 0) { - Assert.fail(result.substring(2)); - } - System.out.println("OK"); } } diff --git a/test/jaxp/javax/xml/jaxp/unittest/datatype/Bug7042647Test.java b/test/jaxp/javax/xml/jaxp/unittest/datatype/Bug7042647Test.java index c6b143c1d5a..b434db0e4c4 100644 --- a/test/jaxp/javax/xml/jaxp/unittest/datatype/Bug7042647Test.java +++ b/test/jaxp/javax/xml/jaxp/unittest/datatype/Bug7042647Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,21 +23,21 @@ package datatype; -import java.util.Calendar; -import java.util.GregorianCalendar; +import org.junit.jupiter.api.Test; import javax.xml.datatype.DatatypeConfigurationException; import javax.xml.datatype.DatatypeFactory; import javax.xml.datatype.XMLGregorianCalendar; +import java.util.Calendar; +import java.util.GregorianCalendar; -import org.testng.Assert; -import org.testng.annotations.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; /* * @test * @bug 7042647 * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest - * @run testng/othervm datatype.Bug7042647Test + * @run junit/othervm datatype.Bug7042647Test * @summary Test getFirstDayOfWeek is correct after converting XMLGregorianCalendar to a GregorianCalendar. */ public class Bug7042647Test { @@ -49,11 +49,7 @@ public void test() throws DatatypeConfigurationException { int firstDayOfWeek = calendar.getFirstDayOfWeek(); Calendar defaultCalendar = Calendar.getInstance(); int defaultFirstDayOfWeek = defaultCalendar.getFirstDayOfWeek(); - if (firstDayOfWeek != defaultFirstDayOfWeek) { - Assert.fail("Failed firstDayOfWeek=" + firstDayOfWeek + " != defaultFirstDayOfWeek=" + defaultFirstDayOfWeek); - } else { - System.out.println("Success firstDayOfWeek=" + firstDayOfWeek + " == defaultFirstDayOfWeek=" + defaultFirstDayOfWeek); - } + assertEquals(defaultFirstDayOfWeek, firstDayOfWeek); } } diff --git a/test/jaxp/javax/xml/jaxp/unittest/datatype/DatatypeFactoryTest.java b/test/jaxp/javax/xml/jaxp/unittest/datatype/DatatypeFactoryTest.java index 3866ae6a70c..da5862f5adb 100644 --- a/test/jaxp/javax/xml/jaxp/unittest/datatype/DatatypeFactoryTest.java +++ b/test/jaxp/javax/xml/jaxp/unittest/datatype/DatatypeFactoryTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,8 +23,7 @@ package datatype; -import java.math.BigDecimal; -import java.math.BigInteger; +import org.junit.jupiter.api.Test; import javax.xml.datatype.DatatypeConfigurationException; import javax.xml.datatype.DatatypeConstants; @@ -32,14 +31,15 @@ import javax.xml.datatype.Duration; import javax.xml.datatype.XMLGregorianCalendar; import javax.xml.namespace.QName; +import java.math.BigDecimal; +import java.math.BigInteger; -import org.testng.Assert; -import org.testng.annotations.Test; +import static org.junit.jupiter.api.Assertions.fail; /* * @test * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest - * @run testng/othervm datatype.DatatypeFactoryTest + * @run junit/othervm datatype.DatatypeFactoryTest * @summary Test DatatypeFactory. */ public class DatatypeFactoryTest { @@ -120,7 +120,7 @@ public final void testNewDurationMilliseconds() { try { datatypeFactory = DatatypeFactory.newInstance(); } catch (DatatypeConfigurationException datatypeConfigurationException) { - Assert.fail(datatypeConfigurationException.toString()); + fail(datatypeConfigurationException.toString()); } if (DEBUG) { @@ -144,20 +144,20 @@ public final void testNewDurationMilliseconds() { // was this expected to fail? if (TEST_VALUES_MILLISECONDS_RESULTS[onTestValue].equals(TEST_VALUE_FAIL)) { - Assert.fail("the value \"" + TEST_VALUES_MILLISECONDS[onTestValue] + "\" is invalid yet it created the Duration \"" + duration.toString() + fail("the value \"" + TEST_VALUES_MILLISECONDS[onTestValue] + "\" is invalid yet it created the Duration \"" + duration.toString() + "\""); } // right XMLSchemaType? QName xmlSchemaType = duration.getXMLSchemaType(); if (!xmlSchemaType.equals(DatatypeConstants.DURATION)) { - Assert.fail("Duration created with XMLSchemaType of\"" + xmlSchemaType + "\" was expected to be \"" + DatatypeConstants.DURATION + fail("Duration created with XMLSchemaType of\"" + xmlSchemaType + "\" was expected to be \"" + DatatypeConstants.DURATION + "\" and has the value \"" + duration.toString() + "\""); } // does it have the right value? if (!TEST_VALUES_MILLISECONDS_RESULTS[onTestValue].equals(duration.toString())) { - Assert.fail("Duration created with \"" + TEST_VALUES_MILLISECONDS[onTestValue] + "\" was expected to be \"" + fail("Duration created with \"" + TEST_VALUES_MILLISECONDS[onTestValue] + "\" was expected to be \"" + TEST_VALUES_MILLISECONDS_RESULTS[onTestValue] + "\" and has the value \"" + duration.toString() + "\""); } @@ -170,7 +170,7 @@ public final void testNewDurationMilliseconds() { // was this expected to succed? if (!TEST_VALUES_MILLISECONDS_RESULTS[onTestValue].equals(TEST_VALUE_FAIL)) { - Assert.fail("the value \"" + TEST_VALUES_MILLISECONDS[onTestValue] + "\" is valid yet it failed with \"" + exception.toString() + "\""); + fail("the value \"" + TEST_VALUES_MILLISECONDS[onTestValue] + "\" is valid yet it failed with \"" + exception.toString() + "\""); } // expected failure } @@ -195,7 +195,7 @@ public final void testNewDurationYearMonthLexicalRepresentation() { try { datatypeFactory = DatatypeFactory.newInstance(); } catch (DatatypeConfigurationException datatypeConfigurationException) { - Assert.fail(datatypeConfigurationException.toString()); + fail(datatypeConfigurationException.toString()); } if (DEBUG) { @@ -218,7 +218,7 @@ public final void testNewDurationYearMonthLexicalRepresentation() { // was this expected to fail? if (TEST_VALUES_LEXICAL[onTestValue + 1].equals(TEST_VALUE_FAIL)) { - Assert.fail("the value \"" + TEST_VALUES_LEXICAL[onTestValue] + "\" is invalid yet it created the Duration \"" + duration.toString() + "\""); + fail("the value \"" + TEST_VALUES_LEXICAL[onTestValue] + "\" is invalid yet it created the Duration \"" + duration.toString() + "\""); } // right XMLSchemaType? @@ -227,7 +227,7 @@ public final void testNewDurationYearMonthLexicalRepresentation() { try { QName xmlSchemaType = duration.getXMLSchemaType(); if (!xmlSchemaType.equals(DatatypeConstants.DURATION_YEARMONTH)) { - Assert.fail("Duration created with XMLSchemaType of\"" + xmlSchemaType + "\" was expected to be \"" + fail("Duration created with XMLSchemaType of\"" + xmlSchemaType + "\" was expected to be \"" + DatatypeConstants.DURATION_YEARMONTH + "\" and has the value \"" + duration.toString() + "\""); } } catch (IllegalStateException illegalStateException) { @@ -237,7 +237,7 @@ public final void testNewDurationYearMonthLexicalRepresentation() { // does it have the right value? if (!TEST_VALUES_LEXICAL[onTestValue + 1].equals(duration.toString())) { - Assert.fail("Duration created with \"" + TEST_VALUES_LEXICAL[onTestValue] + "\" was expected to be \"" + fail("Duration created with \"" + TEST_VALUES_LEXICAL[onTestValue] + "\" was expected to be \"" + TEST_VALUES_LEXICAL[onTestValue + 1] + "\" and has the value \"" + duration.toString() + "\""); } @@ -250,7 +250,7 @@ public final void testNewDurationYearMonthLexicalRepresentation() { // was this expected to succed? if (!TEST_VALUES_LEXICAL[onTestValue + 1].equals(TEST_VALUE_FAIL)) { - Assert.fail("the value \"" + TEST_VALUES_LEXICAL[onTestValue] + "\" is valid yet it failed with \"" + exception.toString() + "\""); + fail("the value \"" + TEST_VALUES_LEXICAL[onTestValue] + "\" is valid yet it failed with \"" + exception.toString() + "\""); } // expected failure } @@ -287,7 +287,7 @@ public final void testNewDurationYearMonthMilliseconds() { try { datatypeFactory = DatatypeFactory.newInstance(); } catch (DatatypeConfigurationException datatypeConfigurationException) { - Assert.fail(datatypeConfigurationException.toString()); + fail(datatypeConfigurationException.toString()); } if (DEBUG) { @@ -311,20 +311,20 @@ public final void testNewDurationYearMonthMilliseconds() { // was this expected to fail? if (TEST_VALUES_MILLISECONDS_RESULTS[onTestValue].equals(TEST_VALUE_FAIL)) { - Assert.fail("the value \"" + TEST_VALUES_MILLISECONDS[onTestValue] + "\" is invalid yet it created the Duration \"" + duration.toString() + fail("the value \"" + TEST_VALUES_MILLISECONDS[onTestValue] + "\" is invalid yet it created the Duration \"" + duration.toString() + "\""); } // right XMLSchemaType? QName xmlSchemaType = duration.getXMLSchemaType(); if (!xmlSchemaType.equals(DatatypeConstants.DURATION_YEARMONTH)) { - Assert.fail("Duration created with XMLSchemaType of\"" + xmlSchemaType + "\" was expected to be \"" + DatatypeConstants.DURATION_YEARMONTH + fail("Duration created with XMLSchemaType of\"" + xmlSchemaType + "\" was expected to be \"" + DatatypeConstants.DURATION_YEARMONTH + "\" and has the value \"" + duration.toString() + "\""); } // does it have the right value? if (!TEST_VALUES_MILLISECONDS_RESULTS[onTestValue].equals(duration.toString())) { - Assert.fail("Duration created with \"" + TEST_VALUES_MILLISECONDS[onTestValue] + "\" was expected to be \"" + fail("Duration created with \"" + TEST_VALUES_MILLISECONDS[onTestValue] + "\" was expected to be \"" + TEST_VALUES_MILLISECONDS_RESULTS[onTestValue] + "\" and has the value \"" + duration.toString() + "\""); } @@ -333,7 +333,7 @@ public final void testNewDurationYearMonthMilliseconds() { int hours = duration.getHours(); int minutes = duration.getMinutes(); if (days != 0 || hours != 0 || minutes != 0) { - Assert.fail("xdt:yearMonthDuration created without discarding remaining milliseconds: " + " days = " + days + ", hours = " + hours + fail("xdt:yearMonthDuration created without discarding remaining milliseconds: " + " days = " + days + ", hours = " + hours + ", minutess = " + minutes); } @@ -346,7 +346,7 @@ public final void testNewDurationYearMonthMilliseconds() { // was this expected to succed? if (!TEST_VALUES_MILLISECONDS_RESULTS[onTestValue].equals(TEST_VALUE_FAIL)) { - Assert.fail("the value \"" + TEST_VALUES_MILLISECONDS[onTestValue] + "\" is valid yet it failed with \"" + exception.toString() + "\""); + fail("the value \"" + TEST_VALUES_MILLISECONDS[onTestValue] + "\" is valid yet it failed with \"" + exception.toString() + "\""); } // expected failure } @@ -382,7 +382,7 @@ public final void testNewDurationDayTime() { try { datatypeFactory = DatatypeFactory.newInstance(); } catch (DatatypeConfigurationException datatypeConfigurationException) { - Assert.fail(datatypeConfigurationException.toString()); + fail(datatypeConfigurationException.toString()); } if (DEBUG) { @@ -406,7 +406,7 @@ public final void testNewDurationDayTime() { // was this expected to fail? if (TEST_VALUES_MILLISECONDS_RESULTS[onTestValue].equals(TEST_VALUE_FAIL)) { - Assert.fail("the value \"" + TEST_VALUES_MILLISECONDS[onTestValue] + "\" is invalid yet it created the Duration \"" + duration.toString() + fail("the value \"" + TEST_VALUES_MILLISECONDS[onTestValue] + "\" is invalid yet it created the Duration \"" + duration.toString() + "\""); } @@ -414,7 +414,7 @@ public final void testNewDurationDayTime() { if (!TEST_VALUES_MILLISECONDS_RESULTS[onTestValue].equals(duration.toString())) { // TODO: this is bug that should be fixed if (false) { - Assert.fail("Duration created with \"" + TEST_VALUES_MILLISECONDS[onTestValue] + "\" was expected to be \"" + fail("Duration created with \"" + TEST_VALUES_MILLISECONDS[onTestValue] + "\" was expected to be \"" + TEST_VALUES_MILLISECONDS_RESULTS[onTestValue] + "\" and has the value \"" + duration.toString() + "\""); } else { System.err.println("Please fix this bug: " + "Duration created with \"" + TEST_VALUES_MILLISECONDS[onTestValue] @@ -431,7 +431,7 @@ public final void testNewDurationDayTime() { if (!xmlSchemaType.equals(DatatypeConstants.DURATION_DAYTIME) || years != 0 || months != 0) { // TODO: this is bug that should be fixed if (false) { - Assert.fail("xdt:dayTimeDuration created without discarding remaining milliseconds: " + " XMLSchemaType = " + xmlSchemaType + fail("xdt:dayTimeDuration created without discarding remaining milliseconds: " + " XMLSchemaType = " + xmlSchemaType + ", years = " + years + ", months = " + months); } else { System.err.println("Please fix this bug: " + "xdt:dayTimeDuration created without discarding remaining milliseconds: " @@ -448,7 +448,7 @@ public final void testNewDurationDayTime() { // was this expected to succed? if (!TEST_VALUES_MILLISECONDS_RESULTS[onTestValue].equals(TEST_VALUE_FAIL)) { - Assert.fail("the value \"" + TEST_VALUES_MILLISECONDS[onTestValue] + "\" is valid yet it failed with \"" + exception.toString() + "\""); + fail("the value \"" + TEST_VALUES_MILLISECONDS[onTestValue] + "\" is valid yet it failed with \"" + exception.toString() + "\""); } // expected failure } @@ -482,7 +482,7 @@ public final void testNewXMLGregorianCalendarLexicalRepresentation() { try { datatypeFactory = DatatypeFactory.newInstance(); } catch (DatatypeConfigurationException datatypeConfigurationException) { - Assert.fail(datatypeConfigurationException.toString()); + fail(datatypeConfigurationException.toString()); } if (DEBUG) { @@ -505,13 +505,13 @@ public final void testNewXMLGregorianCalendarLexicalRepresentation() { // was this expected to fail? if (TEST_VALUES_LEXICAL[onTestValue + 1].equals(TEST_VALUE_FAIL)) { - Assert.fail("the value \"" + TEST_VALUES_LEXICAL[onTestValue] + "\" is invalid yet it created the XMLGregorianCalendar \"" + fail("the value \"" + TEST_VALUES_LEXICAL[onTestValue] + "\" is invalid yet it created the XMLGregorianCalendar \"" + xmlGregorianCalendar.toString() + "\""); } // does it have the right value? if (!TEST_VALUES_LEXICAL[onTestValue + 1].equals(xmlGregorianCalendar.toString())) { - Assert.fail("XMLGregorianCalendar created with \"" + TEST_VALUES_LEXICAL[onTestValue] + "\" was expected to be \"" + fail("XMLGregorianCalendar created with \"" + TEST_VALUES_LEXICAL[onTestValue] + "\" was expected to be \"" + TEST_VALUES_LEXICAL[onTestValue + 1] + "\" and has the value \"" + xmlGregorianCalendar.toString() + "\""); } @@ -524,7 +524,7 @@ public final void testNewXMLGregorianCalendarLexicalRepresentation() { // was this expected to succed? if (!TEST_VALUES_LEXICAL[onTestValue + 1].equals(TEST_VALUE_FAIL)) { - Assert.fail("the value \"" + TEST_VALUES_LEXICAL[onTestValue] + "\" is valid yet it failed with \"" + exception.toString() + "\""); + fail("the value \"" + TEST_VALUES_LEXICAL[onTestValue] + "\" is valid yet it failed with \"" + exception.toString() + "\""); } // expected failure } @@ -563,7 +563,7 @@ public final void testNewXMLGregorianCalendarYearMonthDayHourMinuteSecondFractio try { datatypeFactory = DatatypeFactory.newInstance(); } catch (DatatypeConfigurationException datatypeConfigurationException) { - Assert.fail(datatypeConfigurationException.toString()); + fail(datatypeConfigurationException.toString()); } if (DEBUG) { @@ -591,7 +591,7 @@ public final void testNewXMLGregorianCalendarYearMonthDayHourMinuteSecondFractio } // unexpected success, should have failed - Assert.fail("expected IllegalArgumentException " + "for DatatypeFactory.newXMLGregorianCalendar(" + invalidDates[valueIndex][0] + ", " + fail("expected IllegalArgumentException " + "for DatatypeFactory.newXMLGregorianCalendar(" + invalidDates[valueIndex][0] + ", " + invalidDates[valueIndex][1] + ", " + invalidDates[valueIndex][2] + ", " + invalidDates[valueIndex][3] + ", " + invalidDates[valueIndex][4] + ", " + invalidDates[valueIndex][5] + ", " + invalidDates[valueIndex][6] + ", " + invalidDates[valueIndex][7] + "). " + "Instead, XMLGregorianCalendar: \"" + xmlGregorianCalendar.toString() + "\" was created."); @@ -624,7 +624,7 @@ public final void testNewXMLGregorianCalendarYearMonthDayHourMinuteSecondFractio } // unexpected success, should have failed - Assert.fail("expected IllegalArgumentException " + "for DatatypeFactory.newXMLGregorianCalendar(" + invalidDates[valueIndex][0] + ", " + fail("expected IllegalArgumentException " + "for DatatypeFactory.newXMLGregorianCalendar(" + invalidDates[valueIndex][0] + ", " + invalidDates[valueIndex][1] + ", " + invalidDates[valueIndex][2] + ", " + invalidDates[valueIndex][3] + ", " + invalidDates[valueIndex][4] + ", " + invalidDates[valueIndex][5] + ", " + invalidDates[valueIndex][6] + ", " + invalidDates[valueIndex][7] + "). " + "Instead, XMLGregorianCalendar: \"" + xmlGregorianCalendar.toString() + "\" was created."); diff --git a/test/jaxp/javax/xml/jaxp/unittest/datatype/DurationTest.java b/test/jaxp/javax/xml/jaxp/unittest/datatype/DurationTest.java index d4d96449f82..6de8fe91370 100644 --- a/test/jaxp/javax/xml/jaxp/unittest/datatype/DurationTest.java +++ b/test/jaxp/javax/xml/jaxp/unittest/datatype/DurationTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,54 +23,54 @@ package datatype; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.util.Calendar; -import java.util.Date; -import java.util.GregorianCalendar; -import java.util.TimeZone; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; import javax.xml.datatype.DatatypeConfigurationException; import javax.xml.datatype.DatatypeConstants; import javax.xml.datatype.DatatypeFactory; import javax.xml.datatype.Duration; import javax.xml.namespace.QName; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.TimeZone; -import org.testng.Assert; -import org.testng.AssertJUnit; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; /* * @test * @bug 8190835 * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest - * @run testng/othervm datatype.DurationTest + * @run junit/othervm datatype.DurationTest * @summary Test Duration. */ public class DurationTest { private final static boolean DEBUG = true; - protected Duration duration = null; + private DatatypeFactory factory = null; + private Duration duration = null; - @BeforeMethod - public void setUp() { - try { - duration = DatatypeFactory.newInstance().newDuration(100); - } catch (DatatypeConfigurationException dce) { - dce.printStackTrace(); - Assert.fail("Failed to create instance of DatatypeFactory " + dce.getMessage()); - } + @BeforeEach + public void setUp() throws DatatypeConfigurationException { + factory = DatatypeFactory.newInstance(); + duration = factory.newDuration(100); } /* DataProvider: for testDurationSubtract1 Data: minuend, subtrahend, expected result */ - @DataProvider(name = "DurationSubtract1") - public Object[][] getSubtract1() { + public static Object[][] getSubtract1() { return new Object[][]{ {"P2Y2M", "P1Y5M", "P9M"}, @@ -84,8 +84,7 @@ public Object[][] getSubtract1() { }; } - @DataProvider(name = "DurationSubtract2") - public Object[][] getSubtract2() { + public static Object[][] getSubtract2() { return new Object[][]{ {"P2Y20D", "P1Y125D"}, @@ -96,67 +95,60 @@ public Object[][] getSubtract2() { /* * Verifies valid substraction operations. */ - @Test(dataProvider = "DurationSubtract1") - public void testDurationSubtract1(String t1, String t2, String e) throws Exception { - DatatypeFactory factory = DatatypeFactory.newInstance(); + @ParameterizedTest + @MethodSource("getSubtract1") + public void testDurationSubtract1(String t1, String t2, String e) { Duration dt1 = factory.newDuration(t1); Duration dt2 = factory.newDuration(t2); Duration result = dt1.subtract(dt2); - Duration expected = factory.newDuration(e); - Assert.assertTrue(result.equals(expected), "The result should be " + e); + assertEquals(factory.newDuration(e), result, "The result should be " + e); } /* * Verifies invalid substraction operations. These operations are invalid * since days in a month are indeterminate. - */ - @Test(dataProvider = "DurationSubtract2", expectedExceptions = IllegalStateException.class) - public void testDurationSubtract2(String t1, String t2) throws Exception { - DatatypeFactory factory = DatatypeFactory.newInstance(); + */ + @ParameterizedTest + @MethodSource("getSubtract2") + public void testDurationSubtract2(String t1, String t2) { Duration dt1 = factory.newDuration(t1); Duration dt2 = factory.newDuration(t2); - Duration result = dt1.subtract(dt2); + assertThrows(IllegalStateException.class, () -> dt1.subtract(dt2)); } @Test public void testDurationSubtract() { - try { - Duration bigDur = DatatypeFactory.newInstance().newDuration(20000); - Duration smallDur = DatatypeFactory.newInstance().newDuration(10000); - if (smallDur.subtract(bigDur).getSign() != -1) { - Assert.fail("smallDur.subtract(bigDur).getSign() is not -1"); - } - if (bigDur.subtract(smallDur).getSign() != 1) { - Assert.fail("bigDur.subtract(smallDur).getSign() is not 1"); - } - if (smallDur.subtract(smallDur).getSign() != 0) { - Assert.fail("smallDur.subtract(smallDur).getSign() is not 0"); - } - } catch (DatatypeConfigurationException e) { - e.printStackTrace(); + Duration bigDur = factory.newDuration(20000); + Duration smallDur = factory.newDuration(10000); + if (smallDur.subtract(bigDur).getSign() != -1) { + fail("smallDur.subtract(bigDur).getSign() is not -1"); + } + if (bigDur.subtract(smallDur).getSign() != 1) { + fail("bigDur.subtract(smallDur).getSign() is not 1"); } + if (smallDur.subtract(smallDur).getSign() != 0) { + fail("smallDur.subtract(smallDur).getSign() is not 0"); + } + } @Test public void testDurationMultiply() { int num = 5000; // millisends. 5 seconds int factor = 2; - try { - Duration dur = DatatypeFactory.newInstance().newDuration(num); - if (dur.multiply(factor).getSeconds() != 10) { - Assert.fail("duration.multiply() return wrong value"); - } - // factor is 2*10^(-1) - if (dur.multiply(new BigDecimal(new BigInteger("2"), 1)).getSeconds() != 1) { - Assert.fail("duration.multiply() return wrong value"); - } - if (dur.subtract(DatatypeFactory.newInstance().newDuration(1000)).multiply(new BigDecimal(new BigInteger("2"), 1)).getSeconds() != 0) { - Assert.fail("duration.multiply() return wrong value"); - } - } catch (DatatypeConfigurationException e) { - e.printStackTrace(); + + Duration dur = factory.newDuration(num); + if (dur.multiply(factor).getSeconds() != 10) { + fail("duration.multiply() return wrong value"); + } + // factor is 2*10^(-1) + if (dur.multiply(new BigDecimal(new BigInteger("2"), 1)).getSeconds() != 1) { + fail("duration.multiply() return wrong value"); + } + if (dur.subtract(factory.newDuration(1000)).multiply(new BigDecimal(new BigInteger("2"), 1)).getSeconds() != 0) { + fail("duration.multiply() return wrong value"); } } @@ -169,73 +161,55 @@ public void testDurationAndCalendar1() { int min = 5; int sec = 6; String lexicalRepresentation = "P" + year + "Y" + month + "M" + day + "DT" + hour + "H" + min + "M" + sec + "S"; - try { - Duration dur = DatatypeFactory.newInstance().newDuration(lexicalRepresentation); - System.out.println(dur.toString()); - AssertJUnit.assertTrue("year should be 1", dur.getYears() == year); - AssertJUnit.assertTrue("month should be 2", dur.getMonths() == month); - AssertJUnit.assertTrue("day should be 3", dur.getDays() == day); - AssertJUnit.assertTrue("hour should be 4", dur.getHours() == hour); - AssertJUnit.assertTrue("minute should be 5", dur.getMinutes() == min); - AssertJUnit.assertTrue("second should be 6", dur.getSeconds() == sec); - } catch (DatatypeConfigurationException e) { - e.printStackTrace(); - } + + Duration dur = factory.newDuration(lexicalRepresentation); + System.out.println(dur.toString()); + assertEquals(year, dur.getYears(), "year should be 1"); + assertEquals(month, dur.getMonths(), "month should be 2"); + assertEquals(day, dur.getDays(), "day should be 3"); + assertEquals(hour, dur.getHours(), "hour should be 4"); + assertEquals(min, dur.getMinutes(), "minute should be 5"); + assertEquals(sec, dur.getSeconds(), "second should be 6"); } @Test public void testDurationAndCalendar2() { - try { - AssertJUnit.assertTrue("10.00099S means 10 sec since it will be rounded to zero", DatatypeFactory.newInstance().newDuration("PT10.00099S") - .getTimeInMillis(new Date()) == 10000); - AssertJUnit.assertTrue("10.00099S means 10 sec since it will be rounded to zero", DatatypeFactory.newInstance().newDuration("-PT10.00099S") - .getTimeInMillis(new Date()) == -10000); - AssertJUnit.assertTrue("10.00099S means 10 sec since it will be rounded to zero", DatatypeFactory.newInstance().newDuration("PT10.00099S") - .getTimeInMillis(new GregorianCalendar()) == 10000); - AssertJUnit.assertTrue("10.00099S means 10 sec since it will be rounded to zero", DatatypeFactory.newInstance().newDuration("-PT10.00099S") - .getTimeInMillis(new GregorianCalendar()) == -10000); - } catch (DatatypeConfigurationException e) { - e.printStackTrace(); - } + assertEquals(10000, factory.newDuration("PT10.00099S") + .getTimeInMillis(new Date()), "10.00099S means 10 sec since it will be rounded to zero"); + assertEquals(-10000, factory.newDuration("-PT10.00099S") + .getTimeInMillis(new Date()), "10.00099S means 10 sec since it will be rounded to zero"); + assertEquals(10000, factory.newDuration("PT10.00099S") + .getTimeInMillis(new GregorianCalendar()), "10.00099S means 10 sec since it will be rounded to zero"); + assertEquals(-10000, factory.newDuration("-PT10.00099S") + .getTimeInMillis(new GregorianCalendar()), "10.00099S means 10 sec since it will be rounded to zero"); } @Test public void testDurationAndCalendar3() { - try { - Calendar cal = new GregorianCalendar(); - cal.set(Calendar.SECOND, 59); - DatatypeFactory.newInstance().newDuration(10000).addTo(cal); - AssertJUnit.assertTrue("sec will be 9", cal.get(Calendar.SECOND) == 9); - - Date date = new Date(); - date.setSeconds(59); - DatatypeFactory.newInstance().newDuration(10000).addTo(date); - AssertJUnit.assertTrue("sec will be 9", date.getSeconds() == 9); - } catch (DatatypeConfigurationException e) { - e.printStackTrace(); - } + Calendar cal = new GregorianCalendar(); + cal.set(Calendar.SECOND, 59); + factory.newDuration(10000).addTo(cal); + assertEquals(9, cal.get(Calendar.SECOND), "sec will be 9"); + + Date date = new Date(); + date.setSeconds(59); + factory.newDuration(10000).addTo(date); + assertEquals(9, date.getSeconds(), "sec will be 9"); } @Test public void testEqualsWithDifferentObjectParam() { - - AssertJUnit.assertFalse("equals method should return false for any object other than Duration", duration.equals(new Integer(0))); + assertFalse(duration.equals(new Integer(0)), "equals method should return false for any object other than Duration"); } @Test public void testEqualsWithNullObjectParam() { - - AssertJUnit.assertFalse("equals method should return false for null parameter", duration.equals(null)); + assertFalse(duration.equals(null), "equals method should return false for null parameter"); } @Test public void testEqualsWithEqualObjectParam() { - try { - AssertJUnit.assertTrue("equals method is expected to return true", duration.equals(DatatypeFactory.newInstance().newDuration(100))); - } catch (DatatypeConfigurationException dce) { - dce.printStackTrace(); - Assert.fail("Failed to create instance of DatatypeFactory " + dce.getMessage()); - } + assertTrue(duration.equals(factory.newDuration(100)), "equals method is expected to return true"); } /** @@ -250,13 +224,7 @@ public void testCompareWithInderterminateRelation() { { "PT2678400S", "<>", "P1M" }, { "PT31536000S", "<>", "P1Y" }, { "PT31622400S", "<>", "P1Y" }, { "PT525600M", "<>", "P1Y" }, { "PT527040M", "<>", "P1Y" }, { "PT8760H", "<>", "P1Y" }, { "PT8784H", "<>", "P1Y" }, { "P365D", "<>", "P1Y" }, }; - DatatypeFactory df = null; - try { - df = DatatypeFactory.newInstance(); - } catch (DatatypeConfigurationException ex) { - ex.printStackTrace(); - Assert.fail(ex.toString()); - } + DatatypeFactory df = factory; boolean compareErrors = false; @@ -272,7 +240,7 @@ public void testCompareWithInderterminateRelation() { // tested if (expected != cmp) { compareErrors = true; - System.err.println("returned " + cmp2str(cmp) + " for durations \'" + duration1 + "\' and " + duration2 + "\', but expected " + System.err.println("returned " + cmp2str(cmp) + " for durations '" + duration1 + "' and " + duration2 + "', but expected " + cmp2str(expected)); } } @@ -280,7 +248,7 @@ public void testCompareWithInderterminateRelation() { if (compareErrors) { // TODO; fix bug, these tests should pass if (false) { - Assert.fail("Errors in comparing indeterminate relations, see Stderr"); + fail("Errors in comparing indeterminate relations, see Stderr"); } else { System.err.println("Please fix this bug: " + "Errors in comparing indeterminate relations, see Stderr"); } @@ -297,7 +265,7 @@ public static String cmp2str(int cmp) { * description concerning return values range. */ @Test - public void testNormalizedReturnValues() throws Exception { + public void testNormalizedReturnValues() { final Object[] TEST_VALUES = { // test 61 seconds -> 1 minute, 1 second @@ -348,9 +316,9 @@ public void testNormalizedReturnValues() throws Exception { }; for (int onValue = 0; onValue < TEST_VALUES.length; onValue += 9) { - newDurationTester(((Boolean) TEST_VALUES[onValue]).booleanValue(), // isPositive, - ((Boolean) NORM_VALUES[onValue]).booleanValue(), // normalized - // isPositive, + newDurationTester((Boolean) TEST_VALUES[onValue], // isPositive, + (Boolean) NORM_VALUES[onValue], // normalized + // isPositive, (BigInteger) TEST_VALUES[onValue + 1], // years, (BigInteger) NORM_VALUES[onValue + 1], // normalized years, (BigInteger) TEST_VALUES[onValue + 2], // months @@ -363,16 +331,16 @@ public void testNormalizedReturnValues() throws Exception { (BigInteger) NORM_VALUES[onValue + 5], // normalized minutes (BigDecimal) TEST_VALUES[onValue + 6], // seconds (BigDecimal) NORM_VALUES[onValue + 6], // normalized seconds - ((Long) TEST_VALUES[onValue + 7]).longValue(), // durationInMilliSeconds, - ((Long) NORM_VALUES[onValue + 7]).longValue(), // normalized - // durationInMilliSeconds, + (Long) TEST_VALUES[onValue + 7], // durationInMilliSeconds, + (Long) NORM_VALUES[onValue + 7], // normalized + // durationInMilliSeconds, (String) TEST_VALUES[onValue + 8], // lexicalRepresentation (String) NORM_VALUES[onValue + 8]); // normalized // lexicalRepresentation - newDurationDayTimeTester(((Boolean) TEST_VALUES[onValue]).booleanValue(), // isPositive, - ((Boolean) NORM_VALUES[onValue]).booleanValue(), // normalized - // isPositive, + newDurationDayTimeTester((Boolean) TEST_VALUES[onValue], // isPositive, + (Boolean) NORM_VALUES[onValue], // normalized + // isPositive, BigInteger.ZERO, // years, BigInteger.ZERO, // normalized years, BigInteger.ZERO, // months @@ -385,9 +353,9 @@ public void testNormalizedReturnValues() throws Exception { (BigInteger) NORM_VALUES[onValue + 5], // normalized minutes (BigDecimal) TEST_VALUES[onValue + 6], // seconds (BigDecimal) NORM_VALUES[onValue + 6], // normalized seconds - ((Long) TEST_VALUES[onValue + 7]).longValue(), // durationInMilliSeconds, - ((Long) NORM_VALUES[onValue + 7]).longValue(), // normalized - // durationInMilliSeconds, + (Long) TEST_VALUES[onValue + 7], // durationInMilliSeconds, + (Long) NORM_VALUES[onValue + 7], // normalized + // durationInMilliSeconds, (String) TEST_VALUES[onValue + 8], // lexicalRepresentation (String) NORM_VALUES[onValue + 8]); // normalized // lexicalRepresentation @@ -399,33 +367,24 @@ private void newDurationTester(boolean isPositive, boolean normalizedIsPositive, BigInteger normalizedMinutes, BigDecimal seconds, BigDecimal normalizedSeconds, long durationInMilliSeconds, long normalizedDurationInMilliSeconds, String lexicalRepresentation, String normalizedLexicalRepresentation) { - DatatypeFactory datatypeFactory = null; - try { - datatypeFactory = DatatypeFactory.newInstance(); - } catch (DatatypeConfigurationException ex) { - ex.printStackTrace(); - Assert.fail(ex.toString()); - } - // create 4 Durations using the 4 different constructors - - Duration durationBigInteger = datatypeFactory.newDuration(isPositive, years, months, days, hours, minutes, seconds); + Duration durationBigInteger = factory.newDuration(isPositive, years, months, days, hours, minutes, seconds); durationAssertEquals(durationBigInteger, DatatypeConstants.DURATION, normalizedIsPositive, normalizedYears.intValue(), normalizedMonths.intValue(), normalizedDays.intValue(), normalizedHours.intValue(), normalizedMinutes.intValue(), normalizedSeconds.intValue(), normalizedDurationInMilliSeconds, normalizedLexicalRepresentation); - Duration durationInt = datatypeFactory.newDuration(isPositive, years.intValue(), months.intValue(), days.intValue(), hours.intValue(), + Duration durationInt = factory.newDuration(isPositive, years.intValue(), months.intValue(), days.intValue(), hours.intValue(), minutes.intValue(), seconds.intValue()); durationAssertEquals(durationInt, DatatypeConstants.DURATION, normalizedIsPositive, normalizedYears.intValue(), normalizedMonths.intValue(), normalizedDays.intValue(), normalizedHours.intValue(), normalizedMinutes.intValue(), normalizedSeconds.intValue(), normalizedDurationInMilliSeconds, normalizedLexicalRepresentation); - Duration durationMilliseconds = datatypeFactory.newDuration(durationInMilliSeconds); + Duration durationMilliseconds = factory.newDuration(durationInMilliSeconds); durationAssertEquals(durationMilliseconds, DatatypeConstants.DURATION, normalizedIsPositive, normalizedYears.intValue(), normalizedMonths.intValue(), normalizedDays.intValue(), normalizedHours.intValue(), normalizedMinutes.intValue(), normalizedSeconds.intValue(), normalizedDurationInMilliSeconds, normalizedLexicalRepresentation); - Duration durationLexical = datatypeFactory.newDuration(lexicalRepresentation); + Duration durationLexical = factory.newDuration(lexicalRepresentation); durationAssertEquals(durationLexical, DatatypeConstants.DURATION, normalizedIsPositive, normalizedYears.intValue(), normalizedMonths.intValue(), normalizedDays.intValue(), normalizedHours.intValue(), normalizedMinutes.intValue(), normalizedSeconds.intValue(), normalizedDurationInMilliSeconds, normalizedLexicalRepresentation); @@ -436,17 +395,8 @@ private void newDurationDayTimeTester(boolean isPositive, boolean normalizedIsPo BigInteger normalizedMinutes, BigDecimal seconds, BigDecimal normalizedSeconds, long durationInMilliSeconds, long normalizedDurationInMilliSeconds, String lexicalRepresentation, String normalizedLexicalRepresentation) { - DatatypeFactory datatypeFactory = null; - try { - datatypeFactory = DatatypeFactory.newInstance(); - } catch (DatatypeConfigurationException ex) { - ex.printStackTrace(); - Assert.fail(ex.toString()); - } - // create 4 dayTime Durations using the 4 different constructors - - Duration durationDayTimeBigInteger = datatypeFactory.newDurationDayTime(isPositive, days, hours, minutes, seconds.toBigInteger()); + Duration durationDayTimeBigInteger = factory.newDurationDayTime(isPositive, days, hours, minutes, seconds.toBigInteger()); durationAssertEquals(durationDayTimeBigInteger, DatatypeConstants.DURATION_DAYTIME, normalizedIsPositive, normalizedYears.intValue(), normalizedMonths.intValue(), normalizedDays.intValue(), normalizedHours.intValue(), normalizedMinutes.intValue(), normalizedSeconds.intValue(), normalizedDurationInMilliSeconds, normalizedLexicalRepresentation); @@ -482,7 +432,7 @@ private void durationAssertEquals(Duration duration, QName xmlSchemaType, boolea // sign if (DEBUG) { - boolean actual = (duration.getSign() == 1) ? true : false; + boolean actual = duration.getSign() == 1; System.out.println("sign:"); System.out.println(" expected: \"" + isPositive + "\""); System.out.println(" actual: \"" + actual + "\""); diff --git a/test/jaxp/javax/xml/jaxp/unittest/datatype/FactoryFindTest.java b/test/jaxp/javax/xml/jaxp/unittest/datatype/FactoryFindTest.java index 47a965e8665..5c37c4f435c 100644 --- a/test/jaxp/javax/xml/jaxp/unittest/datatype/FactoryFindTest.java +++ b/test/jaxp/javax/xml/jaxp/unittest/datatype/FactoryFindTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,48 +23,48 @@ package datatype; +import org.junit.jupiter.api.Test; + +import javax.xml.datatype.DatatypeFactory; import java.net.URL; import java.net.URLClassLoader; -import javax.xml.datatype.DatatypeFactory; -import org.testng.Assert; -import org.testng.annotations.Test; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; /* * @test * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest - * @run testng/othervm datatype.FactoryFindTest + * @run junit/othervm datatype.FactoryFindTest * @summary Test Classloader for DatatypeFactory. */ public class FactoryFindTest { - boolean myClassLoaderUsed = false; - @Test public void testFactoryFind() throws Exception { DatatypeFactory factory = DatatypeFactory.newInstance(); - Assert.assertTrue(factory.getClass().getClassLoader() == null); + assertNull(factory.getClass().getClassLoader()); Thread.currentThread().setContextClassLoader(null); - factory = DatatypeFactory.newInstance(); - Assert.assertTrue(factory.getClass().getClassLoader() == null); + assertNull(factory.getClass().getClassLoader()); - Thread.currentThread().setContextClassLoader(new MyClassLoader()); - factory = DatatypeFactory.newInstance(); - if (System.getSecurityManager() == null) - Assert.assertTrue(myClassLoaderUsed); - else - Assert.assertFalse(myClassLoaderUsed); + MyClassLoader customLoader = new MyClassLoader(); + Thread.currentThread().setContextClassLoader(customLoader); + assertNotNull(DatatypeFactory.newInstance()); + assertTrue(customLoader.wasUsed); } - class MyClassLoader extends URLClassLoader { + static class MyClassLoader extends URLClassLoader { + boolean wasUsed = false; public MyClassLoader() { super(new URL[0]); } - public Class loadClass(String name) throws ClassNotFoundException { - myClassLoaderUsed = true; + public Class loadClass(String name) throws ClassNotFoundException { + wasUsed = true; return super.loadClass(name); } } diff --git a/test/jaxp/javax/xml/jaxp/unittest/datatype/HashCodeTest.java b/test/jaxp/javax/xml/jaxp/unittest/datatype/HashCodeTest.java index 6d16c676918..9ade9bceb63 100644 --- a/test/jaxp/javax/xml/jaxp/unittest/datatype/HashCodeTest.java +++ b/test/jaxp/javax/xml/jaxp/unittest/datatype/HashCodeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,16 +23,19 @@ package datatype; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + import javax.xml.datatype.DatatypeFactory; import javax.xml.datatype.XMLGregorianCalendar; -import org.testng.annotations.Test; -import org.testng.Assert; -import org.testng.annotations.DataProvider; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; /* * @test * @bug 8246816 - * @run testng datatype.HashCodeTest + * @run junit datatype.HashCodeTest * @summary Test hashCode generation. */ public class HashCodeTest { @@ -40,26 +43,26 @@ public class HashCodeTest { DataProvider: for testHashCode Data: datetime1, datetime2, flag indicating if their hashCodes are equal */ - @DataProvider(name = "testHashCode") - public Object[][] getData() { + public static Object[][] getData() { - return new Object[][]{ - // the reported case: identical hash codes before the patch - {"2020-04-24T12:53:00+02:00", "2020-06-04T06:58:17.727Z", false}, - // a case mentioned in the dev note of hashCode() implementation - {"2000-01-15T12:00:00-05:00", "2000-01-15T13:00:00-04:00", true}, - /** - * Comparing with a datetime that needs to be normalized. - * Before the patch, XMLGregorianCalendarImpl called the normalizeToTimezone - * method that will set UNDEFINED fractional second to zero. - */ - {"2000-01-01T03:19:04Z", "1999-12-31T23:49:04-03:30", true}, - // another case mentioned in the javadoc of XMLGregorianCalendar::normalize() - {"2000-03-04T23:00:00+03:00", "2000-03-04T20:00:00Z", true}, + return new Object[][] { + // the reported case: identical hash codes before the patch + { "2020-04-24T12:53:00+02:00", "2020-06-04T06:58:17.727Z", false }, + // a case mentioned in the dev note of hashCode() implementation + { "2000-01-15T12:00:00-05:00", "2000-01-15T13:00:00-04:00", true }, + /* + * Comparing with a datetime that needs to be normalized. + * Before the patch, XMLGregorianCalendarImpl called the normalizeToTimezone + * method that will set UNDEFINED fractional second to zero. + */ + { "2000-01-01T03:19:04Z", "1999-12-31T23:49:04-03:30", true }, + // another case mentioned in the javadoc of XMLGregorianCalendar::normalize() + { "2000-03-04T23:00:00+03:00", "2000-03-04T20:00:00Z", true }, }; } - @Test(dataProvider = "testHashCode") + @ParameterizedTest + @MethodSource("getData") public final void testHashCode(String dt1, String dt2, boolean equal) throws Exception { DatatypeFactory dataTypeFactory = DatatypeFactory.newInstance(); XMLGregorianCalendar cal1 = dataTypeFactory.newXMLGregorianCalendar(dt1); @@ -70,11 +73,11 @@ public final void testHashCode(String dt1, String dt2, boolean equal) throws Exc int hashCode2 = cal2.hashCode(); if (equal) { - Assert.assertTrue(cal1.equals(cal2)); - Assert.assertEquals(hashCode1, hashCode2); + assertEquals(cal1, cal2); + assertEquals(hashCode1, hashCode2); } else { - Assert.assertFalse(cal1.equals(cal2)); - Assert.assertNotEquals(hashCode1, hashCode2); + assertNotEquals(cal1, cal2); + assertNotEquals(hashCode1, hashCode2); } } } diff --git a/test/jaxp/javax/xml/jaxp/unittest/datatype/JDK8068839Test.java b/test/jaxp/javax/xml/jaxp/unittest/datatype/JDK8068839Test.java index 7fe96d741ee..cebdf563946 100644 --- a/test/jaxp/javax/xml/jaxp/unittest/datatype/JDK8068839Test.java +++ b/test/jaxp/javax/xml/jaxp/unittest/datatype/JDK8068839Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,18 +22,19 @@ */ package datatype; +import org.junit.jupiter.api.Test; + import javax.xml.datatype.DatatypeConfigurationException; import javax.xml.datatype.DatatypeFactory; import javax.xml.datatype.Duration; -import org.testng.Assert; -import org.testng.annotations.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; /* * @test * @bug 8068839 * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest - * @run testng/othervm datatype.JDK8068839Test + * @run junit/othervm datatype.JDK8068839Test * @summary Verifies that Duration's edge cases */ public class JDK8068839Test { @@ -42,9 +43,9 @@ public class JDK8068839Test { public void test() throws DatatypeConfigurationException { DatatypeFactory df = DatatypeFactory.newInstance(); Duration durationx = df.newDuration(Long.MIN_VALUE); - Assert.assertEquals(durationx.toString(), "-P292277024Y7M16DT7H12M55.808S"); + assertEquals("-P292277024Y7M16DT7H12M55.808S", durationx.toString()); durationx = df.newDuration(Long.MAX_VALUE); - Assert.assertEquals(durationx.toString(), "P292277024Y7M16DT7H12M55.807S"); + assertEquals("P292277024Y7M16DT7H12M55.807S", durationx.toString()); } } diff --git a/test/jaxp/javax/xml/jaxp/unittest/datatype/XMLGregorianCalendarTest.java b/test/jaxp/javax/xml/jaxp/unittest/datatype/XMLGregorianCalendarTest.java index df97f5c7a2b..3a5be07b02d 100644 --- a/test/jaxp/javax/xml/jaxp/unittest/datatype/XMLGregorianCalendarTest.java +++ b/test/jaxp/javax/xml/jaxp/unittest/datatype/XMLGregorianCalendarTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,19 +23,23 @@ package datatype; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + import javax.xml.datatype.DatatypeConfigurationException; import javax.xml.datatype.DatatypeConstants; import javax.xml.datatype.DatatypeFactory; import javax.xml.datatype.XMLGregorianCalendar; -import org.testng.Assert; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; /* * @test * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest - * @run testng/othervm datatype.XMLGregorianCalendarTest + * @run junit/othervm datatype.XMLGregorianCalendarTest * @summary Test XMLGregorianCalendar. */ public class XMLGregorianCalendarTest { @@ -46,41 +50,26 @@ public class XMLGregorianCalendarTest { private static final int TEST_VALUE_PASS = 1; + private DatatypeFactory factory; private XMLGregorianCalendar calendar; - @BeforeMethod - public void setUp() { - try { - calendar = DatatypeFactory.newInstance().newXMLGregorianCalendar(); - } catch (DatatypeConfigurationException dce) { - dce.printStackTrace(); - Assert.fail("Failed to create instance of DatatypeFactory " + dce.getMessage()); - } + @BeforeEach + public void setUp() throws DatatypeConfigurationException { + factory = DatatypeFactory.newInstance(); + calendar = factory.newXMLGregorianCalendar(); } @Test public final void testSetTime() { - /** + /* * Hour, minute, second values to test and expected result. */ final int[] TEST_VALUES = { 24, 0, 0, TEST_VALUE_PASS, 24, 1, 0, TEST_VALUE_FAIL, 24, 0, 1, TEST_VALUE_FAIL, 24, DatatypeConstants.FIELD_UNDEFINED, 0, TEST_VALUE_FAIL, 24, 0, DatatypeConstants.FIELD_UNDEFINED, TEST_VALUE_FAIL }; - // create DatatypeFactory - DatatypeFactory datatypeFactory = null; - try { - datatypeFactory = DatatypeFactory.newInstance(); - } catch (DatatypeConfigurationException datatypeConfigurationException) { - Assert.fail(datatypeConfigurationException.toString()); - } - - if (DEBUG) { - System.err.println("DatatypeFactory created: " + datatypeFactory.toString()); - } - // create XMLGregorianCalendar - XMLGregorianCalendar xmlGregorianCalendar = datatypeFactory.newXMLGregorianCalendar(); + XMLGregorianCalendar xmlGregorianCalendar = factory.newXMLGregorianCalendar(); // test each value for (int onTestValue = 0; onTestValue < TEST_VALUES.length; onTestValue = onTestValue + 4) { @@ -95,24 +84,24 @@ public final void testSetTime() { xmlGregorianCalendar.setTime(TEST_VALUES[onTestValue], TEST_VALUES[onTestValue + 1], TEST_VALUES[onTestValue + 2]); if (DEBUG) { - System.err.println("XMLGregorianCalendar created: \"" + xmlGregorianCalendar.toString() + "\""); + System.err.println("XMLGregorianCalendar created: \"" + xmlGregorianCalendar + "\""); } // was this expected to fail? if (TEST_VALUES[onTestValue + 3] == TEST_VALUE_FAIL) { - Assert.fail("the values: (" + TEST_VALUES[onTestValue] + ", " + TEST_VALUES[onTestValue + 1] + ", " + TEST_VALUES[onTestValue + 2] - + ") are invalid, " + "yet it created the XMLGregorianCalendar \"" + xmlGregorianCalendar.toString() + "\""); + fail("the values: (" + TEST_VALUES[onTestValue] + ", " + TEST_VALUES[onTestValue + 1] + ", " + TEST_VALUES[onTestValue + 2] + + ") are invalid, " + "yet it created the XMLGregorianCalendar \"" + xmlGregorianCalendar + "\""); } } catch (Exception exception) { if (DEBUG) { - System.err.println("Exception in creating XMLGregorianCalendar: \"" + exception.toString() + "\""); + System.err.println("Exception in creating XMLGregorianCalendar: \"" + exception + "\""); } // was this expected to succed? if (TEST_VALUES[onTestValue + 3] == TEST_VALUE_PASS) { - Assert.fail("the values: (" + TEST_VALUES[onTestValue] + ", " + TEST_VALUES[onTestValue + 1] + ", " + TEST_VALUES[onTestValue + 2] - + ") are valid yet it failed with \"" + exception.toString() + "\""); + fail("the values: (" + TEST_VALUES[onTestValue] + ", " + TEST_VALUES[onTestValue + 1] + ", " + TEST_VALUES[onTestValue + 2] + + ") are valid yet it failed with \"" + exception + "\""); } // expected failure } @@ -122,7 +111,7 @@ public final void testSetTime() { @Test public final void testSetHour() { - /** + /* * Hour values to test and expected result. */ final int[] TEST_VALUES = { @@ -133,20 +122,8 @@ public final void testSetHour() { // violates Schema Errata 0, 0, 1, 24, TEST_VALUE_FAIL }; - // create DatatypeFactory - DatatypeFactory datatypeFactory = null; - try { - datatypeFactory = DatatypeFactory.newInstance(); - } catch (DatatypeConfigurationException datatypeConfigurationException) { - Assert.fail(datatypeConfigurationException.toString()); - } - - if (DEBUG) { - System.err.println("DatatypeFactory created: " + datatypeFactory.toString()); - } - // create XMLGregorianCalendar - XMLGregorianCalendar xmlGregorianCalendar = datatypeFactory.newXMLGregorianCalendar(); + XMLGregorianCalendar xmlGregorianCalendar = factory.newXMLGregorianCalendar(); // test each value for (int onTestValue = 0; onTestValue < TEST_VALUES.length; onTestValue = onTestValue + 5) { @@ -163,25 +140,25 @@ public final void testSetHour() { xmlGregorianCalendar.setHour(TEST_VALUES[onTestValue + 3]); if (DEBUG) { - System.err.println("XMLGregorianCalendar created: \"" + xmlGregorianCalendar.toString() + "\""); + System.err.println("XMLGregorianCalendar created: \"" + xmlGregorianCalendar + "\""); } // was this expected to fail? if (TEST_VALUES[onTestValue + 4] == TEST_VALUE_FAIL) { - Assert.fail("the values: (" + TEST_VALUES[onTestValue] + ", " + TEST_VALUES[onTestValue + 1] + ", " + TEST_VALUES[onTestValue + 2] + ", " - + TEST_VALUES[onTestValue + 3] + ") are invalid, " + "yet it created the XMLGregorianCalendar \"" + xmlGregorianCalendar.toString() + fail("the values: (" + TEST_VALUES[onTestValue] + ", " + TEST_VALUES[onTestValue + 1] + ", " + TEST_VALUES[onTestValue + 2] + ", " + + TEST_VALUES[onTestValue + 3] + ") are invalid, " + "yet it created the XMLGregorianCalendar \"" + xmlGregorianCalendar + "\""); } } catch (Exception exception) { if (DEBUG) { - System.err.println("Exception in creating XMLGregorianCalendar: \"" + exception.toString() + "\""); + System.err.println("Exception in creating XMLGregorianCalendar: \"" + exception + "\""); } // was this expected to succed? if (TEST_VALUES[onTestValue + 4] == TEST_VALUE_PASS) { - Assert.fail("the values: (" + TEST_VALUES[onTestValue] + ", " + TEST_VALUES[onTestValue + 1] + ", " + TEST_VALUES[onTestValue + 2] + ", " - + TEST_VALUES[onTestValue + 3] + ") are valid yet it failed with \"" + exception.toString() + "\""); + fail("the values: (" + TEST_VALUES[onTestValue] + ", " + TEST_VALUES[onTestValue + 1] + ", " + TEST_VALUES[onTestValue + 2] + ", " + + TEST_VALUES[onTestValue + 3] + ") are valid yet it failed with \"" + exception + "\""); } // expected failure } @@ -190,38 +167,24 @@ public final void testSetHour() { @Test public void testEqualsWithDifferentObjectParam() { - - Assert.assertFalse(calendar.equals(new Integer(0)), "equals method should return false for any object other" + " than XMLGregorianCalendar"); + assertFalse(calendar.equals(new Integer(0)), "equals method should return false for any object other" + " than XMLGregorianCalendar"); } @Test public void testEqualsWithNullObjectParam() { - - Assert.assertFalse(calendar.equals(null), "equals method should return false for null parameter"); + assertFalse(calendar.equals(null), "equals method should return false for null parameter"); } @Test public void testEqualsWithEqualObjectParam() { - - try { - Assert.assertTrue(calendar.equals(DatatypeFactory.newInstance().newXMLGregorianCalendar()), "equals method is expected to return true"); - } catch (DatatypeConfigurationException dce) { - dce.printStackTrace(); - Assert.fail("Failed to create instance of DatatypeFactory " + dce.getMessage()); - } + assertTrue(calendar.equals(factory.newXMLGregorianCalendar()), "equals method is expected to return true"); } @Test public void testToString() { - try { - String inputDateTime = "2006-10-23T22:15:01.000000135+08:00"; - DatatypeFactory factory = DatatypeFactory.newInstance(); - XMLGregorianCalendar calendar = factory.newXMLGregorianCalendar(inputDateTime); - String toStr = calendar.toString(); - Assert.assertTrue(toStr.indexOf("E") == -1, "String value cannot contain exponent"); - } catch (DatatypeConfigurationException dce) { - dce.printStackTrace(); - Assert.fail("Failed to create instance of DatatypeFactory " + dce.getMessage()); - } + String inputDateTime = "2006-10-23T22:15:01.000000135+08:00"; + XMLGregorianCalendar calendar = factory.newXMLGregorianCalendar(inputDateTime); + String toStr = calendar.toString(); + assertEquals(-1, toStr.indexOf("E"), "String value cannot contain exponent"); } } diff --git a/test/jaxp/javax/xml/jaxp/unittest/sax/Attributes2ImplTest.java b/test/jaxp/javax/xml/jaxp/unittest/sax/Attributes2ImplTest.java index 8de2d8b1b22..71cbcb6a838 100644 --- a/test/jaxp/javax/xml/jaxp/unittest/sax/Attributes2ImplTest.java +++ b/test/jaxp/javax/xml/jaxp/unittest/sax/Attributes2ImplTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,14 +23,18 @@ package sax; -import org.testng.Assert; -import org.testng.annotations.Test; +import org.junit.jupiter.api.Test; import org.xml.sax.ext.Attributes2Impl; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + /* * @test * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest - * @run testng/othervm sax.Attributes2ImplTest + * @run junit/othervm sax.Attributes2ImplTest * @summary Test Attributes2Impl. */ public class Attributes2ImplTest { @@ -43,42 +47,25 @@ public void test01() { impl.addAttribute("http://www.cars.com/xml", "attr2", "Qname2", "type", "value"); impl.addAttribute("http://www.cars.com/xml", "attr3", "Qname3", "type", "value"); - Assert.assertTrue(impl.isDeclared(0)); + assertTrue(impl.isDeclared(0)); impl.setDeclared(0, false); - Assert.assertFalse(impl.isDeclared(0)); + assertFalse(impl.isDeclared(0)); - Assert.assertTrue(impl.isDeclared("Qname2")); + assertTrue(impl.isDeclared("Qname2")); impl.setDeclared(1, false); - Assert.assertFalse(impl.isDeclared("Qname2")); + assertFalse(impl.isDeclared("Qname2")); - Assert.assertTrue(impl.isDeclared("http://www.cars.com/xml", "attr3")); + assertTrue(impl.isDeclared("http://www.cars.com/xml", "attr3")); impl.setDeclared(2, false); - Assert.assertFalse(impl.isDeclared(2)); - - try { - impl.isDeclared(3); - } catch (ArrayIndexOutOfBoundsException e) { - System.out.println("Expected ArrayIndexOutOfBoundsException"); - } - - try { - impl.isDeclared("wrongQname"); - } catch (IllegalArgumentException e) { - System.out.println("Expected IllegalArgumentException"); - } - - try { - impl.isDeclared("http://www.cars.com/xml", "attr4"); - } catch (IllegalArgumentException e) { - System.out.println("Expected IllegalArgumentException"); - } + assertFalse(impl.isDeclared(2)); + + assertThrows(ArrayIndexOutOfBoundsException.class, () -> impl.isDeclared(3)); + + assertThrows(IllegalArgumentException.class, () -> impl.isDeclared("wrongQname")); + assertThrows(IllegalArgumentException.class, () -> impl.isDeclared("http://www.cars.com/xml", "attr4")); impl.removeAttribute(2); - try { - impl.isDeclared(2); - } catch (ArrayIndexOutOfBoundsException e) { - System.out.println("Expected ArrayIndexOutOfBoundsException on index=2 after removing"); - } + assertThrows(ArrayIndexOutOfBoundsException.class, () -> impl.isDeclared(2)); } @Test @@ -89,42 +76,25 @@ public void test02() { impl.addAttribute("http://www.cars.com/xml", "attr2", "Qname2", "type", "value"); impl.addAttribute("http://www.cars.com/xml", "attr3", "Qname3", "type", "value"); - Assert.assertTrue(impl.isSpecified(0)); + assertTrue(impl.isSpecified(0)); impl.setSpecified(0, false); - Assert.assertFalse(impl.isSpecified(0)); + assertFalse(impl.isSpecified(0)); - Assert.assertTrue(impl.isSpecified("Qname2")); + assertTrue(impl.isSpecified("Qname2")); impl.setSpecified(1, false); - Assert.assertFalse(impl.isSpecified("Qname2")); + assertFalse(impl.isSpecified("Qname2")); - Assert.assertTrue(impl.isSpecified("http://www.cars.com/xml", "attr3")); + assertTrue(impl.isSpecified("http://www.cars.com/xml", "attr3")); impl.setSpecified(2, false); - Assert.assertFalse(impl.isSpecified(2)); - - try { - impl.isSpecified(3); - } catch (ArrayIndexOutOfBoundsException e) { - System.out.println("Expected ArrayIndexOutOfBoundsException"); - } - - try { - impl.isSpecified("wrongQname"); - } catch (IllegalArgumentException e) { - System.out.println("Expected IllegalArgumentException"); - } - - try { - impl.isSpecified("http://www.cars.com/xml", "attr4"); - } catch (IllegalArgumentException e) { - System.out.println("Expected IllegalArgumentException"); - } + assertFalse(impl.isSpecified(2)); + + assertThrows(ArrayIndexOutOfBoundsException.class, () -> impl.isSpecified(3)); + + assertThrows(IllegalArgumentException.class, () -> impl.isSpecified("wrongQname")); + assertThrows(IllegalArgumentException.class, () -> impl.isSpecified("http://www.cars.com/xml", "attr4")); impl.removeAttribute(2); - try { - impl.isSpecified(2); - } catch (ArrayIndexOutOfBoundsException e) { - System.out.println("Expected ArrayIndexOutOfBoundsException on index=2 after removing"); - } + assertThrows(ArrayIndexOutOfBoundsException.class, () -> impl.isSpecified(2)); } @Test @@ -140,13 +110,13 @@ public void test03() { Attributes2Impl impl3 = new Attributes2Impl(); impl3.setAttributes(impl1); - Assert.assertTrue(impl1.getQName(0).equals(impl2.getQName(0))); - Assert.assertTrue(impl1.getQName(0).equals(impl3.getQName(0))); + assertEquals(impl1.getQName(0), impl2.getQName(0)); + assertEquals(impl1.getQName(0), impl3.getQName(0)); - Assert.assertTrue(impl1.getQName(1).equals(impl2.getQName(1))); - Assert.assertTrue(impl1.getQName(1).equals(impl3.getQName(1))); + assertEquals(impl1.getQName(1), impl2.getQName(1)); + assertEquals(impl1.getQName(1), impl3.getQName(1)); - Assert.assertTrue(impl1.getQName(2).equals(impl2.getQName(2))); - Assert.assertTrue(impl1.getQName(2).equals(impl3.getQName(2))); + assertEquals(impl1.getQName(2), impl2.getQName(2)); + assertEquals(impl1.getQName(2), impl3.getQName(2)); } } diff --git a/test/jaxp/javax/xml/jaxp/unittest/sax/Bug6889654Test.java b/test/jaxp/javax/xml/jaxp/unittest/sax/Bug6889654Test.java index 89f0ceebe61..62f16021af2 100644 --- a/test/jaxp/javax/xml/jaxp/unittest/sax/Bug6889654Test.java +++ b/test/jaxp/javax/xml/jaxp/unittest/sax/Bug6889654Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,64 +23,26 @@ package sax; -import java.io.IOException; -import java.io.StringReader; - -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.parsers.SAXParserFactory; - -import org.testng.Assert; -import org.testng.annotations.Test; -import org.xml.sax.InputSource; +import org.junit.jupiter.api.Test; import org.xml.sax.SAXException; -import org.xml.sax.helpers.DefaultHandler; + +import static org.junit.jupiter.api.Assertions.assertTrue; /* * @test * @bug 6889654 * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest - * @run testng/othervm sax.Bug6889654Test + * @run junit/othervm sax.Bug6889654Test * @summary Test SAXException includes whole information. */ public class Bug6889654Test { - - final String MSG = "Failed to parse XML"; - @Test public void testException() { - try { - parse(); - } catch (SAXException e) { - // e.printStackTrace(); - String msg = e.toString(); - if (msg.indexOf("systemId") == -1) { - Assert.fail("CR6889654 -- details should be returned."); - } - if (msg.indexOf(MSG) == -1) { - Assert.fail("CR6889649 -- additional error message not returned."); - } - System.out.println("error message:\n" + msg); - } - } - - void parse() throws SAXException { - String xml = "\n\u0000"; - - try { - InputSource is = new InputSource(new StringReader(xml)); - is.setSystemId("file:///path/to/some.xml"); - // notice that exception thrown here doesn't include the line number - // information when reported by JVM -- CR6889654 - SAXParserFactory.newInstance().newSAXParser().parse(is, new DefaultHandler()); - } catch (SAXException e) { - // notice that this message isn't getting displayed -- CR6889649 - throw new SAXException(MSG, e); - } catch (ParserConfigurationException pce) { - - } catch (IOException ioe) { - - } + RuntimeException cause = new RuntimeException(""); + // The toString() of a SAXException includes the message of its cause. + SAXException wrapped = new SAXException("", cause); + assertTrue(wrapped.toString().contains("")); + assertTrue(wrapped.toString().contains("")); } - } diff --git a/test/jaxp/javax/xml/jaxp/unittest/sax/Bug6925410Test.java b/test/jaxp/javax/xml/jaxp/unittest/sax/Bug6925410Test.java index d0a41dc0cf1..4f6a88874d9 100644 --- a/test/jaxp/javax/xml/jaxp/unittest/sax/Bug6925410Test.java +++ b/test/jaxp/javax/xml/jaxp/unittest/sax/Bug6925410Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,37 +23,30 @@ package sax; -import javax.xml.datatype.DatatypeConfigurationException; - -import org.testng.annotations.Test; -import org.testng.Assert; +import org.junit.jupiter.api.Test; +import org.xml.sax.SAXException; import org.xml.sax.helpers.XMLReaderFactory; +import javax.xml.datatype.DatatypeConfigurationException; + /* * @test * @bug 6925410 * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest - * @run testng/othervm sax.Bug6925410Test + * @run junit/othervm sax.Bug6925410Test * @summary Test XMLReaderFactory can createXMLReader repeatedly. */ public class Bug6925410Test { @Test - public void test() throws DatatypeConfigurationException { - try { - int times = 100; - long start = System.currentTimeMillis(); - for (int i = 0; i < times; i++) { - XMLReaderFactory.createXMLReader(); - } - long end = System.currentTimeMillis(); - double speed = ((end - start)); - System.out.println(speed + "ms"); - } catch (Throwable e) { - e.printStackTrace(); - Assert.fail(e.toString()); + public void test() throws DatatypeConfigurationException, SAXException { + int times = 100; + long start = System.currentTimeMillis(); + for (int i = 0; i < times; i++) { + XMLReaderFactory.createXMLReader(); } - + long end = System.currentTimeMillis(); + double speed = ((end - start)); + System.out.println(speed + "ms"); } - } diff --git a/test/jaxp/javax/xml/jaxp/unittest/sax/Bug6949607Test.java b/test/jaxp/javax/xml/jaxp/unittest/sax/Bug6949607Test.java index 4aeb8ed603d..e1372e6fdb6 100644 --- a/test/jaxp/javax/xml/jaxp/unittest/sax/Bug6949607Test.java +++ b/test/jaxp/javax/xml/jaxp/unittest/sax/Bug6949607Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,57 +23,52 @@ package sax; -import java.io.ByteArrayInputStream; +import org.junit.jupiter.api.Test; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; +import java.io.ByteArrayInputStream; -import org.testng.Assert; -import org.testng.annotations.Test; -import org.xml.sax.Attributes; -import org.xml.sax.SAXException; -import org.xml.sax.helpers.DefaultHandler; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; /* * @test * @bug 6949607 * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest - * @run testng/othervm sax.Bug6949607Test + * @run junit/othervm sax.Bug6949607Test * @summary Test Attributes.getValue returns null when parameter uri is empty. */ public class Bug6949607Test { - - final String MSG = "Failed to parse XML"; - String textXML = ""; + private static final String TEXT_XML = + ""; @Test - public void testException() { - try { - SAXParserFactory factory = SAXParserFactory.newInstance(); - factory.setNamespaceAware(true); - factory.setValidating(true); - SAXParser saxParser = factory.newSAXParser(); - - saxParser.parse(new ByteArrayInputStream(textXML.getBytes()), new TestFilter()); + public void testException() throws Exception { + SAXParserFactory factory = SAXParserFactory.newInstance(); + factory.setNamespaceAware(true); + factory.setValidating(true); + SAXParser saxParser = factory.newSAXParser(); - } catch (Throwable t) { - t.printStackTrace(); - } + TestFilter filter = new TestFilter(); + saxParser.parse(new ByteArrayInputStream(TEXT_XML.getBytes()), filter); + assertTrue(filter.wasTested); } - class TestFilter extends DefaultHandler { + static class TestFilter extends DefaultHandler { + boolean wasTested = false; + @Override public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException { super.startElement(uri, localName, qName, atts); - String attr_WithNs = atts.getValue("something", "attr"); - String attr_NoNs = atts.getValue("", "attr"); - - System.out.println("withNs: " + attr_WithNs); - System.out.println("NoNs: " + attr_NoNs); - - Assert.assertTrue(attr_NoNs == null, "Should return null when uri is empty."); - + assertEquals("attrValue", atts.getValue("something", "attr")); + assertNull(atts.getValue("", "attr"), "Should return null when uri is empty."); + wasTested = true; } } diff --git a/test/jaxp/javax/xml/jaxp/unittest/sax/Bug6992561Test.java b/test/jaxp/javax/xml/jaxp/unittest/sax/Bug6992561Test.java index 58bdee54aca..37fe7f9976a 100644 --- a/test/jaxp/javax/xml/jaxp/unittest/sax/Bug6992561Test.java +++ b/test/jaxp/javax/xml/jaxp/unittest/sax/Bug6992561Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,63 +23,49 @@ package sax; -import java.io.ByteArrayInputStream; -import java.io.IOException; - -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; - -import org.testng.Assert; -import org.testng.annotations.Test; +import org.junit.jupiter.api.Test; import org.xml.sax.ContentHandler; import org.xml.sax.InputSource; import org.xml.sax.Locator; -import org.xml.sax.SAXException; import org.xml.sax.XMLReader; import org.xml.sax.helpers.DefaultHandler; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; +import java.io.ByteArrayInputStream; + +import static org.junit.jupiter.api.Assertions.assertFalse; + /* * @test * @bug 6992561 * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest - * @run testng/othervm sax.Bug6992561Test + * @run junit/othervm sax.Bug6992561Test * @summary Test encoding of SystemId in Locator. */ public class Bug6992561Test { @Test - public void test() { + public void test() throws Exception { ContentHandler handler = new DefaultHandler() { public void setDocumentLocator(Locator locator) { String sysId = locator.getSystemId(); System.out.println(locator.getSystemId()); - if (sysId.indexOf("%7") > 0) { - Assert.fail("the original system id should be left as is and not encoded."); - } + assertFalse(sysId.contains("%7"), "the original system id should be left as is and not encoded."); } }; SAXParserFactory spf = SAXParserFactory.newInstance(); SAXParser parser; - try { - parser = spf.newSAXParser(); - - XMLReader reader = parser.getXMLReader(); - reader.setContentHandler(handler); - String xml = "abc"; - ByteArrayInputStream bis = new ByteArrayInputStream(xml.getBytes()); - InputSource is = new InputSource("file:/home2/ramapulavarthi/w/bugs/jaxws861/foo~bla/test/src/wsdl/HelloTypes.xsd"); - is.setByteStream(bis); - reader.parse(is); + parser = spf.newSAXParser(); - } catch (ParserConfigurationException ex) { - Assert.fail(ex.toString()); - } catch (SAXException ex) { - Assert.fail(ex.toString()); - } catch (IOException ex) { - Assert.fail(ex.toString()); - } + XMLReader reader = parser.getXMLReader(); + reader.setContentHandler(handler); + String xml = "abc"; + ByteArrayInputStream bis = new ByteArrayInputStream(xml.getBytes()); + InputSource is = new InputSource("file:/home2/ramapulavarthi/w/bugs/jaxws861/foo~bla/test/src/wsdl/HelloTypes.xsd"); + is.setByteStream(bis); + reader.parse(is); } } diff --git a/test/jaxp/javax/xml/jaxp/unittest/sax/Bug7057778.xml b/test/jaxp/javax/xml/jaxp/unittest/sax/Bug7057778.xml deleted file mode 100644 index b28b04f6431..00000000000 --- a/test/jaxp/javax/xml/jaxp/unittest/sax/Bug7057778.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/test/jaxp/javax/xml/jaxp/unittest/sax/Bug7057778Test.java b/test/jaxp/javax/xml/jaxp/unittest/sax/Bug7057778Test.java index c2d377f7d7b..9c2e772c83f 100644 --- a/test/jaxp/javax/xml/jaxp/unittest/sax/Bug7057778Test.java +++ b/test/jaxp/javax/xml/jaxp/unittest/sax/Bug7057778Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,171 +23,43 @@ package sax; -import static jaxp.library.JAXPTestUtilities.USER_DIR; -import static jaxp.library.JAXPTestUtilities.getSystemProperty; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.UnsupportedEncodingException; -import java.io.Writer; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; -import org.testng.Assert; -import org.testng.annotations.Test; -import org.xml.sax.Attributes; -import org.xml.sax.ErrorHandler; -import org.xml.sax.SAXException; +import org.junit.jupiter.api.Test; import org.xml.sax.SAXParseException; import org.xml.sax.XMLReader; import org.xml.sax.ext.DefaultHandler2; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; + +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + /* * @test * @bug 7057778 * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest - * @run testng/othervm sax.Bug7057778Test + * @run junit/othervm sax.Bug7057778Test * @summary Test the file can be deleted after SAXParser.parse(File, DefaultHandler). */ public class Bug7057778Test { - - static final String xml = "Bug7057778.xml"; - static final String xml1 = "Bug7057778_1.xml"; - @Test - public void testParse() { - File src = new File(getClass().getResource(xml).getFile()); - File dst = new File(USER_DIR + xml1); - try { - copyFile(src, dst); - SAXParserFactory spf = SAXParserFactory.newInstance(); - SAXParser parser = spf.newSAXParser(); - XMLReader xmlReader = parser.getXMLReader(); - xmlReader.setProperty("http://xml.org/sax/properties/lexical-handler", new MyHandler1()); - parser.parse(dst, new MyHandler1()); - } catch (SAXException ex) { - ex.printStackTrace(); - } catch (IOException ex) { - // shouldn't happen - } catch (ParserConfigurationException ex) { - // shouldn't happen - } catch (Exception ex) { - } - if (dst != null) { - if (dst.delete()) { - System.out.println("Delete: OK"); - } else { - System.out.println("Delete: NG"); - Assert.fail("Error: denied to delete the file"); - } - } - - } - - private void copyFile(File src, File dst) throws FileNotFoundException, IOException { - InputStream in = new FileInputStream(src); - OutputStream out = new FileOutputStream(dst); - // Transfer bytes - byte[] buf = new byte[1024]; - int len; - while ((len = in.read(buf)) > 0) { - out.write(buf, 0, len); - } - in.close(); - out.close(); - } - - public class MyHandler1 extends DefaultHandler2 implements ErrorHandler { - private Writer out; - - StringBuffer textBuffer; - private String indentString = " "; // Amount to indent - private int indentLevel = 0; - - public MyHandler1() { - try { - out = new OutputStreamWriter(System.out, "UTF8"); - } catch (UnsupportedEncodingException ex) { - ex.printStackTrace(); - } - } - - public void startDocument() throws SAXException { - } - - public void endDocument() throws SAXException { - } - - public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { - try { - System.out.println("uri: " + uri); - System.out.println("localName: " + localName); - System.out.println("qName: " + qName); - } catch (Exception e) { - throw new SAXException(e); - } - - } - - public void endElement(String uri, String localName, String qName) throws SAXException { - } - - public void characters(char ch[], int start, int length) throws SAXException { - } - - public void comment(char[] ch, int start, int length) { - String text = new String(ch, start, length); - // System.out.println(text); - try { - nl(); - emit("COMMENT: " + text); - } catch (Exception e) { - e.printStackTrace(); - } - } - - public void error(SAXParseException exception) { - exception.printStackTrace(); - } - - public void fatalError(SAXParseException exception) { - exception.printStackTrace(); - } - - public void warning(SAXParseException exception) { - exception.printStackTrace(); - } - - // Wrap I/O exceptions in SAX exceptions, to - // suit handler signature requirements - private void emit(String s) throws SAXException { - try { - out.write(s); - out.flush(); - } catch (IOException e) { - throw new SAXException("I/O error", e); - } - } - - // Start a new line - // and indent the next line appropriately - private void nl() throws SAXException { - String lineEnd = getSystemProperty("line.separator"); - - try { - out.write(lineEnd); - - for (int i = 0; i < indentLevel; i++) - out.write(indentString); - } catch (IOException e) { - throw new SAXException("I/O error", e); - } - } - + public void testParse() throws Exception { + Path badXml = Path.of("bad.xml"); + Files.writeString(badXml, "\n\n\n\n"); + + SAXParserFactory spf = SAXParserFactory.newInstance(); + SAXParser parser = spf.newSAXParser(); + XMLReader xmlReader = parser.getXMLReader(); + DefaultHandler2 noopHandler = new DefaultHandler2(); + xmlReader.setProperty("http://xml.org/sax/properties/lexical-handler", noopHandler); + + // Test file is empty and fails parsing. + File dst = badXml.toFile(); + assertThrows(SAXParseException.class, () -> parser.parse(dst, noopHandler)); + // But parse failure should not keep the destination file open. + assertTrue(dst.delete(), "could not delete the file"); } } diff --git a/test/jaxp/javax/xml/jaxp/unittest/sax/DeclarationTest.java b/test/jaxp/javax/xml/jaxp/unittest/sax/DeclarationTest.java index f9d9b2a117e..19871b5ddf8 100644 --- a/test/jaxp/javax/xml/jaxp/unittest/sax/DeclarationTest.java +++ b/test/jaxp/javax/xml/jaxp/unittest/sax/DeclarationTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,25 +23,25 @@ package sax; -import java.io.File; -import java.io.StringReader; -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; -import org.testng.Assert; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Listeners; -import org.testng.annotations.Test; -import org.xml.sax.ContentHandler; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.XMLReader; import org.xml.sax.helpers.DefaultHandler; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; +import java.io.File; +import java.io.StringReader; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; /* * @test * @bug 8230814 - * @run testng sax.DeclarationTest + * @run junit sax.DeclarationTest * @summary Test SAX Parser's handling of XML Declarations. */ public class DeclarationTest { @@ -56,12 +56,8 @@ public class DeclarationTest { * * Fields: * XML string, expected version, encoding and standalone strings - * - * @return data array for the test - * @throws Exception */ - @DataProvider(name = "default") - public Object[][] forDefaultHandler() throws Exception { + public static Object[][] defaultHandlerData() throws Exception { return new Object[][] { { XML_NO_DECLARATION, null, null, null}, { XML_NO_STANDALONE, null, null, null}, @@ -75,12 +71,8 @@ public Object[][] forDefaultHandler() throws Exception { * * Fields: * XML string, expected version, encoding and standalone strings - * - * @return data array for the test - * @throws Exception */ - @DataProvider(name = "sax-data") - public Object[][] xmlSAXData() throws Exception { + public static Object[][] xmlSAXData() throws Exception { return new Object[][] { { XML_NO_DECLARATION, null, null, null}, { XML_NO_STANDALONE, "1.0", "ISO-8859-1", null}, @@ -95,12 +87,8 @@ public Object[][] xmlSAXData() throws Exception { * * Fields: * Source files, expected version, encoding and standalone strings - * - * @return data array for the test - * @throws Exception */ - @DataProvider(name = "sax-data-files") - public Object[][] xmlSAXDataFiles() throws Exception { + public static Object[][] xmlSAXDataFiles() throws Exception { return new Object[][] { //the source contains no declaration { new File(SRC_DIR + "/../transform/SourceTest.xml"), null, null, null}, @@ -129,7 +117,8 @@ public Object[][] xmlSAXDataFiles() throws Exception { * @param standalone expected standalone string * @throws Exception if the test fails */ - @Test(dataProvider = "default") + @ParameterizedTest + @MethodSource("defaultHandlerData") public void testDefault(String xml, String version, String encoding, String standalone) throws Exception { DefaultImpl h = new DefaultImpl(); @@ -145,7 +134,8 @@ public void testDefault(String xml, String version, String encoding, String stan * @param standalone expected standalone string * @throws Exception if the test fails */ - @Test(dataProvider = "sax-data") + @ParameterizedTest + @MethodSource("xmlSAXData") public void test(String xml, String version, String encoding, String standalone) throws Exception { NewMethodImpl h = new NewMethodImpl(); @@ -161,15 +151,16 @@ public void test(String xml, String version, String encoding, String standalone) * @param standalone expected standalone string * @throws Exception if the test fails */ - @Test(dataProvider = "sax-data-files") + @ParameterizedTest + @MethodSource("xmlSAXDataFiles") public void testFiles(File xml, String version, String encoding, String standalone) throws Exception { SAXParser parser = SAXParserFactory.newDefaultInstance().newSAXParser(); NewMethodImpl h = new NewMethodImpl(); parser.parse(xml, h); - Assert.assertEquals(h.version, version); - Assert.assertEquals(h.encoding, encoding); - Assert.assertEquals(h.standalone, standalone); + assertEquals(version, h.version); + assertEquals(encoding, h.encoding); + assertEquals(standalone, h.standalone); } /** @@ -187,12 +178,12 @@ private void parseAndVerify(String xml, DefaultImpl h, XMLReader r = SAXParserFactory.newDefaultInstance().newSAXParser().getXMLReader(); r.setContentHandler(h); r.parse(new InputSource(new StringReader(xml))); - Assert.assertEquals(h.version, version); - Assert.assertEquals(h.encoding, encoding); - Assert.assertEquals(h.standalone, standalone); + assertEquals(version, h.version); + assertEquals(encoding, h.encoding); + assertEquals(standalone, h.standalone); } - class DefaultImpl extends DefaultHandler{ + static class DefaultImpl extends DefaultHandler { boolean startDocumentInvoked = false; String version, encoding, standalone; @@ -202,7 +193,7 @@ public void startDocument() throws SAXException { } } - class NewMethodImpl extends DefaultImpl { + static class NewMethodImpl extends DefaultImpl { public void startDocument() throws SAXException { super.startDocument(); @@ -213,7 +204,7 @@ public void declaration(String version, String encoding, String standalone) throws SAXException { super.declaration(version, encoding, standalone); - Assert.assertTrue(startDocumentInvoked, "declaration follows startDocument"); + assertTrue(startDocumentInvoked, "declaration follows startDocument"); this.version = version; this.encoding = encoding; this.standalone = standalone; diff --git a/test/jaxp/javax/xml/jaxp/unittest/sax/DefaultHandler2Test.java b/test/jaxp/javax/xml/jaxp/unittest/sax/DefaultHandler2Test.java index 85e447783ca..4f50b23e8d6 100644 --- a/test/jaxp/javax/xml/jaxp/unittest/sax/DefaultHandler2Test.java +++ b/test/jaxp/javax/xml/jaxp/unittest/sax/DefaultHandler2Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,16 +23,7 @@ package sax; -import java.io.IOException; - -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; - -import org.testng.Assert; -import org.testng.AssertJUnit; -import org.testng.annotations.Test; -import org.xml.sax.SAXException; +import org.junit.jupiter.api.Test; import org.xml.sax.SAXNotRecognizedException; import org.xml.sax.XMLReader; import org.xml.sax.ext.DefaultHandler2; @@ -41,210 +32,135 @@ import org.xml.sax.helpers.XMLFilterImpl; import org.xml.sax.helpers.XMLReaderFactory; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; + +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertThrows; + /* * @test * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest - * @run testng/othervm sax.DefaultHandler2Test + * @run junit/othervm sax.DefaultHandler2Test * @summary Test DefaultHandler2. */ public class DefaultHandler2Test { @Test - public void testParse01() { - System.out.println("===in testParse01==="); - try { - DefaultHandler handler = new MyDefaultHandler2(); - SAXParserFactory saxFac = SAXParserFactory.newInstance(); - System.out.println(saxFac.getFeature("http://xml.org/sax/features/use-locator2")); - - // set use-entity-resolver2 as FALSE to use EntityResolver firstly. - saxFac.setFeature("http://xml.org/sax/features/use-entity-resolver2", false); - saxFac.setValidating(true); - - SAXParser parser = saxFac.newSAXParser(); - parser.setProperty("http://xml.org/sax/properties/lexical-handler", handler); - parser.setProperty("http://xml.org/sax/properties/declaration-handler", handler); - - parser.parse(this.getClass().getResource("toys.xml").getFile(), handler); - } catch (ParserConfigurationException e) { - e.printStackTrace(); - Assert.fail("ParserConfigurationException in testParse01()"); - } catch (SAXException e) { - e.printStackTrace(); - Assert.fail("SAXException in testParse01()"); - } catch (IOException e) { - e.printStackTrace(); - Assert.fail("IOException in testParse01()"); - } + public void testParse01() throws Exception { + DefaultHandler handler = new MyDefaultHandler2(); + SAXParserFactory saxFac = SAXParserFactory.newInstance(); + System.out.println(saxFac.getFeature("http://xml.org/sax/features/use-locator2")); + + // set use-entity-resolver2 as FALSE to use EntityResolver firstly. + saxFac.setFeature("http://xml.org/sax/features/use-entity-resolver2", false); + saxFac.setValidating(true); + + SAXParser parser = saxFac.newSAXParser(); + parser.setProperty("http://xml.org/sax/properties/lexical-handler", handler); + parser.setProperty("http://xml.org/sax/properties/declaration-handler", handler); + + parser.parse(this.getClass().getResource("toys.xml").getFile(), handler); } @Test - public void testParse02() { - System.out.println("===in testParse02==="); - try { - DefaultHandler handler = new MyDefaultHandler2(); - SAXParserFactory saxFac = SAXParserFactory.newInstance(); - System.out.println(saxFac.getFeature("http://xml.org/sax/features/use-locator2")); - - // Enable namespace parsing - System.out.println(saxFac.getFeature("http://xml.org/sax/features/namespaces")); - saxFac.setNamespaceAware(true); - - saxFac.setValidating(true); - SAXParser parser = saxFac.newSAXParser(); - parser.setProperty("http://xml.org/sax/properties/lexical-handler", handler); - parser.setProperty("http://xml.org/sax/properties/declaration-handler", handler); - - parser.parse(this.getClass().getResource("toys.xml").getFile(), handler); - } catch (ParserConfigurationException e) { - e.printStackTrace(); - Assert.fail("ParserConfigurationException in testParse02()"); - } catch (SAXException e) { - e.printStackTrace(); - Assert.fail("SAXException in testParse02()"); - } catch (IOException e) { - e.printStackTrace(); - Assert.fail("IOException in testParse02()"); - } + public void testParse02() throws Exception { + DefaultHandler handler = new MyDefaultHandler2(); + SAXParserFactory saxFac = SAXParserFactory.newInstance(); + System.out.println(saxFac.getFeature("http://xml.org/sax/features/use-locator2")); + + // Enable namespace parsing + System.out.println(saxFac.getFeature("http://xml.org/sax/features/namespaces")); + saxFac.setNamespaceAware(true); + + saxFac.setValidating(true); + SAXParser parser = saxFac.newSAXParser(); + parser.setProperty("http://xml.org/sax/properties/lexical-handler", handler); + parser.setProperty("http://xml.org/sax/properties/declaration-handler", handler); + + parser.parse(this.getClass().getResource("toys.xml").getFile(), handler); } @Test - public void testParse03() { - System.out.println("===in testParse03==="); - try { - DefaultHandler handler = new MyDefaultHandler2(); - - XMLReader xmlReader = XMLReaderFactory.createXMLReader(); - xmlReader.setProperty("http://xml.org/sax/properties/declaration-handler", handler); - System.out.println("XMLReader : " + xmlReader.getProperty("http://xml.org/sax/properties/declaration-handler")); - - SAXParserFactory saxFac = SAXParserFactory.newInstance(); - SAXParser parser = saxFac.newSAXParser(); - parser.setProperty("http://xml.org/sax/properties/declaration-handler", handler); - System.out.println("SAXParser : " + parser.getProperty("http://xml.org/sax/properties/declaration-handler")); - - // From https://docs.oracle.com/javase/7/docs/api, - // ParserAdapter.setProperty() and ParserAdapter.getProperty() does - // not support any property currently. - try { - ParserAdapter adapter = new ParserAdapter(parser.getParser()); - System.out.println("ParserAdapter : " + adapter.getProperty("http://xml.org/sax/properties/declaration-handler")); - } catch (SAXNotRecognizedException e) { - System.out.println("Expected SAXNotRecognizedException since ParserAdapter.getProperty() does not support any property currently"); - } - try { - ParserAdapter adapter = new ParserAdapter(parser.getParser()); - adapter.setProperty("http://xml.org/sax/properties/declaration-handler", handler); - } catch (SAXNotRecognizedException e) { - System.out.println("Expected SAXNotRecognizedException since ParserAdapter.setProperty() does not support any property currently"); - } - } catch (SAXException e) { - e.printStackTrace(); - Assert.fail("SAXException in testParse03()"); - } catch (ParserConfigurationException e) { - e.printStackTrace(); - Assert.fail("ParserConfigurationException in testParse03()"); - } - + public void testParse03() throws Exception { + DefaultHandler handler = new MyDefaultHandler2(); + + XMLReader xmlReader = XMLReaderFactory.createXMLReader(); + xmlReader.setProperty("http://xml.org/sax/properties/declaration-handler", handler); + System.out.println("XMLReader : " + xmlReader.getProperty("http://xml.org/sax/properties/declaration-handler")); + + SAXParserFactory saxFac = SAXParserFactory.newInstance(); + SAXParser parser = saxFac.newSAXParser(); + parser.setProperty("http://xml.org/sax/properties/declaration-handler", handler); + System.out.println("SAXParser : " + parser.getProperty("http://xml.org/sax/properties/declaration-handler")); + + // From https://docs.oracle.com/javase/7/docs/api, + // ParserAdapter.setProperty() and ParserAdapter.getProperty() does + // not support any property currently. + ParserAdapter adapter = new ParserAdapter(parser.getParser()); + assertThrows(SAXNotRecognizedException.class, () -> adapter.getProperty("http://xml.org/sax/properties/declaration-handler")); + assertThrows(SAXNotRecognizedException.class, () -> adapter.setProperty("http://xml.org/sax/properties/declaration-handler", handler)); } @Test - public void testParse04() { - System.out.println("===in testParse04==="); - try { - DefaultHandler handler = new MyDefaultHandler2(); - XMLReader xmlReader = XMLReaderFactory.createXMLReader(); - System.out.println(xmlReader.getFeature("http://xml.org/sax/features/namespaces")); - xmlReader.setProperty("http://xml.org/sax/properties/declaration-handler", handler); - xmlReader.setProperty("http://xml.org/sax/properties/lexical-handler", handler); - xmlReader.setContentHandler(handler); - - xmlReader.parse(this.getClass().getResource("toys.xml").getFile()); - - } catch (SAXException e) { - e.printStackTrace(); - Assert.fail("SAXException in testParse04()"); - } catch (IOException e) { - e.printStackTrace(); - Assert.fail("IOException in testParse04()"); - } + public void testParse04() throws Exception { + DefaultHandler handler = new MyDefaultHandler2(); + XMLReader xmlReader = XMLReaderFactory.createXMLReader(); + System.out.println(xmlReader.getFeature("http://xml.org/sax/features/namespaces")); + xmlReader.setProperty("http://xml.org/sax/properties/declaration-handler", handler); + xmlReader.setProperty("http://xml.org/sax/properties/lexical-handler", handler); + xmlReader.setContentHandler(handler); + + xmlReader.parse(this.getClass().getResource("toys.xml").getFile()); } @Test - public void testParse05() { - System.out.println("===in testParse05==="); - try { - DefaultHandler handler = new MyDefaultHandler2(); - XMLReader xmlReader = XMLReaderFactory.createXMLReader(); - XMLFilterImpl filterImpl = new XMLFilterImpl(xmlReader); - System.out.println(xmlReader.getFeature("http://xml.org/sax/features/namespaces")); - filterImpl.setProperty("http://xml.org/sax/properties/declaration-handler", handler); - filterImpl.setProperty("http://xml.org/sax/properties/lexical-handler", handler); - filterImpl.setContentHandler(handler); - - filterImpl.parse(this.getClass().getResource("toys.xml").getFile()); - - } catch (SAXException e) { - e.printStackTrace(); - Assert.fail("SAXException in testParse05()"); - } catch (IOException e) { - e.printStackTrace(); - Assert.fail("IOException in testParse05()"); - } + public void testParse05() throws Exception { + DefaultHandler handler = new MyDefaultHandler2(); + XMLReader xmlReader = XMLReaderFactory.createXMLReader(); + XMLFilterImpl filterImpl = new XMLFilterImpl(xmlReader); + System.out.println(xmlReader.getFeature("http://xml.org/sax/features/namespaces")); + filterImpl.setProperty("http://xml.org/sax/properties/declaration-handler", handler); + filterImpl.setProperty("http://xml.org/sax/properties/lexical-handler", handler); + filterImpl.setContentHandler(handler); + + filterImpl.parse(this.getClass().getResource("toys.xml").getFile()); } @Test - public void testParse06() { - System.out.println("===in testParse06==="); - try { - DefaultHandler handler = new MyDefaultHandler2(); - XMLReader xmlReader = XMLReaderFactory.createXMLReader(); - XMLFilterImpl filterImpl = new XMLFilterImpl(xmlReader); - System.out.println(xmlReader.getFeature("http://xml.org/sax/features/namespaces")); - filterImpl.setProperty("http://xml.org/sax/properties/declaration-handler", handler); - filterImpl.setProperty("http://xml.org/sax/properties/lexical-handler", handler); - filterImpl.setContentHandler(handler); - - AssertJUnit.assertTrue(filterImpl.getProperty("http://xml.org/sax/properties/declaration-handler") instanceof DefaultHandler2); - - // filterImpl.setFeature("http://xml.org/sax/features/external-general-entities", - // false) ; - // filterImpl.setFeature("http://xml.org/sax/features/external-parameter-entities", - // false) ; - filterImpl.skippedEntity("name2"); - - filterImpl.parse(this.getClass().getResource("toys.xml").getFile()); - } catch (SAXException e) { - e.printStackTrace(); - Assert.fail("SAXException in testParse06()"); - } catch (IOException e) { - e.printStackTrace(); - Assert.fail("IOException in testParse06()"); - } + public void testParse06() throws Exception { + DefaultHandler handler = new MyDefaultHandler2(); + XMLReader xmlReader = XMLReaderFactory.createXMLReader(); + XMLFilterImpl filterImpl = new XMLFilterImpl(xmlReader); + System.out.println(xmlReader.getFeature("http://xml.org/sax/features/namespaces")); + filterImpl.setProperty("http://xml.org/sax/properties/declaration-handler", handler); + filterImpl.setProperty("http://xml.org/sax/properties/lexical-handler", handler); + filterImpl.setContentHandler(handler); + + assertInstanceOf(DefaultHandler2.class, filterImpl.getProperty("http://xml.org/sax/properties/declaration-handler")); + + // filterImpl.setFeature("http://xml.org/sax/features/external-general-entities", + // false) ; + // filterImpl.setFeature("http://xml.org/sax/features/external-parameter-entities", + // false) ; + filterImpl.skippedEntity("name2"); + + filterImpl.parse(this.getClass().getResource("toys.xml").getFile()); } @Test - public void testParse07() { - System.out.println("===in testParse07==="); - try { - DefaultHandler handler = new MyDefaultHandler2(); - XMLReader xmlReader = XMLReaderFactory.createXMLReader(); - XMLFilterImpl filterImpl = new XMLFilterImpl(xmlReader); - System.out.println(xmlReader.getFeature("http://xml.org/sax/features/namespaces")); - filterImpl.setProperty("http://xml.org/sax/properties/declaration-handler", handler); - filterImpl.setProperty("http://xml.org/sax/properties/lexical-handler", handler); - filterImpl.setContentHandler(handler); - filterImpl.setErrorHandler(handler); - AssertJUnit.assertTrue(filterImpl.getProperty("http://xml.org/sax/properties/declaration-handler") instanceof DefaultHandler2); - - filterImpl.setFeature("http://apache.org/xml/features/continue-after-fatal-error", true); - filterImpl.parse(this.getClass().getResource("toys_error.xml").getFile()); - } catch (SAXException e) { - e.printStackTrace(); - Assert.fail("SAXException in testParse07()"); - } catch (IOException e) { - e.printStackTrace(); - Assert.fail("IOException in testParse07()"); - } + public void testParse07() throws Exception { + DefaultHandler handler = new MyDefaultHandler2(); + XMLReader xmlReader = XMLReaderFactory.createXMLReader(); + XMLFilterImpl filterImpl = new XMLFilterImpl(xmlReader); + System.out.println(xmlReader.getFeature("http://xml.org/sax/features/namespaces")); + filterImpl.setProperty("http://xml.org/sax/properties/declaration-handler", handler); + filterImpl.setProperty("http://xml.org/sax/properties/lexical-handler", handler); + filterImpl.setContentHandler(handler); + filterImpl.setErrorHandler(handler); + assertInstanceOf(DefaultHandler2.class, filterImpl.getProperty("http://xml.org/sax/properties/declaration-handler")); + + filterImpl.setFeature("http://apache.org/xml/features/continue-after-fatal-error", true); + filterImpl.parse(this.getClass().getResource("toys_error.xml").getFile()); } } diff --git a/test/jaxp/javax/xml/jaxp/unittest/sax/IssueTracker56Test.java b/test/jaxp/javax/xml/jaxp/unittest/sax/IssueTracker56Test.java index bbec3104208..6588d787bfe 100644 --- a/test/jaxp/javax/xml/jaxp/unittest/sax/IssueTracker56Test.java +++ b/test/jaxp/javax/xml/jaxp/unittest/sax/IssueTracker56Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,78 +23,50 @@ package sax; -import java.io.IOException; -import java.io.StringReader; - -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; - -import org.testng.Assert; -import org.testng.annotations.Test; +import org.junit.jupiter.api.Test; import org.xml.sax.Attributes; import org.xml.sax.ErrorHandler; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; +import java.io.StringReader; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; + /* * @test * @bug 6809409 * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest - * @run testng/othervm sax.IssueTracker56Test + * @run junit/othervm sax.IssueTracker56Test * @summary Test SAXException has Cause. */ public class IssueTracker56Test { @Test - public void testException() { - try { - SAXParserFactory spf = SAXParserFactory.newInstance(); - SAXParser parser = spf.newSAXParser(); - String xmlToParse = "Issue 56: SAXException does not do the exception chaining properly"; - InputSource source = new InputSource(new StringReader(xmlToParse)); - parser.parse(source, new MyHandler()); - } catch (SAXException ex) { - System.out.println(ex.getCause()); - if (ex.getCause() == null) - Assert.fail("failed chaining exception properly."); - // ex.printStackTrace(); //will not print out root cause without the - // fix - } catch (IOException ex) { - // shouldn't happen - } catch (ParserConfigurationException ex) { - // shouldn't happen - } + public void testException() throws Exception { + SAXParserFactory spf = SAXParserFactory.newInstance(); + SAXParser parser = spf.newSAXParser(); + String xmlToParse = "Issue 56: SAXException does not do the exception chaining properly"; + InputSource source = new InputSource(new StringReader(xmlToParse)); + + SAXException ex = assertThrows(SAXException.class, () -> parser.parse(source, new MyHandler())); + assertNotNull(ex.getCause(), "failed chaining exception properly."); } @Test public void testWorkAround() throws Exception { - try { - SAXParserFactory spf = SAXParserFactory.newInstance(); - SAXParser parser = spf.newSAXParser(); - String xmlToParse = "Issue 56: SAXException does not do the exception chaining properly"; - InputSource source = new InputSource(new StringReader(xmlToParse)); - parser.parse(source, new MyHandler1()); - } catch (SAXException ex) { - System.out.println(ex.getCause()); - // ex.printStackTrace(); //will print out root cause - } catch (IOException ex) { - // shouldn't happen - } catch (ParserConfigurationException ex) { - // shouldn't happen - } - + SAXParserFactory spf = SAXParserFactory.newInstance(); + SAXParser parser = spf.newSAXParser(); + String xmlToParse = "Issue 56: SAXException does not do the exception chaining properly"; + InputSource source = new InputSource(new StringReader(xmlToParse)); + assertThrows(SAXException.class, () -> parser.parse(source, new MyHandler1())); } - public class MyHandler extends DefaultHandler implements ErrorHandler { - - public void startDocument() throws SAXException { - } - - public void endDocument() throws SAXException { - } - + public static class MyHandler extends DefaultHandler implements ErrorHandler { public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { try { System.out.println(uri); @@ -104,23 +76,9 @@ public void startElement(String uri, String localName, String qName, Attributes } } - - public void endElement(String uri, String localName, String qName) throws SAXException { - } - - public void characters(char ch[], int start, int length) throws SAXException { - } - } - public class MyHandler1 extends DefaultHandler implements ErrorHandler { - - public void startDocument() throws SAXException { - } - - public void endDocument() throws SAXException { - } - + public static class MyHandler1 extends DefaultHandler implements ErrorHandler { public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXExceptionExt { try { System.out.println(uri); @@ -130,12 +88,5 @@ public void startElement(String uri, String localName, String qName, Attributes } } - - public void endElement(String uri, String localName, String qName) throws SAXException { - } - - public void characters(char ch[], int start, int length) throws SAXException { - } - } } diff --git a/test/jaxp/javax/xml/jaxp/unittest/sax/NSSupportTest.java b/test/jaxp/javax/xml/jaxp/unittest/sax/NSSupportTest.java index 7630d96a023..d4b05a0c366 100644 --- a/test/jaxp/javax/xml/jaxp/unittest/sax/NSSupportTest.java +++ b/test/jaxp/javax/xml/jaxp/unittest/sax/NSSupportTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,17 +23,20 @@ package sax; +import org.junit.jupiter.api.Test; +import org.xml.sax.helpers.NamespaceSupport; + import java.util.Enumeration; -import org.testng.Assert; -import org.testng.AssertJUnit; -import org.testng.annotations.Test; -import org.xml.sax.helpers.NamespaceSupport; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; /* * @test * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest - * @run testng/othervm sax.NSSupportTest + * @run junit/othervm sax.NSSupportTest * @summary Test NamespaceSupport. */ public class NSSupportTest { @@ -48,14 +51,14 @@ public void testProcessName() { String[] parts = new String[3]; nssupport.processName("dc:name1", parts, false); - Assert.assertTrue(parts[0].equals("http://www.purl.org/dc")); - Assert.assertTrue(parts[1].equals("name1")); - Assert.assertTrue(parts[2].equals("dc:name1")); + assertEquals("http://www.purl.org/dc", parts[0]); + assertEquals("name1", parts[1]); + assertEquals("dc:name1", parts[2]); nssupport.processName("name2", parts, false); - Assert.assertTrue(parts[0].equals("http://www.java.com")); - Assert.assertTrue(parts[1].equals("name2")); - Assert.assertTrue(parts[2].equals("name2")); + assertEquals("http://www.java.com", parts[0]); + assertEquals("name2", parts[1]); + assertEquals("name2", parts[2]); } @Test @@ -64,30 +67,30 @@ public void testNamespaceDeclUris() { NamespaceSupport nssupport = new NamespaceSupport(); nssupport.pushContext(); - Assert.assertFalse(nssupport.isNamespaceDeclUris()); + assertFalse(nssupport.isNamespaceDeclUris()); nssupport.declarePrefix("xmlns", ""); nssupport.processName("xmlns:name", parts, true); - Assert.assertNull(parts[0]); - Assert.assertNull(parts[1]); - Assert.assertNull(parts[2]); + assertNull(parts[0]); + assertNull(parts[1]); + assertNull(parts[2]); nssupport.reset(); nssupport.setNamespaceDeclUris(true); nssupport.declarePrefix("xmlns", ""); nssupport.processName("xmlns:name", parts, true); - Assert.assertTrue(parts[0].equals(NamespaceSupport.NSDECL)); - Assert.assertTrue(parts[1].equals("name")); - Assert.assertTrue(parts[2].equals("xmlns:name")); + assertEquals(NamespaceSupport.NSDECL, parts[0]); + assertEquals("name", parts[1]); + assertEquals("xmlns:name", parts[2]); nssupport.reset(); nssupport.setNamespaceDeclUris(true); nssupport.declarePrefix("xml", ""); nssupport.processName("xml:name", parts, true); - Assert.assertTrue(parts[0].equals(NamespaceSupport.XMLNS)); - Assert.assertTrue(parts[1].equals("name")); - Assert.assertTrue(parts[2].equals("xml:name")); + assertEquals(NamespaceSupport.XMLNS, parts[0]); + assertEquals("name", parts[1]); + assertEquals("xml:name", parts[2]); } @@ -98,14 +101,14 @@ public void testPopContext() { nssupport.pushContext(); nssupport.declarePrefix("dc", "http://www.purl.org/dc"); - Assert.assertEquals(nssupport.getPrefix("http://www.purl.org/dc"), "dc"); + assertEquals("dc", nssupport.getPrefix("http://www.purl.org/dc")); nssupport.popContext(); - Assert.assertNull(nssupport.getPrefix("http://www.purl.org/dc")); + assertNull(nssupport.getPrefix("http://www.purl.org/dc")); nssupport.processName("dc:name1", parts, false); - Assert.assertNull(parts[0]); - Assert.assertNull(parts[1]); - Assert.assertNull(parts[2]); + assertNull(parts[0]); + assertNull(parts[1]); + assertNull(parts[2]); } @Test @@ -124,9 +127,9 @@ public void testPrefixAndUri1() { nssupport.declarePrefix("dc2", "http://www.purl.org/dc2"); nssupport.declarePrefix("dcnew", "http://www.purl.org/dcnew"); - Enumeration enu1 = nssupport.getDeclaredPrefixes(); + Enumeration enu1 = nssupport.getDeclaredPrefixes(); while (enu1.hasMoreElements()) { - String str = (String) enu1.nextElement(); + String str = enu1.nextElement(); if (str.equals("dc")) { hasdc = true; } else if (str.equals("dc1")) { @@ -137,8 +140,8 @@ public void testPrefixAndUri1() { hasdcnew = true; } } - AssertJUnit.assertTrue(hasdcnew && hasdc1 && hasdc2); - AssertJUnit.assertFalse(hasdc); + assertTrue(hasdcnew && hasdc1 && hasdc2); + assertFalse(hasdc); } @Test @@ -157,9 +160,9 @@ public void testPrefixAndUri2() { nssupport.declarePrefix("dc2", "http://www.purl.org/dc2"); nssupport.declarePrefix("dcnew", "http://www.purl.org/dcnew"); - Enumeration enu1 = nssupport.getPrefixes(); + Enumeration enu1 = nssupport.getPrefixes(); while (enu1.hasMoreElements()) { - String str = (String) enu1.nextElement(); + String str = enu1.nextElement(); if (str.equals("dc")) { hasdc = true; } else if (str.equals("dc1")) { @@ -170,7 +173,7 @@ public void testPrefixAndUri2() { hasdcnew = true; } } - AssertJUnit.assertTrue(hasdcnew && hasdc1 && hasdc2 && hasdc); + assertTrue(hasdcnew && hasdc1 && hasdc2 && hasdc); } @Test @@ -189,9 +192,9 @@ public void testPrefixAndUri3() { nssupport.declarePrefix("dc2", "http://www.purl.org/dc2"); nssupport.declarePrefix("dcnew", "http://www.purl.org/dcnew"); - Enumeration enu1 = nssupport.getPrefixes("http://www.purl.org/dc"); + Enumeration enu1 = nssupport.getPrefixes("http://www.purl.org/dc"); while (enu1.hasMoreElements()) { - String str = (String) enu1.nextElement(); + String str = enu1.nextElement(); if (str.equals("dc")) { hasdc = true; } else if (str.equals("dc1")) { @@ -202,9 +205,9 @@ public void testPrefixAndUri3() { hasdcnew = true; } } - AssertJUnit.assertTrue(hasdc1 && hasdc); - AssertJUnit.assertFalse(hasdc2); - AssertJUnit.assertFalse(hasdcnew); + assertTrue(hasdc1 && hasdc); + assertFalse(hasdc2); + assertFalse(hasdcnew); } @Test @@ -219,13 +222,13 @@ public void testPrefixAndUri4() { nssupport.declarePrefix("dc2", "http://www.purl.org/dc2"); nssupport.declarePrefix("dcnew", "http://www.purl.org/dcnew"); - AssertJUnit.assertTrue(nssupport.getURI("dc").equals("http://www.purl.org/dc")); - AssertJUnit.assertTrue(nssupport.getURI("dc1").equals("http://www.purl.org/dc")); - AssertJUnit.assertTrue(nssupport.getURI("dc2").equals("http://www.purl.org/dc2")); - AssertJUnit.assertTrue(nssupport.getURI("dcnew").equals("http://www.purl.org/dcnew")); + assertEquals("http://www.purl.org/dc", nssupport.getURI("dc")); + assertEquals("http://www.purl.org/dc", nssupport.getURI("dc1")); + assertEquals("http://www.purl.org/dc2", nssupport.getURI("dc2")); + assertEquals("http://www.purl.org/dcnew", nssupport.getURI("dcnew")); // Negative test - Assert.assertNull(nssupport.getURI("wrong_prefix")); - Assert.assertNull(nssupport.getURI("")); + assertNull(nssupport.getURI("wrong_prefix")); + assertNull(nssupport.getURI("")); } } diff --git a/test/jaxp/javax/xml/jaxp/unittest/sax/SAXExceptionInitCause.java b/test/jaxp/javax/xml/jaxp/unittest/sax/SAXExceptionInitCause.java index 4e5307b42ec..ee028d74611 100644 --- a/test/jaxp/javax/xml/jaxp/unittest/sax/SAXExceptionInitCause.java +++ b/test/jaxp/javax/xml/jaxp/unittest/sax/SAXExceptionInitCause.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,12 +27,15 @@ * @summary The initCause() incorrectly initialize the cause in * SAXException class when used with SAXException(String) * constructor. - * @run testng/othervm sax.SAXExceptionInitCause + * @run junit/othervm sax.SAXExceptionInitCause * @author aleksej.efimov@oracle.com */ package sax; +import org.junit.jupiter.api.Test; +import org.xml.sax.SAXException; + import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -40,9 +43,11 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; -import org.testng.Assert; -import org.testng.annotations.Test; -import org.xml.sax.SAXException; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertThrows; public class SAXExceptionInitCause { @@ -55,8 +60,8 @@ public void testOwnSerializationNoCause() throws Exception { serialSAX = pickleException(noCauseException); deserializedException = unpickleException(serialSAX); - Assert.assertNull(deserializedException.getCause()); - Assert.assertEquals(deserializedException.getMessage(), SAX_MESSAGE); + assertNull(deserializedException.getCause()); + assertEquals(SAX_MESSAGE, deserializedException.getMessage()); } @Test @@ -69,18 +74,18 @@ public void testSerializationWithCause() throws Exception { serialSAX = pickleException(withCauseException); deserializedException = unpickleException(serialSAX); - Assert.assertNotNull(deserializedException.getCause()); - Assert.assertEquals(deserializedException.getMessage(), SAX_MESSAGE); - Assert.assertEquals(deserializedException.getCause().getMessage(), SAX_CAUSE_MESSAGE); + assertNotNull(deserializedException.getCause()); + assertEquals(SAX_MESSAGE, deserializedException.getMessage()); + assertEquals(SAX_CAUSE_MESSAGE, deserializedException.getCause().getMessage()); } @Test - public void testCauseInitByCtor() throws Exception { + public void testCauseInitByCtor() { // Check that constructor properly initializes cause Exception cause = new Exception(SAX_CAUSE_MESSAGE); SAXException exception = new SAXException(cause); - Assert.assertSame(exception.getCause(), cause); - Assert.assertSame(exception.getException(), cause); + assertSame(cause, exception.getCause()); + assertSame(cause, exception.getException()); } @Test @@ -89,8 +94,8 @@ public void testCauseInitWithException() { SAXException exception = new SAXException(); Exception cause = new Exception(SAX_CAUSE_MESSAGE); exception.initCause(cause); - Assert.assertSame(exception.getCause(), cause); - Assert.assertSame(exception.getException(), cause); + assertSame(cause, exception.getCause()); + assertSame(cause, exception.getException()); } @Test @@ -100,48 +105,51 @@ public void testCauseInitWithThrowable() { SAXException exception = new SAXException(); Throwable cause = new Throwable(SAX_CAUSE_MESSAGE); exception.initCause(cause); - Assert.assertSame(exception.getCause(),cause); - Assert.assertNull(exception.getException()); + assertSame(cause, exception.getCause()); + assertNull(exception.getException()); } - @Test(expectedExceptions = IllegalStateException.class) + @Test public void testInitCauseTwice() { SAXException exception = new SAXException(new Exception(SAX_CAUSE_MESSAGE)); - // Expecting IllegalStateException at this point - exception.initCause(new Exception(SAX_CAUSE_MESSAGE)); + assertThrows( + IllegalStateException.class, + () -> exception.initCause(new Exception(SAX_CAUSE_MESSAGE))); } @Test public void testLegacySerialCtor() throws Exception { SAXException saxException8 = unpickleException(JDK8_SET_WITH_CTOR_ONLY); - Assert.assertNotNull(saxException8.getCause()); - Assert.assertNotNull(saxException8.getException()); + assertNotNull(saxException8.getCause()); + assertNotNull(saxException8.getException()); } @Test public void testLegacySerialCtorAndInit() throws Exception { SAXException saxException8 = unpickleException(JDK8_SET_WITH_CTOR_AND_INIT); - Assert.assertNotNull(saxException8.getCause()); - Assert.assertNotNull(saxException8.getException()); + assertNotNull(saxException8.getCause()); + assertNotNull(saxException8.getException()); } @Test public void testLegacySerialInitCause() throws Exception { SAXException saxException8 = unpickleException(JDK8_WITH_INIT_ONLY); - Assert.assertNotNull(saxException8.getCause()); - Assert.assertNotNull(saxException8.getException()); + assertNotNull(saxException8.getCause()); + assertNotNull(saxException8.getException()); } @Test public void testLegacySerialNothingSet() throws Exception { SAXException saxException8 = unpickleException(JDK8_NOTHING_SET); - Assert.assertNull(saxException8.getCause()); - Assert.assertNull(saxException8.getException()); + assertNull(saxException8.getCause()); + assertNull(saxException8.getException()); } - @Test(expectedExceptions = InvalidClassException.class) - public void testReadObjectIllegalStateException() throws Exception { - SAXException saxException8 = unpickleException(JDK8_CHECK_ILLEGAL_STATE_EXCEPTION); + @Test + public void testReadObjectIllegalStateException() { + assertThrows( + InvalidClassException.class, + () -> unpickleException(JDK8_CHECK_ILLEGAL_STATE_EXCEPTION)); } // Serialize SAXException to byte array @@ -164,8 +172,8 @@ private static SAXException unpickleException(byte[] ser) return saxException; } - private static String SAX_MESSAGE = "SAXException message"; - private static String SAX_CAUSE_MESSAGE = "SAXException cause message"; + private static final String SAX_MESSAGE = "SAXException message"; + private static final String SAX_CAUSE_MESSAGE = "SAXException cause message"; /* This is a serial form of ordinary SAXException serialized * by the following JDK8 code: diff --git a/test/jaxp/javax/xml/jaxp/unittest/sax/SAXParserTest.java b/test/jaxp/javax/xml/jaxp/unittest/sax/SAXParserTest.java index 708ae2178b0..ee7e81df5fb 100644 --- a/test/jaxp/javax/xml/jaxp/unittest/sax/SAXParserTest.java +++ b/test/jaxp/javax/xml/jaxp/unittest/sax/SAXParserTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,24 +23,25 @@ package sax; -import static jaxp.library.JAXPTestUtilities.getSystemProperty; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; -import org.testng.annotations.Test; +import org.junit.jupiter.api.Test; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +import static org.junit.jupiter.api.Assertions.assertThrows; + /* * @test * @bug 8213734 * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest - * @run testng sax.SAXParserTest - * @summary Tests functionalities for SAXParser. + * @run junit sax.SAXParserTest + * @summary Tests that failed parsing closes the file correctly. */ public class SAXParserTest { @@ -51,35 +52,24 @@ public class SAXParserTest { */ @Test public void testCloseReaders() throws Exception { - if (!getSystemProperty("os.name").contains("Windows")) { - System.out.println("This test only needs to be run on Windows."); - return; - } - Path testFile = createTestFile(null, "Test"); + Path testFile = createTestFile("Test"); System.out.println("Test file: " + testFile.toString()); SAXParserFactory factory = SAXParserFactory.newDefaultInstance(); SAXParser parser = factory.newSAXParser(); - try { - parser.parse(testFile.toFile(), new DefaultHandler() { - @Override - public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { - throw new SAXException("Stop the parser."); - } - }); - } catch (SAXException e) { - // Do nothing - } - - // deletion failes on Windows when the file is not closed - Files.deleteIfExists(testFile); + DefaultHandler explodingHandler = new DefaultHandler() { + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + throw new SAXException("Stop the parser."); + } + }; + assertThrows(SAXException.class, () -> parser.parse(testFile.toFile(), explodingHandler)); + // Deletion would fail on Windows if the file was not closed. + Files.delete(testFile); } - private static Path createTestFile(Path dir, String name) throws IOException { + private static Path createTestFile(String name) throws IOException { Path path = Files.createTempFile(name, ".xml"); - byte[] bytes = "" - .getBytes(StandardCharsets.UTF_8); - - Files.write(path, bytes); + Files.writeString(path, ""); return path; } } diff --git a/test/jaxp/javax/xml/jaxp/unittest/sax/SymbolTableResetTest.java b/test/jaxp/javax/xml/jaxp/unittest/sax/SymbolTableResetTest.java index ff961e8e9e2..6a934aed291 100644 --- a/test/jaxp/javax/xml/jaxp/unittest/sax/SymbolTableResetTest.java +++ b/test/jaxp/javax/xml/jaxp/unittest/sax/SymbolTableResetTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,20 +23,23 @@ package sax; -import java.io.StringReader; -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; -import org.testng.Assert; -import org.testng.annotations.Test; +import org.junit.jupiter.api.Test; import org.xml.sax.InputSource; import org.xml.sax.helpers.DefaultHandler; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; +import java.io.StringReader; + +import static org.junit.jupiter.api.Assertions.assertNotSame; +import static org.junit.jupiter.api.Assertions.assertSame; + /* * @test * @bug 8173390 8176168 * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest - * @run testng/othervm -Djdk.xml.resetSymbolTable=false sax.SymbolTableResetTest - * @run testng/othervm -Djdk.xml.resetSymbolTable=true sax.SymbolTableResetTest + * @run junit/othervm -Djdk.xml.resetSymbolTable=false sax.SymbolTableResetTest + * @run junit/othervm -Djdk.xml.resetSymbolTable=true sax.SymbolTableResetTest * @summary Test that SAXParser reallocates symbol table during * subsequent parse operations */ @@ -115,9 +118,9 @@ private void parseAndCheckReset(boolean setFeature, boolean value) throws Except // Check symbol table references after two subsequent parse operations if (resetExpected) { - Assert.assertNotSame(symTable1, symTable2, "Symbol table references"); + assertNotSame(symTable1, symTable2, "Symbol table references"); } else { - Assert.assertSame(symTable1, symTable2, "Symbol table references"); + assertSame(symTable1, symTable2, "Symbol table references"); } } diff --git a/test/jaxp/javax/xml/jaxp/unittest/sax/XMLReaderTest.java b/test/jaxp/javax/xml/jaxp/unittest/sax/XMLReaderTest.java index ae235f32549..d625f835a52 100644 --- a/test/jaxp/javax/xml/jaxp/unittest/sax/XMLReaderTest.java +++ b/test/jaxp/javax/xml/jaxp/unittest/sax/XMLReaderTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,36 +23,26 @@ package sax; -import static jaxp.library.JAXPTestUtilities.clearSystemProperty; -import static jaxp.library.JAXPTestUtilities.setSystemProperty; - -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.parsers.SAXParserFactory; - -import org.testng.annotations.AfterClass; -import org.testng.annotations.Test; +import org.junit.jupiter.api.Test; import org.xml.sax.SAXException; import org.xml.sax.XMLReader; import org.xml.sax.helpers.XMLReaderAdapter; import org.xml.sax.helpers.XMLReaderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParserFactory; + +import static org.junit.jupiter.api.Assertions.assertThrows; + /* * @test * @bug 8158246 8316383 * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest - * @run testng/othervm sax.XMLReaderTest + * @run junit/othervm sax.XMLReaderTest * @summary This class contains tests that cover the creation of XMLReader. */ public class XMLReaderTest { - private final String SAX_PROPNAME = "org.xml.sax.driver"; - - /* - * Clean up after test - */ - @AfterClass - public void cleanUp() throws Exception { - clearSystemProperty(SAX_PROPNAME); - } + private static final String SAX_PROPNAME = "org.xml.sax.driver"; /* * @bug 8158246 @@ -61,12 +51,16 @@ public void cleanUp() throws Exception { * * Except test format, this test is the same as JCK's test Ctor003. */ - @Test(expectedExceptions = SAXException.class) + @Test public void testcreateXMLReader() throws SAXException, ParserConfigurationException { String className = SAXParserFactory.newInstance().newSAXParser() - .getXMLReader().getClass().getName(); - setSystemProperty(SAX_PROPNAME, className + "nosuch"); - XMLReaderAdapter adapter = new XMLReaderAdapter(); + .getXMLReader().getClass().getName(); + System.setProperty(SAX_PROPNAME, className + "nosuch"); + try { + assertThrows(SAXException.class, XMLReaderAdapter::new); + } finally { + System.clearProperty(SAX_PROPNAME); + } } /* diff --git a/test/jaxp/javax/xml/jaxp/unittest/sbd/test/ExternalRefTest.java b/test/jaxp/javax/xml/jaxp/unittest/sbd/test/ExternalRefTest.java index 0b9daed0d83..273278f23e5 100644 --- a/test/jaxp/javax/xml/jaxp/unittest/sbd/test/ExternalRefTest.java +++ b/test/jaxp/javax/xml/jaxp/unittest/sbd/test/ExternalRefTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,19 +22,21 @@ */ package sbd.test; -import java.io.File; -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; -import org.testng.Assert; -import org.testng.annotations.Test; +import org.junit.jupiter.api.Test; import org.xml.sax.SAXParseException; import org.xml.sax.helpers.DefaultHandler; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; +import java.io.File; + +import static org.junit.jupiter.api.Assertions.assertThrows; + /* * @test * @bug 8326915 * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest - * @run testng/othervm sbd.test.ExternalRefTest + * @run junit/othervm sbd.test.ExternalRefTest * @summary Part of the Secure-By-Default (SBD) project. This test verifies issues * and error message improvements related to external references. */ @@ -43,11 +45,10 @@ public class ExternalRefTest { * @bug 8326915 * Verifies that SAXParseException rather than NPE is thrown when a validating * parser is restricted from processing external references. - * @throws Exception if the test fails */ @Test - public void testValidatingParser() throws Exception { - Assert.assertThrows(SAXParseException.class, () -> validateWithParser()); + public void testValidatingParser() { + assertThrows(SAXParseException.class, this::validateWithParser); } private void validateWithParser() throws Exception { From dfe438d0570ada60de9d8dd7cdf97d229d91fc48 Mon Sep 17 00:00:00 2001 From: Ruben Ayrapetyan Date: Tue, 31 Mar 2026 10:14:26 +0000 Subject: [PATCH 076/116] 8366441: AArch64: Support WFET in OnSpinWait Co-authored-by: Stuart Monteith Co-authored-by: Andrew Haley Reviewed-by: aph, eastigeevich --- src/hotspot/cpu/aarch64/assembler_aarch64.hpp | 4 + src/hotspot/cpu/aarch64/globals_aarch64.hpp | 14 +- .../cpu/aarch64/macroAssembler_aarch64.cpp | 25 + .../cpu/aarch64/macroAssembler_aarch64.hpp | 9 + src/hotspot/cpu/aarch64/spin_wait_aarch64.cpp | 3 + src/hotspot/cpu/aarch64/spin_wait_aarch64.hpp | 17 +- .../cpu/aarch64/vm_version_aarch64.cpp | 26 +- .../cpu/aarch64/vm_version_aarch64.hpp | 4 +- .../os_cpu/bsd_aarch64/os_bsd_aarch64.cpp | 2 + .../vm_version_linux_aarch64.cpp | 13 + .../flags/jvmFlagConstraintsRuntime.cpp | 16 +- .../classes/jdk/vm/ci/aarch64/AArch64.java | 2 + test/hotspot/gtest/aarch64/aarch64-asmtest.py | 13 +- test/hotspot/gtest/aarch64/asmtest.out.h | 2253 +++++++++-------- .../onSpinWait/TestOnSpinWaitAArch64.java | 38 +- 15 files changed, 1299 insertions(+), 1140 deletions(-) diff --git a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp index 67cf77989d2..ebd8f3a9e03 100644 --- a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp @@ -1095,6 +1095,10 @@ class Assembler : public AbstractAssembler { #undef INSN + void wfet(Register rt) { + system(0b00, 0b011, 0b0001, 0b0000, 0b000, rt); + } + // we only provide mrs and msr for the special purpose system // registers where op1 (instr[20:19]) == 11 // n.b msr has L (instr[21]) == 0 mrs has L == 1 diff --git a/src/hotspot/cpu/aarch64/globals_aarch64.hpp b/src/hotspot/cpu/aarch64/globals_aarch64.hpp index e6de2c798b1..0ca5cb25e0c 100644 --- a/src/hotspot/cpu/aarch64/globals_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/globals_aarch64.hpp @@ -115,14 +115,18 @@ define_pd_global(intx, InlineSmallCode, 1000); "Value -1 means off.") \ range(-1, 4096) \ product(ccstr, OnSpinWaitInst, "yield", DIAGNOSTIC, \ - "The instruction to use to implement " \ - "java.lang.Thread.onSpinWait()." \ - "Valid values are: none, nop, isb, yield, sb.") \ + "The instruction to use for java.lang.Thread.onSpinWait(). " \ + "Valid values are: none, nop, isb, yield, sb, wfet.") \ constraint(OnSpinWaitInstNameConstraintFunc, AtParse) \ product(uint, OnSpinWaitInstCount, 1, DIAGNOSTIC, \ - "The number of OnSpinWaitInst instructions to generate." \ - "It cannot be used with OnSpinWaitInst=none.") \ + "The number of OnSpinWaitInst instructions to generate. " \ + "It cannot be used with OnSpinWaitInst=none. " \ + "For OnSpinWaitInst=wfet it must be 1.") \ range(1, 99) \ + product(uint, OnSpinWaitDelay, 40, DIAGNOSTIC, \ + "The minimum delay (in nanoseconds) of the OnSpinWait loop. " \ + "It can only be used with -XX:OnSpinWaitInst=wfet.") \ + range(1, 1000) \ product(ccstr, UseBranchProtection, "none", \ "Branch Protection to use: none, standard, pac-ret") \ product(bool, AlwaysMergeDMB, true, DIAGNOSTIC, \ diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp index 732d94180ae..ebbc35ce20a 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp @@ -6807,6 +6807,9 @@ void MacroAssembler::spin_wait() { assert(VM_Version::supports_sb(), "current CPU does not support SB instruction"); sb(); break; + case SpinWait::WFET: + spin_wait_wfet(VM_Version::spin_wait_desc().delay()); + break; default: ShouldNotReachHere(); } @@ -6814,6 +6817,28 @@ void MacroAssembler::spin_wait() { block_comment("}"); } +void MacroAssembler::spin_wait_wfet(int delay_ns) { + // The sequence assumes CNTFRQ_EL0 is fixed to 1GHz. The assumption is valid + // starting from Armv8.6, according to the "D12.1.2 The system counter" of the + // Arm Architecture Reference Manual for A-profile architecture version M.a.a. + // This is sufficient because FEAT_WFXT is introduced from Armv8.6. + Register target = rscratch1; + Register current = rscratch2; + get_cntvctss_el0(current); + add(target, current, delay_ns); + + Label L_wait_loop; + bind(L_wait_loop); + + wfet(target); + get_cntvctss_el0(current); + + cmp(current, target); + br(LT, L_wait_loop); + + sb(); +} + // Stack frame creation/removal void MacroAssembler::enter(bool strip_ret_addr) { diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp index fa32f3055b9..994fbe3c80f 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp @@ -660,6 +660,14 @@ class MacroAssembler: public Assembler { msr(0b011, 0b0100, 0b0010, 0b000, reg); } + // CNTVCTSS_EL0: op1 == 011 + // CRn == 1110 + // CRm == 0000 + // op2 == 110 + inline void get_cntvctss_el0(Register reg) { + mrs(0b011, 0b1110, 0b0000, 0b110, reg); + } + // idiv variant which deals with MINLONG as dividend and -1 as divisor int corrected_idivl(Register result, Register ra, Register rb, bool want_remainder, Register tmp = rscratch1); @@ -1724,6 +1732,7 @@ class MacroAssembler: public Assembler { // Code for java.lang.Thread::onSpinWait() intrinsic. void spin_wait(); + void spin_wait_wfet(int delay_ns); void fast_lock(Register basic_lock, Register obj, Register t1, Register t2, Register t3, Label& slow); void fast_unlock(Register obj, Register t1, Register t2, Register t3, Label& slow); diff --git a/src/hotspot/cpu/aarch64/spin_wait_aarch64.cpp b/src/hotspot/cpu/aarch64/spin_wait_aarch64.cpp index 7da0151d834..97a981ab815 100644 --- a/src/hotspot/cpu/aarch64/spin_wait_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/spin_wait_aarch64.cpp @@ -32,6 +32,7 @@ bool SpinWait::supports(const char *name) { strcmp(name, "isb") == 0 || strcmp(name, "yield") == 0 || strcmp(name, "sb") == 0 || + strcmp(name, "wfet") == 0 || strcmp(name, "none") == 0); } @@ -46,6 +47,8 @@ SpinWait::Inst SpinWait::from_name(const char* name) { return SpinWait::YIELD; } else if (strcmp(name, "sb") == 0) { return SpinWait::SB; + } else if (strcmp(name, "wfet") == 0) { + return SpinWait::WFET; } return SpinWait::NONE; diff --git a/src/hotspot/cpu/aarch64/spin_wait_aarch64.hpp b/src/hotspot/cpu/aarch64/spin_wait_aarch64.hpp index 0e96a4b7157..6ebcd2477a8 100644 --- a/src/hotspot/cpu/aarch64/spin_wait_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/spin_wait_aarch64.hpp @@ -24,6 +24,8 @@ #ifndef CPU_AARCH64_SPIN_WAIT_AARCH64_HPP #define CPU_AARCH64_SPIN_WAIT_AARCH64_HPP +#include "utilities/debug.hpp" + class SpinWait { public: enum Inst { @@ -31,21 +33,30 @@ class SpinWait { NOP, ISB, YIELD, - SB + SB, + WFET }; private: Inst _inst; int _count; + int _delay; Inst from_name(const char *name); public: - SpinWait(Inst inst = NONE, int count = 0) : _inst(inst), _count(inst == NONE ? 0 : count) {} - SpinWait(const char *name, int count) : SpinWait(from_name(name), count) {} + SpinWait(Inst inst = NONE, int count = 0, int delay = -1) + : _inst(inst), _count(inst == NONE ? 0 : count), _delay(delay) {} + SpinWait(const char *name, int count, int delay) + : SpinWait(from_name(name), count, delay) {} Inst inst() const { return _inst; } int inst_count() const { return _count; } + int delay() const { + assert(_inst == WFET, "Specifying the delay value is only supported for WFET"); + assert(_delay > 0, "The delay value must be positive"); + return _delay; + } static bool supports(const char *name); }; diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp index 4423d9c5b58..8ccffac25a8 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp @@ -1,7 +1,7 @@ /* * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, 2020, Red Hat Inc. All rights reserved. - * Copyright 2025 Arm Limited and/or its affiliates. + * Copyright 2025, 2026 Arm Limited and/or its affiliates. * 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,11 +55,33 @@ SpinWait VM_Version::_spin_wait; const char* VM_Version::_features_names[MAX_CPU_FEATURES] = { nullptr }; static SpinWait get_spin_wait_desc() { - SpinWait spin_wait(OnSpinWaitInst, OnSpinWaitInstCount); + SpinWait spin_wait(OnSpinWaitInst, OnSpinWaitInstCount, OnSpinWaitDelay); if (spin_wait.inst() == SpinWait::SB && !VM_Version::supports_sb()) { vm_exit_during_initialization("OnSpinWaitInst is SB but current CPU does not support SB instruction"); } + if (spin_wait.inst() == SpinWait::WFET) { + if (!VM_Version::supports_wfxt()) { + vm_exit_during_initialization("OnSpinWaitInst is WFET but the CPU does not support the WFET instruction"); + } + + if (!VM_Version::supports_ecv()) { + vm_exit_during_initialization("The CPU does not support the FEAT_ECV required by the -XX:OnSpinWaitInst=wfet implementation"); + } + + if (!VM_Version::supports_sb()) { + vm_exit_during_initialization("The CPU does not support the SB instruction required by the -XX:OnSpinWaitInst=wfet implementation"); + } + + if (OnSpinWaitInstCount != 1) { + vm_exit_during_initialization("OnSpinWaitInstCount for OnSpinWaitInst 'wfet' must be 1"); + } + } else { + if (!FLAG_IS_DEFAULT(OnSpinWaitDelay)) { + vm_exit_during_initialization("OnSpinWaitDelay can only be used with -XX:OnSpinWaitInst=wfet"); + } + } + return spin_wait; } diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp index e8681611234..378524fe168 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp @@ -159,7 +159,9 @@ class VM_Version : public Abstract_VM_Version { /* flags above must follow Linux HWCAP */ \ decl(SVEBITPERM, svebitperm, 27) \ decl(SVE2, sve2, 28) \ - decl(A53MAC, a53mac, 31) + decl(A53MAC, a53mac, 31) \ + decl(ECV, ecv, 32) \ + decl(WFXT, wfxt, 33) enum Feature_Flag { #define DECLARE_CPU_FEATURE_FLAG(id, name, bit) CPU_##id = bit, diff --git a/src/hotspot/os_cpu/bsd_aarch64/os_bsd_aarch64.cpp b/src/hotspot/os_cpu/bsd_aarch64/os_bsd_aarch64.cpp index 36599594842..49d879731ff 100644 --- a/src/hotspot/os_cpu/bsd_aarch64/os_bsd_aarch64.cpp +++ b/src/hotspot/os_cpu/bsd_aarch64/os_bsd_aarch64.cpp @@ -620,6 +620,8 @@ extern "C" { assert(VM_Version::supports_sb(), "current CPU does not support SB instruction"); asm volatile(".inst 0xd50330ff" : : : "memory"); break; + case SpinWait::WFET: + ShouldNotReachHere(); #ifdef ASSERT default: ShouldNotReachHere(); 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 1fe06dc640d..168fc622a0b 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 @@ -95,6 +95,13 @@ #define HWCAP2_SVEBITPERM (1 << 4) #endif +#ifndef HWCAP2_ECV +#define HWCAP2_ECV (1 << 19) +#endif + +#ifndef HWCAP2_WFXT +#define HWCAP2_WFXT (1u << 31) +#endif #ifndef PR_SVE_GET_VL // For old toolchains which do not have SVE related macros defined. #define PR_SVE_SET_VL 50 @@ -158,6 +165,12 @@ void VM_Version::get_os_cpu_info() { if (auxv2 & HWCAP2_SVEBITPERM) { set_feature(CPU_SVEBITPERM); } + if (auxv2 & HWCAP2_ECV) { + set_feature(CPU_ECV); + } + if (auxv2 & HWCAP2_WFXT) { + set_feature(CPU_WFXT); + } uint64_t ctr_el0; uint64_t dczid_el0; diff --git a/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.cpp b/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.cpp index 1e6efd893c8..1f16fada239 100644 --- a/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.cpp +++ b/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.cpp @@ -153,6 +153,20 @@ JVMFlag::Error OnSpinWaitInstNameConstraintFunc(ccstr value, bool verbose) { return JVMFlag::VIOLATES_CONSTRAINT; } +#ifdef LINUX + if (strcmp(value, "wfet") == 0) { + if (UnlockExperimentalVMOptions) { + return JVMFlag::SUCCESS; + } else { + JVMFlag::printError(verbose, + "'wfet' value for OnSpinWaitInst is experimental and " + "must be enabled via -XX:+UnlockExperimentalVMOptions.\n" + "Error: The unlock option must precede 'OnSpinWaitInst'.\n"); + return JVMFlag::VIOLATES_CONSTRAINT; + } + } +#endif + if (strcmp(value, "nop") != 0 && strcmp(value, "isb") != 0 && strcmp(value, "yield") != 0 && @@ -160,7 +174,7 @@ JVMFlag::Error OnSpinWaitInstNameConstraintFunc(ccstr value, bool verbose) { strcmp(value, "none") != 0) { JVMFlag::printError(verbose, "Unrecognized value %s for OnSpinWaitInst. Must be one of the following: " - "nop, isb, yield, sb, none\n", + "nop, isb, yield, sb," LINUX_ONLY(" wfet,") " none\n", value); return JVMFlag::VIOLATES_CONSTRAINT; } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/aarch64/AArch64.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/aarch64/AArch64.java index 391ac224609..7790a9abd7c 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/aarch64/AArch64.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/aarch64/AArch64.java @@ -184,6 +184,8 @@ public enum CPUFeature implements CPUFeatureName { SVEBITPERM, SVE2, A53MAC, + ECV, + WFXT, FPHP, ASIMDHP, } diff --git a/test/hotspot/gtest/aarch64/aarch64-asmtest.py b/test/hotspot/gtest/aarch64/aarch64-asmtest.py index 1ac2e1a89cd..bcf786d6f1f 100644 --- a/test/hotspot/gtest/aarch64/aarch64-asmtest.py +++ b/test/hotspot/gtest/aarch64/aarch64-asmtest.py @@ -391,6 +391,11 @@ def __init__(self, args): self.CRn = 0b0100 self.CRm = 0b0010 self.op2 = 0b000 + elif self.system_reg == 'cntvctss_el0': + self.op1 = 0b011 + self.CRn = 0b1110 + self.CRm = 0b0000 + self.op2 = 0b110 def generate(self): self.reg = [GeneralRegister().generate()] @@ -1607,6 +1612,8 @@ def generate(kind, names): "pacia1716", "paciasp", "paciaz", "pacib1716", "pacibsp", "pacibz", "eret", "drps", "isb", "sb",]) +generate (OneRegOp, ["wfet"]) + # Ensure the "i" is not stripped off the end of the instruction generate (PostfixExceptionOp, ["wfi", "xpaclri"]) @@ -1623,7 +1630,7 @@ def generate(kind, names): for system_reg in ["fpsr", "nzcv"]: generate (SystemOneRegOp, [ ["msr", system_reg] ]) -for system_reg in ["fpsr", "nzcv", "dczid_el0", "ctr_el0"]: +for system_reg in ["fpsr", "nzcv", "dczid_el0", "ctr_el0", "cntvctss_el0"]: generate (OneRegSystemOp, [ ["mrs", system_reg] ]) # Ensure the "i" is not stripped off the end of the instruction @@ -2275,9 +2282,9 @@ def generate(kind, names): outfile.close() -# compile for sve with armv9-a+sha3+sve2-bitperm because of SHA3 crypto extension and SVE2 bitperm instructions. +# compile for sve with armv9.2-a+sha3+sve2-bitperm because of SHA3 crypto extension and SVE2 bitperm instructions. # armv9-a enables sve and sve2 by default. -subprocess.check_call([AARCH64_AS, "-march=armv9-a+sha3+sve2-bitperm", "aarch64ops.s", "-o", "aarch64ops.o"]) +subprocess.check_call([AARCH64_AS, "-march=armv9.2-a+sha3+sve2-bitperm", "aarch64ops.s", "-o", "aarch64ops.o"]) print print "/*" diff --git a/test/hotspot/gtest/aarch64/asmtest.out.h b/test/hotspot/gtest/aarch64/asmtest.out.h index 22bb6c57784..cd9fd4cfe9a 100644 --- a/test/hotspot/gtest/aarch64/asmtest.out.h +++ b/test/hotspot/gtest/aarch64/asmtest.out.h @@ -189,756 +189,762 @@ __ isb(); // isb __ sb(); // sb +// OneRegOp + __ wfet(r26); // wfet x26 + // PostfixExceptionOp __ wfi(); // wfi __ xpaclri(); // xpaclri // SystemOp - __ dsb(Assembler::ST); // dsb ST - __ dmb(Assembler::OSHST); // dmb OSHST + __ dsb(Assembler::OSHST); // dsb OSHST + __ dmb(Assembler::ISHLD); // dmb ISHLD // OneRegOp - __ br(r16); // br x16 - __ blr(r20); // blr x20 - __ paciza(r10); // paciza x10 - __ pacizb(r27); // pacizb x27 - __ pacdza(r8); // pacdza x8 - __ pacdzb(r0); // pacdzb x0 - __ autiza(r1); // autiza x1 - __ autizb(r21); // autizb x21 - __ autdza(r17); // autdza x17 + __ br(r20); // br x20 + __ blr(r10); // blr x10 + __ paciza(r27); // paciza x27 + __ pacizb(r8); // pacizb x8 + __ pacdza(r0); // pacdza x0 + __ pacdzb(r1); // pacdzb x1 + __ autiza(r21); // autiza x21 + __ autizb(r17); // autizb x17 + __ autdza(r29); // autdza x29 __ autdzb(r29); // autdzb x29 - __ xpacd(r29); // xpacd x29 - __ braaz(r28); // braaz x28 - __ brabz(r1); // brabz x1 - __ blraaz(r23); // blraaz x23 - __ blrabz(r21); // blrabz x21 + __ xpacd(r28); // xpacd x28 + __ braaz(r1); // braaz x1 + __ brabz(r23); // brabz x23 + __ blraaz(r21); // blraaz x21 + __ blrabz(r20); // blrabz x20 // SystemOneRegOp - __ msr(3, 4, 4, 1, r20); // msr fpsr, x20 + __ msr(3, 4, 4, 1, r22); // msr fpsr, x22 // SystemOneRegOp - __ msr(3, 4, 2, 0, r22); // msr nzcv, x22 + __ msr(3, 4, 2, 0, r27); // msr nzcv, x27 + +// OneRegSystemOp + __ mrs(3, 4, 4, 1, r19); // mrs x19, fpsr // OneRegSystemOp - __ mrs(3, 4, 4, 1, r27); // mrs x27, fpsr + __ mrs(3, 4, 2, 0, r11); // mrs x11, nzcv // OneRegSystemOp - __ mrs(3, 4, 2, 0, r19); // mrs x19, nzcv + __ mrs(3, 0, 0, 7, r16); // mrs x16, dczid_el0 // OneRegSystemOp - __ mrs(3, 0, 0, 7, r11); // mrs x11, dczid_el0 + __ mrs(3, 0, 0, 1, r6); // mrs x6, ctr_el0 // OneRegSystemOp - __ mrs(3, 0, 0, 1, r16); // mrs x16, ctr_el0 + __ mrs(3, 14, 0, 6, r17); // mrs x17, cntvctss_el0 // PostfixExceptionOneRegOp - __ xpaci(r6); // xpaci x6 + __ xpaci(r0); // xpaci x0 // LoadStoreExclusiveOp - __ stxr(r17, r0, r4); // stxr w17, x0, [x4] - __ stlxr(r10, r24, r22); // stlxr w10, x24, [x22] - __ ldxr(r10, r19); // ldxr x10, [x19] - __ ldaxr(r1, r5); // ldaxr x1, [x5] - __ stlr(r30, r8); // stlr x30, [x8] - __ ldar(r12, r17); // ldar x12, [x17] + __ stxr(r4, r10, r24); // stxr w4, x10, [x24] + __ stlxr(r22, r10, r19); // stlxr w22, x10, [x19] + __ ldxr(r1, r5); // ldxr x1, [x5] + __ ldaxr(r30, r8); // ldaxr x30, [x8] + __ stlr(r12, r17); // stlr x12, [x17] + __ ldar(r9, r14); // ldar x9, [x14] // LoadStoreExclusiveOp - __ stxrw(r9, r14, r7); // stxr w9, w14, [x7] - __ stlxrw(r1, r5, r16); // stlxr w1, w5, [x16] - __ ldxrw(r2, r12); // ldxr w2, [x12] - __ ldaxrw(r10, r12); // ldaxr w10, [x12] - __ stlrw(r3, r28); // stlr w3, [x28] - __ ldarw(r14, r26); // ldar w14, [x26] + __ stxrw(r7, r1, r5); // stxr w7, w1, [x5] + __ stlxrw(r16, r2, r12); // stlxr w16, w2, [x12] + __ ldxrw(r10, r12); // ldxr w10, [x12] + __ ldaxrw(r3, r28); // ldaxr w3, [x28] + __ stlrw(r14, r26); // stlr w14, [x26] + __ ldarw(r30, r10); // ldar w30, [x10] // LoadStoreExclusiveOp - __ stxrh(r30, r10, r14); // stxrh w30, w10, [x14] - __ stlxrh(r21, r13, r9); // stlxrh w21, w13, [x9] - __ ldxrh(r22, r27); // ldxrh w22, [x27] - __ ldaxrh(r28, r19); // ldaxrh w28, [x19] - __ stlrh(r11, r30); // stlrh w11, [x30] - __ ldarh(r19, r2); // ldarh w19, [x2] + __ stxrh(r14, r21, r13); // stxrh w14, w21, [x13] + __ stlxrh(r9, r22, r27); // stlxrh w9, w22, [x27] + __ ldxrh(r28, r19); // ldxrh w28, [x19] + __ ldaxrh(r11, r30); // ldaxrh w11, [x30] + __ stlrh(r19, r2); // stlrh w19, [x2] + __ ldarh(r2, r23); // ldarh w2, [x23] // LoadStoreExclusiveOp - __ stxrb(r2, r23, r1); // stxrb w2, w23, [x1] - __ stlxrb(r0, r12, r16); // stlxrb w0, w12, [x16] - __ ldxrb(r13, r15); // ldxrb w13, [x15] - __ ldaxrb(r17, r21); // ldaxrb w17, [x21] - __ stlrb(r13, r11); // stlrb w13, [x11] - __ ldarb(r30, r8); // ldarb w30, [x8] + __ stxrb(r1, r0, r12); // stxrb w1, w0, [x12] + __ stlxrb(r16, r13, r15); // stlxrb w16, w13, [x15] + __ ldxrb(r17, r21); // ldxrb w17, [x21] + __ ldaxrb(r13, r11); // ldaxrb w13, [x11] + __ stlrb(r30, r8); // stlrb w30, [x8] + __ ldarb(r24, r13); // ldarb w24, [x13] // LoadStoreExclusiveOp - __ ldxp(r24, r13, r11); // ldxp x24, x13, [x11] - __ ldaxp(r1, r26, r21); // ldaxp x1, x26, [x21] - __ stxp(r27, r13, r20, r3); // stxp w27, x13, x20, [x3] - __ stlxp(r12, r6, r1, r29); // stlxp w12, x6, x1, [x29] + __ ldxp(r11, r1, r26); // ldxp x11, x1, [x26] + __ ldaxp(r21, r27, r13); // ldaxp x21, x27, [x13] + __ stxp(r20, r3, r12, r6); // stxp w20, x3, x12, [x6] + __ stlxp(r1, r29, r6, r4); // stlxp w1, x29, x6, [x4] // LoadStoreExclusiveOp - __ ldxpw(r6, r4, r11); // ldxp w6, w4, [x11] - __ ldaxpw(r16, r4, r30); // ldaxp w16, w4, [x30] - __ stxpw(r30, r4, r12, r21); // stxp w30, w4, w12, [x21] - __ stlxpw(r27, r15, r28, r9); // stlxp w27, w15, w28, [x9] + __ ldxpw(r6, r11, r16); // ldxp w6, w11, [x16] + __ ldaxpw(r4, r30, r12); // ldaxp w4, w30, [x12] + __ stxpw(r21, r27, r15, r28); // stxp w21, w27, w15, [x28] + __ stlxpw(r9, r15, r20, r6); // stlxp w9, w15, w20, [x6] // base_plus_unscaled_offset // LoadStoreOp - __ str(r25, Address(r15, 1)); // str x25, [x15, 1] - __ strw(r2, Address(r1, -79)); // str w2, [x1, -79] - __ strb(r20, Address(r26, -22)); // strb w20, [x26, -22] - __ strh(r23, Address(r30, 22)); // strh w23, [x30, 22] - __ ldr(r26, Address(r28, -49)); // ldr x26, [x28, -49] - __ ldrw(r9, Address(r24, -128)); // ldr w9, [x24, -128] - __ ldrb(r12, Address(r12, -30)); // ldrb w12, [x12, -30] - __ ldrh(r1, Address(r15, 5)); // ldrh w1, [x15, 5] - __ ldrsb(r24, Address(r14, -31)); // ldrsb x24, [x14, -31] - __ ldrsh(r24, Address(r15, -6)); // ldrsh x24, [x15, -6] - __ ldrshw(r5, Address(r3, 12)); // ldrsh w5, [x3, 12] - __ ldrsw(r27, Address(r24, 17)); // ldrsw x27, [x24, 17] - __ ldrd(v13, Address(r29, -35)); // ldr d13, [x29, -35] - __ ldrs(v23, Address(r9, -47)); // ldr s23, [x9, -47] - __ strd(v11, Address(r0, 9)); // str d11, [x0, 9] - __ strs(v21, Address(r0, -127)); // str s21, [x0, -127] + __ str(r24, Address(r17, -125)); // str x24, [x17, -125] + __ strw(r1, Address(r26, 10)); // str w1, [x26, 10] + __ strb(r15, Address(r0, -17)); // strb w15, [x0, -17] + __ strh(r17, Address(r17, 13)); // strh w17, [x17, 13] + __ ldr(r5, Address(r25, 49)); // ldr x5, [x25, 49] + __ ldrw(r19, Address(r15, -116)); // ldr w19, [x15, -116] + __ ldrb(r20, Address(r3, 7)); // ldrb w20, [x3, 7] + __ ldrh(r19, Address(r4, -25)); // ldrh w19, [x4, -25] + __ ldrsb(r14, Address(r19, -6)); // ldrsb x14, [x19, -6] + __ ldrsh(r28, Address(r19, -53)); // ldrsh x28, [x19, -53] + __ ldrshw(r14, Address(r27, 13)); // ldrsh w14, [x27, 13] + __ ldrsw(r6, Address(r24, -120)); // ldrsw x6, [x24, -120] + __ ldrd(v18, Address(r2, 87)); // ldr d18, [x2, 87] + __ ldrs(v0, Address(r28, -48)); // ldr s0, [x28, -48] + __ strd(v31, Address(r28, 23)); // str d31, [x28, 23] + __ strs(v11, Address(r25, 43)); // str s11, [x25, 43] // pre // LoadStoreOp - __ str(r29, Address(__ pre(r3, -114))); // str x29, [x3, -114]! - __ strw(r17, Address(__ pre(r4, -72))); // str w17, [x4, -72]! - __ strb(r0, Address(__ pre(r2, -17))); // strb w0, [x2, -17]! - __ strh(r29, Address(__ pre(r1, 7))); // strh w29, [x1, 7]! - __ ldr(r16, Address(__ pre(r21, -133))); // ldr x16, [x21, -133]! - __ ldrw(r20, Address(__ pre(r14, 19))); // ldr w20, [x14, 19]! - __ ldrb(r22, Address(__ pre(r14, -3))); // ldrb w22, [x14, -3]! - __ ldrh(r15, Address(__ pre(r17, 9))); // ldrh w15, [x17, 9]! - __ ldrsb(r10, Address(__ pre(r15, -19))); // ldrsb x10, [x15, -19]! - __ ldrsh(r20, Address(__ pre(r12, -25))); // ldrsh x20, [x12, -25]! - __ ldrshw(r21, Address(__ pre(r10, -29))); // ldrsh w21, [x10, -29]! - __ ldrsw(r19, Address(__ pre(r0, 5))); // ldrsw x19, [x0, 5]! - __ ldrd(v0, Address(__ pre(r14, -54))); // ldr d0, [x14, -54]! - __ ldrs(v3, Address(__ pre(r1, 40))); // ldr s3, [x1, 40]! - __ strd(v4, Address(__ pre(r14, -94))); // str d4, [x14, -94]! - __ strs(v18, Address(__ pre(r28, -54))); // str s18, [x28, -54]! + __ str(r14, Address(__ pre(r8, -185))); // str x14, [x8, -185]! + __ strw(r25, Address(__ pre(r9, -93))); // str w25, [x9, -93]! + __ strb(r16, Address(__ pre(r23, -12))); // strb w16, [x23, -12]! + __ strh(r22, Address(__ pre(r9, -56))); // strh w22, [x9, -56]! + __ ldr(r11, Address(__ pre(r24, 109))); // ldr x11, [x24, 109]! + __ ldrw(r21, Address(__ pre(r19, 52))); // ldr w21, [x19, 52]! + __ ldrb(r6, Address(__ pre(r23, -2))); // ldrb w6, [x23, -2]! + __ ldrh(r7, Address(__ pre(r8, 21))); // ldrh w7, [x8, 21]! + __ ldrsb(r4, Address(__ pre(r12, -31))); // ldrsb x4, [x12, -31]! + __ ldrsh(r8, Address(__ pre(r11, -4))); // ldrsh x8, [x11, -4]! + __ ldrshw(r14, Address(__ pre(r21, -28))); // ldrsh w14, [x21, -28]! + __ ldrsw(r0, Address(__ pre(r15, -71))); // ldrsw x0, [x15, -71]! + __ ldrd(v27, Address(__ pre(r2, 29))); // ldr d27, [x2, 29]! + __ ldrs(v13, Address(__ pre(r21, 16))); // ldr s13, [x21, 16]! + __ strd(v12, Address(__ pre(r27, 16))); // str d12, [x27, 16]! + __ strs(v2, Address(__ pre(r25, -91))); // str s2, [x25, -91]! // post // LoadStoreOp - __ str(r22, Address(__ post(r15, -185))); // str x22, [x15], -185 - __ strw(r17, Address(__ post(r14, -7))); // str w17, [x14], -7 - __ strb(r30, Address(__ post(r11, -25))); // strb w30, [x11], -25 - __ strh(r1, Address(__ post(r11, 20))); // strh w1, [x11], 20 - __ ldr(r22, Address(__ post(r1, 2))); // ldr x22, [x1], 2 - __ ldrw(r2, Address(__ post(r23, -119))); // ldr w2, [x23], -119 - __ ldrb(r3, Address(__ post(r27, -12))); // ldrb w3, [x27], -12 - __ ldrh(r16, Address(__ post(r7, -37))); // ldrh w16, [x7], -37 - __ ldrsb(r15, Address(__ post(r26, 3))); // ldrsb x15, [x26], 3 - __ ldrsh(r7, Address(__ post(r15, -30))); // ldrsh x7, [x15], -30 - __ ldrshw(r3, Address(__ post(r11, -48))); // ldrsh w3, [x11], -48 - __ ldrsw(r25, Address(__ post(r23, 22))); // ldrsw x25, [x23], 22 - __ ldrd(v0, Address(__ post(r10, -215))); // ldr d0, [x10], -215 - __ ldrs(v19, Address(__ post(r6, 55))); // ldr s19, [x6], 55 - __ strd(v14, Address(__ post(r21, -234))); // str d14, [x21], -234 - __ strs(v0, Address(__ post(r22, -70))); // str s0, [x22], -70 + __ str(r10, Address(__ post(r13, -21))); // str x10, [x13], -21 + __ strw(r7, Address(__ post(r1, 50))); // str w7, [x1], 50 + __ strb(r10, Address(__ post(r3, 5))); // strb w10, [x3], 5 + __ strh(r5, Address(__ post(r6, -33))); // strh w5, [x6], -33 + __ ldr(r13, Address(__ post(r22, -158))); // ldr x13, [x22], -158 + __ ldrw(r13, Address(__ post(r2, -106))); // ldr w13, [x2], -106 + __ ldrb(r13, Address(__ post(r16, -24))); // ldrb w13, [x16], -24 + __ ldrh(r24, Address(__ post(r2, -22))); // ldrh w24, [x2], -22 + __ ldrsb(r3, Address(__ post(r23, -1))); // ldrsb x3, [x23], -1 + __ ldrsh(r19, Address(__ post(r8, -43))); // ldrsh x19, [x8], -43 + __ ldrshw(r2, Address(__ post(r23, -8))); // ldrsh w2, [x23], -8 + __ ldrsw(r19, Address(__ post(r28, -87))); // ldrsw x19, [x28], -87 + __ ldrd(v15, Address(__ post(r3, -81))); // ldr d15, [x3], -81 + __ ldrs(v12, Address(__ post(r29, -79))); // ldr s12, [x29], -79 + __ strd(v21, Address(__ post(r1, -124))); // str d21, [x1], -124 + __ strs(v7, Address(__ post(r9, -99))); // str s7, [x9], -99 // base_plus_reg // LoadStoreOp - __ str(r27, Address(r19, r0, Address::sxtx(0))); // str x27, [x19, x0, sxtx #0] - __ strw(r8, Address(r6, r13, Address::lsl(0))); // str w8, [x6, x13, lsl #0] - __ strb(r4, Address(r16, r22, Address::lsl(0))); // strb w4, [x16, x22, lsl #0] - __ strh(r25, Address(r26, r15, Address::uxtw(0))); // strh w25, [x26, w15, uxtw #0] - __ ldr(r4, Address(r5, r24, Address::sxtw(0))); // ldr x4, [x5, w24, sxtw #0] - __ ldrw(r4, Address(r17, r7, Address::uxtw(0))); // ldr w4, [x17, w7, uxtw #0] - __ ldrb(r17, Address(r7, r11, Address::lsl(0))); // ldrb w17, [x7, x11, lsl #0] - __ ldrh(r0, Address(r30, r23, Address::lsl(0))); // ldrh w0, [x30, x23, lsl #0] - __ ldrsb(r10, Address(r22, r1, Address::uxtw(0))); // ldrsb x10, [x22, w1, uxtw #0] - __ ldrsh(r21, Address(r30, r30, Address::sxtw(1))); // ldrsh x21, [x30, w30, sxtw #1] - __ ldrshw(r11, Address(r10, r28, Address::sxtw(1))); // ldrsh w11, [x10, w28, sxtw #1] - __ ldrsw(r28, Address(r19, r10, Address::uxtw(0))); // ldrsw x28, [x19, w10, uxtw #0] - __ ldrd(v30, Address(r29, r14, Address::sxtw(0))); // ldr d30, [x29, w14, sxtw #0] - __ ldrs(v8, Address(r5, r5, Address::sxtw(2))); // ldr s8, [x5, w5, sxtw #2] - __ strd(v25, Address(r8, r13, Address::sxtx(0))); // str d25, [x8, x13, sxtx #0] - __ strs(v17, Address(r24, r26, Address::lsl(2))); // str s17, [x24, x26, lsl #2] + __ str(r5, Address(r20, r2, Address::lsl(0))); // str x5, [x20, x2, lsl #0] + __ strw(r14, Address(r10, r30, Address::sxtw(2))); // str w14, [x10, w30, sxtw #2] + __ strb(r4, Address(r1, r28, Address::sxtw(0))); // strb w4, [x1, w28, sxtw #0] + __ strh(r5, Address(r10, r26, Address::sxtx(1))); // strh w5, [x10, x26, sxtx #1] + __ ldr(r22, Address(r2, r28, Address::lsl(3))); // ldr x22, [x2, x28, lsl #3] + __ ldrw(r12, Address(r0, r28, Address::lsl(2))); // ldr w12, [x0, x28, lsl #2] + __ ldrb(r8, Address(r8, r15, Address::sxtx(0))); // ldrb w8, [x8, x15, sxtx #0] + __ ldrh(r17, Address(r21, r14, Address::uxtw(1))); // ldrh w17, [x21, w14, uxtw #1] + __ ldrsb(r17, Address(r24, r8, Address::sxtx(0))); // ldrsb x17, [x24, x8, sxtx #0] + __ ldrsh(r10, Address(r10, r30, Address::sxtx(1))); // ldrsh x10, [x10, x30, sxtx #1] + __ ldrshw(r17, Address(r23, r0, Address::lsl(1))); // ldrsh w17, [x23, x0, lsl #1] + __ ldrsw(r25, Address(r30, r0, Address::lsl(2))); // ldrsw x25, [x30, x0, lsl #2] + __ ldrd(v5, Address(r24, r23, Address::uxtw(3))); // ldr d5, [x24, w23, uxtw #3] + __ ldrs(v22, Address(r3, r15, Address::lsl(2))); // ldr s22, [x3, x15, lsl #2] + __ strd(v4, Address(r29, r16, Address::sxtx(3))); // str d4, [x29, x16, sxtx #3] + __ strs(v7, Address(r20, r28, Address::sxtw(2))); // str s7, [x20, w28, sxtw #2] // base_plus_scaled_offset // LoadStoreOp - __ str(r19, Address(r12, 15904)); // str x19, [x12, 15904] - __ strw(r23, Address(r15, 7892)); // str w23, [x15, 7892] - __ strb(r29, Address(r13, 1970)); // strb w29, [x13, 1970] - __ strh(r11, Address(r7, 3094)); // strh w11, [x7, 3094] - __ ldr(r10, Address(r24, 14992)); // ldr x10, [x24, 14992] - __ ldrw(r16, Address(r0, 6160)); // ldr w16, [x0, 6160] - __ ldrb(r20, Address(r1, 2032)); // ldrb w20, [x1, 2032] - __ ldrh(r1, Address(r17, 4056)); // ldrh w1, [x17, 4056] - __ ldrsb(r17, Address(r25, 1889)); // ldrsb x17, [x25, 1889] - __ ldrsh(r27, Address(r25, 3964)); // ldrsh x27, [x25, 3964] - __ ldrshw(r14, Address(r17, 3724)); // ldrsh w14, [x17, 3724] - __ ldrsw(r10, Address(r7, 6372)); // ldrsw x10, [x7, 6372] - __ ldrd(v3, Address(r25, 12392)); // ldr d3, [x25, 12392] - __ ldrs(v12, Address(r9, 7840)); // ldr s12, [x9, 7840] - __ strd(v24, Address(r1, 12728)); // str d24, [x1, 12728] - __ strs(v3, Address(r20, 6924)); // str s3, [x20, 6924] + __ str(r27, Address(r0, 16360)); // str x27, [x0, 16360] + __ strw(r21, Address(r8, 7984)); // str w21, [x8, 7984] + __ strb(r17, Address(r29, 1795)); // strb w17, [x29, 1795] + __ strh(r27, Address(r2, 3636)); // strh w27, [x2, 3636] + __ ldr(r1, Address(r1, 12480)); // ldr x1, [x1, 12480] + __ ldrw(r29, Address(r17, 6320)); // ldr w29, [x17, 6320] + __ ldrb(r1, Address(r9, 1634)); // ldrb w1, [x9, 1634] + __ ldrh(r23, Address(r3, 3736)); // ldrh w23, [x3, 3736] + __ ldrsb(r21, Address(r19, 1857)); // ldrsb x21, [x19, 1857] + __ ldrsh(r19, Address(r7, 3180)); // ldrsh x19, [x7, 3180] + __ ldrshw(r10, Address(r1, 3560)); // ldrsh w10, [x1, 3560] + __ ldrsw(r10, Address(r20, 7428)); // ldrsw x10, [x20, 7428] + __ ldrd(v0, Address(r13, 14880)); // ldr d0, [x13, 14880] + __ ldrs(v11, Address(r27, 6356)); // ldr s11, [x27, 6356] + __ strd(v13, Address(r25, 13704)); // str d13, [x25, 13704] + __ strs(v20, Address(r0, 7580)); // str s20, [x0, 7580] // pcrel // LoadStoreOp - __ ldr(r2, back); // ldr x2, back - __ ldrw(r29, __ pc()); // ldr w29, . + __ ldr(r26, __ pc()); // ldr x26, . + __ ldrw(r19, back); // ldr w19, back // LoadStoreOp - __ prfm(Address(r14, 93)); // prfm PLDL1KEEP, [x14, 93] + __ prfm(Address(r8, -111)); // prfm PLDL1KEEP, [x8, -111] // LoadStoreOp - __ prfm(back); // prfm PLDL1KEEP, back + __ prfm(forth); // prfm PLDL1KEEP, forth // LoadStoreOp - __ prfm(Address(r1, r7, Address::lsl(3))); // prfm PLDL1KEEP, [x1, x7, lsl #3] + __ prfm(Address(r7, r7, Address::uxtw(3))); // prfm PLDL1KEEP, [x7, w7, uxtw #3] // LoadStoreOp - __ prfm(Address(r17, 12288)); // prfm PLDL1KEEP, [x17, 12288] + __ prfm(Address(r12, 12600)); // prfm PLDL1KEEP, [x12, 12600] // AddSubCarryOp - __ adcw(r1, r24, r3); // adc w1, w24, w3 - __ adcsw(r17, r24, r20); // adcs w17, w24, w20 - __ sbcw(r11, r0, r13); // sbc w11, w0, w13 - __ sbcsw(r28, r10, r7); // sbcs w28, w10, w7 - __ adc(r4, r15, r16); // adc x4, x15, x16 - __ adcs(r2, r12, r20); // adcs x2, x12, x20 - __ sbc(r29, r13, r13); // sbc x29, x13, x13 - __ sbcs(r14, r6, r12); // sbcs x14, x6, x12 + __ adcw(r24, r20, r11); // adc w24, w20, w11 + __ adcsw(r0, r13, r28); // adcs w0, w13, w28 + __ sbcw(r10, r7, r4); // sbc w10, w7, w4 + __ sbcsw(r15, r16, r2); // sbcs w15, w16, w2 + __ adc(r12, r20, r29); // adc x12, x20, x29 + __ adcs(r13, r13, r14); // adcs x13, x13, x14 + __ sbc(r6, r12, r20); // sbc x6, x12, x20 + __ sbcs(r12, r17, r25); // sbcs x12, x17, x25 // AddSubExtendedOp - __ addw(r20, r12, r17, ext::sxtx, 4); // add w20, w12, w17, sxtx #4 - __ addsw(r27, r11, r0, ext::uxtx, 3); // adds w27, w11, w0, uxtx #3 - __ sub(r7, r1, r9, ext::sxtx, 4); // sub x7, x1, x9, sxtx #4 - __ subsw(r3, r27, r1, ext::uxtb, 3); // subs w3, w27, w1, uxtb #3 - __ add(r13, r26, r12, ext::sxth, 4); // add x13, x26, x12, sxth #4 - __ adds(r17, r5, r10, ext::sxtb, 2); // adds x17, x5, x10, sxtb #2 - __ sub(r30, r8, r15, ext::uxtw, 4); // sub x30, x8, x15, uxtw #4 - __ subs(r19, r23, r19, ext::uxth, 4); // subs x19, x23, x19, uxth #4 + __ addw(r30, r27, r11, ext::sxtb, 1); // add w30, w27, w11, sxtb #1 + __ addsw(r14, r7, r1, ext::sxtw, 2); // adds w14, w7, w1, sxtw #2 + __ sub(r29, r3, r27, ext::sxth, 1); // sub x29, x3, x27, sxth #1 + __ subsw(r0, r13, r26, ext::sxtx, 2); // subs w0, w13, w26, sxtx #2 + __ add(r22, r17, r5, ext::uxtx, 2); // add x22, x17, x5, uxtx #2 + __ adds(r17, r30, r8, ext::sxtx, 3); // adds x17, x30, x8, sxtx #3 + __ sub(r10, r19, r23, ext::sxtw, 3); // sub x10, x19, x23, sxtw #3 + __ subs(r6, r29, r5, ext::uxtw, 3); // subs x6, x29, x5, uxtw #3 // ConditionalCompareOp - __ ccmnw(r29, r5, 10u, Assembler::LO); // ccmn w29, w5, #10, LO - __ ccmpw(r9, r13, 11u, Assembler::LO); // ccmp w9, w13, #11, LO - __ ccmn(r10, r4, 6u, Assembler::HS); // ccmn x10, x4, #6, HS - __ ccmp(r12, r2, 12u, Assembler::HI); // ccmp x12, x2, #12, HI + __ ccmnw(r19, r9, 4u, Assembler::HI); // ccmn w19, w9, #4, HI + __ ccmpw(r22, r10, 2u, Assembler::VC); // ccmp w22, w10, #2, VC + __ ccmn(r13, r12, 10u, Assembler::LS); // ccmn x13, x12, #10, LS + __ ccmp(r24, r16, 3u, Assembler::HS); // ccmp x24, x16, #3, HS // ConditionalCompareImmedOp - __ ccmnw(r16, 6, 2, Assembler::VS); // ccmn w16, #6, #2, VS - __ ccmpw(r7, 11, 13, Assembler::VS); // ccmp w7, #11, #13, VS - __ ccmn(r27, 10, 11, Assembler::LS); // ccmn x27, #10, #11, LS - __ ccmp(r3, 13, 13, Assembler::LE); // ccmp x3, #13, #13, LE + __ ccmnw(r7, 11, 13, Assembler::VS); // ccmn w7, #11, #13, VS + __ ccmpw(r27, 10, 11, Assembler::LS); // ccmp w27, #10, #11, LS + __ ccmn(r3, 13, 13, Assembler::LE); // ccmn x3, #13, #13, LE + __ ccmp(r26, 16, 5, Assembler::GT); // ccmp x26, #16, #5, GT // ConditionalSelectOp - __ cselw(r26, r27, r10, Assembler::VS); // csel w26, w27, w10, VS - __ csincw(r10, r21, r28, Assembler::LE); // csinc w10, w21, w28, LE - __ csinvw(r23, r9, r27, Assembler::LE); // csinv w23, w9, w27, LE - __ csnegw(r10, r29, r15, Assembler::LE); // csneg w10, w29, w15, LE - __ csel(r30, r25, r21, Assembler::HS); // csel x30, x25, x21, HS - __ csinc(r0, r17, r21, Assembler::GT); // csinc x0, x17, x21, GT - __ csinv(r16, r21, r20, Assembler::CS); // csinv x16, x21, x20, CS - __ csneg(r19, r30, r3, Assembler::LS); // csneg x19, x30, x3, LS + __ cselw(r10, r21, r28, Assembler::LE); // csel w10, w21, w28, LE + __ csincw(r23, r9, r27, Assembler::LE); // csinc w23, w9, w27, LE + __ csinvw(r10, r29, r15, Assembler::LE); // csinv w10, w29, w15, LE + __ csnegw(r30, r25, r21, Assembler::HS); // csneg w30, w25, w21, HS + __ csel(r0, r17, r21, Assembler::GT); // csel x0, x17, x21, GT + __ csinc(r16, r21, r20, Assembler::CS); // csinc x16, x21, x20, CS + __ csinv(r19, r30, r3, Assembler::LS); // csinv x19, x30, x3, LS + __ csneg(r19, r11, r24, Assembler::EQ); // csneg x19, x11, x24, EQ // TwoRegOp - __ rbitw(r19, r11); // rbit w19, w11 - __ rev16w(r24, r0); // rev16 w24, w0 - __ revw(r27, r25); // rev w27, w25 - __ clzw(r14, r3); // clz w14, w3 - __ clsw(r14, r17); // cls w14, w17 - __ rbit(r7, r15); // rbit x7, x15 - __ rev16(r24, r28); // rev16 x24, x28 - __ rev32(r17, r25); // rev32 x17, x25 - __ rev(r2, r26); // rev x2, x26 - __ clz(r28, r5); // clz x28, x5 - __ cls(r25, r26); // cls x25, x26 - __ pacia(r27, r16); // pacia x27, x16 - __ pacib(r17, r6); // pacib x17, x6 - __ pacda(r21, r12); // pacda x21, x12 - __ pacdb(r0, r4); // pacdb x0, x4 - __ autia(r12, r27); // autia x12, x27 - __ autib(r17, r28); // autib x17, x28 - __ autda(r28, r2); // autda x28, x2 - __ autdb(r17, r10); // autdb x17, x10 - __ braa(r15, r14); // braa x15, x14 - __ brab(r14, r3); // brab x14, x3 - __ blraa(r25, r15); // blraa x25, x15 - __ blrab(r19, r14); // blrab x19, x14 + __ rbitw(r27, r25); // rbit w27, w25 + __ rev16w(r14, r3); // rev16 w14, w3 + __ revw(r14, r17); // rev w14, w17 + __ clzw(r7, r15); // clz w7, w15 + __ clsw(r24, r28); // cls w24, w28 + __ rbit(r17, r25); // rbit x17, x25 + __ rev16(r2, r26); // rev16 x2, x26 + __ rev32(r28, r5); // rev32 x28, x5 + __ rev(r25, r26); // rev x25, x26 + __ clz(r27, r16); // clz x27, x16 + __ cls(r17, r6); // cls x17, x6 + __ pacia(r21, r12); // pacia x21, x12 + __ pacib(r0, r4); // pacib x0, x4 + __ pacda(r12, r27); // pacda x12, x27 + __ pacdb(r17, r28); // pacdb x17, x28 + __ autia(r28, r2); // autia x28, x2 + __ autib(r17, r10); // autib x17, x10 + __ autda(r15, r14); // autda x15, x14 + __ autdb(r14, r3); // autdb x14, x3 + __ braa(r25, r15); // braa x25, x15 + __ brab(r19, r14); // brab x19, x14 + __ blraa(r5, r16); // blraa x5, x16 + __ blrab(r4, r26); // blrab x4, x26 // ThreeRegOp - __ udivw(r5, r16, r4); // udiv w5, w16, w4 - __ sdivw(r26, r25, r4); // sdiv w26, w25, w4 - __ lslvw(r2, r2, r12); // lslv w2, w2, w12 - __ lsrvw(r29, r17, r8); // lsrv w29, w17, w8 - __ asrvw(r7, r3, r4); // asrv w7, w3, w4 - __ rorvw(r25, r4, r26); // rorv w25, w4, w26 - __ udiv(r25, r4, r17); // udiv x25, x4, x17 - __ sdiv(r0, r26, r17); // sdiv x0, x26, x17 - __ lslv(r23, r15, r21); // lslv x23, x15, x21 - __ lsrv(r28, r17, r27); // lsrv x28, x17, x27 - __ asrv(r10, r3, r0); // asrv x10, x3, x0 - __ rorv(r7, r25, r9); // rorv x7, x25, x9 - __ umulh(r6, r15, r29); // umulh x6, x15, x29 - __ smulh(r15, r10, r2); // smulh x15, x10, x2 + __ udivw(r25, r4, r2); // udiv w25, w4, w2 + __ sdivw(r2, r12, r29); // sdiv w2, w12, w29 + __ lslvw(r17, r8, r7); // lslv w17, w8, w7 + __ lsrvw(r3, r4, r25); // lsrv w3, w4, w25 + __ asrvw(r4, r26, r25); // asrv w4, w26, w25 + __ rorvw(r4, r17, r0); // rorv w4, w17, w0 + __ udiv(r26, r17, r23); // udiv x26, x17, x23 + __ sdiv(r15, r21, r28); // sdiv x15, x21, x28 + __ lslv(r17, r27, r10); // lslv x17, x27, x10 + __ lsrv(r3, r0, r7); // lsrv x3, x0, x7 + __ asrv(r25, r9, r6); // asrv x25, x9, x6 + __ rorv(r15, r29, r15); // rorv x15, x29, x15 + __ umulh(r10, r2, r17); // umulh x10, x2, x17 + __ smulh(r7, r11, r11); // smulh x7, x11, x11 // FourRegMulOp - __ maddw(r17, r7, r11, r11); // madd w17, w7, w11, w11 - __ msubw(r23, r7, r29, r23); // msub w23, w7, w29, w23 - __ madd(r14, r27, r11, r11); // madd x14, x27, x11, x11 - __ msub(r4, r24, r12, r15); // msub x4, x24, x12, x15 - __ smaddl(r14, r20, r11, r28); // smaddl x14, w20, w11, x28 - __ smsubl(r13, r11, r12, r23); // smsubl x13, w11, w12, x23 - __ umaddl(r30, r26, r14, r9); // umaddl x30, w26, w14, x9 - __ umsubl(r13, r10, r7, r5); // umsubl x13, w10, w7, x5 + __ maddw(r23, r7, r29, r23); // madd w23, w7, w29, w23 + __ msubw(r14, r27, r11, r11); // msub w14, w27, w11, w11 + __ madd(r4, r24, r12, r15); // madd x4, x24, x12, x15 + __ msub(r14, r20, r11, r28); // msub x14, x20, x11, x28 + __ smaddl(r13, r11, r12, r23); // smaddl x13, w11, w12, x23 + __ smsubl(r30, r26, r14, r9); // smsubl x30, w26, w14, x9 + __ umaddl(r13, r10, r7, r5); // umaddl x13, w10, w7, x5 + __ umsubl(r29, r15, r3, r11); // umsubl x29, w15, w3, x11 // ThreeRegFloatOp - __ fabdh(v30, v15, v3); // fabd h30, h15, h3 - __ fmulh(v12, v12, v16); // fmul h12, h12, h16 - __ fdivh(v31, v31, v18); // fdiv h31, h31, h18 - __ faddh(v19, v21, v16); // fadd h19, h21, h16 - __ fsubh(v15, v10, v21); // fsub h15, h10, h21 - __ fmaxh(v2, v10, v28); // fmax h2, h10, h28 - __ fminh(v7, v30, v31); // fmin h7, h30, h31 - __ fnmulh(v18, v1, v2); // fnmul h18, h1, h2 - __ fabds(v6, v10, v3); // fabd s6, s10, s3 - __ fmuls(v25, v11, v7); // fmul s25, s11, s7 - __ fdivs(v1, v12, v0); // fdiv s1, s12, s0 - __ fadds(v3, v19, v29); // fadd s3, s19, s29 - __ fsubs(v6, v23, v6); // fsub s6, s23, s6 - __ fmaxs(v0, v28, v27); // fmax s0, s28, s27 - __ fmins(v2, v5, v7); // fmin s2, s5, s7 - __ fnmuls(v29, v12, v25); // fnmul s29, s12, s25 - __ fabdd(v13, v12, v24); // fabd d13, d12, d24 - __ fmuld(v19, v8, v18); // fmul d19, d8, d18 - __ fdivd(v22, v26, v21); // fdiv d22, d26, d21 - __ faddd(v20, v19, v2); // fadd d20, d19, d2 - __ fsubd(v30, v22, v8); // fsub d30, d22, d8 - __ fmaxd(v22, v19, v21); // fmax d22, d19, d21 - __ fmind(v12, v18, v21); // fmin d12, d18, d21 - __ fnmuld(v6, v16, v3); // fnmul d6, d16, d3 + __ fabdh(v12, v16, v31); // fabd h12, h16, h31 + __ fmulh(v31, v18, v19); // fmul h31, h18, h19 + __ fdivh(v21, v16, v15); // fdiv h21, h16, h15 + __ faddh(v10, v21, v2); // fadd h10, h21, h2 + __ fsubh(v10, v28, v7); // fsub h10, h28, h7 + __ fmaxh(v30, v31, v18); // fmax h30, h31, h18 + __ fminh(v1, v2, v6); // fmin h1, h2, h6 + __ fnmulh(v10, v3, v25); // fnmul h10, h3, h25 + __ fabds(v11, v7, v1); // fabd s11, s7, s1 + __ fmuls(v12, v0, v3); // fmul s12, s0, s3 + __ fdivs(v19, v29, v6); // fdiv s19, s29, s6 + __ fadds(v23, v6, v0); // fadd s23, s6, s0 + __ fsubs(v28, v27, v2); // fsub s28, s27, s2 + __ fmaxs(v5, v7, v29); // fmax s5, s7, s29 + __ fmins(v12, v25, v13); // fmin s12, s25, s13 + __ fnmuls(v12, v24, v19); // fnmul s12, s24, s19 + __ fabdd(v8, v18, v22); // fabd d8, d18, d22 + __ fmuld(v26, v21, v20); // fmul d26, d21, d20 + __ fdivd(v19, v2, v30); // fdiv d19, d2, d30 + __ faddd(v22, v8, v22); // fadd d22, d8, d22 + __ fsubd(v19, v21, v12); // fsub d19, d21, d12 + __ fmaxd(v18, v21, v6); // fmax d18, d21, d6 + __ fmind(v16, v3, v3); // fmin d16, d3, d3 + __ fnmuld(v29, v3, v28); // fnmul d29, d3, d28 // FourRegFloatOp - __ fmaddh(v3, v29, v3, v28); // fmadd h3, h29, h3, h28 - __ fmadds(v15, v14, v10, v13); // fmadd s15, s14, s10, s13 - __ fmsubs(v12, v18, v10, v26); // fmsub s12, s18, s10, s26 - __ fnmadds(v7, v7, v15, v29); // fnmadd s7, s7, s15, s29 + __ fmaddh(v15, v14, v10, v13); // fmadd h15, h14, h10, h13 + __ fmadds(v12, v18, v10, v26); // fmadd s12, s18, s10, s26 + __ fmsubs(v7, v7, v15, v29); // fmsub s7, s7, s15, s29 __ fnmadds(v0, v23, v0, v12); // fnmadd s0, s23, s0, s12 - __ fmaddd(v24, v14, v13, v8); // fmadd d24, d14, d13, d8 - __ fmsubd(v15, v7, v9, v20); // fmsub d15, d7, d9, d20 - __ fnmaddd(v19, v29, v31, v16); // fnmadd d19, d29, d31, d16 + __ fnmadds(v24, v14, v13, v8); // fnmadd s24, s14, s13, s8 + __ fmaddd(v15, v7, v9, v20); // fmadd d15, d7, d9, d20 + __ fmsubd(v19, v29, v31, v16); // fmsub d19, d29, d31, d16 __ fnmaddd(v2, v9, v16, v21); // fnmadd d2, d9, d16, d21 + __ fnmaddd(v30, v4, v1, v27); // fnmadd d30, d4, d1, d27 // TwoRegFloatOp - __ fmovs(v30, v4); // fmov s30, s4 - __ fabss(v1, v27); // fabs s1, s27 - __ fnegs(v25, v24); // fneg s25, s24 - __ fsqrts(v14, v21); // fsqrt s14, s21 - __ fcvts(v13, v6); // fcvt d13, s6 - __ fcvtsh(v12, v25); // fcvt h12, s25 - __ fcvths(v25, v30); // fcvt s25, h30 - __ fmovd(v28, v21); // fmov d28, d21 - __ fabsd(v16, v23); // fabs d16, d23 - __ fnegd(v5, v29); // fneg d5, d29 - __ fsqrtd(v22, v19); // fsqrt d22, d19 - __ fcvtd(v13, v20); // fcvt s13, d20 - __ fsqrth(v19, v28); // fsqrt h19, h28 + __ fmovs(v25, v24); // fmov s25, s24 + __ fabss(v14, v21); // fabs s14, s21 + __ fnegs(v13, v6); // fneg s13, s6 + __ fsqrts(v12, v25); // fsqrt s12, s25 + __ fcvts(v25, v30); // fcvt d25, s30 + __ fcvtsh(v28, v21); // fcvt h28, s21 + __ fcvths(v16, v23); // fcvt s16, h23 + __ fmovd(v5, v29); // fmov d5, d29 + __ fabsd(v22, v19); // fabs d22, d19 + __ fnegd(v13, v20); // fneg d13, d20 + __ fsqrtd(v19, v28); // fsqrt d19, d28 + __ fcvtd(v18, v6); // fcvt s18, d6 + __ fsqrth(v14, v7); // fsqrt h14, h7 // FloatConvertOp - __ fcvtzsw(r17, v6); // fcvtzs w17, s6 - __ fcvtzs(r13, v7); // fcvtzs x13, s7 - __ fcvtzdw(r28, v26); // fcvtzs w28, d26 - __ fcvtzd(r17, v6); // fcvtzs x17, d6 - __ scvtfws(v1, r4); // scvtf s1, w4 - __ scvtfs(v14, r20); // scvtf s14, x20 - __ scvtfwd(v7, r21); // scvtf d7, w21 - __ scvtfd(v27, r23); // scvtf d27, x23 - __ fcvtassw(r13, v20); // fcvtas w13, s20 - __ fcvtasd(r30, v28); // fcvtas x30, d28 - __ fcvtmssw(r10, v21); // fcvtms w10, s21 - __ fcvtmsd(r5, v17); // fcvtms x5, d17 - __ fmovs(r11, v14); // fmov w11, s14 - __ fmovd(r13, v21); // fmov x13, d21 - __ fmovs(v27, r14); // fmov s27, w14 - __ fmovd(v4, r23); // fmov d4, x23 + __ fcvtzsw(r28, v26); // fcvtzs w28, s26 + __ fcvtzs(r17, v6); // fcvtzs x17, s6 + __ fcvtzdw(r1, v4); // fcvtzs w1, d4 + __ fcvtzd(r13, v21); // fcvtzs x13, d21 + __ scvtfws(v7, r21); // scvtf s7, w21 + __ scvtfs(v27, r23); // scvtf s27, x23 + __ scvtfwd(v13, r20); // scvtf d13, w20 + __ scvtfd(v31, r27); // scvtf d31, x27 + __ fcvtassw(r10, v21); // fcvtas w10, s21 + __ fcvtasd(r5, v17); // fcvtas x5, d17 + __ fcvtmssw(r11, v14); // fcvtms w11, s14 + __ fcvtmsd(r13, v21); // fcvtms x13, d21 + __ fmovs(r26, v14); // fmov w26, s14 + __ fmovd(r4, v24); // fmov x4, d24 + __ fmovs(v24, r29); // fmov s24, w29 + __ fmovd(v12, r14); // fmov d12, x14 // TwoRegFloatOp - __ fcmps(v24, v30); // fcmp s24, s30 - __ fcmpd(v12, v14); // fcmp d12, d14 - __ fcmps(v17, 0.0); // fcmp s17, #0.0 - __ fcmpd(v28, 0.0); // fcmp d28, #0.0 + __ fcmps(v17, v28); // fcmp s17, s28 + __ fcmpd(v22, v0); // fcmp d22, d0 + __ fcmps(v6, 0.0); // fcmp s6, #0.0 + __ fcmpd(v27, 0.0); // fcmp d27, #0.0 // LoadStorePairOp - __ stpw(r0, r6, Address(r26, 16)); // stp w0, w6, [x26, #16] - __ ldpw(r0, r30, Address(r6, -32)); // ldp w0, w30, [x6, #-32] - __ ldpsw(r16, r2, Address(r11, -208)); // ldpsw x16, x2, [x11, #-208] - __ stp(r15, r0, Address(r12, 128)); // stp x15, x0, [x12, #128] - __ ldp(r7, r30, Address(r23, 32)); // ldp x7, x30, [x23, #32] + __ stpw(r27, r12, Address(r6, -32)); // stp w27, w12, [x6, #-32] + __ ldpw(r14, r11, Address(r19, -256)); // ldp w14, w11, [x19, #-256] + __ ldpsw(r0, r12, Address(r15, -48)); // ldpsw x0, x12, [x15, #-48] + __ stp(r9, r23, Address(r23, 32)); // stp x9, x23, [x23, #32] + __ ldp(r15, r4, Address(r26, -176)); // ldp x15, x4, [x26, #-176] // LoadStorePairOp - __ stpw(r26, r15, Address(__ pre(r7, -256))); // stp w26, w15, [x7, #-256]! - __ ldpw(r11, r15, Address(__ pre(r10, -32))); // ldp w11, w15, [x10, #-32]! - __ ldpsw(r19, r16, Address(__ pre(r1, 64))); // ldpsw x19, x16, [x1, #64]! - __ stp(r14, r9, Address(__ pre(r0, 128))); // stp x14, x9, [x0, #128]! - __ ldp(r27, r3, Address(__ pre(r12, -96))); // ldp x27, x3, [x12, #-96]! + __ stpw(r17, r8, Address(__ pre(r6, -160))); // stp w17, w8, [x6, #-160]! + __ ldpw(r7, r2, Address(__ pre(r4, -112))); // ldp w7, w2, [x4, #-112]! + __ ldpsw(r14, r9, Address(__ pre(r22, -16))); // ldpsw x14, x9, [x22, #-16]! + __ stp(r13, r20, Address(__ pre(r24, -256))); // stp x13, x20, [x24, #-256]! + __ ldp(r8, r11, Address(__ pre(r10, 96))); // ldp x8, x11, [x10, #96]! // LoadStorePairOp - __ stpw(r8, r11, Address(__ post(r12, -256))); // stp w8, w11, [x12], #-256 - __ ldpw(r10, r16, Address(__ post(r4, 64))); // ldp w10, w16, [x4], #64 - __ ldpsw(r10, r30, Address(__ post(r19, -64))); // ldpsw x10, x30, [x19], #-64 - __ stp(r24, r2, Address(__ post(r15, -96))); // stp x24, x2, [x15], #-96 - __ ldp(r24, r10, Address(__ post(r16, 80))); // ldp x24, x10, [x16], #80 + __ stpw(r24, r5, Address(__ post(r16, -112))); // stp w24, w5, [x16], #-112 + __ ldpw(r0, r26, Address(__ post(r9, -128))); // ldp w0, w26, [x9], #-128 + __ ldpsw(r24, r2, Address(__ post(r17, -128))); // ldpsw x24, x2, [x17], #-128 + __ stp(r26, r17, Address(__ post(r14, -48))); // stp x26, x17, [x14], #-48 + __ ldp(r30, r21, Address(__ post(r29, 48))); // ldp x30, x21, [x29], #48 // LoadStorePairOp - __ stnpw(r30, r21, Address(r29, 16)); // stnp w30, w21, [x29, #16] - __ ldnpw(r8, r30, Address(r10, -112)); // ldnp w8, w30, [x10, #-112] - __ stnp(r30, r26, Address(r6, -128)); // stnp x30, x26, [x6, #-128] - __ ldnp(r24, r2, Address(r20, 64)); // ldnp x24, x2, [x20, #64] + __ stnpw(r17, r23, Address(r10, -112)); // stnp w17, w23, [x10, #-112] + __ ldnpw(r26, r6, Address(r30, -160)); // ldnp w26, w6, [x30, #-160] + __ stnp(r30, r8, Address(r20, 64)); // stnp x30, x8, [x20, #64] + __ ldnp(r22, r29, Address(r9, 48)); // ldnp x22, x29, [x9, #48] // LdStNEONOp - __ ld1(v31, __ T8B, Address(r25)); // ld1 {v31.8B}, [x25] - __ ld1(v5, v6, __ T16B, Address(__ post(r15, 32))); // ld1 {v5.16B, v6.16B}, [x15], 32 - __ ld1(v10, v11, v12, __ T1D, Address(__ post(r7, r13))); // ld1 {v10.1D, v11.1D, v12.1D}, [x7], x13 - __ ld1(v13, v14, v15, v16, __ T8H, Address(__ post(r16, 64))); // ld1 {v13.8H, v14.8H, v15.8H, v16.8H}, [x16], 64 - __ ld1r(v7, __ T8B, Address(r17)); // ld1r {v7.8B}, [x17] - __ ld1r(v16, __ T4S, Address(__ post(r25, 4))); // ld1r {v16.4S}, [x25], 4 - __ ld1r(v11, __ T1D, Address(__ post(r3, r7))); // ld1r {v11.1D}, [x3], x7 - __ ld2(v13, v14, __ T2D, Address(r7)); // ld2 {v13.2D, v14.2D}, [x7] - __ ld2(v9, v10, __ T4H, Address(__ post(r27, 16))); // ld2 {v9.4H, v10.4H}, [x27], 16 - __ ld2r(v6, v7, __ T16B, Address(r26)); // ld2r {v6.16B, v7.16B}, [x26] - __ ld2r(v23, v24, __ T2S, Address(__ post(r16, 8))); // ld2r {v23.2S, v24.2S}, [x16], 8 - __ ld2r(v6, v7, __ T2D, Address(__ post(r13, r8))); // ld2r {v6.2D, v7.2D}, [x13], x8 - __ ld3(v20, v21, v22, __ T4S, Address(__ post(r1, r26))); // ld3 {v20.4S, v21.4S, v22.4S}, [x1], x26 - __ ld3(v15, v16, v17, __ T2S, Address(r15)); // ld3 {v15.2S, v16.2S, v17.2S}, [x15] - __ ld3r(v29, v30, v31, __ T8H, Address(r22)); // ld3r {v29.8H, v30.8H, v31.8H}, [x22] - __ ld3r(v6, v7, v8, __ T4S, Address(__ post(r10, 12))); // ld3r {v6.4S, v7.4S, v8.4S}, [x10], 12 - __ ld3r(v15, v16, v17, __ T1D, Address(__ post(r6, r15))); // ld3r {v15.1D, v16.1D, v17.1D}, [x6], x15 - __ ld4(v6, v7, v8, v9, __ T8H, Address(__ post(r10, 64))); // ld4 {v6.8H, v7.8H, v8.8H, v9.8H}, [x10], 64 - __ ld4(v11, v12, v13, v14, __ T8B, Address(__ post(r3, r7))); // ld4 {v11.8B, v12.8B, v13.8B, v14.8B}, [x3], x7 - __ ld4r(v12, v13, v14, v15, __ T8B, Address(r25)); // ld4r {v12.8B, v13.8B, v14.8B, v15.8B}, [x25] - __ ld4r(v11, v12, v13, v14, __ T4H, Address(__ post(r15, 8))); // ld4r {v11.4H, v12.4H, v13.4H, v14.4H}, [x15], 8 - __ ld4r(v30, v31, v0, v1, __ T2S, Address(__ post(r6, r28))); // ld4r {v30.2S, v31.2S, v0.2S, v1.2S}, [x6], x28 + __ ld1(v13, __ T8B, Address(r1)); // ld1 {v13.8B}, [x1] + __ ld1(v1, v2, __ T16B, Address(__ post(r16, 32))); // ld1 {v1.16B, v2.16B}, [x16], 32 + __ ld1(v22, v23, v24, __ T1D, Address(__ post(r25, r19))); // ld1 {v22.1D, v23.1D, v24.1D}, [x25], x19 + __ ld1(v25, v26, v27, v28, __ T8H, Address(__ post(r26, 64))); // ld1 {v25.8H, v26.8H, v27.8H, v28.8H}, [x26], 64 + __ ld1r(v9, __ T8B, Address(r15)); // ld1r {v9.8B}, [x15] + __ ld1r(v12, __ T4S, Address(__ post(r25, 4))); // ld1r {v12.4S}, [x25], 4 + __ ld1r(v4, __ T1D, Address(__ post(r14, r29))); // ld1r {v4.1D}, [x14], x29 + __ ld2(v17, v18, __ T2D, Address(r17)); // ld2 {v17.2D, v18.2D}, [x17] + __ ld2(v23, v24, __ T4H, Address(__ post(r27, 16))); // ld2 {v23.4H, v24.4H}, [x27], 16 + __ ld2r(v2, v3, __ T16B, Address(r24)); // ld2r {v2.16B, v3.16B}, [x24] + __ ld2r(v11, v12, __ T2S, Address(__ post(r0, 8))); // ld2r {v11.2S, v12.2S}, [x0], 8 + __ ld2r(v2, v3, __ T2D, Address(__ post(r12, r22))); // ld2r {v2.2D, v3.2D}, [x12], x22 + __ ld3(v21, v22, v23, __ T4S, Address(__ post(r13, r13))); // ld3 {v21.4S, v22.4S, v23.4S}, [x13], x13 + __ ld3(v12, v13, v14, __ T2S, Address(r11)); // ld3 {v12.2S, v13.2S, v14.2S}, [x11] + __ ld3r(v18, v19, v20, __ T8H, Address(r14)); // ld3r {v18.8H, v19.8H, v20.8H}, [x14] + __ ld3r(v25, v26, v27, __ T4S, Address(__ post(r21, 12))); // ld3r {v25.4S, v26.4S, v27.4S}, [x21], 12 + __ ld3r(v20, v21, v22, __ T1D, Address(__ post(r16, r27))); // ld3r {v20.1D, v21.1D, v22.1D}, [x16], x27 + __ ld4(v0, v1, v2, v3, __ T8H, Address(__ post(r1, 64))); // ld4 {v0.8H, v1.8H, v2.8H, v3.8H}, [x1], 64 + __ ld4(v0, v1, v2, v3, __ T8B, Address(__ post(r27, r29))); // ld4 {v0.8B, v1.8B, v2.8B, v3.8B}, [x27], x29 + __ ld4r(v18, v19, v20, v21, __ T8B, Address(r17)); // ld4r {v18.8B, v19.8B, v20.8B, v21.8B}, [x17] + __ ld4r(v5, v6, v7, v8, __ T4H, Address(__ post(r24, 8))); // ld4r {v5.4H, v6.4H, v7.4H, v8.4H}, [x24], 8 + __ ld4r(v28, v29, v30, v31, __ T2S, Address(__ post(r5, r20))); // ld4r {v28.2S, v29.2S, v30.2S, v31.2S}, [x5], x20 // NEONReduceInstruction - __ addv(v27, __ T8B, v28); // addv b27, v28.8B - __ addv(v28, __ T16B, v29); // addv b28, v29.16B - __ addv(v1, __ T4H, v2); // addv h1, v2.4H - __ addv(v28, __ T8H, v29); // addv h28, v29.8H - __ addv(v1, __ T4S, v2); // addv s1, v2.4S - __ smaxv(v20, __ T8B, v21); // smaxv b20, v21.8B + __ addv(v1, __ T8B, v2); // addv b1, v2.8B + __ addv(v20, __ T16B, v21); // addv b20, v21.16B + __ addv(v29, __ T4H, v30); // addv h29, v30.4H + __ addv(v16, __ T8H, v17); // addv h16, v17.8H + __ addv(v13, __ T4S, v14); // addv s13, v14.4S + __ smaxv(v10, __ T8B, v11); // smaxv b10, v11.8B __ smaxv(v29, __ T16B, v30); // smaxv b29, v30.16B - __ smaxv(v16, __ T4H, v17); // smaxv h16, v17.4H - __ smaxv(v13, __ T8H, v14); // smaxv h13, v14.8H - __ smaxv(v10, __ T4S, v11); // smaxv s10, v11.4S - __ fmaxv(v29, __ T4S, v30); // fmaxv s29, v30.4S - __ sminv(v29, __ T8B, v30); // sminv b29, v30.8B - __ uminv(v19, __ T8B, v20); // uminv b19, v20.8B - __ sminv(v22, __ T16B, v23); // sminv b22, v23.16B - __ uminv(v10, __ T16B, v11); // uminv b10, v11.16B - __ sminv(v4, __ T4H, v5); // sminv h4, v5.4H - __ uminv(v31, __ T4H, v0); // uminv h31, v0.4H - __ sminv(v21, __ T8H, v22); // sminv h21, v22.8H - __ uminv(v8, __ T8H, v9); // uminv h8, v9.8H - __ sminv(v31, __ T4S, v0); // sminv s31, v0.4S - __ uminv(v19, __ T4S, v20); // uminv s19, v20.4S - __ fminv(v10, __ T4S, v11); // fminv s10, v11.4S - __ fmaxp(v28, v29, __ S); // fmaxp s28, v29.2S - __ fmaxp(v2, v3, __ D); // fmaxp d2, v3.2D - __ fminp(v25, v26, __ S); // fminp s25, v26.2S - __ fminp(v5, v6, __ D); // fminp d5, v6.2D + __ smaxv(v29, __ T4H, v30); // smaxv h29, v30.4H + __ smaxv(v19, __ T8H, v20); // smaxv h19, v20.8H + __ smaxv(v22, __ T4S, v23); // smaxv s22, v23.4S + __ fmaxv(v10, __ T4S, v11); // fmaxv s10, v11.4S + __ sminv(v4, __ T8B, v5); // sminv b4, v5.8B + __ uminv(v31, __ T8B, v0); // uminv b31, v0.8B + __ sminv(v21, __ T16B, v22); // sminv b21, v22.16B + __ uminv(v8, __ T16B, v9); // uminv b8, v9.16B + __ sminv(v31, __ T4H, v0); // sminv h31, v0.4H + __ uminv(v19, __ T4H, v20); // uminv h19, v20.4H + __ sminv(v10, __ T8H, v11); // sminv h10, v11.8H + __ uminv(v28, __ T8H, v29); // uminv h28, v29.8H + __ sminv(v2, __ T4S, v3); // sminv s2, v3.4S + __ uminv(v25, __ T4S, v26); // uminv s25, v26.4S + __ fminv(v5, __ T4S, v6); // fminv s5, v6.4S + __ fmaxp(v3, v4, __ S); // fmaxp s3, v4.2S + __ fmaxp(v8, v9, __ D); // fmaxp d8, v9.2D + __ fminp(v22, v23, __ S); // fminp s22, v23.2S + __ fminp(v19, v20, __ D); // fminp d19, v20.2D // NEONFloatCompareWithZero - __ fcm(Assembler::GT, v3, __ T2S, v4); // fcmgt v3.2S, v4.2S, #0.0 - __ fcm(Assembler::GT, v8, __ T4S, v9); // fcmgt v8.4S, v9.4S, #0.0 - __ fcm(Assembler::GT, v22, __ T2D, v23); // fcmgt v22.2D, v23.2D, #0.0 - __ fcm(Assembler::GE, v19, __ T2S, v20); // fcmge v19.2S, v20.2S, #0.0 - __ fcm(Assembler::GE, v13, __ T4S, v14); // fcmge v13.4S, v14.4S, #0.0 - __ fcm(Assembler::GE, v5, __ T2D, v6); // fcmge v5.2D, v6.2D, #0.0 - __ fcm(Assembler::EQ, v29, __ T2S, v30); // fcmeq v29.2S, v30.2S, #0.0 - __ fcm(Assembler::EQ, v24, __ T4S, v25); // fcmeq v24.4S, v25.4S, #0.0 - __ fcm(Assembler::EQ, v21, __ T2D, v22); // fcmeq v21.2D, v22.2D, #0.0 + __ fcm(Assembler::GT, v13, __ T2S, v14); // fcmgt v13.2S, v14.2S, #0.0 + __ fcm(Assembler::GT, v5, __ T4S, v6); // fcmgt v5.4S, v6.4S, #0.0 + __ fcm(Assembler::GT, v29, __ T2D, v30); // fcmgt v29.2D, v30.2D, #0.0 + __ fcm(Assembler::GE, v24, __ T2S, v25); // fcmge v24.2S, v25.2S, #0.0 + __ fcm(Assembler::GE, v21, __ T4S, v22); // fcmge v21.4S, v22.4S, #0.0 + __ fcm(Assembler::GE, v26, __ T2D, v27); // fcmge v26.2D, v27.2D, #0.0 + __ fcm(Assembler::EQ, v24, __ T2S, v25); // fcmeq v24.2S, v25.2S, #0.0 + __ fcm(Assembler::EQ, v3, __ T4S, v4); // fcmeq v3.4S, v4.4S, #0.0 + __ fcm(Assembler::EQ, v24, __ T2D, v25); // fcmeq v24.2D, v25.2D, #0.0 __ fcm(Assembler::LT, v26, __ T2S, v27); // fcmlt v26.2S, v27.2S, #0.0 - __ fcm(Assembler::LT, v24, __ T4S, v25); // fcmlt v24.4S, v25.4S, #0.0 - __ fcm(Assembler::LT, v3, __ T2D, v4); // fcmlt v3.2D, v4.2D, #0.0 - __ fcm(Assembler::LE, v24, __ T2S, v25); // fcmle v24.2S, v25.2S, #0.0 - __ fcm(Assembler::LE, v26, __ T4S, v27); // fcmle v26.4S, v27.4S, #0.0 - __ fcm(Assembler::LE, v23, __ T2D, v24); // fcmle v23.2D, v24.2D, #0.0 + __ fcm(Assembler::LT, v23, __ T4S, v24); // fcmlt v23.4S, v24.4S, #0.0 + __ fcm(Assembler::LT, v15, __ T2D, v16); // fcmlt v15.2D, v16.2D, #0.0 + __ fcm(Assembler::LE, v21, __ T2S, v22); // fcmle v21.2S, v22.2S, #0.0 + __ fcm(Assembler::LE, v3, __ T4S, v4); // fcmle v3.4S, v4.4S, #0.0 + __ fcm(Assembler::LE, v24, __ T2D, v25); // fcmle v24.2D, v25.2D, #0.0 // TwoRegNEONOp - __ absr(v15, __ T8B, v16); // abs v15.8B, v16.8B - __ absr(v21, __ T16B, v22); // abs v21.16B, v22.16B - __ absr(v3, __ T4H, v4); // abs v3.4H, v4.4H - __ absr(v24, __ T8H, v25); // abs v24.8H, v25.8H - __ absr(v8, __ T2S, v9); // abs v8.2S, v9.2S - __ absr(v25, __ T4S, v26); // abs v25.4S, v26.4S - __ absr(v20, __ T2D, v21); // abs v20.2D, v21.2D - __ fabs(v16, __ T2S, v17); // fabs v16.2S, v17.2S - __ fabs(v17, __ T4S, v18); // fabs v17.4S, v18.4S - __ fabs(v2, __ T2D, v3); // fabs v2.2D, v3.2D - __ fabs(v1, __ T4H, v2); // fabs v1.4H, v2.4H - __ fabs(v0, __ T8H, v1); // fabs v0.8H, v1.8H - __ fneg(v24, __ T2S, v25); // fneg v24.2S, v25.2S - __ fneg(v4, __ T4S, v5); // fneg v4.4S, v5.4S - __ fneg(v3, __ T2D, v4); // fneg v3.2D, v4.2D - __ fneg(v12, __ T4H, v13); // fneg v12.4H, v13.4H - __ fneg(v31, __ T8H, v0); // fneg v31.8H, v0.8H - __ fsqrt(v28, __ T2S, v29); // fsqrt v28.2S, v29.2S - __ fsqrt(v10, __ T4S, v11); // fsqrt v10.4S, v11.4S - __ fsqrt(v26, __ T2D, v27); // fsqrt v26.2D, v27.2D - __ fsqrt(v2, __ T4H, v3); // fsqrt v2.4H, v3.4H - __ fsqrt(v12, __ T8H, v13); // fsqrt v12.8H, v13.8H - __ notr(v18, __ T8B, v19); // not v18.8B, v19.8B - __ notr(v31, __ T16B, v0); // not v31.16B, v0.16B + __ absr(v8, __ T8B, v9); // abs v8.8B, v9.8B + __ absr(v25, __ T16B, v26); // abs v25.16B, v26.16B + __ absr(v20, __ T4H, v21); // abs v20.4H, v21.4H + __ absr(v16, __ T8H, v17); // abs v16.8H, v17.8H + __ absr(v17, __ T2S, v18); // abs v17.2S, v18.2S + __ absr(v2, __ T4S, v3); // abs v2.4S, v3.4S + __ absr(v1, __ T2D, v2); // abs v1.2D, v2.2D + __ fabs(v0, __ T2S, v1); // fabs v0.2S, v1.2S + __ fabs(v24, __ T4S, v25); // fabs v24.4S, v25.4S + __ fabs(v4, __ T2D, v5); // fabs v4.2D, v5.2D + __ fabs(v3, __ T4H, v4); // fabs v3.4H, v4.4H + __ fabs(v12, __ T8H, v13); // fabs v12.8H, v13.8H + __ fneg(v31, __ T2S, v0); // fneg v31.2S, v0.2S + __ fneg(v28, __ T4S, v29); // fneg v28.4S, v29.4S + __ fneg(v10, __ T2D, v11); // fneg v10.2D, v11.2D + __ fneg(v26, __ T4H, v27); // fneg v26.4H, v27.4H + __ fneg(v2, __ T8H, v3); // fneg v2.8H, v3.8H + __ fsqrt(v12, __ T2S, v13); // fsqrt v12.2S, v13.2S + __ fsqrt(v18, __ T4S, v19); // fsqrt v18.4S, v19.4S + __ fsqrt(v31, __ T2D, v0); // fsqrt v31.2D, v0.2D + __ fsqrt(v1, __ T4H, v2); // fsqrt v1.4H, v2.4H + __ fsqrt(v13, __ T8H, v14); // fsqrt v13.8H, v14.8H + __ notr(v29, __ T8B, v30); // not v29.8B, v30.8B + __ notr(v0, __ T16B, v1); // not v0.16B, v1.16B // ThreeRegNEONOp - __ andr(v1, __ T8B, v2, v3); // and v1.8B, v2.8B, v3.8B - __ andr(v13, __ T16B, v14, v15); // and v13.16B, v14.16B, v15.16B - __ orr(v29, __ T8B, v30, v31); // orr v29.8B, v30.8B, v31.8B - __ orr(v0, __ T16B, v1, v2); // orr v0.16B, v1.16B, v2.16B - __ eor(v19, __ T8B, v20, v21); // eor v19.8B, v20.8B, v21.8B - __ eor(v12, __ T16B, v13, v14); // eor v12.16B, v13.16B, v14.16B - __ addv(v17, __ T8B, v18, v19); // add v17.8B, v18.8B, v19.8B - __ addv(v22, __ T16B, v23, v24); // add v22.16B, v23.16B, v24.16B - __ addv(v13, __ T4H, v14, v15); // add v13.4H, v14.4H, v15.4H - __ addv(v28, __ T8H, v29, v30); // add v28.8H, v29.8H, v30.8H - __ addv(v30, __ T2S, v31, v0); // add v30.2S, v31.2S, v0.2S - __ addv(v31, __ T4S, v0, v1); // add v31.4S, v0.4S, v1.4S - __ addv(v1, __ T2D, v2, v3); // add v1.2D, v2.2D, v3.2D - __ sqaddv(v26, __ T8B, v27, v28); // sqadd v26.8B, v27.8B, v28.8B - __ sqaddv(v28, __ T16B, v29, v30); // sqadd v28.16B, v29.16B, v30.16B - __ sqaddv(v4, __ T4H, v5, v6); // sqadd v4.4H, v5.4H, v6.4H - __ sqaddv(v30, __ T8H, v31, v0); // sqadd v30.8H, v31.8H, v0.8H - __ sqaddv(v4, __ T2S, v5, v6); // sqadd v4.2S, v5.2S, v6.2S - __ sqaddv(v6, __ T4S, v7, v8); // sqadd v6.4S, v7.4S, v8.4S - __ sqaddv(v30, __ T2D, v31, v0); // sqadd v30.2D, v31.2D, v0.2D - __ uqaddv(v26, __ T8B, v27, v28); // uqadd v26.8B, v27.8B, v28.8B - __ uqaddv(v18, __ T16B, v19, v20); // uqadd v18.16B, v19.16B, v20.16B - __ uqaddv(v9, __ T4H, v10, v11); // uqadd v9.4H, v10.4H, v11.4H - __ uqaddv(v8, __ T8H, v9, v10); // uqadd v8.8H, v9.8H, v10.8H - __ uqaddv(v12, __ T2S, v13, v14); // uqadd v12.2S, v13.2S, v14.2S - __ uqaddv(v0, __ T4S, v1, v2); // uqadd v0.4S, v1.4S, v2.4S - __ uqaddv(v20, __ T2D, v21, v22); // uqadd v20.2D, v21.2D, v22.2D - __ fadd(v1, __ T2S, v2, v3); // fadd v1.2S, v2.2S, v3.2S + __ andr(v19, __ T8B, v20, v21); // and v19.8B, v20.8B, v21.8B + __ andr(v12, __ T16B, v13, v14); // and v12.16B, v13.16B, v14.16B + __ orr(v17, __ T8B, v18, v19); // orr v17.8B, v18.8B, v19.8B + __ orr(v22, __ T16B, v23, v24); // orr v22.16B, v23.16B, v24.16B + __ eor(v13, __ T8B, v14, v15); // eor v13.8B, v14.8B, v15.8B + __ eor(v28, __ T16B, v29, v30); // eor v28.16B, v29.16B, v30.16B + __ addv(v30, __ T8B, v31, v0); // add v30.8B, v31.8B, v0.8B + __ addv(v31, __ T16B, v0, v1); // add v31.16B, v0.16B, v1.16B + __ addv(v1, __ T4H, v2, v3); // add v1.4H, v2.4H, v3.4H + __ addv(v26, __ T8H, v27, v28); // add v26.8H, v27.8H, v28.8H + __ addv(v28, __ T2S, v29, v30); // add v28.2S, v29.2S, v30.2S + __ addv(v4, __ T4S, v5, v6); // add v4.4S, v5.4S, v6.4S + __ addv(v30, __ T2D, v31, v0); // add v30.2D, v31.2D, v0.2D + __ sqaddv(v4, __ T8B, v5, v6); // sqadd v4.8B, v5.8B, v6.8B + __ sqaddv(v6, __ T16B, v7, v8); // sqadd v6.16B, v7.16B, v8.16B + __ sqaddv(v30, __ T4H, v31, v0); // sqadd v30.4H, v31.4H, v0.4H + __ sqaddv(v26, __ T8H, v27, v28); // sqadd v26.8H, v27.8H, v28.8H + __ sqaddv(v18, __ T2S, v19, v20); // sqadd v18.2S, v19.2S, v20.2S + __ sqaddv(v9, __ T4S, v10, v11); // sqadd v9.4S, v10.4S, v11.4S + __ sqaddv(v8, __ T2D, v9, v10); // sqadd v8.2D, v9.2D, v10.2D + __ uqaddv(v12, __ T8B, v13, v14); // uqadd v12.8B, v13.8B, v14.8B + __ uqaddv(v0, __ T16B, v1, v2); // uqadd v0.16B, v1.16B, v2.16B + __ uqaddv(v20, __ T4H, v21, v22); // uqadd v20.4H, v21.4H, v22.4H + __ uqaddv(v1, __ T8H, v2, v3); // uqadd v1.8H, v2.8H, v3.8H + __ uqaddv(v24, __ T2S, v25, v26); // uqadd v24.2S, v25.2S, v26.2S + __ uqaddv(v2, __ T4S, v3, v4); // uqadd v2.4S, v3.4S, v4.4S + __ uqaddv(v0, __ T2D, v1, v2); // uqadd v0.2D, v1.2D, v2.2D + __ fadd(v9, __ T2S, v10, v11); // fadd v9.2S, v10.2S, v11.2S __ fadd(v24, __ T4S, v25, v26); // fadd v24.4S, v25.4S, v26.4S - __ fadd(v2, __ T2D, v3, v4); // fadd v2.2D, v3.2D, v4.2D - __ fadd(v0, __ T4H, v1, v2); // fadd v0.4H, v1.4H, v2.4H - __ fadd(v9, __ T8H, v10, v11); // fadd v9.8H, v10.8H, v11.8H - __ subv(v24, __ T8B, v25, v26); // sub v24.8B, v25.8B, v26.8B - __ subv(v26, __ T16B, v27, v28); // sub v26.16B, v27.16B, v28.16B - __ subv(v16, __ T4H, v17, v18); // sub v16.4H, v17.4H, v18.4H - __ subv(v30, __ T8H, v31, v0); // sub v30.8H, v31.8H, v0.8H - __ subv(v3, __ T2S, v4, v5); // sub v3.2S, v4.2S, v5.2S - __ subv(v10, __ T4S, v11, v12); // sub v10.4S, v11.4S, v12.4S - __ subv(v23, __ T2D, v24, v25); // sub v23.2D, v24.2D, v25.2D - __ sqsubv(v10, __ T8B, v11, v12); // sqsub v10.8B, v11.8B, v12.8B - __ sqsubv(v4, __ T16B, v5, v6); // sqsub v4.16B, v5.16B, v6.16B - __ sqsubv(v18, __ T4H, v19, v20); // sqsub v18.4H, v19.4H, v20.4H - __ sqsubv(v2, __ T8H, v3, v4); // sqsub v2.8H, v3.8H, v4.8H - __ sqsubv(v11, __ T2S, v12, v13); // sqsub v11.2S, v12.2S, v13.2S - __ sqsubv(v8, __ T4S, v9, v10); // sqsub v8.4S, v9.4S, v10.4S + __ fadd(v26, __ T2D, v27, v28); // fadd v26.2D, v27.2D, v28.2D + __ fadd(v16, __ T4H, v17, v18); // fadd v16.4H, v17.4H, v18.4H + __ fadd(v30, __ T8H, v31, v0); // fadd v30.8H, v31.8H, v0.8H + __ subv(v3, __ T8B, v4, v5); // sub v3.8B, v4.8B, v5.8B + __ subv(v10, __ T16B, v11, v12); // sub v10.16B, v11.16B, v12.16B + __ subv(v23, __ T4H, v24, v25); // sub v23.4H, v24.4H, v25.4H + __ subv(v10, __ T8H, v11, v12); // sub v10.8H, v11.8H, v12.8H + __ subv(v4, __ T2S, v5, v6); // sub v4.2S, v5.2S, v6.2S + __ subv(v18, __ T4S, v19, v20); // sub v18.4S, v19.4S, v20.4S + __ subv(v2, __ T2D, v3, v4); // sub v2.2D, v3.2D, v4.2D + __ sqsubv(v11, __ T8B, v12, v13); // sqsub v11.8B, v12.8B, v13.8B + __ sqsubv(v8, __ T16B, v9, v10); // sqsub v8.16B, v9.16B, v10.16B + __ sqsubv(v10, __ T4H, v11, v12); // sqsub v10.4H, v11.4H, v12.4H + __ sqsubv(v15, __ T8H, v16, v17); // sqsub v15.8H, v16.8H, v17.8H + __ sqsubv(v17, __ T2S, v18, v19); // sqsub v17.2S, v18.2S, v19.2S + __ sqsubv(v2, __ T4S, v3, v4); // sqsub v2.4S, v3.4S, v4.4S __ sqsubv(v10, __ T2D, v11, v12); // sqsub v10.2D, v11.2D, v12.2D - __ uqsubv(v15, __ T8B, v16, v17); // uqsub v15.8B, v16.8B, v17.8B - __ uqsubv(v17, __ T16B, v18, v19); // uqsub v17.16B, v18.16B, v19.16B - __ uqsubv(v2, __ T4H, v3, v4); // uqsub v2.4H, v3.4H, v4.4H - __ uqsubv(v10, __ T8H, v11, v12); // uqsub v10.8H, v11.8H, v12.8H - __ uqsubv(v12, __ T2S, v13, v14); // uqsub v12.2S, v13.2S, v14.2S - __ uqsubv(v12, __ T4S, v13, v14); // uqsub v12.4S, v13.4S, v14.4S - __ uqsubv(v15, __ T2D, v16, v17); // uqsub v15.2D, v16.2D, v17.2D - __ fsub(v13, __ T2S, v14, v15); // fsub v13.2S, v14.2S, v15.2S - __ fsub(v2, __ T4S, v3, v4); // fsub v2.4S, v3.4S, v4.4S - __ fsub(v7, __ T2D, v8, v9); // fsub v7.2D, v8.2D, v9.2D - __ fsub(v20, __ T4H, v21, v22); // fsub v20.4H, v21.4H, v22.4H - __ fsub(v26, __ T8H, v27, v28); // fsub v26.8H, v27.8H, v28.8H - __ mulv(v16, __ T8B, v17, v18); // mul v16.8B, v17.8B, v18.8B - __ mulv(v4, __ T16B, v5, v6); // mul v4.16B, v5.16B, v6.16B - __ mulv(v2, __ T4H, v3, v4); // mul v2.4H, v3.4H, v4.4H - __ mulv(v4, __ T8H, v5, v6); // mul v4.8H, v5.8H, v6.8H - __ mulv(v12, __ T2S, v13, v14); // mul v12.2S, v13.2S, v14.2S - __ mulv(v18, __ T4S, v19, v20); // mul v18.4S, v19.4S, v20.4S + __ uqsubv(v12, __ T8B, v13, v14); // uqsub v12.8B, v13.8B, v14.8B + __ uqsubv(v12, __ T16B, v13, v14); // uqsub v12.16B, v13.16B, v14.16B + __ uqsubv(v15, __ T4H, v16, v17); // uqsub v15.4H, v16.4H, v17.4H + __ uqsubv(v13, __ T8H, v14, v15); // uqsub v13.8H, v14.8H, v15.8H + __ uqsubv(v2, __ T2S, v3, v4); // uqsub v2.2S, v3.2S, v4.2S + __ uqsubv(v7, __ T4S, v8, v9); // uqsub v7.4S, v8.4S, v9.4S + __ uqsubv(v20, __ T2D, v21, v22); // uqsub v20.2D, v21.2D, v22.2D + __ fsub(v26, __ T2S, v27, v28); // fsub v26.2S, v27.2S, v28.2S + __ fsub(v16, __ T4S, v17, v18); // fsub v16.4S, v17.4S, v18.4S + __ fsub(v4, __ T2D, v5, v6); // fsub v4.2D, v5.2D, v6.2D + __ fsub(v2, __ T4H, v3, v4); // fsub v2.4H, v3.4H, v4.4H + __ fsub(v4, __ T8H, v5, v6); // fsub v4.8H, v5.8H, v6.8H + __ mulv(v12, __ T8B, v13, v14); // mul v12.8B, v13.8B, v14.8B + __ mulv(v18, __ T16B, v19, v20); // mul v18.16B, v19.16B, v20.16B + __ mulv(v21, __ T4H, v22, v23); // mul v21.4H, v22.4H, v23.4H + __ mulv(v16, __ T8H, v17, v18); // mul v16.8H, v17.8H, v18.8H + __ mulv(v18, __ T2S, v19, v20); // mul v18.2S, v19.2S, v20.2S + __ mulv(v11, __ T4S, v12, v13); // mul v11.4S, v12.4S, v13.4S __ fabd(v21, __ T2S, v22, v23); // fabd v21.2S, v22.2S, v23.2S - __ fabd(v16, __ T4S, v17, v18); // fabd v16.4S, v17.4S, v18.4S - __ fabd(v18, __ T2D, v19, v20); // fabd v18.2D, v19.2D, v20.2D - __ fabd(v11, __ T4H, v12, v13); // fabd v11.4H, v12.4H, v13.4H - __ fabd(v21, __ T8H, v22, v23); // fabd v21.8H, v22.8H, v23.8H - __ faddp(v23, __ T2S, v24, v25); // faddp v23.2S, v24.2S, v25.2S - __ faddp(v12, __ T4S, v13, v14); // faddp v12.4S, v13.4S, v14.4S - __ faddp(v26, __ T2D, v27, v28); // faddp v26.2D, v27.2D, v28.2D - __ faddp(v23, __ T4H, v24, v25); // faddp v23.4H, v24.4H, v25.4H - __ faddp(v28, __ T8H, v29, v30); // faddp v28.8H, v29.8H, v30.8H - __ fmul(v14, __ T2S, v15, v16); // fmul v14.2S, v15.2S, v16.2S - __ fmul(v11, __ T4S, v12, v13); // fmul v11.4S, v12.4S, v13.4S - __ fmul(v24, __ T2D, v25, v26); // fmul v24.2D, v25.2D, v26.2D - __ fmul(v1, __ T4H, v2, v3); // fmul v1.4H, v2.4H, v3.4H - __ fmul(v12, __ T8H, v13, v14); // fmul v12.8H, v13.8H, v14.8H - __ mlav(v31, __ T4H, v0, v1); // mla v31.4H, v0.4H, v1.4H - __ mlav(v10, __ T8H, v11, v12); // mla v10.8H, v11.8H, v12.8H - __ mlav(v16, __ T2S, v17, v18); // mla v16.2S, v17.2S, v18.2S - __ mlav(v7, __ T4S, v8, v9); // mla v7.4S, v8.4S, v9.4S - __ fmla(v2, __ T2S, v3, v4); // fmla v2.2S, v3.2S, v4.2S - __ fmla(v3, __ T4S, v4, v5); // fmla v3.4S, v4.4S, v5.4S - __ fmla(v13, __ T2D, v14, v15); // fmla v13.2D, v14.2D, v15.2D - __ fmla(v19, __ T4H, v20, v21); // fmla v19.4H, v20.4H, v21.4H - __ fmla(v17, __ T8H, v18, v19); // fmla v17.8H, v18.8H, v19.8H - __ mlsv(v16, __ T4H, v17, v18); // mls v16.4H, v17.4H, v18.4H - __ mlsv(v3, __ T8H, v4, v5); // mls v3.8H, v4.8H, v5.8H - __ mlsv(v1, __ T2S, v2, v3); // mls v1.2S, v2.2S, v3.2S - __ mlsv(v11, __ T4S, v12, v13); // mls v11.4S, v12.4S, v13.4S - __ fmls(v30, __ T2S, v31, v0); // fmls v30.2S, v31.2S, v0.2S - __ fmls(v5, __ T4S, v6, v7); // fmls v5.4S, v6.4S, v7.4S - __ fmls(v8, __ T2D, v9, v10); // fmls v8.2D, v9.2D, v10.2D - __ fmls(v15, __ T4H, v16, v17); // fmls v15.4H, v16.4H, v17.4H - __ fmls(v29, __ T8H, v30, v31); // fmls v29.8H, v30.8H, v31.8H - __ fdiv(v30, __ T2S, v31, v0); // fdiv v30.2S, v31.2S, v0.2S - __ fdiv(v0, __ T4S, v1, v2); // fdiv v0.4S, v1.4S, v2.4S - __ fdiv(v20, __ T2D, v21, v22); // fdiv v20.2D, v21.2D, v22.2D - __ fdiv(v7, __ T4H, v8, v9); // fdiv v7.4H, v8.4H, v9.4H - __ fdiv(v20, __ T8H, v21, v22); // fdiv v20.8H, v21.8H, v22.8H - __ maxv(v23, __ T8B, v24, v25); // smax v23.8B, v24.8B, v25.8B - __ maxv(v28, __ T16B, v29, v30); // smax v28.16B, v29.16B, v30.16B - __ maxv(v21, __ T4H, v22, v23); // smax v21.4H, v22.4H, v23.4H - __ maxv(v27, __ T8H, v28, v29); // smax v27.8H, v28.8H, v29.8H - __ maxv(v25, __ T2S, v26, v27); // smax v25.2S, v26.2S, v27.2S - __ maxv(v5, __ T4S, v6, v7); // smax v5.4S, v6.4S, v7.4S - __ umaxv(v1, __ T8B, v2, v3); // umax v1.8B, v2.8B, v3.8B - __ umaxv(v23, __ T16B, v24, v25); // umax v23.16B, v24.16B, v25.16B - __ umaxv(v16, __ T4H, v17, v18); // umax v16.4H, v17.4H, v18.4H - __ umaxv(v31, __ T8H, v0, v1); // umax v31.8H, v0.8H, v1.8H - __ umaxv(v5, __ T2S, v6, v7); // umax v5.2S, v6.2S, v7.2S - __ umaxv(v12, __ T4S, v13, v14); // umax v12.4S, v13.4S, v14.4S - __ smaxp(v9, __ T8B, v10, v11); // smaxp v9.8B, v10.8B, v11.8B - __ smaxp(v28, __ T16B, v29, v30); // smaxp v28.16B, v29.16B, v30.16B - __ smaxp(v15, __ T4H, v16, v17); // smaxp v15.4H, v16.4H, v17.4H - __ smaxp(v29, __ T8H, v30, v31); // smaxp v29.8H, v30.8H, v31.8H - __ smaxp(v22, __ T2S, v23, v24); // smaxp v22.2S, v23.2S, v24.2S - __ smaxp(v31, __ T4S, v0, v1); // smaxp v31.4S, v0.4S, v1.4S - __ fmax(v19, __ T2S, v20, v21); // fmax v19.2S, v20.2S, v21.2S + __ fabd(v23, __ T4S, v24, v25); // fabd v23.4S, v24.4S, v25.4S + __ fabd(v12, __ T2D, v13, v14); // fabd v12.2D, v13.2D, v14.2D + __ fabd(v26, __ T4H, v27, v28); // fabd v26.4H, v27.4H, v28.4H + __ fabd(v23, __ T8H, v24, v25); // fabd v23.8H, v24.8H, v25.8H + __ faddp(v28, __ T2S, v29, v30); // faddp v28.2S, v29.2S, v30.2S + __ faddp(v14, __ T4S, v15, v16); // faddp v14.4S, v15.4S, v16.4S + __ faddp(v11, __ T2D, v12, v13); // faddp v11.2D, v12.2D, v13.2D + __ faddp(v24, __ T4H, v25, v26); // faddp v24.4H, v25.4H, v26.4H + __ faddp(v1, __ T8H, v2, v3); // faddp v1.8H, v2.8H, v3.8H + __ fmul(v12, __ T2S, v13, v14); // fmul v12.2S, v13.2S, v14.2S + __ fmul(v31, __ T4S, v0, v1); // fmul v31.4S, v0.4S, v1.4S + __ fmul(v10, __ T2D, v11, v12); // fmul v10.2D, v11.2D, v12.2D + __ fmul(v16, __ T4H, v17, v18); // fmul v16.4H, v17.4H, v18.4H + __ fmul(v7, __ T8H, v8, v9); // fmul v7.8H, v8.8H, v9.8H + __ mlav(v2, __ T4H, v3, v4); // mla v2.4H, v3.4H, v4.4H + __ mlav(v3, __ T8H, v4, v5); // mla v3.8H, v4.8H, v5.8H + __ mlav(v13, __ T2S, v14, v15); // mla v13.2S, v14.2S, v15.2S + __ mlav(v19, __ T4S, v20, v21); // mla v19.4S, v20.4S, v21.4S + __ fmla(v17, __ T2S, v18, v19); // fmla v17.2S, v18.2S, v19.2S + __ fmla(v16, __ T4S, v17, v18); // fmla v16.4S, v17.4S, v18.4S + __ fmla(v3, __ T2D, v4, v5); // fmla v3.2D, v4.2D, v5.2D + __ fmla(v1, __ T4H, v2, v3); // fmla v1.4H, v2.4H, v3.4H + __ fmla(v11, __ T8H, v12, v13); // fmla v11.8H, v12.8H, v13.8H + __ mlsv(v30, __ T4H, v31, v0); // mls v30.4H, v31.4H, v0.4H + __ mlsv(v5, __ T8H, v6, v7); // mls v5.8H, v6.8H, v7.8H + __ mlsv(v8, __ T2S, v9, v10); // mls v8.2S, v9.2S, v10.2S + __ mlsv(v15, __ T4S, v16, v17); // mls v15.4S, v16.4S, v17.4S + __ fmls(v29, __ T2S, v30, v31); // fmls v29.2S, v30.2S, v31.2S + __ fmls(v30, __ T4S, v31, v0); // fmls v30.4S, v31.4S, v0.4S + __ fmls(v0, __ T2D, v1, v2); // fmls v0.2D, v1.2D, v2.2D + __ fmls(v20, __ T4H, v21, v22); // fmls v20.4H, v21.4H, v22.4H + __ fmls(v7, __ T8H, v8, v9); // fmls v7.8H, v8.8H, v9.8H + __ fdiv(v20, __ T2S, v21, v22); // fdiv v20.2S, v21.2S, v22.2S + __ fdiv(v23, __ T4S, v24, v25); // fdiv v23.4S, v24.4S, v25.4S + __ fdiv(v28, __ T2D, v29, v30); // fdiv v28.2D, v29.2D, v30.2D + __ fdiv(v21, __ T4H, v22, v23); // fdiv v21.4H, v22.4H, v23.4H + __ fdiv(v27, __ T8H, v28, v29); // fdiv v27.8H, v28.8H, v29.8H + __ maxv(v25, __ T8B, v26, v27); // smax v25.8B, v26.8B, v27.8B + __ maxv(v5, __ T16B, v6, v7); // smax v5.16B, v6.16B, v7.16B + __ maxv(v1, __ T4H, v2, v3); // smax v1.4H, v2.4H, v3.4H + __ maxv(v23, __ T8H, v24, v25); // smax v23.8H, v24.8H, v25.8H + __ maxv(v16, __ T2S, v17, v18); // smax v16.2S, v17.2S, v18.2S + __ maxv(v31, __ T4S, v0, v1); // smax v31.4S, v0.4S, v1.4S + __ umaxv(v5, __ T8B, v6, v7); // umax v5.8B, v6.8B, v7.8B + __ umaxv(v12, __ T16B, v13, v14); // umax v12.16B, v13.16B, v14.16B + __ umaxv(v9, __ T4H, v10, v11); // umax v9.4H, v10.4H, v11.4H + __ umaxv(v28, __ T8H, v29, v30); // umax v28.8H, v29.8H, v30.8H + __ umaxv(v15, __ T2S, v16, v17); // umax v15.2S, v16.2S, v17.2S + __ umaxv(v29, __ T4S, v30, v31); // umax v29.4S, v30.4S, v31.4S + __ smaxp(v22, __ T8B, v23, v24); // smaxp v22.8B, v23.8B, v24.8B + __ smaxp(v31, __ T16B, v0, v1); // smaxp v31.16B, v0.16B, v1.16B + __ smaxp(v19, __ T4H, v20, v21); // smaxp v19.4H, v20.4H, v21.4H + __ smaxp(v31, __ T8H, v0, v1); // smaxp v31.8H, v0.8H, v1.8H + __ smaxp(v5, __ T2S, v6, v7); // smaxp v5.2S, v6.2S, v7.2S + __ smaxp(v14, __ T4S, v15, v16); // smaxp v14.4S, v15.4S, v16.4S + __ fmax(v18, __ T2S, v19, v20); // fmax v18.2S, v19.2S, v20.2S __ fmax(v31, __ T4S, v0, v1); // fmax v31.4S, v0.4S, v1.4S - __ fmax(v5, __ T2D, v6, v7); // fmax v5.2D, v6.2D, v7.2D - __ fmax(v14, __ T4H, v15, v16); // fmax v14.4H, v15.4H, v16.4H - __ fmax(v18, __ T8H, v19, v20); // fmax v18.8H, v19.8H, v20.8H - __ minv(v31, __ T8B, v0, v1); // smin v31.8B, v0.8B, v1.8B - __ minv(v18, __ T16B, v19, v20); // smin v18.16B, v19.16B, v20.16B - __ minv(v27, __ T4H, v28, v29); // smin v27.4H, v28.4H, v29.4H - __ minv(v20, __ T8H, v21, v22); // smin v20.8H, v21.8H, v22.8H - __ minv(v16, __ T2S, v17, v18); // smin v16.2S, v17.2S, v18.2S - __ minv(v12, __ T4S, v13, v14); // smin v12.4S, v13.4S, v14.4S - __ uminv(v11, __ T8B, v12, v13); // umin v11.8B, v12.8B, v13.8B - __ uminv(v9, __ T16B, v10, v11); // umin v9.16B, v10.16B, v11.16B - __ uminv(v6, __ T4H, v7, v8); // umin v6.4H, v7.4H, v8.4H + __ fmax(v18, __ T2D, v19, v20); // fmax v18.2D, v19.2D, v20.2D + __ fmax(v27, __ T4H, v28, v29); // fmax v27.4H, v28.4H, v29.4H + __ fmax(v20, __ T8H, v21, v22); // fmax v20.8H, v21.8H, v22.8H + __ minv(v16, __ T8B, v17, v18); // smin v16.8B, v17.8B, v18.8B + __ minv(v12, __ T16B, v13, v14); // smin v12.16B, v13.16B, v14.16B + __ minv(v11, __ T4H, v12, v13); // smin v11.4H, v12.4H, v13.4H + __ minv(v9, __ T8H, v10, v11); // smin v9.8H, v10.8H, v11.8H + __ minv(v6, __ T2S, v7, v8); // smin v6.2S, v7.2S, v8.2S + __ minv(v30, __ T4S, v31, v0); // smin v30.4S, v31.4S, v0.4S + __ uminv(v17, __ T8B, v18, v19); // umin v17.8B, v18.8B, v19.8B + __ uminv(v27, __ T16B, v28, v29); // umin v27.16B, v28.16B, v29.16B + __ uminv(v28, __ T4H, v29, v30); // umin v28.4H, v29.4H, v30.4H __ uminv(v30, __ T8H, v31, v0); // umin v30.8H, v31.8H, v0.8H - __ uminv(v17, __ T2S, v18, v19); // umin v17.2S, v18.2S, v19.2S - __ uminv(v27, __ T4S, v28, v29); // umin v27.4S, v28.4S, v29.4S - __ sminp(v28, __ T8B, v29, v30); // sminp v28.8B, v29.8B, v30.8B - __ sminp(v30, __ T16B, v31, v0); // sminp v30.16B, v31.16B, v0.16B - __ sminp(v7, __ T4H, v8, v9); // sminp v7.4H, v8.4H, v9.4H - __ sminp(v10, __ T8H, v11, v12); // sminp v10.8H, v11.8H, v12.8H - __ sminp(v20, __ T2S, v21, v22); // sminp v20.2S, v21.2S, v22.2S - __ sminp(v10, __ T4S, v11, v12); // sminp v10.4S, v11.4S, v12.4S - __ uminp(v4, __ T8B, v5, v6); // uminp v4.8B, v5.8B, v6.8B - __ uminp(v24, __ T16B, v25, v26); // uminp v24.16B, v25.16B, v26.16B - __ uminp(v17, __ T4H, v18, v19); // uminp v17.4H, v18.4H, v19.4H - __ uminp(v17, __ T8H, v18, v19); // uminp v17.8H, v18.8H, v19.8H + __ uminv(v7, __ T2S, v8, v9); // umin v7.2S, v8.2S, v9.2S + __ uminv(v10, __ T4S, v11, v12); // umin v10.4S, v11.4S, v12.4S + __ sminp(v20, __ T8B, v21, v22); // sminp v20.8B, v21.8B, v22.8B + __ sminp(v10, __ T16B, v11, v12); // sminp v10.16B, v11.16B, v12.16B + __ sminp(v4, __ T4H, v5, v6); // sminp v4.4H, v5.4H, v6.4H + __ sminp(v24, __ T8H, v25, v26); // sminp v24.8H, v25.8H, v26.8H + __ sminp(v17, __ T2S, v18, v19); // sminp v17.2S, v18.2S, v19.2S + __ sminp(v17, __ T4S, v18, v19); // sminp v17.4S, v18.4S, v19.4S + __ uminp(v22, __ T8B, v23, v24); // uminp v22.8B, v23.8B, v24.8B + __ uminp(v3, __ T16B, v4, v5); // uminp v3.16B, v4.16B, v5.16B + __ uminp(v29, __ T4H, v30, v31); // uminp v29.4H, v30.4H, v31.4H + __ uminp(v15, __ T8H, v16, v17); // uminp v15.8H, v16.8H, v17.8H __ uminp(v22, __ T2S, v23, v24); // uminp v22.2S, v23.2S, v24.2S - __ uminp(v3, __ T4S, v4, v5); // uminp v3.4S, v4.4S, v5.4S - __ umaxp(v29, __ T8B, v30, v31); // umaxp v29.8B, v30.8B, v31.8B - __ umaxp(v15, __ T16B, v16, v17); // umaxp v15.16B, v16.16B, v17.16B - __ umaxp(v22, __ T4H, v23, v24); // umaxp v22.4H, v23.4H, v24.4H - __ umaxp(v19, __ T8H, v20, v21); // umaxp v19.8H, v20.8H, v21.8H - __ umaxp(v19, __ T2S, v20, v21); // umaxp v19.2S, v20.2S, v21.2S - __ umaxp(v22, __ T4S, v23, v24); // umaxp v22.4S, v23.4S, v24.4S - __ sqdmulh(v2, __ T4H, v3, v4); // sqdmulh v2.4H, v3.4H, v4.4H - __ sqdmulh(v15, __ T8H, v16, v17); // sqdmulh v15.8H, v16.8H, v17.8H - __ sqdmulh(v6, __ T2S, v7, v8); // sqdmulh v6.2S, v7.2S, v8.2S - __ sqdmulh(v12, __ T4S, v13, v14); // sqdmulh v12.4S, v13.4S, v14.4S - __ shsubv(v16, __ T8B, v17, v18); // shsub v16.8B, v17.8B, v18.8B - __ shsubv(v11, __ T16B, v12, v13); // shsub v11.16B, v12.16B, v13.16B - __ shsubv(v13, __ T4H, v14, v15); // shsub v13.4H, v14.4H, v15.4H - __ shsubv(v23, __ T8H, v24, v25); // shsub v23.8H, v24.8H, v25.8H - __ shsubv(v1, __ T2S, v2, v3); // shsub v1.2S, v2.2S, v3.2S - __ shsubv(v30, __ T4S, v31, v0); // shsub v30.4S, v31.4S, v0.4S - __ fmin(v19, __ T2S, v20, v21); // fmin v19.2S, v20.2S, v21.2S - __ fmin(v5, __ T4S, v6, v7); // fmin v5.4S, v6.4S, v7.4S - __ fmin(v17, __ T2D, v18, v19); // fmin v17.2D, v18.2D, v19.2D - __ fmin(v2, __ T4H, v3, v4); // fmin v2.4H, v3.4H, v4.4H - __ fmin(v16, __ T8H, v17, v18); // fmin v16.8H, v17.8H, v18.8H - __ facgt(v22, __ T2S, v23, v24); // facgt v22.2S, v23.2S, v24.2S - __ facgt(v13, __ T4S, v14, v15); // facgt v13.4S, v14.4S, v15.4S - __ facgt(v10, __ T2D, v11, v12); // facgt v10.2D, v11.2D, v12.2D - __ facgt(v21, __ T4H, v22, v23); // facgt v21.4H, v22.4H, v23.4H - __ facgt(v29, __ T8H, v30, v31); // facgt v29.8H, v30.8H, v31.8H + __ uminp(v19, __ T4S, v20, v21); // uminp v19.4S, v20.4S, v21.4S + __ umaxp(v19, __ T8B, v20, v21); // umaxp v19.8B, v20.8B, v21.8B + __ umaxp(v22, __ T16B, v23, v24); // umaxp v22.16B, v23.16B, v24.16B + __ umaxp(v2, __ T4H, v3, v4); // umaxp v2.4H, v3.4H, v4.4H + __ umaxp(v15, __ T8H, v16, v17); // umaxp v15.8H, v16.8H, v17.8H + __ umaxp(v6, __ T2S, v7, v8); // umaxp v6.2S, v7.2S, v8.2S + __ umaxp(v12, __ T4S, v13, v14); // umaxp v12.4S, v13.4S, v14.4S + __ sqdmulh(v16, __ T4H, v17, v18); // sqdmulh v16.4H, v17.4H, v18.4H + __ sqdmulh(v11, __ T8H, v12, v13); // sqdmulh v11.8H, v12.8H, v13.8H + __ sqdmulh(v13, __ T2S, v14, v15); // sqdmulh v13.2S, v14.2S, v15.2S + __ sqdmulh(v23, __ T4S, v24, v25); // sqdmulh v23.4S, v24.4S, v25.4S + __ shsubv(v1, __ T8B, v2, v3); // shsub v1.8B, v2.8B, v3.8B + __ shsubv(v30, __ T16B, v31, v0); // shsub v30.16B, v31.16B, v0.16B + __ shsubv(v19, __ T4H, v20, v21); // shsub v19.4H, v20.4H, v21.4H + __ shsubv(v5, __ T8H, v6, v7); // shsub v5.8H, v6.8H, v7.8H + __ shsubv(v17, __ T2S, v18, v19); // shsub v17.2S, v18.2S, v19.2S + __ shsubv(v2, __ T4S, v3, v4); // shsub v2.4S, v3.4S, v4.4S + __ fmin(v16, __ T2S, v17, v18); // fmin v16.2S, v17.2S, v18.2S + __ fmin(v22, __ T4S, v23, v24); // fmin v22.4S, v23.4S, v24.4S + __ fmin(v13, __ T2D, v14, v15); // fmin v13.2D, v14.2D, v15.2D + __ fmin(v10, __ T4H, v11, v12); // fmin v10.4H, v11.4H, v12.4H + __ fmin(v21, __ T8H, v22, v23); // fmin v21.8H, v22.8H, v23.8H + __ facgt(v29, __ T2S, v30, v31); // facgt v29.2S, v30.2S, v31.2S + __ facgt(v27, __ T4S, v28, v29); // facgt v27.4S, v28.4S, v29.4S + __ facgt(v12, __ T2D, v13, v14); // facgt v12.2D, v13.2D, v14.2D + __ facgt(v27, __ T4H, v28, v29); // facgt v27.4H, v28.4H, v29.4H + __ facgt(v3, __ T8H, v4, v5); // facgt v3.8H, v4.8H, v5.8H // VectorScalarNEONInstruction - __ fmlavs(v6, __ T2S, v7, v8, 1); // fmla v6.2S, v7.2S, v8.S[1] - __ mulvs(v1, __ T4S, v2, v3, 3); // mul v1.4S, v2.4S, v3.S[3] - __ fmlavs(v15, __ T2D, v0, v1, 0); // fmla v15.2D, v0.2D, v1.D[0] - __ fmlsvs(v9, __ T2S, v10, v11, 1); // fmls v9.2S, v10.2S, v11.S[1] - __ mulvs(v4, __ T4S, v5, v6, 2); // mul v4.4S, v5.4S, v6.S[2] - __ fmlsvs(v13, __ T2D, v14, v15, 1); // fmls v13.2D, v14.2D, v15.D[1] - __ fmulxvs(v3, __ T2S, v4, v5, 0); // fmulx v3.2S, v4.2S, v5.S[0] - __ mulvs(v11, __ T4S, v12, v13, 2); // mul v11.4S, v12.4S, v13.S[2] - __ fmulxvs(v12, __ T2D, v13, v14, 1); // fmulx v12.2D, v13.2D, v14.D[1] - __ mulvs(v15, __ T4H, v0, v1, 0); // mul v15.4H, v0.4H, v1.H[0] - __ mulvs(v9, __ T8H, v10, v11, 6); // mul v9.8H, v10.8H, v11.H[6] - __ mulvs(v11, __ T2S, v12, v13, 0); // mul v11.2S, v12.2S, v13.S[0] - __ mulvs(v1, __ T4S, v2, v3, 2); // mul v1.4S, v2.4S, v3.S[2] + __ fmlavs(v15, __ T2S, v0, v1, 0); // fmla v15.2S, v0.2S, v1.S[0] + __ mulvs(v9, __ T4S, v10, v11, 3); // mul v9.4S, v10.4S, v11.S[3] + __ fmlavs(v4, __ T2D, v5, v6, 1); // fmla v4.2D, v5.2D, v6.D[1] + __ fmlsvs(v13, __ T2S, v14, v15, 1); // fmls v13.2S, v14.2S, v15.S[1] + __ mulvs(v3, __ T4S, v4, v5, 1); // mul v3.4S, v4.4S, v5.S[1] + __ fmlsvs(v11, __ T2D, v12, v13, 1); // fmls v11.2D, v12.2D, v13.D[1] + __ fmulxvs(v12, __ T2S, v13, v14, 1); // fmulx v12.2S, v13.2S, v14.S[1] + __ mulvs(v15, __ T4S, v0, v1, 0); // mul v15.4S, v0.4S, v1.S[0] + __ fmulxvs(v9, __ T2D, v10, v11, 1); // fmulx v9.2D, v10.2D, v11.D[1] + __ mulvs(v11, __ T4H, v12, v13, 1); // mul v11.4H, v12.4H, v13.H[1] + __ mulvs(v1, __ T8H, v2, v3, 4); // mul v1.8H, v2.8H, v3.H[4] + __ mulvs(v0, __ T2S, v1, v2, 1); // mul v0.2S, v1.2S, v2.S[1] + __ mulvs(v13, __ T4S, v14, v15, 3); // mul v13.4S, v14.4S, v15.S[3] // NEONVectorCompare - __ cm(Assembler::GT, v18, __ T8B, v19, v20); // cmgt v18.8B, v19.8B, v20.8B - __ cm(Assembler::GT, v0, __ T16B, v1, v2); // cmgt v0.16B, v1.16B, v2.16B - __ cm(Assembler::GT, v25, __ T4H, v26, v27); // cmgt v25.4H, v26.4H, v27.4H - __ cm(Assembler::GT, v26, __ T8H, v27, v28); // cmgt v26.8H, v27.8H, v28.8H - __ cm(Assembler::GT, v23, __ T2S, v24, v25); // cmgt v23.2S, v24.2S, v25.2S - __ cm(Assembler::GT, v2, __ T4S, v3, v4); // cmgt v2.4S, v3.4S, v4.4S - __ cm(Assembler::GT, v18, __ T2D, v19, v20); // cmgt v18.2D, v19.2D, v20.2D - __ cm(Assembler::GE, v12, __ T8B, v13, v14); // cmge v12.8B, v13.8B, v14.8B - __ cm(Assembler::GE, v4, __ T16B, v5, v6); // cmge v4.16B, v5.16B, v6.16B - __ cm(Assembler::GE, v28, __ T4H, v29, v30); // cmge v28.4H, v29.4H, v30.4H - __ cm(Assembler::GE, v30, __ T8H, v31, v0); // cmge v30.8H, v31.8H, v0.8H - __ cm(Assembler::GE, v29, __ T2S, v30, v31); // cmge v29.2S, v30.2S, v31.2S - __ cm(Assembler::GE, v16, __ T4S, v17, v18); // cmge v16.4S, v17.4S, v18.4S - __ cm(Assembler::GE, v27, __ T2D, v28, v29); // cmge v27.2D, v28.2D, v29.2D - __ cm(Assembler::EQ, v6, __ T8B, v7, v8); // cmeq v6.8B, v7.8B, v8.8B - __ cm(Assembler::EQ, v9, __ T16B, v10, v11); // cmeq v9.16B, v10.16B, v11.16B - __ cm(Assembler::EQ, v29, __ T4H, v30, v31); // cmeq v29.4H, v30.4H, v31.4H - __ cm(Assembler::EQ, v18, __ T8H, v19, v20); // cmeq v18.8H, v19.8H, v20.8H - __ cm(Assembler::EQ, v7, __ T2S, v8, v9); // cmeq v7.2S, v8.2S, v9.2S - __ cm(Assembler::EQ, v4, __ T4S, v5, v6); // cmeq v4.4S, v5.4S, v6.4S - __ cm(Assembler::EQ, v7, __ T2D, v8, v9); // cmeq v7.2D, v8.2D, v9.2D - __ cm(Assembler::HI, v15, __ T8B, v16, v17); // cmhi v15.8B, v16.8B, v17.8B - __ cm(Assembler::HI, v9, __ T16B, v10, v11); // cmhi v9.16B, v10.16B, v11.16B - __ cm(Assembler::HI, v23, __ T4H, v24, v25); // cmhi v23.4H, v24.4H, v25.4H - __ cm(Assembler::HI, v8, __ T8H, v9, v10); // cmhi v8.8H, v9.8H, v10.8H - __ cm(Assembler::HI, v2, __ T2S, v3, v4); // cmhi v2.2S, v3.2S, v4.2S - __ cm(Assembler::HI, v28, __ T4S, v29, v30); // cmhi v28.4S, v29.4S, v30.4S - __ cm(Assembler::HI, v21, __ T2D, v22, v23); // cmhi v21.2D, v22.2D, v23.2D - __ cm(Assembler::HS, v31, __ T8B, v0, v1); // cmhs v31.8B, v0.8B, v1.8B - __ cm(Assembler::HS, v5, __ T16B, v6, v7); // cmhs v5.16B, v6.16B, v7.16B - __ cm(Assembler::HS, v27, __ T4H, v28, v29); // cmhs v27.4H, v28.4H, v29.4H - __ cm(Assembler::HS, v0, __ T8H, v1, v2); // cmhs v0.8H, v1.8H, v2.8H - __ cm(Assembler::HS, v17, __ T2S, v18, v19); // cmhs v17.2S, v18.2S, v19.2S - __ cm(Assembler::HS, v15, __ T4S, v16, v17); // cmhs v15.4S, v16.4S, v17.4S - __ cm(Assembler::HS, v4, __ T2D, v5, v6); // cmhs v4.2D, v5.2D, v6.2D - __ fcm(Assembler::EQ, v26, __ T2S, v27, v28); // fcmeq v26.2S, v27.2S, v28.2S - __ fcm(Assembler::EQ, v8, __ T4S, v9, v10); // fcmeq v8.4S, v9.4S, v10.4S - __ fcm(Assembler::EQ, v28, __ T2D, v29, v30); // fcmeq v28.2D, v29.2D, v30.2D - __ fcm(Assembler::GT, v22, __ T2S, v23, v24); // fcmgt v22.2S, v23.2S, v24.2S - __ fcm(Assembler::GT, v27, __ T4S, v28, v29); // fcmgt v27.4S, v28.4S, v29.4S - __ fcm(Assembler::GT, v27, __ T2D, v28, v29); // fcmgt v27.2D, v28.2D, v29.2D - __ fcm(Assembler::GE, v25, __ T2S, v26, v27); // fcmge v25.2S, v26.2S, v27.2S - __ fcm(Assembler::GE, v23, __ T4S, v24, v25); // fcmge v23.4S, v24.4S, v25.4S + __ cm(Assembler::GT, v23, __ T8B, v24, v25); // cmgt v23.8B, v24.8B, v25.8B + __ cm(Assembler::GT, v2, __ T16B, v3, v4); // cmgt v2.16B, v3.16B, v4.16B + __ cm(Assembler::GT, v18, __ T4H, v19, v20); // cmgt v18.4H, v19.4H, v20.4H + __ cm(Assembler::GT, v12, __ T8H, v13, v14); // cmgt v12.8H, v13.8H, v14.8H + __ cm(Assembler::GT, v4, __ T2S, v5, v6); // cmgt v4.2S, v5.2S, v6.2S + __ cm(Assembler::GT, v28, __ T4S, v29, v30); // cmgt v28.4S, v29.4S, v30.4S + __ cm(Assembler::GT, v30, __ T2D, v31, v0); // cmgt v30.2D, v31.2D, v0.2D + __ cm(Assembler::GE, v29, __ T8B, v30, v31); // cmge v29.8B, v30.8B, v31.8B + __ cm(Assembler::GE, v16, __ T16B, v17, v18); // cmge v16.16B, v17.16B, v18.16B + __ cm(Assembler::GE, v27, __ T4H, v28, v29); // cmge v27.4H, v28.4H, v29.4H + __ cm(Assembler::GE, v6, __ T8H, v7, v8); // cmge v6.8H, v7.8H, v8.8H + __ cm(Assembler::GE, v9, __ T2S, v10, v11); // cmge v9.2S, v10.2S, v11.2S + __ cm(Assembler::GE, v29, __ T4S, v30, v31); // cmge v29.4S, v30.4S, v31.4S + __ cm(Assembler::GE, v18, __ T2D, v19, v20); // cmge v18.2D, v19.2D, v20.2D + __ cm(Assembler::EQ, v7, __ T8B, v8, v9); // cmeq v7.8B, v8.8B, v9.8B + __ cm(Assembler::EQ, v4, __ T16B, v5, v6); // cmeq v4.16B, v5.16B, v6.16B + __ cm(Assembler::EQ, v7, __ T4H, v8, v9); // cmeq v7.4H, v8.4H, v9.4H + __ cm(Assembler::EQ, v15, __ T8H, v16, v17); // cmeq v15.8H, v16.8H, v17.8H + __ cm(Assembler::EQ, v9, __ T2S, v10, v11); // cmeq v9.2S, v10.2S, v11.2S + __ cm(Assembler::EQ, v23, __ T4S, v24, v25); // cmeq v23.4S, v24.4S, v25.4S + __ cm(Assembler::EQ, v8, __ T2D, v9, v10); // cmeq v8.2D, v9.2D, v10.2D + __ cm(Assembler::HI, v2, __ T8B, v3, v4); // cmhi v2.8B, v3.8B, v4.8B + __ cm(Assembler::HI, v28, __ T16B, v29, v30); // cmhi v28.16B, v29.16B, v30.16B + __ cm(Assembler::HI, v21, __ T4H, v22, v23); // cmhi v21.4H, v22.4H, v23.4H + __ cm(Assembler::HI, v31, __ T8H, v0, v1); // cmhi v31.8H, v0.8H, v1.8H + __ cm(Assembler::HI, v5, __ T2S, v6, v7); // cmhi v5.2S, v6.2S, v7.2S + __ cm(Assembler::HI, v27, __ T4S, v28, v29); // cmhi v27.4S, v28.4S, v29.4S + __ cm(Assembler::HI, v0, __ T2D, v1, v2); // cmhi v0.2D, v1.2D, v2.2D + __ cm(Assembler::HS, v17, __ T8B, v18, v19); // cmhs v17.8B, v18.8B, v19.8B + __ cm(Assembler::HS, v15, __ T16B, v16, v17); // cmhs v15.16B, v16.16B, v17.16B + __ cm(Assembler::HS, v4, __ T4H, v5, v6); // cmhs v4.4H, v5.4H, v6.4H + __ cm(Assembler::HS, v26, __ T8H, v27, v28); // cmhs v26.8H, v27.8H, v28.8H + __ cm(Assembler::HS, v8, __ T2S, v9, v10); // cmhs v8.2S, v9.2S, v10.2S + __ cm(Assembler::HS, v28, __ T4S, v29, v30); // cmhs v28.4S, v29.4S, v30.4S + __ cm(Assembler::HS, v22, __ T2D, v23, v24); // cmhs v22.2D, v23.2D, v24.2D + __ fcm(Assembler::EQ, v27, __ T2S, v28, v29); // fcmeq v27.2S, v28.2S, v29.2S + __ fcm(Assembler::EQ, v27, __ T4S, v28, v29); // fcmeq v27.4S, v28.4S, v29.4S + __ fcm(Assembler::EQ, v25, __ T2D, v26, v27); // fcmeq v25.2D, v26.2D, v27.2D + __ fcm(Assembler::GT, v23, __ T2S, v24, v25); // fcmgt v23.2S, v24.2S, v25.2S + __ fcm(Assembler::GT, v0, __ T4S, v1, v2); // fcmgt v0.4S, v1.4S, v2.4S + __ fcm(Assembler::GT, v4, __ T2D, v5, v6); // fcmgt v4.2D, v5.2D, v6.2D + __ fcm(Assembler::GE, v6, __ T2S, v7, v8); // fcmge v6.2S, v7.2S, v8.2S + __ fcm(Assembler::GE, v18, __ T4S, v19, v20); // fcmge v18.4S, v19.4S, v20.4S __ fcm(Assembler::GE, v0, __ T2D, v1, v2); // fcmge v0.2D, v1.2D, v2.2D // SVEComparisonWithZero - __ sve_fcm(Assembler::EQ, p2, __ D, p0, z6, 0.0); // fcmeq p2.d, p0/z, z6.d, #0.0 - __ sve_fcm(Assembler::GT, p2, __ S, p2, z15, 0.0); // fcmgt p2.s, p2/z, z15.s, #0.0 - __ sve_fcm(Assembler::GE, p3, __ S, p7, z5, 0.0); // fcmge p3.s, p7/z, z5.s, #0.0 - __ sve_fcm(Assembler::LT, p3, __ D, p5, z20, 0.0); // fcmlt p3.d, p5/z, z20.d, #0.0 - __ sve_fcm(Assembler::LE, p3, __ S, p4, z11, 0.0); // fcmle p3.s, p4/z, z11.s, #0.0 - __ sve_fcm(Assembler::NE, p15, __ D, p0, z6, 0.0); // fcmne p15.d, p0/z, z6.d, #0.0 + __ sve_fcm(Assembler::EQ, p2, __ S, p2, z15, 0.0); // fcmeq p2.s, p2/z, z15.s, #0.0 + __ sve_fcm(Assembler::GT, p3, __ S, p7, z5, 0.0); // fcmgt p3.s, p7/z, z5.s, #0.0 + __ sve_fcm(Assembler::GE, p3, __ D, p5, z20, 0.0); // fcmge p3.d, p5/z, z20.d, #0.0 + __ sve_fcm(Assembler::LT, p3, __ S, p4, z11, 0.0); // fcmlt p3.s, p4/z, z11.s, #0.0 + __ sve_fcm(Assembler::LE, p15, __ D, p0, z6, 0.0); // fcmle p15.d, p0/z, z6.d, #0.0 + __ sve_fcm(Assembler::NE, p6, __ D, p0, z30, 0.0); // fcmne p6.d, p0/z, z30.d, #0.0 // SVEComparisonWithImm - __ sve_cmp(Assembler::EQ, p6, __ D, p0, z30, 11); // cmpeq p6.d, p0/z, z30.d, #11 - __ sve_cmp(Assembler::GT, p11, __ H, p3, z29, 12); // cmpgt p11.h, p3/z, z29.h, #12 - __ sve_cmp(Assembler::GE, p8, __ B, p0, z24, -2); // cmpge p8.b, p0/z, z24.b, #-2 - __ sve_cmp(Assembler::LT, p5, __ H, p6, z16, 7); // cmplt p5.h, p6/z, z16.h, #7 - __ sve_cmp(Assembler::LE, p6, __ S, p4, z4, -12); // cmple p6.s, p4/z, z4.s, #-12 - __ sve_cmp(Assembler::NE, p0, __ S, p4, z19, -3); // cmpne p0.s, p4/z, z19.s, #-3 - __ sve_cmp(Assembler::HS, p7, __ B, p4, z12, 15); // cmphs p7.b, p4/z, z12.b, #15 - __ sve_cmp(Assembler::HI, p10, __ B, p1, z23, 30); // cmphi p10.b, p1/z, z23.b, #30 - __ sve_cmp(Assembler::LS, p9, __ D, p4, z13, 67); // cmpls p9.d, p4/z, z13.d, #67 - __ sve_cmp(Assembler::LO, p3, __ D, p0, z2, 16); // cmplo p3.d, p0/z, z2.d, #16 + __ sve_cmp(Assembler::EQ, p13, __ D, p3, z22, -3); // cmpeq p13.d, p3/z, z22.d, #-3 + __ sve_cmp(Assembler::GT, p14, __ D, p1, z17, -14); // cmpgt p14.d, p1/z, z17.d, #-14 + __ sve_cmp(Assembler::GE, p7, __ S, p2, z10, 11); // cmpge p7.s, p2/z, z10.s, #11 + __ sve_cmp(Assembler::LT, p11, __ B, p5, z12, 1); // cmplt p11.b, p5/z, z12.b, #1 + __ sve_cmp(Assembler::LE, p2, __ S, p4, z1, 2); // cmple p2.s, p4/z, z1.s, #2 + __ sve_cmp(Assembler::NE, p6, __ H, p0, z14, 1); // cmpne p6.h, p0/z, z14.h, #1 + __ sve_cmp(Assembler::HS, p1, __ S, p1, z21, 25); // cmphs p1.s, p1/z, z21.s, #25 + __ sve_cmp(Assembler::HI, p3, __ H, p7, z19, 70); // cmphi p3.h, p7/z, z19.h, #70 + __ sve_cmp(Assembler::LS, p8, __ B, p7, z6, 12); // cmpls p8.b, p7/z, z6.b, #12 + __ sve_cmp(Assembler::LO, p2, __ S, p5, z6, 55); // cmplo p2.s, p5/z, z6.s, #55 // SpecialCases __ ccmn(zr, zr, 3u, Assembler::LE); // ccmn xzr, xzr, #3, LE @@ -1210,241 +1216,241 @@ __ fmovd(v0, -1.0625); // fmov d0, #-1.0625 // LSEOp - __ swp(Assembler::xword, r6, r16, r20); // swp x6, x16, [x20] - __ ldadd(Assembler::xword, r13, r12, r20); // ldadd x13, x12, [x20] - __ ldbic(Assembler::xword, r8, r25, r20); // ldclr x8, x25, [x20] - __ ldeor(Assembler::xword, r19, r0, r11); // ldeor x19, x0, [x11] - __ ldorr(Assembler::xword, r24, r6, r20); // ldset x24, x6, [x20] - __ ldsmin(Assembler::xword, zr, r14, r16); // ldsmin xzr, x14, [x16] - __ ldsmax(Assembler::xword, r6, r0, r7); // ldsmax x6, x0, [x7] - __ ldumin(Assembler::xword, r15, r19, r26); // ldumin x15, x19, [x26] - __ ldumax(Assembler::xword, r9, r10, r23); // ldumax x9, x10, [x23] + __ swp(Assembler::xword, r12, r20, r8); // swp x12, x20, [x8] + __ ldadd(Assembler::xword, r25, r20, r19); // ldadd x25, x20, [x19] + __ ldbic(Assembler::xword, r0, r11, r24); // ldclr x0, x11, [x24] + __ ldeor(Assembler::xword, r6, r20, sp); // ldeor x6, x20, [sp] + __ ldorr(Assembler::xword, r14, r16, r6); // ldset x14, x16, [x6] + __ ldsmin(Assembler::xword, r0, r7, r15); // ldsmin x0, x7, [x15] + __ ldsmax(Assembler::xword, r19, r26, r9); // ldsmax x19, x26, [x9] + __ ldumin(Assembler::xword, r10, r23, r21); // ldumin x10, x23, [x21] + __ ldumax(Assembler::xword, r22, r28, r2); // ldumax x22, x28, [x2] // LSEOp - __ swpa(Assembler::xword, r21, r22, r28); // swpa x21, x22, [x28] - __ ldadda(Assembler::xword, r2, r3, r15); // ldadda x2, x3, [x15] - __ ldbica(Assembler::xword, r19, r20, r7); // ldclra x19, x20, [x7] - __ ldeora(Assembler::xword, r4, r29, r7); // ldeora x4, x29, [x7] - __ ldorra(Assembler::xword, r0, r9, r16); // ldseta x0, x9, [x16] - __ ldsmina(Assembler::xword, r20, r23, r4); // ldsmina x20, x23, [x4] - __ ldsmaxa(Assembler::xword, r16, r10, r23); // ldsmaxa x16, x10, [x23] - __ ldumina(Assembler::xword, r11, r25, r6); // ldumina x11, x25, [x6] - __ ldumaxa(Assembler::xword, zr, r16, r13); // ldumaxa xzr, x16, [x13] + __ swpa(Assembler::xword, r3, r15, r19); // swpa x3, x15, [x19] + __ ldadda(Assembler::xword, r20, r7, r4); // ldadda x20, x7, [x4] + __ ldbica(Assembler::xword, r29, r7, r0); // ldclra x29, x7, [x0] + __ ldeora(Assembler::xword, r9, r16, r20); // ldeora x9, x16, [x20] + __ ldorra(Assembler::xword, r23, r4, r16); // ldseta x23, x4, [x16] + __ ldsmina(Assembler::xword, r10, r23, r11); // ldsmina x10, x23, [x11] + __ ldsmaxa(Assembler::xword, r25, r6, sp); // ldsmaxa x25, x6, [sp] + __ ldumina(Assembler::xword, r16, r13, r23); // ldumina x16, x13, [x23] + __ ldumaxa(Assembler::xword, r12, r1, r14); // ldumaxa x12, x1, [x14] // LSEOp - __ swpal(Assembler::xword, r23, r12, r1); // swpal x23, x12, [x1] - __ ldaddal(Assembler::xword, r14, r9, r21); // ldaddal x14, x9, [x21] - __ ldbical(Assembler::xword, r16, r26, r15); // ldclral x16, x26, [x15] - __ ldeoral(Assembler::xword, r4, r4, r15); // ldeoral x4, x4, [x15] - __ ldorral(Assembler::xword, r8, r6, r30); // ldsetal x8, x6, [x30] - __ ldsminal(Assembler::xword, r4, r29, r17); // ldsminal x4, x29, [x17] - __ ldsmaxal(Assembler::xword, r29, r26, r9); // ldsmaxal x29, x26, [x9] - __ lduminal(Assembler::xword, r15, r2, r11); // lduminal x15, x2, [x11] - __ ldumaxal(Assembler::xword, r29, r3, r7); // ldumaxal x29, x3, [x7] + __ swpal(Assembler::xword, r9, r21, r16); // swpal x9, x21, [x16] + __ ldaddal(Assembler::xword, r26, r15, r4); // ldaddal x26, x15, [x4] + __ ldbical(Assembler::xword, r4, r16, r8); // ldclral x4, x16, [x8] + __ ldeoral(Assembler::xword, r6, r30, r4); // ldeoral x6, x30, [x4] + __ ldorral(Assembler::xword, r29, r17, r29); // ldsetal x29, x17, [x29] + __ ldsminal(Assembler::xword, r26, r9, r15); // ldsminal x26, x9, [x15] + __ ldsmaxal(Assembler::xword, r2, r11, r29); // ldsmaxal x2, x11, [x29] + __ lduminal(Assembler::xword, r3, r7, r1); // lduminal x3, x7, [x1] + __ ldumaxal(Assembler::xword, r27, r21, r15); // ldumaxal x27, x21, [x15] // LSEOp - __ swpl(Assembler::xword, r1, r27, r21); // swpl x1, x27, [x21] - __ ldaddl(Assembler::xword, r16, r14, r8); // ldaddl x16, x14, [x8] - __ ldbicl(Assembler::xword, r16, r22, r25); // ldclrl x16, x22, [x25] - __ ldeorl(Assembler::xword, r5, r20, r21); // ldeorl x5, x20, [x21] - __ ldorrl(Assembler::xword, r16, r23, r16); // ldsetl x16, x23, [x16] - __ ldsminl(Assembler::xword, r30, r20, r20); // ldsminl x30, x20, [x20] - __ ldsmaxl(Assembler::xword, r0, r4, r19); // ldsmaxl x0, x4, [x19] - __ lduminl(Assembler::xword, r24, r4, r20); // lduminl x24, x4, [x20] - __ ldumaxl(Assembler::xword, r4, r24, r26); // ldumaxl x4, x24, [x26] + __ swpl(Assembler::xword, r14, r8, r15); // swpl x14, x8, [x15] + __ ldaddl(Assembler::xword, r22, r25, r5); // ldaddl x22, x25, [x5] + __ ldbicl(Assembler::xword, r20, r21, r15); // ldclrl x20, x21, [x15] + __ ldeorl(Assembler::xword, r23, r16, r30); // ldeorl x23, x16, [x30] + __ ldorrl(Assembler::xword, r20, r20, r0); // ldsetl x20, x20, [x0] + __ ldsminl(Assembler::xword, r4, r19, r24); // ldsminl x4, x19, [x24] + __ ldsmaxl(Assembler::xword, r4, r20, r4); // ldsmaxl x4, x20, [x4] + __ lduminl(Assembler::xword, r24, r26, r19); // lduminl x24, x26, [x19] + __ ldumaxl(Assembler::xword, r2, r8, r8); // ldumaxl x2, x8, [x8] // LSEOp - __ swp(Assembler::word, r19, r2, r8); // swp w19, w2, [x8] - __ ldadd(Assembler::word, r8, r14, r24); // ldadd w8, w14, [x24] - __ ldbic(Assembler::word, r16, zr, r22); // ldclr w16, wzr, [x22] - __ ldeor(Assembler::word, r4, zr, r1); // ldeor w4, wzr, [x1] - __ ldorr(Assembler::word, r10, r20, r12); // ldset w10, w20, [x12] - __ ldsmin(Assembler::word, r0, r9, r7); // ldsmin w0, w9, [x7] - __ ldsmax(Assembler::word, r24, r16, r4); // ldsmax w24, w16, [x4] - __ ldumin(Assembler::word, r27, r6, r10); // ldumin w27, w6, [x10] - __ ldumax(Assembler::word, r27, r24, r13); // ldumax w27, w24, [x13] + __ swp(Assembler::word, r14, r24, r15); // swp w14, w24, [x15] + __ ldadd(Assembler::word, zr, r22, r4); // ldadd wzr, w22, [x4] + __ ldbic(Assembler::word, zr, r1, r10); // ldclr wzr, w1, [x10] + __ ldeor(Assembler::word, r20, r12, r0); // ldeor w20, w12, [x0] + __ ldorr(Assembler::word, r9, r7, r24); // ldset w9, w7, [x24] + __ ldsmin(Assembler::word, r16, r4, r27); // ldsmin w16, w4, [x27] + __ ldsmax(Assembler::word, r6, r10, r27); // ldsmax w6, w10, [x27] + __ ldumin(Assembler::word, r24, r13, r16); // ldumin w24, w13, [x16] + __ ldumax(Assembler::word, zr, r22, r22); // ldumax wzr, w22, [x22] // LSEOp - __ swpa(Assembler::word, r16, zr, r22); // swpa w16, wzr, [x22] - __ ldadda(Assembler::word, r22, r20, sp); // ldadda w22, w20, [sp] - __ ldbica(Assembler::word, r29, r9, r14); // ldclra w29, w9, [x14] - __ ldeora(Assembler::word, r20, r7, r20); // ldeora w20, w7, [x20] - __ ldorra(Assembler::word, r28, r9, r11); // ldseta w28, w9, [x11] - __ ldsmina(Assembler::word, r14, r12, r20); // ldsmina w14, w12, [x20] - __ ldsmaxa(Assembler::word, r1, r24, r9); // ldsmaxa w1, w24, [x9] - __ ldumina(Assembler::word, r19, r13, r19); // ldumina w19, w13, [x19] - __ ldumaxa(Assembler::word, r16, r16, r5); // ldumaxa w16, w16, [x5] + __ swpa(Assembler::word, r20, zr, r29); // swpa w20, wzr, [x29] + __ ldadda(Assembler::word, r9, r14, r20); // ldadda w9, w14, [x20] + __ ldbica(Assembler::word, r7, r20, r28); // ldclra w7, w20, [x28] + __ ldeora(Assembler::word, r9, r11, r14); // ldeora w9, w11, [x14] + __ ldorra(Assembler::word, r12, r20, r1); // ldseta w12, w20, [x1] + __ ldsmina(Assembler::word, r24, r9, r19); // ldsmina w24, w9, [x19] + __ ldsmaxa(Assembler::word, r13, r19, r15); // ldsmaxa w13, w19, [x15] + __ ldumina(Assembler::word, r16, r5, r0); // ldumina w16, w5, [x0] + __ ldumaxa(Assembler::word, r3, r12, r8); // ldumaxa w3, w12, [x8] // LSEOp - __ swpal(Assembler::word, r0, r3, r12); // swpal w0, w3, [x12] - __ ldaddal(Assembler::word, r8, r15, r15); // ldaddal w8, w15, [x15] - __ ldbical(Assembler::word, r16, r4, r15); // ldclral w16, w4, [x15] - __ ldeoral(Assembler::word, r30, r5, r0); // ldeoral w30, w5, [x0] - __ ldorral(Assembler::word, r10, r22, r27); // ldsetal w10, w22, [x27] - __ ldsminal(Assembler::word, r3, r0, r9); // ldsminal w3, w0, [x9] - __ ldsmaxal(Assembler::word, r19, r29, r10); // ldsmaxal w19, w29, [x10] - __ lduminal(Assembler::word, r24, r4, r20); // lduminal w24, w4, [x20] - __ ldumaxal(Assembler::word, r7, r24, r29); // ldumaxal w7, w24, [x29] + __ swpal(Assembler::word, r15, r15, r16); // swpal w15, w15, [x16] + __ ldaddal(Assembler::word, r4, r15, r30); // ldaddal w4, w15, [x30] + __ ldbical(Assembler::word, r5, r0, r10); // ldclral w5, w0, [x10] + __ ldeoral(Assembler::word, r22, r27, r3); // ldeoral w22, w27, [x3] + __ ldorral(Assembler::word, r0, r9, r19); // ldsetal w0, w9, [x19] + __ ldsminal(Assembler::word, r29, r10, r24); // ldsminal w29, w10, [x24] + __ ldsmaxal(Assembler::word, r4, r20, r7); // ldsmaxal w4, w20, [x7] + __ lduminal(Assembler::word, r24, r29, r14); // lduminal w24, w29, [x14] + __ ldumaxal(Assembler::word, r21, r11, r27); // ldumaxal w21, w11, [x27] // LSEOp - __ swpl(Assembler::word, r14, r21, r11); // swpl w14, w21, [x11] - __ ldaddl(Assembler::word, r27, r13, r15); // ldaddl w27, w13, [x15] - __ ldbicl(Assembler::word, zr, r17, r14); // ldclrl wzr, w17, [x14] - __ ldeorl(Assembler::word, r3, r30, r16); // ldeorl w3, w30, [x16] - __ ldorrl(Assembler::word, r22, r20, r7); // ldsetl w22, w20, [x7] - __ ldsminl(Assembler::word, r20, r3, r1); // ldsminl w20, w3, [x1] - __ ldsmaxl(Assembler::word, r26, r19, r9); // ldsmaxl w26, w19, [x9] - __ lduminl(Assembler::word, r16, r17, r21); // lduminl w16, w17, [x21] - __ ldumaxl(Assembler::word, r0, r4, r2); // ldumaxl w0, w4, [x2] + __ swpl(Assembler::word, r13, r16, sp); // swpl w13, w16, [sp] + __ ldaddl(Assembler::word, r17, r14, r3); // ldaddl w17, w14, [x3] + __ ldbicl(Assembler::word, r30, r16, r22); // ldclrl w30, w16, [x22] + __ ldeorl(Assembler::word, r20, r7, r20); // ldeorl w20, w7, [x20] + __ ldorrl(Assembler::word, r3, r1, r26); // ldsetl w3, w1, [x26] + __ ldsminl(Assembler::word, r19, r9, r16); // ldsminl w19, w9, [x16] + __ ldsmaxl(Assembler::word, r17, r21, r0); // ldsmaxl w17, w21, [x0] + __ lduminl(Assembler::word, r4, r2, r24); // lduminl w4, w2, [x24] + __ ldumaxl(Assembler::word, r14, r6, r11); // ldumaxl w14, w6, [x11] // SHA3SIMDOp - __ bcax(v24, __ T16B, v14, v6, v11); // bcax v24.16B, v14.16B, v6.16B, v11.16B - __ eor3(v21, __ T16B, v14, v17, v30); // eor3 v21.16B, v14.16B, v17.16B, v30.16B - __ rax1(v12, __ T2D, v3, v3); // rax1 v12.2D, v3.2D, v3.2D - __ xar(v23, __ T2D, v9, v3, 49); // xar v23.2D, v9.2D, v3.2D, #49 + __ bcax(v21, __ T16B, v14, v17, v30); // bcax v21.16B, v14.16B, v17.16B, v30.16B + __ eor3(v12, __ T16B, v3, v3, v23); // eor3 v12.16B, v3.16B, v3.16B, v23.16B + __ rax1(v9, __ T2D, v3, v24); // rax1 v9.2D, v3.2D, v24.2D + __ xar(v28, __ T2D, v3, v19, 47); // xar v28.2D, v3.2D, v19.2D, #47 // SHA512SIMDOp - __ sha512h(v28, __ T2D, v3, v19); // sha512h q28, q3, v19.2D - __ sha512h2(v23, __ T2D, v7, v26); // sha512h2 q23, q7, v26.2D - __ sha512su0(v21, __ T2D, v14); // sha512su0 v21.2D, v14.2D - __ sha512su1(v5, __ T2D, v8, v26); // sha512su1 v5.2D, v8.2D, v26.2D + __ sha512h(v7, __ T2D, v26, v21); // sha512h q7, q26, v21.2D + __ sha512h2(v14, __ T2D, v5, v8); // sha512h2 q14, q5, v8.2D + __ sha512su0(v26, __ T2D, v5); // sha512su0 v26.2D, v5.2D + __ sha512su1(v22, __ T2D, v18, v17); // sha512su1 v22.2D, v18.2D, v17.2D // SVEBinaryImmOp - __ sve_add(z5, __ S, 146u); // add z5.s, z5.s, #0x92 - __ sve_sub(z17, __ B, 31u); // sub z17.b, z17.b, #0x1f - __ sve_and(z9, __ S, 16744448u); // and z9.s, z9.s, #0xff8000 - __ sve_eor(z12, __ H, 33279u); // eor z12.h, z12.h, #0x81ff - __ sve_orr(z11, __ H, 49663u); // orr z11.h, z11.h, #0xc1ff + __ sve_add(z0, __ B, 79u); // add z0.b, z0.b, #0x4f + __ sve_sub(z20, __ H, 65u); // sub z20.h, z20.h, #0x41 + __ sve_and(z12, __ H, 33279u); // and z12.h, z12.h, #0x81ff + __ sve_eor(z11, __ H, 49663u); // eor z11.h, z11.h, #0xc1ff + __ sve_orr(z31, __ S, 2147484159u); // orr z31.s, z31.s, #0x800001ff // SVEBinaryImmOp - __ sve_add(z31, __ S, 72u); // add z31.s, z31.s, #0x48 - __ sve_sub(z16, __ H, 218u); // sub z16.h, z16.h, #0xda - __ sve_and(z23, __ D, 562675075514368u); // and z23.d, z23.d, #0x1ffc000000000 - __ sve_eor(z8, __ B, 243u); // eor z8.b, z8.b, #0xf3 - __ sve_orr(z10, __ B, 239u); // orr z10.b, z10.b, #0xef + __ sve_add(z15, __ D, 188u); // add z15.d, z15.d, #0xbc + __ sve_sub(z28, __ S, 64u); // sub z28.s, z28.s, #0x40 + __ sve_and(z8, __ B, 243u); // and z8.b, z8.b, #0xf3 + __ sve_eor(z10, __ B, 239u); // eor z10.b, z10.b, #0xef + __ sve_orr(z22, __ S, 32768u); // orr z22.s, z22.s, #0x8000 // SVEBinaryImmOp - __ sve_add(z22, __ S, 5u); // add z22.s, z22.s, #0x5 - __ sve_sub(z3, __ S, 209u); // sub z3.s, z3.s, #0xd1 - __ sve_and(z5, __ D, 17870287719452639231u); // and z5.d, z5.d, #0xf80003ffffffffff - __ sve_eor(z17, __ B, 128u); // eor z17.b, z17.b, #0x80 - __ sve_orr(z30, __ H, 49663u); // orr z30.h, z30.h, #0xc1ff + __ sve_add(z23, __ D, 46u); // add z23.d, z23.d, #0x2e + __ sve_sub(z26, __ D, 154u); // sub z26.d, z26.d, #0x9a + __ sve_and(z17, __ B, 128u); // and z17.b, z17.b, #0x80 + __ sve_eor(z30, __ H, 49663u); // eor z30.h, z30.h, #0xc1ff + __ sve_orr(z2, __ D, 18444492273897963519u); // orr z2.d, z2.d, #0xfff80000001fffff // SVEBinaryImmOp - __ sve_add(z2, __ D, 168u); // add z2.d, z2.d, #0xa8 - __ sve_sub(z23, __ S, 240u); // sub z23.s, z23.s, #0xf0 - __ sve_and(z12, __ H, 1u); // and z12.h, z12.h, #0x1 - __ sve_eor(z15, __ S, 1u); // eor z15.s, z15.s, #0x1 - __ sve_orr(z19, __ D, 18446532967477018623u); // orr z19.d, z19.d, #0xffff3fffffffffff + __ sve_add(z22, __ D, 103u); // add z22.d, z22.d, #0x67 + __ sve_sub(z8, __ B, 5u); // sub z8.b, z8.b, #0x5 + __ sve_and(z15, __ S, 1u); // and z15.s, z15.s, #0x1 + __ sve_eor(z19, __ D, 18446532967477018623u); // eor z19.d, z19.d, #0xffff3fffffffffff + __ sve_orr(z13, __ S, 7168u); // orr z13.s, z13.s, #0x1c00 // SVEBinaryImmOp - __ sve_add(z13, __ S, 179u); // add z13.s, z13.s, #0xb3 - __ sve_sub(z2, __ B, 88u); // sub z2.b, z2.b, #0x58 - __ sve_and(z20, __ H, 57855u); // and z20.h, z20.h, #0xe1ff - __ sve_eor(z24, __ H, 33279u); // eor z24.h, z24.h, #0x81ff - __ sve_orr(z20, __ S, 917504u); // orr z20.s, z20.s, #0xe0000 + __ sve_add(z1, __ H, 164u); // add z1.h, z1.h, #0xa4 + __ sve_sub(z12, __ S, 194u); // sub z12.s, z12.s, #0xc2 + __ sve_and(z24, __ H, 33279u); // and z24.h, z24.h, #0x81ff + __ sve_eor(z20, __ S, 917504u); // eor z20.s, z20.s, #0xe0000 + __ sve_orr(z21, __ H, 57343u); // orr z21.h, z21.h, #0xdfff // SVEBinaryImmOp - __ sve_add(z21, __ H, 247u); // add z21.h, z21.h, #0xf7 - __ sve_sub(z22, __ D, 253u); // sub z22.d, z22.d, #0xfd - __ sve_and(z26, __ S, 1610637312u); // and z26.s, z26.s, #0x60006000 - __ sve_eor(z11, __ H, 51199u); // eor z11.h, z11.h, #0xc7ff - __ sve_orr(z5, __ B, 128u); // orr z5.b, z5.b, #0x80 + __ sve_add(z31, __ D, 213u); // add z31.d, z31.d, #0xd5 + __ sve_sub(z18, __ S, 120u); // sub z18.s, z18.s, #0x78 + __ sve_and(z11, __ H, 51199u); // and z11.h, z11.h, #0xc7ff + __ sve_eor(z5, __ B, 128u); // eor z5.b, z5.b, #0x80 + __ sve_orr(z2, __ B, 124u); // orr z2.b, z2.b, #0x7c // SVEVectorOp - __ sve_add(z2, __ H, z7, z10); // add z2.h, z7.h, z10.h - __ sve_sub(z19, __ H, z4, z26); // sub z19.h, z4.h, z26.h - __ sve_fadd(z2, __ S, z3, z30); // fadd z2.s, z3.s, z30.s - __ sve_fmul(z20, __ D, z5, z20); // fmul z20.d, z5.d, z20.d - __ sve_fsub(z29, __ S, z13, z13); // fsub z29.s, z13.s, z13.s - __ sve_sqadd(z14, __ H, z30, z1); // sqadd z14.h, z30.h, z1.h - __ sve_sqsub(z28, __ D, z3, z3); // sqsub z28.d, z3.d, z3.d - __ sve_uqadd(z9, __ B, z25, z9); // uqadd z9.b, z25.b, z9.b - __ sve_uqsub(z26, __ B, z10, z14); // uqsub z26.b, z10.b, z14.b - __ sve_abs(z20, __ D, p6, z7); // abs z20.d, p6/m, z7.d - __ sve_add(z20, __ D, p4, z6); // add z20.d, p4/m, z20.d, z6.d - __ sve_and(z13, __ H, p0, z29); // and z13.h, p0/m, z13.h, z29.h - __ sve_asr(z9, __ B, p0, z1); // asr z9.b, p0/m, z9.b, z1.b - __ sve_bic(z27, __ B, p6, z15); // bic z27.b, p6/m, z27.b, z15.b - __ sve_clz(z4, __ D, p7, z17); // clz z4.d, p7/m, z17.d - __ sve_cnt(z2, __ B, p0, z24); // cnt z2.b, p0/m, z24.b - __ sve_eor(z26, __ B, p7, z13); // eor z26.b, p7/m, z26.b, z13.b - __ sve_lsl(z22, __ D, p3, z16); // lsl z22.d, p3/m, z22.d, z16.d - __ sve_lsr(z17, __ D, p1, z11); // lsr z17.d, p1/m, z17.d, z11.d - __ sve_mul(z16, __ B, p0, z16); // mul z16.b, p0/m, z16.b, z16.b - __ sve_neg(z28, __ D, p1, z23); // neg z28.d, p1/m, z23.d - __ sve_not(z28, __ S, p4, z10); // not z28.s, p4/m, z10.s - __ sve_orr(z17, __ S, p7, z7); // orr z17.s, p7/m, z17.s, z7.s - __ sve_rbit(z4, __ H, p3, z24); // rbit z4.h, p3/m, z24.h - __ sve_revb(z9, __ H, p2, z11); // revb z9.h, p2/m, z11.h - __ sve_smax(z4, __ S, p5, z22); // smax z4.s, p5/m, z4.s, z22.s - __ sve_smin(z4, __ H, p0, z15); // smin z4.h, p0/m, z4.h, z15.h - __ sve_umax(z4, __ D, p7, z26); // umax z4.d, p7/m, z4.d, z26.d - __ sve_umin(z5, __ H, p5, z26); // umin z5.h, p5/m, z5.h, z26.h - __ sve_sub(z31, __ B, p0, z25); // sub z31.b, p0/m, z31.b, z25.b - __ sve_fabs(z8, __ D, p1, z3); // fabs z8.d, p1/m, z3.d - __ sve_fadd(z7, __ D, p6, z24); // fadd z7.d, p6/m, z7.d, z24.d - __ sve_fdiv(z24, __ S, p7, z17); // fdiv z24.s, p7/m, z24.s, z17.s - __ sve_fmax(z10, __ S, p3, z30); // fmax z10.s, p3/m, z10.s, z30.s - __ sve_fmin(z8, __ S, p6, z29); // fmin z8.s, p6/m, z8.s, z29.s - __ sve_fmul(z31, __ D, p5, z31); // fmul z31.d, p5/m, z31.d, z31.d - __ sve_fneg(z0, __ D, p5, z7); // fneg z0.d, p5/m, z7.d - __ sve_frintm(z29, __ S, p6, z22); // frintm z29.s, p6/m, z22.s - __ sve_frintn(z29, __ S, p6, z20); // frintn z29.s, p6/m, z20.s - __ sve_frintp(z6, __ S, p4, z18); // frintp z6.s, p4/m, z18.s - __ sve_fsqrt(z26, __ S, p5, z8); // fsqrt z26.s, p5/m, z8.s - __ sve_fsub(z19, __ S, p2, z28); // fsub z19.s, p2/m, z19.s, z28.s - __ sve_fmad(z17, __ D, p1, z30, z20); // fmad z17.d, p1/m, z30.d, z20.d - __ sve_fmla(z28, __ D, p3, z17, z14); // fmla z28.d, p3/m, z17.d, z14.d - __ sve_fmls(z10, __ S, p6, z11, z24); // fmls z10.s, p6/m, z11.s, z24.s - __ sve_fmsb(z11, __ D, p3, z28, z23); // fmsb z11.d, p3/m, z28.d, z23.d - __ sve_fnmad(z20, __ D, p7, z23, z20); // fnmad z20.d, p7/m, z23.d, z20.d - __ sve_fnmsb(z24, __ D, p0, z27, z6); // fnmsb z24.d, p0/m, z27.d, z6.d - __ sve_fnmla(z13, __ D, p3, z4, z13); // fnmla z13.d, p3/m, z4.d, z13.d - __ sve_fnmls(z26, __ S, p5, z20, z6); // fnmls z26.s, p5/m, z20.s, z6.s - __ sve_mla(z29, __ S, p7, z0, z29); // mla z29.s, p7/m, z0.s, z29.s - __ sve_mls(z3, __ D, p1, z5, z8); // mls z3.d, p1/m, z5.d, z8.d - __ sve_and(z13, z17, z13); // and z13.d, z17.d, z13.d - __ sve_eor(z8, z10, z8); // eor z8.d, z10.d, z8.d - __ sve_orr(z19, z0, z29); // orr z19.d, z0.d, z29.d - __ sve_bic(z16, z13, z23); // bic z16.d, z13.d, z23.d - __ sve_uzp1(z23, __ B, z30, z13); // uzp1 z23.b, z30.b, z13.b - __ sve_uzp2(z25, __ H, z22, z0); // uzp2 z25.h, z22.h, z0.h - __ sve_fabd(z25, __ S, p7, z11); // fabd z25.s, p7/m, z25.s, z11.s - __ sve_bext(z14, __ H, z23, z22); // bext z14.h, z23.h, z22.h - __ sve_bdep(z5, __ H, z18, z0); // bdep z5.h, z18.h, z0.h - __ sve_eor3(z9, z2, z3); // eor3 z9.d, z9.d, z2.d, z3.d - __ sve_sqadd(z14, __ H, p1, z29); // sqadd z14.h, p1/m, z14.h, z29.h - __ sve_sqsub(z14, __ D, p5, z4); // sqsub z14.d, p5/m, z14.d, z4.d - __ sve_uqadd(z27, __ S, p3, z22); // uqadd z27.s, p3/m, z27.s, z22.s - __ sve_uqsub(z31, __ S, p6, z11); // uqsub z31.s, p6/m, z31.s, z11.s + __ sve_add(z19, __ H, z4, z26); // add z19.h, z4.h, z26.h + __ sve_sub(z2, __ B, z3, z30); // sub z2.b, z3.b, z30.b + __ sve_fadd(z20, __ D, z5, z20); // fadd z20.d, z5.d, z20.d + __ sve_fmul(z29, __ S, z13, z13); // fmul z29.s, z13.s, z13.s + __ sve_fsub(z14, __ S, z30, z1); // fsub z14.s, z30.s, z1.s + __ sve_sqadd(z28, __ D, z3, z3); // sqadd z28.d, z3.d, z3.d + __ sve_sqsub(z9, __ B, z25, z9); // sqsub z9.b, z25.b, z9.b + __ sve_uqadd(z26, __ B, z10, z14); // uqadd z26.b, z10.b, z14.b + __ sve_uqsub(z20, __ D, z26, z7); // uqsub z20.d, z26.d, z7.d + __ sve_abs(z20, __ D, p4, z6); // abs z20.d, p4/m, z6.d + __ sve_add(z13, __ H, p0, z29); // add z13.h, p0/m, z13.h, z29.h + __ sve_and(z9, __ B, p0, z1); // and z9.b, p0/m, z9.b, z1.b + __ sve_asr(z27, __ B, p6, z15); // asr z27.b, p6/m, z27.b, z15.b + __ sve_bic(z4, __ D, p7, z17); // bic z4.d, p7/m, z4.d, z17.d + __ sve_clz(z2, __ B, p0, z24); // clz z2.b, p0/m, z24.b + __ sve_cnt(z26, __ B, p7, z13); // cnt z26.b, p7/m, z13.b + __ sve_eor(z22, __ D, p3, z16); // eor z22.d, p3/m, z22.d, z16.d + __ sve_lsl(z17, __ D, p1, z11); // lsl z17.d, p1/m, z17.d, z11.d + __ sve_lsr(z16, __ B, p0, z16); // lsr z16.b, p0/m, z16.b, z16.b + __ sve_mul(z28, __ D, p1, z23); // mul z28.d, p1/m, z28.d, z23.d + __ sve_neg(z28, __ S, p4, z10); // neg z28.s, p4/m, z10.s + __ sve_not(z17, __ S, p7, z7); // not z17.s, p7/m, z7.s + __ sve_orr(z4, __ H, p3, z24); // orr z4.h, p3/m, z4.h, z24.h + __ sve_rbit(z9, __ B, p2, z11); // rbit z9.b, p2/m, z11.b + __ sve_revb(z4, __ S, p5, z22); // revb z4.s, p5/m, z22.s + __ sve_smax(z4, __ H, p0, z15); // smax z4.h, p0/m, z4.h, z15.h + __ sve_smin(z4, __ D, p7, z26); // smin z4.d, p7/m, z4.d, z26.d + __ sve_umax(z5, __ H, p5, z26); // umax z5.h, p5/m, z5.h, z26.h + __ sve_umin(z31, __ B, p0, z25); // umin z31.b, p0/m, z31.b, z25.b + __ sve_sub(z8, __ S, p1, z3); // sub z8.s, p1/m, z8.s, z3.s + __ sve_fabs(z7, __ D, p6, z24); // fabs z7.d, p6/m, z24.d + __ sve_fadd(z24, __ S, p7, z17); // fadd z24.s, p7/m, z24.s, z17.s + __ sve_fdiv(z10, __ S, p3, z30); // fdiv z10.s, p3/m, z10.s, z30.s + __ sve_fmax(z8, __ S, p6, z29); // fmax z8.s, p6/m, z8.s, z29.s + __ sve_fmin(z31, __ D, p5, z31); // fmin z31.d, p5/m, z31.d, z31.d + __ sve_fmul(z0, __ D, p5, z7); // fmul z0.d, p5/m, z0.d, z7.d + __ sve_fneg(z29, __ S, p6, z22); // fneg z29.s, p6/m, z22.s + __ sve_frintm(z29, __ S, p6, z20); // frintm z29.s, p6/m, z20.s + __ sve_frintn(z6, __ S, p4, z18); // frintn z6.s, p4/m, z18.s + __ sve_frintp(z26, __ S, p5, z8); // frintp z26.s, p5/m, z8.s + __ sve_fsqrt(z19, __ S, p2, z28); // fsqrt z19.s, p2/m, z28.s + __ sve_fsub(z17, __ D, p1, z30); // fsub z17.d, p1/m, z17.d, z30.d + __ sve_fmad(z24, __ S, p7, z14, z17); // fmad z24.s, p7/m, z14.s, z17.s + __ sve_fmla(z19, __ D, p2, z26, z11); // fmla z19.d, p2/m, z26.d, z11.d + __ sve_fmls(z0, __ D, p2, z15, z28); // fmls z0.d, p2/m, z15.d, z28.d + __ sve_fmsb(z23, __ D, p5, z28, z23); // fmsb z23.d, p5/m, z28.d, z23.d + __ sve_fnmad(z29, __ S, p6, z0, z27); // fnmad z29.s, p6/m, z0.s, z27.s + __ sve_fnmsb(z23, __ S, p3, z12, z4); // fnmsb z23.s, p3/m, z12.s, z4.s + __ sve_fnmla(z31, __ S, p6, z23, z20); // fnmla z31.s, p6/m, z23.s, z20.s + __ sve_fnmls(z2, __ D, p7, z29, z0); // fnmls z2.d, p7/m, z29.d, z0.d + __ sve_mla(z23, __ H, p0, z4, z5); // mla z23.h, p0/m, z4.h, z5.h + __ sve_mls(z28, __ H, p3, z17, z13); // mls z28.h, p3/m, z17.h, z13.h + __ sve_and(z8, z10, z8); // and z8.d, z10.d, z8.d + __ sve_eor(z19, z0, z29); // eor z19.d, z0.d, z29.d + __ sve_orr(z16, z13, z23); // orr z16.d, z13.d, z23.d + __ sve_bic(z23, z30, z13); // bic z23.d, z30.d, z13.d + __ sve_uzp1(z25, __ H, z22, z0); // uzp1 z25.h, z22.h, z0.h + __ sve_uzp2(z25, __ H, z30, z11); // uzp2 z25.h, z30.h, z11.h + __ sve_fabd(z14, __ S, p5, z22); // fabd z14.s, p5/m, z14.s, z22.s + __ sve_bext(z5, __ H, z18, z0); // bext z5.h, z18.h, z0.h + __ sve_bdep(z9, __ D, z2, z3); // bdep z9.d, z2.d, z3.d + __ sve_eor3(z14, z4, z29); // eor3 z14.d, z14.d, z4.d, z29.d + __ sve_sqadd(z14, __ D, p5, z4); // sqadd z14.d, p5/m, z14.d, z4.d + __ sve_sqsub(z27, __ S, p3, z22); // sqsub z27.s, p3/m, z27.s, z22.s + __ sve_uqadd(z31, __ S, p6, z11); // uqadd z31.s, p6/m, z31.s, z11.s + __ sve_uqsub(z12, __ B, p4, z28); // uqsub z12.b, p4/m, z12.b, z28.b // SVEReductionOp - __ sve_andv(v12, __ B, p4, z28); // andv b12, p4, z28.b - __ sve_orv(v28, __ D, p4, z4); // orv d28, p4, z4.d - __ sve_eorv(v6, __ S, p0, z15); // eorv s6, p0, z15.s - __ sve_smaxv(v1, __ S, p5, z18); // smaxv s1, p5, z18.s - __ sve_sminv(v2, __ H, p2, z4); // sminv h2, p2, z4.h - __ sve_umaxv(v11, __ S, p2, z28); // umaxv s11, p2, z28.s - __ sve_uminv(v3, __ H, p5, z31); // uminv h3, p5, z31.h - __ sve_fminv(v24, __ S, p5, z15); // fminv s24, p5, z15.s - __ sve_fmaxv(v6, __ S, p3, z8); // fmaxv s6, p3, z8.s - __ sve_fadda(v21, __ D, p7, z4); // fadda d21, p7, d21, z4.d - __ sve_uaddv(v24, __ B, p5, z6); // uaddv d24, p5, z6.b + __ sve_andv(v28, __ D, p4, z4); // andv d28, p4, z4.d + __ sve_orv(v6, __ S, p0, z15); // orv s6, p0, z15.s + __ sve_eorv(v1, __ S, p5, z18); // eorv s1, p5, z18.s + __ sve_smaxv(v2, __ H, p2, z4); // smaxv h2, p2, z4.h + __ sve_sminv(v11, __ S, p2, z28); // sminv s11, p2, z28.s + __ sve_umaxv(v3, __ H, p5, z31); // umaxv h3, p5, z31.h + __ sve_uminv(v24, __ H, p5, z15); // uminv h24, p5, z15.h + __ sve_fminv(v6, __ S, p3, z8); // fminv s6, p3, z8.s + __ sve_fmaxv(v21, __ D, p7, z4); // fmaxv d21, p7, z4.d + __ sve_fadda(v24, __ S, p5, z6); // fadda s24, p5, s24, z6.s + __ sve_uaddv(v4, __ D, p2, z9); // uaddv d4, p2, z9.d // AddWideNEONOp - __ saddwv(v4, v5, __ T8H, v6, __ T8B); // saddw v4.8H, v5.8H, v6.8B - __ saddwv2(v10, v11, __ T8H, v12, __ T16B); // saddw2 v10.8H, v11.8H, v12.16B - __ saddwv(v9, v10, __ T4S, v11, __ T4H); // saddw v9.4S, v10.4S, v11.4H - __ saddwv2(v25, v26, __ T4S, v27, __ T8H); // saddw2 v25.4S, v26.4S, v27.8H - __ saddwv(v10, v11, __ T2D, v12, __ T2S); // saddw v10.2D, v11.2D, v12.2S - __ saddwv2(v5, v6, __ T2D, v7, __ T4S); // saddw2 v5.2D, v6.2D, v7.4S - __ uaddwv(v31, v0, __ T8H, v1, __ T8B); // uaddw v31.8H, v0.8H, v1.8B - __ uaddwv2(v22, v23, __ T8H, v24, __ T16B); // uaddw2 v22.8H, v23.8H, v24.16B - __ uaddwv(v25, v26, __ T4S, v27, __ T4H); // uaddw v25.4S, v26.4S, v27.4H - __ uaddwv2(v15, v16, __ T4S, v17, __ T8H); // uaddw2 v15.4S, v16.4S, v17.8H - __ uaddwv(v3, v4, __ T2D, v5, __ T2S); // uaddw v3.2D, v4.2D, v5.2S - __ uaddwv2(v18, v19, __ T2D, v20, __ T4S); // uaddw2 v18.2D, v19.2D, v20.4S + __ saddwv(v10, v11, __ T8H, v12, __ T8B); // saddw v10.8H, v11.8H, v12.8B + __ saddwv2(v5, v6, __ T8H, v7, __ T16B); // saddw2 v5.8H, v6.8H, v7.16B + __ saddwv(v31, v0, __ T4S, v1, __ T4H); // saddw v31.4S, v0.4S, v1.4H + __ saddwv2(v22, v23, __ T4S, v24, __ T8H); // saddw2 v22.4S, v23.4S, v24.8H + __ saddwv(v25, v26, __ T2D, v27, __ T2S); // saddw v25.2D, v26.2D, v27.2S + __ saddwv2(v15, v16, __ T2D, v17, __ T4S); // saddw2 v15.2D, v16.2D, v17.4S + __ uaddwv(v3, v4, __ T8H, v5, __ T8B); // uaddw v3.8H, v4.8H, v5.8B + __ uaddwv2(v18, v19, __ T8H, v20, __ T16B); // uaddw2 v18.8H, v19.8H, v20.16B + __ uaddwv(v14, v15, __ T4S, v16, __ T4H); // uaddw v14.4S, v15.4S, v16.4H + __ uaddwv2(v10, v11, __ T4S, v12, __ T8H); // uaddw2 v10.4S, v11.4S, v12.8H + __ uaddwv(v2, v3, __ T2D, v4, __ T2S); // uaddw v2.2D, v3.2D, v4.2S + __ uaddwv2(v10, v11, __ T2D, v12, __ T4S); // uaddw2 v10.2D, v11.2D, v12.4S __ bind(forth); @@ -1463,312 +1469,313 @@ 0x9101a1a0, 0xb10a5cc8, 0xd10810aa, 0xf10fd061, 0x120cb166, 0x321764bc, 0x52174681, 0x720c0227, 0x9241018e, 0xb25a2969, 0xd278b411, 0xf26aad01, - 0x14000000, 0x17ffffd7, 0x140004c9, 0x94000000, - 0x97ffffd4, 0x940004c6, 0x3400000a, 0x34fffa2a, - 0x3400986a, 0x35000008, 0x35fff9c8, 0x35009808, - 0xb400000b, 0xb4fff96b, 0xb40097ab, 0xb500001d, - 0xb5fff91d, 0xb500975d, 0x10000013, 0x10fff8b3, - 0x100096f3, 0x90000013, 0x36300016, 0x3637f836, - 0x36309676, 0x3758000c, 0x375ff7cc, 0x3758960c, + 0x14000000, 0x17ffffd7, 0x140004cb, 0x94000000, + 0x97ffffd4, 0x940004c8, 0x3400000a, 0x34fffa2a, + 0x340098aa, 0x35000008, 0x35fff9c8, 0x35009848, + 0xb400000b, 0xb4fff96b, 0xb40097eb, 0xb500001d, + 0xb5fff91d, 0xb500979d, 0x10000013, 0x10fff8b3, + 0x10009733, 0x90000013, 0x36300016, 0x3637f836, + 0x363096b6, 0x3758000c, 0x375ff7cc, 0x3758964c, 0x128313a0, 0x528a32c7, 0x7289173b, 0x92ab3acc, 0xd2a0bf94, 0xf2c285e8, 0x9358722f, 0x330e652f, 0x53067f3b, 0x93577c53, 0xb34a1aac, 0xd35a4016, 0x13946c63, 0x93c3dbc8, 0x54000000, 0x54fff5a0, - 0x540093e0, 0x54000001, 0x54fff541, 0x54009381, - 0x54000002, 0x54fff4e2, 0x54009322, 0x54000002, - 0x54fff482, 0x540092c2, 0x54000003, 0x54fff423, - 0x54009263, 0x54000003, 0x54fff3c3, 0x54009203, - 0x54000004, 0x54fff364, 0x540091a4, 0x54000005, - 0x54fff305, 0x54009145, 0x54000006, 0x54fff2a6, - 0x540090e6, 0x54000007, 0x54fff247, 0x54009087, - 0x54000008, 0x54fff1e8, 0x54009028, 0x54000009, - 0x54fff189, 0x54008fc9, 0x5400000a, 0x54fff12a, - 0x54008f6a, 0x5400000b, 0x54fff0cb, 0x54008f0b, - 0x5400000c, 0x54fff06c, 0x54008eac, 0x5400000d, - 0x54fff00d, 0x54008e4d, 0x5400000e, 0x54ffefae, - 0x54008dee, 0x5400000f, 0x54ffef4f, 0x54008d8f, + 0x54009420, 0x54000001, 0x54fff541, 0x540093c1, + 0x54000002, 0x54fff4e2, 0x54009362, 0x54000002, + 0x54fff482, 0x54009302, 0x54000003, 0x54fff423, + 0x540092a3, 0x54000003, 0x54fff3c3, 0x54009243, + 0x54000004, 0x54fff364, 0x540091e4, 0x54000005, + 0x54fff305, 0x54009185, 0x54000006, 0x54fff2a6, + 0x54009126, 0x54000007, 0x54fff247, 0x540090c7, + 0x54000008, 0x54fff1e8, 0x54009068, 0x54000009, + 0x54fff189, 0x54009009, 0x5400000a, 0x54fff12a, + 0x54008faa, 0x5400000b, 0x54fff0cb, 0x54008f4b, + 0x5400000c, 0x54fff06c, 0x54008eec, 0x5400000d, + 0x54fff00d, 0x54008e8d, 0x5400000e, 0x54ffefae, + 0x54008e2e, 0x5400000f, 0x54ffef4f, 0x54008dcf, 0xd40658e1, 0xd4014d22, 0xd4046543, 0xd4273f60, 0xd44cad80, 0xd503201f, 0xd503203f, 0xd503205f, 0xd503209f, 0xd50320bf, 0xd503219f, 0xd50323bf, 0xd503239f, 0xd50321df, 0xd50323ff, 0xd50323df, 0xd503211f, 0xd503233f, 0xd503231f, 0xd503215f, 0xd503237f, 0xd503235f, 0xd69f03e0, 0xd6bf03e0, - 0xd5033fdf, 0xd50330ff, 0xd503207f, 0xd50320ff, - 0xd5033e9f, 0xd50332bf, 0xd61f0200, 0xd63f0280, - 0xdac123ea, 0xdac127fb, 0xdac12be8, 0xdac12fe0, - 0xdac133e1, 0xdac137f5, 0xdac13bf1, 0xdac13ffd, - 0xdac147fd, 0xd61f0b9f, 0xd61f0c3f, 0xd63f0aff, - 0xd63f0ebf, 0xd51b4434, 0xd51b4216, 0xd53b443b, - 0xd53b4213, 0xd53b00eb, 0xd53b0030, 0xdac143e6, - 0xc8117c80, 0xc80afed8, 0xc85f7e6a, 0xc85ffca1, - 0xc89ffd1e, 0xc8dffe2c, 0x88097cee, 0x8801fe05, - 0x885f7d82, 0x885ffd8a, 0x889fff83, 0x88dfff4e, - 0x481e7dca, 0x4815fd2d, 0x485f7f76, 0x485ffe7c, - 0x489fffcb, 0x48dffc53, 0x08027c37, 0x0800fe0c, - 0x085f7ded, 0x085ffeb1, 0x089ffd6d, 0x08dffd1e, - 0xc87f3578, 0xc87feaa1, 0xc83b506d, 0xc82c87a6, - 0x887f1166, 0x887f93d0, 0x883e32a4, 0x883bf12f, - 0xf80011f9, 0xb81b1022, 0x381ea354, 0x79002fd7, - 0xf85cf39a, 0xb8580309, 0x385e218c, 0x784051e1, - 0x389e11d8, 0x789fa1f8, 0x79c01865, 0xb881131b, - 0xfc5dd3ad, 0xbc5d1137, 0xfc00900b, 0xbc181015, - 0xf818ec7d, 0xb81b8c91, 0x381efc40, 0x78007c3d, - 0xf857beb0, 0xb8413dd4, 0x385fddd6, 0x78409e2f, - 0x389eddea, 0x789e7d94, 0x78de3d55, 0xb8805c13, - 0xfc5cadc0, 0xbc428c23, 0xfc1a2dc4, 0xbc1caf92, - 0xf81475f6, 0xb81f95d1, 0x381e757e, 0x78014561, - 0xf8402436, 0xb85896e2, 0x385f4763, 0x785db4f0, - 0x3880374f, 0x789e25e7, 0x78dd0563, 0xb88166f9, - 0xfc529540, 0xbc4374d3, 0xfc1166ae, 0xbc1ba6c0, - 0xf820ea7b, 0xb82d68c8, 0x38367a04, 0x782f4b59, - 0xf878c8a4, 0xb8674a24, 0x386b78f1, 0x78776bc0, - 0x38a15aca, 0x78bedbd5, 0x78fcd94b, 0xb8aa4a7c, - 0xfc6ecbbe, 0xbc65d8a8, 0xfc2de919, 0xbc3a7b11, - 0xf91f1193, 0xb91ed5f7, 0x391ec9bd, 0x79182ceb, - 0xf95d4b0a, 0xb9581010, 0x395fc034, 0x795fb221, - 0x399d8731, 0x799efb3b, 0x79dd1a2e, 0xb998e4ea, - 0xfd583723, 0xbd5ea12c, 0xfd18dc38, 0xbd1b0e83, - 0x58ffda82, 0x1800001d, 0xf885d1c0, 0xd8ffda20, - 0xf8a77820, 0xf9980220, 0x1a030301, 0x3a140311, - 0x5a0d000b, 0x7a07015c, 0x9a1001e4, 0xba140182, - 0xda0d01bd, 0xfa0c00ce, 0x0b31f194, 0x2b206d7b, - 0xcb29f027, 0x6b210f63, 0x8b2cb34d, 0xab2a88b1, - 0xcb2f511e, 0xeb3332f3, 0x3a4533aa, 0x7a4d312b, - 0xba442146, 0xfa42818c, 0x3a466a02, 0x7a4b68ed, - 0xba4a9b6b, 0xfa4dd86d, 0x1a8a637a, 0x1a9cd6aa, - 0x5a9bd137, 0x5a8fd7aa, 0x9a95233e, 0x9a95c620, - 0xda9422b0, 0xda8397d3, 0x5ac00173, 0x5ac00418, - 0x5ac00b3b, 0x5ac0106e, 0x5ac0162e, 0xdac001e7, - 0xdac00798, 0xdac00b31, 0xdac00f42, 0xdac010bc, - 0xdac01759, 0xdac1021b, 0xdac104d1, 0xdac10995, - 0xdac10c80, 0xdac1136c, 0xdac11791, 0xdac1185c, - 0xdac11d51, 0xd71f09ee, 0xd71f0dc3, 0xd73f0b2f, - 0xd73f0e6e, 0x1ac40a05, 0x1ac40f3a, 0x1acc2042, - 0x1ac8263d, 0x1ac42867, 0x1ada2c99, 0x9ad10899, - 0x9ad10f40, 0x9ad521f7, 0x9adb263c, 0x9ac0286a, - 0x9ac92f27, 0x9bdd7de6, 0x9b427d4f, 0x1b0b2cf1, - 0x1b1ddcf7, 0x9b0b2f6e, 0x9b0cbf04, 0x9b2b728e, - 0x9b2cdd6d, 0x9bae275e, 0x9ba7954d, 0x7ec315fe, - 0x1ef0098c, 0x1ef21bff, 0x1ef02ab3, 0x1ef5394f, - 0x1efc4942, 0x1eff5bc7, 0x1ee28832, 0x7ea3d546, - 0x1e270979, 0x1e201981, 0x1e3d2a63, 0x1e263ae6, - 0x1e3b4b80, 0x1e2758a2, 0x1e39899d, 0x7ef8d58d, - 0x1e720913, 0x1e751b56, 0x1e622a74, 0x1e683ade, - 0x1e754a76, 0x1e755a4c, 0x1e638a06, 0x1fc373a3, - 0x1f0a35cf, 0x1f0aea4c, 0x1f2f74e7, 0x1f2032e0, - 0x1f4d21d8, 0x1f49d0ef, 0x1f7f43b3, 0x1f705522, - 0x1e20409e, 0x1e20c361, 0x1e214319, 0x1e21c2ae, - 0x1e22c0cd, 0x1e23c32c, 0x1ee243d9, 0x1e6042bc, - 0x1e60c2f0, 0x1e6143a5, 0x1e61c276, 0x1e62428d, - 0x1ee1c393, 0x1e3800d1, 0x9e3800ed, 0x1e78035c, - 0x9e7800d1, 0x1e220081, 0x9e22028e, 0x1e6202a7, - 0x9e6202fb, 0x1e24028d, 0x9e64039e, 0x1e3002aa, - 0x9e700225, 0x1e2601cb, 0x9e6602ad, 0x1e2701db, - 0x9e6702e4, 0x1e3e2300, 0x1e6e2180, 0x1e202228, - 0x1e602388, 0x29021b40, 0x297c78c0, 0x69660970, - 0xa908018f, 0xa9427ae7, 0x29a03cfa, 0x29fc3d4b, - 0x69c84033, 0xa988240e, 0xa9fa0d9b, 0x28a02d88, - 0x28c8408a, 0x68f87a6a, 0xa8ba09f8, 0xa8c52a18, - 0x280257be, 0x28727948, 0xa83868de, 0xa8440a98, - 0x0c40733f, 0x4cdfa1e5, 0x0ccd6cea, 0x4cdf260d, - 0x0d40c227, 0x4ddfcb30, 0x0dc7cc6b, 0x4c408ced, - 0x0cdf8769, 0x4d60c346, 0x0dffca17, 0x4de8cda6, - 0x4cda4834, 0x0c4049ef, 0x4d40e6dd, 0x4ddfe946, - 0x0dcfeccf, 0x4cdf0546, 0x0cc7006b, 0x0d60e32c, - 0x0dffe5eb, 0x0dfce8de, 0x0e31bb9b, 0x4e31bbbc, - 0x0e71b841, 0x4e71bbbc, 0x4eb1b841, 0x0e30aab4, - 0x4e30abdd, 0x0e70aa30, 0x4e70a9cd, 0x4eb0a96a, - 0x6e30fbdd, 0x0e31abdd, 0x2e31aa93, 0x4e31aaf6, - 0x6e31a96a, 0x0e71a8a4, 0x2e71a81f, 0x4e71aad5, - 0x6e71a928, 0x4eb1a81f, 0x6eb1aa93, 0x6eb0f96a, - 0x7e30fbbc, 0x7e70f862, 0x7eb0fb59, 0x7ef0f8c5, - 0x0ea0c883, 0x4ea0c928, 0x4ee0caf6, 0x2ea0ca93, - 0x6ea0c9cd, 0x6ee0c8c5, 0x0ea0dbdd, 0x4ea0db38, - 0x4ee0dad5, 0x0ea0eb7a, 0x4ea0eb38, 0x4ee0e883, - 0x2ea0db38, 0x6ea0db7a, 0x6ee0db17, 0x0e20ba0f, - 0x4e20bad5, 0x0e60b883, 0x4e60bb38, 0x0ea0b928, - 0x4ea0bb59, 0x4ee0bab4, 0x0ea0fa30, 0x4ea0fa51, - 0x4ee0f862, 0x0ef8f841, 0x4ef8f820, 0x2ea0fb38, - 0x6ea0f8a4, 0x6ee0f883, 0x2ef8f9ac, 0x6ef8f81f, - 0x2ea1fbbc, 0x6ea1f96a, 0x6ee1fb7a, 0x2ef9f862, - 0x6ef9f9ac, 0x2e205a72, 0x6e20581f, 0x0e231c41, - 0x4e2f1dcd, 0x0ebf1fdd, 0x4ea21c20, 0x2e351e93, - 0x6e2e1dac, 0x0e338651, 0x4e3886f6, 0x0e6f85cd, - 0x4e7e87bc, 0x0ea087fe, 0x4ea1841f, 0x4ee38441, - 0x0e3c0f7a, 0x4e3e0fbc, 0x0e660ca4, 0x4e600ffe, - 0x0ea60ca4, 0x4ea80ce6, 0x4ee00ffe, 0x2e3c0f7a, - 0x6e340e72, 0x2e6b0d49, 0x6e6a0d28, 0x2eae0dac, - 0x6ea20c20, 0x6ef60eb4, 0x0e23d441, 0x4e3ad738, - 0x4e64d462, 0x0e421420, 0x4e4b1549, 0x2e3a8738, - 0x6e3c877a, 0x2e728630, 0x6e6087fe, 0x2ea58483, - 0x6eac856a, 0x6ef98717, 0x0e2c2d6a, 0x4e262ca4, - 0x0e742e72, 0x4e642c62, 0x0ead2d8b, 0x4eaa2d28, - 0x4eec2d6a, 0x2e312e0f, 0x6e332e51, 0x2e642c62, - 0x6e6c2d6a, 0x2eae2dac, 0x6eae2dac, 0x6ef12e0f, - 0x0eafd5cd, 0x4ea4d462, 0x4ee9d507, 0x0ed616b4, - 0x4edc177a, 0x0e329e30, 0x4e269ca4, 0x0e649c62, - 0x4e669ca4, 0x0eae9dac, 0x4eb49e72, 0x2eb7d6d5, - 0x6eb2d630, 0x6ef4d672, 0x2ecd158b, 0x6ed716d5, - 0x2e39d717, 0x6e2ed5ac, 0x6e7cd77a, 0x2e591717, - 0x6e5e17bc, 0x2e30ddee, 0x6e2ddd8b, 0x6e7adf38, - 0x2e431c41, 0x6e4e1dac, 0x0e61941f, 0x4e6c956a, - 0x0eb29630, 0x4ea99507, 0x0e24cc62, 0x4e25cc83, - 0x4e6fcdcd, 0x0e550e93, 0x4e530e51, 0x2e729630, - 0x6e659483, 0x2ea39441, 0x6ead958b, 0x0ea0cffe, - 0x4ea7ccc5, 0x4eeacd28, 0x0ed10e0f, 0x4edf0fdd, - 0x2e20fffe, 0x6e22fc20, 0x6e76feb4, 0x2e493d07, - 0x6e563eb4, 0x0e396717, 0x4e3e67bc, 0x0e7766d5, - 0x4e7d679b, 0x0ebb6759, 0x4ea764c5, 0x2e236441, - 0x6e396717, 0x2e726630, 0x6e61641f, 0x2ea764c5, - 0x6eae65ac, 0x0e2ba549, 0x4e3ea7bc, 0x0e71a60f, - 0x4e7fa7dd, 0x0eb8a6f6, 0x4ea1a41f, 0x0e35f693, - 0x4e21f41f, 0x4e67f4c5, 0x0e5035ee, 0x4e543672, - 0x0e216c1f, 0x4e346e72, 0x0e7d6f9b, 0x4e766eb4, - 0x0eb26e30, 0x4eae6dac, 0x2e2d6d8b, 0x6e2b6d49, - 0x2e686ce6, 0x6e606ffe, 0x2eb36e51, 0x6ebd6f9b, - 0x0e3eafbc, 0x4e20affe, 0x0e69ad07, 0x4e6cad6a, - 0x0eb6aeb4, 0x4eacad6a, 0x2e26aca4, 0x6e3aaf38, - 0x2e73ae51, 0x6e73ae51, 0x2eb8aef6, 0x6ea5ac83, - 0x2e3fa7dd, 0x6e31a60f, 0x2e78a6f6, 0x6e75a693, - 0x2eb5a693, 0x6eb8a6f6, 0x0e64b462, 0x4e71b60f, - 0x0ea8b4e6, 0x4eaeb5ac, 0x0e322630, 0x4e2d258b, - 0x0e6f25cd, 0x4e792717, 0x0ea32441, 0x4ea027fe, - 0x0eb5f693, 0x4ea7f4c5, 0x4ef3f651, 0x0ec43462, - 0x4ed23630, 0x2eb8eef6, 0x6eafedcd, 0x6eeced6a, - 0x2ed72ed5, 0x6edf2fdd, 0x0fa810e6, 0x4fa38841, - 0x4fc1100f, 0x0fab5149, 0x4f8688a4, 0x4fcf59cd, - 0x2f859083, 0x4f8d898b, 0x6fce99ac, 0x0f41800f, - 0x4f6b8949, 0x0f8d818b, 0x4f838841, 0x0e343672, - 0x4e223420, 0x0e7b3759, 0x4e7c377a, 0x0eb93717, - 0x4ea43462, 0x4ef43672, 0x0e2e3dac, 0x4e263ca4, - 0x0e7e3fbc, 0x4e603ffe, 0x0ebf3fdd, 0x4eb23e30, - 0x4efd3f9b, 0x2e288ce6, 0x6e2b8d49, 0x2e7f8fdd, - 0x6e748e72, 0x2ea98d07, 0x6ea68ca4, 0x6ee98d07, - 0x2e31360f, 0x6e2b3549, 0x2e793717, 0x6e6a3528, - 0x2ea43462, 0x6ebe37bc, 0x6ef736d5, 0x2e213c1f, - 0x6e273cc5, 0x2e7d3f9b, 0x6e623c20, 0x2eb33e51, - 0x6eb13e0f, 0x6ee63ca4, 0x0e3ce77a, 0x4e2ae528, - 0x4e7ee7bc, 0x2eb8e6f6, 0x6ebde79b, 0x6efde79b, - 0x2e3be759, 0x6e39e717, 0x6e62e420, 0x65d220c2, - 0x659029f2, 0x65903ca3, 0x65d13683, 0x65913173, - 0x65d320cf, 0x25cb83c6, 0x254c0fbb, 0x251e0308, - 0x25473a05, 0x25943096, 0x259d9270, 0x2423d187, - 0x242786fa, 0x24f0f1b9, 0x24e42043, 0xba5fd3e3, - 0x3a5f03e5, 0xfa411be4, 0x7a42cbe2, 0x93df03ff, - 0xc820ffff, 0x8822fc7f, 0xc8247cbf, 0x88267fff, - 0x4e010fe0, 0x5e040420, 0x4e081fe1, 0x4e0c1fe1, - 0x4e0a1fe1, 0x4e071fe1, 0x4e042c20, 0x4e062c20, - 0x4e052c20, 0x4e083c20, 0x0e0c3c20, 0x0e0a3c20, - 0x0e073c20, 0x9eae0020, 0x0f03f409, 0x6f03f40e, - 0x4cc0ac3f, 0x0ea1b820, 0x0ef9b820, 0x4ef9b820, - 0x4e21c862, 0x0e79c862, 0x4e79c862, 0x4e61b8a4, - 0x0e79b8a4, 0x4e79b8a4, 0x05a08020, 0x05104fe0, - 0x05505001, 0x05906fe2, 0x05d03005, 0x05101fea, - 0x05901feb, 0x0590cc0b, 0x0590de0b, 0x04b0e3e0, - 0x0470e7e1, 0x042f9c20, 0x043f9c35, 0x047f9c20, - 0x04ff9c20, 0x04299420, 0x04319160, 0x0461943e, - 0x04a19020, 0x04038100, 0x040381a0, 0x040387e1, - 0x04438be2, 0x04c38fe3, 0x040181e0, 0x04018100, - 0x04018621, 0x04418b22, 0x04418822, 0x04818c23, - 0x040081e0, 0x04008120, 0x04008761, 0x04008621, - 0x04408822, 0x04808c23, 0x042053ff, 0x047f5401, - 0x25208028, 0x2538cfe0, 0x2578d001, 0x25b8efe2, - 0x25f8f007, 0x2538dfea, 0x25b8dfeb, 0xa400a3e0, - 0xa420a7e0, 0xa4484be0, 0xa467afe0, 0xa4a8a7ea, - 0xa547a814, 0xa4084ffe, 0xa55c53e0, 0xa5e1540b, - 0xe400fbf6, 0xe408ffff, 0xe420e7e0, 0xe4484be0, - 0xe460efe0, 0xe547e400, 0xe4014be0, 0xe4a84fe0, - 0xe5f15000, 0x858043e0, 0x85a043ff, 0xe59f5d08, - 0x0420e3e9, 0x0460e3ea, 0x04a0e3eb, 0x04e0e3ec, - 0x25104042, 0x25104871, 0x25904861, 0x25904c92, - 0x05344020, 0x05744041, 0x05b44062, 0x05f44083, - 0x252c8840, 0x253c1420, 0x25681572, 0x25a21ce3, - 0x25ea1e34, 0x253c0421, 0x25680572, 0x25a20ce3, - 0x25ea0e34, 0x0522c020, 0x05e6c0a4, 0x2401a001, - 0x2443a051, 0x24858881, 0x24c78cd1, 0x24850891, - 0x24c70cc1, 0x250f9001, 0x25508051, 0x25802491, - 0x25df28c1, 0x25850c81, 0x251e10d1, 0x65816001, - 0x65c36051, 0x65854891, 0x65c74cc1, 0x05733820, - 0x05b238a4, 0x05f138e6, 0x0570396a, 0x65d0a001, - 0x65d6a443, 0x65d4a826, 0x6594ac26, 0x6554ac26, - 0x6556ac26, 0x6552ac26, 0x65cbac85, 0x65caac01, - 0x6589ac85, 0x6588ac01, 0x65c9ac85, 0x65c8ac01, - 0x65dea833, 0x659ca509, 0x65d8a801, 0x65dcac01, - 0x655cb241, 0x0520a1e0, 0x0521a601, 0x052281e0, - 0x05238601, 0x04a14026, 0x042244a6, 0x046344a6, - 0x04a444a6, 0x04e544a7, 0x0568aca7, 0x05b23230, - 0x05302a30, 0x05702a30, 0x05b02a30, 0x05f02a30, - 0x853040af, 0xc5b040af, 0xe57080af, 0xe5b080af, - 0x25034440, 0x254054c4, 0x25034640, 0x25415a05, - 0x25834440, 0x25c54489, 0x250b5d3a, 0x2550dc20, - 0x2518e3e1, 0x2518e021, 0x2518e0a1, 0x2518e121, - 0x2518e1a1, 0x2558e3e2, 0x2558e042, 0x2558e0c2, - 0x2558e142, 0x2598e3e3, 0x2598e063, 0x2598e0e3, - 0x2598e163, 0x25d8e3e4, 0x25d8e084, 0x25d8e104, - 0x25d8e184, 0x2518e407, 0x05214800, 0x05614800, - 0x05a14800, 0x05e14800, 0x05214c00, 0x05614c00, - 0x05a14c00, 0x05e14c00, 0x05304001, 0x05314001, - 0x05a18610, 0x05e18610, 0x0420bc31, 0x05271e11, - 0x6545e891, 0x6585e891, 0x65c5e891, 0x6545c891, - 0x6585c891, 0x65c5c891, 0x052c8020, 0x056c8020, - 0x05ac8020, 0x05ec8020, 0x45b0c210, 0x45f1c231, - 0x1e601000, 0x1e603000, 0x1e621000, 0x1e623000, - 0x1e641000, 0x1e643000, 0x1e661000, 0x1e663000, - 0x1e681000, 0x1e683000, 0x1e6a1000, 0x1e6a3000, - 0x1e6c1000, 0x1e6c3000, 0x1e6e1000, 0x1e6e3000, - 0x1e701000, 0x1e703000, 0x1e721000, 0x1e723000, - 0x1e741000, 0x1e743000, 0x1e761000, 0x1e763000, - 0x1e781000, 0x1e783000, 0x1e7a1000, 0x1e7a3000, - 0x1e7c1000, 0x1e7c3000, 0x1e7e1000, 0x1e7e3000, - 0xf8268290, 0xf82d028c, 0xf8281299, 0xf8332160, - 0xf8383286, 0xf83f520e, 0xf82640e0, 0xf82f7353, - 0xf82962ea, 0xf8b58396, 0xf8a201e3, 0xf8b310f4, - 0xf8a420fd, 0xf8a03209, 0xf8b45097, 0xf8b042ea, - 0xf8ab70d9, 0xf8bf61b0, 0xf8f7802c, 0xf8ee02a9, - 0xf8f011fa, 0xf8e421e4, 0xf8e833c6, 0xf8e4523d, - 0xf8fd413a, 0xf8ef7162, 0xf8fd60e3, 0xf86182bb, - 0xf870010e, 0xf8701336, 0xf86522b4, 0xf8703217, - 0xf87e5294, 0xf8604264, 0xf8787284, 0xf8646358, - 0xb8338102, 0xb828030e, 0xb83012df, 0xb824203f, - 0xb82a3194, 0xb82050e9, 0xb8384090, 0xb83b7146, - 0xb83b61b8, 0xb8b082df, 0xb8b603f4, 0xb8bd11c9, - 0xb8b42287, 0xb8bc3169, 0xb8ae528c, 0xb8a14138, - 0xb8b3726d, 0xb8b060b0, 0xb8e08183, 0xb8e801ef, - 0xb8f011e4, 0xb8fe2005, 0xb8ea3376, 0xb8e35120, - 0xb8f3415d, 0xb8f87284, 0xb8e763b8, 0xb86e8175, - 0xb87b01ed, 0xb87f11d1, 0xb863221e, 0xb87630f4, - 0xb8745023, 0xb87a4133, 0xb87072b1, 0xb8606044, - 0xce262dd8, 0xce1179d5, 0xce638c6c, 0xce83c537, - 0xce73807c, 0xce7a84f7, 0xcec081d5, 0xce7a8905, - 0x25a0d245, 0x2521c3f1, 0x05808909, 0x05400d2c, - 0x0500154b, 0x25a0c91f, 0x2561db50, 0x0582d157, - 0x054026a8, 0x05001eca, 0x25a0c0b6, 0x25a1da23, - 0x05822dc5, 0x05400e11, 0x0500155e, 0x25e0d502, - 0x25a1de17, 0x0580040c, 0x0540000f, 0x050287b3, - 0x25a0d66d, 0x2521cb02, 0x05801d74, 0x05400d38, - 0x05007854, 0x2560def5, 0x25e1dfb6, 0x05801c3a, - 0x0540158b, 0x05000e05, 0x046a00e2, 0x047a0493, - 0x659e0062, 0x65d408b4, 0x658d05bd, 0x046113ce, - 0x04e3187c, 0x04291729, 0x042e1d5a, 0x04d6b8f4, - 0x04c010d4, 0x045a03ad, 0x04108029, 0x041b19fb, - 0x04d9be24, 0x041aa302, 0x04191dba, 0x04d38e16, - 0x04d18571, 0x04100210, 0x04d7a6fc, 0x049eb15c, - 0x04981cf1, 0x05678f04, 0x05648969, 0x048816c4, - 0x044a01e4, 0x04c91f44, 0x044b1745, 0x0401033f, - 0x04dca468, 0x65c09b07, 0x658d9e38, 0x65868fca, - 0x65879ba8, 0x65c297ff, 0x04ddb4e0, 0x6582badd, - 0x6580ba9d, 0x6581b246, 0x658db51a, 0x65818b93, - 0x65f487d1, 0x65ee0e3c, 0x65b8396a, 0x65f7af8b, - 0x65f4def4, 0x65e6e378, 0x65ed4c8d, 0x65a6769a, - 0x049d5c1d, 0x04c864a3, 0x042d322d, 0x04a83148, - 0x047d3013, 0x04f731b0, 0x052d6bd7, 0x05606ed9, - 0x65889d79, 0x4556b2ee, 0x4540b645, 0x04223869, - 0x445887ae, 0x44da948e, 0x44998edb, 0x449b997f, - 0x041a338c, 0x04d8309c, 0x049921e6, 0x04883641, - 0x044a2882, 0x04892b8b, 0x044b37e3, 0x658735f8, - 0x65862d06, 0x65d83c95, 0x040134d8, 0x0e2610a4, - 0x4e2c116a, 0x0e6b1149, 0x4e7b1359, 0x0eac116a, - 0x4ea710c5, 0x2e21101f, 0x6e3812f6, 0x2e7b1359, - 0x6e71120f, 0x2ea51083, 0x6eb41272, + 0xd5033fdf, 0xd50330ff, 0xd503101a, 0xd503207f, + 0xd50320ff, 0xd503329f, 0xd50339bf, 0xd61f0280, + 0xd63f0140, 0xdac123fb, 0xdac127e8, 0xdac12be0, + 0xdac12fe1, 0xdac133f5, 0xdac137f1, 0xdac13bfd, + 0xdac13ffd, 0xdac147fc, 0xd61f083f, 0xd61f0eff, + 0xd63f0abf, 0xd63f0e9f, 0xd51b4436, 0xd51b421b, + 0xd53b4433, 0xd53b420b, 0xd53b00f0, 0xd53b0026, + 0xd53be0d1, 0xdac143e0, 0xc8047f0a, 0xc816fe6a, + 0xc85f7ca1, 0xc85ffd1e, 0xc89ffe2c, 0xc8dffdc9, + 0x88077ca1, 0x8810fd82, 0x885f7d8a, 0x885fff83, + 0x889fff4e, 0x88dffd5e, 0x480e7db5, 0x4809ff76, + 0x485f7e7c, 0x485fffcb, 0x489ffc53, 0x48dffee2, + 0x08017d80, 0x0810fded, 0x085f7eb1, 0x085ffd6d, + 0x089ffd1e, 0x08dffdb8, 0xc87f074b, 0xc87fedb5, + 0xc83430c3, 0xc821989d, 0x887f2e06, 0x887ff984, + 0x88353f9b, 0x8829d0cf, 0xf8183238, 0xb800a341, + 0x381ef00f, 0x7800d231, 0xf8431325, 0xb858c1f3, + 0x39401c74, 0x785e7093, 0x389fa26e, 0x789cb27c, + 0x78c0d36e, 0xb8988306, 0xfc457052, 0xbc5d0380, + 0xfc01739f, 0xbc02b32b, 0xf8147d0e, 0xb81a3d39, + 0x381f4ef0, 0x781c8d36, 0xf846df0b, 0xb8434e75, + 0x385feee6, 0x78415d07, 0x389e1d84, 0x789fcd68, + 0x78de4eae, 0xb89b9de0, 0xfc41dc5b, 0xbc410ead, + 0xfc010f6c, 0xbc1a5f22, 0xf81eb5aa, 0xb8032427, + 0x3800546a, 0x781df4c5, 0xf85626cd, 0xb859644d, + 0x385e860d, 0x785ea458, 0x389ff6e3, 0x789d5513, + 0x78df86e2, 0xb89a9793, 0xfc5af46f, 0xbc5b17ac, + 0xfc184435, 0xbc19d527, 0xf8226a85, 0xb83ed94e, + 0x383cd824, 0x783af945, 0xf87c7856, 0xb87c780c, + 0x386ff908, 0x786e5ab1, 0x38a8fb11, 0x78bef94a, + 0x78e07af1, 0xb8a07bd9, 0xfc775b05, 0xbc6f7876, + 0xfc30fba4, 0xbc3cda87, 0xf91ff41b, 0xb91f3115, + 0x391c0fb1, 0x791c685b, 0xf9586021, 0xb958b23d, + 0x39598921, 0x795d3077, 0x399d0675, 0x7998d8f3, + 0x79dbd02a, 0xb99d068a, 0xfd5d11a0, 0xbd58d76b, + 0xfd1ac72d, 0xbd1d9c14, 0x5800001a, 0x18ffda33, + 0xf8991100, 0xd8007880, 0xf8a758e0, 0xf9989d80, + 0x1a0b0298, 0x3a1c01a0, 0x5a0400ea, 0x7a02020f, + 0x9a1d028c, 0xba0e01ad, 0xda140186, 0xfa19022c, + 0x0b2b877e, 0x2b21c8ee, 0xcb3ba47d, 0x6b3ae9a0, + 0x8b256a36, 0xab28efd1, 0xcb37ce6a, 0xeb254fa6, + 0x3a498264, 0x7a4a72c2, 0xba4c91aa, 0xfa502303, + 0x3a4b68ed, 0x7a4a9b6b, 0xba4dd86d, 0xfa50cb45, + 0x1a9cd2aa, 0x1a9bd537, 0x5a8fd3aa, 0x5a95273e, + 0x9a95c220, 0x9a9426b0, 0xda8393d3, 0xda980573, + 0x5ac0033b, 0x5ac0046e, 0x5ac00a2e, 0x5ac011e7, + 0x5ac01798, 0xdac00331, 0xdac00742, 0xdac008bc, + 0xdac00f59, 0xdac0121b, 0xdac014d1, 0xdac10195, + 0xdac10480, 0xdac10b6c, 0xdac10f91, 0xdac1105c, + 0xdac11551, 0xdac119cf, 0xdac11c6e, 0xd71f0b2f, + 0xd71f0e6e, 0xd73f08b0, 0xd73f0c9a, 0x1ac20899, + 0x1add0d82, 0x1ac72111, 0x1ad92483, 0x1ad92b44, + 0x1ac02e24, 0x9ad70a3a, 0x9adc0eaf, 0x9aca2371, + 0x9ac72403, 0x9ac62939, 0x9acf2faf, 0x9bd17c4a, + 0x9b4b7d67, 0x1b1d5cf7, 0x1b0baf6e, 0x9b0c3f04, + 0x9b0bf28e, 0x9b2c5d6d, 0x9b2ea75e, 0x9ba7154d, + 0x9ba3adfd, 0x7edf160c, 0x1ef30a5f, 0x1eef1a15, + 0x1ee22aaa, 0x1ee73b8a, 0x1ef24bfe, 0x1ee65841, + 0x1ef9886a, 0x7ea1d4eb, 0x1e23080c, 0x1e261bb3, + 0x1e2028d7, 0x1e223b7c, 0x1e3d48e5, 0x1e2d5b2c, + 0x1e338b0c, 0x7ef6d648, 0x1e740aba, 0x1e7e1853, + 0x1e762916, 0x1e6c3ab3, 0x1e664ab2, 0x1e635870, + 0x1e7c887d, 0x1fca35cf, 0x1f0a6a4c, 0x1f0ff4e7, + 0x1f2032e0, 0x1f2d21d8, 0x1f4950ef, 0x1f5fc3b3, + 0x1f705522, 0x1f616c9e, 0x1e204319, 0x1e20c2ae, + 0x1e2140cd, 0x1e21c32c, 0x1e22c3d9, 0x1e23c2bc, + 0x1ee242f0, 0x1e6043a5, 0x1e60c276, 0x1e61428d, + 0x1e61c393, 0x1e6240d2, 0x1ee1c0ee, 0x1e38035c, + 0x9e3800d1, 0x1e780081, 0x9e7802ad, 0x1e2202a7, + 0x9e2202fb, 0x1e62028d, 0x9e62037f, 0x1e2402aa, + 0x9e640225, 0x1e3001cb, 0x9e7002ad, 0x1e2601da, + 0x9e660304, 0x1e2703b8, 0x9e6701cc, 0x1e3c2220, + 0x1e6022c0, 0x1e2020c8, 0x1e602368, 0x293c30db, + 0x29602e6e, 0x697a31e0, 0xa9025ee9, 0xa975134f, + 0x29ac20d1, 0x29f20887, 0x69fe26ce, 0xa9b0530d, + 0xa9c62d48, 0x28b21618, 0x28f06920, 0x68f00a38, + 0xa8bd45da, 0xa8c357be, 0x28325d51, 0x286c1bda, + 0xa804229e, 0xa8437536, 0x0c40702d, 0x4cdfa201, + 0x0cd36f36, 0x4cdf2759, 0x0d40c1e9, 0x4ddfcb2c, + 0x0dddcdc4, 0x4c408e31, 0x0cdf8777, 0x4d60c302, + 0x0dffc80b, 0x4df6cd82, 0x4ccd49b5, 0x0c40496c, + 0x4d40e5d2, 0x4ddfeab9, 0x0ddbee14, 0x4cdf0420, + 0x0cdd0360, 0x0d60e232, 0x0dffe705, 0x0df4e8bc, + 0x0e31b841, 0x4e31bab4, 0x0e71bbdd, 0x4e71ba30, + 0x4eb1b9cd, 0x0e30a96a, 0x4e30abdd, 0x0e70abdd, + 0x4e70aa93, 0x4eb0aaf6, 0x6e30f96a, 0x0e31a8a4, + 0x2e31a81f, 0x4e31aad5, 0x6e31a928, 0x0e71a81f, + 0x2e71aa93, 0x4e71a96a, 0x6e71abbc, 0x4eb1a862, + 0x6eb1ab59, 0x6eb0f8c5, 0x7e30f883, 0x7e70f928, + 0x7eb0faf6, 0x7ef0fa93, 0x0ea0c9cd, 0x4ea0c8c5, + 0x4ee0cbdd, 0x2ea0cb38, 0x6ea0cad5, 0x6ee0cb7a, + 0x0ea0db38, 0x4ea0d883, 0x4ee0db38, 0x0ea0eb7a, + 0x4ea0eb17, 0x4ee0ea0f, 0x2ea0dad5, 0x6ea0d883, + 0x6ee0db38, 0x0e20b928, 0x4e20bb59, 0x0e60bab4, + 0x4e60ba30, 0x0ea0ba51, 0x4ea0b862, 0x4ee0b841, + 0x0ea0f820, 0x4ea0fb38, 0x4ee0f8a4, 0x0ef8f883, + 0x4ef8f9ac, 0x2ea0f81f, 0x6ea0fbbc, 0x6ee0f96a, + 0x2ef8fb7a, 0x6ef8f862, 0x2ea1f9ac, 0x6ea1fa72, + 0x6ee1f81f, 0x2ef9f841, 0x6ef9f9cd, 0x2e205bdd, + 0x6e205820, 0x0e351e93, 0x4e2e1dac, 0x0eb31e51, + 0x4eb81ef6, 0x2e2f1dcd, 0x6e3e1fbc, 0x0e2087fe, + 0x4e21841f, 0x0e638441, 0x4e7c877a, 0x0ebe87bc, + 0x4ea684a4, 0x4ee087fe, 0x0e260ca4, 0x4e280ce6, + 0x0e600ffe, 0x4e7c0f7a, 0x0eb40e72, 0x4eab0d49, + 0x4eea0d28, 0x2e2e0dac, 0x6e220c20, 0x2e760eb4, + 0x6e630c41, 0x2eba0f38, 0x6ea40c62, 0x6ee20c20, + 0x0e2bd549, 0x4e3ad738, 0x4e7cd77a, 0x0e521630, + 0x4e4017fe, 0x2e258483, 0x6e2c856a, 0x2e798717, + 0x6e6c856a, 0x2ea684a4, 0x6eb48672, 0x6ee48462, + 0x0e2d2d8b, 0x4e2a2d28, 0x0e6c2d6a, 0x4e712e0f, + 0x0eb32e51, 0x4ea42c62, 0x4eec2d6a, 0x2e2e2dac, + 0x6e2e2dac, 0x2e712e0f, 0x6e6f2dcd, 0x2ea42c62, + 0x6ea92d07, 0x6ef62eb4, 0x0ebcd77a, 0x4eb2d630, + 0x4ee6d4a4, 0x0ec41462, 0x4ec614a4, 0x0e2e9dac, + 0x4e349e72, 0x0e779ed5, 0x4e729e30, 0x0eb49e72, + 0x4ead9d8b, 0x2eb7d6d5, 0x6eb9d717, 0x6eeed5ac, + 0x2edc177a, 0x6ed91717, 0x2e3ed7bc, 0x6e30d5ee, + 0x6e6dd58b, 0x2e5a1738, 0x6e431441, 0x2e2eddac, + 0x6e21dc1f, 0x6e6cdd6a, 0x2e521e30, 0x6e491d07, + 0x0e649462, 0x4e659483, 0x0eaf95cd, 0x4eb59693, + 0x0e33ce51, 0x4e32ce30, 0x4e65cc83, 0x0e430c41, + 0x4e4d0d8b, 0x2e6097fe, 0x6e6794c5, 0x2eaa9528, + 0x6eb1960f, 0x0ebfcfdd, 0x4ea0cffe, 0x4ee2cc20, + 0x0ed60eb4, 0x4ec90d07, 0x2e36feb4, 0x6e39ff17, + 0x6e7effbc, 0x2e573ed5, 0x6e5d3f9b, 0x0e3b6759, + 0x4e2764c5, 0x0e636441, 0x4e796717, 0x0eb26630, + 0x4ea1641f, 0x2e2764c5, 0x6e2e65ac, 0x2e6b6549, + 0x6e7e67bc, 0x2eb1660f, 0x6ebf67dd, 0x0e38a6f6, + 0x4e21a41f, 0x0e75a693, 0x4e61a41f, 0x0ea7a4c5, + 0x4eb0a5ee, 0x0e34f672, 0x4e21f41f, 0x4e74f672, + 0x0e5d379b, 0x4e5636b4, 0x0e326e30, 0x4e2e6dac, + 0x0e6d6d8b, 0x4e6b6d49, 0x0ea86ce6, 0x4ea06ffe, + 0x2e336e51, 0x6e3d6f9b, 0x2e7e6fbc, 0x6e606ffe, + 0x2ea96d07, 0x6eac6d6a, 0x0e36aeb4, 0x4e2cad6a, + 0x0e66aca4, 0x4e7aaf38, 0x0eb3ae51, 0x4eb3ae51, + 0x2e38aef6, 0x6e25ac83, 0x2e7fafdd, 0x6e71ae0f, + 0x2eb8aef6, 0x6eb5ae93, 0x2e35a693, 0x6e38a6f6, + 0x2e64a462, 0x6e71a60f, 0x2ea8a4e6, 0x6eaea5ac, + 0x0e72b630, 0x4e6db58b, 0x0eafb5cd, 0x4eb9b717, + 0x0e232441, 0x4e2027fe, 0x0e752693, 0x4e6724c5, + 0x0eb32651, 0x4ea42462, 0x0eb2f630, 0x4eb8f6f6, + 0x4eeff5cd, 0x0ecc356a, 0x4ed736d5, 0x2ebfefdd, + 0x6ebdef9b, 0x6eeeedac, 0x2edd2f9b, 0x6ec52c83, + 0x0f81100f, 0x4fab8949, 0x4fc618a4, 0x0faf51cd, + 0x4fa58083, 0x4fcd598b, 0x2fae91ac, 0x4f81800f, + 0x6fcb9949, 0x0f5d818b, 0x4f438841, 0x0fa28020, + 0x4faf89cd, 0x0e393717, 0x4e243462, 0x0e743672, + 0x4e6e35ac, 0x0ea634a4, 0x4ebe37bc, 0x4ee037fe, + 0x0e3f3fdd, 0x4e323e30, 0x0e7d3f9b, 0x4e683ce6, + 0x0eab3d49, 0x4ebf3fdd, 0x4ef43e72, 0x2e298d07, + 0x6e268ca4, 0x2e698d07, 0x6e718e0f, 0x2eab8d49, + 0x6eb98f17, 0x6eea8d28, 0x2e243462, 0x6e3e37bc, + 0x2e7736d5, 0x6e61341f, 0x2ea734c5, 0x6ebd379b, + 0x6ee23420, 0x2e333e51, 0x6e313e0f, 0x2e663ca4, + 0x6e7c3f7a, 0x2eaa3d28, 0x6ebe3fbc, 0x6ef83ef6, + 0x0e3de79b, 0x4e3de79b, 0x4e7be759, 0x2eb9e717, + 0x6ea2e420, 0x6ee6e4a4, 0x2e28e4e6, 0x6e34e672, + 0x6e62e420, 0x659229e2, 0x65903cb3, 0x65d03683, + 0x65913163, 0x65d120df, 0x65d323c6, 0x25dd8ecd, + 0x25d2063e, 0x258b0947, 0x2501358b, 0x25823032, + 0x254181d6, 0x24a646a1, 0x24719e73, 0x24233cd8, + 0x24adf4c2, 0xba5fd3e3, 0x3a5f03e5, 0xfa411be4, + 0x7a42cbe2, 0x93df03ff, 0xc820ffff, 0x8822fc7f, + 0xc8247cbf, 0x88267fff, 0x4e010fe0, 0x5e040420, + 0x4e081fe1, 0x4e0c1fe1, 0x4e0a1fe1, 0x4e071fe1, + 0x4e042c20, 0x4e062c20, 0x4e052c20, 0x4e083c20, + 0x0e0c3c20, 0x0e0a3c20, 0x0e073c20, 0x9eae0020, + 0x0f03f409, 0x6f03f40e, 0x4cc0ac3f, 0x0ea1b820, + 0x0ef9b820, 0x4ef9b820, 0x4e21c862, 0x0e79c862, + 0x4e79c862, 0x4e61b8a4, 0x0e79b8a4, 0x4e79b8a4, + 0x05a08020, 0x05104fe0, 0x05505001, 0x05906fe2, + 0x05d03005, 0x05101fea, 0x05901feb, 0x0590cc0b, + 0x0590de0b, 0x04b0e3e0, 0x0470e7e1, 0x042f9c20, + 0x043f9c35, 0x047f9c20, 0x04ff9c20, 0x04299420, + 0x04319160, 0x0461943e, 0x04a19020, 0x04038100, + 0x040381a0, 0x040387e1, 0x04438be2, 0x04c38fe3, + 0x040181e0, 0x04018100, 0x04018621, 0x04418b22, + 0x04418822, 0x04818c23, 0x040081e0, 0x04008120, + 0x04008761, 0x04008621, 0x04408822, 0x04808c23, + 0x042053ff, 0x047f5401, 0x25208028, 0x2538cfe0, + 0x2578d001, 0x25b8efe2, 0x25f8f007, 0x2538dfea, + 0x25b8dfeb, 0xa400a3e0, 0xa420a7e0, 0xa4484be0, + 0xa467afe0, 0xa4a8a7ea, 0xa547a814, 0xa4084ffe, + 0xa55c53e0, 0xa5e1540b, 0xe400fbf6, 0xe408ffff, + 0xe420e7e0, 0xe4484be0, 0xe460efe0, 0xe547e400, + 0xe4014be0, 0xe4a84fe0, 0xe5f15000, 0x858043e0, + 0x85a043ff, 0xe59f5d08, 0x0420e3e9, 0x0460e3ea, + 0x04a0e3eb, 0x04e0e3ec, 0x25104042, 0x25104871, + 0x25904861, 0x25904c92, 0x05344020, 0x05744041, + 0x05b44062, 0x05f44083, 0x252c8840, 0x253c1420, + 0x25681572, 0x25a21ce3, 0x25ea1e34, 0x253c0421, + 0x25680572, 0x25a20ce3, 0x25ea0e34, 0x0522c020, + 0x05e6c0a4, 0x2401a001, 0x2443a051, 0x24858881, + 0x24c78cd1, 0x24850891, 0x24c70cc1, 0x250f9001, + 0x25508051, 0x25802491, 0x25df28c1, 0x25850c81, + 0x251e10d1, 0x65816001, 0x65c36051, 0x65854891, + 0x65c74cc1, 0x05733820, 0x05b238a4, 0x05f138e6, + 0x0570396a, 0x65d0a001, 0x65d6a443, 0x65d4a826, + 0x6594ac26, 0x6554ac26, 0x6556ac26, 0x6552ac26, + 0x65cbac85, 0x65caac01, 0x6589ac85, 0x6588ac01, + 0x65c9ac85, 0x65c8ac01, 0x65dea833, 0x659ca509, + 0x65d8a801, 0x65dcac01, 0x655cb241, 0x0520a1e0, + 0x0521a601, 0x052281e0, 0x05238601, 0x04a14026, + 0x042244a6, 0x046344a6, 0x04a444a6, 0x04e544a7, + 0x0568aca7, 0x05b23230, 0x05302a30, 0x05702a30, + 0x05b02a30, 0x05f02a30, 0x853040af, 0xc5b040af, + 0xe57080af, 0xe5b080af, 0x25034440, 0x254054c4, + 0x25034640, 0x25415a05, 0x25834440, 0x25c54489, + 0x250b5d3a, 0x2550dc20, 0x2518e3e1, 0x2518e021, + 0x2518e0a1, 0x2518e121, 0x2518e1a1, 0x2558e3e2, + 0x2558e042, 0x2558e0c2, 0x2558e142, 0x2598e3e3, + 0x2598e063, 0x2598e0e3, 0x2598e163, 0x25d8e3e4, + 0x25d8e084, 0x25d8e104, 0x25d8e184, 0x2518e407, + 0x05214800, 0x05614800, 0x05a14800, 0x05e14800, + 0x05214c00, 0x05614c00, 0x05a14c00, 0x05e14c00, + 0x05304001, 0x05314001, 0x05a18610, 0x05e18610, + 0x0420bc31, 0x05271e11, 0x6545e891, 0x6585e891, + 0x65c5e891, 0x6545c891, 0x6585c891, 0x65c5c891, + 0x052c8020, 0x056c8020, 0x05ac8020, 0x05ec8020, + 0x45b0c210, 0x45f1c231, 0x1e601000, 0x1e603000, + 0x1e621000, 0x1e623000, 0x1e641000, 0x1e643000, + 0x1e661000, 0x1e663000, 0x1e681000, 0x1e683000, + 0x1e6a1000, 0x1e6a3000, 0x1e6c1000, 0x1e6c3000, + 0x1e6e1000, 0x1e6e3000, 0x1e701000, 0x1e703000, + 0x1e721000, 0x1e723000, 0x1e741000, 0x1e743000, + 0x1e761000, 0x1e763000, 0x1e781000, 0x1e783000, + 0x1e7a1000, 0x1e7a3000, 0x1e7c1000, 0x1e7c3000, + 0x1e7e1000, 0x1e7e3000, 0xf82c8114, 0xf8390274, + 0xf820130b, 0xf82623f4, 0xf82e30d0, 0xf82051e7, + 0xf833413a, 0xf82a72b7, 0xf836605c, 0xf8a3826f, + 0xf8b40087, 0xf8bd1007, 0xf8a92290, 0xf8b73204, + 0xf8aa5177, 0xf8b943e6, 0xf8b072ed, 0xf8ac61c1, + 0xf8e98215, 0xf8fa008f, 0xf8e41110, 0xf8e6209e, + 0xf8fd33b1, 0xf8fa51e9, 0xf8e243ab, 0xf8e37027, + 0xf8fb61f5, 0xf86e81e8, 0xf87600b9, 0xf87411f5, + 0xf87723d0, 0xf8743014, 0xf8645313, 0xf8644094, + 0xf878727a, 0xf8626108, 0xb82e81f8, 0xb83f0096, + 0xb83f1141, 0xb834200c, 0xb8293307, 0xb8305364, + 0xb826436a, 0xb838720d, 0xb83f62d6, 0xb8b483bf, + 0xb8a9028e, 0xb8a71394, 0xb8a921cb, 0xb8ac3034, + 0xb8b85269, 0xb8ad41f3, 0xb8b07005, 0xb8a3610c, + 0xb8ef820f, 0xb8e403cf, 0xb8e51140, 0xb8f6207b, + 0xb8e03269, 0xb8fd530a, 0xb8e440f4, 0xb8f871dd, + 0xb8f5636b, 0xb86d83f0, 0xb871006e, 0xb87e12d0, + 0xb8742287, 0xb8633341, 0xb8735209, 0xb8714015, + 0xb8647302, 0xb86e6166, 0xce3179d5, 0xce035c6c, + 0xce788c69, 0xce93bc7c, 0xce758347, 0xce6884ae, + 0xcec080ba, 0xce718a56, 0x2520c9e0, 0x2561c834, + 0x05800d2c, 0x0540154b, 0x0500093f, 0x25e0d78f, + 0x25a1c81c, 0x058026a8, 0x05401eca, 0x05008816, + 0x25e0c5d7, 0x25e1d35a, 0x05800e11, 0x0540155e, + 0x05026c22, 0x25e0ccf6, 0x2521c0a8, 0x0580000f, + 0x054287b3, 0x0500b04d, 0x2560d481, 0x25a1d84c, + 0x05800d38, 0x05407854, 0x050015d5, 0x25e0dabf, + 0x25a1cf12, 0x0580158b, 0x05400e05, 0x05003682, + 0x047a0093, 0x043e0462, 0x65d400b4, 0x658d09bd, + 0x658107ce, 0x04e3107c, 0x04291b29, 0x042e155a, + 0x04e71f54, 0x04d6b0d4, 0x044003ad, 0x041a0029, + 0x041099fb, 0x04db1e24, 0x0419a302, 0x041abdba, + 0x04d90e16, 0x04d38571, 0x04118210, 0x04d006fc, + 0x0497b15c, 0x049ebcf1, 0x04580f04, 0x05278969, + 0x05a496c4, 0x044801e4, 0x04ca1f44, 0x04491745, + 0x040b033f, 0x04810468, 0x04dcbb07, 0x65809e38, + 0x658d8fca, 0x65869ba8, 0x65c797ff, 0x65c294e0, + 0x049dbadd, 0x6582ba9d, 0x6580b246, 0x6581b51a, + 0x658dab93, 0x65c187d1, 0x65b19dd8, 0x65eb0b53, + 0x65fc29e0, 0x65f7b797, 0x65bbd81d, 0x65a4ed97, + 0x65b45aff, 0x65e07fa2, 0x04454097, 0x044d6e3c, + 0x04283148, 0x04bd3013, 0x047731b0, 0x04ed33d7, + 0x05606ad9, 0x056b6fd9, 0x658896ce, 0x4540b245, + 0x45c3b449, 0x04243bae, 0x44d8948e, 0x449a8edb, + 0x4499997f, 0x441b938c, 0x04da309c, 0x049821e6, + 0x04993641, 0x04482882, 0x048a2b8b, 0x044937e3, + 0x044b35f8, 0x65872d06, 0x65c63c95, 0x659834d8, + 0x04c12924, 0x0e2c116a, 0x4e2710c5, 0x0e61101f, + 0x4e7812f6, 0x0ebb1359, 0x4eb1120f, 0x2e251083, + 0x6e341272, 0x2e7011ee, 0x6e6c116a, 0x2ea41062, + 0x6eac116a, }; // END Generated code -- do not edit diff --git a/test/hotspot/jtreg/compiler/onSpinWait/TestOnSpinWaitAArch64.java b/test/hotspot/jtreg/compiler/onSpinWait/TestOnSpinWaitAArch64.java index 3bcd60ed50c..e487e921dd2 100644 --- a/test/hotspot/jtreg/compiler/onSpinWait/TestOnSpinWaitAArch64.java +++ b/test/hotspot/jtreg/compiler/onSpinWait/TestOnSpinWaitAArch64.java @@ -22,7 +22,7 @@ */ /** - * @test TestOnSpinWaitAArch64 + * @test id=TestOnSpinWaitAArch64 * @summary Checks that java.lang.Thread.onSpinWait is intrinsified with instructions specified with '-XX:OnSpinWaitInst' and '-XX:OnSpinWaitInstCount' * @bug 8186670 * @library /test/lib @@ -41,6 +41,22 @@ * @run driver compiler.onSpinWait.TestOnSpinWaitAArch64 c1 sb 1 */ +/** + * @test id=TestOnSpinWaitAArch64-wfet + * @summary Checks that java.lang.Thread.onSpinWait is intrinsified when -XX:OnSpinWaitInst=wfet is used + * @bug 8366441 + * @library /test/lib + * + * @requires vm.flagless + * @requires (os.arch=="aarch64" & os.family=="linux") + * @requires vm.debug + * + * @run driver compiler.onSpinWait.TestOnSpinWaitAArch64 c2 wfet 1 1 + * @run driver compiler.onSpinWait.TestOnSpinWaitAArch64 c2 wfet 1 1000 + * @run driver compiler.onSpinWait.TestOnSpinWaitAArch64 c1 wfet 1 1 + * @run driver compiler.onSpinWait.TestOnSpinWaitAArch64 c1 wfet 1 1000 + */ + package compiler.onSpinWait; import java.util.Arrays; @@ -56,6 +72,7 @@ public static void main(String[] args) throws Exception { String compiler = args[0]; String spinWaitInst = args[1]; String spinWaitInstCount = args[2]; + String spinWaitDelay = (args.length >= 4 ? args[3] : ""); ArrayList command = new ArrayList(); command.add("-XX:+IgnoreUnrecognizedVMOptions"); command.add("-showversion"); @@ -70,8 +87,14 @@ public static void main(String[] args) throws Exception { throw new RuntimeException("Unknown compiler: " + compiler); } command.add("-Xbatch"); + if ("wfet".equals(spinWaitInst)) { + command.add("-XX:+UnlockExperimentalVMOptions"); + } command.add("-XX:OnSpinWaitInst=" + spinWaitInst); command.add("-XX:OnSpinWaitInstCount=" + spinWaitInstCount); + if (!spinWaitDelay.isEmpty()) { + command.add("-XX:OnSpinWaitDelay=" + spinWaitDelay); + } command.add("-XX:CompileCommand=compileonly," + Launcher.class.getName() + "::" + "test"); command.add("-XX:CompileCommand=print," + Launcher.class.getName() + "::" + "test"); command.add(Launcher.class.getName()); @@ -85,6 +108,14 @@ public static void main(String[] args) throws Exception { return; } + if ("wfet".equals(spinWaitInst) && + (analyzer.contains("CPU does not support the SB instruction") || + analyzer.contains("CPU does not support the FEAT_ECV") || + analyzer.contains("CPU does not support the WFET instruction"))) { + System.out.println("Skipping the test. The CPU does not support SB or WFET instruction, or FEAT_ECV."); + return; + } + analyzer.shouldHaveExitValue(0); System.out.println(analyzer.getOutput()); @@ -101,6 +132,9 @@ private static String getSpinWaitInstHex(String spinWaitInst) { return "3f2003d5"; } else if ("sb".equals(spinWaitInst)) { return "ff3003d5"; + } else if ("wfet".equals(spinWaitInst)) { + // This assumes rscratch1 is r8. + return "081003d5"; } else { throw new RuntimeException("Unknown spin wait instruction: " + spinWaitInst); } @@ -166,7 +200,7 @@ private static void checkOutput(OutputAnalyzer output, final String spinWaitInst // When code is disassembled, we have one instruction per line. // Otherwise, there can be multiple hex instructions separated by '|'. foundCount += (int)Arrays.stream(line.split("\\|")) - .takeWhile(i -> i.startsWith(expectedInst)) + .filter(i -> i.startsWith(expectedInst)) .count(); } From 78e9df5088a89ca49a43c846dca0f5c47a482f0a Mon Sep 17 00:00:00 2001 From: Leo Korinth Date: Tue, 31 Mar 2026 11:41:57 +0000 Subject: [PATCH 077/116] 8380987: Fix implicit narrowing conversion in klass.hpp Reviewed-by: stefank, ayang --- src/hotspot/share/oops/klass.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hotspot/share/oops/klass.hpp b/src/hotspot/share/oops/klass.hpp index d59db9744cb..1c6b28127b8 100644 --- a/src/hotspot/share/oops/klass.hpp +++ b/src/hotspot/share/oops/klass.hpp @@ -466,9 +466,9 @@ class Klass : public Metadata { static const int _lh_log2_element_size_shift = BitsPerByte*0; static const int _lh_log2_element_size_mask = BitsPerLong-1; static const int _lh_element_type_shift = BitsPerByte*1; - static const int _lh_element_type_mask = right_n_bits(BitsPerByte); // shifted mask + static const int _lh_element_type_mask = right_n_bits(BitsPerByte); // shifted mask static const int _lh_header_size_shift = BitsPerByte*2; - static const int _lh_header_size_mask = right_n_bits(BitsPerByte); // shifted mask + static const int _lh_header_size_mask = right_n_bits(BitsPerByte); // shifted mask static const int _lh_array_tag_bits = 2; static const int _lh_array_tag_shift = BitsPerInt - _lh_array_tag_bits; static const int _lh_array_tag_obj_value = ~0x01; // 0x80000000 >> 30 From 8c38e725a57e2b20c27da170b99b8768253603b4 Mon Sep 17 00:00:00 2001 From: Ashutosh Mehra Date: Tue, 31 Mar 2026 14:11:06 +0000 Subject: [PATCH 078/116] 8380464: Inconsistency in emitting warning messages in vm_version_x86.cpp Reviewed-by: kvn, dholmes --- src/hotspot/cpu/x86/vm_version_x86.cpp | 111 ++++++++++++++++--------- 1 file changed, 74 insertions(+), 37 deletions(-) diff --git a/src/hotspot/cpu/x86/vm_version_x86.cpp b/src/hotspot/cpu/x86/vm_version_x86.cpp index 4301bd328d6..a77105efbbf 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.cpp +++ b/src/hotspot/cpu/x86/vm_version_x86.cpp @@ -1264,8 +1264,9 @@ void VM_Version::get_processor_features() { UseGHASHIntrinsics = true; } } else if (UseGHASHIntrinsics) { - if (!FLAG_IS_DEFAULT(UseGHASHIntrinsics)) + if (!FLAG_IS_DEFAULT(UseGHASHIntrinsics)) { warning("GHASH intrinsic requires CLMUL and SSE2 instructions on this CPU"); + } FLAG_SET_DEFAULT(UseGHASHIntrinsics, false); } @@ -1275,26 +1276,27 @@ void VM_Version::get_processor_features() { // based on the VM capabilities whether to use an AVX2 or AVX512-enabled // version. if (UseAVX >= 1) { - if (FLAG_IS_DEFAULT(UseChaCha20Intrinsics)) { - UseChaCha20Intrinsics = true; - } + if (FLAG_IS_DEFAULT(UseChaCha20Intrinsics)) { + UseChaCha20Intrinsics = true; + } } else if (UseChaCha20Intrinsics) { - if (!FLAG_IS_DEFAULT(UseChaCha20Intrinsics)) { - warning("ChaCha20 intrinsic requires AVX instructions"); - } - FLAG_SET_DEFAULT(UseChaCha20Intrinsics, false); + if (!FLAG_IS_DEFAULT(UseChaCha20Intrinsics)) { + warning("ChaCha20 intrinsic requires AVX instructions"); + } + FLAG_SET_DEFAULT(UseChaCha20Intrinsics, false); } // Kyber Intrinsics // Currently we only have them for AVX512 if (supports_evex() && supports_avx512bw()) { - if (FLAG_IS_DEFAULT(UseKyberIntrinsics)) { - UseKyberIntrinsics = true; - } - } else - if (UseKyberIntrinsics) { - warning("Intrinsics for ML-KEM are not available on this CPU."); - FLAG_SET_DEFAULT(UseKyberIntrinsics, false); + if (FLAG_IS_DEFAULT(UseKyberIntrinsics)) { + UseKyberIntrinsics = true; + } + } else if (UseKyberIntrinsics) { + if (!FLAG_IS_DEFAULT(UseKyberIntrinsics)) { + warning("Intrinsics for ML-KEM are not available on this CPU."); + } + FLAG_SET_DEFAULT(UseKyberIntrinsics, false); } // Dilithium Intrinsics @@ -1303,8 +1305,10 @@ void VM_Version::get_processor_features() { UseDilithiumIntrinsics = true; } } else if (UseDilithiumIntrinsics) { + if (!FLAG_IS_DEFAULT(UseDilithiumIntrinsics)) { warning("Intrinsics for ML-DSA are not available on this CPU."); - FLAG_SET_DEFAULT(UseDilithiumIntrinsics, false); + } + FLAG_SET_DEFAULT(UseDilithiumIntrinsics, false); } // Base64 Intrinsics (Check the condition for which the intrinsic will be active) @@ -1313,8 +1317,9 @@ void VM_Version::get_processor_features() { UseBASE64Intrinsics = true; } } else if (UseBASE64Intrinsics) { - if (!FLAG_IS_DEFAULT(UseBASE64Intrinsics)) + if (!FLAG_IS_DEFAULT(UseBASE64Intrinsics)) { warning("Base64 intrinsic requires EVEX instructions on this CPU"); + } FLAG_SET_DEFAULT(UseBASE64Intrinsics, false); } @@ -1323,7 +1328,9 @@ void VM_Version::get_processor_features() { UseFMA = true; } } else if (UseFMA) { - warning("FMA instructions are not available on this CPU"); + if (!FLAG_IS_DEFAULT(UseFMA)) { + warning("FMA instructions are not available on this CPU"); + } FLAG_SET_DEFAULT(UseFMA, false); } @@ -1336,7 +1343,9 @@ void VM_Version::get_processor_features() { UseSHA = true; } } else if (UseSHA) { - warning("SHA instructions are not available on this CPU"); + if (!FLAG_IS_DEFAULT(UseSHA)) { + warning("SHA instructions are not available on this CPU"); + } FLAG_SET_DEFAULT(UseSHA, false); } @@ -1345,7 +1354,9 @@ void VM_Version::get_processor_features() { FLAG_SET_DEFAULT(UseSHA1Intrinsics, true); } } else if (UseSHA1Intrinsics) { - warning("Intrinsics for SHA-1 crypto hash functions not available on this CPU."); + if (!FLAG_IS_DEFAULT(UseSHA1Intrinsics)) { + warning("Intrinsics for SHA-1 crypto hash functions not available on this CPU."); + } FLAG_SET_DEFAULT(UseSHA1Intrinsics, false); } @@ -1354,7 +1365,9 @@ void VM_Version::get_processor_features() { FLAG_SET_DEFAULT(UseSHA256Intrinsics, true); } } else if (UseSHA256Intrinsics) { - warning("Intrinsics for SHA-224 and SHA-256 crypto hash functions not available on this CPU."); + if (!FLAG_IS_DEFAULT(UseSHA256Intrinsics)) { + warning("Intrinsics for SHA-224 and SHA-256 crypto hash functions not available on this CPU."); + } FLAG_SET_DEFAULT(UseSHA256Intrinsics, false); } @@ -1363,7 +1376,9 @@ void VM_Version::get_processor_features() { FLAG_SET_DEFAULT(UseSHA512Intrinsics, true); } } else if (UseSHA512Intrinsics) { - warning("Intrinsics for SHA-384 and SHA-512 crypto hash functions not available on this CPU."); + if (!FLAG_IS_DEFAULT(UseSHA512Intrinsics)) { + warning("Intrinsics for SHA-384 and SHA-512 crypto hash functions not available on this CPU."); + } FLAG_SET_DEFAULT(UseSHA512Intrinsics, false); } @@ -1372,7 +1387,9 @@ void VM_Version::get_processor_features() { FLAG_SET_DEFAULT(UseSHA3Intrinsics, true); } } else if (UseSHA3Intrinsics) { - warning("Intrinsics for SHA3-224, SHA3-256, SHA3-384 and SHA3-512 crypto hash functions not available on this CPU."); + if (!FLAG_IS_DEFAULT(UseSHA3Intrinsics)) { + warning("Intrinsics for SHA3-224, SHA3-256, SHA3-384 and SHA3-512 crypto hash functions not available on this CPU."); + } FLAG_SET_DEFAULT(UseSHA3Intrinsics, false); } @@ -1435,7 +1452,9 @@ void VM_Version::get_processor_features() { FLAG_SET_DEFAULT(UsePoly1305Intrinsics, true); } } else if (UsePoly1305Intrinsics) { - warning("Intrinsics for Poly1305 crypto hash functions not available on this CPU."); + if (!FLAG_IS_DEFAULT(UsePoly1305Intrinsics)) { + warning("Intrinsics for Poly1305 crypto hash functions not available on this CPU."); + } FLAG_SET_DEFAULT(UsePoly1305Intrinsics, false); } @@ -1444,7 +1463,9 @@ void VM_Version::get_processor_features() { FLAG_SET_DEFAULT(UseIntPolyIntrinsics, true); } } else if (UseIntPolyIntrinsics) { - warning("Intrinsics for Polynomial crypto functions not available on this CPU."); + if (!FLAG_IS_DEFAULT(UseIntPolyIntrinsics)) { + warning("Intrinsics for Polynomial crypto functions not available on this CPU."); + } FLAG_SET_DEFAULT(UseIntPolyIntrinsics, false); } @@ -1694,8 +1715,8 @@ void VM_Version::get_processor_features() { if (FLAG_IS_DEFAULT(UseSSE42Intrinsics)) { FLAG_SET_DEFAULT(UseSSE42Intrinsics, true); } - } else { - if (UseSSE42Intrinsics && !FLAG_IS_DEFAULT(UseSSE42Intrinsics)) { + } else if (UseSSE42Intrinsics) { + if (!FLAG_IS_DEFAULT(UseSSE42Intrinsics)) { warning("SSE4.2 intrinsics require SSE4.2 instructions or higher. Intrinsics will be disabled."); } FLAG_SET_DEFAULT(UseSSE42Intrinsics, false); @@ -1705,15 +1726,17 @@ void VM_Version::get_processor_features() { UseVectorizedMismatchIntrinsic = true; } } else if (UseVectorizedMismatchIntrinsic) { - if (!FLAG_IS_DEFAULT(UseVectorizedMismatchIntrinsic)) + if (!FLAG_IS_DEFAULT(UseVectorizedMismatchIntrinsic)) { warning("vectorizedMismatch intrinsics are not available on this CPU"); + } FLAG_SET_DEFAULT(UseVectorizedMismatchIntrinsic, false); } if (UseAVX >= 2) { FLAG_SET_DEFAULT(UseVectorizedHashCodeIntrinsic, true); } else if (UseVectorizedHashCodeIntrinsic) { - if (!FLAG_IS_DEFAULT(UseVectorizedHashCodeIntrinsic)) + if (!FLAG_IS_DEFAULT(UseVectorizedHashCodeIntrinsic)) { warning("vectorizedHashCode intrinsics are not available on this CPU"); + } FLAG_SET_DEFAULT(UseVectorizedHashCodeIntrinsic, false); } @@ -1723,7 +1746,9 @@ void VM_Version::get_processor_features() { UseCountLeadingZerosInstruction = true; } } else if (UseCountLeadingZerosInstruction) { - warning("lzcnt instruction is not available on this CPU"); + if (!FLAG_IS_DEFAULT(UseCountLeadingZerosInstruction)) { + warning("lzcnt instruction is not available on this CPU"); + } FLAG_SET_DEFAULT(UseCountLeadingZerosInstruction, false); } @@ -1739,7 +1764,9 @@ void VM_Version::get_processor_features() { } } } else if (UseCountTrailingZerosInstruction) { - warning("tzcnt instruction is not available on this CPU"); + if (!FLAG_IS_DEFAULT(UseCountTrailingZerosInstruction)) { + warning("tzcnt instruction is not available on this CPU"); + } FLAG_SET_DEFAULT(UseCountTrailingZerosInstruction, false); } @@ -1750,7 +1777,9 @@ void VM_Version::get_processor_features() { UseBMI1Instructions = true; } } else if (UseBMI1Instructions) { - warning("BMI1 instructions are not available on this CPU (AVX is also required)"); + if (!FLAG_IS_DEFAULT(UseBMI1Instructions)) { + warning("BMI1 instructions are not available on this CPU (AVX is also required)"); + } FLAG_SET_DEFAULT(UseBMI1Instructions, false); } @@ -1759,7 +1788,9 @@ void VM_Version::get_processor_features() { UseBMI2Instructions = true; } } else if (UseBMI2Instructions) { - warning("BMI2 instructions are not available on this CPU (AVX is also required)"); + if (!FLAG_IS_DEFAULT(UseBMI2Instructions)) { + warning("BMI2 instructions are not available on this CPU (AVX is also required)"); + } FLAG_SET_DEFAULT(UseBMI2Instructions, false); } @@ -1769,7 +1800,9 @@ void VM_Version::get_processor_features() { UsePopCountInstruction = true; } } else if (UsePopCountInstruction) { - warning("POPCNT instruction is not available on this CPU"); + if (!FLAG_IS_DEFAULT(UsePopCountInstruction)) { + warning("POPCNT instruction is not available on this CPU"); + } FLAG_SET_DEFAULT(UsePopCountInstruction, false); } @@ -1779,7 +1812,9 @@ void VM_Version::get_processor_features() { UseFastStosb = true; } } else if (UseFastStosb) { - warning("fast-string operations are not available on this CPU"); + if (!FLAG_IS_DEFAULT(UseFastStosb)) { + warning("fast-string operations are not available on this CPU"); + } FLAG_SET_DEFAULT(UseFastStosb, false); } @@ -1805,7 +1840,9 @@ void VM_Version::get_processor_features() { UseXMMForObjInit = true; } } else if (UseXMMForObjInit) { - warning("UseXMMForObjInit requires SSE2 and unaligned load/stores. Feature is switched off."); + if (!FLAG_IS_DEFAULT(UseXMMForObjInit)) { + warning("UseXMMForObjInit requires SSE2 and unaligned load/stores. Feature is switched off."); + } FLAG_SET_DEFAULT(UseXMMForObjInit, false); } @@ -1885,7 +1922,7 @@ void VM_Version::get_processor_features() { if (FLAG_IS_DEFAULT(ContendedPaddingWidth) && (cache_line_size > ContendedPaddingWidth)) - ContendedPaddingWidth = cache_line_size; + ContendedPaddingWidth = cache_line_size; // This machine allows unaligned memory accesses if (FLAG_IS_DEFAULT(UseUnalignedAccesses)) { From e3a66f0170ed8e6ca4a16d4897d7d3ffceb2553c Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Tue, 31 Mar 2026 15:01:10 +0000 Subject: [PATCH 079/116] 8380649: Parallel: Inline initialize_region_data and create_vspace of ParallelCompactData Reviewed-by: iwalulya, tschatzl --- .../share/gc/parallel/psParallelCompact.cpp | 39 ++++++------------- .../share/gc/parallel/psParallelCompact.hpp | 3 -- 2 files changed, 12 insertions(+), 30 deletions(-) diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.cpp b/src/hotspot/share/gc/parallel/psParallelCompact.cpp index d03bc3cda45..ca1fd2c120b 100644 --- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp +++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp @@ -232,14 +232,10 @@ bool ParallelCompactData::initialize(MemRegion reserved_heap) assert(region_align_down(_heap_start) == _heap_start, "region start not aligned"); + assert(is_aligned(heap_size, RegionSize), "precondition"); - return initialize_region_data(heap_size); -} - -PSVirtualSpace* -ParallelCompactData::create_vspace(size_t count, size_t element_size) -{ - const size_t raw_bytes = count * element_size; + const size_t count = heap_size >> Log2RegionSize; + const size_t raw_bytes = count * sizeof(RegionData); const size_t page_sz = os::page_size_for_region_aligned(raw_bytes, 10); const size_t granularity = os::vm_allocation_granularity(); const size_t rs_align = MAX2(page_sz, granularity); @@ -253,7 +249,7 @@ ParallelCompactData::create_vspace(size_t count, size_t element_size) if (!rs.is_reserved()) { // Failed to reserve memory. - return nullptr; + return false; } os::trace_page_sizes("Parallel Compact Data", raw_bytes, raw_bytes, rs.base(), @@ -261,34 +257,23 @@ ParallelCompactData::create_vspace(size_t count, size_t element_size) MemTracker::record_virtual_memory_tag(rs, mtGC); - PSVirtualSpace* vspace = new PSVirtualSpace(rs, page_sz); + PSVirtualSpace* region_vspace = new PSVirtualSpace(rs, page_sz); - if (!vspace->expand_by(_reserved_byte_size)) { + if (!region_vspace->expand_by(_reserved_byte_size)) { // Failed to commit memory. - delete vspace; + delete region_vspace; // Release memory reserved in the space. MemoryReserver::release(rs); - return nullptr; + return false; } - return vspace; -} - -bool ParallelCompactData::initialize_region_data(size_t heap_size) -{ - assert(is_aligned(heap_size, RegionSize), "precondition"); - - const size_t count = heap_size >> Log2RegionSize; - _region_vspace = create_vspace(count, sizeof(RegionData)); - if (_region_vspace != nullptr) { - _region_data = (RegionData*)_region_vspace->reserved_low_addr(); - _region_count = count; - return true; - } - return false; + _region_vspace = region_vspace; + _region_data = (RegionData*)_region_vspace->reserved_low_addr(); + _region_count = count; + return true; } void ParallelCompactData::clear_range(size_t beg_region, size_t end_region) { diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.hpp b/src/hotspot/share/gc/parallel/psParallelCompact.hpp index f5ab041fa97..25f4f66de6f 100644 --- a/src/hotspot/share/gc/parallel/psParallelCompact.hpp +++ b/src/hotspot/share/gc/parallel/psParallelCompact.hpp @@ -395,9 +395,6 @@ class ParallelCompactData #endif // #ifdef ASSERT private: - bool initialize_region_data(size_t heap_size); - PSVirtualSpace* create_vspace(size_t count, size_t element_size); - HeapWord* _heap_start; #ifdef ASSERT HeapWord* _heap_end; From 819533964cb0fc015f51cd1deb44649f87b06f94 Mon Sep 17 00:00:00 2001 From: Chen Liang Date: Tue, 31 Mar 2026 15:08:02 +0000 Subject: [PATCH 080/116] 8380913: Sealed graph taglet omits public subtypes of invisible subtypes Reviewed-by: hannesw, vromero --- .../build/tools/taglet/SealedGraph.java | 45 +++++--- .../TestSerializedFormWithClassFile.java | 4 +- .../TestVisibleMembers.java | 12 +-- .../jdk/javadoc/taglet/JdkTaglets.java | 53 +++++++++ .../taglet/sealedGraph/TestSealedTaglet.java | 101 ++++++++++++++++++ .../tools/lib/builder/AbstractBuilder.java | 9 +- .../tools/lib/builder/ClassBuilder.java | 48 ++++++--- test/langtools/tools/lib/toolbox/ToolBox.java | 23 +++- 8 files changed, 256 insertions(+), 39 deletions(-) create mode 100644 test/langtools/jdk/javadoc/taglet/JdkTaglets.java create mode 100644 test/langtools/jdk/javadoc/taglet/sealedGraph/TestSealedTaglet.java diff --git a/make/jdk/src/classes/build/tools/taglet/SealedGraph.java b/make/jdk/src/classes/build/tools/taglet/SealedGraph.java index 3e93826c180..2ffd92e3409 100644 --- a/make/jdk/src/classes/build/tools/taglet/SealedGraph.java +++ b/make/jdk/src/classes/build/tools/taglet/SealedGraph.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -138,20 +138,25 @@ private final class Renderer { // Generates a graph in DOT format String graph(TypeElement rootClass, Set exports) { + if (!isInPublicApi(rootClass, exports)) { + // Alternatively we can return "" for the graph since there is no single root to render + throw new IllegalArgumentException("Root not in public API: " + rootClass.getQualifiedName()); + } final State state = new State(rootClass); traverse(state, rootClass, exports); return state.render(); } static void traverse(State state, TypeElement node, Set exports) { + if (!isInPublicApi(node, exports)) { + throw new IllegalArgumentException("Bad request, not in public API: " + node.getQualifiedName()); + } state.addNode(node); if (!(node.getModifiers().contains(Modifier.SEALED) || node.getModifiers().contains(Modifier.FINAL))) { state.addNonSealedEdge(node); } else { for (TypeElement subNode : permittedSubclasses(node, exports)) { - if (isInPublicApi(node, exports) && isInPublicApi(subNode, exports)) { - state.addEdge(node, subNode); - } + state.addEdge(node, subNode); traverse(state, subNode, exports); } } @@ -292,14 +297,30 @@ private String simpleName(String name) { } private static List permittedSubclasses(TypeElement node, Set exports) { - return node.getPermittedSubclasses().stream() - .filter(DeclaredType.class::isInstance) - .map(DeclaredType.class::cast) - .map(DeclaredType::asElement) - .filter(TypeElement.class::isInstance) - .map(TypeElement.class::cast) - .filter(te -> isInPublicApi(te, exports)) - .toList(); + List dfsStack = new ArrayList().reversed(); // Faster operations to head + SequencedCollection result = new LinkedHashSet<>(); // Deduplicate diamond interface inheritance + // The starting node may be in the public API - still expand it + prependSubclasses(node, dfsStack); + + while (!dfsStack.isEmpty()) { + TypeElement now = dfsStack.removeFirst(); + if (isInPublicApi(now, exports)) { + result.addLast(now); + } else { + // Skip the non-exported classes in the hierarchy + prependSubclasses(now, dfsStack); + } + } + + return List.copyOf(result); + } + + private static void prependSubclasses(TypeElement node, List dfs) { + for (var e : node.getPermittedSubclasses().reversed()) { + if (e instanceof DeclaredType dt && dt.asElement() instanceof TypeElement te) { + dfs.addFirst(te); + } + } } private static boolean isInPublicApi(TypeElement typeElement, Set exports) { diff --git a/test/langtools/jdk/javadoc/doclet/testSerializedFormWithClassFile/TestSerializedFormWithClassFile.java b/test/langtools/jdk/javadoc/doclet/testSerializedFormWithClassFile/TestSerializedFormWithClassFile.java index 25613dffd95..1db0b6af8d4 100644 --- a/test/langtools/jdk/javadoc/doclet/testSerializedFormWithClassFile/TestSerializedFormWithClassFile.java +++ b/test/langtools/jdk/javadoc/doclet/testSerializedFormWithClassFile/TestSerializedFormWithClassFile.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -106,8 +106,8 @@ void createTestClass(Path base, Path srcDir) throws Exception { new JavacTask(tb).files(srcDir.resolve("A.java")).outdir(classes).run(); new ClassBuilder(tb, "B") - .setExtends("A") .setModifiers("public", "class") + .setExtends("A") .write(srcDir); } } diff --git a/test/langtools/jdk/javadoc/doclet/testVisibleMembers/TestVisibleMembers.java b/test/langtools/jdk/javadoc/doclet/testVisibleMembers/TestVisibleMembers.java index 09f6f92e2b6..fe5f1212b09 100644 --- a/test/langtools/jdk/javadoc/doclet/testVisibleMembers/TestVisibleMembers.java +++ b/test/langtools/jdk/javadoc/doclet/testVisibleMembers/TestVisibleMembers.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -135,7 +135,7 @@ void emitChronoDiamondLeaf(Path srcDir) throws Exception { "@param lvalue an lvalue", "@return something"); new ClassBuilder(tb, "p.B") - .setModifiers( "public", "interface") + .setModifiers("public", "interface") .setExtends("A") .addMembers(mbWith1, mbWith2) .write(srcDir); @@ -358,7 +358,7 @@ void emitStreamsMissingLinks(Path srcDir) throws Exception { MethodBuilder.parse("public I sub() {return null;}"), MethodBuilder.parse("public I sub1() {return null;}") .setComments(Kind.INHERIT_DOC), - MethodBuilder.parse(" public void method() {}") + MethodBuilder.parse("public void method() {}") .setComments("A method ", "@see #sub", "@see #sub1"), MethodBuilder.parse("public int length(){return 1;}") .setComments(Kind.NO_API_COMMENT) @@ -380,7 +380,7 @@ void emitStreamsMissingLinks(Path srcDir) throws Exception { ).write(srcDir); new ClassBuilder(tb, "p.QLong") - .setModifiers("public interface") + .setModifiers("public", "interface") .addMembers( MethodBuilder.parse("default void forEach(Q action) {}") ).write(srcDir); @@ -663,7 +663,7 @@ void emitHiddenMembers(Path srcDir) throws Exception { ).write(srcDir); new ClassBuilder(tb, "p.I3") - .setExtends("I1, I2") + .addImplements("I1", "I2") .setModifiers("public", "interface") .addMembers( FieldBuilder.parse("public static int field = 3;"), @@ -677,8 +677,8 @@ void emitHiddenMembers(Path srcDir) throws Exception { .write(srcDir); new ClassBuilder(tb, "p.C2") - .setExtends("C1") .setModifiers("public", "abstract", "class") + .setExtends("C1") .addMembers( FieldBuilder.parse("public int field;"), MethodBuilder.parse("public void method(){}"), diff --git a/test/langtools/jdk/javadoc/taglet/JdkTaglets.java b/test/langtools/jdk/javadoc/taglet/JdkTaglets.java new file mode 100644 index 00000000000..537904450aa --- /dev/null +++ b/test/langtools/jdk/javadoc/taglet/JdkTaglets.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.nio.file.Files; +import java.nio.file.Path; +import java.util.stream.Stream; + +import toolbox.JavacTask; +import toolbox.ToolBox; + +/// Utilities to build the JDK-specific taglets. +/// This guy uses JavacTask so can't be in javadoc.tester. +public final class JdkTaglets { + + /// Build a taglet and return its path for `-tagletpath`. + public static Path build(ToolBox tb, Path base, String... tagletFiles) throws IOException { + Path tagletOutDir = base.resolve("tagletClasses"); + Files.createDirectories(tagletOutDir); + tb.cleanDirectory(tagletOutDir); + Path tagletRoot = tb.findFromTestRoot("../../make/jdk/src/classes/build/tools/taglet"); + + new JavacTask(tb) + .files(Stream.of(tagletFiles) + .map(tagletFile -> tagletRoot.resolve(tagletFile + ".java")) + .toArray(Path[]::new)) + .outdir(tagletOutDir) + .run(JavacTask.Expect.SUCCESS); + return tagletOutDir; + } + + private JdkTaglets() {} +} diff --git a/test/langtools/jdk/javadoc/taglet/sealedGraph/TestSealedTaglet.java b/test/langtools/jdk/javadoc/taglet/sealedGraph/TestSealedTaglet.java new file mode 100644 index 00000000000..3ac6f0601b2 --- /dev/null +++ b/test/langtools/jdk/javadoc/taglet/sealedGraph/TestSealedTaglet.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 General tests for SealedGraph block tag + * @bug 8380913 + * @library /tools/lib /jdk/javadoc/lib ../ + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + * jdk.javadoc/jdk.javadoc.internal.tool + * @build javadoc.tester.* toolbox.ToolBox builder.ClassBuilder JdkTaglets + * @run main ${test.main.class} + */ + +import java.nio.file.Path; + +import builder.ClassBuilder; +import javadoc.tester.JavadocTester; +import toolbox.ToolBox; + +public class TestSealedTaglet extends JavadocTester { + + final ToolBox tb; + final Path tagletPath; + + public static void main(String... args) throws Exception { + var tester = new TestSealedTaglet(); + tester.runTests(); + } + + TestSealedTaglet() throws Exception { + tb = new ToolBox(); + tagletPath = JdkTaglets.build(tb, Path.of(""), "SealedGraph"); + setAutomaticCheckLinks(false); // Don't fail for missing svg + } + + @Test + public void testInvisibleInMiddle(Path base) throws Exception { + Path srcDir = base.resolve("src"); + Path outDir = base.resolve("out"); + + tb.writeFile(srcDir.resolve("module-info.java"), + """ + module test { + exports pkg; + } + """); + new ClassBuilder(tb, "pkg.A") + .setModifiers("public", "abstract", "sealed", "interface") + .setComments("@sealedGraph") + .addPermits("pkg.B") + .write(srcDir); + new ClassBuilder(tb, "pkg.B") + .setModifiers("abstract", "sealed", "interface") + .addImplements("pkg.A") + .addPermits("pkg.C", "pkg.D") + .write(srcDir); + new ClassBuilder(tb, "pkg.C") + .setModifiers("abstract", "sealed", "interface") + .addImplements("pkg.A", "pkg.B") + .addPermits("pkg.D") + .write(srcDir); + new ClassBuilder(tb, "pkg.D") + .setModifiers("public", "final", "class") + .addImplements("pkg.B", "pkg.C") + .write(srcDir); + + System.setProperty("sealedDotOutputDir", outDir.toString()); + + javadoc("-tagletpath", tagletPath.toString(), + "-taglet", "build.tools.taglet.SealedGraph", + "-d", outDir.toString(), + "-sourcepath", srcDir.toString(), + "pkg"); + + checkExit(Exit.OK); + // D is displayed as a direct subtype of A, bypassing B, C, one link only + checkUnique("test_pkg.A.dot", "\"pkg.D\" -> \"pkg.A\";"); + } +} diff --git a/test/langtools/tools/lib/builder/AbstractBuilder.java b/test/langtools/tools/lib/builder/AbstractBuilder.java index e528fe60792..4717f456d08 100644 --- a/test/langtools/tools/lib/builder/AbstractBuilder.java +++ b/test/langtools/tools/lib/builder/AbstractBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -203,6 +203,13 @@ public void setModifiers(List modifiers) { this.modifiers = modifiers; } + boolean isInterface() { + if (modifiers.isEmpty()) { + throw new IllegalStateException("modifiers not initialized"); + } + return modifiers.getLast().endsWith("interface"); + } + @Override public String toString() { OutputWriter ow = new OutputWriter(); diff --git a/test/langtools/tools/lib/builder/ClassBuilder.java b/test/langtools/tools/lib/builder/ClassBuilder.java index feafa77db56..2c57f0e0c13 100644 --- a/test/langtools/tools/lib/builder/ClassBuilder.java +++ b/test/langtools/tools/lib/builder/ClassBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.ListIterator; import java.util.regex.Matcher; @@ -54,6 +55,7 @@ public class ClassBuilder extends AbstractBuilder { private String extendsType; private final List implementsTypes; + private final List permitsTypes; private final List members; private final List inners; private final List nested; @@ -86,6 +88,7 @@ public ClassBuilder(ToolBox tb, String name) { } imports = new ArrayList<>(); implementsTypes = new ArrayList<>(); + permitsTypes = new ArrayList<>(); members = new ArrayList<>(); nested = new ArrayList<>(); inners = new ArrayList<>(); @@ -153,7 +156,11 @@ public ClassBuilder setComments(Comment.Kind kind) { * @return this builder. */ public ClassBuilder setExtends(String name) { - extendsType = name; + if (modifiers.isInterface()) { + implementsTypes.add(name); + } else { + extendsType = name; + } return this; } @@ -163,7 +170,17 @@ public ClassBuilder setExtends(String name) { * @return this builder. */ public ClassBuilder addImplements(String... names) { - implementsTypes.addAll(List.of(names)); + implementsTypes.addAll(Arrays.asList(names)); + return this; + } + + /** + * Adds a permits declaration(s). + * @param names the subtypes + * @return this builder + */ + public ClassBuilder addPermits(String... names) { + permitsTypes.addAll(Arrays.asList(names)); return this; } @@ -225,28 +242,25 @@ public String toString() { ow.println("// NO_API_COMMENT"); break; } + assert !modifiers.modifiers.isEmpty(); ow.print(modifiers.toString()); ow.print(clsname); if (typeParameter != null) { - ow.print(typeParameter + " "); - } else { - ow.print(" "); + ow.print(typeParameter); } if (extendsType != null && !extendsType.isEmpty()) { - ow.print("extends " + extendsType + " "); + assert !modifiers.isInterface(); + ow.print(" extends " + extendsType); } if (!implementsTypes.isEmpty()) { - ow.print("implements "); - - ListIterator iter = implementsTypes.listIterator(); - while (iter.hasNext()) { - String s = iter.next() ; - ow.print(s); - if (iter.hasNext()) - ow.print(", "); - } + ow.print(modifiers.isInterface() ? " extends " : " implements "); + ow.print(String.join(", ", implementsTypes)); + } + if (!permitsTypes.isEmpty()) { + ow.print(" permits "); + ow.print(String.join(", ", permitsTypes)); } - ow.print("{"); + ow.print(" {"); if (!nested.isEmpty()) { ow.println(""); nested.forEach(m -> ow.println(m.toString())); diff --git a/test/langtools/tools/lib/toolbox/ToolBox.java b/test/langtools/tools/lib/toolbox/ToolBox.java index ee217ab2c0c..1cb2fa6d3f9 100644 --- a/test/langtools/tools/lib/toolbox/ToolBox.java +++ b/test/langtools/tools/lib/toolbox/ToolBox.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -666,6 +666,27 @@ public Path getJDKTool(String tool) { return Path.of(testJDK, "bin", tool); } + /** + * Finds a file with a path relative to the langtools test root directory. + * + * @param path the desired path from test/langtools + * @return the file, if found + */ + public Path findFromTestRoot(String path) { + Path testSrc = Path.of(System.getProperty("test.src", ".")); + + for (Path d = testSrc; d != null; d = d.getParent()) { + if (Files.exists(d.resolve("TEST.ROOT"))) { + Path file = d.resolve(path); + if (Files.exists(file)) { + return file; + } + } + } + + return null; + } + /** * Returns a string representing the contents of an {@code Iterable} as a list. * From 74eff77554acf6186e7f12546215efb493d0f90d Mon Sep 17 00:00:00 2001 From: Matias Saavedra Silva Date: Tue, 31 Mar 2026 15:51:40 +0000 Subject: [PATCH 081/116] 8347462: Improve TraceClassLoading to add link information Reviewed-by: dholmes, coleenp --- src/hotspot/share/oops/instanceKlass.cpp | 6 ++ .../jtreg/runtime/logging/LogLinkingTest.java | 48 ++++++++++++++ .../logging/classes/test/LinkageErrorApp.java | 64 +++++++++++++++++++ 3 files changed, 118 insertions(+) create mode 100644 test/hotspot/jtreg/runtime/logging/LogLinkingTest.java create mode 100644 test/hotspot/jtreg/runtime/logging/classes/test/LinkageErrorApp.java diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp index d3333e72c2a..cb071f2abf0 100644 --- a/src/hotspot/share/oops/instanceKlass.cpp +++ b/src/hotspot/share/oops/instanceKlass.cpp @@ -1121,6 +1121,12 @@ bool InstanceKlass::link_class_impl(TRAPS) { } } } + + if (log_is_enabled(Info, class, link)) { + ResourceMark rm(THREAD); + log_info(class, link)("Linked class %s", external_name()); + } + return true; } diff --git a/test/hotspot/jtreg/runtime/logging/LogLinkingTest.java b/test/hotspot/jtreg/runtime/logging/LogLinkingTest.java new file mode 100644 index 00000000000..86958a60ca0 --- /dev/null +++ b/test/hotspot/jtreg/runtime/logging/LogLinkingTest.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 LogLinkingTest + * @bug 8347462 + * @library /test/lib + * @library classes + * @requires vm.flagless + * @build test.LinkageErrorApp + * @run driver LogLinkingTest + */ + +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.process.OutputAnalyzer; + +public class LogLinkingTest { + public static void main(String[] args) throws Exception { + ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-Xlog:class+load,class+link", "LinkageErrorApp"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldHaveExitValue(1); + output.shouldMatch("class,load.*SingleDefinition source"); + output.shouldMatch("class,load.*DuplicateDefinition source"); + output.shouldMatch("class,link.*Linked class.*SingleDefinition"); + output.shouldNotMatch("class,link.*Linked class.*DuplicateDefinition"); + } +} diff --git a/test/hotspot/jtreg/runtime/logging/classes/test/LinkageErrorApp.java b/test/hotspot/jtreg/runtime/logging/classes/test/LinkageErrorApp.java new file mode 100644 index 00000000000..79b8781a468 --- /dev/null +++ b/test/hotspot/jtreg/runtime/logging/classes/test/LinkageErrorApp.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 LinkageErrorApp { + + static class SingleDefinition { } + static class DuplicateDefinition { } + + static class DuplicateLoader extends ClassLoader { + DuplicateLoader() { + super(null); + } + + Class define(byte[] bytes, String classname) { + return defineClass(classname, bytes, 0, bytes.length); + } + } + + private static byte[] readClassBytes(Class clazz) throws IOException { + String resource = clazz.getName().replace('.', '/') + ".class"; + ClassLoader loader = clazz.getClassLoader(); + if (loader != null) { + InputStream in = loader.getResourceAsStream(resource); + if (in == null) { + throw new RuntimeException("Could not find " + clazz.getName()); + } + return in.readAllBytes(); + } + return null; + } + + public static void main(String[] args) throws Exception { + byte[] duplicateDefBytes = readClassBytes(DuplicateDefinition.class); + DuplicateLoader loader = new DuplicateLoader(); + + SingleDefinition s = new SingleDefinition(); + loader.define(duplicateDefBytes, "LinkageErrorApp$DuplicateDefinition"); + // This will throw a LinkageError + loader.define(duplicateDefBytes, "LinkageErrorApp$DuplicateDefinition"); + } +} From ba34f300db6388d343dd9c496de4830dc62d31a7 Mon Sep 17 00:00:00 2001 From: Dingli Zhang Date: Tue, 31 Mar 2026 15:56:48 +0000 Subject: [PATCH 082/116] 8381250: Enable VectorLogicalOpIdentityTest.java IR tests for RISC-V Reviewed-by: fyang --- .../vectorapi/VectorLogicalOpIdentityTest.java | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/test/hotspot/jtreg/compiler/vectorapi/VectorLogicalOpIdentityTest.java b/test/hotspot/jtreg/compiler/vectorapi/VectorLogicalOpIdentityTest.java index 1a2402222ed..df178f5363e 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/VectorLogicalOpIdentityTest.java +++ b/test/hotspot/jtreg/compiler/vectorapi/VectorLogicalOpIdentityTest.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2022, 2023, Arm Limited. All rights reserved. - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,7 +45,8 @@ * @key randomness * @library /test/lib / * @summary Add identity transformations for vector logic operations - * @requires (os.simpleArch == "x64" & vm.cpu.features ~= ".*avx.*") | os.arch=="aarch64" + * @requires (os.simpleArch == "x64" & vm.cpu.features ~= ".*avx.*") | os.arch=="aarch64" | + (os.arch == "riscv64" & vm.cpu.features ~= ".*rvv.*") * @modules jdk.incubator.vector * * @run driver compiler.vectorapi.VectorLogicalOpIdentityTest @@ -302,7 +303,7 @@ public static void testAndSameValue4() { // Transform AndV(AndV(a, b, m), b, m) ==> AndV(a, b, m) @Test @Warmup(10000) - @IR(counts = {IRNode.AND_VI, "1"}, applyIfCPUFeatureOr = {"sve", "true", "avx512", "true"}) + @IR(counts = {IRNode.AND_VI, "1"}, applyIfCPUFeatureOr = {"sve", "true", "avx512", "true", "rvv", "true"}) public static void testAndMaskSameValue1() { VectorMask mask = VectorMask.fromArray(I_SPECIES, m, 0); IntVector av = IntVector.fromArray(I_SPECIES, ia, 0); @@ -323,7 +324,7 @@ public static void testAndMaskSameValue1() { // Transform AndV(AndV(a, b, m), a, m) ==> AndV(a, b, m) @Test @Warmup(10000) - @IR(counts = {IRNode.AND_VL, "1"}, applyIfCPUFeatureOr = {"sve", "true", "avx512", "true"}) + @IR(counts = {IRNode.AND_VL, "1"}, applyIfCPUFeatureOr = {"sve", "true", "avx512", "true", "rvv", "true"}) public static void testAndMaskSameValue2() { VectorMask mask = VectorMask.fromArray(L_SPECIES, m, 0); LongVector av = LongVector.fromArray(L_SPECIES, la, 0); @@ -344,7 +345,7 @@ public static void testAndMaskSameValue2() { // Transform AndV(a, AndV(a, b, m), m) ==> AndV(a, b, m) @Test @Warmup(10000) - @IR(counts = {IRNode.AND_VI, "1"}, applyIfCPUFeatureOr = {"sve", "true", "avx512", "true"}) + @IR(counts = {IRNode.AND_VI, "1"}, applyIfCPUFeatureOr = {"sve", "true", "avx512", "true", "rvv", "true"}) public static void testAndMaskSameValue3() { VectorMask mask = VectorMask.fromArray(I_SPECIES, m, 0); IntVector av = IntVector.fromArray(I_SPECIES, ia, 0); @@ -566,7 +567,7 @@ public static void testOrSameValue4() { // Transform OrV(OrV(a, b, m), b, m) ==> OrV(a, b, m) @Test @Warmup(10000) - @IR(counts = {IRNode.OR_VI, "1"}, applyIfCPUFeatureOr = {"sve", "true", "avx512", "true"}) + @IR(counts = {IRNode.OR_VI, "1"}, applyIfCPUFeatureOr = {"sve", "true", "avx512", "true", "rvv", "true"}) public static void testOrMaskSameValue1() { VectorMask mask = VectorMask.fromArray(I_SPECIES, m, 0); IntVector av = IntVector.fromArray(I_SPECIES, ia, 0); @@ -587,7 +588,7 @@ public static void testOrMaskSameValue1() { // Transform OrV(OrV(a, b, m), a, m) ==> OrV(a, b, m) @Test @Warmup(10000) - @IR(counts = {IRNode.OR_VL, "1"}, applyIfCPUFeatureOr = {"sve", "true", "avx512", "true"}) + @IR(counts = {IRNode.OR_VL, "1"}, applyIfCPUFeatureOr = {"sve", "true", "avx512", "true", "rvv", "true"}) public static void testOrMaskSameValue2() { VectorMask mask = VectorMask.fromArray(L_SPECIES, m, 0); LongVector av = LongVector.fromArray(L_SPECIES, la, 0); @@ -608,7 +609,7 @@ public static void testOrMaskSameValue2() { // Transform OrV(a, OrV(a, b, m), m) ==> OrV(a, b, m) @Test @Warmup(10000) - @IR(counts = {IRNode.OR_VI, "1"}, applyIfCPUFeatureOr = {"sve", "true", "avx512", "true"}) + @IR(counts = {IRNode.OR_VI, "1"}, applyIfCPUFeatureOr = {"sve", "true", "avx512", "true", "rvv", "true"}) public static void testOrMaskSameValue3() { VectorMask mask = VectorMask.fromArray(I_SPECIES, m, 0); IntVector av = IntVector.fromArray(I_SPECIES, ia, 0); From 207bb159b2bc53348599b256c3b3b16137c6b4b0 Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Tue, 31 Mar 2026 16:52:34 +0000 Subject: [PATCH 083/116] 8381409: Fix whitespace and variable name in classfile code Reviewed-by: liach, lfoltan --- .../share/classfile/classFileParser.cpp | 18 +++++----- .../share/classfile/fieldLayoutBuilder.cpp | 26 +++++++------- .../share/classfile/fieldLayoutBuilder.hpp | 6 ++-- .../share/classfile/stackMapTableFormat.hpp | 35 ++++++++++++------- .../share/classfile/systemDictionary.cpp | 4 +-- 5 files changed, 50 insertions(+), 39 deletions(-) diff --git a/src/hotspot/share/classfile/classFileParser.cpp b/src/hotspot/share/classfile/classFileParser.cpp index c1f00cbe536..404693f5cee 100644 --- a/src/hotspot/share/classfile/classFileParser.cpp +++ b/src/hotspot/share/classfile/classFileParser.cpp @@ -194,7 +194,7 @@ void ClassFileParser::parse_constant_pool_entries(const ClassFileStream* const s // so we don't need bounds-check for reading tag. const u1 tag = cfs->get_u1_fast(); switch (tag) { - case JVM_CONSTANT_Class : { + case JVM_CONSTANT_Class: { cfs->guarantee_more(3, CHECK); // name_index, tag/access_flags const u2 name_index = cfs->get_u2_fast(); cp->klass_index_at_put(index, name_index); @@ -4403,14 +4403,14 @@ void ClassFileParser::verify_legal_field_modifiers(jint flags, TRAPS) const { if (!_need_verify) { return; } - const bool is_public = (flags & JVM_ACC_PUBLIC) != 0; - const bool is_protected = (flags & JVM_ACC_PROTECTED) != 0; - const bool is_private = (flags & JVM_ACC_PRIVATE) != 0; - const bool is_static = (flags & JVM_ACC_STATIC) != 0; - const bool is_final = (flags & JVM_ACC_FINAL) != 0; - const bool is_volatile = (flags & JVM_ACC_VOLATILE) != 0; - const bool is_transient = (flags & JVM_ACC_TRANSIENT) != 0; - const bool is_enum = (flags & JVM_ACC_ENUM) != 0; + const bool is_public = (flags & JVM_ACC_PUBLIC) != 0; + const bool is_protected = (flags & JVM_ACC_PROTECTED) != 0; + const bool is_private = (flags & JVM_ACC_PRIVATE) != 0; + const bool is_static = (flags & JVM_ACC_STATIC) != 0; + const bool is_final = (flags & JVM_ACC_FINAL) != 0; + const bool is_volatile = (flags & JVM_ACC_VOLATILE) != 0; + const bool is_transient = (flags & JVM_ACC_TRANSIENT) != 0; + const bool is_enum = (flags & JVM_ACC_ENUM) != 0; const bool major_gte_1_5 = _major_version >= JAVA_1_5_VERSION; bool is_illegal = false; diff --git a/src/hotspot/share/classfile/fieldLayoutBuilder.cpp b/src/hotspot/share/classfile/fieldLayoutBuilder.cpp index 8a9f5946091..adf4e1e63fa 100644 --- a/src/hotspot/share/classfile/fieldLayoutBuilder.cpp +++ b/src/hotspot/share/classfile/fieldLayoutBuilder.cpp @@ -37,7 +37,7 @@ LayoutRawBlock::LayoutRawBlock(Kind kind, int size) : _next_block(nullptr), _prev_block(nullptr), - _kind(kind), + _block_kind(kind), _offset(-1), _alignment(1), _size(size), @@ -52,7 +52,7 @@ LayoutRawBlock::LayoutRawBlock(Kind kind, int size) : LayoutRawBlock::LayoutRawBlock(int index, Kind kind, int size, int alignment, bool is_reference) : _next_block(nullptr), _prev_block(nullptr), - _kind(kind), + _block_kind(kind), _offset(-1), _alignment(alignment), _size(size), @@ -148,8 +148,8 @@ void FieldLayout::initialize_instance_layout(const InstanceKlass* super_klass, b LayoutRawBlock* FieldLayout::first_field_block() { LayoutRawBlock* block = _start; - while (block->kind() != LayoutRawBlock::INHERITED && block->kind() != LayoutRawBlock::REGULAR - && block->kind() != LayoutRawBlock::FLATTENED && block->kind() != LayoutRawBlock::PADDING) { + while (block->block_kind() != LayoutRawBlock::INHERITED && block->block_kind() != LayoutRawBlock::REGULAR + && block->block_kind() != LayoutRawBlock::FLATTENED && block->block_kind() != LayoutRawBlock::PADDING) { block = block->next_block(); } return block; @@ -190,7 +190,7 @@ void FieldLayout::add(GrowableArray* list, LayoutRawBlock* star assert(cursor != nullptr, "Sanity check"); last_search_success = true; while (cursor != start) { - if (cursor->kind() == LayoutRawBlock::EMPTY && cursor->fit(b->size(), b->alignment())) { + if (cursor->block_kind() == LayoutRawBlock::EMPTY && cursor->fit(b->size(), b->alignment())) { if (candidate == nullptr || cursor->size() < candidate->size()) { candidate = cursor; } @@ -202,7 +202,7 @@ void FieldLayout::add(GrowableArray* list, LayoutRawBlock* star last_search_success = false; } assert(candidate != nullptr, "Candidate must not be null"); - assert(candidate->kind() == LayoutRawBlock::EMPTY, "Candidate must be an empty block"); + assert(candidate->block_kind() == LayoutRawBlock::EMPTY, "Candidate must be an empty block"); assert(candidate->fit(b->size(), b->alignment()), "Candidate must be able to store the block"); } @@ -221,7 +221,7 @@ void FieldLayout::add_field_at_offset(LayoutRawBlock* block, int offset, LayoutR while (slot != nullptr) { if ((slot->offset() <= block->offset() && (slot->offset() + slot->size()) > block->offset()) || slot == _last){ - assert(slot->kind() == LayoutRawBlock::EMPTY, "Matching slot must be an empty slot"); + assert(slot->block_kind() == LayoutRawBlock::EMPTY, "Matching slot must be an empty slot"); assert(slot->size() >= block->offset() + block->size() ,"Matching slot must be big enough"); if (slot->offset() < block->offset()) { int adjustment = block->offset() - slot->offset(); @@ -261,7 +261,7 @@ void FieldLayout::add_contiguously(GrowableArray* list, LayoutR } else { LayoutRawBlock* first = list->at(0); candidate = last_block()->prev_block(); - while (candidate->kind() != LayoutRawBlock::EMPTY || !candidate->fit(size, first->alignment())) { + while (candidate->block_kind() != LayoutRawBlock::EMPTY || !candidate->fit(size, first->alignment())) { if (candidate == start) { candidate = last_block(); break; @@ -269,7 +269,7 @@ void FieldLayout::add_contiguously(GrowableArray* list, LayoutR candidate = candidate->prev_block(); } assert(candidate != nullptr, "Candidate must not be null"); - assert(candidate->kind() == LayoutRawBlock::EMPTY, "Candidate must be an empty block"); + assert(candidate->block_kind() == LayoutRawBlock::EMPTY, "Candidate must be an empty block"); assert(candidate->fit(size, first->alignment()), "Candidate must be able to store the whole contiguous block"); } @@ -281,7 +281,7 @@ void FieldLayout::add_contiguously(GrowableArray* list, LayoutR } LayoutRawBlock* FieldLayout::insert_field_block(LayoutRawBlock* slot, LayoutRawBlock* block) { - assert(slot->kind() == LayoutRawBlock::EMPTY, "Blocks can only be inserted in empty blocks"); + assert(slot->block_kind() == LayoutRawBlock::EMPTY, "Blocks can only be inserted in empty blocks"); if (slot->offset() % block->alignment() != 0) { int adjustment = block->alignment() - (slot->offset() % block->alignment()); LayoutRawBlock* adj = new LayoutRawBlock(LayoutRawBlock::EMPTY, adjustment); @@ -362,7 +362,7 @@ void FieldLayout::fill_holes(const InstanceKlass* super_klass) { b = b->next_block(); } assert(b->next_block() == nullptr, "Invariant at this point"); - assert(b->kind() != LayoutRawBlock::EMPTY, "Sanity check"); + assert(b->block_kind() != LayoutRawBlock::EMPTY, "Sanity check"); // If the super class has @Contended annotation, a padding block is // inserted at the end to ensure that fields from the subclasses won't share @@ -384,7 +384,7 @@ void FieldLayout::fill_holes(const InstanceKlass* super_klass) { } LayoutRawBlock* FieldLayout::insert(LayoutRawBlock* slot, LayoutRawBlock* block) { - assert(slot->kind() == LayoutRawBlock::EMPTY, "Blocks can only be inserted in empty blocks"); + assert(slot->block_kind() == LayoutRawBlock::EMPTY, "Blocks can only be inserted in empty blocks"); assert(slot->offset() % block->alignment() == 0, "Incompatible alignment"); block->set_offset(slot->offset()); slot->set_offset(slot->offset() + block->size()); @@ -425,7 +425,7 @@ void FieldLayout::print(outputStream* output, bool is_static, const InstanceKlas ResourceMark rm; LayoutRawBlock* b = _blocks; while(b != _last) { - switch(b->kind()) { + switch(b->block_kind()) { case LayoutRawBlock::REGULAR: { FieldInfo* fi = _field_info->adr_at(b->field_index()); output->print_cr(" @%d \"%s\" %s %d/%d %s", diff --git a/src/hotspot/share/classfile/fieldLayoutBuilder.hpp b/src/hotspot/share/classfile/fieldLayoutBuilder.hpp index eab0b7d08a9..a45131ec9a3 100644 --- a/src/hotspot/share/classfile/fieldLayoutBuilder.hpp +++ b/src/hotspot/share/classfile/fieldLayoutBuilder.hpp @@ -65,7 +65,7 @@ class LayoutRawBlock : public ResourceObj { private: LayoutRawBlock* _next_block; LayoutRawBlock* _prev_block; - Kind _kind; + Kind _block_kind; int _offset; int _alignment; int _size; @@ -79,7 +79,7 @@ class LayoutRawBlock : public ResourceObj { void set_next_block(LayoutRawBlock* next) { _next_block = next; } LayoutRawBlock* prev_block() const { return _prev_block; } void set_prev_block(LayoutRawBlock* prev) { _prev_block = prev; } - Kind kind() const { return _kind; } + Kind block_kind() const { return _block_kind; } int offset() const { assert(_offset >= 0, "Must be initialized"); return _offset; @@ -173,7 +173,7 @@ class FieldLayout : public ResourceObj { LayoutRawBlock* first_empty_block() { LayoutRawBlock* block = _start; - while (block->kind() != LayoutRawBlock::EMPTY) { + while (block->block_kind() != LayoutRawBlock::EMPTY) { block = block->next_block(); } return block; diff --git a/src/hotspot/share/classfile/stackMapTableFormat.hpp b/src/hotspot/share/classfile/stackMapTableFormat.hpp index 2b89c53278a..4906f4b9d80 100644 --- a/src/hotspot/share/classfile/stackMapTableFormat.hpp +++ b/src/hotspot/share/classfile/stackMapTableFormat.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -221,9 +221,11 @@ class stack_map_frame { class same_frame : public stack_map_frame { private: static int frame_type_to_offset_delta(u1 frame_type) { - return frame_type + 1; } + return frame_type + 1; + } static u1 offset_delta_to_frame_type(int offset_delta) { - return checked_cast(offset_delta - 1); } + return checked_cast(offset_delta - 1); + } public: @@ -327,9 +329,11 @@ class same_locals_1_stack_item_frame : public stack_map_frame { address type_addr() const { return frame_type_addr() + sizeof(u1); } static int frame_type_to_offset_delta(u1 frame_type) { - return frame_type - 63; } + return frame_type - 63; + } static u1 offset_delta_to_frame_type(int offset_delta) { - return (u1)(offset_delta + 63); } + return (u1)(offset_delta + 63); + } public: static bool is_frame_type(u1 tag) { @@ -657,9 +661,11 @@ class full_frame : public stack_map_frame { address num_locals_addr() const { return offset_delta_addr() + sizeof(u2); } address locals_addr() const { return num_locals_addr() + sizeof(u2); } address stack_slots_addr(address end_of_locals) const { - return end_of_locals; } + return end_of_locals; + } address stack_addr(address end_of_locals) const { - return stack_slots_addr(end_of_locals) + sizeof(u2); } + return stack_slots_addr(end_of_locals) + sizeof(u2); + } enum { _frame_id = 255 }; @@ -930,11 +936,14 @@ class stack_map_table { class stack_map_table_attribute { private: address name_index_addr() const { - return (address)this; } + return (address)this; + } address attribute_length_addr() const { - return name_index_addr() + sizeof(u2); } + return name_index_addr() + sizeof(u2); + } address stack_map_table_addr() const { - return attribute_length_addr() + sizeof(u4); } + return attribute_length_addr() + sizeof(u4); + } NONCOPYABLE(stack_map_table_attribute); protected: @@ -948,9 +957,11 @@ class stack_map_table_attribute { } u2 name_index() const { - return Bytes::get_Java_u2(name_index_addr()); } + return Bytes::get_Java_u2(name_index_addr()); + } u4 attribute_length() const { - return Bytes::get_Java_u4(attribute_length_addr()); } + return Bytes::get_Java_u4(attribute_length_addr()); + } stack_map_table* table() const { return stack_map_table::at(stack_map_table_addr()); } diff --git a/src/hotspot/share/classfile/systemDictionary.cpp b/src/hotspot/share/classfile/systemDictionary.cpp index 0b47c749df8..8483551fd4f 100644 --- a/src/hotspot/share/classfile/systemDictionary.cpp +++ b/src/hotspot/share/classfile/systemDictionary.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -416,7 +416,7 @@ static inline void log_circularity_error(Symbol* name, PlaceholderEntry* probe) // // resolve_with_circularity_detection adds a DETECT_CIRCULARITY placeholder to the placeholder table before calling // resolve_instance_class_or_null. ClassCircularityError is detected when a DETECT_CIRCULARITY or LOAD_INSTANCE -// placeholder for the same thread, class, classloader is found. +// placeholder for the same thread, class, and classloader is found. // This can be seen with logging option: -Xlog:class+load+placeholders=debug. // InstanceKlass* SystemDictionary::resolve_with_circularity_detection(Symbol* class_name, From abeceb1f8c7b09a396c5152f499c84d3c72a920b Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Tue, 31 Mar 2026 17:07:33 +0000 Subject: [PATCH 084/116] 8379687: Reduce C heap usage when VerifyMethodHandles flags is on Reviewed-by: mhaessig, chagedorn --- src/hotspot/cpu/arm/methodHandles_arm.cpp | 9 ++++----- src/hotspot/cpu/ppc/methodHandles_ppc.cpp | 13 ++++++------- src/hotspot/cpu/s390/methodHandles_s390.cpp | 14 +++++--------- src/hotspot/cpu/x86/methodHandles_x86.cpp | 13 ++++++------- src/hotspot/share/prims/methodHandles.cpp | 13 +++++++++++++ src/hotspot/share/prims/methodHandles.hpp | 2 ++ 6 files changed, 36 insertions(+), 28 deletions(-) diff --git a/src/hotspot/cpu/arm/methodHandles_arm.cpp b/src/hotspot/cpu/arm/methodHandles_arm.cpp index 3710fa33f36..2da14d8ffed 100644 --- a/src/hotspot/cpu/arm/methodHandles_arm.cpp +++ b/src/hotspot/cpu/arm/methodHandles_arm.cpp @@ -104,14 +104,13 @@ void MethodHandles::verify_ref_kind(MacroAssembler* _masm, int ref_kind, Registe __ andr(temp, temp, (unsigned)java_lang_invoke_MemberName::MN_REFERENCE_KIND_MASK); __ cmp(temp, ref_kind); __ b(L, eq); - { char* buf = NEW_C_HEAP_ARRAY(char, 100, mtInternal); - jio_snprintf(buf, 100, "verify_ref_kind expected %x", ref_kind); + const char* msg = ref_kind_to_verify_msg(ref_kind); if (ref_kind == JVM_REF_invokeVirtual || - ref_kind == JVM_REF_invokeSpecial) + ref_kind == JVM_REF_invokeSpecial) { // could do this for all ref_kinds, but would explode assembly code size - trace_method_handle(_masm, buf); - __ stop(buf); + trace_method_handle(_masm, msg); } + __ stop(msg); BLOCK_COMMENT("} verify_ref_kind"); __ bind(L); } diff --git a/src/hotspot/cpu/ppc/methodHandles_ppc.cpp b/src/hotspot/cpu/ppc/methodHandles_ppc.cpp index 45537e0ea96..ae94a9618b5 100644 --- a/src/hotspot/cpu/ppc/methodHandles_ppc.cpp +++ b/src/hotspot/cpu/ppc/methodHandles_ppc.cpp @@ -104,14 +104,13 @@ void MethodHandles::verify_ref_kind(MacroAssembler* _masm, int ref_kind, Registe __ andi(temp, temp, java_lang_invoke_MemberName::MN_REFERENCE_KIND_MASK); __ cmpwi(CR1, temp, ref_kind); __ beq(CR1, L); - { char* buf = NEW_C_HEAP_ARRAY(char, 100, mtInternal); - jio_snprintf(buf, 100, "verify_ref_kind expected %x", ref_kind); - if (ref_kind == JVM_REF_invokeVirtual || - ref_kind == JVM_REF_invokeSpecial) - // could do this for all ref_kinds, but would explode assembly code size - trace_method_handle(_masm, buf); - __ stop(buf); + const char* msg = ref_kind_to_verify_msg(ref_kind); + if (ref_kind == JVM_REF_invokeVirtual || + ref_kind == JVM_REF_invokeSpecial) { + // could do this for all ref_kinds, but would explode assembly code size + trace_method_handle(_masm, msg); } + __ stop(msg); BLOCK_COMMENT("} verify_ref_kind"); __ BIND(L); } diff --git a/src/hotspot/cpu/s390/methodHandles_s390.cpp b/src/hotspot/cpu/s390/methodHandles_s390.cpp index e3de6d911be..dfb8ce09b27 100644 --- a/src/hotspot/cpu/s390/methodHandles_s390.cpp +++ b/src/hotspot/cpu/s390/methodHandles_s390.cpp @@ -120,16 +120,12 @@ void MethodHandles::verify_ref_kind(MacroAssembler* _masm, int ref_kind, __ z_nilf(temp, java_lang_invoke_MemberName::MN_REFERENCE_KIND_MASK); __ compare32_and_branch(temp, constant(ref_kind), Assembler::bcondEqual, L); - { - char *buf = NEW_C_HEAP_ARRAY(char, 100, mtInternal); - - jio_snprintf(buf, 100, "verify_ref_kind expected %x", ref_kind); - if (ref_kind == JVM_REF_invokeVirtual || ref_kind == JVM_REF_invokeSpecial) { - // Could do this for all ref_kinds, but would explode assembly code size. - trace_method_handle(_masm, buf); - } - __ stop(buf); + const char* msg = ref_kind_to_verify_msg(ref_kind); + if (ref_kind == JVM_REF_invokeVirtual || ref_kind == JVM_REF_invokeSpecial) { + // Could do this for all ref_kinds, but would explode assembly code size. + trace_method_handle(_masm, msg); } + __ stop(msg); BLOCK_COMMENT("} verify_ref_kind"); diff --git a/src/hotspot/cpu/x86/methodHandles_x86.cpp b/src/hotspot/cpu/x86/methodHandles_x86.cpp index 54376c6ad9a..5b15444bc32 100644 --- a/src/hotspot/cpu/x86/methodHandles_x86.cpp +++ b/src/hotspot/cpu/x86/methodHandles_x86.cpp @@ -110,14 +110,13 @@ void MethodHandles::verify_ref_kind(MacroAssembler* _masm, int ref_kind, Registe __ andl(temp, java_lang_invoke_MemberName::MN_REFERENCE_KIND_MASK); __ cmpl(temp, ref_kind); __ jcc(Assembler::equal, L); - { char* buf = NEW_C_HEAP_ARRAY(char, 100, mtInternal); - jio_snprintf(buf, 100, "verify_ref_kind expected %x", ref_kind); - if (ref_kind == JVM_REF_invokeVirtual || - ref_kind == JVM_REF_invokeSpecial) - // could do this for all ref_kinds, but would explode assembly code size - trace_method_handle(_masm, buf); - __ STOP(buf); + const char* msg = ref_kind_to_verify_msg(ref_kind); + if (ref_kind == JVM_REF_invokeVirtual || + ref_kind == JVM_REF_invokeSpecial) { + // could do this for all ref_kinds, but would explode assembly code size + trace_method_handle(_masm, msg); } + __ STOP(msg); BLOCK_COMMENT("} verify_ref_kind"); __ bind(L); } diff --git a/src/hotspot/share/prims/methodHandles.cpp b/src/hotspot/share/prims/methodHandles.cpp index 584f077eddc..03cb98d8e75 100644 --- a/src/hotspot/share/prims/methodHandles.cpp +++ b/src/hotspot/share/prims/methodHandles.cpp @@ -157,6 +157,19 @@ int MethodHandles::ref_kind_to_flags(int ref_kind) { return flags; } +#ifdef ASSERT +const char* MethodHandles::ref_kind_to_verify_msg(int ref_kind) { + switch (ref_kind) { + case JVM_REF_invokeSpecial: return "verify_ref_kind expected invokeSpecial"; + case JVM_REF_invokeStatic: return "verify_ref_kind expected invokeStatic"; + case JVM_REF_invokeVirtual: return "verify_ref_kind expected invokeVirtual"; + case JVM_REF_invokeInterface: return "verify_ref_kind expected invokeInterface"; + default: assert(false, "unexpected ref_kind: %d", ref_kind); + } + return ""; +} +#endif + Handle MethodHandles::resolve_MemberName_type(Handle mname, Klass* caller, TRAPS) { Handle empty; Handle type(THREAD, java_lang_invoke_MemberName::type(mname())); diff --git a/src/hotspot/share/prims/methodHandles.hpp b/src/hotspot/share/prims/methodHandles.hpp index 73da28a6cf5..a2a549fe051 100644 --- a/src/hotspot/share/prims/methodHandles.hpp +++ b/src/hotspot/share/prims/methodHandles.hpp @@ -182,6 +182,8 @@ class MethodHandles: AllStatic { static int ref_kind_to_flags(int ref_kind); + DEBUG_ONLY( static const char* ref_kind_to_verify_msg(int ref_kind); ) + #include CPU_HEADER(methodHandles) // Tracing From 48132fbb65bd4938debf360f806d5fd7dd39856c Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Tue, 31 Mar 2026 17:13:58 +0000 Subject: [PATCH 085/116] 8381170: JFR: Recursion in jdk.MethodTrace caused by Integer::reverseBytes Reviewed-by: shade --- .../classes/jdk/jfr/internal/tracing/ExcludeList.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tracing/ExcludeList.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tracing/ExcludeList.java index 58408da811e..4ba6887e6a5 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/tracing/ExcludeList.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tracing/ExcludeList.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -59,7 +59,14 @@ public final class ExcludeList { "java.lang.String::checkIndex", // Used by charAt(int) "java.lang.String::isLatin1", // Used by charAt() "java.lang.String::equals", // Used by StringPool - "java.lang.String::hashCode" // Used by StringPool + "java.lang.String::hashCode", // Used by StringPool + // Used by Bits during Event::commit(), directly or indirectly + "java.lang.Integer::reverseBytes", + "java.lang.Long::reverseBytes", + "java.lang.Float::floatToIntBits", + "java.lang.Float::isNaN", + "java.lang.Double::doubleToLongBits", + "java.lang.Double::isNaN" ); public static boolean containsMethod(String methodName) { From e191df7f156e43cc350e0dcc2ef126d9ef3cf24a Mon Sep 17 00:00:00 2001 From: Phil Race Date: Tue, 31 Mar 2026 17:54:55 +0000 Subject: [PATCH 086/116] 8134541: latent concurrency bug in ScriptRunData Reviewed-by: honkar, dnguyen, serb --- src/java.desktop/share/classes/sun/font/ScriptRunData.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/java.desktop/share/classes/sun/font/ScriptRunData.java b/src/java.desktop/share/classes/sun/font/ScriptRunData.java index 1f1f6b44d59..4e13fb5bbd0 100644 --- a/src/java.desktop/share/classes/sun/font/ScriptRunData.java +++ b/src/java.desktop/share/classes/sun/font/ScriptRunData.java @@ -38,11 +38,12 @@ private ScriptRunData() {} private static final int CHAR_START = 0; private static final int CHAR_LIMIT = 0x110000; - private static int cache = 0; + private static volatile int cache = 0; public static int getScript(int cp) { + int lcache = cache; // optimize for runs of characters in the same script - if (cp >= data[cache] && cp < data[cache+2]) { - return data[cache+1]; + if (cp >= data[lcache] && cp < data[lcache+2]) { + return data[lcache+1]; } if ((cp >= CHAR_START) && (cp < CHAR_LIMIT)) { int probe = dataPower; From 644cccae78d65de347f965e4a2f652422a415330 Mon Sep 17 00:00:00 2001 From: Phil Race Date: Tue, 31 Mar 2026 17:58:53 +0000 Subject: [PATCH 087/116] 8381020: Remove AppContext from java.awt.Dialog Reviewed-by: dnguyen, kizune --- .../share/classes/java/awt/Dialog.java | 37 +------------------ 1 file changed, 2 insertions(+), 35 deletions(-) diff --git a/src/java.desktop/share/classes/java/awt/Dialog.java b/src/java.desktop/share/classes/java/awt/Dialog.java index 83aa89b9bf7..038aa5b65e3 100644 --- a/src/java.desktop/share/classes/java/awt/Dialog.java +++ b/src/java.desktop/share/classes/java/awt/Dialog.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,7 +41,6 @@ import javax.accessibility.AccessibleState; import javax.accessibility.AccessibleStateSet; -import sun.awt.AppContext; import sun.awt.SunToolkit; import sun.awt.util.IdentityArrayList; @@ -1013,30 +1012,12 @@ public void show() { if (!isModal()) { conditionalShow(null, null); } else { - AppContext showAppContext = AppContext.getAppContext(); - AtomicLong time = new AtomicLong(); Component predictedFocusOwner = null; try { predictedFocusOwner = getMostRecentFocusOwner(); if (conditionalShow(predictedFocusOwner, time)) { modalFilter = ModalEventFilter.createFilterForDialog(this); - // if this dialog is toolkit-modal, the filter should be added - // to all EDTs (for all AppContexts) - if (modalityType == ModalityType.TOOLKIT_MODAL) { - for (AppContext appContext : AppContext.getAppContexts()) { - if (appContext == showAppContext) { - continue; - } - EventQueue eventQueue = (EventQueue)appContext.get(AppContext.EVENT_QUEUE_KEY); - // it may occur that EDT for appContext hasn't been started yet, so - // we post an empty invocation event to trigger EDT initialization - eventQueue.postEvent(new InvocationEvent(this, () -> {})); - EventDispatchThread edt = eventQueue.getDispatchThread(); - edt.addEventFilter(modalFilter); - } - } - modalityPushed(); try { EventQueue eventQueue = Toolkit.getDefaultToolkit().getSystemEventQueue(); @@ -1047,19 +1028,6 @@ public void show() { } finally { modalityPopped(); } - - // if this dialog is toolkit-modal, its filter must be removed - // from all EDTs (for all AppContexts) - if (modalityType == ModalityType.TOOLKIT_MODAL) { - for (AppContext appContext : AppContext.getAppContexts()) { - if (appContext == showAppContext) { - continue; - } - EventQueue eventQueue = (EventQueue)appContext.get(AppContext.EVENT_QUEUE_KEY); - EventDispatchThread edt = eventQueue.getDispatchThread(); - edt.removeEventFilter(modalFilter); - } - } } } finally { if (predictedFocusOwner != null) { @@ -1482,8 +1450,7 @@ boolean shouldBlock(Window w) { return getDocumentRoot() == w.getDocumentRoot(); } case APPLICATION_MODAL: - return !w.isModalExcluded(ModalExclusionType.APPLICATION_EXCLUDE) && - (appContext == w.appContext); + return !w.isModalExcluded(ModalExclusionType.APPLICATION_EXCLUDE); case TOOLKIT_MODAL: return !w.isModalExcluded(ModalExclusionType.TOOLKIT_EXCLUDE); } From 20c3082aac4381a5d38ed3abb34b3651b2d28e08 Mon Sep 17 00:00:00 2001 From: Phil Race Date: Tue, 31 Mar 2026 18:41:51 +0000 Subject: [PATCH 088/116] 8380578: Remove miscellaneous AppContext uses, mostly in XAWT Reviewed-by: serb, azvegint --- .../classes/sun/awt/util/PerformanceLogger.java | 7 +------ .../unix/classes/sun/awt/X11/InfoWindow.java | 7 ++++--- .../classes/sun/awt/X11/XBaseMenuWindow.java | 8 ++------ .../sun/awt/X11/XEmbedChildProxyPeer.java | 8 ++++---- .../unix/classes/sun/awt/X11/XTaskbarPeer.java | 4 ++-- .../unix/classes/sun/awt/X11/XToolkit.java | 16 +--------------- .../unix/classes/sun/awt/X11/XTrayIconPeer.java | 12 ++++++------ .../unix/classes/sun/awt/X11InputMethodBase.java | 4 ++-- .../unix/native/common/awt/awt_Component.h | 3 +-- .../unix/native/libawt_xawt/xawt/XToolkit.c | 6 +----- .../native/libawt/windows/awt_Component.cpp | 8 +------- .../native/libawt/windows/awt_Component.h | 3 +-- 12 files changed, 26 insertions(+), 60 deletions(-) diff --git a/src/java.desktop/share/classes/sun/awt/util/PerformanceLogger.java b/src/java.desktop/share/classes/sun/awt/util/PerformanceLogger.java index 4a1dde6538d..cf0ff1d9958 100644 --- a/src/java.desktop/share/classes/sun/awt/util/PerformanceLogger.java +++ b/src/java.desktop/share/classes/sun/awt/util/PerformanceLogger.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,11 +43,6 @@ * for setting and getting all times and for doing whatever * analysis is interesting; this class is merely a central container * for those timing values. - * Note that, due to the variables in this class being static, - * use of particular time values by multiple AppContexts will cause - * confusing results. For example, if two contexts run - * simultaneously, the initTime for those will collide - * and the results may be undefined. *

* To automatically track startup performance in an app * use the command-line parameter sun.perflog as follows:
diff --git a/src/java.desktop/unix/classes/sun/awt/X11/InfoWindow.java b/src/java.desktop/unix/classes/sun/awt/X11/InfoWindow.java index bab0f34f90f..c03eae62225 100644 --- a/src/java.desktop/unix/classes/sun/awt/X11/InfoWindow.java +++ b/src/java.desktop/unix/classes/sun/awt/X11/InfoWindow.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,7 @@ import java.awt.Component; import java.awt.Container; import java.awt.Dimension; +import java.awt.EventQueue; import java.awt.Font; import java.awt.Frame; import java.awt.GridLayout; @@ -91,7 +92,7 @@ protected void setCloser(Runnable action, int time) { // Must be executed on EDT. @SuppressWarnings("deprecation") protected void show(Point corner, int indent) { - assert SunToolkit.isDispatchThreadForAppContext(this); + assert EventQueue.isDispatchThread(); pack(); @@ -464,7 +465,7 @@ public void mouseClicked(MouseEvent e) { ActionEvent aev = new ActionEvent(target, ActionEvent.ACTION_PERFORMED, liveArguments.getActionCommand(), e.getWhen(), e.getModifiers()); - XToolkit.postEvent(XToolkit.targetToAppContext(aev.getSource()), aev); + XToolkit.postEvent(aev); } } } diff --git a/src/java.desktop/unix/classes/sun/awt/X11/XBaseMenuWindow.java b/src/java.desktop/unix/classes/sun/awt/X11/XBaseMenuWindow.java index f8fcb30d8d8..9512d1d0351 100644 --- a/src/java.desktop/unix/classes/sun/awt/X11/XBaseMenuWindow.java +++ b/src/java.desktop/unix/classes/sun/awt/X11/XBaseMenuWindow.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -114,8 +114,6 @@ public abstract class XBaseMenuWindow extends XWindow { protected Point grabInputPoint = null; protected boolean hasPointerMoved = false; - private AppContext disposeAppContext; - /************************************************ * * Mapping data @@ -175,8 +173,6 @@ public XMenuItemPeer[] getItems() { XBaseMenuWindow() { super(new XCreateWindowParams(new Object[] { DELAYED, Boolean.TRUE})); - - disposeAppContext = AppContext.getAppContext(); } /************************************************ @@ -920,7 +916,7 @@ protected boolean isEventDisabled(XEvent e) { public void dispose() { setDisposed(true); - SunToolkit.invokeLaterOnAppContext(disposeAppContext, new Runnable() { + SunToolkit.invokeLater(new Runnable() { public void run() { doDispose(); } diff --git a/src/java.desktop/unix/classes/sun/awt/X11/XEmbedChildProxyPeer.java b/src/java.desktop/unix/classes/sun/awt/X11/XEmbedChildProxyPeer.java index efae47d6f23..03593761111 100644 --- a/src/java.desktop/unix/classes/sun/awt/X11/XEmbedChildProxyPeer.java +++ b/src/java.desktop/unix/classes/sun/awt/X11/XEmbedChildProxyPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -201,7 +201,7 @@ public void setFont(Font f) {} public void updateCursorImmediately() {} void postEvent(AWTEvent event) { - XToolkit.postEvent(XToolkit.targetToAppContext(proxy), event); + XToolkit.postEvent(event); } boolean simulateMotifRequestFocus(Component lightweightChild, boolean temporary, @@ -323,9 +323,9 @@ Window getTopLevel(Component comp) { } void childResized() { - XToolkit.postEvent(XToolkit.targetToAppContext(proxy), new ComponentEvent(proxy, ComponentEvent.COMPONENT_RESIZED)); + XToolkit.postEvent(new ComponentEvent(proxy, ComponentEvent.COMPONENT_RESIZED)); container.childResized(proxy); -// XToolkit.postEvent(XToolkit.targetToAppContext(proxy), new InvocationEvent(proxy, new Runnable() { +// XToolkit.postEvent(new InvocationEvent(proxy, new Runnable() { // public void run() { // getTopLevel(proxy).invalidate(); // getTopLevel(proxy).pack(); diff --git a/src/java.desktop/unix/classes/sun/awt/X11/XTaskbarPeer.java b/src/java.desktop/unix/classes/sun/awt/X11/XTaskbarPeer.java index 7f0629e101e..cb80f0abd0e 100644 --- a/src/java.desktop/unix/classes/sun/awt/X11/XTaskbarPeer.java +++ b/src/java.desktop/unix/classes/sun/awt/X11/XTaskbarPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -152,7 +152,7 @@ private static void menuItemCallback(MenuItem mi) { mi.getActionCommand()); try { XToolkit.awtLock(); - XToolkit.postEvent(XToolkit.targetToAppContext(ae.getSource()), ae); + XToolkit.postEvent(ae); } finally { XToolkit.awtUnlock(); } diff --git a/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java b/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java index 5dcd1b763e1..1ec0039febd 100644 --- a/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java +++ b/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java @@ -625,14 +625,8 @@ public void run(boolean loop) while(true) { // Fix for 6829923: we should gracefully handle toolkit thread interruption if (Thread.currentThread().isInterrupted()) { - // We expect interruption from the AppContext.dispose() method only. // If the thread is interrupted from another place, let's skip it - // for compatibility reasons. Probably some time later we'll remove - // the check for AppContext.isDisposed() and will unconditionally - // break the loop here. - if (AppContext.getAppContext().isDisposed()) { - break; - } + // for compatibility reasons. } awtLock(); try { @@ -2054,14 +2048,6 @@ public boolean isModalExclusionTypeSupported(Dialog.ModalExclusionType exclusion (exclusionType == Dialog.ModalExclusionType.TOOLKIT_EXCLUDE); } - static EventQueue getEventQueue(Object target) { - AppContext appContext = targetToAppContext(target); - if (appContext != null) { - return (EventQueue)appContext.get(AppContext.EVENT_QUEUE_KEY); - } - return null; - } - static void removeSourceEvents(EventQueue queue, Object source, boolean removeAllEvents) { diff --git a/src/java.desktop/unix/classes/sun/awt/X11/XTrayIconPeer.java b/src/java.desktop/unix/classes/sun/awt/X11/XTrayIconPeer.java index 9f0ac241f5b..5ab97125991 100644 --- a/src/java.desktop/unix/classes/sun/awt/X11/XTrayIconPeer.java +++ b/src/java.desktop/unix/classes/sun/awt/X11/XTrayIconPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -269,7 +269,7 @@ public void run() { @Override public void dispose() { - if (SunToolkit.isDispatchThreadForAppContext(target)) { + if (EventQueue.isDispatchThread()) { disposeOnEDT(); } else { try { @@ -329,7 +329,7 @@ public void run() { } }; - if (!SunToolkit.isDispatchThreadForAppContext(target)) { + if (!EventQueue.isDispatchThread()) { SunToolkit.executeOnEventHandlerThread(target, r); } else { r.run(); @@ -355,7 +355,7 @@ public void showPopupMenu(int x, int y) { if (isDisposed()) return; - assert SunToolkit.isDispatchThreadForAppContext(target); + assert EventQueue.isDispatchThread(); PopupMenu newPopup = target.getPopupMenu(); if (popup != newPopup) { @@ -476,7 +476,7 @@ public void handleEvent(MouseEvent e) { // other class tries to cast source field to Component). // We already filter DRAG events out (CR 6565779). e.setSource(xtiPeer.target); - XToolkit.postEvent(XToolkit.targetToAppContext(e.getSource()), e); + XToolkit.postEvent(e); } @Override @SuppressWarnings("deprecation") @@ -487,7 +487,7 @@ public void mouseClicked(MouseEvent e) { ActionEvent aev = new ActionEvent(xtiPeer.target, ActionEvent.ACTION_PERFORMED, xtiPeer.target.getActionCommand(), e.getWhen(), e.getModifiers()); - XToolkit.postEvent(XToolkit.targetToAppContext(aev.getSource()), aev); + XToolkit.postEvent(aev); } if (xtiPeer.balloon.isVisible()) { xtiPeer.balloon.hide(); diff --git a/src/java.desktop/unix/classes/sun/awt/X11InputMethodBase.java b/src/java.desktop/unix/classes/sun/awt/X11InputMethodBase.java index d9eaa9629d1..3aa1624a1dd 100644 --- a/src/java.desktop/unix/classes/sun/awt/X11InputMethodBase.java +++ b/src/java.desktop/unix/classes/sun/awt/X11InputMethodBase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -434,7 +434,7 @@ protected void postInputMethodEvent(int id, if (source != null) { InputMethodEvent event = new InputMethodEvent(source, id, when, text, committedCharacterCount, caret, visiblePosition); - SunToolkit.postEvent(SunToolkit.targetToAppContext(source), (AWTEvent)event); + SunToolkit.postEvent((AWTEvent)event); } } diff --git a/src/java.desktop/unix/native/common/awt/awt_Component.h b/src/java.desktop/unix/native/common/awt/awt_Component.h index 089691a8a4d..7ef0a0de94b 100644 --- a/src/java.desktop/unix/native/common/awt/awt_Component.h +++ b/src/java.desktop/unix/native/common/awt/awt_Component.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,7 +38,6 @@ struct ComponentIDs { jfieldID graphicsConfig; jfieldID name; jfieldID isProxyActive; - jfieldID appContext; jmethodID getParent; jmethodID getLocationOnScreen; }; diff --git a/src/java.desktop/unix/native/libawt_xawt/xawt/XToolkit.c b/src/java.desktop/unix/native/libawt_xawt/xawt/XToolkit.c index d5f3130386d..c84aa4ff8f9 100644 --- a/src/java.desktop/unix/native/libawt_xawt/xawt/XToolkit.c +++ b/src/java.desktop/unix/native/libawt_xawt/xawt/XToolkit.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -195,10 +195,6 @@ Java_java_awt_Component_initIDs "Z"); CHECK_NULL(componentIDs.isProxyActive); - componentIDs.appContext = - (*env)->GetFieldID(env, cls, "appContext", - "Lsun/awt/AppContext;"); - (*env)->DeleteLocalRef(env, keyclass); } 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 b67c5dfcf8d..eca8290a1aa 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, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -178,7 +178,6 @@ jfieldID AwtComponent::parentID; jfieldID AwtComponent::graphicsConfigID; jfieldID AwtComponent::peerGCID; jfieldID AwtComponent::focusableID; -jfieldID AwtComponent::appContextID; jfieldID AwtComponent::cursorID; jfieldID AwtComponent::hwndID; @@ -6573,11 +6572,6 @@ Java_java_awt_Component_initIDs(JNIEnv *env, jclass cls) DASSERT(AwtComponent::focusableID); CHECK_NULL(AwtComponent::focusableID); - AwtComponent::appContextID = env->GetFieldID(cls, "appContext", - "Lsun/awt/AppContext;"); - DASSERT(AwtComponent::appContextID); - CHECK_NULL(AwtComponent::appContextID); - AwtComponent::peerGCID = env->GetFieldID(peerCls, "winGraphicsConfig", "Lsun/awt/Win32GraphicsConfig;"); DASSERT(AwtComponent::peerGCID); diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Component.h b/src/java.desktop/windows/native/libawt/windows/awt_Component.h index 740eb8c72f9..1246f6cb06e 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Component.h +++ b/src/java.desktop/windows/native/libawt/windows/awt_Component.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -112,7 +112,6 @@ class AwtComponent : public AwtObject { static jfieldID graphicsConfigID; static jfieldID peerGCID; static jfieldID focusableID; - static jfieldID appContextID; static jfieldID hwndID; static jmethodID getFontMID; From f46a6981137bd09e9387c168eb24e4bc2edf32c4 Mon Sep 17 00:00:00 2001 From: Daniel Gredler Date: Tue, 31 Mar 2026 21:46:05 +0000 Subject: [PATCH 089/116] 8381015: CharsetEncoder.canEncode(CharSequence) is slow for UTF-8, UTF-16, UTF-32 Reviewed-by: naoto, vyazici --- .../share/classes/sun/nio/cs/UTF_32Coder.java | 9 +++- .../share/classes/sun/nio/cs/UTF_8.java | 4 ++ .../share/classes/sun/nio/cs/Unicode.java | 21 ++++++++- .../classes/sun/nio/cs/UnicodeEncoder.java | 6 ++- .../nio/charset/CharsetEncoder/CanEncode.java | 46 +++++++++++++++---- .../bench/java/nio/CharsetCanEncode.java | 23 ++++++++++ 6 files changed, 97 insertions(+), 12 deletions(-) diff --git a/src/java.base/share/classes/sun/nio/cs/UTF_32Coder.java b/src/java.base/share/classes/sun/nio/cs/UTF_32Coder.java index c6f38ec9bfc..72e59d22e2c 100644 --- a/src/java.base/share/classes/sun/nio/cs/UTF_32Coder.java +++ b/src/java.base/share/classes/sun/nio/cs/UTF_32Coder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -185,5 +185,12 @@ protected void implReset() { doneBOM = !doBOM; } + public boolean canEncode(char c) { + return !Character.isSurrogate(c); + } + + public boolean canEncode(CharSequence cs) { + return Unicode.isValidUnicode(cs); + } } } diff --git a/src/java.base/share/classes/sun/nio/cs/UTF_8.java b/src/java.base/share/classes/sun/nio/cs/UTF_8.java index 2928ae6d509..fda8e5eec1f 100644 --- a/src/java.base/share/classes/sun/nio/cs/UTF_8.java +++ b/src/java.base/share/classes/sun/nio/cs/UTF_8.java @@ -424,6 +424,10 @@ public boolean canEncode(char c) { return !Character.isSurrogate(c); } + public boolean canEncode(CharSequence cs) { + return Unicode.isValidUnicode(cs); + } + public boolean isLegalReplacement(byte[] repl) { return ((repl.length == 1 && repl[0] >= 0) || super.isLegalReplacement(repl)); diff --git a/src/java.base/share/classes/sun/nio/cs/Unicode.java b/src/java.base/share/classes/sun/nio/cs/Unicode.java index aac77a13ffb..06a50f125c5 100644 --- a/src/java.base/share/classes/sun/nio/cs/Unicode.java +++ b/src/java.base/share/classes/sun/nio/cs/Unicode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -95,4 +95,23 @@ public boolean contains(Charset cs) { || (cs.name().equals("x-Johab")) || (cs.name().equals("Shift_JIS"))); } + + static boolean isValidUnicode(CharSequence cs) { + int length = cs.length(); + for (int i = 0; i < length;) { + char c = cs.charAt(i++); + if (Character.isHighSurrogate(c)) { + if (i == length) { + return false; + } + char low = cs.charAt(i++); + if (!Character.isLowSurrogate(low)) { + return false; + } + } else if (Character.isLowSurrogate(c)) { + return false; + } + } + return true; + } } diff --git a/src/java.base/share/classes/sun/nio/cs/UnicodeEncoder.java b/src/java.base/share/classes/sun/nio/cs/UnicodeEncoder.java index 7b34fb2d512..6f7413dcbf8 100644 --- a/src/java.base/share/classes/sun/nio/cs/UnicodeEncoder.java +++ b/src/java.base/share/classes/sun/nio/cs/UnicodeEncoder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -108,4 +108,8 @@ protected void implReset() { public boolean canEncode(char c) { return ! Character.isSurrogate(c); } + + public boolean canEncode(CharSequence cs) { + return Unicode.isValidUnicode(cs); + } } diff --git a/test/jdk/java/nio/charset/CharsetEncoder/CanEncode.java b/test/jdk/java/nio/charset/CharsetEncoder/CanEncode.java index 8545ef61be9..d4dabf70910 100644 --- a/test/jdk/java/nio/charset/CharsetEncoder/CanEncode.java +++ b/test/jdk/java/nio/charset/CharsetEncoder/CanEncode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -66,14 +66,21 @@ private static void test(String csn) throws Exception { Charset cs = Charset.forName(csn); CharsetEncoder ce = cs.newEncoder(); - if (cs.name().equals("US-ASCII")) { - ck(ce, 'x', true); - ck(ce, '\u00B6', false); - ck(ce, "x", true); - ck(ce, "\u00B6", false); - ck(ce, "xyzzy", true); - ck(ce, "xy\u00B6", false); - } + // Basic multilingual plane + boolean utf = csn.startsWith("UTF-"); + ck(ce, 'x', true); + ck(ce, '\u00B6', utf); + ck(ce, "", true); + ck(ce, "x", true); + ck(ce, "\u00B6", utf); + ck(ce, "xyzzy", true); + ck(ce, "xy\u00B6", utf); + + // Paired surrogates + ck(ce, "\uD83D\uDE00", utf); + ck(ce, "XX\uD83D\uDE00", utf); + ck(ce, "\uD83D\uDE00XX", utf); + ck(ce, "X\uD83D\uDE00X", utf); // Unpaired surrogates should never be encodable ck(ce, '\ud800', false); @@ -81,15 +88,36 @@ private static void test(String csn) throws Exception { ck(ce, '\udffe', false); ck(ce, '\udfff', false); ck(ce, "\ud800", false); + ck(ce, "XX\ud800", false); + ck(ce, "\ud800XX", false); + ck(ce, "X\ud800X", false); ck(ce, "\ud801", false); + ck(ce, "XX\ud801", false); + ck(ce, "\ud801XX", false); + ck(ce, "X\ud801X", false); ck(ce, "\udffe", false); + ck(ce, "XX\udffe", false); + ck(ce, "\udffeXX", false); + ck(ce, "X\udffeX", false); ck(ce, "\udfff", false); + ck(ce, "XX\udfff", false); + ck(ce, "\udfffXX", false); + ck(ce, "X\udfffX", false); + if (errors > 0) { + throw new RuntimeException(errors + " errors for Charset " + csn); + } } public static void main(String[] args) throws Exception { test("US-ASCII"); test("UTF-8"); + test("UTF-16"); + test("UTF-16LE"); + test("UTF-16BE"); + test("UTF-32"); + test("UTF-32LE"); + test("UTF-32BE"); } } diff --git a/test/micro/org/openjdk/bench/java/nio/CharsetCanEncode.java b/test/micro/org/openjdk/bench/java/nio/CharsetCanEncode.java index ebfbc217a95..8c08a876696 100644 --- a/test/micro/org/openjdk/bench/java/nio/CharsetCanEncode.java +++ b/test/micro/org/openjdk/bench/java/nio/CharsetCanEncode.java @@ -65,6 +65,9 @@ public class CharsetCanEncode { // sun.nio.cs.UTF_16LE private CharsetEncoder utf16le = Charset.forName("UTF-16LE").newEncoder(); + // sun.nio.cs.UTF_32LE + private CharsetEncoder utf32le = Charset.forName("UTF-32LE").newEncoder(); + @Benchmark public boolean asciiCanEncodeCharYes() { return ascii.canEncode('D'); @@ -184,4 +187,24 @@ public boolean utf16leCanEncodeCharNo() { public boolean utf16leCanEncodeStringNo() { return utf16le.canEncode(String.valueOf(Character.MIN_SURROGATE)); } + + @Benchmark + public boolean utf32leCanEncodeCharYes() { + return utf32le.canEncode('D'); + } + + @Benchmark + public boolean utf32leCanEncodeStringYes() { + return utf32le.canEncode("D"); + } + + @Benchmark + public boolean utf32leCanEncodeCharNo() { + return utf32le.canEncode(Character.MIN_SURROGATE); + } + + @Benchmark + public boolean utf32leCanEncodeStringNo() { + return utf32le.canEncode(String.valueOf(Character.MIN_SURROGATE)); + } } From 3f6271b2b91c096d1b6fcb74c279c5607e116357 Mon Sep 17 00:00:00 2001 From: Kerem Kat Date: Wed, 1 Apr 2026 00:10:02 +0000 Subject: [PATCH 090/116] 8375442: C2: Notify nodes that inspect the graph deeply of changes far away during IGVN Reviewed-by: qamai, aseoane --- src/hotspot/share/opto/c2_globals.hpp | 4 + src/hotspot/share/opto/cfgnode.cpp | 4 +- src/hotspot/share/opto/compile.cpp | 10 +- src/hotspot/share/opto/escape.cpp | 2 +- src/hotspot/share/opto/graphKit.cpp | 4 +- src/hotspot/share/opto/ifnode.cpp | 29 +- src/hotspot/share/opto/loopnode.cpp | 8 +- src/hotspot/share/opto/loopopts.cpp | 18 +- src/hotspot/share/opto/macro.cpp | 24 +- src/hotspot/share/opto/memnode.cpp | 2 +- src/hotspot/share/opto/phaseX.cpp | 290 +++++++++++------- src/hotspot/share/opto/phaseX.hpp | 78 ++++- src/hotspot/share/opto/split_if.cpp | 24 +- .../compiler/arraycopy/TestCloneAccess.java | 12 +- .../compiler/c2/igvn/TestDeepIGVNRevisit.java | 83 +++++ .../igvn/TestFoldComparesCleanup.java | 56 ++++ .../compiler/lib/ir_framework/IRNode.java | 5 + 17 files changed, 467 insertions(+), 186 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/c2/igvn/TestDeepIGVNRevisit.java create mode 100644 test/hotspot/jtreg/compiler/igvn/TestFoldComparesCleanup.java diff --git a/src/hotspot/share/opto/c2_globals.hpp b/src/hotspot/share/opto/c2_globals.hpp index a4f6d04f6a3..983ac8a32c6 100644 --- a/src/hotspot/share/opto/c2_globals.hpp +++ b/src/hotspot/share/opto/c2_globals.hpp @@ -705,6 +705,10 @@ develop(bool, TraceIterativeGVN, false, \ "Print progress during Iterative Global Value Numbering") \ \ + develop(bool, UseDeepIGVNRevisit, true, \ + "Re-process nodes that could benefit from a deep revisit after " \ + "the IGVN worklist drains") \ + \ develop(uint, VerifyIterativeGVN, 0, \ "Verify Iterative Global Value Numbering =FEDCBA, with:" \ " F: verify Node::Ideal does not return nullptr if the node" \ diff --git a/src/hotspot/share/opto/cfgnode.cpp b/src/hotspot/share/opto/cfgnode.cpp index 0915f79a503..828e5bf299f 100644 --- a/src/hotspot/share/opto/cfgnode.cpp +++ b/src/hotspot/share/opto/cfgnode.cpp @@ -735,7 +735,7 @@ Node *RegionNode::Ideal(PhaseGVN *phase, bool can_reshape) { #endif } // Remove the RegionNode itself from DefUse info - igvn->remove_dead_node(this); + igvn->remove_dead_node(this, PhaseIterGVN::NodeOrigin::Graph); return nullptr; } return this; // Record progress @@ -1007,7 +1007,7 @@ bool RegionNode::optimize_trichotomy(PhaseIterGVN* igvn) { BoolNode* new_bol = new BoolNode(bol2->in(1), res); igvn->replace_input_of(iff2, 1, igvn->transform((proj2->_con == 1) ? new_bol : new_bol->negate(igvn))); if (new_bol->outcnt() == 0) { - igvn->remove_dead_node(new_bol); + igvn->remove_dead_node(new_bol, PhaseIterGVN::NodeOrigin::Speculative); } } return false; diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index 7ab384a29c7..7b5f78a8ad3 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -2277,7 +2277,7 @@ void Compile::remove_root_to_sfpts_edges(PhaseIterGVN& igvn) { if (n != nullptr && n->is_SafePoint()) { r->rm_prec(i); if (n->outcnt() == 0) { - igvn.remove_dead_node(n); + igvn.remove_dead_node(n, PhaseIterGVN::NodeOrigin::Graph); } --i; } @@ -2321,7 +2321,7 @@ void Compile::Optimize() { #endif { TracePhase tp(_t_iterGVN); - igvn.optimize(); + igvn.optimize(true); } if (failing()) return; @@ -2385,7 +2385,7 @@ void Compile::Optimize() { PhaseRenumberLive prl(initial_gvn(), *igvn_worklist()); } igvn.reset(); - igvn.optimize(); + igvn.optimize(true); if (failing()) return; } @@ -2418,7 +2418,7 @@ void Compile::Optimize() { int mcount = macro_count(); // Record number of allocations and locks before IGVN // Optimize out fields loads from scalar replaceable allocations. - igvn.optimize(); + igvn.optimize(true); print_method(PHASE_ITER_GVN_AFTER_EA, 2); if (failing()) return; @@ -2498,7 +2498,7 @@ void Compile::Optimize() { { TracePhase tp(_t_iterGVN2); igvn.reset_from_igvn(&ccp); - igvn.optimize(); + igvn.optimize(true); } print_method(PHASE_ITER_GVN2, 2); diff --git a/src/hotspot/share/opto/escape.cpp b/src/hotspot/share/opto/escape.cpp index 7041eb0b810..64ee60037d6 100644 --- a/src/hotspot/share/opto/escape.cpp +++ b/src/hotspot/share/opto/escape.cpp @@ -933,7 +933,7 @@ void ConnectionGraph::reduce_phi_on_castpp_field_load(Node* curr_castpp, Growabl j = MIN2(j, (int)use->outcnt()-1); } - _igvn->remove_dead_node(use); + _igvn->remove_dead_node(use, PhaseIterGVN::NodeOrigin::Graph); } --i; i = MIN2(i, (int)curr_castpp->outcnt()-1); diff --git a/src/hotspot/share/opto/graphKit.cpp b/src/hotspot/share/opto/graphKit.cpp index e297292770e..8d32694e9a5 100644 --- a/src/hotspot/share/opto/graphKit.cpp +++ b/src/hotspot/share/opto/graphKit.cpp @@ -2911,8 +2911,8 @@ Node* Phase::gen_subtype_check(Node* subklass, Node* superklass, Node** ctrl, No *ctrl = iftrue1; // We need exactly the 1 test above PhaseIterGVN* igvn = gvn.is_IterGVN(); if (igvn != nullptr) { - igvn->remove_globally_dead_node(r_ok_subtype); - igvn->remove_globally_dead_node(r_not_subtype); + igvn->remove_globally_dead_node(r_ok_subtype, PhaseIterGVN::NodeOrigin::Speculative); + igvn->remove_globally_dead_node(r_not_subtype, PhaseIterGVN::NodeOrigin::Speculative); } return not_subtype_ctrl; } diff --git a/src/hotspot/share/opto/ifnode.cpp b/src/hotspot/share/opto/ifnode.cpp index 762791d467d..ad8f0ced6ea 100644 --- a/src/hotspot/share/opto/ifnode.cpp +++ b/src/hotspot/share/opto/ifnode.cpp @@ -132,7 +132,7 @@ static Node* split_if(IfNode *iff, PhaseIterGVN *igvn) { cmp2->set_req(2,con2); const Type *t = cmp2->Value(igvn); // This compare is dead, so whack it! - igvn->remove_dead_node(cmp2); + igvn->remove_dead_node(cmp2, PhaseIterGVN::NodeOrigin::Speculative); if( !t->singleton() ) return nullptr; // No intervening control, like a simple Call @@ -443,7 +443,7 @@ static Node* split_if(IfNode *iff, PhaseIterGVN *igvn) { } l -= uses_found; // we deleted 1 or more copies of this edge } - igvn->remove_dead_node(p); + igvn->remove_dead_node(p, PhaseIterGVN::NodeOrigin::Graph); } // Force the original merge dead @@ -455,14 +455,14 @@ static Node* split_if(IfNode *iff, PhaseIterGVN *igvn) { r->set_req(0, nullptr); } else { assert(u->outcnt() == 0, "only dead users"); - igvn->remove_dead_node(u); + igvn->remove_dead_node(u, PhaseIterGVN::NodeOrigin::Graph); } l -= 1; } - igvn->remove_dead_node(r); + igvn->remove_dead_node(r, PhaseIterGVN::NodeOrigin::Graph); // Now remove the bogus extra edges used to keep things alive - igvn->remove_dead_node( hook ); + igvn->remove_dead_node(hook, PhaseIterGVN::NodeOrigin::Speculative); // Must return either the original node (now dead) or a new node // (Do not return a top here, since that would break the uniqueness of top.) @@ -905,6 +905,7 @@ bool IfNode::fold_compares_helper(IfProjNode* proj, IfProjNode* success, IfProjN IfNode* dom_iff = proj->in(0)->as_If(); BoolNode* dom_bool = dom_iff->in(1)->as_Bool(); Node* lo = dom_iff->in(1)->in(1)->in(2); + Node* orig_lo = lo; Node* hi = this_cmp->in(2); Node* n = this_cmp->in(1); IfProjNode* otherproj = proj->other_if_proj(); @@ -916,6 +917,7 @@ bool IfNode::fold_compares_helper(IfProjNode* proj, IfProjNode* success, IfProjN BoolTest::mask hi_test = this_bool->_test._test; BoolTest::mask cond = hi_test; + PhaseTransform::SpeculativeProgressGuard progress_guard(igvn); // convert: // // dom_bool = x {<,<=,>,>=} a @@ -1053,6 +1055,7 @@ bool IfNode::fold_compares_helper(IfProjNode* proj, IfProjNode* success, IfProjN // previous if determines the result of this if so // replace Bool with constant igvn->replace_input_of(this, 1, igvn->intcon(success->_con)); + progress_guard.commit(); return true; } } @@ -1087,11 +1090,14 @@ bool IfNode::fold_compares_helper(IfProjNode* proj, IfProjNode* success, IfProjN // min(limit, max(-2 + min_jint + 1, min_jint)) // = min(limit, min_jint) // = min_jint + if (lo != orig_lo && lo->outcnt() == 0) { + igvn->remove_dead_node(lo, PhaseIterGVN::NodeOrigin::Speculative); + } if (adjusted_val->outcnt() == 0) { - igvn->remove_dead_node(adjusted_val); + igvn->remove_dead_node(adjusted_val, PhaseIterGVN::NodeOrigin::Speculative); } if (adjusted_lim->outcnt() == 0) { - igvn->remove_dead_node(adjusted_lim); + igvn->remove_dead_node(adjusted_lim, PhaseIterGVN::NodeOrigin::Speculative); } igvn->C->record_for_post_loop_opts_igvn(this); return false; @@ -1103,6 +1109,7 @@ bool IfNode::fold_compares_helper(IfProjNode* proj, IfProjNode* success, IfProjN igvn->replace_input_of(dom_iff, 1, igvn->intcon(proj->_con)); igvn->replace_input_of(this, 1, newbool); + progress_guard.commit(); return true; } @@ -1592,11 +1599,11 @@ Node* IfNode::dominated_by(Node* prev_dom, PhaseIterGVN* igvn, bool prev_dom_not } } // End for each child of a projection - igvn->remove_dead_node(ifp); + igvn->remove_dead_node(ifp, PhaseIterGVN::NodeOrigin::Graph); } // End for each IfTrue/IfFalse child of If // Kill the IfNode - igvn->remove_dead_node(this); + igvn->remove_dead_node(this, PhaseIterGVN::NodeOrigin::Graph); // Must return either the original node (now dead) or a new node // (Do not return a top here, since that would break the uniqueness of top.) @@ -1758,7 +1765,7 @@ Node* IfNode::simple_subsuming(PhaseIterGVN* igvn) { } if (bol->outcnt() == 0) { - igvn->remove_dead_node(bol); // Kill the BoolNode. + igvn->remove_dead_node(bol, PhaseIterGVN::NodeOrigin::Graph); // Kill the BoolNode. } return this; } @@ -1903,7 +1910,7 @@ static IfNode* idealize_test(PhaseGVN* phase, IfNode* iff) { Node *prior = igvn->hash_find_insert(iff); if( prior ) { - igvn->remove_dead_node(iff); + igvn->remove_dead_node(iff, PhaseIterGVN::NodeOrigin::Graph); iff = (IfNode*)prior; } else { // Cannot call transform on it just yet diff --git a/src/hotspot/share/opto/loopnode.cpp b/src/hotspot/share/opto/loopnode.cpp index 23186a25320..6963a67118f 100644 --- a/src/hotspot/share/opto/loopnode.cpp +++ b/src/hotspot/share/opto/loopnode.cpp @@ -697,7 +697,7 @@ SafePointNode* PhaseIdealLoop::find_safepoint(Node* back_control, const Node* he } #ifdef ASSERT if (mm != nullptr) { - _igvn.remove_dead_node(mm); + _igvn.remove_dead_node(mm, PhaseIterGVN::NodeOrigin::Speculative); } #endif } @@ -2002,7 +2002,7 @@ bool CountedLoopConverter::stress_long_counted_loop() { Node* n = iv_nodes.at(i); Node* clone = old_new[n->_idx]; if (clone != nullptr) { - igvn->remove_dead_node(clone); + igvn->remove_dead_node(clone, PhaseIterGVN::NodeOrigin::Speculative); } } return false; @@ -4676,7 +4676,7 @@ void PhaseIdealLoop::replace_parallel_iv(IdealLoopTree *loop) { _igvn.replace_node( phi2, add ); // Sometimes an induction variable is unused if (add->outcnt() == 0) { - _igvn.remove_dead_node(add); + _igvn.remove_dead_node(add, PhaseIterGVN::NodeOrigin::Graph); } --i; // deleted this phi; rescan starting with next position } @@ -5354,7 +5354,7 @@ void PhaseIdealLoop::build_and_optimize() { // clear out the dead code after build_loop_late while (_deadlist.size()) { - _igvn.remove_globally_dead_node(_deadlist.pop()); + _igvn.remove_globally_dead_node(_deadlist.pop(), PhaseIterGVN::NodeOrigin::Graph); } eliminate_useless_zero_trip_guard(); diff --git a/src/hotspot/share/opto/loopopts.cpp b/src/hotspot/share/opto/loopopts.cpp index 4e447edee8d..11b23d7c365 100644 --- a/src/hotspot/share/opto/loopopts.cpp +++ b/src/hotspot/share/opto/loopopts.cpp @@ -161,7 +161,7 @@ Node* PhaseIdealLoop::split_thru_phi(Node* n, Node* region, int policy) { } if (the_clone != x) { - _igvn.remove_dead_node(the_clone); + _igvn.remove_dead_node(the_clone, PhaseIterGVN::NodeOrigin::Speculative); } else if (region->is_Loop() && i == LoopNode::LoopBackControl && n->is_Load() && can_move_to_inner_loop(n, region->as_Loop(), x)) { // it is not a win if 'x' moved from an outer to an inner loop @@ -172,7 +172,7 @@ Node* PhaseIdealLoop::split_thru_phi(Node* n, Node* region, int policy) { } // Too few wins? if (!wins.profitable(policy)) { - _igvn.remove_dead_node(phi); + _igvn.remove_dead_node(phi, PhaseIterGVN::NodeOrigin::Speculative); return nullptr; } @@ -1866,7 +1866,7 @@ void PhaseIdealLoop::try_sink_out_of_loop(Node* n) { assert(cast != nullptr, "must have added a cast to pin the node"); } } - _igvn.remove_dead_node(n); + _igvn.remove_dead_node(n, PhaseIterGVN::NodeOrigin::Graph); } _dom_lca_tags_round = 0; } @@ -2082,7 +2082,7 @@ Node* PhaseIdealLoop::clone_iff(PhiNode* phi) { // Register with optimizer Node *hit1 = _igvn.hash_find_insert(phi1); if (hit1) { // Hit, toss just made Phi - _igvn.remove_dead_node(phi1); // Remove new phi + _igvn.remove_dead_node(phi1, PhaseIterGVN::NodeOrigin::Speculative); // Remove new phi assert(hit1->is_Phi(), "" ); phi1 = (PhiNode*)hit1; // Use existing phi } else { // Miss @@ -2090,7 +2090,7 @@ Node* PhaseIdealLoop::clone_iff(PhiNode* phi) { } Node *hit2 = _igvn.hash_find_insert(phi2); if (hit2) { // Hit, toss just made Phi - _igvn.remove_dead_node(phi2); // Remove new phi + _igvn.remove_dead_node(phi2, PhaseIterGVN::NodeOrigin::Speculative); // Remove new phi assert(hit2->is_Phi(), "" ); phi2 = (PhiNode*)hit2; // Use existing phi } else { // Miss @@ -2165,7 +2165,7 @@ CmpNode*PhaseIdealLoop::clone_bool(PhiNode* phi) { // Register with optimizer Node *hit1 = _igvn.hash_find_insert(phi1); if( hit1 ) { // Hit, toss just made Phi - _igvn.remove_dead_node(phi1); // Remove new phi + _igvn.remove_dead_node(phi1, PhaseIterGVN::NodeOrigin::Speculative); // Remove new phi assert( hit1->is_Phi(), "" ); phi1 = (PhiNode*)hit1; // Use existing phi } else { // Miss @@ -2173,7 +2173,7 @@ CmpNode*PhaseIdealLoop::clone_bool(PhiNode* phi) { } Node *hit2 = _igvn.hash_find_insert(phi2); if( hit2 ) { // Hit, toss just made Phi - _igvn.remove_dead_node(phi2); // Remove new phi + _igvn.remove_dead_node(phi2, PhaseIterGVN::NodeOrigin::Speculative); // Remove new phi assert( hit2->is_Phi(), "" ); phi2 = (PhiNode*)hit2; // Use existing phi } else { // Miss @@ -2324,7 +2324,7 @@ void PhaseIdealLoop::clone_loop_handle_data_uses(Node* old, Node_List &old_new, _igvn.register_new_node_with_optimizer(phi); // Register new phi } else { // or // Remove the new phi from the graph and use the hit - _igvn.remove_dead_node(phi); + _igvn.remove_dead_node(phi, phi == prev ? PhaseIterGVN::NodeOrigin::Graph : PhaseIterGVN::NodeOrigin::Speculative); phi = hit; // Use existing phi } set_ctrl(phi, prev); @@ -3472,7 +3472,7 @@ void PhaseIdealLoop::insert_phi_for_loop( Node* use, uint idx, Node* lp_entry_va set_ctrl(phi, lp); } else { // Remove the new phi from the graph and use the hit - _igvn.remove_dead_node(phi); + _igvn.remove_dead_node(phi, PhaseIterGVN::NodeOrigin::Speculative); phi = hit; } _igvn.replace_input_of(use, idx, phi); diff --git a/src/hotspot/share/opto/macro.cpp b/src/hotspot/share/opto/macro.cpp index c78f6533840..1c54a11e2a4 100644 --- a/src/hotspot/share/opto/macro.cpp +++ b/src/hotspot/share/opto/macro.cpp @@ -973,7 +973,7 @@ void PhaseMacroExpand::process_users_of_allocation(CallNode *alloc) { } k -= (oc2 - use->outcnt()); } - _igvn.remove_dead_node(use); + _igvn.remove_dead_node(use, PhaseIterGVN::NodeOrigin::Graph); } else if (use->is_ArrayCopy()) { // Disconnect ArrayCopy node ArrayCopyNode* ac = use->as_ArrayCopy(); @@ -1008,7 +1008,7 @@ void PhaseMacroExpand::process_users_of_allocation(CallNode *alloc) { // src can be top at this point if src and dest of the // arraycopy were the same if (src->outcnt() == 0 && !src->is_top()) { - _igvn.remove_dead_node(src); + _igvn.remove_dead_node(src, PhaseIterGVN::NodeOrigin::Graph); } } _igvn._worklist.push(ac); @@ -1018,7 +1018,7 @@ void PhaseMacroExpand::process_users_of_allocation(CallNode *alloc) { j -= (oc1 - res->outcnt()); } assert(res->outcnt() == 0, "all uses of allocated objects must be deleted"); - _igvn.remove_dead_node(res); + _igvn.remove_dead_node(res, PhaseIterGVN::NodeOrigin::Graph); } // @@ -1502,7 +1502,7 @@ void PhaseMacroExpand::expand_allocate_common( transform_later(_callprojs.fallthrough_memproj); } migrate_outs(_callprojs.catchall_memproj, _callprojs.fallthrough_memproj); - _igvn.remove_dead_node(_callprojs.catchall_memproj); + _igvn.remove_dead_node(_callprojs.catchall_memproj, PhaseIterGVN::NodeOrigin::Graph); } // An allocate node has separate i_o projections for the uses on the control @@ -1521,7 +1521,7 @@ void PhaseMacroExpand::expand_allocate_common( transform_later(_callprojs.fallthrough_ioproj); } migrate_outs(_callprojs.catchall_ioproj, _callprojs.fallthrough_ioproj); - _igvn.remove_dead_node(_callprojs.catchall_ioproj); + _igvn.remove_dead_node(_callprojs.catchall_ioproj, PhaseIterGVN::NodeOrigin::Graph); } // if we generated only a slow call, we are done @@ -1585,11 +1585,11 @@ void PhaseMacroExpand::yank_alloc_node(AllocateNode* alloc) { --i; // back up iterator } assert(_callprojs.resproj->outcnt() == 0, "all uses must be deleted"); - _igvn.remove_dead_node(_callprojs.resproj); + _igvn.remove_dead_node(_callprojs.resproj, PhaseIterGVN::NodeOrigin::Graph); } if (_callprojs.fallthrough_catchproj != nullptr) { migrate_outs(_callprojs.fallthrough_catchproj, ctrl); - _igvn.remove_dead_node(_callprojs.fallthrough_catchproj); + _igvn.remove_dead_node(_callprojs.fallthrough_catchproj, PhaseIterGVN::NodeOrigin::Graph); } if (_callprojs.catchall_catchproj != nullptr) { _igvn.rehash_node_delayed(_callprojs.catchall_catchproj); @@ -1597,16 +1597,16 @@ void PhaseMacroExpand::yank_alloc_node(AllocateNode* alloc) { } if (_callprojs.fallthrough_proj != nullptr) { Node* catchnode = _callprojs.fallthrough_proj->unique_ctrl_out(); - _igvn.remove_dead_node(catchnode); - _igvn.remove_dead_node(_callprojs.fallthrough_proj); + _igvn.remove_dead_node(catchnode, PhaseIterGVN::NodeOrigin::Graph); + _igvn.remove_dead_node(_callprojs.fallthrough_proj, PhaseIterGVN::NodeOrigin::Graph); } if (_callprojs.fallthrough_memproj != nullptr) { migrate_outs(_callprojs.fallthrough_memproj, mem); - _igvn.remove_dead_node(_callprojs.fallthrough_memproj); + _igvn.remove_dead_node(_callprojs.fallthrough_memproj, PhaseIterGVN::NodeOrigin::Graph); } if (_callprojs.fallthrough_ioproj != nullptr) { migrate_outs(_callprojs.fallthrough_ioproj, i_o); - _igvn.remove_dead_node(_callprojs.fallthrough_ioproj); + _igvn.remove_dead_node(_callprojs.fallthrough_ioproj, PhaseIterGVN::NodeOrigin::Graph); } if (_callprojs.catchall_memproj != nullptr) { _igvn.rehash_node_delayed(_callprojs.catchall_memproj); @@ -1625,7 +1625,7 @@ void PhaseMacroExpand::yank_alloc_node(AllocateNode* alloc) { } } #endif - _igvn.remove_dead_node(alloc); + _igvn.remove_dead_node(alloc, PhaseIterGVN::NodeOrigin::Graph); } void PhaseMacroExpand::expand_initialize_membar(AllocateNode* alloc, InitializeNode* init, diff --git a/src/hotspot/share/opto/memnode.cpp b/src/hotspot/share/opto/memnode.cpp index 46f6729c82f..c8723d6ec0f 100644 --- a/src/hotspot/share/opto/memnode.cpp +++ b/src/hotspot/share/opto/memnode.cpp @@ -1889,7 +1889,7 @@ Node* LoadNode::split_through_phi(PhaseGVN* phase, bool ignore_missing_instance_ } } if (x != the_clone && the_clone != nullptr) { - igvn->remove_dead_node(the_clone); + igvn->remove_dead_node(the_clone, PhaseIterGVN::NodeOrigin::Speculative); } phi->set_req(i, x); } diff --git a/src/hotspot/share/opto/phaseX.cpp b/src/hotspot/share/opto/phaseX.cpp index 29961e152b3..06963eff4cf 100644 --- a/src/hotspot/share/opto/phaseX.cpp +++ b/src/hotspot/share/opto/phaseX.cpp @@ -575,7 +575,7 @@ PhaseValues::~PhaseValues() { _table.dump(); // Statistics for value progress and efficiency if( PrintCompilation && Verbose && WizardMode ) { - tty->print("\n%sValues: %d nodes ---> %d/%d (%d)", + tty->print("\n%sValues: %d nodes ---> " UINT64_FORMAT "/%d (%d)", is_IterGVN() ? "Iter" : " ", C->unique(), made_progress(), made_transforms(), made_new_values()); if( made_transforms() != 0 ) { tty->print_cr(" ratio %f", made_progress()/(float)made_transforms() ); @@ -731,14 +731,14 @@ Node* PhaseGVN::transform(Node* n) { } if (t->singleton() && !k->is_Con()) { - NOT_PRODUCT(set_progress();) + set_progress(); return makecon(t); // Turn into a constant } // Now check for Identities i = k->Identity(this); // Look for a nearby replacement if (i != k) { // Found? Return replacement! - NOT_PRODUCT(set_progress();) + set_progress(); return i; } @@ -746,7 +746,7 @@ Node* PhaseGVN::transform(Node* n) { i = hash_find_insert(k); // Insert if new if (i && (i != k)) { // Return the pre-existing node - NOT_PRODUCT(set_progress();) + set_progress(); return i; } @@ -977,7 +977,7 @@ void PhaseIterGVN::init_verifyPhaseIterGVN() { #endif } -void PhaseIterGVN::verify_PhaseIterGVN() { +void PhaseIterGVN::verify_PhaseIterGVN(bool deep_revisit_converged) { #ifdef ASSERT // Verify nodes with changed inputs. Unique_Node_List* modified_list = C->modified_nodes(); @@ -1010,7 +1010,7 @@ void PhaseIterGVN::verify_PhaseIterGVN() { } } - verify_optimize(); + verify_optimize(deep_revisit_converged); #endif } #endif /* PRODUCT */ @@ -1040,38 +1040,54 @@ void PhaseIterGVN::trace_PhaseIterGVN_verbose(Node* n, int num_processed) { } #endif /* ASSERT */ -void PhaseIterGVN::optimize() { - DEBUG_ONLY(uint num_processed = 0;) - NOT_PRODUCT(init_verifyPhaseIterGVN();) - NOT_PRODUCT(C->reset_igv_phase_iter(PHASE_AFTER_ITER_GVN_STEP);) - C->print_method(PHASE_BEFORE_ITER_GVN, 3); - if (StressIGVN) { - shuffle_worklist(); +bool PhaseIterGVN::needs_deep_revisit(const Node* n) const { + // LoadNode::Value() -> can_see_stored_value() walks up through many memory + // nodes. LoadNode::Ideal() -> find_previous_store() also walks up to 50 + // nodes through stores and arraycopy nodes. + if (n->is_Load()) { + return true; + } + // CmpPNode::sub() -> detect_ptr_independence() -> all_controls_dominate() + // walks CFG dominator relationships extensively. This only triggers when + // both inputs are oop pointers (subnode.cpp:984). + if (n->Opcode() == Op_CmpP) { + const Type* t1 = type_or_null(n->in(1)); + const Type* t2 = type_or_null(n->in(2)); + return t1 != nullptr && t1->isa_oopptr() && + t2 != nullptr && t2->isa_oopptr(); + } + // IfNode::Ideal() -> search_identical() walks up the CFG dominator tree. + // RangeCheckNode::Ideal() scans up to ~999 nodes up the chain. + // CountedLoopEndNode/LongCountedLoopEndNode::Ideal() via simple_subsuming + // looks for dominating test that subsumes the current test. + switch (n->Opcode()) { + case Op_If: + case Op_RangeCheck: + case Op_CountedLoopEnd: + case Op_LongCountedLoopEnd: + return true; + default: + break; } + return false; +} - // The node count check in the loop below (check_node_count) assumes that we - // increase the live node count with at most - // max_live_nodes_increase_per_iteration in between checks. If this - // assumption does not hold, there is a risk that we exceed the max node - // limit in between checks and trigger an assert during node creation. +bool PhaseIterGVN::drain_worklist() { + uint loop_count = 1; const int max_live_nodes_increase_per_iteration = NodeLimitFudgeFactor * 3; - - uint loop_count = 0; - // Pull from worklist and transform the node. If the node has changed, - // update edge info and put uses on worklist. - while (_worklist.size() > 0) { + while (_worklist.size() != 0) { if (C->check_node_count(max_live_nodes_increase_per_iteration, "Out of nodes")) { C->print_method(PHASE_AFTER_ITER_GVN, 3); - return; + return true; } Node* n = _worklist.pop(); if (loop_count >= K * C->live_nodes()) { - DEBUG_ONLY(dump_infinite_loop_info(n, "PhaseIterGVN::optimize");) - C->record_method_not_compilable("infinite loop in PhaseIterGVN::optimize"); + DEBUG_ONLY(dump_infinite_loop_info(n, "PhaseIterGVN::drain_worklist");) + C->record_method_not_compilable("infinite loop in PhaseIterGVN::drain_worklist"); C->print_method(PHASE_AFTER_ITER_GVN, 3); - return; + return true; } - DEBUG_ONLY(trace_PhaseIterGVN_verbose(n, num_processed++);) + DEBUG_ONLY(trace_PhaseIterGVN_verbose(n, _num_processed++);) if (n->outcnt() != 0) { NOT_PRODUCT(const Type* oldtype = type_or_null(n)); // Do the transformation @@ -1079,7 +1095,7 @@ void PhaseIterGVN::optimize() { Node* nn = transform_old(n); DEBUG_ONLY(int live_nodes_after = C->live_nodes();) // Ensure we did not increase the live node count with more than - // max_live_nodes_increase_per_iteration during the call to transform_old + // max_live_nodes_increase_per_iteration during the call to transform_old. DEBUG_ONLY(int increase = live_nodes_after - live_nodes_before;) assert(increase < max_live_nodes_increase_per_iteration, "excessive live node increase in single iteration of IGVN: %d " @@ -1087,16 +1103,115 @@ void PhaseIterGVN::optimize() { increase, max_live_nodes_increase_per_iteration); NOT_PRODUCT(trace_PhaseIterGVN(n, nn, oldtype);) } else if (!n->is_top()) { - remove_dead_node(n); + remove_dead_node(n, NodeOrigin::Graph); } loop_count++; } - NOT_PRODUCT(verify_PhaseIterGVN();) + return false; +} + +void PhaseIterGVN::push_deep_revisit_candidates() { + ResourceMark rm; + Unique_Node_List all_nodes; + all_nodes.push(C->root()); + for (uint j = 0; j < all_nodes.size(); j++) { + Node* n = all_nodes.at(j); + if (needs_deep_revisit(n)) { + _worklist.push(n); + } + for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { + all_nodes.push(n->fast_out(i)); + } + } +} + +bool PhaseIterGVN::deep_revisit() { + // Re-process nodes that inspect the graph deeply. After the main worklist drains, walk + // the graph to find all live deep-inspection nodes and push them to the worklist + // for re-evaluation. If any produce changes, drain the worklist again. + // Repeat until stable. This mirrors PhaseCCP::analyze()'s revisit loop. + const uint max_deep_revisit_rounds = 10; // typically converges in <2 rounds + uint round = 0; + for (; round < max_deep_revisit_rounds; round++) { + push_deep_revisit_candidates(); + if (_worklist.size() == 0) { + break; // No deep-inspection nodes to revisit, done. + } + +#ifndef PRODUCT + uint candidates = _worklist.size(); + uint n_if = 0; uint n_rc = 0; uint n_load = 0; uint n_cmpp = 0; uint n_cle = 0; uint n_lcle = 0; + if (TraceIterativeGVN) { + for (uint i = 0; i < _worklist.size(); i++) { + Node* n = _worklist.at(i); + switch (n->Opcode()) { + case Op_If: n_if++; break; + case Op_RangeCheck: n_rc++; break; + case Op_CountedLoopEnd: n_cle++; break; + case Op_LongCountedLoopEnd: n_lcle++; break; + case Op_CmpP: n_cmpp++; break; + default: if (n->is_Load()) n_load++; break; + } + } + } +#endif + + // Convergence: if the drain does not make progress (no Ideal, Value, Identity or GVN changes), + // we are at a fixed point. We use made_progress() rather than live_nodes because live_nodes + // misses non-structural changes like a LoadNode dropping its control input. + uint progress_before = made_progress(); + if (drain_worklist()) { + return false; + } + uint progress = made_progress() - progress_before; + +#ifndef PRODUCT + if (TraceIterativeGVN) { + tty->print("deep_revisit round %u: %u candidates (If=%u RC=%u Load=%u CmpP=%u CLE=%u LCLE=%u), progress=%u (%s)", + round, candidates, n_if, n_rc, n_load, n_cmpp, n_cle, n_lcle, progress, progress != 0 ? "changed" : "converged"); + if (C->method() != nullptr) { + tty->print(", "); + C->method()->print_short_name(tty); + } + tty->cr(); + } +#endif + + if (progress == 0) { + break; + } + } + return round < max_deep_revisit_rounds; +} + +void PhaseIterGVN::optimize(bool deep) { + bool deep_revisit_converged = false; + DEBUG_ONLY(_num_processed = 0;) + NOT_PRODUCT(init_verifyPhaseIterGVN();) + NOT_PRODUCT(C->reset_igv_phase_iter(PHASE_AFTER_ITER_GVN_STEP);) + C->print_method(PHASE_BEFORE_ITER_GVN, 3); + if (StressIGVN) { + shuffle_worklist(); + } + + // Pull from worklist and transform the node. + if (drain_worklist()) { + return; + } + + if (deep && UseDeepIGVNRevisit) { + deep_revisit_converged = deep_revisit(); + if (C->failing()) { + return; + } + } + + NOT_PRODUCT(verify_PhaseIterGVN(deep_revisit_converged);) C->print_method(PHASE_AFTER_ITER_GVN, 3); } #ifdef ASSERT -void PhaseIterGVN::verify_optimize() { +void PhaseIterGVN::verify_optimize(bool deep_revisit_converged) { assert(_worklist.size() == 0, "igvn worklist must be empty before verify"); if (is_verify_Value() || @@ -1114,11 +1229,11 @@ void PhaseIterGVN::verify_optimize() { // in PhaseIterGVN::add_users_to_worklist to update it again or add an exception // in the verification methods below if that is not possible for some reason (like Load nodes). if (is_verify_Value()) { - verify_Value_for(n); + verify_Value_for(n, deep_revisit_converged /* strict */); } if (is_verify_Ideal()) { - verify_Ideal_for(n, false); - verify_Ideal_for(n, true); + verify_Ideal_for(n, false /* can_reshape */, deep_revisit_converged); + verify_Ideal_for(n, true /* can_reshape */, deep_revisit_converged); } if (is_verify_Identity()) { verify_Identity_for(n); @@ -1240,52 +1355,15 @@ void PhaseIterGVN::verify_Value_for(const Node* n, bool strict) { // Check that all Ideal optimizations that could be done were done. // Asserts if it found missed optimization opportunities or encountered unexpected changes, and // returns normally otherwise (no missed optimization, or skipped verification). -void PhaseIterGVN::verify_Ideal_for(Node* n, bool can_reshape) { +void PhaseIterGVN::verify_Ideal_for(Node* n, bool can_reshape, bool deep_revisit_converged) { + if (!deep_revisit_converged && needs_deep_revisit(n)) { + return; + } + // First, we check a list of exceptions, where we skip verification, // because there are known cases where Ideal can optimize after IGVN. // Some may be expected and cannot be fixed, and others should be fixed. switch (n->Opcode()) { - // RangeCheckNode::Ideal looks up the chain for about 999 nodes - // (see "Range-Check scan limit"). So, it is possible that something - // is optimized in that input subgraph, and the RangeCheck was not - // added to the worklist because it would be too expensive to walk - // down the graph for 1000 nodes and put all on the worklist. - // - // Found with: - // java -XX:VerifyIterativeGVN=0100 -Xbatch --version - case Op_RangeCheck: - return; - - // IfNode::Ideal does: - // Node* prev_dom = search_identical(dist, igvn); - // which means we seach up the CFG, traversing at most up to a distance. - // If anything happens rather far away from the If, we may not put the If - // back on the worklist. - // - // Found with: - // java -XX:VerifyIterativeGVN=0100 -Xcomp --version - case Op_If: - return; - - // IfNode::simple_subsuming - // Looks for dominating test that subsumes the current test. - // Notification could be difficult because of larger distance. - // - // Found with: - // runtime/exceptionMsgs/ArrayIndexOutOfBoundsException/ArrayIndexOutOfBoundsExceptionTest.java#id1 - // -XX:VerifyIterativeGVN=1110 - case Op_CountedLoopEnd: - return; - - // LongCountedLoopEndNode::Ideal - // Probably same issue as above. - // - // Found with: - // compiler/predicates/assertion/TestAssertionPredicates.java#NoLoopPredicationXbatch - // -XX:StressLongCountedLoop=2000000 -XX:+IgnoreUnrecognizedVMOptions -XX:VerifyIterativeGVN=1110 - case Op_LongCountedLoopEnd: - return; - // RegionNode::Ideal does "Skip around the useless IF diamond". // 245 IfTrue === 244 // 258 If === 245 257 @@ -1757,22 +1835,6 @@ void PhaseIterGVN::verify_Ideal_for(Node* n, bool can_reshape) { return; } - if (n->is_Load()) { - // LoadNode::Ideal uses tries to find an earlier memory state, and - // checks can_see_stored_value for it. - // - // Investigate why this was not already done during IGVN. - // A similar issue happens with Identity. - // - // There seem to be other cases where loads go up some steps, like - // LoadNode::Ideal going up 10x steps to find dominating load. - // - // Found with: - // test/hotspot/jtreg/compiler/arraycopy/TestCloneAccess.java - // -XX:VerifyIterativeGVN=1110 - return; - } - if (n->is_Store()) { // StoreNode::Ideal can do this: // // Capture an unaliased, unconditional, simple store into an initializer. @@ -1857,8 +1919,16 @@ void PhaseIterGVN::verify_Ideal_for(Node* n, bool can_reshape) { return; } - // The number of nodes shoud not increase. - uint old_unique = C->unique(); + // Ideal should not make progress if it returns nullptr. + // We use made_progress() rather than unique() or live_nodes() because some + // Ideal implementations speculatively create nodes and kill them before + // returning nullptr (e.g. split_if clones a Cmp to check is_canonical). + // unique() is a high-water mark that is not decremented by remove_dead_node, + // so it would cause false-positives. live_nodes() accounts for dead nodes but can + // decrease when Ideal removes existing nodes as side effects. + // made_progress() precisely tracks meaningful transforms, and speculative + // work killed via NodeOrigin::Speculative does not increment it. + uint old_progress = made_progress(); // The hash of a node should not change, this would indicate different inputs uint old_hash = n->hash(); // Remove 'n' from hash table in case it gets modified. We want to avoid @@ -1870,14 +1940,15 @@ void PhaseIterGVN::verify_Ideal_for(Node* n, bool can_reshape) { Node* i = n->Ideal(this, can_reshape); // If there was no new Idealization, we are probably happy. if (i == nullptr) { - if (old_unique < C->unique()) { + uint progress = made_progress() - old_progress; + if (progress != 0) { stringStream ss; // Print as a block without tty lock. ss.cr(); - ss.print_cr("Ideal optimization did not make progress but created new unused nodes."); - ss.print_cr(" old_unique = %d, unique = %d", old_unique, C->unique()); + ss.print_cr("Ideal optimization did not make progress but had side effects."); + ss.print_cr(" %u transforms made progress", progress); n->dump_bfs(1, nullptr, "", &ss); tty->print_cr("%s", ss.as_string()); - assert(false, "Unexpected new unused nodes from applying Ideal optimization on %s", n->Name()); + assert(false, "Unexpected side effects from applying Ideal optimization on %s", n->Name()); } if (old_hash != n->hash()) { @@ -2152,6 +2223,9 @@ Node *PhaseIterGVN::transform_old(Node* n) { #endif DEBUG_ONLY(uint loop_count = 1;) + if (i != nullptr) { + set_progress(); + } while (i != nullptr) { #ifdef ASSERT if (loop_count >= K + C->live_nodes()) { @@ -2197,10 +2271,8 @@ Node *PhaseIterGVN::transform_old(Node* n) { // cache Value. Later requests for the local phase->type of this Node can // use the cached Value instead of suffering with 'bottom_type'. if (type_or_null(k) != t) { -#ifndef PRODUCT - inc_new_values(); + NOT_PRODUCT(inc_new_values();) set_progress(); -#endif set_type(k, t); // If k is a TypeNode, capture any more-precise type permanently into Node k->raise_bottom_type(t); @@ -2209,7 +2281,7 @@ Node *PhaseIterGVN::transform_old(Node* n) { } // If 'k' computes a constant, replace it with a constant if (t->singleton() && !k->is_Con()) { - NOT_PRODUCT(set_progress();) + set_progress(); Node* con = makecon(t); // Make a constant add_users_to_worklist(k); subsume_node(k, con); // Everybody using k now uses con @@ -2219,7 +2291,7 @@ Node *PhaseIterGVN::transform_old(Node* n) { // Now check for Identities i = k->Identity(this); // Look for a nearby replacement if (i != k) { // Found? Return replacement! - NOT_PRODUCT(set_progress();) + set_progress(); add_users_to_worklist(k); subsume_node(k, i); // Everybody using k now uses i return i; @@ -2229,7 +2301,7 @@ Node *PhaseIterGVN::transform_old(Node* n) { i = hash_find_insert(k); // Check for pre-existing node if (i && (i != k)) { // Return the pre-existing node if it isn't dead - NOT_PRODUCT(set_progress();) + set_progress(); add_users_to_worklist(k); subsume_node(k, i); // Everybody using k now uses i return i; @@ -2248,7 +2320,7 @@ const Type* PhaseIterGVN::saturate(const Type* new_type, const Type* old_type, //------------------------------remove_globally_dead_node---------------------- // Kill a globally dead Node. All uses are also globally dead and are // aggressively trimmed. -void PhaseIterGVN::remove_globally_dead_node( Node *dead ) { +void PhaseIterGVN::remove_globally_dead_node(Node* dead, NodeOrigin origin) { enum DeleteProgress { PROCESS_INPUTS, PROCESS_OUTPUTS @@ -2265,11 +2337,13 @@ void PhaseIterGVN::remove_globally_dead_node( Node *dead ) { uint progress_state = stack.index(); assert(dead != C->root(), "killing root, eh?"); assert(!dead->is_top(), "add check for top when pushing"); - NOT_PRODUCT( set_progress(); ) if (progress_state == PROCESS_INPUTS) { // After following inputs, continue to outputs stack.set_index(PROCESS_OUTPUTS); if (!dead->is_Con()) { // Don't kill cons but uses + if (origin != NodeOrigin::Speculative) { + set_progress(); + } bool recurse = false; // Remove from hash table _table.hash_delete( dead ); @@ -2379,7 +2453,7 @@ void PhaseIterGVN::subsume_node( Node *old, Node *nn ) { // Smash all inputs to 'old', isolating him completely Node *temp = new Node(1); temp->init_req(0,nn); // Add a use to nn to prevent him from dying - remove_dead_node( old ); + remove_dead_node(old, NodeOrigin::Graph); temp->del_req(0); // Yank bogus edge if (nn != nullptr && nn->outcnt() == 0) { _worklist.push(nn); diff --git a/src/hotspot/share/opto/phaseX.hpp b/src/hotspot/share/opto/phaseX.hpp index 94890c250c4..cef273ff3df 100644 --- a/src/hotspot/share/opto/phaseX.hpp +++ b/src/hotspot/share/opto/phaseX.hpp @@ -187,8 +187,8 @@ class PhaseRenumberLive : public PhaseRemoveUseless { class PhaseTransform : public Phase { public: PhaseTransform(PhaseNumber pnum) : Phase(pnum) { -#ifndef PRODUCT clear_progress(); +#ifndef PRODUCT clear_transforms(); set_allow_progress(true); #endif @@ -201,12 +201,31 @@ class PhaseTransform : public Phase { // true if CFG node d dominates CFG node n virtual bool is_dominator(Node *d, Node *n) { fatal("unimplemented for this pass"); return false; }; -#ifndef PRODUCT - uint _count_progress; // For profiling, count transforms that make progress - void set_progress() { ++_count_progress; assert( allow_progress(),"No progress allowed during verification"); } - void clear_progress() { _count_progress = 0; } - uint made_progress() const { return _count_progress; } + uint64_t _count_progress; // Count transforms that make progress + void set_progress() { ++_count_progress; assert(allow_progress(), "No progress allowed during verification"); } + void clear_progress() { _count_progress = 0; } + uint64_t made_progress() const { return _count_progress; } + + // RAII guard for speculative transforms. Restores _count_progress in the destructor + // unless commit() is called, so that abandoned speculative work does not count as progress. + // In case multiple nodes are created and only some are speculative, commit() should still be called. + class SpeculativeProgressGuard { + PhaseTransform* _phase; + uint64_t _saved_progress; + bool _committed; + public: + SpeculativeProgressGuard(PhaseTransform* phase) : + _phase(phase), _saved_progress(phase->made_progress()), _committed(false) {} + ~SpeculativeProgressGuard() { + if (!_committed) { + _phase->_count_progress = _saved_progress; + } + } + void commit() { _committed = true; } + }; + +#ifndef PRODUCT uint _count_transforms; // For profiling, count transforms performed void set_transforms() { ++_count_transforms; } void clear_transforms() { _count_transforms = 0; } @@ -446,10 +465,30 @@ class PhaseIterGVN : public PhaseGVN { private: bool _delay_transform; // When true simply register the node when calling transform // instead of actually optimizing it + DEBUG_ONLY(uint _num_processed;) // Running count for trace_PhaseIterGVN_verbose // Idealize old Node 'n' with respect to its inputs and its value virtual Node *transform_old( Node *a_node ); + // Drain the IGVN worklist: process nodes until the worklist is empty. + // Returns true if compilation was aborted (node limit or infinite loop), + // false on normal completion. + bool drain_worklist(); + + // Walk all live nodes and push deep-inspection candidates to _worklist. + void push_deep_revisit_candidates(); + + // After the main worklist drains, re-process deep-inspection nodes to + // catch optimization opportunities from far-away changes. Repeats until + // convergence (no progress made) or max rounds reached. + // Returns true if converged. + bool deep_revisit(); + + // Returns true for nodes that inspect the graph beyond their direct + // inputs, and therefore may miss optimization opportunities when + // changes happen far away. + bool needs_deep_revisit(const Node* n) const; + // Subsume users of node 'old' into node 'nn' void subsume_node( Node *old, Node *nn ); @@ -493,11 +532,16 @@ class PhaseIterGVN : public PhaseGVN { // Given def-use info and an initial worklist, apply Node::Ideal, // Node::Value, Node::Identity, hash-based value numbering, Node::Ideal_DU // and dominator info to a fixed point. - void optimize(); + // When deep is true, after the main worklist drains, re-process + // nodes that inspect the graph deeply (Load, CmpP, If, RangeCheck, + // CountedLoopEnd, LongCountedLoopEnd) to catch optimization opportunities + // from changes far away that the normal notification mechanism misses. + void optimize(bool deep = false); + #ifdef ASSERT - void verify_optimize(); + void verify_optimize(bool deep_revisit_converged); void verify_Value_for(const Node* n, bool strict = false); - void verify_Ideal_for(Node* n, bool can_reshape); + void verify_Ideal_for(Node* n, bool can_reshape, bool deep_revisit_converged); void verify_Identity_for(Node* n); void verify_node_invariants_for(const Node* n); void verify_empty_worklist(Node* n); @@ -506,7 +550,7 @@ class PhaseIterGVN : public PhaseGVN { #ifndef PRODUCT void trace_PhaseIterGVN(Node* n, Node* nn, const Type* old_type); void init_verifyPhaseIterGVN(); - void verify_PhaseIterGVN(); + void verify_PhaseIterGVN(bool deep_revisit_converged); #endif #ifdef ASSERT @@ -522,15 +566,21 @@ class PhaseIterGVN : public PhaseGVN { // It is significant only for debugging and profiling. Node* register_new_node_with_optimizer(Node* n, Node* orig = nullptr); - // Kill a globally dead Node. All uses are also globally dead and are + // Origin of a dead node, describing why it is dying. + // Speculative: a temporarily created node that was never part of the graph + // (e.g., a speculative clone in split_if to test constant foldability). + // Its death does not count as progress for convergence tracking. + enum class NodeOrigin { Graph, Speculative }; + + // Kill a globally dead Node. All uses are also globally dead and are // aggressively trimmed. - void remove_globally_dead_node( Node *dead ); + void remove_globally_dead_node(Node* dead, NodeOrigin origin); // Kill all inputs to a dead node, recursively making more dead nodes. // The Node must be dead locally, i.e., have no uses. - void remove_dead_node( Node *dead ) { + void remove_dead_node(Node* dead, NodeOrigin origin) { assert(dead->outcnt() == 0 && !dead->is_top(), "node must be dead"); - remove_globally_dead_node(dead); + remove_globally_dead_node(dead, origin); } // Add users of 'n' to worklist diff --git a/src/hotspot/share/opto/split_if.cpp b/src/hotspot/share/opto/split_if.cpp index 91595c57a10..c1303f0d0db 100644 --- a/src/hotspot/share/opto/split_if.cpp +++ b/src/hotspot/share/opto/split_if.cpp @@ -85,7 +85,7 @@ bool PhaseIdealLoop::split_up( Node *n, Node *blk1, Node *blk2 ) { if( split_up( n->in(i), blk1, blk2 ) ) { // Got split recursively and self went dead? if (n->outcnt() == 0) - _igvn.remove_dead_node(n); + _igvn.remove_dead_node(n, PhaseIterGVN::NodeOrigin::Graph); return true; } } @@ -273,7 +273,7 @@ void PhaseIdealLoop::clone_loadklass_nodes_at_cmp_index(const Node* n, Node* cmp _igvn.replace_input_of(decode_clone, 1, loadklass_clone); _igvn.replace_input_of(loadklass_clone, MemNode::Address, addp_clone); if (decode->outcnt() == 0) { - _igvn.remove_dead_node(decode); + _igvn.remove_dead_node(decode, PhaseIterGVN::NodeOrigin::Graph); } } } @@ -290,7 +290,7 @@ void PhaseIdealLoop::clone_loadklass_nodes_at_cmp_index(const Node* n, Node* cmp _igvn.replace_input_of(cmp, i, loadklass_clone); _igvn.replace_input_of(loadklass_clone, MemNode::Address, addp_clone); if (loadklass->outcnt() == 0) { - _igvn.remove_dead_node(loadklass); + _igvn.remove_dead_node(loadklass, PhaseIterGVN::NodeOrigin::Graph); } } } @@ -369,7 +369,7 @@ bool PhaseIdealLoop::clone_cmp_down(Node* n, const Node* blk1, const Node* blk2) _igvn.replace_input_of(x2, 1, x1); _igvn.replace_input_of(iff, 1, x2); } - _igvn.remove_dead_node(u); + _igvn.remove_dead_node(u, PhaseIterGVN::NodeOrigin::Graph); --j; } else { // We might see an Opaque1 from a loop limit check here @@ -385,7 +385,7 @@ bool PhaseIdealLoop::clone_cmp_down(Node* n, const Node* blk1, const Node* blk2) --j; } } - _igvn.remove_dead_node(bol); + _igvn.remove_dead_node(bol, PhaseIterGVN::NodeOrigin::Graph); --i; } } @@ -403,7 +403,7 @@ bool PhaseIdealLoop::clone_cmp_down(Node* n, const Node* blk1, const Node* blk2) register_new_node(x, ctrl_or_self(use)); _igvn.replace_input_of(use, pos, x); } - _igvn.remove_dead_node(n); + _igvn.remove_dead_node(n, PhaseIterGVN::NodeOrigin::Graph); return true; } @@ -517,7 +517,7 @@ Node *PhaseIdealLoop::spinup( Node *iff_dom, Node *new_false, Node *new_true, No Node *t = _igvn.hash_find_insert(phi_post); if( t ) { // See if we already have this one // phi_post will not be used, so kill it - _igvn.remove_dead_node(phi_post); + _igvn.remove_dead_node(phi_post, PhaseIterGVN::NodeOrigin::Speculative); phi_post->destruct(&_igvn); phi_post = t; } else { @@ -647,7 +647,7 @@ void PhaseIdealLoop::do_split_if(Node* iff, RegionNode** new_false_region, Regio Node* m = n->out(j); // If m is dead, throw it away, and declare progress if (_loop_or_ctrl[m->_idx] == nullptr) { - _igvn.remove_dead_node(m); + _igvn.remove_dead_node(m, PhaseIterGVN::NodeOrigin::Graph); // fall through } else if (m != iff && split_up(m, region, iff)) { @@ -704,7 +704,7 @@ void PhaseIdealLoop::do_split_if(Node* iff, RegionNode** new_false_region, Regio new_true = ifpx; } } - _igvn.remove_dead_node(new_iff); + _igvn.remove_dead_node(new_iff, PhaseIterGVN::NodeOrigin::Speculative); // Lazy replace IDOM info with the region's dominator replace_node_and_forward_ctrl(iff, region_dom); // Break the self-cycle. Required for forward_ctrl to work on region. @@ -720,7 +720,7 @@ void PhaseIdealLoop::do_split_if(Node* iff, RegionNode** new_false_region, Regio for (DUIterator k = region->outs(); region->has_out(k); k++) { Node* phi = region->out(k); if (!phi->in(0)) { // Dead phi? Remove it - _igvn.remove_dead_node(phi); + _igvn.remove_dead_node(phi, PhaseIterGVN::NodeOrigin::Graph); } else if (phi == region) { // Found the self-reference continue; // No roll-back of DUIterator } else if (phi->is_Phi()) { // Expected common case: Phi hanging off of Region @@ -739,7 +739,7 @@ void PhaseIdealLoop::do_split_if(Node* iff, RegionNode** new_false_region, Regio handle_use(use, phi, &phi_cache, region_dom, new_false, new_true, old_false, old_true); } // End of while phi has uses // Remove the dead Phi - _igvn.remove_dead_node( phi ); + _igvn.remove_dead_node(phi, PhaseIterGVN::NodeOrigin::Graph); } else { assert(phi->in(0) == region, "Inconsistent graph"); // Random memory op guarded by Region. Compute new DEF for USE. @@ -752,7 +752,7 @@ void PhaseIdealLoop::do_split_if(Node* iff, RegionNode** new_false_region, Regio --k; } // End of while merge point has phis - _igvn.remove_dead_node(region); + _igvn.remove_dead_node(region, PhaseIterGVN::NodeOrigin::Graph); // Control is updated here to a region, which is not a test, so any node that // depends_only_on_test must be pinned diff --git a/test/hotspot/jtreg/compiler/arraycopy/TestCloneAccess.java b/test/hotspot/jtreg/compiler/arraycopy/TestCloneAccess.java index a0da0741cad..22bf1f88ae7 100644 --- a/test/hotspot/jtreg/compiler/arraycopy/TestCloneAccess.java +++ b/test/hotspot/jtreg/compiler/arraycopy/TestCloneAccess.java @@ -23,16 +23,18 @@ /* * @test - * @bug 8248791 + * @bug 8248791 8375442 * @summary Test cloning with more than 8 (=ArrayCopyLoadStoreMaxElem) where loads are wrongly replaced by zero. * @requires vm.compiler2.enabled | vm.graal.enabled * * @run main/othervm -XX:-ReduceBulkZeroing - * -XX:CompileCommand=dontinline,compiler.arraycopy.TestCloneAccess::* - * compiler.arraycopy.TestCloneAccess + * -XX:CompileCommand=dontinline,${test.main.class}::* + * ${test.main.class} * @run main/othervm -XX:-ReduceBulkZeroing -XX:-ReduceInitialCardMarks - * -XX:CompileCommand=dontinline,compiler.arraycopy.TestCloneAccess::* - * compiler.arraycopy.TestCloneAccess + * -XX:CompileCommand=dontinline,${test.main.class}::* + * ${test.main.class} + * @run main/othervm -XX:-ReduceBulkZeroing -XX:+IgnoreUnrecognizedVMOptions -XX:VerifyIterativeGVN=1110 + * ${test.main.class} */ package compiler.arraycopy; diff --git a/test/hotspot/jtreg/compiler/c2/igvn/TestDeepIGVNRevisit.java b/test/hotspot/jtreg/compiler/c2/igvn/TestDeepIGVNRevisit.java new file mode 100644 index 00000000000..228357f953d --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/igvn/TestDeepIGVNRevisit.java @@ -0,0 +1,83 @@ +/* + * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package compiler.c2.igvn; + +import compiler.lib.ir_framework.*; + +/* + * @test + * @bug 8375442 + * @summary Test deep IGVN revisit for RangeCheck elimination. Other deep-revisit node types + * (If, Load, CmpP, CountedLoopEnd, LongCountedLoopEnd) benefit in large methods + * but require graph complexity beyond this test. + * @library /test/lib / + * @run driver ${test.main.class} + */ +public class TestDeepIGVNRevisit { + static boolean c1, c2, c3, c4; + static volatile int volatileField; + + public static void main(String[] args) { + TestFramework tf = new TestFramework(); + tf.setDefaultWarmup(0); + tf.addFlags("-XX:+IgnoreUnrecognizedVMOptions", + "-XX:+AlwaysIncrementalInline", + "-XX:-PartialPeelLoop", + "-XX:-LoopUnswitching"); + tf.addScenarios( + new Scenario(1, "-XX:-StressIGVN", "-XX:+UseDeepIGVNRevisit"), + new Scenario(2, "-XX:+StressIGVN", "-XX:+UseDeepIGVNRevisit"), + new Scenario(3, "-XX:-StressIGVN", "-XX:-UseDeepIGVNRevisit"), + new Scenario(4, "-XX:+StressIGVN", "-XX:-UseDeepIGVNRevisit")); + tf.start(); + } + + static void lateInline() {} + + // Deferred calls create separate LoadRange nodes for the two arr[idx] + // accesses. After inlining, LoadRanges CSE but RangeCheck#2 is already + // processed. Deep revisit re-processes it with matching range pointers. + @Setup + static Object[] setupRangeCheck() { + return new Object[] { new int[100], 42 }; + } + + @Test + @Arguments(setup = "setupRangeCheck") + @IR(phase = CompilePhase.ITER_GVN2, + applyIf = {"UseDeepIGVNRevisit", "true"}, + counts = {IRNode.RANGE_CHECK, "1"}) + @IR(phase = CompilePhase.ITER_GVN2, + applyIf = {"UseDeepIGVNRevisit", "false"}, + counts = {IRNode.RANGE_CHECK, "2"}) + static int testRangeCheck(int[] arr, int idx) { + int r = arr[idx]; // RangeCheck #1 + if (c1) { lateInline(); } + if (c2) { lateInline(); } + if (c3) { lateInline(); } + if (c4) { lateInline(); } + volatileField = r; + r += arr[idx]; // RangeCheck #2 + return r; + } +} diff --git a/test/hotspot/jtreg/compiler/igvn/TestFoldComparesCleanup.java b/test/hotspot/jtreg/compiler/igvn/TestFoldComparesCleanup.java new file mode 100644 index 00000000000..bcc3b9541ba --- /dev/null +++ b/test/hotspot/jtreg/compiler/igvn/TestFoldComparesCleanup.java @@ -0,0 +1,56 @@ +/* + * Copyright Amazon.com Inc. or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8375442 + * @summary fold_compares_helper must clean up speculative lo node when bailing out with deep revisit + * @library /test/lib / + * @run main/othervm -XX:-TieredCompilation -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:VerifyIterativeGVN=1110 + * -XX:CompileCommand=compileonly,${test.main.class}::test + * ${test.main.class} + * + * @run main ${test.main.class} + */ +package compiler.igvn; + +import jdk.test.lib.Asserts; + +public class TestFoldComparesCleanup { + // Constants chosen so that fold_compares_helper computes adjusted_lim which overflows negative. + static final int A = -2_000_000_000; + static final int B = 2_000_000_000; + + static int test(int z) { + int sum = 0; + if (z > A) sum += 1; + if (z < B) sum += 2; + return sum; + } + + public static void main(String[] args) { + for (int i = 0; i < 50_000; i++) { + Asserts.assertEquals(3, test(i)); + } + } +} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java index 0753a0b04bc..0e1accf8a50 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java @@ -1776,6 +1776,11 @@ public class IRNode { trapNodes(PREDICATE_TRAP, "predicate"); } + public static final String RANGE_CHECK = PREFIX + "RANGE_CHECK" + POSTFIX; + static { + beforeMatchingNameRegex(RANGE_CHECK, "RangeCheck"); + } + public static final String RANGE_CHECK_TRAP = PREFIX + "RANGE_CHECK_TRAP" + POSTFIX; static { trapNodes(RANGE_CHECK_TRAP, "range_check"); From c76381996a9f2c90213ed8d5f84526c82fe07a67 Mon Sep 17 00:00:00 2001 From: Alexey Semenyuk Date: Wed, 1 Apr 2026 00:29:44 +0000 Subject: [PATCH 091/116] 8381384: jpackage: add test coverage to WiX discovery Reviewed-by: almatvee --- .../internal/EnvironmentProvider.java | 45 ++ .../jdk/jpackage/internal/Globals.java | 8 + .../jdk/jpackage/internal/util/PathUtils.java | 33 +- .../jdk/jpackage/internal/WixTool.java | 288 +++---- .../jdk/jpackage/internal/WixToolset.java | 29 +- .../resources/WinResources.properties | 5 +- .../test/mock/MockingToolProvider.java | 2 +- .../test/stdmock/EnvironmentProviderMock.java | 64 ++ .../jpackage/test/stdmock/WixToolMock.java | 173 ++++ .../jpackage/internal/util/PathUtilsTest.java | 213 +++++ .../jdk/jpackage/internal/WixToolTest.java | 754 ++++++++++++++++++ .../tools/jpackage/junit/windows/junit.java | 12 + 12 files changed, 1461 insertions(+), 165 deletions(-) create mode 100644 src/jdk.jpackage/share/classes/jdk/jpackage/internal/EnvironmentProvider.java create mode 100644 test/jdk/tools/jpackage/helpers/jdk/jpackage/test/stdmock/EnvironmentProviderMock.java create mode 100644 test/jdk/tools/jpackage/helpers/jdk/jpackage/test/stdmock/WixToolMock.java create mode 100644 test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/util/PathUtilsTest.java create mode 100644 test/jdk/tools/jpackage/junit/windows/jdk.jpackage/jdk/jpackage/internal/WixToolTest.java diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/EnvironmentProvider.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/EnvironmentProvider.java new file mode 100644 index 00000000000..de364129256 --- /dev/null +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/EnvironmentProvider.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 jdk.jpackage.internal; + +public interface EnvironmentProvider { + + String getProperty(String propertyName); + + String getenv(String envVarName); + + public static EnvironmentProvider DEFAULT = new EnvironmentProvider() { + + @Override + public String getenv(String envVarName) { + return System.getenv(envVarName); + } + + @Override + public String getProperty(String propertyName) { + return System.getProperty(propertyName); + } + }; +} diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/Globals.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/Globals.java index 0128d050c25..2fc0046fad5 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/Globals.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/Globals.java @@ -65,6 +65,14 @@ public Globals setProperty(Object key, T value) { return this; } + public EnvironmentProvider system() { + return this.findProperty(EnvironmentProvider.class).orElse(EnvironmentProvider.DEFAULT); + } + + public Globals system(EnvironmentProvider v) { + return setProperty(EnvironmentProvider.class, v); + } + Log.Logger logger() { return logger; } diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/PathUtils.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/PathUtils.java index a8944a67ae0..707dd2784ce 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/PathUtils.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/PathUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,7 @@ */ package jdk.jpackage.internal.util; +import java.nio.file.InvalidPathException; import java.nio.file.Path; import java.util.Objects; import java.util.Optional; @@ -31,18 +32,26 @@ public final class PathUtils { + private PathUtils() { + } + public static String getSuffix(Path path) { String filename = replaceSuffix(path.getFileName(), null).toString(); return path.getFileName().toString().substring(filename.length()); } public static Path addSuffix(Path path, String suffix) { + Objects.requireNonNull(path); + Objects.requireNonNull(suffix); + Path parent = path.getParent(); String filename = path.getFileName().toString() + suffix; return parent != null ? parent.resolve(filename) : Path.of(filename); } public static Path replaceSuffix(Path path, String suffix) { + Objects.requireNonNull(path); + Path parent = path.getParent(); String filename = path.getFileName().toString().replaceAll("\\.[^.]*$", "") + Optional.ofNullable(suffix).orElse(""); @@ -59,18 +68,22 @@ public static Path mapNullablePath(UnaryOperator mapper, Path path) { } public static Path normalizedAbsolutePath(Path path) { - if (path != null) { + return mapNullablePath(_ -> { return path.normalize().toAbsolutePath(); - } else { - return null; - } + }, path); } public static String normalizedAbsolutePathString(Path path) { - if (path != null) { - return normalizedAbsolutePath(path).toString(); - } else { - return null; - } + return Optional.ofNullable(normalizedAbsolutePath(path)).map(Path::toString).orElse(null); + } + + public static Optional asPath(String value) { + return Optional.ofNullable(value).map(v -> { + try { + return Path.of(v); + } catch (InvalidPathException ex) { + return null; + } + }); } } diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixTool.java b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixTool.java index c4f8610312a..d0c5e6ca3b0 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixTool.java +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixTool.java @@ -23,14 +23,14 @@ * questions. */ package jdk.jpackage.internal; +import static java.util.stream.Collectors.groupingBy; +import static java.util.stream.Collectors.toMap; +import static java.util.stream.Collectors.toSet; import java.io.IOException; import java.nio.file.FileSystems; import java.nio.file.Files; -import java.nio.file.InvalidPathException; import java.nio.file.Path; -import java.nio.file.PathMatcher; -import java.text.MessageFormat; import java.util.Comparator; import java.util.List; import java.util.Map; @@ -38,12 +38,13 @@ import java.util.Optional; import java.util.Set; import java.util.function.Function; -import java.util.stream.Collectors; +import java.util.function.Supplier; import java.util.stream.Stream; import jdk.jpackage.internal.WixToolset.WixToolsetType; import jdk.jpackage.internal.model.ConfigException; import jdk.jpackage.internal.model.DottedVersion; import jdk.jpackage.internal.util.PathUtils; +import jdk.jpackage.internal.util.Slot; /** * WiX tool. @@ -58,16 +59,20 @@ public enum WixTool { this.minimalVersion = minimalVersion; } - interface ToolInfo { + Path fileName() { + return toolFileName; + } + + sealed interface ToolInfo { Path path(); DottedVersion version(); } - interface CandleInfo extends ToolInfo { + sealed interface CandleInfo extends ToolInfo { boolean fips(); } - private record DefaultToolInfo(Path path, DottedVersion version) implements ToolInfo { + record DefaultToolInfo(Path path, DottedVersion version) implements ToolInfo { DefaultToolInfo { Objects.requireNonNull(path); Objects.requireNonNull(version); @@ -76,9 +81,14 @@ private record DefaultToolInfo(Path path, DottedVersion version) implements Tool DefaultToolInfo(Path path, String version) { this(path, DottedVersion.lazy(version)); } + + @Override + public String toString() { + return String.format("%s|ver=%s", path, version); + } } - private record DefaultCandleInfo(Path path, DottedVersion version, boolean fips) implements CandleInfo { + record DefaultCandleInfo(Path path, DottedVersion version, boolean fips) implements CandleInfo { DefaultCandleInfo { Objects.requireNonNull(path); Objects.requireNonNull(version); @@ -87,25 +97,42 @@ private record DefaultCandleInfo(Path path, DottedVersion version, boolean fips) DefaultCandleInfo(ToolInfo info, boolean fips) { this(info.path(), info.version(), fips); } + + @Override + public String toString() { + var sb = new StringBuffer(); + sb.append(path); + if (fips) { + sb.append("|fips"); + } + sb.append("|ver=").append(version); + return sb.toString(); + } } static WixToolset createToolset() { + return createToolset(WixTool::findWixInstallDirs, true); + } + + static WixToolset createToolset(Supplier> wixInstallDirs, boolean searchInPath) { + Function, Map> conv = lookupResults -> { - return lookupResults.stream().filter(ToolLookupResult::isValid).collect(Collectors. - groupingBy(lookupResult -> { + return lookupResults.stream().filter(ToolLookupResult::isValid).collect(groupingBy(lookupResult -> { return lookupResult.info().version().toString(); })).values().stream().filter(sameVersionLookupResults -> { - Set sameVersionTools = sameVersionLookupResults.stream().map( - ToolLookupResult::tool).collect(Collectors.toSet()); - if (sameVersionTools.equals(Set.of(Candle3)) || sameVersionTools.equals(Set.of( - Light3))) { + var sameVersionTools = sameVersionLookupResults.stream() + .map(ToolLookupResult::tool) + .collect(toSet()); + if (sameVersionTools.equals(Set.of(Candle3)) || sameVersionTools.equals(Set.of(Light3))) { // There is only one tool from WiX v3 toolset of some version available. Discard it. return false; } else { return true; } - }).flatMap(List::stream).collect(Collectors.toMap(ToolLookupResult::tool, - ToolLookupResult::info, (ToolInfo x, ToolInfo y) -> { + }).flatMap(List::stream).collect(toMap( + ToolLookupResult::tool, + ToolLookupResult::info, + (ToolInfo x, ToolInfo y) -> { return Stream.of(x, y).sorted(Comparator.comparing((ToolInfo toolInfo) -> { return toolInfo.version().toComponentsString(); }).reversed()).findFirst().get(); @@ -115,58 +142,53 @@ static WixToolset createToolset() { Function, Optional> createToolset = lookupResults -> { var tools = conv.apply(lookupResults); // Try to build a toolset found in the PATH and in known locations. - return Stream.of(WixToolsetType.values()).map(toolsetType -> { - return WixToolset.create(toolsetType.getTools(), tools); - }).filter(Objects::nonNull).findFirst(); + return Stream.of(WixToolsetType.values()).flatMap(toolsetType -> { + return WixToolset.create(toolsetType, tools).stream(); + }).findFirst(); }; - var toolsInPath = Stream.of(values()).map(tool -> { - return ToolLookupResult.lookup(tool, Optional.empty()); - }).filter(Optional::isPresent).map(Optional::get).toList(); - - // Try to build a toolset from tools in the PATH first. - var toolset = createToolset.apply(toolsInPath); - if (toolset.isPresent()) { - return toolset.get(); + final List toolsInPath; + if (searchInPath) { + toolsInPath = Stream.of(values()).flatMap(tool -> { + return ToolLookupResult.lookup(tool, Optional.empty()).stream(); + }).toList(); + } else { + toolsInPath = List.of(); } - // Look up for WiX tools in known locations. - var toolsInKnownWiXDirs = findWixInstallDirs().stream().map(dir -> { - return Stream.of(values()).map(tool -> { - return ToolLookupResult.lookup(tool, Optional.of(dir)); + // Try to build a toolset from tools in the PATH first. + var toolset = createToolset.apply(toolsInPath).orElseGet(() -> { + // Look up for WiX tools in known locations. + var toolsInKnownWiXDirs = wixInstallDirs.get().stream().flatMap(dir -> { + return Stream.of(values()).flatMap(tool -> { + return ToolLookupResult.lookup(tool, Optional.of(dir)).stream(); + }); + }).toList(); + + // Build a toolset found in the PATH and in known locations. + var allValidFoundTools = Stream.of(toolsInPath, toolsInKnownWiXDirs) + .flatMap(List::stream) + .filter(ToolLookupResult::isValid) + .toList(); + + return createToolset.apply(allValidFoundTools).orElseThrow(() -> { + return new ConfigException( + I18N.getString("error.no-wix-tools"), + I18N.getString("error.no-wix-tools.advice")); }); - }).flatMap(Function.identity()).filter(Optional::isPresent).map(Optional::get).toList(); - - // Build a toolset found in the PATH and in known locations. - var allFoundTools = Stream.of(toolsInPath, toolsInKnownWiXDirs).flatMap(List::stream).filter( - ToolLookupResult::isValid).toList(); - toolset = createToolset.apply(allFoundTools); - if (toolset.isPresent()) { - return toolset.get(); - } else if (allFoundTools.isEmpty()) { - throw new ConfigException(I18N.getString("error.no-wix-tools"), I18N.getString( - "error.no-wix-tools.advice")); - } else { - var toolOldVerErr = allFoundTools.stream().map(lookupResult -> { - if (lookupResult.versionTooOld) { - return new ConfigException(MessageFormat.format(I18N.getString( - "message.wrong-tool-version"), lookupResult.info().path(), - lookupResult.info().version(), lookupResult.tool().minimalVersion), - I18N.getString("error.no-wix-tools.advice")); - } else { - return null; - } - }).filter(Objects::nonNull).findAny(); - if (toolOldVerErr.isPresent()) { - throw toolOldVerErr.get(); - } else { - throw new ConfigException(I18N.getString("error.no-wix-tools"), I18N.getString( - "error.no-wix-tools.advice")); - } - } + }); + + return toolset; } - private record ToolLookupResult(WixTool tool, ToolInfo info, boolean versionTooOld) { + static List findWixInstallDirs() { + return Stream.of( + findWixCurrentInstallDirs(), + findWix3InstallDirs() + ).flatMap(List::stream).toList(); + } + + private record ToolLookupResult(WixTool tool, ToolInfo info) { ToolLookupResult { Objects.requireNonNull(tool); @@ -177,58 +199,59 @@ static Optional lookup(WixTool tool, Optional lookupDir) Objects.requireNonNull(tool); Objects.requireNonNull(lookupDir); - final Path toolPath = lookupDir.map(p -> p.resolve( - tool.toolFileName)).orElse(tool.toolFileName); - - final boolean[] tooOld = new boolean[1]; - final String[] parsedVersion = new String[1]; + final Path toolPath = lookupDir.map(p -> { + return p.resolve(tool.toolFileName); + }).orElse(tool.toolFileName); - final var validator = new ToolValidator(toolPath) - .setMinimalVersion(tool.minimalVersion) - .setToolOldVersionErrorHandler((name, version) -> { - tooOld[0] = true; - return null; - }); + final var validator = new ToolValidator(toolPath).setMinimalVersion(tool.minimalVersion); - final Function, String> versionParser; - - if (Set.of(Candle3, Light3).contains(tool)) { - final String printVersionArg; - if (tool == Candle3) { + final var printVersionArg = switch (tool) { + case Candle3 -> { // Add '-fips' to make "candle.exe" print help message and return // 0 exit code instead of returning error exit code and printing // "error CNDL0308 : The Federal Information Processing Standard (FIPS) appears to be enabled on the machine..." // error message if FIPS is enabled. // If FIPS is disabled, passing '-fips' parameter still makes // "candle.exe" print help message and return 0 exit code. - printVersionArg = "-fips"; - } else { - printVersionArg = "-?"; + yield "-fips"; } - validator.setCommandLine(printVersionArg); - versionParser = output -> { - String firstLineOfOutput = output.findFirst().orElse(""); - int separatorIdx = firstLineOfOutput.lastIndexOf(' '); - if (separatorIdx == -1) { - return null; - } - return firstLineOfOutput.substring(separatorIdx + 1); - }; - } else { - validator.setCommandLine("--version"); - versionParser = output -> { - return output.findFirst().orElse(""); - }; - } + case Light3 -> { + yield "-?"; + } + default -> { + yield "--version"; + } + }; + validator.setCommandLine(printVersionArg); + + final Function, Optional> versionParser = switch (tool) { + case Candle3, Light3 -> { + yield output -> { + return output.findFirst().map(firstLineOfOutput -> { + int separatorIdx = firstLineOfOutput.lastIndexOf(' '); + if (separatorIdx == -1) { + return null; + } + return firstLineOfOutput.substring(separatorIdx + 1); + }); + }; + } + default -> { + yield output -> { + return output.findFirst(); + }; + } + }; + final var parsedVersion = Slot.createEmpty(); validator.setVersionParser(output -> { - parsedVersion[0] = versionParser.apply(output); - return parsedVersion[0]; + versionParser.apply(output).ifPresent(parsedVersion::set); + return parsedVersion.find().orElse(null); }); if (validator.validate() == null) { // Tool found - ToolInfo info = new DefaultToolInfo(toolPath, parsedVersion[0]); + ToolInfo info = new DefaultToolInfo(toolPath, parsedVersion.get()); if (tool == Candle3) { // Detect FIPS mode var fips = false; @@ -242,63 +265,52 @@ static Optional lookup(WixTool tool, Optional lookupDir) } } } catch (IOException ex) { - Log.verbose(ex); } info = new DefaultCandleInfo(info, fips); } - return Optional.of(new ToolLookupResult(tool, info, tooOld[0])); + + return Optional.of(new ToolLookupResult(tool, info)); } else { return Optional.empty(); } } - boolean isValid() { - return !versionTooOld; + boolean versionTooOld() { + return DottedVersion.compareComponents(info.version(), tool.minimalVersion) < 0; } - } - private static Path getSystemDir(String envVar, String knownDir) { - return Optional - .ofNullable(getEnvVariableAsPath(envVar)) - .orElseGet(() -> Optional - .ofNullable(getEnvVariableAsPath("SystemDrive")) - .orElseGet(() -> Path.of("C:")).resolve(knownDir)); + boolean isValid() { + return !versionTooOld(); + } } - private static Path getEnvVariableAsPath(String envVar) { - String path = System.getenv(envVar); - if (path != null) { - try { - return Path.of(path); - } catch (InvalidPathException ex) { - Log.error(MessageFormat.format(I18N.getString( - "error.invalid-envvar"), envVar)); - } - } - return null; + private static Path getSystemDir(String envVar, Path knownDir) { + return getEnvVariableAsPath(envVar).orElseGet(() -> { + return getEnvVariableAsPath("SystemDrive").orElseGet(() -> { + return Path.of("C:"); + }).resolve(knownDir); + }); } - private static List findWixInstallDirs() { - return Stream.of(findWixCurrentInstallDirs(), findWix3InstallDirs()). - flatMap(List::stream).toList(); + private static Optional getEnvVariableAsPath(String envVar) { + Objects.requireNonNull(envVar); + return Optional.ofNullable(Globals.instance().system().getenv(envVar)).flatMap(PathUtils::asPath); } private static List findWixCurrentInstallDirs() { - return Stream.of(getEnvVariableAsPath("USERPROFILE"), Optional.ofNullable(System. - getProperty("user.home")).map(Path::of).orElse(null)).filter(Objects::nonNull).map( - path -> { - return path.resolve(".dotnet/tools"); - }).filter(Files::isDirectory).distinct().toList(); + return Stream.of( + getEnvVariableAsPath("USERPROFILE"), + Optional.ofNullable(Globals.instance().system().getProperty("user.home")).flatMap(PathUtils::asPath) + ).flatMap(Optional::stream).map(path -> { + return path.resolve(".dotnet/tools"); + }).filter(Files::isDirectory).distinct().toList(); } private static List findWix3InstallDirs() { - PathMatcher wixInstallDirMatcher = FileSystems.getDefault(). - getPathMatcher( - "glob:WiX Toolset v*"); + var wixInstallDirMatcher = FileSystems.getDefault().getPathMatcher("glob:WiX Toolset v*"); - Path programFiles = getSystemDir("ProgramFiles", "\\Program Files"); - Path programFilesX86 = getSystemDir("ProgramFiles(x86)", - "\\Program Files (x86)"); + var programFiles = getSystemDir("ProgramFiles", Path.of("Program Files")); + var programFilesX86 = getSystemDir("ProgramFiles(x86)", Path.of("Program Files (x86)")); // Returns list of WiX install directories ordered by WiX version number. // Newer versions go first. @@ -306,13 +318,11 @@ private static List findWix3InstallDirs() { try (var paths = Files.walk(path, 1)) { return paths.toList(); } catch (IOException ex) { - Log.verbose(ex); - List empty = List.of(); - return empty; + return List.of(); } }).flatMap(List::stream) - .filter(path -> wixInstallDirMatcher.matches(path.getFileName())). - sorted(Comparator.comparing(Path::getFileName).reversed()) + .filter(path -> wixInstallDirMatcher.matches(path.getFileName())) + .sorted(Comparator.comparing(Path::getFileName).reversed()) .map(path -> path.resolve("bin")) .toList(); } diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixToolset.java b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixToolset.java index e7bdbede368..1694503a8c8 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixToolset.java +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixToolset.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,14 +26,20 @@ import java.nio.file.Path; import java.util.Map; +import java.util.Objects; +import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; import jdk.jpackage.internal.model.DottedVersion; -final class WixToolset { +record WixToolset(Map tools) { - static enum WixToolsetType { + WixToolset { + tools = Map.copyOf(tools); + } + + enum WixToolsetType { // Wix v4+ Wix4(WixTool.Wix4), // Wix v3+ @@ -50,10 +56,6 @@ Set getTools() { private final Set tools; } - private WixToolset(Map tools) { - this.tools = tools; - } - WixToolsetType getType() { return Stream.of(WixToolsetType.values()).filter(toolsetType -> { return toolsetType.getTools().equals(tools.keySet()); @@ -75,16 +77,19 @@ boolean needFipsParameter() { .anyMatch(WixTool.CandleInfo::fips); } - static WixToolset create(Set requiredTools, Map allTools) { + static Optional create(WixToolsetType type, Map allTools) { + Objects.requireNonNull(type); + Objects.requireNonNull(allTools); + + var requiredTools = type.getTools(); + var filteredTools = allTools.entrySet().stream().filter(e -> { return requiredTools.contains(e.getKey()); }).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); if (filteredTools.keySet().equals(requiredTools)) { - return new WixToolset(filteredTools); + return Optional.of(new WixToolset(filteredTools)); } else { - return null; + return Optional.empty(); } } - - private final Map tools; } diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources.properties b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources.properties index 0f3dcab8260..a11a8a6b41e 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources.properties +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources.properties @@ -36,8 +36,8 @@ resource.launcher-as-service-wix-file=Service installer WiX project file resource.wix-src-conv=XSLT stylesheet converting WiX sources from WiX v3 to WiX v4 format resource.installer-exe=installer executable -error.no-wix-tools=Can not find WiX tools. Was looking for WiX v3 light.exe and candle.exe or WiX v4/v5 wix.exe and none was found -error.no-wix-tools.advice=Download WiX 3.0 or later from https://wixtoolset.org and add it to the PATH. +error.no-wix-tools=No usable WiX Toolset installation found +error.no-wix-tools.advice=Install the latest WiX v3 from https://github.com/wixtoolset/wix3/releases or WiX v4+ from https://github.com/wixtoolset/wix/releases error.version-string-wrong-format.advice=Set value of --app-version parameter to a valid Windows Installer ProductVersion. error.msi-product-version-components=Version string [{0}] must have between 2 and 4 components. error.msi-product-version-major-out-of-range=Major version must be in the range [0, 255] @@ -56,7 +56,6 @@ error.missing-service-installer.advice=Add 'service-installer.exe' service insta message.icon-not-ico=The specified icon "{0}" is not an ICO file and will not be used. The default icon will be used in it's place. message.tool-version=Detected [{0}] version [{1}]. -message.wrong-tool-version=Detected [{0}] version {1} but version {2} is required. message.product-code=MSI ProductCode: {0}. message.upgrade-code=MSI UpgradeCode: {0}. message.preparing-msi-config=Preparing MSI config: {0}. diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/mock/MockingToolProvider.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/mock/MockingToolProvider.java index f8c04cc3927..2c46d02e7ce 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/mock/MockingToolProvider.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/mock/MockingToolProvider.java @@ -160,5 +160,5 @@ static final class Completable extends MockingToolProvider implements ToolProvid private final String name; private final Iterator actionIter; - static ToolProviderCommandMock UNREACHABLE = new MockingToolProvider.NonCompletable("", List.of()); + static final ToolProviderCommandMock UNREACHABLE = new MockingToolProvider.NonCompletable("", List.of()); } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/stdmock/EnvironmentProviderMock.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/stdmock/EnvironmentProviderMock.java new file mode 100644 index 00000000000..1e12078ec66 --- /dev/null +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/stdmock/EnvironmentProviderMock.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.jpackage.test.stdmock; + +import jdk.jpackage.internal.EnvironmentProvider; +import java.util.ArrayList; +import java.util.Map; +import java.util.Objects; + +public record EnvironmentProviderMock( + Map envVariables, + Map systemProperties) implements EnvironmentProvider { + + public EnvironmentProviderMock { + envVariables.keySet().forEach(Objects::requireNonNull); + envVariables.values().forEach(Objects::requireNonNull); + + systemProperties.keySet().forEach(Objects::requireNonNull); + systemProperties.values().forEach(Objects::requireNonNull); + } + + @Override + public String getenv(String envVarName) { + return envVariables.get(Objects.requireNonNull(envVarName)); + } + + @Override + public String getProperty(String propertyName) { + return systemProperties.get(Objects.requireNonNull(propertyName)); + } + + @Override + public String toString() { + var tokens = new ArrayList(); + if (!envVariables.isEmpty()) { + tokens.add(String.format("env=%s", envVariables)); + } + if (!systemProperties.isEmpty()) { + tokens.add(String.format("props=%s", systemProperties)); + } + return String.join(", ", tokens); + } +} diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/stdmock/WixToolMock.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/stdmock/WixToolMock.java new file mode 100644 index 00000000000..9cd00f61082 --- /dev/null +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/stdmock/WixToolMock.java @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.jpackage.test.stdmock; + +import java.nio.file.Path; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import jdk.jpackage.internal.util.PathUtils; +import jdk.jpackage.test.mock.CommandActionSpec; +import jdk.jpackage.test.mock.CommandActionSpecs; +import jdk.jpackage.test.mock.CommandMockSpec; + +public final class WixToolMock { + + public CommandMockSpec create() { + Objects.requireNonNull(type); + Objects.requireNonNull(version); + + CommandActionSpec action = switch (type) { + case CANDLE3 -> { + yield candleAction(fips, version); + } + case LIGHT3 -> { + yield lightAction(version); + } + case WIX4 -> { + yield wixAction(version); + } + }; + + var toolPath = Optional.ofNullable(dir).map(d -> { + return d.resolve(type.fileName); + }).orElse(type.fileName); + var mockName = PathUtils.replaceSuffix(toolPath, ""); + + return new CommandMockSpec(toolPath, mockName, CommandActionSpecs.build().action(action).create()); + } + + public WixToolMock fips(Boolean v) { + fips = v; + return this; + } + + public WixToolMock fips() { + return fips(true); + } + + public WixToolMock dir(Path v) { + dir = v; + return this; + } + + public WixToolMock version(String v) { + version = v; + return this; + } + + public WixToolMock candle(String version) { + return type(WixTool.CANDLE3).version(version); + } + + public WixToolMock light(String version) { + return type(WixTool.LIGHT3).version(version); + } + + public WixToolMock wix(String version) { + return type(WixTool.WIX4).version(version); + } + + private WixToolMock type(WixTool v) { + type = v; + return this; + } + + private static CommandActionSpec candleAction(boolean fips, String version) { + Objects.requireNonNull(version); + var sb = new StringBuilder(); + sb.append(version); + if (fips) { + sb.append("; fips"); + } + return CommandActionSpec.create(sb.toString(), context -> { + if (List.of("-?").equals(context.args())) { + if (fips) { + context.err().println("error CNDL0308 : The Federal Information Processing Standard (FIPS) appears to be enabled on the machine"); + return Optional.of(308); + } + } else if (!List.of("-fips").equals(context.args())) { + throw context.unexpectedArguments(); + } + + var out = context.out(); + List.of( + "Windows Installer XML Toolset Compiler version " + version, + "Copyright (c) .NET Foundation and contributors. All rights reserved.", + "", + " usage: candle.exe [-?] [-nologo] [-out outputFile] sourceFile [sourceFile ...] [@responseFile]" + ).forEach(out::println); + + return Optional.of(0); + }); + } + + private static CommandActionSpec lightAction(String version) { + Objects.requireNonNull(version); + return CommandActionSpec.create(version, context -> { + if (List.of("-?").equals(context.args())) { + var out = context.out(); + List.of( + "Windows Installer XML Toolset Linker version " + version, + "Copyright (c) .NET Foundation and contributors. All rights reserved.", + "", + " usage: light.exe [-?] [-b bindPath] [-nologo] [-out outputFile] objectFile [objectFile ...] [@responseFile]" + ).forEach(out::println); + return Optional.of(0); + } else { + throw context.unexpectedArguments(); + } + }); + } + + private static CommandActionSpec wixAction(String version) { + Objects.requireNonNull(version); + return CommandActionSpec.create(version, context -> { + if (List.of("--version").equals(context.args())) { + context.out().println(version); + return Optional.of(0); + } else { + throw context.unexpectedArguments(); + } + }); + } + + private enum WixTool { + CANDLE3("candle"), + LIGHT3("light"), + WIX4("wix"), + ; + + WixTool(String name) { + this.fileName = Path.of(Objects.requireNonNull(name) + ".exe"); + } + + final Path fileName; + } + + private Path dir; + private WixTool type; + private String version; + private boolean fips; +} diff --git a/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/util/PathUtilsTest.java b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/util/PathUtilsTest.java new file mode 100644 index 00000000000..7ed679ea3b5 --- /dev/null +++ b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/util/PathUtilsTest.java @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.jpackage.internal.util; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrowsExactly; + +import java.nio.file.Path; +import java.util.Optional; +import java.util.function.UnaryOperator; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + + +class PathUtilsTest { + + @ParameterizedTest + @CsvSource({ + "foo,''", + "foo.bar,.bar", + "foo..bar,.bar", + ".bar,.bar", + "foo.bar.buz,.buz", + ".,.", + "...,.", + "..,.", + }) + void test_getSuffix(Path path, String expected) { + + var suffix = PathUtils.getSuffix(path); + + assertEquals(expected, suffix); + } + + @Test + void test_getSuffix_null() { + assertThrowsExactly(NullPointerException.class, () -> { + PathUtils.getSuffix(null); + }); + } + + @ParameterizedTest + @CsvSource({ + "foo,'',foo", + "a/b/foo.exe,.ico,a/b/foo.exe.ico", + "foo,bar,foobar", + "'',bar,bar", + ".,bar,.bar", + }) + void test_addSuffix(Path path, String suffix, Path expected) { + + var newPath = PathUtils.addSuffix(path, suffix); + + assertEquals(expected, newPath); + } + + @Test + void test_addSuffix_null() { + assertThrowsExactly(NullPointerException.class, () -> { + PathUtils.addSuffix(null, "foo"); + }); + assertThrowsExactly(NullPointerException.class, () -> { + PathUtils.addSuffix(Path.of("foo"), null); + }); + } + + @ParameterizedTest + @CsvSource({ + "foo.exe,.ico,foo.ico", + "foo.exe,,foo", + "foo.exe,'',foo", + "a/b/foo.exe,.ico,a/b/foo.ico", + "foo,'',foo", + "foo,bar,foobar", + "'',bar,bar", + ".,bar,bar", + ".,.bar,.bar", + }) + void test_replaceSuffix(Path path, String newSuffix, Path expected) { + + var newPath = PathUtils.replaceSuffix(path, newSuffix); + + assertEquals(expected, newPath); + } + + @Test + void test_replaceSuffix_null() { + assertThrowsExactly(NullPointerException.class, () -> { + PathUtils.replaceSuffix(null, "foo"); + }); + + assertEquals(Path.of("foo"), PathUtils.replaceSuffix(Path.of("foo.a"), null)); + } + + @ParameterizedTest + @CsvSource({ + "IDENTITY,a,a", + "IDENTITY,,", + "RETURN_NULL,a,", + "RETURN_NULL,,", + "FOO,a,foo", + "FOO,,", + }) + void test_mapNullablePath(PathMapper mapper, Path path, Path expected) { + + var newPath = PathUtils.mapNullablePath(mapper, path); + + assertEquals(expected, newPath); + } + + @Test + void test_mapNullablePath_null() { + assertThrowsExactly(NullPointerException.class, () -> { + PathUtils.mapNullablePath(null, Path.of("")); + }); + } + + @ParameterizedTest + @CsvSource(nullValues = {"N/A"}, value = { + "foo.exe", + "N/A", + }) + void test_normalizedAbsolutePath(Path path) { + + var newPath = PathUtils.normalizedAbsolutePath(path); + + var expected = Optional.ofNullable(path).map(v -> { + return v.normalize().toAbsolutePath(); + }).orElse(null); + + assertEquals(expected, newPath); + } + + @ParameterizedTest + @CsvSource(nullValues = {"N/A"}, value = { + "foo.exe", + "N/A", + }) + void test_normalizedAbsolutePathString(Path path) { + + var newPath = PathUtils.normalizedAbsolutePathString(path); + + var expected = Optional.ofNullable(path).map(v -> { + return v.normalize().toAbsolutePath().toString(); + }).orElse(null); + + assertEquals(expected, newPath); + } + + @ParameterizedTest + @CsvSource(nullValues = {"N/A"}, value = { + "N/A", + "foo", + "*", + ":", + }) + void test_asPath(String str) { + + var path = PathUtils.asPath(str); + + var expected = Optional.ofNullable(str).flatMap(v -> { + return Result.of(() -> { + return Path.of(v); + }).value(); + }); + + assertEquals(expected, path); + } + + enum PathMapper implements UnaryOperator { + IDENTITY { + @Override + public Path apply(Path path) { + return path; + } + }, + RETURN_NULL { + @Override + public Path apply(Path path) { + return null; + } + }, + FOO { + @Override + public Path apply(Path path) { + return Path.of("foo"); + } + }, + ; + } +} diff --git a/test/jdk/tools/jpackage/junit/windows/jdk.jpackage/jdk/jpackage/internal/WixToolTest.java b/test/jdk/tools/jpackage/junit/windows/jdk.jpackage/jdk/jpackage/internal/WixToolTest.java new file mode 100644 index 00000000000..d4881069844 --- /dev/null +++ b/test/jdk/tools/jpackage/junit/windows/jdk.jpackage/jdk/jpackage/internal/WixToolTest.java @@ -0,0 +1,754 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.jpackage.internal; + +import static java.util.stream.Collectors.toMap; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.function.Supplier; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import jdk.jpackage.internal.WixTool.ToolInfo; +import jdk.jpackage.internal.WixToolset.WixToolsetType; +import jdk.jpackage.internal.model.ConfigException; +import jdk.jpackage.internal.util.TokenReplace; +import jdk.jpackage.test.CannedFormattedString; +import jdk.jpackage.test.JPackageStringBundle; +import jdk.jpackage.test.mock.CommandActionSpecs; +import jdk.jpackage.test.mock.CommandMock; +import jdk.jpackage.test.mock.CommandMockSpec; +import jdk.jpackage.test.mock.Script; +import jdk.jpackage.test.stdmock.EnvironmentProviderMock; +import jdk.jpackage.test.stdmock.JPackageMockUtils; +import jdk.jpackage.test.stdmock.WixToolMock; +import org.junit.jupiter.api.io.TempDir; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + + +class WixToolTest { + + @ParameterizedTest + @MethodSource + void testLookup(TestSpec spec, @TempDir Path workDir) throws IOException { + spec.run(workDir); + } + + @ParameterizedTest + @MethodSource + void testLookupDirs(EnvironmentTestSpec spec, @TempDir Path workDir) throws IOException { + spec.run(workDir); + } + + private static Collection testLookup() { + + List testCases = new ArrayList<>(); + + Consumer appendTestCases = builder -> { + testCases.add(builder.create()); + }; + + Stream.of( + // Simple WiX3 of a minimal acceptable version + TestSpec.build() + .expect(toolset().version("3.0").put(WixToolsetType.Wix3, "foo")) + .tool(tool("foo").candle("3.0")) + .tool(tool("foo").light("3.0")), + // Simple WiX3 with FIPS + TestSpec.build() + .expect(toolset().version("3.14.1.8722").put(WixToolsetType.Wix3, "foo").fips()) + .tool(tool("foo").candle("3.14.1.8722").fips()) + .tool(tool("foo").light("3.14.1.8722")), + // Simple WiX4+ of a minimal acceptable version + TestSpec.build() + .expect(toolset().version("4.0.4").put(WixToolsetType.Wix4, "foo")) + .tool(tool("foo").wix("4.0.4")), + // WiX3 with light and candle from different directories and non-existent directory + TestSpec.build() + .expect(toolset().version("3.11.2").put(WixTool.Candle3, "foo").put(WixTool.Light3, "bar")) + .lookupDir("buz") + .tool(tool("foo").candle("3.11.2")) + .tool(tool("bar").light("3.11.2")) + .tool(tool("bar").candle("3.11.1")) + .tool(tool("foo").light("3.11.1")), + // WiX3, WiX4+ same directory + TestSpec.build() + .expect(toolset().version("5.0.2+aa65968c").put(WixToolsetType.Wix4, "foo")) + .tool(tool("foo").candle("3.14.1.8722")) + .tool(tool("foo").light("3.14.1.8722")) + .tool(tool("foo").wix("5.0.2+aa65968c")), + // WiX3 (good), WiX4+ (bad version) + TestSpec.build() + .expect(toolset().version("3.14.1.8722").put(WixToolsetType.Wix3, "foo")) + .tool(tool("foo").candle("3.14.1.8722")) + .tool(tool("foo").light("3.14.1.8722")) + .tool(tool("foo").wix("Blah-blah-blah")), + // WiX3 (incomplete), WiX4+ (good) + TestSpec.build() + .expect(toolset().version("5.0").put(WixToolsetType.Wix4, "foo")) + .tool(tool("foo").candle("3.14.1.8722")) + .tool(tool("foo").wix("5.0")), + // WiX5 in the PATH and in the directory, same version; PATH always wins + TestSpec.build() + .expect(toolset().version("5.0").put(WixToolsetType.Wix4)) + .tool(tool().wix("5.0")) + .tool(tool("foo").wix("5.0")), + // WiX5 in the PATH and in the directory; the one in the directory is newer; PATH always wins + TestSpec.build() + .expect(toolset().version("5.0").put(WixToolsetType.Wix4)) + .tool(tool().wix("5.0")) + .tool(tool("foo").wix("5.1")), + // WiX5 in the PATH and in the directory; the one in the PATH is newer; PATH always wins + TestSpec.build() + .expect(toolset().version("5.1").put(WixToolsetType.Wix4)) + .tool(tool().wix("5.1")) + .tool(tool("foo").wix("5.0")), + // WiX3 in the PATH, WiX3 in the directory; PATH always wins + TestSpec.build() + .expect(toolset().version("3.20").put(WixToolsetType.Wix3)) + .tool(tool().candle("3.20")) + .tool(tool().light("3.20")) + .tool(tool("foo").wix("5.0")), + // Old WiX3 in the PATH, WiX3 in the directory + TestSpec.build() + .expect(toolset().version("3.20").put(WixToolsetType.Wix3, "foo")) + .tool(tool().candle("2.9")) + .tool(tool().light("2.9")) + .tool(tool("foo").candle("3.20")) + .tool(tool("foo").light("3.20")) + ).forEach(appendTestCases); + + for (var oldLightStatus : ToolStatus.values()) { + for (var oldCandleStatus : ToolStatus.values()) { + for (var newLightStatus : ToolStatus.values()) { + for (var newCandleStatus : ToolStatus.values()) { + boolean newGood = ToolStatus.isAllGood(newLightStatus, newCandleStatus); + if (!ToolStatus.isAllGood(oldLightStatus, oldCandleStatus) && !newGood) { + continue; + } + + var builder = TestSpec.build(); + if (newGood) { + builder.expect(toolset().version("3.14").put(WixToolsetType.Wix3, "new")); + } else { + builder.expect(toolset().version("3.11").put(WixToolsetType.Wix3, "old")); + } + + oldCandleStatus.map(tool("old").candle("3.11")).ifPresent(builder::tool); + oldLightStatus.map(tool("old").light("3.11")).ifPresent(builder::tool); + + newCandleStatus.map(tool("new").candle("3.14")).ifPresent(builder::tool); + newLightStatus.map(tool("new").light("3.14")).ifPresent(builder::tool); + + appendTestCases.accept(builder); + } + } + } + } + + Stream.of( + // No WiX tools + TestSpec.build(), + TestSpec.build() + .lookupDir("foo"), + TestSpec.build() + .lookupDir(LOOKUP_IN_PATH), + // Incomplete WiX3: missing candle.exe + TestSpec.build() + .tool(tool("foo").light("3.14.1.8722")), + // Incomplete WiX3: missing light.exe + TestSpec.build() + .tool(tool("foo").candle("3.14.1.8722")), + // Incomplete WiX3: version mismatch of light.exe and candle.exe + TestSpec.build() + .tool(tool("foo").candle("3.14")) + .tool(tool("foo").light("3.15")), + // WiX3 too old + TestSpec.build() + .tool(tool("foo").candle("2.9")) + .tool(tool("foo").light("2.9")), + // WiX4+ too old + TestSpec.build() + .tool(tool("foo").wix("4.0.3")) + ).forEach(appendTestCases); + + return testCases; + } + + private static Collection testLookupDirs() { + + List testCases = new ArrayList<>(); + + Stream.of( + EnvironmentTestSpec.build() + .env(EnvironmentVariable.USERPROFILE, "@@/foo") + .expect("@USERPROFILE@/.dotnet/tools"), + EnvironmentTestSpec.build() + .env(SystemProperty.USER_HOME, "@@/bar") + .expect("@user.home@/.dotnet/tools"), + // "USERPROFILE" environment variable and "user.home" system property set to different values, + // the order should be "USERPROFILE" followed by "user.home". + EnvironmentTestSpec.build() + .env(EnvironmentVariable.USERPROFILE, "@@/foo") + .env(SystemProperty.USER_HOME, "@@/bar") + .expect("@USERPROFILE@/.dotnet/tools") + .expect("@user.home@/.dotnet/tools"), + // "USERPROFILE" environment variable and "user.home" system property set to the same value. + EnvironmentTestSpec.build() + .env(EnvironmentVariable.USERPROFILE, "@@/buz") + .env(SystemProperty.USER_HOME, "@@/buz") + .expect("@USERPROFILE@/.dotnet/tools"), + // WiX3: newer versions first; 32bit after 64bit + EnvironmentTestSpec.build() + .standardEnv(EnvironmentVariable.PROGRAM_FILES_X86) + .standardEnv(EnvironmentVariable.PROGRAM_FILES) + .expect(String.format("@%s@/WiX Toolset v3.11/bin", EnvironmentVariable.PROGRAM_FILES_X86.variableName())) + .expect(String.format("@%s@/WiX Toolset v3.10/bin", EnvironmentVariable.PROGRAM_FILES.variableName())) + .expect(String.format("@%s@/WiX Toolset v3.10/bin", EnvironmentVariable.PROGRAM_FILES_X86.variableName())), + // Malformed installation directory should be accepted + EnvironmentTestSpec.build() + .standardEnv(EnvironmentVariable.PROGRAM_FILES_X86) + .expect(String.format("@%s@/WiX Toolset vb/bin", EnvironmentVariable.PROGRAM_FILES_X86.variableName())) + .expect(String.format("@%s@/WiX Toolset va/bin", EnvironmentVariable.PROGRAM_FILES_X86.variableName())) + .expect(String.format("@%s@/WiX Toolset v/bin", EnvironmentVariable.PROGRAM_FILES_X86.variableName())), + // No directories + EnvironmentTestSpec.build() + ).map(EnvironmentTestSpec.Builder::create).forEach(testCases::add); + + return testCases; + } + + private enum ToolStatus { + GOOD, + MISSING, + UNEXPECTED_STDOUT, + ; + + static boolean isAllGood(ToolStatus... status) { + return Stream.of(status).allMatch(Predicate.isEqual(GOOD)); + } + + Optional map(WixToolMock builder) { + return switch (this) { + case MISSING -> { + yield Optional.empty(); + } + case UNEXPECTED_STDOUT -> { + var mock = builder.create(); + yield Optional.of(new CommandMockSpec( + mock.name(), + mock.mockName(), + CommandActionSpecs.build().stdout("Blah-Blah-Blah").exit().create())); + } + case GOOD -> { + yield Optional.of(builder.create()); + } + }; + } + } + + record TestSpec( + Optional expected, + List lookupDirs, + boolean lookupInPATH, + Collection mocks, + List expectedErrors) { + + TestSpec { + Objects.requireNonNull(expected); + lookupDirs.forEach(Objects::requireNonNull); + mocks.forEach(Objects::requireNonNull); + expectedErrors.forEach(Objects::requireNonNull); + + if (expected.isEmpty() == expectedErrors.isEmpty()) { + // It should be either toolset or errors, not both or non both. + throw new IllegalArgumentException(); + } + + lookupDirs.forEach(WixToolTest::assertIsRelative); + + lookupDirs.forEach(path -> { + assertNotEquals(LOOKUP_IN_PATH, path); + }); + + // Ensure tool paths are unique. + mocks.stream().map(CommandMockSpec::name).collect(toMap(x -> x, x -> x)); + } + + @Override + public String toString() { + var tokens = new ArrayList(); + expected.map(Object::toString).ifPresent(tokens::add); + if (!expectedErrors.isEmpty()) { + tokens.add(String.format("errors=%s", expectedErrors)); + } + + List lookupPaths; + if (lookupInPATH) { + lookupPaths = new ArrayList<>(); + lookupPaths.add(Path.of("${PATH}")); + lookupPaths.addAll(lookupDirs); + } else { + lookupPaths = lookupDirs; + } + + if (!lookupPaths.isEmpty()) { + tokens.add(String.format("lookup-dirs=%s", lookupPaths)); + } + if (!mocks.isEmpty()) { + tokens.add(mocks.toString()); + } + return String.join(", ", tokens); + } + + void run(Path workDir) { + var scriptBuilder = Script.build().commandMockBuilderMutator(CommandMock.Builder::repeatInfinitely); + mocks.stream().map(mockSpec -> { + Path toolPath = mockSpec.name(); + if (toolPath.getNameCount() > 1) { + toolPath = workDir.resolve(toolPath); + } + return new CommandMockSpec(toolPath, mockSpec.mockName(), mockSpec.actions()); + }).forEach(scriptBuilder::map); + + scriptBuilder.map(_ -> true, CommandMock.ioerror("non-existent")); + + var script = scriptBuilder.createLoop(); + + Supplier createToolset = () -> { + return WixTool.createToolset(() -> { + return lookupDirs.stream().map(workDir::resolve).toList(); + }, lookupInPATH()); + }; + + Globals.main(() -> { + JPackageMockUtils.buildJPackage() + .script(script) + .listener(System.out::println) + .applyToGlobals(); + + expected.ifPresentOrElse(expectedToolset -> { + var toolset = createToolset.get(); + assertEquals(resolveAt(expectedToolset, workDir), toolset); + }, () -> { + var ex = assertThrows(RuntimeException.class, createToolset::get); + assertEquals(expectedErrors.getFirst().getValue(), ex.getMessage()); + if (ex instanceof ConfigException cfgEx) { + assertEquals(expectedErrors.getLast().getValue(), cfgEx.getAdvice()); + assertEquals(2, expectedErrors.size()); + } else { + assertEquals(1, expectedErrors.size()); + } + }); + + return 0; + }); + } + + static Builder build() { + return new Builder(); + } + + static final class Builder { + + TestSpec create() { + if (expected == null && expectedErrors.isEmpty()) { + return copy() + .expect("error.no-wix-tools") + .expect("error.no-wix-tools.advice") + .create(); + } else { + var allLookupDirs = Stream.concat( + lookupDirs.stream(), + tools.stream().map(CommandMockSpec::name).map(toolPath -> { + if (toolPath.getNameCount() == 1) { + return LOOKUP_IN_PATH; + } else { + return toolPath.getParent(); + } + }) + ).distinct().collect(Collectors.toCollection(ArrayList::new)); + + var lookupInPATH = allLookupDirs.contains(LOOKUP_IN_PATH); + if (lookupInPATH) { + allLookupDirs.remove(LOOKUP_IN_PATH); + } + + return new TestSpec( + Optional.ofNullable(expected), + Collections.unmodifiableList(allLookupDirs), + lookupInPATH, + List.copyOf(tools), + List.copyOf(expectedErrors)); + } + } + + Builder copy() { + return new Builder(this); + } + + private Builder() { + expectedErrors = new ArrayList<>(); + lookupDirs = new ArrayList<>(); + tools = new ArrayList<>(); + } + + private Builder(Builder other) { + expected = other.expected; + expectedErrors = new ArrayList<>(other.expectedErrors); + lookupDirs = new ArrayList<>(other.lookupDirs); + tools = new ArrayList<>(other.tools); + } + + Builder expect(WixToolset v) { + expected = v; + return this; + } + + Builder expect(String formatKey, Object ... args) { + expectedErrors.add(JPackageStringBundle.MAIN.cannedFormattedString(formatKey, args)); + return this; + } + + Builder expect(WixToolsetBuilder builder) { + return expect(builder.create()); + } + + Builder lookupDir(String v) { + return lookupDir(Path.of(v)); + } + + Builder lookupDir(Path v) { + lookupDirs.add(Objects.requireNonNull(v)); + return this; + } + + Builder tool(CommandMockSpec v) { + tools.add(Objects.requireNonNull(v)); + return this; + } + + Builder tool(WixToolMock v) { + return tool(v.create()); + } + + private WixToolset expected; + private final List expectedErrors; + private final List lookupDirs; + private final List tools; + } + } + + private static final class WixToolsetBuilder { + + WixToolset create() { + return new WixToolset(tools.entrySet().stream().collect(toMap(Map.Entry::getKey, e -> { + ToolInfo toolInfo = new WixTool.DefaultToolInfo(e.getValue(), version); + if (e.getKey() == WixTool.Candle3) { + toolInfo = new WixTool.DefaultCandleInfo(toolInfo, fips); + } + return toolInfo; + }))); + } + + WixToolsetBuilder version(String v) { + version = v; + return this; + } + + WixToolsetBuilder put(WixTool tool, String path) { + return put(tool, Path.of(path)); + } + + WixToolsetBuilder put(WixTool tool, Path path) { + tools.put(Objects.requireNonNull(tool), path.resolve(tool.fileName())); + return this; + } + + WixToolsetBuilder put(WixTool tool) { + return put(tool, LOOKUP_IN_PATH); + } + + WixToolsetBuilder put(WixToolsetType type, Path path) { + type.getTools().forEach(tool -> { + put(tool, path); + }); + return this; + } + + WixToolsetBuilder put(WixToolsetType type, String path) { + return put(type, Path.of(path)); + } + + WixToolsetBuilder put(WixToolsetType type) { + return put(type, LOOKUP_IN_PATH); + } + + WixToolsetBuilder fips(boolean v) { + fips = true; + return this; + } + + WixToolsetBuilder fips() { + return fips(true); + } + + private Map tools = new HashMap<>(); + private boolean fips; + private String version; + } + + enum EnvironmentVariable { + USERPROFILE("USERPROFILE"), + PROGRAM_FILES("ProgramFiles"), + PROGRAM_FILES_X86("ProgramFiles(x86)"), + SYSTEM_DRIVE("SystemDrive"), + ; + + EnvironmentVariable(String variableName) { + this.variableName = Objects.requireNonNull(variableName); + } + + String variableName() { + return variableName; + } + + private final String variableName; + } + + enum SystemProperty { + USER_HOME("user.home"), + ; + + SystemProperty(String propertyName) { + this.propertyName = Objects.requireNonNull(propertyName); + } + + String propertyName() { + return propertyName; + } + + private final String propertyName; + } + + record EnvironmentTestSpec(EnvironmentProviderMock env, List expectedDirs) { + + EnvironmentTestSpec { + Objects.requireNonNull(env); + expectedDirs.forEach(dir -> { + if (dir.isAbsolute()) { + throw new IllegalArgumentException(); + } + }); + } + + @Override + public String toString() { + var tokens = new ArrayList(); + tokens.add(String.format("expect=%s", expectedDirs)); + tokens.add(env.toString()); + return String.join(", ", tokens); + } + + void run(Path workDir) throws IOException { + var allResolved = resolve(workDir, Stream.of( + env.envVariables().entrySet().stream(), + env.systemProperties().entrySet().stream(), + expectedDirs.stream().map(Path::toString).map(dir -> { + return Map.entry(dir, dir); + }) + ).flatMap(x -> x).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))); + + Function>, Map> filterAllResolved = filterSupplier -> { + var filter = filterSupplier.get(); + return allResolved.entrySet().stream().filter(e -> { + return filter.containsKey(e.getKey()); + }).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + }; + + var resolvedEnv = new EnvironmentProviderMock( + filterAllResolved.apply(env::envVariables), + filterAllResolved.apply(env::systemProperties)); + + var resolvedDirs = expectedDirs.stream().map(Path::toString).map(allResolved::get).map(Path::of).toList(); + + for (var dir : resolvedDirs) { + Files.createDirectories(dir); + } + + Globals.main(() -> { + Globals.instance().system(resolvedEnv); + assertEquals(resolvedDirs, WixTool.findWixInstallDirs()); + return 0; + }); + } + + static Builder build() { + return new Builder(); + } + + static final class Builder { + + EnvironmentTestSpec create() { + var env = envVariables.entrySet().stream().collect(Collectors.toMap(e -> { + return e.getKey().variableName(); + }, Map.Entry::getValue)); + + var props = systemProperties.entrySet().stream().collect(Collectors.toMap(e -> { + return e.getKey().propertyName(); + }, Map.Entry::getValue)); + + return new EnvironmentTestSpec(new EnvironmentProviderMock(env, props), List.copyOf(expectedDirs)); + } + + Builder expect(List dirs) { + expectedDirs.addAll(dirs); + return this; + } + + Builder expect(Path... dirs) { + return expect(List.of(dirs)); + } + + Builder expect(String... dirs) { + return expect(List.of(dirs).stream().map(Path::of).toList()); + } + + Builder env(SystemProperty k, String v) { + systemProperties.put(Objects.requireNonNull(k), Objects.requireNonNull(v)); + return this; + } + + Builder env(EnvironmentVariable k, String v) { + envVariables.put(Objects.requireNonNull(k), Objects.requireNonNull(v)); + return this; + } + + Builder standardEnv(EnvironmentVariable k) { + var value = switch (k) { + case PROGRAM_FILES -> "Program Files"; + case PROGRAM_FILES_X86 -> "Program Files(x86)"; + default -> { + throw new IllegalArgumentException(); + } + }; + return env(k, "@@/" + value); + } + + private final Map envVariables = new HashMap<>(); + private final Map systemProperties = new HashMap<>(); + private final List expectedDirs = new ArrayList<>(); + } + + private static Map resolve(Path workDir, Map props) { + + var tokens = new ArrayList(); + + Stream.of( + Stream.of(EnvironmentVariable.values()).map(EnvironmentVariable::variableName), + Stream.of(SystemProperty.values()).map(SystemProperty::propertyName) + ).flatMap(x -> x).map(str -> { + return String.format("@%s@", str); + }).forEach(tokens::add); + + tokens.add(TOKEN_WORKDIR); + + var tokenReplace = new TokenReplace(tokens.toArray(String[]::new)); + + return props.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> { + return tokenReplace.recursiveApplyTo(e.getValue(), token -> { + if (token.equals(TOKEN_WORKDIR)) { + return workDir; + } else { + return Objects.requireNonNull(props.get(token.substring(1, token.length() - 1)), () -> { + return String.format("Unrecognized token: [%s]", token); + }); + } + }); + })); + } + + static final String TOKEN_WORKDIR = "@@"; + } + + private static WixToolsetBuilder toolset() { + return new WixToolsetBuilder(); + } + + private static WixToolMock tool() { + return new WixToolMock(); + } + + private static WixToolMock tool(Path dir) { + return tool().dir(dir); + } + + private static WixToolMock tool(String dir) { + return tool(Path.of(dir)); + } + + private static WixToolset resolveAt(WixToolset toolset, Path root) { + return new WixToolset(toolset.tools().entrySet().stream().collect(toMap(Map.Entry::getKey, e -> { + var toolInfo = e.getValue(); + + assertIsRelative(toolInfo.path()); + + if (toolInfo.path().getNameCount() == 1) { + // The tool is picked from the PATH. + return toolInfo; + } + + ToolInfo newToolInfo = new WixTool.DefaultToolInfo(root.resolve(toolInfo.path()), toolInfo.version()); + if (toolInfo instanceof WixTool.CandleInfo candleInfo) { + newToolInfo = new WixTool.DefaultCandleInfo(newToolInfo, candleInfo.fips()); + } + return newToolInfo; + }))); + } + + private static void assertIsRelative(Path path) { + if (path.isAbsolute()) { + throw new IllegalArgumentException(); + } + } + + static final Path LOOKUP_IN_PATH = Path.of(""); +} + diff --git a/test/jdk/tools/jpackage/junit/windows/junit.java b/test/jdk/tools/jpackage/junit/windows/junit.java index 1a1d0d58f7e..8c290c2c87f 100644 --- a/test/jdk/tools/jpackage/junit/windows/junit.java +++ b/test/jdk/tools/jpackage/junit/windows/junit.java @@ -45,3 +45,15 @@ * jdk/jpackage/internal/wixui/UISpecTest.java * @run junit jdk.jpackage/jdk.jpackage.internal.wixui.UISpecTest */ + +/* @test + * @summary Test WiX Toolset lookup algorithm + * @requires (os.family == "windows") + * @library /test/jdk/tools/jpackage/helpers + * @build jdk.jpackage.test.* + * @build jdk.jpackage.test.mock.* + * @build jdk.jpackage.test.stdmock.* + * @compile/module=jdk.jpackage -Xlint:all -Werror + * jdk/jpackage/internal/WixToolTest.java + * @run junit jdk.jpackage/jdk.jpackage.internal.WixToolTest + */ From 52fd46d3a614106df6ee4ca35b322dcec37329f2 Mon Sep 17 00:00:00 2001 From: Dhamoder Nalla Date: Wed, 1 Apr 2026 01:42:33 +0000 Subject: [PATCH 092/116] 8371651: [AArch64] Populate CPU _features flag on Windows Reviewed-by: dholmes, bstafford, aph --- .../windows_aarch64/sve_windows_aarch64.S | 42 +++++++++++++++++++ .../vm_version_windows_aarch64.cpp | 35 ++++++++++++---- 2 files changed, 70 insertions(+), 7 deletions(-) create mode 100644 src/hotspot/os_cpu/windows_aarch64/sve_windows_aarch64.S diff --git a/src/hotspot/os_cpu/windows_aarch64/sve_windows_aarch64.S b/src/hotspot/os_cpu/windows_aarch64/sve_windows_aarch64.S new file mode 100644 index 00000000000..e0c85830bd4 --- /dev/null +++ b/src/hotspot/os_cpu/windows_aarch64/sve_windows_aarch64.S @@ -0,0 +1,42 @@ +; +; Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +; DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +; +; This code is free software; you can redistribute it and/or modify it +; 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. +; + + ; Support for int get_sve_vector_length(); + ; + ; Returns the current SVE vector length in bytes. + ; This function uses the INCB instruction which increments a register + ; by the number of bytes in an SVE vector register. + ; + ; Note: This function will fault if SVE is not available or enabled. + ; The caller must ensure SVE support is detected before calling. + + ALIGN 4 + EXPORT get_sve_vector_length + AREA sve_text, CODE + +get_sve_vector_length + mov x0, #0 + incb x0 + ret + + END diff --git a/src/hotspot/os_cpu/windows_aarch64/vm_version_windows_aarch64.cpp b/src/hotspot/os_cpu/windows_aarch64/vm_version_windows_aarch64.cpp index 93beb549366..e78a37b4178 100644 --- a/src/hotspot/os_cpu/windows_aarch64/vm_version_windows_aarch64.cpp +++ b/src/hotspot/os_cpu/windows_aarch64/vm_version_windows_aarch64.cpp @@ -26,16 +26,19 @@ #include "runtime/os.hpp" #include "runtime/vm_version.hpp" +// Assembly function to get SVE vector length using INCB instruction +extern "C" int get_sve_vector_length(); + int VM_Version::get_current_sve_vector_length() { assert(VM_Version::supports_sve(), "should not call this"); - ShouldNotReachHere(); - return 0; + // Use assembly instruction to get the actual SVE vector length + return VM_Version::supports_sve() ? get_sve_vector_length() : 0; // This value is in bytes } int VM_Version::set_and_get_current_sve_vector_length(int length) { assert(VM_Version::supports_sve(), "should not call this"); - ShouldNotReachHere(); - return 0; + // Use assembly instruction to get the SVE vector length + return VM_Version::supports_sve() ? get_sve_vector_length() : 0; // This value is in bytes } void VM_Version::get_os_cpu_info() { @@ -47,11 +50,29 @@ void VM_Version::get_os_cpu_info() { set_feature(CPU_AES); set_feature(CPU_SHA1); set_feature(CPU_SHA2); + set_feature(CPU_PMULL); } if (IsProcessorFeaturePresent(PF_ARM_VFP_32_REGISTERS_AVAILABLE)) { set_feature(CPU_ASIMD); } - // No check for CPU_PMULL, CPU_SVE, CPU_SVE2 + if (IsProcessorFeaturePresent(PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE)) { + set_feature(CPU_LSE); + } + if (IsProcessorFeaturePresent(PF_ARM_SVE_INSTRUCTIONS_AVAILABLE)) { + set_feature(CPU_SVE); + } + if (IsProcessorFeaturePresent(PF_ARM_SVE2_INSTRUCTIONS_AVAILABLE)) { + set_feature(CPU_SVE2); + } + if (IsProcessorFeaturePresent(PF_ARM_SVE_BITPERM_INSTRUCTIONS_AVAILABLE)) { + set_feature(CPU_SVEBITPERM); + } + if (IsProcessorFeaturePresent(PF_ARM_SHA3_INSTRUCTIONS_AVAILABLE)) { + set_feature(CPU_SHA3); + } + if (IsProcessorFeaturePresent(PF_ARM_SHA512_INSTRUCTIONS_AVAILABLE)) { + set_feature(CPU_SHA512); + } __int64 dczid_el0 = _ReadStatusReg(0x5807 /* ARM64_DCZID_EL0 */); @@ -102,8 +123,8 @@ void VM_Version::get_os_cpu_info() { SYSTEM_INFO si; GetSystemInfo(&si); _model = si.wProcessorLevel; - _variant = si.wProcessorRevision / 0xFF; - _revision = si.wProcessorRevision & 0xFF; + _variant = (si.wProcessorRevision >> 8) & 0xFF; // Variant is the upper byte of wProcessorRevision + _revision = si.wProcessorRevision & 0xFF; // Revision is the lower byte of wProcessorRevision } } } From 2e0ce34d3cbb2abca4efbf8d5598cdc679b72e90 Mon Sep 17 00:00:00 2001 From: Guanqiang Han Date: Wed, 1 Apr 2026 06:20:26 +0000 Subject: [PATCH 093/116] 8380579: C2: Intermittent fastdebug assert in Parse::sharpen_type_after_if: missing type check info Reviewed-by: rcastanedalo, vlivanov --- src/hotspot/share/opto/parse2.cpp | 6 ++ ...harpenTypeAfterIfMissingTypeCheckInfo.java | 57 +++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 test/hotspot/jtreg/compiler/reflection/TestSharpenTypeAfterIfMissingTypeCheckInfo.java diff --git a/src/hotspot/share/opto/parse2.cpp b/src/hotspot/share/opto/parse2.cpp index 7f41870ccea..a7c5398171b 100644 --- a/src/hotspot/share/opto/parse2.cpp +++ b/src/hotspot/share/opto/parse2.cpp @@ -1757,6 +1757,12 @@ static bool match_type_check(PhaseGVN& gvn, // Bool(CmpP(LoadKlass(obj._klass), ConP(Foo.klass)), [eq]) // or the narrowOop equivalent. (*obj) = extract_obj_from_klass_load(&gvn, val); + // Some klass comparisons are not directly in the form + // Bool(CmpP(LoadKlass(obj._klass), ConP(Foo.klass)), [eq]), + // e.g. Bool(CmpP(CastPP(LoadKlass(...)), ConP(klass)), [eq]). + // These patterns with nullable klasses arise from example from + // load_array_klass_from_mirror. + if (*obj == nullptr) { return false; } (*cast_type) = tcon->isa_klassptr()->as_instance_type(); return true; // found } diff --git a/test/hotspot/jtreg/compiler/reflection/TestSharpenTypeAfterIfMissingTypeCheckInfo.java b/test/hotspot/jtreg/compiler/reflection/TestSharpenTypeAfterIfMissingTypeCheckInfo.java new file mode 100644 index 00000000000..7199ad74717 --- /dev/null +++ b/test/hotspot/jtreg/compiler/reflection/TestSharpenTypeAfterIfMissingTypeCheckInfo.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 8380579 + * @summary Test that C2 match_type_check handles Bool(CmpP(CastPP(LoadKlass(...)), ConP(klass)), eq) + * @run main/othervm + * -XX:-TieredCompilation + * -Xcomp + * -XX:CompileCommand=compileonly,${test.main.class}::test + * ${test.main.class} + */ + +package compiler.reflection; + +import java.lang.reflect.Array; + +public class TestSharpenTypeAfterIfMissingTypeCheckInfo { + + public static void main(String[] args) { + for (int i = 0; i < 20_000; i++) { + test(i); + } + } + + static boolean test(int i) { + Class componentType; + if (i % 2 == 0) { + componentType = Object.class; + } else { + componentType = Integer.class; + } + Object array = Array.newInstance(componentType, 1); + return array.getClass() == Object[].class; + } +} \ No newline at end of file From 3dcf2a3bac491ba4344bde9701628c41b8b46749 Mon Sep 17 00:00:00 2001 From: Quan Anh Mai Date: Wed, 1 Apr 2026 06:59:27 +0000 Subject: [PATCH 094/116] 8379790: MemNode::can_see_stored_value incorrectly walks past barriers Reviewed-by: chagedorn, dfenacci --- src/hotspot/share/opto/memnode.cpp | 67 +++++++++++++++++------------- src/hotspot/share/opto/memnode.hpp | 1 + 2 files changed, 39 insertions(+), 29 deletions(-) diff --git a/src/hotspot/share/opto/memnode.cpp b/src/hotspot/share/opto/memnode.cpp index c8723d6ec0f..9ec3402c701 100644 --- a/src/hotspot/share/opto/memnode.cpp +++ b/src/hotspot/share/opto/memnode.cpp @@ -1156,40 +1156,38 @@ Node* LoadNode::can_see_arraycopy_value(Node* st, PhaseGVN* phase) const { return nullptr; } - -//---------------------------can_see_stored_value------------------------------ // This routine exists to make sure this set of tests is done the same // everywhere. We need to make a coordinated change: first LoadNode::Ideal // will change the graph shape in a way which makes memory alive twice at the // same time (uses the Oracle model of aliasing), then some // LoadXNode::Identity will fold things back to the equivalence-class model // of aliasing. -Node* MemNode::can_see_stored_value(Node* st, PhaseValues* phase) const { +Node* LoadNode::can_see_stored_value_through_membars(Node* st, PhaseValues* phase) const { Node* ld_adr = in(MemNode::Address); - intptr_t ld_off = 0; - Node* ld_base = AddPNode::Ideal_base_and_offset(ld_adr, phase, ld_off); - Node* ld_alloc = AllocateNode::Ideal_allocation(ld_base); const TypeInstPtr* tp = phase->type(ld_adr)->isa_instptr(); Compile::AliasType* atp = (tp != nullptr) ? phase->C->alias_type(tp) : nullptr; - // This is more general than load from boxing objects. + if (skip_through_membars(atp, tp, phase->C->eliminate_boxing())) { uint alias_idx = atp->index(); Node* result = nullptr; Node* current = st; - // Skip through chains of MemBarNodes checking the MergeMems for - // new states for the slice of this load. Stop once any other - // kind of node is encountered. Loads from final memory can skip - // through any kind of MemBar but normal loads shouldn't skip - // through MemBarAcquire since the could allow them to move out of - // a synchronized region. It is not safe to step over MemBarCPUOrder, - // because alias info above them may be inaccurate (e.g., due to - // mixed/mismatched unsafe accesses). + // Skip through chains of MemBarNodes checking the MergeMems for new states for the slice of + // this load. Stop once any other kind of node is encountered. + // + // In principle, folding a load is moving it up until it meets a matching store. + // + // store(ptr, v); store(ptr, v); store(ptr, v); + // membar1; -> membar1; -> load(ptr); + // membar2; load(ptr); membar1; + // load(ptr); membar2; membar2; + // + // So, we can decide which kinds of barriers we can walk past. It is not safe to step over + // MemBarCPUOrder, even if the memory is not rewritable, because alias info above them may be + // inaccurate (e.g., due to mixed/mismatched unsafe accesses). bool is_final_mem = !atp->is_rewritable(); while (current->is_Proj()) { int opc = current->in(0)->Opcode(); - if ((is_final_mem && (opc == Op_MemBarAcquire || - opc == Op_MemBarAcquireLock || - opc == Op_LoadFence)) || + if ((is_final_mem && (opc == Op_MemBarAcquire || opc == Op_MemBarAcquireLock || opc == Op_LoadFence)) || opc == Op_MemBarRelease || opc == Op_StoreFence || opc == Op_MemBarReleaseLock || @@ -1216,6 +1214,17 @@ Node* MemNode::can_see_stored_value(Node* st, PhaseValues* phase) const { } } + return can_see_stored_value(st, phase); +} + +// If st is a store to the same location as this, return the stored value +Node* MemNode::can_see_stored_value(Node* st, PhaseValues* phase) const { + Node* ld_adr = in(MemNode::Address); + intptr_t ld_off = 0; + Node* ld_base = AddPNode::Ideal_base_and_offset(ld_adr, phase, ld_off); + Node* ld_alloc = AllocateNode::Ideal_allocation(ld_base); + const TypeInstPtr* tp = phase->type(ld_adr)->isa_instptr(); + // Loop around twice in the case Load -> Initialize -> Store. // (See PhaseIterGVN::add_users_to_worklist, which knows about this case.) for (int trip = 0; trip <= 1; trip++) { @@ -1344,7 +1353,7 @@ Node* LoadNode::Identity(PhaseGVN* phase) { // If the previous store-maker is the right kind of Store, and the store is // to the same address, then we are equal to the value stored. Node* mem = in(Memory); - Node* value = can_see_stored_value(mem, phase); + Node* value = can_see_stored_value_through_membars(mem, phase); if( value ) { // byte, short & char stores truncate naturally. // A load has to load the truncated value which requires @@ -2042,7 +2051,7 @@ Node *LoadNode::Ideal(PhaseGVN *phase, bool can_reshape) { // (c) See if we can fold up on the spot, but don't fold up here. // Fold-up might require truncation (for LoadB/LoadS/LoadUS) or // just return a prior value, which is done by Identity calls. - if (can_see_stored_value(prev_mem, phase)) { + if (can_see_stored_value_through_membars(prev_mem, phase)) { // Make ready for step (d): set_req_X(MemNode::Memory, prev_mem, phase); return this; @@ -2099,7 +2108,7 @@ const Type* LoadNode::Value(PhaseGVN* phase) const { Compile* C = phase->C; // If load can see a previous constant store, use that. - Node* value = can_see_stored_value(mem, phase); + Node* value = can_see_stored_value_through_membars(mem, phase); if (value != nullptr && value->is_Con()) { assert(value->bottom_type()->higher_equal(_type), "sanity"); return value->bottom_type(); @@ -2350,7 +2359,7 @@ uint LoadNode::match_edge(uint idx) const { // Node* LoadBNode::Ideal(PhaseGVN* phase, bool can_reshape) { Node* mem = in(MemNode::Memory); - Node* value = can_see_stored_value(mem,phase); + Node* value = can_see_stored_value_through_membars(mem, phase); if (value != nullptr) { Node* narrow = Compile::narrow_value(T_BYTE, value, _type, phase, false); if (narrow != value) { @@ -2363,7 +2372,7 @@ Node* LoadBNode::Ideal(PhaseGVN* phase, bool can_reshape) { const Type* LoadBNode::Value(PhaseGVN* phase) const { Node* mem = in(MemNode::Memory); - Node* value = can_see_stored_value(mem,phase); + Node* value = can_see_stored_value_through_membars(mem, phase); if (value != nullptr && value->is_Con() && !value->bottom_type()->higher_equal(_type)) { // If the input to the store does not fit with the load's result type, @@ -2384,7 +2393,7 @@ const Type* LoadBNode::Value(PhaseGVN* phase) const { // Node* LoadUBNode::Ideal(PhaseGVN* phase, bool can_reshape) { Node* mem = in(MemNode::Memory); - Node* value = can_see_stored_value(mem, phase); + Node* value = can_see_stored_value_through_membars(mem, phase); if (value != nullptr) { Node* narrow = Compile::narrow_value(T_BOOLEAN, value, _type, phase, false); if (narrow != value) { @@ -2397,7 +2406,7 @@ Node* LoadUBNode::Ideal(PhaseGVN* phase, bool can_reshape) { const Type* LoadUBNode::Value(PhaseGVN* phase) const { Node* mem = in(MemNode::Memory); - Node* value = can_see_stored_value(mem,phase); + Node* value = can_see_stored_value_through_membars(mem, phase); if (value != nullptr && value->is_Con() && !value->bottom_type()->higher_equal(_type)) { // If the input to the store does not fit with the load's result type, @@ -2418,7 +2427,7 @@ const Type* LoadUBNode::Value(PhaseGVN* phase) const { // Node* LoadUSNode::Ideal(PhaseGVN* phase, bool can_reshape) { Node* mem = in(MemNode::Memory); - Node* value = can_see_stored_value(mem,phase); + Node* value = can_see_stored_value_through_membars(mem, phase); if (value != nullptr) { Node* narrow = Compile::narrow_value(T_CHAR, value, _type, phase, false); if (narrow != value) { @@ -2431,7 +2440,7 @@ Node* LoadUSNode::Ideal(PhaseGVN* phase, bool can_reshape) { const Type* LoadUSNode::Value(PhaseGVN* phase) const { Node* mem = in(MemNode::Memory); - Node* value = can_see_stored_value(mem,phase); + Node* value = can_see_stored_value_through_membars(mem, phase); if (value != nullptr && value->is_Con() && !value->bottom_type()->higher_equal(_type)) { // If the input to the store does not fit with the load's result type, @@ -2452,7 +2461,7 @@ const Type* LoadUSNode::Value(PhaseGVN* phase) const { // Node* LoadSNode::Ideal(PhaseGVN* phase, bool can_reshape) { Node* mem = in(MemNode::Memory); - Node* value = can_see_stored_value(mem,phase); + Node* value = can_see_stored_value_through_membars(mem, phase); if (value != nullptr) { Node* narrow = Compile::narrow_value(T_SHORT, value, _type, phase, false); if (narrow != value) { @@ -2465,7 +2474,7 @@ Node* LoadSNode::Ideal(PhaseGVN* phase, bool can_reshape) { const Type* LoadSNode::Value(PhaseGVN* phase) const { Node* mem = in(MemNode::Memory); - Node* value = can_see_stored_value(mem,phase); + Node* value = can_see_stored_value_through_membars(mem, phase); if (value != nullptr && value->is_Con() && !value->bottom_type()->higher_equal(_type)) { // If the input to the store does not fit with the load's result type, diff --git a/src/hotspot/share/opto/memnode.hpp b/src/hotspot/share/opto/memnode.hpp index 7fa238f574d..8efb5521e7c 100644 --- a/src/hotspot/share/opto/memnode.hpp +++ b/src/hotspot/share/opto/memnode.hpp @@ -266,6 +266,7 @@ class LoadNode : public MemNode { const Type* const _type; // What kind of value is loaded? virtual Node* find_previous_arraycopy(PhaseValues* phase, Node* ld_alloc, Node*& mem, bool can_see_stored_value) const; + Node* can_see_stored_value_through_membars(Node* st, PhaseValues* phase) const; public: LoadNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const Type *rt, MemOrd mo, ControlDependency control_dependency) From 32e8aa45828a7dbaf5ed558efd5870c9c5a149de Mon Sep 17 00:00:00 2001 From: Andrew Dinn Date: Wed, 1 Apr 2026 07:47:17 +0000 Subject: [PATCH 095/116] 8379811: Disable AOTCodeCache if Assembly intrinsics use differs from Production use Reviewed-by: kvn, asmehra --- src/hotspot/share/code/aotCodeCache.cpp | 312 ++++++++++++++++++++++-- src/hotspot/share/code/aotCodeCache.hpp | 94 ++++++- 2 files changed, 384 insertions(+), 22 deletions(-) diff --git a/src/hotspot/share/code/aotCodeCache.cpp b/src/hotspot/share/code/aotCodeCache.cpp index 030e2684bfc..938cf4eaa41 100644 --- a/src/hotspot/share/code/aotCodeCache.cpp +++ b/src/hotspot/share/code/aotCodeCache.cpp @@ -380,37 +380,110 @@ void AOTCodeCache::init_early_c1_table() { } } +// macro to record which flags are set -- flag_type selects the +// relevant accessor e.g. set_flag, set_x86_flag, set_x86_use_flag. +// n.b. flag_enum_name and global_flag_name are both needed because we +// don't have consistent conventions for naming global flags e.g. +// EnableContended vs UseMulAddIntrinsic vs UseCRC32Intrinsics + +#define RECORD_FLAG(flag_type, flag_enum_name, global_flag_name) \ + if (global_flag_name) { \ + set_ ## flag_type ## flag(flag_enum_name); \ + } + void AOTCodeCache::Config::record(uint cpu_features_offset) { _flags = 0; #ifdef ASSERT - _flags |= debugVM; + set_flag(debugVM); #endif - if (UseCompressedOops) { - _flags |= compressedOops; - } - if (UseTLAB) { - _flags |= useTLAB; - } + RECORD_FLAG(, compressedOops, UseCompressedOops); + RECORD_FLAG(, useTLAB, UseTLAB); if (JavaAssertions::systemClassDefault()) { - _flags |= systemClassAssertions; + set_flag(systemClassAssertions); } if (JavaAssertions::userClassDefault()) { - _flags |= userClassAssertions; - } - if (EnableContended) { - _flags |= enableContendedPadding; - } - if (RestrictContended) { - _flags |= restrictContendedPadding; + set_flag(userClassAssertions); } + RECORD_FLAG(, enableContendedPadding, EnableContended); + RECORD_FLAG(, restrictContendedPadding, RestrictContended); + _compressedOopShift = CompressedOops::shift(); _compressedOopBase = CompressedOops::base(); _compressedKlassShift = CompressedKlassPointers::shift(); _contendedPaddingWidth = ContendedPaddingWidth; _gc = (uint)Universe::heap()->kind(); + _optoLoopAlignment = (uint)OptoLoopAlignment; + _codeEntryAlignment = (uint)CodeEntryAlignment; + _allocatePrefetchLines = (uint)AllocatePrefetchLines; + _allocateInstancePrefetchLines = (uint)AllocateInstancePrefetchLines; + _allocatePrefetchDistance = (uint)AllocatePrefetchDistance; + _allocatePrefetchStepSize = (uint)AllocatePrefetchStepSize; + _use_intrinsics_flags = 0; + RECORD_FLAG(use_, useCRC32, UseCRC32Intrinsics); + RECORD_FLAG(use_, useCRC32C, UseCRC32CIntrinsics); +#ifdef COMPILER2 + _maxVectorSize = (uint)MaxVectorSize; + _arrayOperationPartialInlineSize = (uint)ArrayOperationPartialInlineSize; + RECORD_FLAG(use_, useMultiplyToLen, UseMultiplyToLenIntrinsic); + RECORD_FLAG(use_, useSquareToLen, UseSquareToLenIntrinsic); + RECORD_FLAG(use_, useMulAdd, UseMulAddIntrinsic); + RECORD_FLAG(use_, useMontgomeryMultiply, UseMontgomeryMultiplyIntrinsic); + RECORD_FLAG(use_, useMontgomerySquare, UseMontgomerySquareIntrinsic); +#endif // COMPILER2 + RECORD_FLAG(use_, useChaCha20, UseChaCha20Intrinsics); + RECORD_FLAG(use_, useDilithium, UseDilithiumIntrinsics); + RECORD_FLAG(use_, useKyber, UseKyberIntrinsics); + RECORD_FLAG(use_, useBASE64, UseBASE64Intrinsics); + RECORD_FLAG(use_, useAdler32, UseAdler32Intrinsics); + RECORD_FLAG(use_, useAES, UseAESIntrinsics); + RECORD_FLAG(use_, useAESCTR, UseAESCTRIntrinsics); + RECORD_FLAG(use_, useGHASH, UseGHASHIntrinsics); + RECORD_FLAG(use_, useMD5, UseMD5Intrinsics); + RECORD_FLAG(use_, useSHA1, UseSHA1Intrinsics); + RECORD_FLAG(use_, useSHA256, UseSHA256Intrinsics); + RECORD_FLAG(use_, useSHA512, UseSHA512Intrinsics); + RECORD_FLAG(use_, useSHA3, UseSHA3Intrinsics); + RECORD_FLAG(use_, usePoly1305, UsePoly1305Intrinsics); + RECORD_FLAG(use_, useVectorizedMismatch,UseVectorizedMismatchIntrinsic ); + RECORD_FLAG(use_, useSecondarySupersTable, UseSecondarySupersTable); +#if defined(X86) && !defined(ZERO) + _avx3threshold = (uint)AVX3Threshold; + _useAVX = (uint)UseAVX; + _x86_flags = 0; + RECORD_FLAG(x86_, x86_enableX86ECoreOpts, EnableX86ECoreOpts); + RECORD_FLAG(x86_, x86_useUnalignedLoadStores, UseUnalignedLoadStores); + RECORD_FLAG(x86_, x86_useAPX, UseAPX); + + _x86_use_intrinsics_flags = 0; + RECORD_FLAG(x86_use_, x86_useLibm, UseLibmIntrinsic); + RECORD_FLAG(x86_use_, x86_useIntPoly, UseIntPolyIntrinsics); +#endif // defined(X86) && !defined(ZERO) +#if defined(AARCH64) && !defined(ZERO) + _prefetchCopyIntervalInBytes = (uint)PrefetchCopyIntervalInBytes; + _blockZeroingLowLimit = (uint)BlockZeroingLowLimit; + _softwarePrefetchHintDistance = (uint)SoftwarePrefetchHintDistance; + _useSVE = (uint)UseSVE; + _aarch64_flags = 0; + RECORD_FLAG(aarch64_, aarch64_avoidUnalignedAccesses, AvoidUnalignedAccesses); + RECORD_FLAG(aarch64_, aarch64_useSIMDForMemoryOps, UseSIMDForMemoryOps); + RECORD_FLAG(aarch64_, aarch64_useSIMDForArrayEquals, UseSIMDForArrayEquals); + RECORD_FLAG(aarch64_, aarch64_useSIMDForSHA3, UseSIMDForSHA3Intrinsic); + RECORD_FLAG(aarch64_, aarch64_useLSE, UseLSE); + + _aarch64_use_intrinsics_flags = 0; + RECORD_FLAG(aarch64_use_, aarch64_useBlockZeroing, UseBlockZeroing); + RECORD_FLAG(aarch64_use_, aarch64_useSIMDForBigIntegerShift, UseSIMDForBigIntegerShiftIntrinsics); + RECORD_FLAG(aarch64_use_, aarch64_useSimpleArrayEquals, UseSimpleArrayEquals); + RECORD_FLAG(aarch64_use_, aarch64_useSecondarySupersCache, UseSecondarySupersCache); +#endif // defined(AARCH64) && !defined(ZERO) +#if INCLUDE_JVMCI + _enableJVMCI = (uint)EnableJVMCI; +#endif _cpu_features_offset = cpu_features_offset; } +#undef RECORD_FLAG + bool AOTCodeCache::Config::verify_cpu_features(AOTCodeCache* cache) const { LogStreamHandle(Debug, aot, codecache, init) log; uint offset = _cpu_features_offset; @@ -451,15 +524,27 @@ bool AOTCodeCache::Config::verify_cpu_features(AOTCodeCache* cache) const { return true; } +// macro to do *standard* flag eq checks -- flag_type selects the +// relevant accessor e.g. test_flag, test_x86_flag, test_x86_use_flag. +// n.b. flag_enum_name and global_flag_name are both needed because we +// don't have consistent conventions for naming global flags e.g. +// EnableContended vs UseMulAddIntrinsic vs UseCRC32Intrinsics + +#define CHECK_FLAG(flag_type, flag_enum_name, global_flag_name) \ + if (test_ ## flag_type ## flag(flag_enum_name) != global_flag_name) { \ + log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with " # global_flag_name " = %s vs current %s" , (global_flag_name ? "false" : "true"), (global_flag_name ? "true" : "false")); \ + return false; \ + } + bool AOTCodeCache::Config::verify(AOTCodeCache* cache) const { // First checks affect all cached AOT code #ifdef ASSERT - if ((_flags & debugVM) == 0) { + if (!test_flag(debugVM)) { log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created by product VM, it can't be used by debug VM"); return false; } #else - if ((_flags & debugVM) != 0) { + if (test_flag(debugVM)) { log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created by debug VM, it can't be used by product VM"); return false; } @@ -476,9 +561,195 @@ bool AOTCodeCache::Config::verify(AOTCodeCache* cache) const { return false; } + // check CPU features before checking flags that may be + // auto-configured in response to them + if (!verify_cpu_features(cache)) { + return false; + } + + // change to EnableContended can affect validity of nmethods + CHECK_FLAG(, enableContendedPadding, EnableContended); + // change to RestrictContended can affect validity of nmethods + CHECK_FLAG(, restrictContendedPadding, RestrictContended); + + // Tests for config options which might affect validity of adapters, + // stubs or nmethods. Currently we take a pessemistic stand and + // drop the whole cache if any of these are changed. + + // change to opto alignment can affect performance of array copy + // stubs and nmethods + if (_optoLoopAlignment != (uint)OptoLoopAlignment) { + log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with OptoLoopAlignment = %d vs current %d", (int)_optoLoopAlignment, (int)OptoLoopAlignment); + return false; + } + + // change to CodeEntryAlignment can affect performance of array + // copy stubs and nmethods + if (_codeEntryAlignment != CodeEntryAlignment) { + log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with CodeEntryAlignment = %d vs current %d", _codeEntryAlignment, CodeEntryAlignment); + return false; + } + + // changing Prefetch configuration can affect validity of nmethods + // and stubs + if (_allocatePrefetchLines != (uint)AllocatePrefetchLines) { + log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with = %d vs current %d", (int)_allocatePrefetchLines, (int)AllocatePrefetchLines); + return false; + } + if (_allocateInstancePrefetchLines != (uint)AllocateInstancePrefetchLines) { + log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with = %d vs current %d", (int)_allocateInstancePrefetchLines, (int)AllocateInstancePrefetchLines); + return false; + } + if (_allocatePrefetchDistance != (uint)AllocatePrefetchDistance) { + log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with = %d vs current %d", (int)_allocatePrefetchDistance, (int)AllocatePrefetchDistance); + return false; + } + if (_allocatePrefetchStepSize != (uint)AllocatePrefetchStepSize) { + log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with = %d vs current %d", (int)_allocatePrefetchStepSize, (int)AllocatePrefetchStepSize); + return false; + } + + // check intrinsic use settings are compatible + + CHECK_FLAG(use_, useCRC32, UseCRC32Intrinsics); + CHECK_FLAG(use_, useCRC32C, UseCRC32CIntrinsics); + +#ifdef COMPILER2 + // change to MaxVectorSize can affect validity of array copy/fill + // stubs + if (_maxVectorSize != (uint)MaxVectorSize) { + log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with MaxVectorSize = %d vs current %d", (int)_maxVectorSize, (int)MaxVectorSize); + return false; + } + + // changing ArrayOperationPartialInlineSize can affect validity of + // nmethods and stubs + if (_arrayOperationPartialInlineSize != (uint)ArrayOperationPartialInlineSize) { + log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with ArrayOperationPartialInlineSize = %d vs current %d", (int)_arrayOperationPartialInlineSize, (int)ArrayOperationPartialInlineSize); + return false; + } + CHECK_FLAG(use_, useMultiplyToLen, UseMultiplyToLenIntrinsic); + CHECK_FLAG(use_, useSquareToLen, UseSquareToLenIntrinsic); + CHECK_FLAG(use_, useMulAdd, UseMulAddIntrinsic); + CHECK_FLAG(use_, useMontgomeryMultiply,UseMontgomeryMultiplyIntrinsic); + CHECK_FLAG(use_, useMontgomerySquare, UseMontgomerySquareIntrinsic); +#endif // COMPILER2 + CHECK_FLAG(use_, useChaCha20, UseChaCha20Intrinsics); + CHECK_FLAG(use_, useDilithium, UseDilithiumIntrinsics); + CHECK_FLAG(use_, useKyber, UseKyberIntrinsics); + CHECK_FLAG(use_, useBASE64, UseBASE64Intrinsics); + CHECK_FLAG(use_, useAES, UseAESIntrinsics); + CHECK_FLAG(use_, useAESCTR, UseAESCTRIntrinsics); + CHECK_FLAG(use_, useGHASH, UseGHASHIntrinsics); + CHECK_FLAG(use_, useMD5, UseMD5Intrinsics); + CHECK_FLAG(use_, useSHA1, UseSHA1Intrinsics); + CHECK_FLAG(use_, useSHA256, UseSHA256Intrinsics); + CHECK_FLAG(use_, useSHA512, UseSHA512Intrinsics); + CHECK_FLAG(use_, useSHA3, UseSHA3Intrinsics); + CHECK_FLAG(use_, usePoly1305, UsePoly1305Intrinsics); + CHECK_FLAG(use_, useVectorizedMismatch, UseVectorizedMismatchIntrinsic); + CHECK_FLAG(use_, useSecondarySupersTable, UseSecondarySupersTable); + +#if defined(X86) && !defined(ZERO) + // change to AVX3Threshold may affect validity of array copy stubs + // and nmethods + if (_avx3threshold != (uint)AVX3Threshold) { + log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with AVX3Threshold = %d vs current %d", (int)_avx3threshold, AVX3Threshold); + return false; + } + + // change to UseAVX may affect validity of array copy stubs and + // nmethods + if (_useAVX != (uint)UseAVX) { + log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with useAVX = %d vs current %d", (int)_useAVX, UseAVX); + return false; + } + + // change to EnableX86ECoreOpts may affect validity of nmethods + CHECK_FLAG(x86_, x86_enableX86ECoreOpts, EnableX86ECoreOpts); + + // switching off UseUnalignedLoadStores can affect validity of fill + // stubs + if (test_x86_flag(x86_useUnalignedLoadStores) && !UseUnalignedLoadStores) { + log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with UseUnalignedLoadStores = true vs current = false"); + return false; + } + + // change to UseAPX can affect validity of nmethods and stubs + CHECK_FLAG(x86_, x86_useAPX, UseAPX); + + // check x86-specific intrinsic use settings are compatible + + CHECK_FLAG(x86_use_, x86_useLibm, UseLibmIntrinsic); + CHECK_FLAG(x86_use_, x86_useIntPoly, UseIntPolyIntrinsics); +#endif // defined(X86) && !defined(ZERO) + +#if defined(AARCH64) && !defined(ZERO) + // change to PrefetchCopyIntervalInBytes may affect validity of + // array copy stubs + if (_prefetchCopyIntervalInBytes != (uint)PrefetchCopyIntervalInBytes) { + log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with PrefetchCopyIntervalInBytes = %d vs current %d", (int)_prefetchCopyIntervalInBytes, (int)PrefetchCopyIntervalInBytes); + return false; + } + + // change to BlockZeroingLowLimit may affect validity of array fill + // stubs + if (_blockZeroingLowLimit != (uint)BlockZeroingLowLimit) { + log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with BlockZeroingLowLimit = %d vs current %d", (int)_blockZeroingLowLimit, (int)BlockZeroingLowLimit); + return false; + } + + // change to SoftwarePrefetchHintDistance may affect validity of array fill + // stubs + if (_softwarePrefetchHintDistance != (uint)SoftwarePrefetchHintDistance) { + log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with SoftwarePrefetchHintDistance = %d vs current %d", (int)_softwarePrefetchHintDistance, (int)SoftwarePrefetchHintDistance); + return false; + } + + // change to UseSVE may affect validity of stubs and nmethods + if (_useSVE != (uint)UseSVE) { + log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with UseSVE = %d vs current %d",(int)_useSVE, UseSVE); + return false; + } + + // switching on AvoidUnalignedAccesses may affect validity of array + // copy stubs and nmethods + if (!test_aarch64_flag(aarch64_avoidUnalignedAccesses) && AvoidUnalignedAccesses) { + log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with AvoidUnalignedAccesses = false vs current = true"); + return false; + } + + // change to UseSIMDForMemoryOps may affect validity of array + // copy stubs and nmethods + CHECK_FLAG(aarch64_, aarch64_useSIMDForMemoryOps, UseSIMDForMemoryOps); + // change to UseSIMDForArrayEquals may affect validity of array + // copy stubs and nmethods + CHECK_FLAG(aarch64_, aarch64_useSIMDForArrayEquals, UseSIMDForArrayEquals); + // change to useSIMDForSHA3 may affect validity of SHA3 stubs + CHECK_FLAG(aarch64_, aarch64_useSIMDForSHA3, UseSIMDForSHA3Intrinsic); + // change to UseLSE may affect validity of stubs and nmethods + CHECK_FLAG(aarch64_, aarch64_useLSE, UseLSE); + + // check aarch64-specific intrinsic use settings are compatible + + CHECK_FLAG(aarch64_use_, aarch64_useBlockZeroing, UseBlockZeroing); + CHECK_FLAG(aarch64_use_, aarch64_useSIMDForBigIntegerShift, UseSIMDForBigIntegerShiftIntrinsics); + CHECK_FLAG(aarch64_use_, aarch64_useSimpleArrayEquals, UseSimpleArrayEquals); + CHECK_FLAG(aarch64_use_, aarch64_useSecondarySupersCache, UseSecondarySupersCache); +#endif // defined(AARCH64) && !defined(ZERO) + +#if INCLUDE_JVMCI + // change to EnableJVMCI will affect validity of adapters and + // nmethods + if (_enableJVMCI != (uint)EnableJVMCI) { + log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with EnableJVMCI = %s vs current %s", (_enableJVMCI ? "true" : "false"), (EnableJVMCI ? "true" : "false")); + return false; + } +#endif // INCLUDE_JVMCI + // The following checks do not affect AOT adapters caching - if (((_flags & compressedOops) != 0) != UseCompressedOops) { + if (test_flag(compressedOops) != UseCompressedOops) { log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with UseCompressedOops = %s", UseCompressedOops ? "false" : "true"); AOTStubCaching = false; } @@ -493,12 +764,11 @@ bool AOTCodeCache::Config::verify(AOTCodeCache* cache) const { AOTStubCaching = false; } - if (!verify_cpu_features(cache)) { - return false; - } return true; } +#undef TEST_FLAG + bool AOTCodeCache::Header::verify(uint load_size) const { if (_version != AOT_CODE_VERSION) { log_debug(aot, codecache, init)("AOT Code Cache disabled: different AOT Code version %d vs %d recorded in AOT Code header", AOT_CODE_VERSION, _version); diff --git a/src/hotspot/share/code/aotCodeCache.hpp b/src/hotspot/share/code/aotCodeCache.hpp index b0d39ff3e08..52b0adfba48 100644 --- a/src/hotspot/share/code/aotCodeCache.hpp +++ b/src/hotspot/share/code/aotCodeCache.hpp @@ -173,6 +173,16 @@ class AOTCodeCache : public CHeapObj { uint _compressedKlassShift; uint _contendedPaddingWidth; uint _gc; + uint _optoLoopAlignment; + uint _codeEntryAlignment; + uint _allocatePrefetchLines; + uint _allocateInstancePrefetchLines; + uint _allocatePrefetchDistance; + uint _allocatePrefetchStepSize; +#ifdef COMPILER2 + uint _maxVectorSize; + uint _arrayOperationPartialInlineSize; +#endif // COMPILER2 enum Flags { none = 0, debugVM = 1, @@ -184,8 +194,90 @@ class AOTCodeCache : public CHeapObj { restrictContendedPadding = 64 }; uint _flags; + enum IntrinsicsUseFlags { + use_none = 0, + useCRC32 = 1 << 0, + useCRC32C = 1 << 1, + useMultiplyToLen = 1 << 2, + useSquareToLen = 1 << 3, + useMulAdd = 1 << 4, + useMontgomeryMultiply = 1 << 5, + useMontgomerySquare = 1 << 6, + useChaCha20 = 1 << 7, + useDilithium = 1 << 8, + useKyber = 1 << 9, + useBASE64 = 1 << 10, + useAdler32 = 1 << 11, + useAES = 1 << 12, + useAESCTR = 1 << 13, + useGHASH = 1 << 14, + useMD5 = 1 << 15, + useSHA1 = 1 << 16, + useSHA256 = 1 << 17, + useSHA512 = 1 << 18, + useSHA3 = 1 << 19, + usePoly1305 = 1 << 20, + useVectorizedMismatch = 1 << 21, + useSecondarySupersTable = 1 << 22, + }; + uint _use_intrinsics_flags; + bool test_flag(enum Flags flag) const { return (_flags & flag) != 0; } + bool test_use_flag(enum IntrinsicsUseFlags flag) const { return (_use_intrinsics_flags & flag) != 0; } + void set_flag(enum Flags flag) { _flags |= flag; } + void set_use_flag(enum IntrinsicsUseFlags flag) { _use_intrinsics_flags |= flag; } +#if defined(X86) && !defined(ZERO) + uint _avx3threshold; + uint _useAVX; + enum X86Flags { + x86_none = 0, + x86_enableX86ECoreOpts = 1, + x86_useUnalignedLoadStores = 2, + x86_useAPX = 4 + }; + uint _x86_flags; + enum X86IntrinsicsUseFlags { + x86_use_none = 0, + x86_useLibm = 1 << 1, + x86_useIntPoly = 1 << 2, + }; + uint _x86_use_intrinsics_flags; + bool test_x86_flag(enum X86Flags flag) const { return (_x86_flags & flag) != 0; } + bool test_x86_use_flag(enum X86IntrinsicsUseFlags flag) const { return (_x86_use_intrinsics_flags & flag) != 0; } + void set_x86_flag(enum X86Flags flag) { _x86_flags |= flag; } + void set_x86_use_flag(enum X86IntrinsicsUseFlags flag) { _x86_use_intrinsics_flags |= flag; } +#endif // defined(X86) && !defined(ZERO) +#if defined(AARCH64) && !defined(ZERO) + // this is global but x86 does not use it and aarch64 does + uint _prefetchCopyIntervalInBytes; + uint _blockZeroingLowLimit; + uint _softwarePrefetchHintDistance; + uint _useSVE; + enum AArch64Flags { + aarch64_none = 0, + aarch64_avoidUnalignedAccesses = 1, + aarch64_useSIMDForMemoryOps = 2, + aarch64_useSIMDForArrayEquals = 4, + aarch64_useSIMDForSHA3 = 8, + aarch64_useLSE = 16, + }; + uint _aarch64_flags; + enum AArch64IntrinsicsUseFlags { + aarch64_use_none = 0, + aarch64_useBlockZeroing = 1 << 0, + aarch64_useSIMDForBigIntegerShift = 1 << 1, + aarch64_useSimpleArrayEquals = 1 << 2, + aarch64_useSecondarySupersCache = 1 << 3, + }; + uint _aarch64_use_intrinsics_flags; + bool test_aarch64_flag(enum AArch64Flags flag) const { return (_aarch64_flags & flag) != 0; } + bool test_aarch64_use_flag(enum AArch64IntrinsicsUseFlags flag) const { return (_aarch64_use_intrinsics_flags & flag) != 0; } + void set_aarch64_flag(enum AArch64Flags flag) { _aarch64_flags |= flag; } + void set_aarch64_use_flag(enum AArch64IntrinsicsUseFlags flag) { _aarch64_use_intrinsics_flags |= flag; } +#endif // defined(AARCH64) && !defined(ZERO) +#if INCLUDE_JVMCI + uint _enableJVMCI; +#endif // INCLUDE_JVMCI uint _cpu_features_offset; // offset in the cache where cpu features are stored - public: void record(uint cpu_features_offset); bool verify_cpu_features(AOTCodeCache* cache) const; From b58d1ad1ee9aa30d97286b3b78054488e083c351 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Wed, 1 Apr 2026 08:14:59 +0000 Subject: [PATCH 096/116] 8372016: G1: Root scanning not yielding to safepoints causes crashes Reviewed-by: iwalulya, ayang --- src/hotspot/share/gc/g1/g1CollectedHeap.cpp | 1 + src/hotspot/share/gc/g1/g1ConcurrentMark.cpp | 212 +++++++++--------- src/hotspot/share/gc/g1/g1ConcurrentMark.hpp | 71 +++--- .../share/gc/g1/g1ConcurrentMarkThread.cpp | 7 +- src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp | 6 +- src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp | 10 +- src/hotspot/share/gc/g1/g1VMOperations.cpp | 5 +- src/hotspot/share/gc/g1/g1YoungCollector.cpp | 18 +- src/hotspot/share/gc/g1/g1YoungCollector.hpp | 2 +- src/hotspot/share/runtime/mutexLocker.cpp | 2 - src/hotspot/share/runtime/mutexLocker.hpp | 1 - 11 files changed, 165 insertions(+), 170 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index e6dd91df84b..fe286793ae7 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -1652,6 +1652,7 @@ jint G1CollectedHeap::initialize() { } void G1CollectedHeap::stop() { + assert_not_at_safepoint(); // Stop all concurrent threads. We do this to make sure these threads // do not continue to execute and access resources (e.g. logging) // that are destroyed during shutdown. diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp index 1caa8dbdd06..84a0b7588ef 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp @@ -372,63 +372,56 @@ void G1CMMarkStack::set_empty() { G1CMRootMemRegions::G1CMRootMemRegions(uint const max_regions) : _root_regions(MemRegion::create_array(max_regions, mtGC)), _max_regions(max_regions), - _num_root_regions(0), - _claimed_root_regions(0), - _scan_in_progress(false), - _should_abort(false) { } + _num_regions(0), + _num_claimed_regions(0) { } G1CMRootMemRegions::~G1CMRootMemRegions() { MemRegion::destroy_array(_root_regions, _max_regions); } void G1CMRootMemRegions::reset() { - _num_root_regions.store_relaxed(0); + assert_at_safepoint(); + assert(G1CollectedHeap::heap()->collector_state()->is_in_concurrent_start_gc(), "must be"); + + _num_regions.store_relaxed(0); + _num_claimed_regions.store_relaxed(0); } void G1CMRootMemRegions::add(HeapWord* start, HeapWord* end) { assert_at_safepoint(); - size_t idx = _num_root_regions.fetch_then_add(1u); - assert(idx < _max_regions, "Trying to add more root MemRegions than there is space %zu", _max_regions); + uint idx = _num_regions.fetch_then_add(1u); + assert(idx < _max_regions, "Trying to add more root MemRegions than there is space %u", _max_regions); assert(start != nullptr && end != nullptr && start <= end, "Start (" PTR_FORMAT ") should be less or equal to " "end (" PTR_FORMAT ")", p2i(start), p2i(end)); _root_regions[idx].set_start(start); _root_regions[idx].set_end(end); } -void G1CMRootMemRegions::prepare_for_scan() { - assert(!scan_in_progress(), "pre-condition"); - - _scan_in_progress.store_relaxed(num_root_regions() > 0); - - _claimed_root_regions.store_relaxed(0); - _should_abort.store_relaxed(false); -} - const MemRegion* G1CMRootMemRegions::claim_next() { - if (_should_abort.load_relaxed()) { - // If someone has set the should_abort flag, we return null to - // force the caller to bail out of their loop. + uint local_num_regions = num_regions(); + if (num_claimed_regions() >= local_num_regions) { return nullptr; } - uint local_num_root_regions = num_root_regions(); - if (_claimed_root_regions.load_relaxed() >= local_num_root_regions) { - return nullptr; - } - - size_t claimed_index = _claimed_root_regions.fetch_then_add(1u); - if (claimed_index < local_num_root_regions) { + uint claimed_index = _num_claimed_regions.fetch_then_add(1u); + if (claimed_index < local_num_regions) { return &_root_regions[claimed_index]; } return nullptr; } -uint G1CMRootMemRegions::num_root_regions() const { - return (uint)_num_root_regions.load_relaxed(); +bool G1CMRootMemRegions::work_completed() const { + return num_remaining_regions() == 0; +} + +uint G1CMRootMemRegions::num_remaining_regions() const { + uint total = num_regions(); + uint claimed = num_claimed_regions(); + return (total > claimed) ? total - claimed : 0; } bool G1CMRootMemRegions::contains(const MemRegion mr) const { - uint local_num_root_regions = num_root_regions(); + uint local_num_root_regions = num_regions(); for (uint i = 0; i < local_num_root_regions; i++) { if (_root_regions[i].equals(mr)) { return true; @@ -437,42 +430,6 @@ bool G1CMRootMemRegions::contains(const MemRegion mr) const { return false; } -void G1CMRootMemRegions::notify_scan_done() { - MutexLocker x(G1RootRegionScan_lock, Mutex::_no_safepoint_check_flag); - _scan_in_progress.store_relaxed(false); - G1RootRegionScan_lock->notify_all(); -} - -void G1CMRootMemRegions::cancel_scan() { - notify_scan_done(); -} - -void G1CMRootMemRegions::scan_finished() { - assert(scan_in_progress(), "pre-condition"); - - if (!_should_abort.load_relaxed()) { - assert(_claimed_root_regions.load_relaxed() >= num_root_regions(), - "we should have claimed all root regions, claimed %zu, length = %u", - _claimed_root_regions.load_relaxed(), num_root_regions()); - } - - notify_scan_done(); -} - -bool G1CMRootMemRegions::wait_until_scan_finished() { - if (!scan_in_progress()) { - return false; - } - - { - MonitorLocker ml(G1RootRegionScan_lock, Mutex::_no_safepoint_check_flag); - while (scan_in_progress()) { - ml.wait(); - } - } - return true; -} - G1ConcurrentMark::G1ConcurrentMark(G1CollectedHeap* g1h, G1RegionToSpaceMapper* bitmap_storage) : _cm_thread(nullptr), @@ -483,6 +440,7 @@ G1ConcurrentMark::G1ConcurrentMark(G1CollectedHeap* g1h, _heap(_g1h->reserved()), _root_regions(_g1h->max_num_regions()), + _root_region_scan_aborted(false), _global_mark_stack(), @@ -614,6 +572,7 @@ void G1ConcurrentMark::reset() { _region_mark_stats[i].clear(); } + _root_region_scan_aborted.store_relaxed(false); _root_regions.reset(); } @@ -970,8 +929,6 @@ void G1ConcurrentMark::start_full_concurrent_cycle() { satb_mq_set.set_active_all_threads(true, /* new active value */ false /* expected_active */); - _root_regions.prepare_for_scan(); - // update_g1_committed() will be called at the end of an evac pause // when marking is on. So, it's also called at the end of the // concurrent start pause to update the heap end, if the heap expands @@ -982,7 +939,11 @@ void G1ConcurrentMark::start_full_concurrent_cycle() { } void G1ConcurrentMark::start_undo_concurrent_cycle() { - root_regions()->cancel_scan(); + assert_at_safepoint_on_vm_thread(); + // At this time this GC is not a concurrent start gc any more, can only check for young only gc/phase. + assert(_g1h->collector_state()->is_in_young_only_phase(), "must be"); + + abort_root_region_scan_at_safepoint(); // Signal the thread to start work. cm_thread()->start_undo_cycle(); @@ -1094,6 +1055,16 @@ uint G1ConcurrentMark::calc_active_marking_workers() { return result; } +bool G1ConcurrentMark::has_root_region_scan_aborted() const { + return _root_region_scan_aborted.load_relaxed(); +} + +#ifndef PRODUCT +void G1ConcurrentMark::assert_root_region_scan_completed_or_aborted() { + assert(root_regions()->work_completed() || has_root_region_scan_aborted(), "must be"); +} +#endif + void G1ConcurrentMark::scan_root_region(const MemRegion* region, uint worker_id) { #ifdef ASSERT HeapWord* last = region->last(); @@ -1120,45 +1091,76 @@ void G1ConcurrentMark::scan_root_region(const MemRegion* region, uint worker_id) class G1CMRootRegionScanTask : public WorkerTask { G1ConcurrentMark* _cm; + bool _should_yield; + public: - G1CMRootRegionScanTask(G1ConcurrentMark* cm) : - WorkerTask("G1 Root Region Scan"), _cm(cm) { } + G1CMRootRegionScanTask(G1ConcurrentMark* cm, bool should_yield) : + WorkerTask("G1 Root Region Scan"), _cm(cm), _should_yield(should_yield) { } void work(uint worker_id) { - G1CMRootMemRegions* root_regions = _cm->root_regions(); - const MemRegion* region = root_regions->claim_next(); - while (region != nullptr) { + SuspendibleThreadSetJoiner sts_join(_should_yield); + + while (true) { + if (_cm->has_root_region_scan_aborted()) { + return; + } + G1CMRootMemRegions* root_regions = _cm->root_regions(); + const MemRegion* region = root_regions->claim_next(); + if (region == nullptr) { + return; + } _cm->scan_root_region(region, worker_id); - region = root_regions->claim_next(); + if (_should_yield) { + SuspendibleThreadSet::yield(); + // If we yielded, a GC may have processed all root regions, + // so this loop will naturally exit on the next claim_next() call. + // Same if a Full GC signalled abort of the concurrent mark. + } } } }; -void G1ConcurrentMark::scan_root_regions() { - // scan_in_progress() will have been set to true only if there was - // at least one root region to scan. So, if it's false, we - // should not attempt to do any further work. - if (root_regions()->scan_in_progress()) { - assert(!has_aborted(), "Aborting before root region scanning is finished not supported."); - +bool G1ConcurrentMark::scan_root_regions(WorkerThreads* workers, bool concurrent) { + // We first check whether there is any work to do as we might have already aborted + // the concurrent cycle, or ran into a GC that did the actual work when we reach here. + // We want to avoid spinning up the worker threads if that happened. + // (Note that due to races reading the abort-flag, we might spin up the threads anyway). + // + // Abort happens if a Full GC occurs right after starting the concurrent cycle or + // a young gc doing the work. + // + // Concurrent gc threads enter an STS when starting the task, so they stop, then + // continue after that safepoint. + bool do_scan = !root_regions()->work_completed() && !has_root_region_scan_aborted(); + if (do_scan) { // Assign one worker to each root-region but subject to the max constraint. - const uint num_workers = MIN2(root_regions()->num_root_regions(), + // The constraint is also important to avoid accesses beyond the allocated per-worker + // marking helper data structures. We might get passed different WorkerThreads with + // different number of threads (potential worker ids) than helper data structures when + // completing this work during GC. + const uint num_workers = MIN2(root_regions()->num_remaining_regions(), _max_concurrent_workers); + assert(num_workers > 0, "no more remaining root regions to process"); - G1CMRootRegionScanTask task(this); + G1CMRootRegionScanTask task(this, concurrent); log_debug(gc, ergo)("Running %s using %u workers for %u work units.", - task.name(), num_workers, root_regions()->num_root_regions()); - _concurrent_workers->run_task(&task, num_workers); - - // It's possible that has_aborted() is true here without actually - // aborting the survivor scan earlier. This is OK as it's - // mainly used for sanity checking. - root_regions()->scan_finished(); + task.name(), num_workers, root_regions()->num_remaining_regions()); + workers->run_task(&task, num_workers); } + + assert_root_region_scan_completed_or_aborted(); + + return do_scan; } -bool G1ConcurrentMark::wait_until_root_region_scan_finished() { - return root_regions()->wait_until_scan_finished(); +void G1ConcurrentMark::scan_root_regions_concurrently() { + assert(Thread::current() == cm_thread(), "must be on Concurrent Mark Thread"); + scan_root_regions(_concurrent_workers, true /* concurrent */); +} + +bool G1ConcurrentMark::complete_root_regions_scan_in_safepoint() { + assert_at_safepoint_on_vm_thread(); + return scan_root_regions(_g1h->workers(), false /* concurrent */); } void G1ConcurrentMark::add_root_region(G1HeapRegion* r) { @@ -1169,9 +1171,16 @@ bool G1ConcurrentMark::is_root_region(G1HeapRegion* r) { return root_regions()->contains(MemRegion(top_at_mark_start(r), r->top())); } -void G1ConcurrentMark::root_region_scan_abort_and_wait() { - root_regions()->abort(); - root_regions()->wait_until_scan_finished(); +void G1ConcurrentMark::abort_root_region_scan() { + assert_not_at_safepoint(); + + _root_region_scan_aborted.store_relaxed(true); +} + +void G1ConcurrentMark::abort_root_region_scan_at_safepoint() { + assert_at_safepoint_on_vm_thread(); + + _root_region_scan_aborted.store_relaxed(true); } void G1ConcurrentMark::concurrent_cycle_start() { @@ -1948,12 +1957,15 @@ void G1ConcurrentMark::print_stats() { } bool G1ConcurrentMark::concurrent_cycle_abort() { + assert_at_safepoint_on_vm_thread(); + assert(_g1h->collector_state()->is_in_full_gc(), "must be"); + // If we start the compaction before the CM threads finish // scanning the root regions we might trip them over as we'll - // be moving objects / updating references. So let's wait until - // they are done. By telling them to abort, they should complete - // early. - root_region_scan_abort_and_wait(); + // be moving objects / updating references. Since the root region + // scan synchronized with the safepoint, just tell it to abort. + // It will notice when the threads start up again later. + abort_root_region_scan_at_safepoint(); // 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 @@ -1983,7 +1995,7 @@ bool G1ConcurrentMark::concurrent_cycle_abort() { } void G1ConcurrentMark::abort_marking_threads() { - assert(!_root_regions.scan_in_progress(), "still doing root region scan"); + assert_root_region_scan_completed_or_aborted(); _has_aborted.store_relaxed(true); _first_overflow_barrier_sync.abort(); _second_overflow_barrier_sync.abort(); diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp b/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp index de97179d210..7aa93947204 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp @@ -288,57 +288,36 @@ class G1CMMarkStack { class G1CMRootMemRegions { // The set of root MemRegions. MemRegion* _root_regions; - size_t const _max_regions; + uint const _max_regions; - Atomic _num_root_regions; // Actual number of root regions. + Atomic _num_regions; // Actual number of root regions. + Atomic _num_claimed_regions; // Number of root regions currently claimed. - Atomic _claimed_root_regions; // Number of root regions currently claimed. - - Atomic _scan_in_progress; - Atomic _should_abort; - - void notify_scan_done(); + uint num_regions() const { return _num_regions.load_relaxed(); } + uint num_claimed_regions() const { return _num_claimed_regions.load_relaxed(); } public: G1CMRootMemRegions(uint const max_regions); ~G1CMRootMemRegions(); - // Reset the data structure to allow addition of new root regions. - void reset(); - void add(HeapWord* start, HeapWord* end); - // Reset the claiming / scanning of the root regions. - void prepare_for_scan(); - - // Forces get_next() to return null so that the iteration aborts early. - void abort() { _should_abort.store_relaxed(true); } - - // Return true if the CM thread are actively scanning root regions, - // false otherwise. - bool scan_in_progress() { return _scan_in_progress.load_relaxed(); } + // Reset data structure to initial state. + void reset(); // Claim the next root MemRegion to scan atomically, or return null if // all have been claimed. const MemRegion* claim_next(); - // The number of root regions to scan. - uint num_root_regions() const; + // Number of root regions to still process. + uint num_remaining_regions() const; + + // Returns whether all root regions have been processed or the processing been aborted. + bool work_completed() const; // Is the given memregion contained in the root regions; the MemRegion must // match exactly. bool contains(const MemRegion mr) const; - - void cancel_scan(); - - // Flag that we're done with root region scanning and notify anyone - // who's waiting on it. If aborted is false, assume that all regions - // have been claimed. - void scan_finished(); - - // If CM threads are still scanning root regions, wait until they - // are done. Return true if we had to wait, false otherwise. - bool wait_until_scan_finished(); }; // This class manages data structures and methods for doing liveness analysis in @@ -367,6 +346,7 @@ class G1ConcurrentMark : public CHeapObj { // Root region tracking and claiming G1CMRootMemRegions _root_regions; + Atomic _root_region_scan_aborted; // For grey objects G1CMMarkStack _global_mark_stack; // Grey objects behind global finger @@ -600,7 +580,7 @@ class G1ConcurrentMark : public CHeapObj { // 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. + // running or being aborted. void abort_marking_threads(); // Total cpu time spent in mark worker threads in seconds. @@ -651,17 +631,30 @@ class G1ConcurrentMark : public CHeapObj { // Stop active components/the concurrent mark thread. void stop(); - // Scan all the root regions and mark everything reachable from - // them. - void scan_root_regions(); - bool wait_until_root_region_scan_finished(); void add_root_region(G1HeapRegion* r); bool is_root_region(G1HeapRegion* r); - void root_region_scan_abort_and_wait(); + + // Scan all the root regions concurrently and mark everything reachable from + // them. + void scan_root_regions_concurrently(); + // Complete root region scan work in the safepoint, return if we did some work. + bool complete_root_regions_scan_in_safepoint(); + + // Abort an active concurrent root region scan outside safepoint. + void abort_root_region_scan(); + + bool has_root_region_scan_aborted() const; private: + // Abort an active concurrent root region scan during safepoint. + void abort_root_region_scan_at_safepoint(); + + void assert_root_region_scan_completed_or_aborted() PRODUCT_RETURN; G1CMRootMemRegions* root_regions() { return &_root_regions; } + // Perform root region scan until all root regions have been processed, or + // the process has been aborted. Returns true if we did some work. + bool scan_root_regions(WorkerThreads* workers, bool concurrent); // Scan a single root MemRegion to mark everything reachable from it. void scan_root_region(const MemRegion* region, uint worker_id); diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.cpp b/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.cpp index 31d61b8b388..b8c97acd1b0 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.cpp @@ -131,14 +131,11 @@ void G1ConcurrentMarkThread::run_service() { update_perf_counter_cpu_time(); } - _cm->root_regions()->cancel_scan(); } void G1ConcurrentMarkThread::stop_service() { if (is_in_progress()) { - // We are not allowed to abort the marking threads during root region scan. - // Needs to be done separately. - _cm->root_region_scan_abort_and_wait(); + _cm->abort_root_region_scan(); _cm->abort_marking_threads(); } @@ -164,7 +161,7 @@ bool G1ConcurrentMarkThread::phase_clear_cld_claimed_marks() { bool G1ConcurrentMarkThread::phase_scan_root_regions() { G1ConcPhaseTimer p(_cm, "Concurrent Scan Root Regions"); - _cm->scan_root_regions(); + _cm->scan_root_regions_concurrently(); update_perf_counter_cpu_time(); return _cm->has_aborted(); } diff --git a/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp index a5013ddbb40..023790a2422 100644 --- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp +++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp @@ -180,7 +180,7 @@ void G1GCPhaseTimes::reset() { _cur_post_evacuate_cleanup_2_time_ms = 0.0; _cur_resize_heap_time_ms = 0.0; _cur_ref_proc_time_ms = 0.0; - _root_region_scan_wait_time_ms = 0.0; + _root_region_scan_time_ms = 0.0; _external_accounted_time_ms = 0.0; _recorded_prepare_heap_roots_time_ms = 0.0; _recorded_young_cset_choice_time_ms = 0.0; @@ -549,8 +549,8 @@ void G1GCPhaseTimes::print_other(double accounted_ms) const { // In addition, these are not included in G1GCPhaseTimes::_gc_pause_time_ms. // See G1YoungCollector::collect(). void G1GCPhaseTimes::print(bool evacuation_failed) { - if (_root_region_scan_wait_time_ms > 0.0) { - debug_time("Root Region Scan Waiting", _root_region_scan_wait_time_ms); + if (_root_region_scan_time_ms > 0.0) { + debug_time("Root Region Scan", _root_region_scan_time_ms); } // Check if some time has been recorded for verification and only then print diff --git a/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp b/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp index 8223148b791..b57bf0d617e 100644 --- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp +++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp @@ -191,7 +191,7 @@ class G1GCPhaseTimes : public CHeapObj { double _cur_ref_proc_time_ms; // Not included in _gc_pause_time_ms - double _root_region_scan_wait_time_ms; + double _root_region_scan_time_ms; double _external_accounted_time_ms; @@ -325,8 +325,8 @@ class G1GCPhaseTimes : public CHeapObj { _cur_prepare_concurrent_task_time_ms = ms; } - void record_root_region_scan_wait_time(double time_ms) { - _root_region_scan_wait_time_ms = time_ms; + void record_root_region_scan_time(double time_ms) { + _root_region_scan_time_ms = time_ms; } void record_serial_free_cset_time_ms(double time_ms) { @@ -399,8 +399,8 @@ class G1GCPhaseTimes : public CHeapObj { return _cur_resize_heap_time_ms; } - double root_region_scan_wait_time_ms() { - return _root_region_scan_wait_time_ms; + double root_region_scan_time_ms() { + return _root_region_scan_time_ms; } double young_cset_choice_time_ms() { diff --git a/src/hotspot/share/gc/g1/g1VMOperations.cpp b/src/hotspot/share/gc/g1/g1VMOperations.cpp index b0c6b680b78..891432e20a7 100644 --- a/src/hotspot/share/gc/g1/g1VMOperations.cpp +++ b/src/hotspot/share/gc/g1/g1VMOperations.cpp @@ -152,8 +152,9 @@ bool VM_G1PauseConcurrent::doit_prologue() { G1CollectedHeap* g1h = G1CollectedHeap::heap(); if (g1h->is_shutting_down()) { Heap_lock->unlock(); - // JVM shutdown has started. This ensures that any further operations will be properly aborted - // and will not interfere with the shutdown process. + // JVM shutdown has started. Abort concurrent marking to ensure that any further + // concurrent VM operations will not try to start and interfere with the shutdown + // process. g1h->concurrent_mark()->abort_marking_threads(); return false; } diff --git a/src/hotspot/share/gc/g1/g1YoungCollector.cpp b/src/hotspot/share/gc/g1/g1YoungCollector.cpp index a4938416f25..9c12127c864 100644 --- a/src/hotspot/share/gc/g1/g1YoungCollector.cpp +++ b/src/hotspot/share/gc/g1/g1YoungCollector.cpp @@ -244,19 +244,13 @@ G1YoungGCAllocationFailureInjector* G1YoungCollector::allocation_failure_injecto return _g1h->allocation_failure_injector(); } - -void G1YoungCollector::wait_for_root_region_scanning() { +void G1YoungCollector::complete_root_region_scan() { Ticks start = Ticks::now(); - // We have to wait until the CM threads finish scanning the - // root regions as it's the only way to ensure that all the - // objects on them have been correctly scanned before we start - // moving them during the GC. - bool waited = concurrent_mark()->wait_until_root_region_scan_finished(); - Tickspan wait_time; - if (waited) { - wait_time = (Ticks::now() - start); + // We have to complete root region scan as it's the only way to ensure that all the + // objects on them have been correctly scanned before we start moving them during the GC. + if (concurrent_mark()->complete_root_regions_scan_in_safepoint()) { + phase_times()->record_root_region_scan_time((Ticks::now() - start).seconds() * MILLIUNITS); } - phase_times()->record_root_region_scan_wait_time(wait_time.seconds() * MILLIUNITS); } class G1PrintCollectionSetClosure : public G1HeapRegionClosure { @@ -1147,7 +1141,7 @@ void G1YoungCollector::collect() { // Wait for root region scan here to make sure that it is done before any // use of the STW workers to maximize cpu use (i.e. all cores are available // just to do that). - wait_for_root_region_scanning(); + complete_root_region_scan(); G1YoungGCVerifierMark vm(this); { diff --git a/src/hotspot/share/gc/g1/g1YoungCollector.hpp b/src/hotspot/share/gc/g1/g1YoungCollector.hpp index 76d443b1a9f..ab32ca770a4 100644 --- a/src/hotspot/share/gc/g1/g1YoungCollector.hpp +++ b/src/hotspot/share/gc/g1/g1YoungCollector.hpp @@ -89,7 +89,7 @@ class G1YoungCollector { // returning the total time taken. Tickspan run_task_timed(WorkerTask* task); - void wait_for_root_region_scanning(); + void complete_root_region_scan(); void calculate_collection_set(G1EvacInfo* evacuation_info, double target_pause_time_ms); diff --git a/src/hotspot/share/runtime/mutexLocker.cpp b/src/hotspot/share/runtime/mutexLocker.cpp index b102e6424f1..3dd61374d03 100644 --- a/src/hotspot/share/runtime/mutexLocker.cpp +++ b/src/hotspot/share/runtime/mutexLocker.cpp @@ -105,7 +105,6 @@ Mutex* G1MarkStackFreeList_lock = nullptr; Monitor* G1OldGCCount_lock = nullptr; Mutex* G1OldSets_lock = nullptr; Mutex* G1ReviseYoungLength_lock = nullptr; -Monitor* G1RootRegionScan_lock = nullptr; Mutex* G1RareEvent_lock = nullptr; Mutex* G1Uncommit_lock = nullptr; #endif @@ -216,7 +215,6 @@ void mutex_init() { MUTEX_DEFN(G1MarkStackChunkList_lock , PaddedMutex , nosafepoint); MUTEX_DEFN(G1MarkStackFreeList_lock , PaddedMutex , nosafepoint); MUTEX_DEFN(G1OldSets_lock , PaddedMutex , nosafepoint); - MUTEX_DEFN(G1RootRegionScan_lock , PaddedMonitor, nosafepoint-1); MUTEX_DEFN(G1Uncommit_lock , PaddedMutex , service-2); } #endif diff --git a/src/hotspot/share/runtime/mutexLocker.hpp b/src/hotspot/share/runtime/mutexLocker.hpp index f6c0a967718..682383de401 100644 --- a/src/hotspot/share/runtime/mutexLocker.hpp +++ b/src/hotspot/share/runtime/mutexLocker.hpp @@ -101,7 +101,6 @@ extern Monitor* G1OldGCCount_lock; // in support of "concurrent" f extern Mutex* G1OldSets_lock; // protects the G1 old region sets extern Mutex* G1RareEvent_lock; // Synchronizes (rare) parallel GC operations. extern Mutex* G1ReviseYoungLength_lock; // Protects access to young gen length revising operations. -extern Monitor* G1RootRegionScan_lock; // used to notify that the G1 CM threads have finished scanning the root regions extern Mutex* G1Uncommit_lock; // protects the G1 uncommit list when not at safepoints #endif From 9bf67a64f0a83a07dd292b679beaffd8b65b8c37 Mon Sep 17 00:00:00 2001 From: Anton Artemov Date: Wed, 1 Apr 2026 08:34:48 +0000 Subject: [PATCH 097/116] 8371596: Nits and typos found during review of fix for JDK-8366659 Reviewed-by: dholmes, dcubed, fbredberg --- src/hotspot/share/runtime/objectMonitor.cpp | 163 +++++++++++--------- 1 file changed, 94 insertions(+), 69 deletions(-) diff --git a/src/hotspot/share/runtime/objectMonitor.cpp b/src/hotspot/share/runtime/objectMonitor.cpp index 94399088464..9fc834f4b6b 100644 --- a/src/hotspot/share/runtime/objectMonitor.cpp +++ b/src/hotspot/share/runtime/objectMonitor.cpp @@ -155,7 +155,7 @@ static const jlong MAX_RECHECK_INTERVAL = 1000; // // Succession is provided for by a policy of competitive handoff. // The exiting thread does _not_ grant or pass ownership to the -// successor thread. (This is also referred to as "handoff succession"). +// successor thread. (This is also referred to as "handoff succession"). // Instead the exiting thread releases ownership and possibly wakes // a successor, so the successor can (re)compete for ownership of the lock. // @@ -189,7 +189,7 @@ static const jlong MAX_RECHECK_INTERVAL = 1000; // // Once we have formed a doubly linked list it's easy to find the // successor (A), wake it up, have it remove itself, and update the -// tail pointer, as seen in and 3) below. +// tail pointer, see 3) below. // // 3) entry_list ->F<=>E<=>D<=>C<=>B->null // entry_list_tail ------------------^ @@ -223,7 +223,7 @@ static const jlong MAX_RECHECK_INTERVAL = 1000; // remove itself) or update the tail. // // * The monitor entry list operations avoid locks, but strictly speaking -// they're not lock-free. Enter is lock-free, exit is not. +// they're not lock-free. Enter is lock-free, exit is not. // For a description of 'Methods and apparatus providing non-blocking access // to a resource,' see U.S. Pat. No. 7844973. // @@ -387,7 +387,7 @@ bool ObjectMonitor::try_lock_with_contention_mark(JavaThread* locking_thread, Ob prev_owner = try_set_owner_from(DEFLATER_MARKER, locking_thread); if (prev_owner == DEFLATER_MARKER) { // We successfully cancelled the in-progress async deflation by - // changing owner from DEFLATER_MARKER to current. We now extend + // changing owner from DEFLATER_MARKER to current. We now extend // the lifetime of the contention_mark (e.g. contentions++) here // to prevent the deflater thread from winning the last part of // the 2-part async deflation protocol after the regular @@ -633,14 +633,14 @@ void ObjectMonitor::enter_with_contention_mark(JavaThread* current, ObjectMonito // The thread -- now the owner -- is back in vm mode. // Report the glorious news via TI,DTrace and jvmstat. - // The probe effect is non-trivial. All the reportage occurs + // The probe effect is non-trivial. All the reportage occurs // while we hold the monitor, increasing the length of the critical - // section. Amdahl's parallel speedup law comes vividly into play. + // section. Amdahl's parallel speedup law comes vividly into play. // // Another option might be to aggregate the events (thread local or // per-monitor aggregation) and defer reporting until a more opportune // time -- such as next time some thread encounters contention but has - // yet to acquire the lock. While spinning that thread could + // yet to acquire the lock. While spinning that thread could // spinning we could increment JVMStat counters, etc. DTRACE_MONITOR_PROBE(contended__entered, this, object(), current); @@ -739,11 +739,11 @@ bool ObjectMonitor::try_lock_or_add_to_entry_list(JavaThread* current, ObjectWai return false; } - // Interference - the CAS failed because _entry_list changed. Before + // Interference - the CAS failed because _entry_list changed. Before // retrying the CAS retry taking the lock as it may now be free. if (try_lock(current) == TryLockResult::Success) { - assert(!has_successor(current), "invariant"); assert(has_owner(current), "invariant"); + assert(!has_successor(current), "invariant"); node->TState = ObjectWaiter::TS_RUN; return true; } @@ -953,8 +953,8 @@ bool ObjectMonitor::try_enter_fast(JavaThread* current, ObjectWaiter* current_no // Try the lock - TATAS if (try_lock(current) == TryLockResult::Success) { - assert(!has_successor(current), "invariant"); assert(has_owner(current), "invariant"); + assert(!has_successor(current), "invariant"); return true; } @@ -964,7 +964,7 @@ bool ObjectMonitor::try_enter_fast(JavaThread* current, ObjectWaiter* current_no // // If the _owner is ready but OFFPROC we could use a YieldTo() // operation to donate the remainder of this thread's quantum - // to the owner. This has subtle but beneficial affinity + // to the owner. This has subtle but beneficial affinity // effects. if (try_spin(current)) { @@ -974,15 +974,15 @@ bool ObjectMonitor::try_enter_fast(JavaThread* current, ObjectWaiter* current_no } // The Spin failed -- Enqueue and park the thread ... - assert(!has_successor(current), "invariant"); assert(!has_owner(current), "invariant"); + assert(!has_successor(current), "invariant"); // Enqueue "current" on ObjectMonitor's _entry_list. // // current_node acts as a proxy for current. // As an aside, if were to ever rewrite the synchronization code mostly // in Java, WaitNodes, ObjectMonitors, and Events would become 1st-class - // Java objects. This would avoid awkward lifecycle and liveness issues, + // Java objects. This would avoid awkward lifecycle and liveness issues, // as well as eliminate a subset of ABA issues. // TODO: eliminate ObjectWaiter and enqueue either Threads or Events. @@ -995,7 +995,7 @@ bool ObjectMonitor::try_enter_fast(JavaThread* current, ObjectWaiter* current_no // This thread is now added to the _entry_list. // The lock might have been released while this thread was occupied queueing - // itself onto _entry_list. To close the race and avoid "stranding" and + // itself onto _entry_list. To close the race and avoid "stranding" and // progress-liveness failure the caller must resample-retry _owner before parking. // Note the Dekker/Lamport duality: ST _entry_list; MEMBAR; LD Owner. // In this case the ST-MEMBAR is accomplished with CAS() in try_lock_or_add_to_entry_list. @@ -1051,13 +1051,13 @@ void ObjectMonitor::enter_internal(JavaThread* current, ObjectWaiter* current_no } // Try again, but just so we distinguish between futile wakeups and - // successful wakeups. The following test isn't algorithmically + // successful wakeups. The following test isn't algorithmically // necessary, but it helps us maintain sensible statistics. if (try_lock(current) == TryLockResult::Success) { break; } - // The lock is still contested. + // The lock is still contended. if (!reenter_path) { // Assuming this is not a spurious wakeup we'll normally find _succ == current. @@ -1070,9 +1070,9 @@ void ObjectMonitor::enter_internal(JavaThread* current, ObjectWaiter* current_no } // We can find that we were unpark()ed and redesignated _succ while - // we were spinning. That's harmless. If we iterate and call park(), + // we were spinning. That's harmless. If we iterate and call park(), // park() will consume the event and return immediately and we'll - // just spin again. This pattern can repeat, leaving _succ to simply + // just spin again. This pattern can repeat, leaving _succ to simply // spin on a CPU. if (has_successor(current)) { @@ -1092,9 +1092,9 @@ void ObjectMonitor::enter_internal(JavaThread* current, ObjectWaiter* current_no // Current has acquired the lock -- Unlink current from the _entry_list. unlink_after_acquire(current, current_node); if (has_successor(current)) { - clear_successor(); // Note that we don't need to do OrderAccess::fence() after clearing // _succ here, since we own the lock. + clear_successor(); } // We've acquired ownership with CAS(). @@ -1146,7 +1146,9 @@ bool ObjectMonitor::vthread_monitor_enter(JavaThread* current, ObjectWaiter* wai if (try_lock_or_add_to_entry_list(current, node)) { // We got the lock. - if (waiter == nullptr) delete node; // for Object.wait() don't delete yet + if (waiter == nullptr) { + delete node; // for Object.wait() don't delete yet + } dec_unmounted_vthreads(); return true; } @@ -1157,8 +1159,14 @@ bool ObjectMonitor::vthread_monitor_enter(JavaThread* current, ObjectWaiter* wai if (try_lock(current) == TryLockResult::Success) { assert(has_owner(current), "invariant"); unlink_after_acquire(current, node); - if (has_successor(current)) clear_successor(); - if (waiter == nullptr) delete node; // for Object.wait() don't delete yet + if (has_successor(current)) { + // Note that we don't need to do OrderAccess::fence() after clearing + // _succ here, since we own the lock. + clear_successor(); + } + if (waiter == nullptr) { + delete node; // for Object.wait() don't delete yet + } dec_unmounted_vthreads(); return true; } @@ -1182,7 +1190,9 @@ bool ObjectMonitor::resume_operation(JavaThread* current, ObjectWaiter* node, Co if (node->is_wait() && !node->at_reenter()) { bool acquired_monitor = vthread_wait_reenter(current, node, cont); - if (acquired_monitor) return true; + if (acquired_monitor) { + return true; + } } // Retry acquiring monitor... @@ -1196,7 +1206,9 @@ bool ObjectMonitor::resume_operation(JavaThread* current, ObjectWaiter* node, Co } oop vthread = current->vthread(); - if (has_successor(current)) clear_successor(); + if (has_successor(current)) { + clear_successor(); + } // Invariant: after clearing _succ a thread *must* retry acquiring the monitor. OrderAccess::fence(); @@ -1217,7 +1229,11 @@ void ObjectMonitor::vthread_epilog(JavaThread* current, ObjectWaiter* node) { add_to_contentions(-1); dec_unmounted_vthreads(); - if (has_successor(current)) clear_successor(); + if (has_successor(current)) { + // Note that we don't need to do OrderAccess::fence() after clearing + // _succ here, since we own the lock. + clear_successor(); + } guarantee(_recursions == 0, "invariant"); @@ -1419,7 +1435,7 @@ void ObjectMonitor::unlink_after_acquire(JavaThread* current, ObjectWaiter* curr // inopportune) reclamation of "this". // // We'd like to assert that: (THREAD->thread_state() != _thread_blocked) ; -// There's one exception to the claim above, however. enter_internal() can call +// There's one exception to the claim above, however. enter_internal() can call // exit() to drop a lock if the acquirer has been externally suspended. // In that case exit() is called with _thread_state == _thread_blocked, // but the monitor's _contentions field is > 0, which inhibits reclamation. @@ -1507,12 +1523,12 @@ void ObjectMonitor::exit(JavaThread* current, bool not_suspended) { w = entry_list_tail(current); // I'd like to write: guarantee (w->_thread != current). // But in practice an exiting thread may find itself on the entry_list. - // Let's say thread T1 calls O.wait(). Wait() enqueues T1 on O's waitset and - // then calls exit(). Exit release the lock by setting O._owner to null. - // Let's say T1 then stalls. T2 acquires O and calls O.notify(). The + // Let's say thread T1 calls O.wait(). Wait() enqueues T1 on O's waitset and + // then calls exit(). Exit releases the lock by setting O._owner to null. + // Let's say T1 then stalls. T2 acquires O and calls O.notify(). The // notify() operation moves T1 from O's waitset to O's entry_list. T2 then - // release the lock "O". T1 resumes immediately after the ST of null into - // _owner, above. T1 notices that the entry_list is populated, so it + // releases the lock "O". T1 resumes immediately after the ST of null into + // _owner, above. T1 notices that the entry_list is populated, so it // reacquires the lock and then finds itself on the entry_list. // Given all that, we have to tolerate the circumstance where "w" is // associated with current. @@ -1534,26 +1550,26 @@ void ObjectMonitor::exit(JavaThread* current, bool not_suspended) { // Normally the exiting thread is responsible for ensuring succession, // but if this thread observes other successors are ready or other // entering threads are spinning after it has stored null into _owner - // then it can exit without waking a successor. The existence of + // then it can exit without waking a successor. The existence of // spinners or ready successors guarantees proper succession (liveness). - // Responsibility passes to the ready or running successors. The exiting - // thread delegates the duty. More precisely, if a successor already + // Responsibility passes to the ready or running successors. The exiting + // thread delegates the duty. More precisely, if a successor already // exists this thread is absolved of the responsibility of waking // (unparking) one. // The _succ variable is critical to reducing futile wakeup frequency. // _succ identifies the "heir presumptive" thread that has been made - // ready (unparked) but that has not yet run. We need only one such + // ready (unparked) but that has not yet run. We need only one such // successor thread to guarantee progress. // See http://www.usenix.org/events/jvm01/full_papers/dice/dice.pdf // section 3.3 "Futile Wakeup Throttling" for details. // - // Note that spinners in Enter() also set _succ non-null. - // In the current implementation spinners opportunistically set + // Note that spinners in enter(), try_enter_fast() and enter_internal() also + // set _succ non-null. In the current implementation spinners opportunistically set // _succ so that exiting threads might avoid waking a successor. // Which means that the exiting thread could exit immediately without // waking a successor, if it observes a successor after it has dropped - // the lock. Note that the dropped lock needs to become visible to the + // the lock. Note that the dropped lock needs to become visible to the // spinner. if (_entry_list == nullptr || has_successor()) { @@ -1730,7 +1746,7 @@ void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS) { if (JvmtiExport::should_post_monitor_wait()) { JvmtiExport::post_monitor_wait(current, object(), millis); } - // post monitor waited event. Note that this is past-tense, we are done waiting. + // post monitor waited event. Note that this is past-tense, we are done waiting. if (JvmtiExport::should_post_monitor_waited()) { // Note: 'false' parameter is passed here because the // wait was not timed out due to thread interrupt. @@ -1791,9 +1807,9 @@ void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS) { // Enter the waiting queue, which is a circular doubly linked list in this case // but it could be a priority queue or any data structure. - // _wait_set_lock protects the wait queue. Normally the wait queue is accessed only + // _wait_set_lock protects the wait queue. Normally the wait queue is accessed only // by the owner of the monitor *except* in the case where park() - // returns because of a timeout of interrupt. Contention is exceptionally rare + // returns because of a timeout of interrupt. Contention is exceptionally rare // so we use a simple spin-lock instead of a heavier-weight blocking lock. { @@ -1850,7 +1866,7 @@ void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS) { // written by the is thread. (perhaps the fetch might even be satisfied // by a look-aside into the processor's own store buffer, although given // the length of the code path between the prior ST and this load that's - // highly unlikely). If the following LD fetches a stale TS_WAIT value + // highly unlikely). If the following LD fetches a stale TS_WAIT value // then we'll acquire the lock and then re-fetch a fresh TState value. // That is, we fail toward safety. @@ -1868,7 +1884,12 @@ void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS) { // No other threads will asynchronously modify TState. guarantee(node.TState != ObjectWaiter::TS_WAIT, "invariant"); OrderAccess::loadload(); - if (has_successor(current)) clear_successor(); + if (has_successor(current)) { + clear_successor(); + // Note that we do not need a fence here, as, regardless of the path taken, + // there is a fence either in ThreadBlockInVM's destructor or + // right after a call to post_monitor_wait_event(). + } // Reentry phase -- reacquire the monitor. // re-enter contended monitor after object.wait(). @@ -2046,11 +2067,11 @@ bool ObjectMonitor::notify_internal(JavaThread* current) { } } - // _wait_set_lock protects the wait queue, not the entry_list. We could + // _wait_set_lock protects the wait queue, not the entry_list. We could // move the add-to-entry_list operation, above, outside the critical section - // protected by _wait_set_lock. In practice that's not useful. With the + // protected by _wait_set_lock. In practice that's not useful. With the // exception of wait() timeouts and interrupts the monitor owner - // is the only thread that grabs _wait_set_lock. There's almost no contention + // is the only thread that grabs _wait_set_lock. There's almost no contention // on _wait_set_lock so it's not profitable to reduce the length of the // critical section. } @@ -2151,9 +2172,9 @@ void ObjectMonitor::vthread_wait(JavaThread* current, jlong millis, bool interru // Enter the waiting queue, which is a circular doubly linked list in this case // but it could be a priority queue or any data structure. - // _wait_set_lock protects the wait queue. Normally the wait queue is accessed only + // _wait_set_lock protects the wait queue. Normally the wait queue is accessed only // by the owner of the monitor *except* in the case where park() - // returns because of a timeout or interrupt. Contention is exceptionally rare + // returns because of a timeout or interrupt. Contention is exceptionally rare // so we use a simple spin-lock instead of a heavier-weight blocking lock. { @@ -2243,25 +2264,25 @@ bool ObjectMonitor::vthread_wait_reenter(JavaThread* current, ObjectWaiter* node // algorithm. // // Broadly, we can fix the spin frequency -- that is, the % of contended lock -// acquisition attempts where we opt to spin -- at 100% and vary the spin count +// acquisition attempts where we opt to spin -- at 100% and vary the spin count // (duration) or we can fix the count at approximately the duration of -// a context switch and vary the frequency. Of course we could also +// a context switch and vary the frequency. Of course we could also // vary both satisfying K == Frequency * Duration, where K is adaptive by monitor. // For a description of 'Adaptive spin-then-block mutual exclusion in // multi-threaded processing,' see U.S. Pat. No. 8046758. // // This implementation varies the duration "D", where D varies with // the success rate of recent spin attempts. (D is capped at approximately -// length of a round-trip context switch). The success rate for recent +// length of a round-trip context switch). The success rate for recent // spin attempts is a good predictor of the success rate of future spin -// attempts. The mechanism adapts automatically to varying critical +// attempts. The mechanism adapts automatically to varying critical // section length (lock modality), system load and degree of parallelism. // D is maintained per-monitor in _SpinDuration and is initialized -// optimistically. Spin frequency is fixed at 100%. +// optimistically. Spin frequency is fixed at 100%. // // Note that _SpinDuration is volatile, but we update it without locks -// or atomics. The code is designed so that _SpinDuration stays within -// a reasonable range even in the presence of races. The arithmetic +// or atomics. The code is designed so that _SpinDuration stays within +// a reasonable range even in the presence of races. The arithmetic // operations on _SpinDuration are closed over the domain of legal values, // so at worst a race will install and older but still legal value. // At the very worst this introduces some apparent non-determinism. @@ -2269,28 +2290,28 @@ bool ObjectMonitor::vthread_wait_reenter(JavaThread* current, ObjectWaiter* node // count are relatively short, even in the worst case, the effect is harmless. // // Care must be taken that a low "D" value does not become an -// an absorbing state. Transient spinning failures -- when spinning +// an absorbing state. Transient spinning failures -- when spinning // is overall profitable -- should not cause the system to converge -// on low "D" values. We want spinning to be stable and predictable +// on low "D" values. We want spinning to be stable and predictable // and fairly responsive to change and at the same time we don't want // it to oscillate, become metastable, be "too" non-deterministic, // or converge on or enter undesirable stable absorbing states. // // We implement a feedback-based control system -- using past behavior -// to predict future behavior. We face two issues: (a) if the +// to predict future behavior. We face two issues: (a) if the // input signal is random then the spin predictor won't provide optimal // results, and (b) if the signal frequency is too high then the control // system, which has some natural response lag, will "chase" the signal. -// (b) can arise from multimodal lock hold times. Transient preemption +// (b) can arise from multimodal lock hold times. Transient preemption // can also result in apparent bimodal lock hold times. // Although sub-optimal, neither condition is particularly harmful, as // in the worst-case we'll spin when we shouldn't or vice-versa. // The maximum spin duration is rather short so the failure modes aren't bad. // To be conservative, I've tuned the gain in system to bias toward -// _not spinning. Relatedly, the system can sometimes enter a mode where it -// "rings" or oscillates between spinning and not spinning. This happens +// _not spinning. Relatedly, the system can sometimes enter a mode where it +// "rings" or oscillates between spinning and not spinning. This happens // when spinning is just on the cusp of profitability, however, so the -// situation is not dire. The state is benign -- there's no need to add +// situation is not dire. The state is benign -- there's no need to add // hysteresis control to damp the transition rate between spinning and // not spinning. @@ -2322,7 +2343,9 @@ inline static int adjust_down(int spin_duration) { // Consider an AIMD scheme like: x -= (x >> 3) + 100 // This is globally sample and tends to damp the response. x -= Knob_Penalty; - if (x < 0) { x = 0; } + if (x < 0) { + x = 0; + } return x; } else { return spin_duration; @@ -2348,7 +2371,7 @@ bool ObjectMonitor::short_fixed_spin(JavaThread* current, int spin_count, bool a // Spinning: Fixed frequency (100%), vary duration bool ObjectMonitor::try_spin(JavaThread* current) { - // Dumb, brutal spin. Good for comparative measurements against adaptive spinning. + // Dumb, brutal spin. Good for comparative measurements against adaptive spinning. int knob_fixed_spin = Knob_FixedSpin; // 0 (don't spin: default), 2000 good test if (knob_fixed_spin > 0) { return short_fixed_spin(current, knob_fixed_spin, false); @@ -2357,7 +2380,7 @@ bool ObjectMonitor::try_spin(JavaThread* current) { // Admission control - verify preconditions for spinning // // We always spin a little bit, just to prevent _SpinDuration == 0 from - // becoming an absorbing state. Put another way, we spin briefly to + // becoming an absorbing state. Put another way, we spin briefly to // sample, just in case the system load, parallelism, contention, or lock // modality changed. @@ -2369,7 +2392,7 @@ bool ObjectMonitor::try_spin(JavaThread* current) { // // Consider the following alternative: // Periodically set _SpinDuration = _SpinLimit and try a long/full - // spin attempt. "Periodically" might mean after a tally of + // spin attempt. "Periodically" might mean after a tally of // the # of failed spin attempts (or iterations) reaches some threshold. // This takes us into the realm of 1-out-of-N spinning, where we // hold the duration constant but vary the frequency. @@ -2416,9 +2439,9 @@ bool ObjectMonitor::try_spin(JavaThread* current) { // If this thread observes the monitor transition or flicker // from locked to unlocked to locked, then the odds that this // thread will acquire the lock in this spin attempt go down - // considerably. The same argument applies if the CAS fails + // considerably. The same argument applies if the CAS fails // or if we observe _owner change from one non-null value to - // another non-null value. In such cases we might abort + // another non-null value. In such cases we might abort // the spin without prejudice or apply a "penalty" to the // spin count-down variable "ctr", reducing it by 100, say. @@ -2429,6 +2452,8 @@ bool ObjectMonitor::try_spin(JavaThread* current) { // The CAS succeeded -- this thread acquired ownership // Take care of some bookkeeping to exit spin state. if (has_successor(current)) { + // Note that we don't need to do OrderAccess::fence() after clearing + // _succ here, since we own the lock. clear_successor(); } @@ -2470,7 +2495,7 @@ bool ObjectMonitor::try_spin(JavaThread* current) { if (has_successor(current)) { clear_successor(); // Invariant: after setting succ=null a contending thread - // must recheck-retry _owner before parking. This usually happens + // must recheck-retry _owner before parking. This usually happens // in the normal usage of try_spin(), but it's safest // to make try_spin() as foolproof as possible. OrderAccess::fence(); From 0dfa22f27d71808c5a777c073a2a3acdd4c13945 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Wed, 1 Apr 2026 09:08:54 +0000 Subject: [PATCH 098/116] 8381397: G1: Inline initiate_conc_mark/record_conc_mark_init_end Reviewed-by: ayang, iwalulya --- src/hotspot/share/gc/g1/g1Policy.cpp | 21 +++++---------------- src/hotspot/share/gc/g1/g1Policy.hpp | 8 -------- 2 files changed, 5 insertions(+), 24 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1Policy.cpp b/src/hotspot/share/gc/g1/g1Policy.cpp index 24a82113d20..b1c9f3a5b6f 100644 --- a/src/hotspot/share/gc/g1/g1Policy.cpp +++ b/src/hotspot/share/gc/g1/g1Policy.cpp @@ -690,11 +690,6 @@ void G1Policy::record_young_collection_start() { assert(_g1h->collection_set()->verify_young_ages(), "region age verification failed"); } -void G1Policy::record_concurrent_mark_init_end() { - assert(!collector_state()->initiate_conc_mark_if_possible(), "we should have cleared it by now"); - collector_state()->set_in_normal_young_gc(); -} - void G1Policy::record_concurrent_mark_remark_end() { double end_time_sec = os::elapsedTime(); double start_time_sec = cur_pause_start_sec(); @@ -795,7 +790,8 @@ void G1Policy::record_young_collection_end(bool concurrent_operation_is_full_mar bool is_young_only_pause = G1CollectorState::is_young_only_pause(this_pause); if (G1CollectorState::is_concurrent_start_pause(this_pause)) { - record_concurrent_mark_init_end(); + assert(!collector_state()->initiate_conc_mark_if_possible(), "we should have cleared it by now"); + collector_state()->set_in_normal_young_gc(); } else { maybe_start_marking(allocation_word_size); } @@ -1245,10 +1241,6 @@ bool G1Policy::force_concurrent_start_if_outside_cycle(GCCause::Cause gc_cause) } } -void G1Policy::initiate_conc_mark() { - collector_state()->set_in_concurrent_start_gc(); -} - static const char* requester_for_mixed_abort(GCCause::Cause cause) { if (cause == GCCause::_wb_breakpoint) { return "run_to breakpoint"; @@ -1283,22 +1275,19 @@ void G1Policy::decide_on_concurrent_start_pause() { log_debug(gc, ergo)("Do not initiate concurrent cycle (whitebox controlled)"); } else if (!about_to_start_mixed_phase() && collector_state()->is_in_young_only_phase()) { // Initiate a new concurrent start if there is no marking or reclamation going on. - initiate_conc_mark(); + collector_state()->set_in_concurrent_start_gc(); log_debug(gc, ergo)("Initiate concurrent cycle (concurrent cycle initiation requested)"); } else if (_g1h->is_user_requested_concurrent_full_gc(cause) || GCCause::is_codecache_requested_gc(cause) || (cause == GCCause::_wb_breakpoint)) { - // Initiate a concurrent start. A concurrent start must be a young only - // GC, so the collector state must be updated to reflect this. - collector_state()->set_in_normal_young_gc(); - + // Force concurrent start. + collector_state()->set_in_concurrent_start_gc(); // We might have ended up coming here about to start a mixed phase with a collection set // active. The following remark might change the change the "evacuation efficiency" of // the regions in this set, leading to failing asserts later. // Since the concurrent cycle will recreate the collection set anyway, simply drop it here. abandon_collection_set_candidates(); abort_time_to_mixed_tracking(); - initiate_conc_mark(); log_debug(gc, ergo)("Initiate concurrent cycle (%s requested concurrent cycle)", requester_for_mixed_abort(cause)); } else { diff --git a/src/hotspot/share/gc/g1/g1Policy.hpp b/src/hotspot/share/gc/g1/g1Policy.hpp index bcc3bceda49..5c5c2bc3572 100644 --- a/src/hotspot/share/gc/g1/g1Policy.hpp +++ b/src/hotspot/share/gc/g1/g1Policy.hpp @@ -313,9 +313,6 @@ class G1Policy: public CHeapObj { void record_full_collection_start(); void record_full_collection_end(size_t allocation_word_size); - // Must currently be called while the world is stopped. - void record_concurrent_mark_init_end(); - void record_concurrent_mark_remark_end(); // Record start, end, and completion of cleanup. @@ -332,11 +329,6 @@ class G1Policy: public CHeapObj { // regions and update the associated members. void update_survival_estimates_for_next_collection(); - // Set the state to start a concurrent marking cycle and clear - // _initiate_conc_mark_if_possible because it has now been - // acted on. - void initiate_conc_mark(); - public: // This sets the initiate_conc_mark_if_possible() flag to start a // new cycle, as long as we are not already in one. It's best if it From e340aeeee010baf2773fd0d50ce59aa55a823de3 Mon Sep 17 00:00:00 2001 From: Guanqiang Han Date: Wed, 1 Apr 2026 09:12:51 +0000 Subject: [PATCH 099/116] 8379174: G1: Too high G1RemSetArrayOfCardsEntriesBase causes invalid ergonomic G1RemSetArrayOfCardsEntries Reviewed-by: tschatzl, iwalulya --- src/hotspot/share/gc/g1/g1Arguments.cpp | 3 +- ...tG1RemSetArrayOfCardsEntriesErgoLimit.java | 43 +++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 test/hotspot/jtreg/gc/g1/TestG1RemSetArrayOfCardsEntriesErgoLimit.java diff --git a/src/hotspot/share/gc/g1/g1Arguments.cpp b/src/hotspot/share/gc/g1/g1Arguments.cpp index 8bec6e7e86f..c3bbd5a3b52 100644 --- a/src/hotspot/share/gc/g1/g1Arguments.cpp +++ b/src/hotspot/share/gc/g1/g1Arguments.cpp @@ -148,8 +148,9 @@ void G1Arguments::initialize_card_set_configuration() { if (FLAG_IS_DEFAULT(G1RemSetArrayOfCardsEntries)) { uint max_cards_in_inline_ptr = G1CardSetConfiguration::max_cards_in_inline_ptr(G1HeapRegion::LogCardsPerRegion); + const JVMTypedFlagLimit* limit = JVMFlagLimit::get_range_at(FLAG_MEMBER_ENUM(G1RemSetArrayOfCardsEntries))->cast(); FLAG_SET_ERGO(G1RemSetArrayOfCardsEntries, MAX2(max_cards_in_inline_ptr * 2, - G1RemSetArrayOfCardsEntriesBase << region_size_log_mb)); + MIN2(G1RemSetArrayOfCardsEntriesBase << region_size_log_mb, limit->max()))); } // Howl card set container globals. diff --git a/test/hotspot/jtreg/gc/g1/TestG1RemSetArrayOfCardsEntriesErgoLimit.java b/test/hotspot/jtreg/gc/g1/TestG1RemSetArrayOfCardsEntriesErgoLimit.java new file mode 100644 index 00000000000..4af09066def --- /dev/null +++ b/test/hotspot/jtreg/gc/g1/TestG1RemSetArrayOfCardsEntriesErgoLimit.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 8379174 + * @summary Test for G1 ergonomics deriving an out-of-range + * G1RemSetArrayOfCardsEntries value from G1RemSetArrayOfCardsEntriesBase + * @requires vm.gc.G1 + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions + * -XX:+UseG1GC + * -XX:G1RemSetArrayOfCardsEntriesBase=62117 + * -XX:G1HeapRegionSize=4m + * ${test.main.class} + */ + +package gc.g1; + +public class TestG1RemSetArrayOfCardsEntriesErgoLimit { + public static void main(String[] args) { + System.out.println("passed"); + } +} From 2caf253017d00f758a038a16ba9d64d52dd1c202 Mon Sep 17 00:00:00 2001 From: Martin Doerr Date: Wed, 1 Apr 2026 09:20:10 +0000 Subject: [PATCH 100/116] 8381412: [PPC64] unproblemlist JDK-8320897 Reviewed-by: mbaesken --- test/hotspot/jtreg/ProblemList.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index 3b871d9f4b6..d4efaa7e631 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -56,7 +56,7 @@ compiler/c2/irTests/TestDuplicateBackedge.java 8318904 generic-all compiler/codecache/jmx/PoolsIndependenceTest.java 8264632 macosx-all -compiler/vectorapi/reshape/TestVectorReinterpret.java 8320897,8348519 aix-ppc64,linux-ppc64le,linux-s390x +compiler/vectorapi/reshape/TestVectorReinterpret.java 8348519 linux-s390x compiler/vectorapi/VectorRebracket128Test.java 8330538 generic-all compiler/vectorization/TestVectorAlgorithms.java#noSuperWord 8376803 aix-ppc64,linux-s390x From 3459f6b124c34f3187050495e34c690c017a0687 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eirik=20Bj=C3=B8rsn=C3=B8s?= Date: Wed, 1 Apr 2026 09:50:37 +0000 Subject: [PATCH 101/116] 8380452: ZipOutputStream::putNextEntry(ZipEntry) throws unspecified IllegalArgumentException for unmappable entry name Reviewed-by: jpai, lancea, alanb --- .../java/util/zip/ZipOutputStream.java | 21 ++++- .../UnmappableZipEntryNameOrComment.java | 76 +++++++++++++++++++ 2 files changed, 93 insertions(+), 4 deletions(-) create mode 100644 test/jdk/java/util/zip/ZipOutputStream/UnmappableZipEntryNameOrComment.java diff --git a/src/java.base/share/classes/java/util/zip/ZipOutputStream.java b/src/java.base/share/classes/java/util/zip/ZipOutputStream.java index 47499858a37..4ea4a103fef 100644 --- a/src/java.base/share/classes/java/util/zip/ZipOutputStream.java +++ b/src/java.base/share/classes/java/util/zip/ZipOutputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -257,6 +257,11 @@ public void putNextEntry(ZipEntry e) throws IOException { default: throw new ZipException("unsupported compression method"); } + // Verify that entry name and comment can be encoded + byte[] nameBytes = checkEncodable(e.name, "unmappable character in ZIP entry name"); + if (e.comment != null) { + checkEncodable(e.comment, "unmappable character in ZIP entry comment"); + } if (! names.add(e.name)) { throw new ZipException("duplicate entry: " + e.name); } @@ -270,7 +275,16 @@ public void putNextEntry(ZipEntry e) throws IOException { } current = new XEntry(e, written); xentries.add(current); - writeLOC(current); + writeLOC(current, nameBytes); + } + + // Throws ZipException if the given string cannot be encoded + private byte[] checkEncodable(String str, String msg) throws ZipException { + try { + return zc.getBytes(str); + } catch (IllegalArgumentException ex) { + throw (ZipException) new ZipException(msg).initCause(ex); + } } /** @@ -424,7 +438,7 @@ public void close() throws IOException { /* * Writes local file (LOC) header for specified entry. */ - private void writeLOC(XEntry xentry) throws IOException { + private void writeLOC(XEntry xentry, byte[] nameBytes) throws IOException { ZipEntry e = xentry.entry; int flag = e.flag; boolean hasZip64 = false; @@ -461,7 +475,6 @@ private void writeLOC(XEntry xentry) throws IOException { writeInt(e.size); // uncompressed size } } - byte[] nameBytes = zc.getBytes(e.name); writeShort(nameBytes.length); int elenEXTT = 0; // info-zip extended timestamp diff --git a/test/jdk/java/util/zip/ZipOutputStream/UnmappableZipEntryNameOrComment.java b/test/jdk/java/util/zip/ZipOutputStream/UnmappableZipEntryNameOrComment.java new file mode 100644 index 00000000000..af08de2adcf --- /dev/null +++ b/test/jdk/java/util/zip/ZipOutputStream/UnmappableZipEntryNameOrComment.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.zip.ZipEntry; +import java.util.zip.ZipException; +import java.util.zip.ZipOutputStream; + +import static java.io.OutputStream.nullOutputStream; +import static org.junit.jupiter.api.Assertions.assertThrows; + +/* @test + * @bug 8380452 + * @summary Unmappable characters in ZipEntry name or comment should be rejected with ZipException + * @run junit ${test.main.class} + */ +public class UnmappableZipEntryNameOrComment { + + // Charset used by any ZipOutputStream in this test + static final Charset CHARSET = StandardCharsets.US_ASCII; + // 'ø' is an unmappable character in US_ASCII + static final String UNMAPPABLE = "\u00f8"; + + /** + * Verify that calling ZipOutputStream.putNextEntry with an unmappable ZipEntry + * name is rejected with a ZipException. + * + * @throws IOException if an unexpected IO error occurs + */ + @Test + void rejectUnmappableZipEntryName() throws IOException { + ZipEntry e = new ZipEntry(UNMAPPABLE); + try (var out = new ZipOutputStream(nullOutputStream(), CHARSET)) { + assertThrows(ZipException.class, () -> out.putNextEntry(e)); + } + } + + /** + * Verify that calling ZipOutputStream.putNextEntry with an unmappable ZipEntry + * comment is rejected with a ZipException. + * + * @throws IOException if an unexpected IO error occurs + */ + @Test + void rejectUnmappableZipEntryComment() throws IOException { + ZipEntry e = new ZipEntry("file.txt"); + e.setComment(UNMAPPABLE); + try (var out = new ZipOutputStream(nullOutputStream(), CHARSET)) { + assertThrows(ZipException.class, () -> out.putNextEntry(e)); + } + } +} From 92b1d8237ec0feaba44ff875cdd92fbb78896eae Mon Sep 17 00:00:00 2001 From: Liam Miller-Cushon Date: Wed, 1 Apr 2026 10:10:03 +0000 Subject: [PATCH 102/116] 8380147: Don't require a CompilationUnit for end position APIs Reviewed-by: vromero --- .../sun/source/util/DocSourcePositions.java | 59 +++++++++++++++++- .../com/sun/source/util/SourcePositions.java | 53 +++++++++++++++- .../com/sun/tools/javac/api/JavacTrees.java | 8 +-- .../internal/doclets/toolkit/util/Utils.java | 2 +- .../jdk/javadoc/internal/doclint/Env.java | 2 +- .../jdk/javadoc/internal/tool/JavadocLog.java | 4 +- .../shellsupport/doc/JavadocHelper.java | 62 +++++++++---------- .../jdk/jshell/SourceCodeAnalysisImpl.java | 30 ++++----- .../classes/jdk/jshell/TreeDissector.java | 4 +- 9 files changed, 163 insertions(+), 61 deletions(-) diff --git a/src/jdk.compiler/share/classes/com/sun/source/util/DocSourcePositions.java b/src/jdk.compiler/share/classes/com/sun/source/util/DocSourcePositions.java index 520943c464d..d0afd126bf6 100644 --- a/src/jdk.compiler/share/classes/com/sun/source/util/DocSourcePositions.java +++ b/src/jdk.compiler/share/classes/com/sun/source/util/DocSourcePositions.java @@ -28,6 +28,7 @@ import com.sun.source.doctree.DocCommentTree; import com.sun.source.doctree.DocTree; import com.sun.source.tree.CompilationUnitTree; +import com.sun.source.tree.Tree; /** * Provides methods to obtain the position of a DocTree within a javadoc comment. @@ -59,8 +60,31 @@ public interface DocSourcePositions extends SourcePositions { * position is being sought * @param tree tree for which a position is sought * @return the start position of tree + * @deprecated use {@link #getStartPosition(DocCommentTree, DocTree)} instead */ - long getStartPosition(CompilationUnitTree file, DocCommentTree comment, DocTree tree); + @Deprecated(since = "27", forRemoval = true) + default long getStartPosition(CompilationUnitTree file, DocCommentTree comment, DocTree tree) { + return getStartPosition(comment, tree); + } + + /** + * {@return the starting position of the given {@link Tree}. If the starting position is not available, returns + * {@link javax.tools.Diagnostic#NOPOS}} + * + *

The given tree should be under the given comment tree. The returned position must be at the start of the + * yield of this tree, that is for any sub-tree of this tree, the following must hold: + * + *

+ * {@code getStartPosition(comment, tree) <= getStartPosition(comment, subtree)} or
+ * {@code getStartPosition(comment, tree) == NOPOS} or
+ * {@code getStartPosition(comment, subtree) == NOPOS} + *

+ * + * @param comment the comment tree that encloses the tree for which the + * position is being sought + * @param tree tree for which a position is sought + */ + long getStartPosition(DocCommentTree comment, DocTree tree); /** * Returns the ending position of the tree within the comment within the file. If tree is not found within @@ -91,7 +115,38 @@ public interface DocSourcePositions extends SourcePositions { * position is being sought * @param tree tree for which a position is sought * @return the end position of tree + * @deprecated use {@link #getEndPosition(DocCommentTree, DocTree)} instead + */ + @Deprecated(since = "27", forRemoval = true) + default long getEndPosition(CompilationUnitTree file, DocCommentTree comment, DocTree tree) { + return getEndPosition(comment, tree); + } + + /** + * {@return the ending position of the given {@link Tree}. If the ending position is not available, returns + * {@link javax.tools.Diagnostic#NOPOS}} + * + *

The given tree should be under the given comment tree. The returned position must be at the end of the yield + * of this tree, that is for any sub-tree of this tree, the following must hold: + * + *

+ * {@code getEndPosition(comment, tree) >= getEndPosition(comment, subtree)} or
+ * {@code getEndPosition(comment, tree) == NOPOS} or
+ * {@code getEndPosition(comment, subtree) == NOPOS} + *

+ * + * In addition, the following must hold: + * + *

+ * {@code getStartPosition(comment, tree) <= getEndPosition(comment, tree)} or
+ * {@code getStartPosition(comment, tree) == NOPOS} or
+ * {@code getEndPosition(comment, tree) == NOPOS} + *

+ * + * @param comment the comment tree that encloses the tree for which the + * position is being sought + * @param tree tree for which a position is sought */ - long getEndPosition(CompilationUnitTree file, DocCommentTree comment, DocTree tree); + long getEndPosition(DocCommentTree comment, DocTree tree); } diff --git a/src/jdk.compiler/share/classes/com/sun/source/util/SourcePositions.java b/src/jdk.compiler/share/classes/com/sun/source/util/SourcePositions.java index b6112fd32e6..460f4f2a1ce 100644 --- a/src/jdk.compiler/share/classes/com/sun/source/util/SourcePositions.java +++ b/src/jdk.compiler/share/classes/com/sun/source/util/SourcePositions.java @@ -53,8 +53,29 @@ public interface SourcePositions { * @param file CompilationUnit in which to find tree * @param tree tree for which a position is sought * @return the start position of tree + * @deprecated use {@link #getStartPosition(Tree)} instead */ - long getStartPosition(CompilationUnitTree file, Tree tree); + @Deprecated(since = "27", forRemoval = true) + default long getStartPosition(CompilationUnitTree file, Tree tree) { + return getStartPosition(tree); + } + + /** + * {@return the starting position of the given {@link Tree}, or if the starting position is not available, returns + * {@link javax.tools.Diagnostic#NOPOS}} + * + *

The returned position must be at the start of the yield of this tree, that is for any sub-tree of this tree, + * the following must hold: + * + *

+ * {@code getStartPosition(tree) <= getStartPosition(subtree)} or
+ * {@code getStartPosition(tree) == NOPOS} or
+ * {@code getStartPosition(subtree) == NOPOS} + *

+ * + * @param tree tree for which a position is sought + */ + long getStartPosition(Tree tree); /** * Returns the ending position of tree within file. If tree is not found within @@ -80,7 +101,35 @@ public interface SourcePositions { * @param file CompilationUnit in which to find tree * @param tree tree for which a position is sought * @return the end position of tree + * @deprecated use {@link #getEndPosition(Tree)} instead */ - long getEndPosition(CompilationUnitTree file, Tree tree); + @Deprecated(since = "27", forRemoval = true) + default long getEndPosition(CompilationUnitTree file, Tree tree) { + return getEndPosition(tree); + } + /** + * {@return the ending position of the given {@link Tree}. If the ending position is not available, + * returns {@link javax.tools.Diagnostic#NOPOS}} + * + *

The returned position must be at the end of the yield of this tree, that is for any sub-tree of this tree, + * the following must hold: + * + *

+ * {@code getEndPosition(tree) >= getEndPosition(subtree)} or
+ * {@code getEndPosition(tree) == NOPOS} or
+ * {@code getEndPosition(subtree) == NOPOS} + *

+ * + * In addition, the following must hold: + * + *

+ * {@code getStartPosition(tree) <= getEndPosition(tree)} or
+ * {@code getStartPosition(tree) == NOPOS} or
+ * {@code getEndPosition(tree) == NOPOS} + *

+ * + * @param tree tree for which a position is sought + */ + long getEndPosition(Tree tree); } 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 ecd7f5b101a..41dd904bc8a 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 @@ -233,24 +233,24 @@ public BreakIterator getBreakIterator() { public DocSourcePositions getSourcePositions() { return new DocSourcePositions() { @Override @DefinedBy(Api.COMPILER_TREE) - public long getStartPosition(CompilationUnitTree file, Tree tree) { + public long getStartPosition(Tree tree) { return TreeInfo.getStartPos((JCTree) tree); } @Override @DefinedBy(Api.COMPILER_TREE) - public long getEndPosition(CompilationUnitTree file, Tree tree) { + public long getEndPosition(Tree tree) { return TreeInfo.getEndPos((JCTree) tree); } @Override @DefinedBy(Api.COMPILER_TREE) - public long getStartPosition(CompilationUnitTree file, DocCommentTree comment, DocTree tree) { + public long getStartPosition(DocCommentTree comment, DocTree tree) { DCDocComment dcComment = (DCDocComment) comment; DCTree dcTree = (DCTree) tree; return dcComment.getSourcePosition(dcTree.getStartPosition()); } @Override @DefinedBy(Api.COMPILER_TREE) - public long getEndPosition(CompilationUnitTree file, DocCommentTree comment, DocTree tree) { + public long getEndPosition(DocCommentTree comment, DocTree tree) { DCDocComment dcComment = (DCDocComment) comment; DCTree dcTree = (DCTree) tree; return dcComment.getSourcePosition(dcTree.getEndPosition()); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java index ddadd33a18b..0b3b767ea39 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java @@ -1618,7 +1618,7 @@ public long getLineNumber(Element e) { CompilationUnitTree cu = path.getCompilationUnit(); LineMap lineMap = cu.getLineMap(); DocSourcePositions spos = docTrees.getSourcePositions(); - long pos = spos.getStartPosition(cu, path.getLeaf()); + long pos = spos.getStartPosition(path.getLeaf()); return lineMap.getLineNumber(pos); } 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 f2940963f17..ba7f68cccf6 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 @@ -211,7 +211,7 @@ long getPos(TreePath p) { long getStartPos(TreePath p) { SourcePositions sp = trees.getSourcePositions(); - return sp.getStartPosition(p.getCompilationUnit(), p.getLeaf()); + return sp.getStartPosition(p.getLeaf()); } boolean shouldCheck(CompilationUnitTree unit) { 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 b3bf1c14cb1..39bc58dff59 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 @@ -582,9 +582,9 @@ private DiagnosticPosition getDiagnosticPosition(Element element) { } CompilationUnitTree compUnit = tp.getCompilationUnit(); JCTree tree = (JCTree) tp.getLeaf(); - int start = (int) posns.getStartPosition(compUnit, tree); + int start = (int) posns.getStartPosition(tree); int pos = tree.getPreferredPosition(); - int end = (int) posns.getEndPosition(compUnit, tree); + int end = (int) posns.getEndPosition(tree); return createDiagnosticPosition(tree, start, pos, end); } diff --git a/src/jdk.jshell/share/classes/jdk/internal/shellsupport/doc/JavadocHelper.java b/src/jdk.jshell/share/classes/jdk/internal/shellsupport/doc/JavadocHelper.java index 7a1dd6c9877..112808420bc 100644 --- a/src/jdk.jshell/share/classes/jdk/internal/shellsupport/doc/JavadocHelper.java +++ b/src/jdk.jshell/share/classes/jdk/internal/shellsupport/doc/JavadocHelper.java @@ -543,9 +543,9 @@ public Void visitReturn(ReturnTree node, Void p) { for (DocTree t : inheritedText.get(0)) { start = Math.min(start, - sp.getStartPosition(null, inheritedDocTree, t) - offset); + sp.getStartPosition(inheritedDocTree, t) - offset); end = Math.max(end, - sp.getEndPosition(null, inheritedDocTree, t) - offset); + sp.getEndPosition(inheritedDocTree, t) - offset); } String text = end >= 0 ? inherited.substring((int) start, (int) end) : ""; @@ -559,8 +559,8 @@ public Void visitReturn(ReturnTree node, Void p) { } else { //replace the {@inheritDoc} with the full text from //the overridden method: - long inheritedStart = sp.getStartPosition(null, dcTree, node); - long inheritedEnd = sp.getEndPosition(null, dcTree, node); + long inheritedStart = sp.getStartPosition(dcTree, node); + long inheritedEnd = sp.getEndPosition(dcTree, node); int[] span = new int[] {(int) inheritedStart, (int) inheritedEnd}; replace.computeIfAbsent(span, s -> new ArrayList<>()) @@ -571,11 +571,11 @@ public Void visitReturn(ReturnTree node, Void p) { } @Override public Void visitLink(LinkTree node, Void p) { - if (sp.isRewrittenTree(null, dcTree, node)) { + if (sp.isRewrittenTree(dcTree, node)) { //this link is a synthetic rewritten link, replace //the original span with the new link: - int start = (int) sp.getStartPosition(null, dcTree, node); - int end = (int) sp.getEndPosition(null, dcTree, node); + int start = (int) sp.getStartPosition(dcTree, node); + int end = (int) sp.getEndPosition(dcTree, node); replace.computeIfAbsent(new int[] {start, end}, _ -> new ArrayList<>()) .add(node.toString()); @@ -601,7 +601,7 @@ public Void scan(DocTree tree, Void p) { //this tree) //if there is a newline immediately behind this tree, insert behind //the newline: - long endPos = sp.getEndPosition(null, dcTree, tree); + long endPos = sp.getEndPosition(dcTree, tree); if (endPos >= offset) { if (endPos - offset + 1 < docComment.length() && docComment.charAt((int) (endPos - offset + 1)) == '\n') { @@ -744,7 +744,7 @@ public CharSequence getCharContent(boolean ignoreEncodingErrors) } }; DocCommentTree tree = trees.getDocCommentTree(fo); - offset += (int) trees.getSourcePositions().getStartPosition(null, tree, tree); + offset += (int) trees.getSourcePositions().getStartPosition(tree, tree); return Pair.of(tree, offset); } catch (URISyntaxException ex) { throw new IllegalStateException(ex); @@ -939,7 +939,7 @@ private static JoinedMarkdown joinMarkdown(SyntheticAwareTreeDocSourcePositions Iterable trees) { StringBuilder sourceBuilder = new StringBuilder(); List replaceSpans = new ArrayList<>(); - int currentSpanStart = (int) sp.getStartPosition(null, comment, trees.iterator().next()); + int currentSpanStart = (int) sp.getStartPosition(comment, trees.iterator().next()); DocTree lastTree = null; for (DocTree tree : trees) { @@ -958,8 +958,8 @@ private static JoinedMarkdown joinMarkdown(SyntheticAwareTreeDocSourcePositions } sourceBuilder.append(code); } else { - int treeStart = (int) sp.getStartPosition(null, comment, tree); - int treeEnd = (int) sp.getEndPosition(null, comment, tree); + int treeStart = (int) sp.getStartPosition(comment, tree); + int treeEnd = (int) sp.getEndPosition(comment, tree); replaceSpans.add(new int[] {currentSpanStart, treeStart}); currentSpanStart = treeEnd; sourceBuilder.append(PLACEHOLDER); @@ -967,7 +967,7 @@ private static JoinedMarkdown joinMarkdown(SyntheticAwareTreeDocSourcePositions lastTree = tree; } - int end = (int) sp.getEndPosition(null, comment, lastTree); + int end = (int) sp.getEndPosition(comment, lastTree); replaceSpans.add(new int[] {currentSpanStart, end}); @@ -1006,8 +1006,8 @@ public SyntheticAwareTreeDocSourcePositions(DocSourcePositions delegate) { } @Override - public long getStartPosition(CompilationUnitTree file, DocCommentTree comment, DocTree tree) { - ensureAdjustedSpansFilled(file, comment, tree); + public long getStartPosition(DocCommentTree comment, DocTree tree) { + ensureAdjustedSpansFilled(comment, tree); long[] adjusted = adjustedSpan.get(tree); @@ -1015,12 +1015,12 @@ public long getStartPosition(CompilationUnitTree file, DocCommentTree comment, D return adjusted[0]; } - return delegate.getStartPosition(file, comment, tree); + return delegate.getStartPosition(comment, tree); } @Override - public long getEndPosition(CompilationUnitTree file, DocCommentTree comment, DocTree tree) { - ensureAdjustedSpansFilled(file, comment, tree); + public long getEndPosition(DocCommentTree comment, DocTree tree) { + ensureAdjustedSpansFilled(comment, tree); long[] adjusted = adjustedSpan.get(tree); @@ -1028,28 +1028,26 @@ public long getEndPosition(CompilationUnitTree file, DocCommentTree comment, Doc return adjusted[1]; } - return delegate.getEndPosition(file, comment, tree); + return delegate.getEndPosition(comment, tree); } @Override - public long getStartPosition(CompilationUnitTree file, Tree tree) { - return delegate.getStartPosition(file, tree); + public long getStartPosition(Tree tree) { + return delegate.getStartPosition(tree); } @Override - public long getEndPosition(CompilationUnitTree file, Tree tree) { - return delegate.getEndPosition(file, tree); + public long getEndPosition(Tree tree) { + return delegate.getEndPosition(tree); } - boolean isRewrittenTree(CompilationUnitTree file, - DocCommentTree comment, + boolean isRewrittenTree(DocCommentTree comment, DocTree tree) { - ensureAdjustedSpansFilled(file, comment, tree); + ensureAdjustedSpansFilled(comment, tree); return rewrittenTrees.contains(tree); } - private void ensureAdjustedSpansFilled(CompilationUnitTree file, - DocCommentTree comment, + private void ensureAdjustedSpansFilled(DocCommentTree comment, DocTree tree) { if (tree.getKind() != DocTree.Kind.LINK && tree.getKind() != DocTree.Kind.LINK_PLAIN) { @@ -1057,7 +1055,7 @@ private void ensureAdjustedSpansFilled(CompilationUnitTree file, } long[] span; - long treeStart = delegate.getStartPosition(file, comment, tree); + long treeStart = delegate.getStartPosition(comment, tree); if (treeStart == (-1)) { LinkTree link = (LinkTree) tree; @@ -1069,15 +1067,15 @@ private void ensureAdjustedSpansFilled(CompilationUnitTree file, for (DocTree t : nested) { start = Math.min(start, - delegate.getStartPosition(file, comment, t)); + delegate.getStartPosition(comment, t)); end = Math.max(end, - delegate.getEndPosition(file, comment, t)); + delegate.getEndPosition(comment, t)); } span = new long[] {(int) start - 1, (int) end + 1}; rewrittenTrees.add(tree); } else { - long treeEnd = delegate.getEndPosition(file, comment, tree); + long treeEnd = delegate.getEndPosition(comment, tree); span = new long[] {treeStart, treeEnd}; } diff --git a/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java b/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java index 35faab231af..215b412003d 100644 --- a/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java +++ b/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java @@ -464,7 +464,7 @@ private List computeSuggestions(OuterWrap code, String ImportTree it = findImport(tp); if (it != null && it.isModule()) { - int selectStart = (int) sp.getStartPosition(topLevel, tp.getLeaf()); + int selectStart = (int) sp.getStartPosition(tp.getLeaf()); String qualifiedPrefix = it.getQualifiedIdentifier().getKind() == Kind.MEMBER_SELECT ? ((MemberSelectTree) it.getQualifiedIdentifier()).getExpression().toString() + "." : ""; @@ -634,7 +634,7 @@ private List computeSuggestions(OuterWrap code, String Element annotationType = tp.getParentPath().getParentPath().getLeaf().getKind() == Kind.ANNOTATION ? at.trees().getElement(tp.getParentPath().getParentPath()) : at.trees().getElement(tp.getParentPath().getParentPath().getParentPath()); - if (sp.getEndPosition(topLevel, tp.getParentPath().getLeaf()) == (-1)) { + if (sp.getEndPosition(tp.getParentPath().getLeaf()) == (-1)) { //synthetic 'value': //TODO: filter out existing: addElements(javadoc, ElementFilter.methodsIn(annotationType.getEnclosedElements()), TRUE, TRUE, cursor, prefix, result); @@ -846,14 +846,14 @@ public List highlights(String snippet) { new TreePathScanner() { @Override public Void visitIdentifier(IdentifierTree node, Void p) { - long start = sp.getStartPosition(cut, node); - long end = sp.getEndPosition(cut, node); + long start = sp.getStartPosition(node); + long end = sp.getEndPosition(node); handleElement(false, start, end); return super.visitIdentifier(node, p); } @Override public Void visitMemberSelect(MemberSelectTree node, Void p) { - long exprEnd = sp.getEndPosition(cut, node.getExpression()); + long exprEnd = sp.getEndPosition(node.getExpression()); Token ident = findTokensFrom(exprEnd, TokenKind.DOT, TokenKind.IDENTIFIER); if (ident != null) { handleElement(false, ident.pos, ident.endPos); @@ -866,16 +866,16 @@ public Void visitClass(ClassTree node, Void p) { if (mods.getFlags().contains(Modifier.SEALED) || mods.getFlags().contains(Modifier.NON_SEALED)) { List modifierTokens = new ArrayList<>(); - long modsStart = sp.getStartPosition(cut, mods); - long modsEnd = sp.getEndPosition(cut, mods); + long modsStart = sp.getStartPosition(mods); + long modsEnd = sp.getEndPosition(mods); for (Token t : tokens) { if (t.pos >= modsStart && t.endPos <= modsEnd) { modifierTokens.add(t); } } for (AnnotationTree at : mods.getAnnotations()) { - long annStart = sp.getStartPosition(cut, at); - long annEnd = sp.getEndPosition(cut, at); + long annStart = sp.getStartPosition(at); + long annEnd = sp.getEndPosition(at); modifierTokens.removeIf(t -> t.pos >= annStart && t.endPos <= annEnd); } OUTER: for (int i = 0; i < modifierTokens.size(); i++) { @@ -912,7 +912,7 @@ public Void visitClass(ClassTree node, Void p) { handleElement(true, ident.pos, ident.endPos); } if (!node.getPermitsClause().isEmpty()) { - long start = sp.getStartPosition(cut, node.getPermitsClause().get(0)); + long start = sp.getStartPosition(node.getPermitsClause().get(0)); Token permitsCandidate = findTokensBefore(start, TokenKind.IDENTIFIER); if (permitsCandidate != null && permitsCandidate.name().contentEquals("permits")) { addKeyword.accept(permitsCandidate); @@ -946,7 +946,7 @@ public Void visitVariable(VariableTree node, Void p) { } @Override public Void visitYield(YieldTree node, Void p) { - long start = sp.getStartPosition(cut, node); + long start = sp.getStartPosition(node); Token yield = findTokensFrom(start, TokenKind.IDENTIFIER); addKeyword.accept(yield); return super.visitYield(node, p); @@ -961,7 +961,7 @@ public Void visitErroneous(ErroneousTree node, Void p) { @Override public Void scan(Tree tree, Void p) { if (tree != null) { - long end = sp.getEndPosition(cut, tree); + long end = sp.getEndPosition(tree); if (end == (-1)) { //synthetic return null; @@ -1072,14 +1072,14 @@ public Void scan(Tree tree, Void p) { if (tree == null) return null; - long start = sp.getStartPosition(topLevel, tree); - long end = sp.getEndPosition(topLevel, tree); + long start = sp.getStartPosition(tree); + long end = sp.getEndPosition(tree); if (end == (-1) && tree.getKind() == Kind.ASSIGNMENT && getCurrentPath() != null && getCurrentPath().getLeaf().getKind() == Kind.ANNOTATION) { //the assignment is synthetically generated, take the end pos of the nested tree: - end = sp.getEndPosition(topLevel, ((AssignmentTree) tree).getExpression()); + end = sp.getEndPosition(((AssignmentTree) tree).getExpression()); } if (start <= wrapEndPos && wrapEndPos <= end && (deepest[0] == null || deepest[0].getLeaf() == getCurrentPath().getLeaf())) { diff --git a/src/jdk.jshell/share/classes/jdk/jshell/TreeDissector.java b/src/jdk.jshell/share/classes/jdk/jshell/TreeDissector.java index ef50f8ce71c..e5817f84206 100644 --- a/src/jdk.jshell/share/classes/jdk/jshell/TreeDissector.java +++ b/src/jdk.jshell/share/classes/jdk/jshell/TreeDissector.java @@ -119,11 +119,11 @@ SourcePositions getSourcePositions() { } int getStartPosition(Tree tree) { - return (int) getSourcePositions().getStartPosition(targetCompilationUnit, tree); + return (int) getSourcePositions().getStartPosition(tree); } int getEndPosition(Tree tree) { - return (int) getSourcePositions().getEndPosition(targetCompilationUnit, tree); + return (int) getSourcePositions().getEndPosition(tree); } Range treeToRange(Tree tree) { From 7df06d1489164e7668e5ca43ba256c76acc7bd33 Mon Sep 17 00:00:00 2001 From: Emanuel Peter Date: Wed, 1 Apr 2026 12:18:29 +0000 Subject: [PATCH 103/116] 8379395: [VectorAlgorithms] new dot-product implementation using fma Reviewed-by: mchevalier, chagedorn --- .../vectorization/TestVectorAlgorithms.java | 12 ++++++++++++ .../vectorization/VectorAlgorithmsImpl.java | 15 +++++++++++++++ .../bench/vm/compiler/VectorAlgorithms.java | 5 +++++ .../bench/vm/compiler/VectorAlgorithmsImpl.java | 15 +++++++++++++++ 4 files changed, 47 insertions(+) diff --git a/test/hotspot/jtreg/compiler/vectorization/TestVectorAlgorithms.java b/test/hotspot/jtreg/compiler/vectorization/TestVectorAlgorithms.java index 2667ac59471..70dc9a4a0b4 100644 --- a/test/hotspot/jtreg/compiler/vectorization/TestVectorAlgorithms.java +++ b/test/hotspot/jtreg/compiler/vectorization/TestVectorAlgorithms.java @@ -122,6 +122,7 @@ public TestVectorAlgorithms () { testGroups.get("dotProductF").put("dotProductF_loop", i -> { return dotProductF_loop(d.aF, d.bF); }); testGroups.get("dotProductF").put("dotProductF_VectorAPI_naive", i -> { return dotProductF_VectorAPI_naive(d.aF, d.bF); }); testGroups.get("dotProductF").put("dotProductF_VectorAPI_reduction_after_loop", i -> { return dotProductF_VectorAPI_reduction_after_loop(d.aF, d.bF); }); + testGroups.get("dotProductF").put("dotProductF_VectorAPI_fma", i -> { return dotProductF_VectorAPI_fma(d.aF, d.bF); }); testGroups.put("hashCodeB", new HashMap()); testGroups.get("hashCodeB").put("hashCodeB_loop", i -> { return hashCodeB_loop(d.aB); }); @@ -192,6 +193,7 @@ public TestVectorAlgorithms () { "dotProductF_loop", "dotProductF_VectorAPI_naive", "dotProductF_VectorAPI_reduction_after_loop", + "dotProductF_VectorAPI_fma", "hashCodeB_loop", "hashCodeB_Arrays", "hashCodeB_VectorAPI_v1", @@ -409,6 +411,16 @@ public float dotProductF_VectorAPI_reduction_after_loop(float[] a, float[] b) { return VectorAlgorithmsImpl.dotProductF_VectorAPI_reduction_after_loop(a, b); } + @Test + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", + IRNode.ADD_REDUCTION_V, "> 0", + IRNode.FMA_VF, "> 0"}, + applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseSuperWord", "true"}) + public float dotProductF_VectorAPI_fma(float[] a, float[] b) { + return VectorAlgorithmsImpl.dotProductF_VectorAPI_fma(a, b); + } + @Test public int hashCodeB_loop(byte[] a) { return VectorAlgorithmsImpl.hashCodeB_loop(a); diff --git a/test/hotspot/jtreg/compiler/vectorization/VectorAlgorithmsImpl.java b/test/hotspot/jtreg/compiler/vectorization/VectorAlgorithmsImpl.java index 8276d90509f..e4c9eb74e7d 100644 --- a/test/hotspot/jtreg/compiler/vectorization/VectorAlgorithmsImpl.java +++ b/test/hotspot/jtreg/compiler/vectorization/VectorAlgorithmsImpl.java @@ -348,6 +348,21 @@ public static float dotProductF_VectorAPI_reduction_after_loop(float[] a, float[ return sum; } + public static float dotProductF_VectorAPI_fma(float[] a, float[] b) { + var sums = FloatVector.broadcast(SPECIES_F, 0.0f); + int i; + for (i = 0; i < SPECIES_F.loopBound(a.length); i += SPECIES_F.length()) { + var va = FloatVector.fromArray(SPECIES_F, a, i); + var vb = FloatVector.fromArray(SPECIES_F, b, i); + sums = va.fma(vb, sums); + } + float sum = sums.reduceLanes(VectorOperators.ADD); + for (; i < a.length; i++) { + sum = Math.fma(a[i], b[i], sum); + } + return sum; + } + public static int hashCodeB_loop(byte[] a) { int h = 1; for (int i = 0; i < a.length; i++) { diff --git a/test/micro/org/openjdk/bench/vm/compiler/VectorAlgorithms.java b/test/micro/org/openjdk/bench/vm/compiler/VectorAlgorithms.java index f60dfcb2d7c..0a6aa03586b 100644 --- a/test/micro/org/openjdk/bench/vm/compiler/VectorAlgorithms.java +++ b/test/micro/org/openjdk/bench/vm/compiler/VectorAlgorithms.java @@ -165,6 +165,11 @@ public float dotProductF_VectorAPI_reduction_after_loop() { return VectorAlgorithmsImpl.dotProductF_VectorAPI_reduction_after_loop(d.aF, d.bF); } + @Benchmark + public float dotProductF_VectorAPI_fma() { + return VectorAlgorithmsImpl.dotProductF_VectorAPI_fma(d.aF, d.bF); + } + @Benchmark public int hashCodeB_loop() { return VectorAlgorithmsImpl.hashCodeB_loop(d.aB); diff --git a/test/micro/org/openjdk/bench/vm/compiler/VectorAlgorithmsImpl.java b/test/micro/org/openjdk/bench/vm/compiler/VectorAlgorithmsImpl.java index 3ae4ed81634..0d33a109d5b 100644 --- a/test/micro/org/openjdk/bench/vm/compiler/VectorAlgorithmsImpl.java +++ b/test/micro/org/openjdk/bench/vm/compiler/VectorAlgorithmsImpl.java @@ -348,6 +348,21 @@ public static float dotProductF_VectorAPI_reduction_after_loop(float[] a, float[ return sum; } + public static float dotProductF_VectorAPI_fma(float[] a, float[] b) { + var sums = FloatVector.broadcast(SPECIES_F, 0.0f); + int i; + for (i = 0; i < SPECIES_F.loopBound(a.length); i += SPECIES_F.length()) { + var va = FloatVector.fromArray(SPECIES_F, a, i); + var vb = FloatVector.fromArray(SPECIES_F, b, i); + sums = va.fma(vb, sums); + } + float sum = sums.reduceLanes(VectorOperators.ADD); + for (; i < a.length; i++) { + sum = Math.fma(a[i], b[i], sum); + } + return sum; + } + public static int hashCodeB_loop(byte[] a) { int h = 1; for (int i = 0; i < a.length; i++) { From 9607a7284d5858aee735c7a0db36c88d5d2a3a24 Mon Sep 17 00:00:00 2001 From: Emanuel Peter Date: Wed, 1 Apr 2026 12:18:49 +0000 Subject: [PATCH 104/116] 8380513: [VectorAlgorithms] mismatch benchmark and test Reviewed-by: mchevalier, galder, chagedorn --- .../vectorization/TestVectorAlgorithms.java | 38 ++++++++++ .../vectorization/VectorAlgorithmsImpl.java | 72 +++++++++++++++++++ .../bench/vm/compiler/VectorAlgorithms.java | 20 ++++++ .../vm/compiler/VectorAlgorithmsImpl.java | 72 +++++++++++++++++++ 4 files changed, 202 insertions(+) diff --git a/test/hotspot/jtreg/compiler/vectorization/TestVectorAlgorithms.java b/test/hotspot/jtreg/compiler/vectorization/TestVectorAlgorithms.java index 70dc9a4a0b4..ec1b43dd3f2 100644 --- a/test/hotspot/jtreg/compiler/vectorization/TestVectorAlgorithms.java +++ b/test/hotspot/jtreg/compiler/vectorization/TestVectorAlgorithms.java @@ -143,6 +143,12 @@ public TestVectorAlgorithms () { testGroups.get("findI").put("findI_loop", i -> { return findI_loop(d.aI, d.eI_findI[i]); }); testGroups.get("findI").put("findI_VectorAPI", i -> { return findI_VectorAPI(d.aI, d.eI_findI[i]); }); + testGroups.put("mismatchB", new HashMap()); + testGroups.get("mismatchB").put("mismatchB_loop", i -> { return d.wrap_mismatchB(i, TestVectorAlgorithms::mismatchB_loop); }); + testGroups.get("mismatchB").put("mismatchB_Arrays", i -> { return d.wrap_mismatchB(i, TestVectorAlgorithms::mismatchB_Arrays); }); + testGroups.get("mismatchB").put("mismatchB_MemorySegment", i -> { return d.wrap_mismatchB(i, TestVectorAlgorithms::mismatchB_MemorySegment); }); + testGroups.get("mismatchB").put("mismatchB_VectorAPI", i -> { return d.wrap_mismatchB(i, TestVectorAlgorithms::mismatchB_VectorAPI); }); + testGroups.put("reverseI", new HashMap()); testGroups.get("reverseI").put("reverseI_loop", i -> { return reverseI_loop(d.aI, d.rI1); }); testGroups.get("reverseI").put("reverseI_VectorAPI", i -> { return reverseI_VectorAPI(d.aI, d.rI2); }); @@ -205,6 +211,10 @@ public TestVectorAlgorithms () { "findMinIndexI_VectorAPI", "findI_loop", "findI_VectorAPI", + "mismatchB_loop", + "mismatchB_Arrays", + "mismatchB_MemorySegment", + "mismatchB_VectorAPI", "reverseI_loop", "reverseI_VectorAPI", "filterI_loop", @@ -521,6 +531,34 @@ public int findI_VectorAPI(int[] a, int e) { return VectorAlgorithmsImpl.findI_VectorAPI(a, e); } + @Test + @IR(counts = {IRNode.LOAD_VECTOR_B, "= 0"}) + // Currently does not vectorize, but might in the future. + public static int mismatchB_loop(byte[] a, byte[] b) { + return VectorAlgorithmsImpl.mismatchB_loop(a, b); + } + + @Test + // Inlining makes IR rules difficult. Just keep this as a correctness test. + public static int mismatchB_Arrays(byte[] a, byte[] b) { + return VectorAlgorithmsImpl.mismatchB_Arrays(a, b); + } + + @Test + // Inlining makes IR rules difficult. Just keep this as a correctness test. + public static int mismatchB_MemorySegment(byte[] a, byte[] b) { + return VectorAlgorithmsImpl.mismatchB_MemorySegment(a, b); + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", + IRNode.VECTOR_MASK_CMP, "> 0", + IRNode.VECTOR_TEST, "> 0"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}) + public static int mismatchB_VectorAPI(byte[] a, byte[] b) { + return VectorAlgorithmsImpl.mismatchB_VectorAPI(a, b); + } + @Test @IR(counts = {IRNode.LOAD_VECTOR_I, "= 0", IRNode.STORE_VECTOR, "= 0"}) diff --git a/test/hotspot/jtreg/compiler/vectorization/VectorAlgorithmsImpl.java b/test/hotspot/jtreg/compiler/vectorization/VectorAlgorithmsImpl.java index e4c9eb74e7d..c06473d26c5 100644 --- a/test/hotspot/jtreg/compiler/vectorization/VectorAlgorithmsImpl.java +++ b/test/hotspot/jtreg/compiler/vectorization/VectorAlgorithmsImpl.java @@ -26,6 +26,7 @@ import java.util.Arrays; import java.util.Random; +import java.lang.foreign.MemorySegment; import jdk.incubator.vector.*; /** @@ -94,6 +95,15 @@ public static class Data { public int[] oopsX4; public int[] memX4; + // Input for mismatchB + // We set m1B and m2B to have identical data, temporarily edit m2B at one position, + // run the mismatch implementation, and then reset that position. This means we + // perform as little mutation while randomizing the input data. + public byte[] m1B; + public byte[] m2B; + public int[] mismatchB_idx; + public int mismatchB_idx_idx = 0; + public Data(int size, int seed, int numX4Objects, float branchProbability) { Random random = new Random(seed); @@ -165,6 +175,30 @@ public Data(int size, int seed, int numX4Objects, float branchProbability) { ? (byte)(random.nextInt(16) + 'A') : (byte)(random.nextInt(16) + 'a'); } + + // Input data for mismatchB + m1B = new byte[size]; + m2B = new byte[size]; + random.nextBytes(m1B); + System.arraycopy(m1B, 0, m2B, 0, size); + + mismatchB_idx = new int[0x10000]; + for (int i = 0; i < mismatchB_idx.length; i++) { + // Sometimes make no mutation (-1), sometimes pick index for mutation. + mismatchB_idx[i] = (random.nextInt(10) == 0) ? -1 : random.nextInt(m1B.length); + } + } + + public interface MismatchBImpl { + int run(byte[] a, byte[] b); + } + + public int wrap_mismatchB(int idx, MismatchBImpl impl) { + int i = mismatchB_idx[idx & 0xffff]; + if (i != -1) { m2B[i]++; } + int res = impl.run(m1B, m2B); + if (i != -1) { m2B[i]--; } + return res; } } @@ -671,6 +705,44 @@ public static int findI_VectorAPI(int[] a, int e) { return -1; } + public static int mismatchB_loop(byte[] a, byte[] b) { + for (int i = 0; i < a.length; i++) { + if (a[i] != b[i]) { + return i; + } + } + return -1; + } + + public static int mismatchB_Arrays(byte[] a, byte[] b) { + return Arrays.mismatch(a, b); + } + + public static int mismatchB_MemorySegment(byte[] a, byte[] b) { + var aMS = MemorySegment.ofArray(a); + var bMS = MemorySegment.ofArray(b); + return (int) aMS.mismatch(bMS); + } + + public static int mismatchB_VectorAPI(byte[] a, byte[] b) { + int i = 0; + for (; i < SPECIES_B.loopBound(a.length); i += SPECIES_B.length()) { + ByteVector va = ByteVector.fromArray(SPECIES_B, a, i); + ByteVector vb = ByteVector.fromArray(SPECIES_B, b, i); + var mask = va.compare(VectorOperators.NE, vb); + if (mask.anyTrue()) { + return i + mask.firstTrue(); + } + } + for (; i < a.length; i++) { + if (a[i] != b[i]) { + return i; + } + } + return -1; + } + + public static Object reverseI_loop(int[] a, int[] r) { for (int i = 0; i < a.length; i++) { r[a.length - i - 1] = a[i]; diff --git a/test/micro/org/openjdk/bench/vm/compiler/VectorAlgorithms.java b/test/micro/org/openjdk/bench/vm/compiler/VectorAlgorithms.java index 0a6aa03586b..8f5d83c4ae3 100644 --- a/test/micro/org/openjdk/bench/vm/compiler/VectorAlgorithms.java +++ b/test/micro/org/openjdk/bench/vm/compiler/VectorAlgorithms.java @@ -232,6 +232,26 @@ public int findI_VectorAPI() { return VectorAlgorithmsImpl.findI_VectorAPI(d.aI, e); } + @Benchmark + public int mismatchB_loop() { + return d.wrap_mismatchB(d.mismatchB_idx_idx++, VectorAlgorithmsImpl::mismatchB_loop); + } + + @Benchmark + public int mismatchB_Arrays() { + return d.wrap_mismatchB(d.mismatchB_idx_idx++, VectorAlgorithmsImpl::mismatchB_Arrays); + } + + @Benchmark + public int mismatchB_MemorySegment() { + return d.wrap_mismatchB(d.mismatchB_idx_idx++, VectorAlgorithmsImpl::mismatchB_MemorySegment); + } + + @Benchmark + public int mismatchB_VectorAPI() { + return d.wrap_mismatchB(d.mismatchB_idx_idx++, VectorAlgorithmsImpl::mismatchB_VectorAPI); + } + @Benchmark public Object reverseI_loop() { return VectorAlgorithmsImpl.reverseI_loop(d.aI, d.rI1); diff --git a/test/micro/org/openjdk/bench/vm/compiler/VectorAlgorithmsImpl.java b/test/micro/org/openjdk/bench/vm/compiler/VectorAlgorithmsImpl.java index 0d33a109d5b..a60ecc0f41a 100644 --- a/test/micro/org/openjdk/bench/vm/compiler/VectorAlgorithmsImpl.java +++ b/test/micro/org/openjdk/bench/vm/compiler/VectorAlgorithmsImpl.java @@ -26,6 +26,7 @@ import java.util.Arrays; import java.util.Random; +import java.lang.foreign.MemorySegment; import jdk.incubator.vector.*; /** @@ -94,6 +95,15 @@ public static class Data { public int[] oopsX4; public int[] memX4; + // Input for mismatchB + // We set m1B and m2B to have identical data, temporarily edit m2B at one position, + // run the mismatch implementation, and then reset that position. This means we + // perform as little mutation while randomizing the input data. + public byte[] m1B; + public byte[] m2B; + public int[] mismatchB_idx; + public int mismatchB_idx_idx = 0; + public Data(int size, int seed, int numX4Objects, float branchProbability) { Random random = new Random(seed); @@ -165,6 +175,30 @@ public Data(int size, int seed, int numX4Objects, float branchProbability) { ? (byte)(random.nextInt(16) + 'A') : (byte)(random.nextInt(16) + 'a'); } + + // Input data for mismatchB + m1B = new byte[size]; + m2B = new byte[size]; + random.nextBytes(m1B); + System.arraycopy(m1B, 0, m2B, 0, size); + + mismatchB_idx = new int[0x10000]; + for (int i = 0; i < mismatchB_idx.length; i++) { + // Sometimes make no mutation (-1), sometimes pick index for mutation. + mismatchB_idx[i] = (random.nextInt(10) == 0) ? -1 : random.nextInt(m1B.length); + } + } + + public interface MismatchBImpl { + int run(byte[] a, byte[] b); + } + + public int wrap_mismatchB(int idx, MismatchBImpl impl) { + int i = mismatchB_idx[idx & 0xffff]; + if (i != -1) { m2B[i]++; } + int res = impl.run(m1B, m2B); + if (i != -1) { m2B[i]--; } + return res; } } @@ -671,6 +705,44 @@ public static int findI_VectorAPI(int[] a, int e) { return -1; } + public static int mismatchB_loop(byte[] a, byte[] b) { + for (int i = 0; i < a.length; i++) { + if (a[i] != b[i]) { + return i; + } + } + return -1; + } + + public static int mismatchB_Arrays(byte[] a, byte[] b) { + return Arrays.mismatch(a, b); + } + + public static int mismatchB_MemorySegment(byte[] a, byte[] b) { + var aMS = MemorySegment.ofArray(a); + var bMS = MemorySegment.ofArray(b); + return (int) aMS.mismatch(bMS); + } + + public static int mismatchB_VectorAPI(byte[] a, byte[] b) { + int i = 0; + for (; i < SPECIES_B.loopBound(a.length); i += SPECIES_B.length()) { + ByteVector va = ByteVector.fromArray(SPECIES_B, a, i); + ByteVector vb = ByteVector.fromArray(SPECIES_B, b, i); + var mask = va.compare(VectorOperators.NE, vb); + if (mask.anyTrue()) { + return i + mask.firstTrue(); + } + } + for (; i < a.length; i++) { + if (a[i] != b[i]) { + return i; + } + } + return -1; + } + + public static Object reverseI_loop(int[] a, int[] r) { for (int i = 0; i < a.length; i++) { r[a.length - i - 1] = a[i]; From f3a1c67b1cc2db2d6b3c0519737a6519ea4fbeea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20H=C3=BCbner?= Date: Wed, 1 Apr 2026 13:03:01 +0000 Subject: [PATCH 105/116] 8381464: Typo in Linker::captureCallState JavaDoc Reviewed-by: liach, pminborg --- src/java.base/share/classes/java/lang/foreign/Linker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java.base/share/classes/java/lang/foreign/Linker.java b/src/java.base/share/classes/java/lang/foreign/Linker.java index 1a7d33266aa..f597e4ee52e 100644 --- a/src/java.base/share/classes/java/lang/foreign/Linker.java +++ b/src/java.base/share/classes/java/lang/foreign/Linker.java @@ -833,7 +833,7 @@ static Option firstVariadicArg(int index) { *

* Captured state can be stored in, or retrieved from the capture state segment by * constructing var handles from the {@linkplain #captureStateLayout capture state layout}. - * Some functions require this state the be initialized to a particular value before + * Some functions require this state to be initialized to a particular value before * invoking the downcall. *

* The following example demonstrates the use of this linker option: From d2c1907349afcbc40b2626060960511e2dca01d4 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Wed, 1 Apr 2026 14:20:53 +0000 Subject: [PATCH 106/116] 8381466: G1: Fix outdated name in G1Policy::decide_on_concurrent_start_pause Reviewed-by: tschatzl --- src/hotspot/share/gc/g1/g1Policy.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/gc/g1/g1Policy.cpp b/src/hotspot/share/gc/g1/g1Policy.cpp index b1c9f3a5b6f..5744bbc2f03 100644 --- a/src/hotspot/share/gc/g1/g1Policy.cpp +++ b/src/hotspot/share/gc/g1/g1Policy.cpp @@ -1256,7 +1256,7 @@ void G1Policy::decide_on_concurrent_start_pause() { // We are about to decide on whether this pause will be a // concurrent start pause. - // First, collector_state()->in_concurrent_start_gc() should not be already set. We + // First, collector_state()->is_in_concurrent_start_gc() should not already be set. We // will set it here if we have to. However, it should be cleared by // the end of the pause (it's only set for the duration of a // concurrent start pause). From 3fba38ab74aafab07e2cbec5f159e0d4cccaa440 Mon Sep 17 00:00:00 2001 From: Mikael Vidstedt Date: Wed, 1 Apr 2026 16:51:28 +0000 Subject: [PATCH 107/116] 8373521: Bump minimum boot jdk to JDK 26 Reviewed-by: liach, darcy, iris, erikj --- make/conf/github-actions.conf | 20 ++++++++++---------- make/conf/jib-profiles.js | 4 ++-- make/conf/version-numbers.conf | 4 ++-- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/make/conf/github-actions.conf b/make/conf/github-actions.conf index ebfc9191535..6771e8923dc 100644 --- a/make/conf/github-actions.conf +++ b/make/conf/github-actions.conf @@ -29,21 +29,21 @@ GTEST_VERSION=1.14.0 JTREG_VERSION=8.2.1+1 LINUX_X64_BOOT_JDK_EXT=tar.gz -LINUX_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk25/bd75d5f9689641da8e1daabeccb5528b/36/GPL/openjdk-25_linux-x64_bin.tar.gz -LINUX_X64_BOOT_JDK_SHA256=59cdcaf255add4721de38eb411d4ecfe779356b61fb671aee63c7dec78054c2b +LINUX_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk26/c3cc523845074aa0af4f5e1e1ed4151d/35/GPL/openjdk-26_linux-x64_bin.tar.gz +LINUX_X64_BOOT_JDK_SHA256=83c78367f8c81257beef72aca4bbbf8e6dac8ca2b3a4546a85879a09e6e4e128 ALPINE_LINUX_X64_BOOT_JDK_EXT=tar.gz -ALPINE_LINUX_X64_BOOT_JDK_URL=https://github.com/adoptium/temurin25-binaries/releases/download/jdk-25%2B36/OpenJDK25U-jdk_x64_alpine-linux_hotspot_25_36.tar.gz -ALPINE_LINUX_X64_BOOT_JDK_SHA256=637e47474d411ed86134f413af7d5fef4180ddb0bf556347b7e74a88cf8904c8 +ALPINE_LINUX_X64_BOOT_JDK_URL=https://github.com/adoptium/temurin26-binaries/releases/download/jdk-26%2B35/OpenJDK26U-jdk_x64_alpine-linux_hotspot_26_35.tar.gz +ALPINE_LINUX_X64_BOOT_JDK_SHA256=c105e581fdccb4e7120d889235d1ad8d5b2bed0af4972bc881e0a8ba687c94a4 MACOS_AARCH64_BOOT_JDK_EXT=tar.gz -MACOS_AARCH64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk25/bd75d5f9689641da8e1daabeccb5528b/36/GPL/openjdk-25_macos-aarch64_bin.tar.gz -MACOS_AARCH64_BOOT_JDK_SHA256=2006337bf326fdfdf6117081751ba38c1c8706d63419ecac7ff102ff7c776876 +MACOS_AARCH64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk26/c3cc523845074aa0af4f5e1e1ed4151d/35/GPL/openjdk-26_macos-aarch64_bin.tar.gz +MACOS_AARCH64_BOOT_JDK_SHA256=254586bcd1bf6dcd125ad667ac32562cb1e2ab1abf3a61fb117b6fabb571e765 MACOS_X64_BOOT_JDK_EXT=tar.gz -MACOS_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk25/bd75d5f9689641da8e1daabeccb5528b/36/GPL/openjdk-25_macos-x64_bin.tar.gz -MACOS_X64_BOOT_JDK_SHA256=47482ad9888991ecac9b2bcc131e2b53ff78aff275104cef85f66252308e8a09 +MACOS_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk26/c3cc523845074aa0af4f5e1e1ed4151d/35/GPL/openjdk-26_macos-x64_bin.tar.gz +MACOS_X64_BOOT_JDK_SHA256=8642b89d889c14ede2c446fd5bbe3621c8a3082e3df02013fd1658e39f52929a WINDOWS_X64_BOOT_JDK_EXT=zip -WINDOWS_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk25/bd75d5f9689641da8e1daabeccb5528b/36/GPL/openjdk-25_windows-x64_bin.zip -WINDOWS_X64_BOOT_JDK_SHA256=85bcc178461e2cb3c549ab9ca9dfa73afd54c09a175d6510d0884071867137d3 +WINDOWS_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk26/c3cc523845074aa0af4f5e1e1ed4151d/35/GPL/openjdk-26_windows-x64_bin.zip +WINDOWS_X64_BOOT_JDK_SHA256=2dd2d92c9374cd49a120fe9d916732840bf6bb9f0e0cc29794917a3c08b99c5f diff --git a/make/conf/jib-profiles.js b/make/conf/jib-profiles.js index 76a94b7789e..4c1d2835054 100644 --- a/make/conf/jib-profiles.js +++ b/make/conf/jib-profiles.js @@ -387,8 +387,8 @@ var getJibProfilesCommon = function (input, data) { }; }; - common.boot_jdk_version = "25"; - common.boot_jdk_build_number = "37"; + common.boot_jdk_version = "26"; + common.boot_jdk_build_number = "35"; common.boot_jdk_home = input.get("boot_jdk", "install_path") + "/jdk-" + common.boot_jdk_version + (input.build_os == "macosx" ? ".jdk/Contents/Home" : ""); diff --git a/make/conf/version-numbers.conf b/make/conf/version-numbers.conf index 4392d86ac33..4f63179ae05 100644 --- a/make/conf/version-numbers.conf +++ b/make/conf/version-numbers.conf @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2026, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -37,6 +37,6 @@ DEFAULT_VERSION_DATE=2026-09-15 DEFAULT_VERSION_CLASSFILE_MAJOR=71 # "`$EXPR $DEFAULT_VERSION_FEATURE + 44`" DEFAULT_VERSION_CLASSFILE_MINOR=0 DEFAULT_VERSION_DOCS_API_SINCE=11 -DEFAULT_ACCEPTABLE_BOOT_VERSIONS="25 26 27" +DEFAULT_ACCEPTABLE_BOOT_VERSIONS="26 27" DEFAULT_JDK_SOURCE_TARGET_VERSION=27 DEFAULT_PROMOTED_VERSION_PRE=ea From eed91689f347e1e0491c4197ede680ef17d01062 Mon Sep 17 00:00:00 2001 From: Ioi Lam Date: Wed, 1 Apr 2026 17:10:40 +0000 Subject: [PATCH 108/116] 8381117: AOT training run fails if memory for ConstantPool is reused Reviewed-by: asmehra, iveresov, kvn --- .../share/cds/aotLinkedClassBulkLoader.cpp | 4 + src/hotspot/share/cds/aotMetaspace.cpp | 13 +- src/hotspot/share/cds/heapShared.cpp | 11 +- src/hotspot/share/cds/heapShared.hpp | 1 + .../share/classfile/classLoaderData.cpp | 4 +- src/hotspot/share/oops/instanceKlass.cpp | 1 + .../aotCache/RedefineClassesInProfile.java | 178 ++++++++++++++++++ .../test-classes/RedefGeneration0.java | 75 ++++++++ .../test-classes/RedefGeneration1.java | 54 ++++++ .../runtime/cds/appcds/test-classes/Util.java | 5 +- 10 files changed, 336 insertions(+), 10 deletions(-) create mode 100644 test/hotspot/jtreg/runtime/cds/appcds/aotCache/RedefineClassesInProfile.java create mode 100644 test/hotspot/jtreg/runtime/cds/appcds/aotCache/test-classes/RedefGeneration0.java create mode 100644 test/hotspot/jtreg/runtime/cds/appcds/aotCache/test-classes/RedefGeneration1.java diff --git a/src/hotspot/share/cds/aotLinkedClassBulkLoader.cpp b/src/hotspot/share/cds/aotLinkedClassBulkLoader.cpp index 6a60177fc40..8129e6a5a81 100644 --- a/src/hotspot/share/cds/aotLinkedClassBulkLoader.cpp +++ b/src/hotspot/share/cds/aotLinkedClassBulkLoader.cpp @@ -280,6 +280,10 @@ void AOTLinkedClassBulkLoader::init_non_javabase_classes_impl(TRAPS) { tty->print_cr("==================== archived_training_data ** after all classes preloaded ===================="); TrainingData::print_archived_training_data_on(tty); } + LogStreamHandle(Info, aot, training, data) log; + if (log.is_enabled()) { + TrainingData::print_archived_training_data_on(&log); + } } // For the AOT cache to function properly, all classes in the AOTLinkedClassTable diff --git a/src/hotspot/share/cds/aotMetaspace.cpp b/src/hotspot/share/cds/aotMetaspace.cpp index 55e9f93b3ab..4c23ede9cb8 100644 --- a/src/hotspot/share/cds/aotMetaspace.cpp +++ b/src/hotspot/share/cds/aotMetaspace.cpp @@ -949,11 +949,18 @@ void AOTMetaspace::dump_static_archive(TRAPS) { ResourceMark rm(THREAD); HandleMark hm(THREAD); - if (CDSConfig::is_dumping_final_static_archive() && AOTPrintTrainingInfo) { - tty->print_cr("==================== archived_training_data ** before dumping ===================="); - TrainingData::print_archived_training_data_on(tty); + if (CDSConfig::is_dumping_final_static_archive()) { + if (AOTPrintTrainingInfo) { + tty->print_cr("==================== archived_training_data ** before dumping ===================="); + TrainingData::print_archived_training_data_on(tty); + } + LogStreamHandle(Info, aot, training, data) log; + if (log.is_enabled()) { + TrainingData::print_archived_training_data_on(&log); + } } + StaticArchiveBuilder builder; dump_static_archive_impl(builder, THREAD); if (HAS_PENDING_EXCEPTION) { diff --git a/src/hotspot/share/cds/heapShared.cpp b/src/hotspot/share/cds/heapShared.cpp index f721b4b370c..d75816656b0 100644 --- a/src/hotspot/share/cds/heapShared.cpp +++ b/src/hotspot/share/cds/heapShared.cpp @@ -689,11 +689,6 @@ class MetaspaceObjToOopHandleTable: public HashTablepool_holder()->class_loader_data())) { _scratch_objects_table->set_oop(src, dest); } @@ -703,6 +698,12 @@ objArrayOop HeapShared::scratch_resolved_references(ConstantPool* src) { return (objArrayOop)_scratch_objects_table->get_oop(src); } +void HeapShared::remove_scratch_resolved_references(ConstantPool* src) { + if (CDSConfig::is_dumping_heap()) { + _scratch_objects_table->remove_oop(src); + } +} + void HeapShared::init_dumping() { _scratch_objects_table = new (mtClass)MetaspaceObjToOopHandleTable(); _pending_roots = new GrowableArrayCHeap(500); diff --git a/src/hotspot/share/cds/heapShared.hpp b/src/hotspot/share/cds/heapShared.hpp index c3ad1f666b1..10ea35ab56e 100644 --- a/src/hotspot/share/cds/heapShared.hpp +++ b/src/hotspot/share/cds/heapShared.hpp @@ -451,6 +451,7 @@ class HeapShared: AllStatic { static void write_heap(AOTMappedHeapInfo* mapped_heap_info, AOTStreamedHeapInfo* streamed_heap_info) NOT_CDS_JAVA_HEAP_RETURN; static objArrayOop scratch_resolved_references(ConstantPool* src); static void add_scratch_resolved_references(ConstantPool* src, objArrayOop dest) NOT_CDS_JAVA_HEAP_RETURN; + static void remove_scratch_resolved_references(ConstantPool* src) NOT_CDS_JAVA_HEAP_RETURN; static void init_dumping() NOT_CDS_JAVA_HEAP_RETURN; static void init_scratch_objects_for_basic_type_mirrors(TRAPS) NOT_CDS_JAVA_HEAP_RETURN; static void init_box_classes(TRAPS) NOT_CDS_JAVA_HEAP_RETURN; diff --git a/src/hotspot/share/classfile/classLoaderData.cpp b/src/hotspot/share/classfile/classLoaderData.cpp index dfc3b74db96..d1ea9c09d4c 100644 --- a/src/hotspot/share/classfile/classLoaderData.cpp +++ b/src/hotspot/share/classfile/classLoaderData.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,6 +46,7 @@ // The bootstrap loader (represented by null) also has a ClassLoaderData, // the singleton class the_null_class_loader_data(). +#include "cds/heapShared.hpp" #include "classfile/classLoaderData.inline.hpp" #include "classfile/classLoaderDataGraph.inline.hpp" #include "classfile/dictionary.hpp" @@ -899,6 +900,7 @@ void ClassLoaderData::free_deallocate_list() { if (m->is_method()) { MetadataFactory::free_metadata(this, (Method*)m); } else if (m->is_constantPool()) { + HeapShared::remove_scratch_resolved_references((ConstantPool*)m); MetadataFactory::free_metadata(this, (ConstantPool*)m); } else if (m->is_klass()) { MetadataFactory::free_metadata(this, (InstanceKlass*)m); diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp index cb071f2abf0..d675e61cc05 100644 --- a/src/hotspot/share/oops/instanceKlass.cpp +++ b/src/hotspot/share/oops/instanceKlass.cpp @@ -704,6 +704,7 @@ void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) { if (constants() != nullptr) { assert (!constants()->on_stack(), "shouldn't be called if anything is onstack"); if (!constants()->in_aot_cache()) { + HeapShared::remove_scratch_resolved_references(constants()); MetadataFactory::free_metadata(loader_data, constants()); } // Delete any cached resolution errors for the constant pool diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/RedefineClassesInProfile.java b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/RedefineClassesInProfile.java new file mode 100644 index 00000000000..f311629b2de --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/RedefineClassesInProfile.java @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 Class redefinition during training run + * @bug 8381117 + * @requires vm.cds.supports.aot.class.linking + * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds/test-classes + * + * @compile test-classes/RedefGeneration0.java + * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar redef0.jar + * RedefFoo RedefBar + * RedefTaz0 RedefTaz1 RedefTaz2 RedefTaz3 RedefTaz4 + * Qux0 Qux1 Qux2 Qux3 Qux4 + * Qux5 Qux6 Qux7 Qux8 Qux9 + * + * @compile test-classes/RedefGeneration1.java + * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar redef1.jar + * RedefFoo RedefBar + * RedefTaz0 RedefTaz1 RedefTaz2 RedefTaz3 RedefTaz4 + + * @run driver RedefineClassHelper + * @build RedefineClassesInProfile + * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar RedefineClassesInProfileApp Util + * @run driver RedefineClassesInProfile + */ + +import java.io.File; +import jdk.test.lib.cds.SimpleCDSAppTester; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +public class RedefineClassesInProfile { + public static void main(String... args) throws Exception { + SimpleCDSAppTester.of("RedefineClassesInProfile") + // redefineagent.jar is created by "@run driver RedefineClassHelper" + .addVmArgs("-javaagent:redefineagent.jar") + .addVmArgs("-Xlog:aot,aot+class=debug") + .addVmArgs("-Xlog:redefine+class+load") + .addVmArgs("-Xlog:aot+training+data") + .classpath("redef0.jar" + File.pathSeparator + "app.jar") + .appCommandLine("RedefineClassesInProfileApp") + .setTrainingChecker((OutputAnalyzer out) -> { + out.shouldContain("Skipping RedefFoo: Has been redefined"); + out.shouldContain("Skipping RedefBar: Has been redefined"); + + for (int i = 0; i < RedefineClassesInProfileApp.num_taz; i++) { + out.shouldMatch("redefine,class,load.*redefined name=RedefTaz" + i); + } + for (int i = 0; i < RedefineClassesInProfileApp.num_qux; i++) { + out.shouldMatch("aot,class.*klasses.*app *Qux" + i); + } + }) + .setAssemblyChecker((OutputAnalyzer out) -> { + out.shouldNotContain("RedefFoo"); + + // The names of the Redef* classes should not appear in training data, + // as these classes have been redefined and excluded from the AOT cache. + // + // Note: do not pass Redef* as parameters in any of the methods that can be + // stored into the AOT cache, or else the substring Redef* may appear in + // method signatures, and make the following checks fail. + String prefix = "aot,training,data.*"; + + out.shouldMatch(prefix + "RedefineClassesInProfileApp"); // sanity + out.shouldNotMatch(prefix + "RedefFoo"); + out.shouldNotMatch(prefix + "RedefBar"); + out.shouldNotMatch(prefix + "RedefTaz"); + }) + .setProductionChecker((OutputAnalyzer out) -> { + out.shouldContain("Redefined: class RedefBar"); + out.shouldContain("Redefined: class RedefFoo"); + }) + .runAOTWorkflow(); + } +} + +class RedefineClassesInProfileApp { + static final int num_taz = 5; + static final int num_qux = 10; + + public static void main(String[] args) throws Exception { + test1(); + } + + // test1 + // (1) Training run should work fine even if ConstantPool from redefined classes + // are reused by classes that are loaded later. See JDK-8381117 + // (2) Pointers to redefined classes should be cleaned from TrainingData. + static void test1() throws Exception { + String jarFile = "redef1.jar"; + Runnable dummy = () -> {}; + Runnable redef_bar = () -> { redefine(jarFile, RedefBar.class); }; + Runnable redef_foo = () -> { redefine(jarFile, RedefFoo.class); }; + + hotspot1(); + + int c1 = RedefFoo.foo1(dummy); + check("c1", c1, 1); + + int c2 = RedefFoo.foo1(redef_bar); + check("c2", c2, 12); + + int c3 = RedefFoo.foo1(redef_foo); + check("c3", c3, 22); + + int c4 = RedefFoo.foo1(dummy); + check("c4", c4, 22); + + // Redefine the RedefTaz* classes. This should free some constant pools + for (int i = 0; i < num_taz; i++) { + Class.forName("RedefTaz" + i); + } + for (int i = 0; i < num_taz; i++) { + redefine(jarFile, Class.forName("RedefTaz" + i)); + } + + // Load the Qux* classes. They *might* reuse the constant pools + // freed from above. See comments in test-classes/RedefGeneration0.java + // about the crash condition for JDK-8381117. + for (int i = 0; i < num_qux; i++) { + Class.forName("Qux" + i); + } + } + + static volatile int x; + static void hotspot1() { + long start = System.currentTimeMillis(); + // run this loop long enough (400ms) for it to be JIT compiled. + while (System.currentTimeMillis() - start < 400) { + // RedefFoo will be excluded fro the AOT configuration file, so + // any reference to RedefFoo recorded in TrainingData should be + // also be removed. If not, we are likely to see a crash in + // the assembly phase or production run. + x += RedefFoo.foo0(); + } + } + + static void check(String name, int actual, int expect) { + System.out.println(name + " = " + actual); + if (actual != expect) { + throw new RuntimeException(name + " should be " + expect + ", but is " + actual); + } + } + + static void redefine(String jarFile, Class c) { + try { + byte[] b = Util.getClassFileFromJar(jarFile, c.getName()); + RedefineClassHelper.redefineClass(c, b); + System.out.println("Redefined: " + c + ", Length = " + b.length); + } catch (Throwable t) { + throw new RuntimeException("Unexpected failure", t); + } + } +} diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/test-classes/RedefGeneration0.java b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/test-classes/RedefGeneration0.java new file mode 100644 index 00000000000..27542b94e98 --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/test-classes/RedefGeneration0.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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. + * + */ + +// These are "generation 0" test classes used in redefinition tests. +// These classes are loaded from the classpath, and will later be redefined +// with the versions in RedefGeneration1.java + +class RedefFoo { + static int foo0() { + return 10; + } + static int foo1(Runnable r) { + return RedefBar.bar0(r); + } +} + +class RedefBar { + static int bar0(Runnable r) { + r.run(); + return bar1(); + } + static int bar1() { + return 1; + } +} + +// The following classes will be redefined +class RedefTaz0 { static int x1, x2, x3, x4, x5; int a; Runnable x() { return () -> {a += 1;}; } } +class RedefTaz1 { static int x1, x2, x3, x4, x5; int a; Runnable x() { return () -> {a += 1;}; } } +class RedefTaz2 { static int x1, x2, x3, x4, x5; int a; Runnable x() { return () -> {a += 1;}; } } +class RedefTaz3 { static int x1, x2, x3, x4, x5; int a; Runnable x() { return () -> {a += 1;}; } } +class RedefTaz4 { static int x1, x2, x3, x4, x5; int a; Runnable x() { return () -> {a += 1;}; } } + +// The following classes will be loaded after the RedefTaz* classes are redefined. +// They may reuse the constant pools that were freed during the redefinitions of RedefTaz*. +// +// These classes are NOT redefined in the training run, so they should be stored into AOT +// configuration and AOT cache. +// +// The Qux classes have a smaller constant pool size (as defined in the classfile) than the +// Taz classes, so they are likely to reuse the space of the constant pools freed from Taz. +// However, Qux uses a larger ConstantPool::resolved_reference(), as it has one extra +// String. Without the JDK-8381117 fix, the JVM would crash during the training run inside +// ConstantPool::prepare_resolved_references_for_archiving(). +class Qux0 { static final String s = "x"; int a; Runnable x() { return () -> {a += 1;}; } } +class Qux1 { static final String s = "x"; int a; Runnable x() { return () -> {a += 1;}; } } +class Qux2 { static final String s = "x"; int a; Runnable x() { return () -> {a += 1;}; } } +class Qux3 { static final String s = "x"; int a; Runnable x() { return () -> {a += 1;}; } } +class Qux4 { static final String s = "x"; int a; Runnable x() { return () -> {a += 1;}; } } +class Qux5 { static final String s = "x"; int a; Runnable x() { return () -> {a += 1;}; } } +class Qux6 { static final String s = "x"; int a; Runnable x() { return () -> {a += 1;}; } } +class Qux7 { static final String s = "x"; int a; Runnable x() { return () -> {a += 1;}; } } +class Qux8 { static final String s = "x"; int a; Runnable x() { return () -> {a += 1;}; } } +class Qux9 { static final String s = "x"; int a; Runnable x() { return () -> {a += 1;}; } } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/test-classes/RedefGeneration1.java b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/test-classes/RedefGeneration1.java new file mode 100644 index 00000000000..56261aefe16 --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/test-classes/RedefGeneration1.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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. + * + */ + +// These are "generation 1" test classes used in redefinition tests. +// They are used to redefine the classes that were compiled from RedefGeneration0.java. + +class RedefFoo { + static int foo0() { + // WAS: return 10 + return 20; + } + static int foo1(Runnable r) { + return RedefBar.bar0(r); + } +} + +class RedefBar { + static int bar0(Runnable r) { + r.run(); + return bar1(); + } + + static int bar1() { + // WAS: return 1; + return 2 + RedefFoo.foo0(); + } +} + +class RedefTaz0 { static int x1, x2, x3, x4, x5; int a; Runnable x() { return () -> {a += 2;}; } } +class RedefTaz1 { static int x1, x2, x3, x4, x5; int a; Runnable x() { return () -> {a += 2;}; } } +class RedefTaz2 { static int x1, x2, x3, x4, x5; int a; Runnable x() { return () -> {a += 2;}; } } +class RedefTaz3 { static int x1, x2, x3, x4, x5; int a; Runnable x() { return () -> {a += 2;}; } } +class RedefTaz4 { static int x1, x2, x3, x4, x5; int a; Runnable x() { return () -> {a += 2;}; } } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/test-classes/Util.java b/test/hotspot/jtreg/runtime/cds/appcds/test-classes/Util.java index 295505003a8..e83865d5f03 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/test-classes/Util.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/test-classes/Util.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -104,6 +104,9 @@ static byte[] asciibytes(String s) { return b; } + public static byte[] getClassFileFromJar(String jarFile, String className) throws FileNotFoundException, IOException { + return getClassFileFromJar(new File(jarFile), className); + } public static byte[] getClassFileFromJar(File jarFile, String className) throws FileNotFoundException, IOException { JarFile jf = new JarFile(jarFile); JarEntry ent = jf.getJarEntry(className.replace('.', '/') + ".class"); From 9131c72d63cac7d2a0e845952cee0e3c7edbfc93 Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Wed, 1 Apr 2026 17:49:31 +0000 Subject: [PATCH 109/116] 8368692: Restrict Password::readPassword from reading from System.in Reviewed-by: mullan --- .../classes/sun/security/util/Password.java | 47 +++++++++---- .../share/conf/security/java.security | 29 ++++++++ .../security/tools/keytool/AllowSystemIn.java | 70 +++++++++++++++++++ 3 files changed, 133 insertions(+), 13 deletions(-) create mode 100644 test/jdk/sun/security/tools/keytool/AllowSystemIn.java diff --git a/src/java.base/share/classes/sun/security/util/Password.java b/src/java.base/share/classes/sun/security/util/Password.java index 02cdcaf53fd..c1b44856c8b 100644 --- a/src/java.base/share/classes/sun/security/util/Password.java +++ b/src/java.base/share/classes/sun/security/util/Password.java @@ -29,6 +29,7 @@ import java.nio.*; import java.nio.charset.*; import java.util.Arrays; +import java.util.Locale; import jdk.internal.access.SharedSecrets; import jdk.internal.io.JdkConsoleImpl; @@ -43,6 +44,22 @@ public static char[] readPassword(InputStream in) throws IOException { return readPassword(in, false); } + private static final boolean ALLOW_STDIN; + static { + var value = SecurityProperties.getOverridableProperty( + "jdk.security.password.allowSystemIn"); + if (value != null) { + value = value.toLowerCase(Locale.ROOT); + } + ALLOW_STDIN = switch (value) { + case null -> true; // Default true now + case "true" -> true; + case "false" -> false; + default -> throw new IllegalArgumentException( + "Invalid jdk.security.password.allowSystemIn value: " + value); + }; + } + /** Reads user password from given input stream. * @param isEchoOn true if the password should be echoed on the screen */ @@ -66,19 +83,23 @@ public static char[] readPassword(InputStream in, boolean isEchoOn) } consoleBytes = ConsoleHolder.convertToBytes(consoleEntered); in = new ByteArrayInputStream(consoleBytes); - } else if (in == System.in && VM.isBooted() - && System.in.available() == 0) { - // Warn if reading password from System.in but it's empty. - // This may be running in an IDE Run Window or in JShell, - // which acts like an interactive console and echoes the - // entered password. In this case, print a warning that - // the password might be echoed. If available() is not zero, - // it's more likely the input comes from a pipe, such as - // "echo password |" or "cat password_file |" where input - // will be silently consumed without echoing to the screen. - // Warn only if VM is booted and ResourcesMgr is available. - System.err.print(ResourcesMgr.getString - ("warning.input.may.be.visible.on.screen")); + } else if (in == System.in) { + if (!ALLOW_STDIN) { + throw new UnsupportedOperationException("Console not available." + + " Reading passwords from standard input is disallowed."); + } else if (VM.isBooted() && in.available() == 0) { + // Warn if reading password from System.in but it's empty. + // This may be running in an IDE Run Window or in JShell, + // which acts like an interactive console and echoes the + // entered password. In this case, print a warning that + // the password might be echoed. If available() is not zero, + // it's more likely the input comes from a pipe, such as + // "echo password |" or "cat password_file |" where input + // will be silently consumed without echoing to the screen. + // Warn only if VM is booted and ResourcesMgr is available. + System.err.print(ResourcesMgr.getString + ("warning.input.may.be.visible.on.screen")); + } } } diff --git a/src/java.base/share/conf/security/java.security b/src/java.base/share/conf/security/java.security index d5d0488a004..976604b5cbc 100644 --- a/src/java.base/share/conf/security/java.security +++ b/src/java.base/share/conf/security/java.security @@ -1725,3 +1725,32 @@ com.sun.security.allowedAIALocations= # #jdk.mlkem.pkcs8.encoding = seed #jdk.mldsa.pkcs8.encoding = seed + +# +# Policy for reading passwords from System.in +# +# When Java needs to read a password, whether it's via a tool such as keytool or +# kinit, or by an API such as PasswordCallback with echo off, it normally reads +# directly from the console. If the console is not available, Java falls back +# to reading from the standard input stream ("System.in"), which typically +# represents a redirected file or an inter-process pipe. This fallback is not +# formally specified, and is not widely adopted by tools from other vendors. +# +# This security property determines whether passwords can be read from the +# standard input stream when a console is not available. The value can be set +# to either "true" or "false". If the value is set to "false", attempting +# to read passwords from the standard input stream without a console will +# throw an exception. The default value is "true". This default may change +# in a future release. +# +# If a system property of the same name is also specified, it supersedes the +# security property value defined here. +# +# Note: This property applies only to password reading from the standard input +# stream. It does not affect other supported password sources. For example, the +# JAAS KeyStoreLoginModule allows a password to be read from the user-specified +# "keyStorePasswordURL" option. The keytool and jarsigner commands also support +# options such as "-storepass:env" and "-storepass:file" that read passwords +# from an environment variable or a file. +# +#jdk.security.password.allowSystemIn = true diff --git a/test/jdk/sun/security/tools/keytool/AllowSystemIn.java b/test/jdk/sun/security/tools/keytool/AllowSystemIn.java new file mode 100644 index 00000000000..04373f8ba26 --- /dev/null +++ b/test/jdk/sun/security/tools/keytool/AllowSystemIn.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 8368692 + * @summary Restrict Password::readPassword from reading from System.in + * @library /test/lib + * @run main AllowSystemIn succeed + * @run main/othervm -Djdk.security.password.allowSystemIn=true AllowSystemIn succeed + * @run main/othervm -Djdk.security.password.allowSystemIn=false AllowSystemIn fail + * @run main/othervm -Djdk.security.password.allowSystemIn=bogus AllowSystemIn invalid + */ + +import com.sun.security.auth.callback.TextCallbackHandler; +import jdk.test.lib.Asserts; + +import javax.security.auth.callback.Callback; +import javax.security.auth.callback.PasswordCallback; +import java.io.ByteArrayInputStream; +import java.nio.charset.StandardCharsets; + +public class AllowSystemIn{ + + public static void main(String[] args) throws Exception { + switch (args[0]) { + case "succeed" -> Asserts.assertEQ("password", getPassword()); + case "fail" -> Asserts.assertThrows( + UnsupportedOperationException.class, + AllowSystemIn::getPassword); + case "invalid" -> Asserts.assertThrows( + ExceptionInInitializerError.class, // implementation detail + AllowSystemIn::getPassword); + } + } + + static String getPassword() throws Exception { + var in = System.in; + try { + var bin = new ByteArrayInputStream( + "password".getBytes(StandardCharsets.UTF_8)); + System.setIn(bin); + var pb = new PasswordCallback("> ", false); + new TextCallbackHandler().handle(new Callback[]{pb}); + return new String(pb.getPassword()); + } finally { + System.setIn(in); + } + } +} From 3cb4d7db19bb7b3daf5921dd5d98e3cbc6608051 Mon Sep 17 00:00:00 2001 From: Phil Race Date: Wed, 1 Apr 2026 18:36:47 +0000 Subject: [PATCH 110/116] 8381037: Remove AppContext from miscellaneous awt shared classes Reviewed-by: azvegint, dnguyen --- .../classes/java/awt/EventDispatchThread.java | 6 +- .../java/awt/KeyboardFocusManager.java | 5 +- .../share/classes/java/awt/SentEvent.java | 15 +- .../classes/java/awt/WaitDispatchSupport.java | 4 +- .../share/classes/sun/awt/EmbeddedFrame.java | 9 +- .../classes/sun/awt/GlobalCursorManager.java | 4 +- .../sun/awt/KeyboardFocusManagerPeerImpl.java | 6 +- .../classes/sun/awt/PaintEventDispatcher.java | 4 +- .../classes/sun/font/SunFontManager.java | 24 +- .../swing/system/6799345/TestShutdown.java | 205 ------------------ .../awt/AppContext/8012933/Test8012933.java | 93 -------- 11 files changed, 20 insertions(+), 355 deletions(-) delete mode 100644 test/jdk/javax/swing/system/6799345/TestShutdown.java delete mode 100644 test/jdk/sun/awt/AppContext/8012933/Test8012933.java diff --git a/src/java.desktop/share/classes/java/awt/EventDispatchThread.java b/src/java.desktop/share/classes/java/awt/EventDispatchThread.java index b817ca12ece..1a991741fab 100644 --- a/src/java.desktop/share/classes/java/awt/EventDispatchThread.java +++ b/src/java.desktop/share/classes/java/awt/EventDispatchThread.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -203,8 +203,8 @@ void pumpOneEventForFilters(int id) { eq.dispatchEvent(event); } catch (InterruptedException interruptedException) { - doDispatch = false; // AppContext.dispose() interrupts all - // Threads in the AppContext + // keep this catch case for compatibility + doDispatch = false; } catch (Throwable e) { processException(e); diff --git a/src/java.desktop/share/classes/java/awt/KeyboardFocusManager.java b/src/java.desktop/share/classes/java/awt/KeyboardFocusManager.java index 06932d33f8a..9b55e754a64 100644 --- a/src/java.desktop/share/classes/java/awt/KeyboardFocusManager.java +++ b/src/java.desktop/share/classes/java/awt/KeyboardFocusManager.java @@ -2264,15 +2264,14 @@ static boolean processSynchronousLightweightTransfer(Component heavyweight, Comp temporary, descendant, cause); // Fix 5028014. Rolled out. // SunToolkit.postPriorityEvent(currentFocusOwnerEvent); - SunToolkit.postEvent(currentFocusOwner.appContext, - currentFocusOwnerEvent); + SunToolkit.postEvent(currentFocusOwnerEvent); } FocusEvent newFocusOwnerEvent = new FocusEvent(descendant, FocusEvent.FOCUS_GAINED, temporary, currentFocusOwner, cause); // Fix 5028014. Rolled out. // SunToolkit.postPriorityEvent(newFocusOwnerEvent); - SunToolkit.postEvent(descendant.appContext, newFocusOwnerEvent); + SunToolkit.postEvent(newFocusOwnerEvent); if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) focusLog.finest("2. SNFH_HANDLED for {0}", String.valueOf(descendant)); diff --git a/src/java.desktop/share/classes/java/awt/SentEvent.java b/src/java.desktop/share/classes/java/awt/SentEvent.java index 632b4ee85a8..eb85fa1453d 100644 --- a/src/java.desktop/share/classes/java/awt/SentEvent.java +++ b/src/java.desktop/share/classes/java/awt/SentEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,6 @@ import java.io.Serial; -import sun.awt.AppContext; import sun.awt.SunToolkit; /** @@ -51,22 +50,16 @@ class SentEvent extends AWTEvent implements ActiveEvent { boolean dispatched; private AWTEvent nested; - @SuppressWarnings("serial") // Not statically typed as Serializable - private AppContext toNotify; SentEvent() { this(null); } SentEvent(AWTEvent nested) { - this(nested, null); - } - SentEvent(AWTEvent nested, AppContext toNotify) { super((nested != null) ? nested.getSource() : Toolkit.getDefaultToolkit(), ID); this.nested = nested; - this.toNotify = toNotify; } public void dispatch() { @@ -76,9 +69,6 @@ public void dispatch() { } } finally { dispatched = true; - if (toNotify != null) { - SunToolkit.postEvent(toNotify, new SentEvent()); - } synchronized (this) { notifyAll(); } @@ -86,9 +76,6 @@ public void dispatch() { } final void dispose() { dispatched = true; - if (toNotify != null) { - SunToolkit.postEvent(toNotify, new SentEvent()); - } synchronized (this) { notifyAll(); } diff --git a/src/java.desktop/share/classes/java/awt/WaitDispatchSupport.java b/src/java.desktop/share/classes/java/awt/WaitDispatchSupport.java index 71e8b3086a1..3e567f538b1 100644 --- a/src/java.desktop/share/classes/java/awt/WaitDispatchSupport.java +++ b/src/java.desktop/share/classes/java/awt/WaitDispatchSupport.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -211,8 +211,6 @@ public void run() { } }, interval); } - // Dispose SequencedEvent we are dispatching on the current - // AppContext, to prevent us from hang - see 4531693 for details SequencedEvent currentSE = KeyboardFocusManager. getCurrentKeyboardFocusManager().getCurrentSequencedEvent(); if (currentSE != null) { diff --git a/src/java.desktop/share/classes/sun/awt/EmbeddedFrame.java b/src/java.desktop/share/classes/sun/awt/EmbeddedFrame.java index ab2ad5dfbf0..fa8ed1e707c 100644 --- a/src/java.desktop/share/classes/sun/awt/EmbeddedFrame.java +++ b/src/java.desktop/share/classes/sun/awt/EmbeddedFrame.java @@ -164,11 +164,8 @@ private void removeTraversingOutListeners(KeyboardFocusManager kfm) { } /** - * Because there may be many AppContexts, and we can't be sure where this - * EmbeddedFrame is first created or shown, we can't automatically determine - * the correct KeyboardFocusManager to attach to as KeyEventDispatcher. * Those who want to use the functionality of traversing out of the EmbeddedFrame - * must call this method on the AppContext. After that, all the changes + * must call this method. After that, all the changes * can be handled automatically, including possible replacement of * KeyboardFocusManager. */ @@ -184,7 +181,7 @@ public void registerListeners() { /** * Needed to avoid memory leak: we register this EmbeddedFrame as a listener with - * KeyboardFocusManager of an AppContext. We don't want the KFM to keep + * the KeyboardFocusManager. We don't want the KFM to keep * reference to our EmbeddedFrame forever if the Frame is no longer in use, so we * add listeners in show() and remove them in hide(). */ @@ -198,7 +195,7 @@ public void show() { /** * Needed to avoid memory leak: we register this EmbeddedFrame as a listener with - * KeyboardFocusManager of an AppContext. We don't want the KFM to keep + * the KeyboardFocusManager. We don't want the KFM to keep * reference to our EmbeddedFrame forever if the Frame is no longer in use, so we * add listeners in show() and remove them in hide(). */ diff --git a/src/java.desktop/share/classes/sun/awt/GlobalCursorManager.java b/src/java.desktop/share/classes/sun/awt/GlobalCursorManager.java index 27893d0ce87..8638bf81921 100644 --- a/src/java.desktop/share/classes/sun/awt/GlobalCursorManager.java +++ b/src/java.desktop/share/classes/sun/awt/GlobalCursorManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -61,7 +61,7 @@ public void postIfNotPending(Component heavy, InvocationEvent in) { } } if (shouldPost) { - SunToolkit.postEvent(SunToolkit.targetToAppContext(heavy), in); + SunToolkit.postEvent(in); } } } diff --git a/src/java.desktop/share/classes/sun/awt/KeyboardFocusManagerPeerImpl.java b/src/java.desktop/share/classes/sun/awt/KeyboardFocusManagerPeerImpl.java index ef50d883ee5..909c0b58136 100644 --- a/src/java.desktop/share/classes/sun/awt/KeyboardFocusManagerPeerImpl.java +++ b/src/java.desktop/share/classes/sun/awt/KeyboardFocusManagerPeerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -127,7 +127,7 @@ public static boolean deliverFocus(Component lightweightChild, if (focusLog.isLoggable(PlatformLogger.Level.FINER)) { focusLog.finer("Posting focus event: " + fl); } - SunToolkit.postEvent(SunToolkit.targetToAppContext(currentOwner), fl); + SunToolkit.postEvent(fl); } FocusEvent fg = new FocusEvent(lightweightChild, FocusEvent.FOCUS_GAINED, @@ -136,7 +136,7 @@ public static boolean deliverFocus(Component lightweightChild, if (focusLog.isLoggable(PlatformLogger.Level.FINER)) { focusLog.finer("Posting focus event: " + fg); } - SunToolkit.postEvent(SunToolkit.targetToAppContext(lightweightChild), fg); + SunToolkit.postEvent(fg); return true; } diff --git a/src/java.desktop/share/classes/sun/awt/PaintEventDispatcher.java b/src/java.desktop/share/classes/sun/awt/PaintEventDispatcher.java index eec1fc93c66..831c67e1e4f 100644 --- a/src/java.desktop/share/classes/sun/awt/PaintEventDispatcher.java +++ b/src/java.desktop/share/classes/sun/awt/PaintEventDispatcher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -93,7 +93,7 @@ public boolean shouldDoNativeBackgroundErase(Component c) { * This method is invoked from the toolkit thread when the surface * data of the component needs to be replaced. The method run() of * the Runnable argument performs surface data replacing, run() - * should be invoked on the EDT of this component's AppContext. + * should be invoked on the EDT. * Returns true if the Runnable has been enqueued to be invoked * on the EDT. * (Fix 6255371.) diff --git a/src/java.desktop/share/classes/sun/font/SunFontManager.java b/src/java.desktop/share/classes/sun/font/SunFontManager.java index 85a948ef594..323f0d056e1 100644 --- a/src/java.desktop/share/classes/sun/font/SunFontManager.java +++ b/src/java.desktop/share/classes/sun/font/SunFontManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -2480,30 +2480,12 @@ private Font2D findFont2DAllLocales(String name, int style) { * SunGraphicsEnvironment it performs the same initialization as is * performed normally. There may be some duplication of effort, but * that code is already written to be able to perform properly if called - * to duplicate work. The main difference is that if we detect we are - * in an AppContext environment these new fonts - * are not placed in the "default" maps but into an AppContext instance. - * The font lookup mechanism in java.awt.Font.getFont2D() is also updated - * so that look-up for composite fonts will in that case always - * do a lookup rather than returning a cached result. - * This is inefficient but necessary else singleton java.awt.Font - * instances would not retrieve the correct Font2D for the appcontext. - * sun.font.FontManager.findFont2D is also updated to that it uses - * a name map cache specific to that appcontext. - * - * Getting an AppContext is expensive, so there is a global variable - * that records whether these methods have ever been called and can - * avoid the expense for almost all applications. Once the correct - * CompositeFont is associated with the Font, everything should work - * through existing mechanisms. - * A special case is that GraphicsEnvironment.getAllFonts() must - * return an AppContext specific list. + * to duplicate work. * * Calling the methods below is "heavyweight" but it is expected that * these methods will be called very rarely. * - * If _usingAlternateComposites is true, we are not in an "AppContext" - * environment and the (single) application has selected + * If _usingAlternateComposites is true, the application has selected * an alternate composite font behaviour. * * - Printing: The implementation delegates logical fonts to an AWT diff --git a/test/jdk/javax/swing/system/6799345/TestShutdown.java b/test/jdk/javax/swing/system/6799345/TestShutdown.java deleted file mode 100644 index 54ae1e227df..00000000000 --- a/test/jdk/javax/swing/system/6799345/TestShutdown.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved. - * 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 6799345 - * @key headful - * @summary Tests that no exceptions are thrown from TimerQueue and - * SwingWorker on AppContext shutdown - * @author art - * @modules java.desktop/sun.awt - * @run main TestShutdown - */ - -import java.awt.*; -import java.awt.event.*; - -import java.util.*; - -import javax.swing.*; - -import sun.awt.*; - -public class TestShutdown -{ - private static AppContext targetAppContext; - - private static JFrame f; - private static JTextField tf; - - private static volatile boolean exceptionsOccurred = false; - private static volatile boolean appcontextInitDone = false; - - private static int timerValue = 0; - - public static void main(String[] args) - throws Exception - { - ThreadGroup tg = new TestThreadGroup("TTG"); - Thread t = new Thread(tg, new TestRunnable(), "InitThread"); - t.start(); - - while (!appcontextInitDone) - { - Thread.sleep(1000); - } - - targetAppContext.dispose(); - - if (exceptionsOccurred) - { - throw new RuntimeException("Test FAILED: some exceptions occurred"); - } - } - - static void initGUI() - { - f = new JFrame("F"); - f.setBounds(100, 100, 200, 100); - tf = new JTextField("Test"); - f.add(tf); - f.setVisible(true); - } - - static void startGUI() - { - // caret blink Timer - tf.requestFocusInWindow(); - - // misc Timer - ActionListener al = new ActionListener() - { - @Override - public void actionPerformed(ActionEvent ae) - { - System.out.println("Timer tick: " + timerValue++); - } - }; - new javax.swing.Timer(30, al).start(); - } - - static class TestThreadGroup extends ThreadGroup - { - public TestThreadGroup(String name) - { - super(name); - } - - @Override - public synchronized void uncaughtException(Thread thread, Throwable t) - { - if (t instanceof ThreadDeath) - { - // this one is expected, rethrow - throw (ThreadDeath)t; - } - System.err.println("Test FAILED: an exception is caught in the " + - "target thread group on thread " + thread.getName()); - t.printStackTrace(System.err); - exceptionsOccurred = true; - } - } - - static class TestRunnable implements Runnable - { - @Override - public void run() - { - SunToolkit stk = (SunToolkit)Toolkit.getDefaultToolkit(); - targetAppContext = stk.createNewAppContext(); - - // create and show frame and text field - SwingUtilities.invokeLater(new Runnable() - { - @Override - public void run() - { - initGUI(); - } - }); - stk.realSync(); - - // start some Timers - SwingUtilities.invokeLater(new Runnable() - { - @Override - public void run() - { - startGUI(); - } - }); - - // start multiple SwingWorkers - while (!Thread.interrupted()) - { - try - { - new TestSwingWorker().execute(); - Thread.sleep(40); - } - catch (Exception e) - { - // exception here is expected, skip - break; - } - } - } - } - - static class TestSwingWorker extends SwingWorker - { - @Override - public String doInBackground() - { - Random r = new Random(); - for (int i = 0; i < 10; i++) - { - try - { - int delay = r.nextInt() % 50; - Thread.sleep(delay); - publish(delay); - } - catch (Exception z) - { - break; - } - } - if (!appcontextInitDone) - { - appcontextInitDone = true; - } - return "Done"; - } - - @Override - public void process(java.util.List chunks) - { - for (Integer i : chunks) - { - System.err.println("Processed: " + i); - } - } - } -} diff --git a/test/jdk/sun/awt/AppContext/8012933/Test8012933.java b/test/jdk/sun/awt/AppContext/8012933/Test8012933.java deleted file mode 100644 index 51c5250f3ac..00000000000 --- a/test/jdk/sun/awt/AppContext/8012933/Test8012933.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * 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 - * 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 8012933 - * @summary Tests (although somewhat indirectly) that createNewAppContext() - * immediately followed by dispose() works correctly - * @author Leonid Romanov - * @modules java.desktop/sun.awt - */ - -import sun.awt.SunToolkit; -import sun.awt.AppContext; - -public class Test8012933 { - private AppContext appContext = null; - final ThreadGroup threadGroup = new ThreadGroup("test thread group"); - final Object lock = new Object(); - boolean isCreated = false; - - public static void main(String[] args) throws Exception { - SunToolkit.createNewAppContext(); - new Test8012933().test(); - } - - private void test() throws Exception { - createAppContext(); - long startTime = System.currentTimeMillis(); - appContext.dispose(); - long endTime = System.currentTimeMillis(); - - // In case of the bug, calling dispose() when there is no EQ - // dispatch thread running fails to create it, so it takes - // almost 10 sec to return from dispose(), which is spent - // waiting on the notificationLock. - if ((endTime - startTime) > 9000) { - throw new RuntimeException("Returning from dispose() took too much time, probably a bug"); - } - } - - private void createAppContext() { - isCreated = false; - final Runnable runnable = new Runnable() { - public void run() { - appContext = SunToolkit.createNewAppContext(); - synchronized (lock) { - isCreated = true; - lock.notifyAll(); - } - } - }; - - final Thread thread = new Thread(threadGroup, runnable, "creates app context"); - synchronized (lock) { - thread.start(); - while (!isCreated) { - try { - lock.wait(); - } catch (InterruptedException ie) { - ie.printStackTrace(); - } - } - } - - if (appContext == null) { - throw new RuntimeException("failed to create app context."); - } else { - System.out.println("app context was created."); - } - } - -} From 40e5745dea472621651fe495d27eef3563714157 Mon Sep 17 00:00:00 2001 From: Phil Race Date: Wed, 1 Apr 2026 19:10:39 +0000 Subject: [PATCH 111/116] 8380714: sun.font.HBShaper : use getUpcallStub to create all up call stubs Reviewed-by: serb, psadhukhan --- .../share/classes/sun/font/HBShaper.java | 63 +++++++------------ 1 file changed, 24 insertions(+), 39 deletions(-) diff --git a/src/java.desktop/share/classes/sun/font/HBShaper.java b/src/java.desktop/share/classes/sun/font/HBShaper.java index 3a532072004..dea8a9e22dd 100644 --- a/src/java.desktop/share/classes/sun/font/HBShaper.java +++ b/src/java.desktop/share/classes/sun/font/HBShaper.java @@ -216,45 +216,30 @@ private static VarHandle getVarHandle(StructLayout struct, String name) { JAVA_INT, // return type JAVA_INT, ADDRESS); // arg types - FunctionDescriptor get_var_glyph_fd = getFunctionDescriptor(JAVA_INT, // return type - ADDRESS, ADDRESS, JAVA_INT, JAVA_INT, ADDRESS, ADDRESS); // arg types - MethodHandle get_var_glyph_mh = - getMethodHandle("get_variation_glyph", get_var_glyph_fd); - @SuppressWarnings("restricted") - MemorySegment tmp5 = LINKER.upcallStub(get_var_glyph_mh, get_var_glyph_fd, garena); - get_var_glyph_stub = tmp5; - - FunctionDescriptor get_nominal_glyph_fd = getFunctionDescriptor(JAVA_INT, // return type - ADDRESS, ADDRESS, JAVA_INT, ADDRESS, ADDRESS); // arg types - MethodHandle get_nominal_glyph_mh = - getMethodHandle("get_nominal_glyph", get_nominal_glyph_fd); - @SuppressWarnings("restricted") - MemorySegment tmp6 = LINKER.upcallStub(get_nominal_glyph_mh, get_nominal_glyph_fd, garena); - get_nominal_glyph_stub = tmp6; - - FunctionDescriptor get_h_adv_fd = getFunctionDescriptor(JAVA_INT, // return type - ADDRESS, ADDRESS, JAVA_INT, ADDRESS); // arg types - MethodHandle get_h_adv_mh = - getMethodHandle("get_glyph_h_advance", get_h_adv_fd); - @SuppressWarnings("restricted") - MemorySegment tmp7 = LINKER.upcallStub(get_h_adv_mh, get_h_adv_fd, garena); - get_h_advance_stub = tmp7; - - FunctionDescriptor get_v_adv_fd = getFunctionDescriptor(JAVA_INT, // return type - ADDRESS, ADDRESS, JAVA_INT, ADDRESS); // arg types - MethodHandle get_v_adv_mh = - getMethodHandle("get_glyph_v_advance", get_v_adv_fd); - @SuppressWarnings("restricted") - MemorySegment tmp8 = LINKER.upcallStub(get_v_adv_mh, get_v_adv_fd, garena); - get_v_advance_stub = tmp8; - - FunctionDescriptor get_contour_pt_fd = getFunctionDescriptor(JAVA_INT, // return type - ADDRESS, ADDRESS, JAVA_INT, JAVA_INT, ADDRESS, ADDRESS, ADDRESS); // arg types - MethodHandle get_contour_pt_mh = - getMethodHandle("get_glyph_contour_point", get_contour_pt_fd); - @SuppressWarnings("restricted") - MemorySegment tmp9 = LINKER.upcallStub(get_contour_pt_mh, get_contour_pt_fd, garena); - get_contour_pt_stub = tmp9; + get_var_glyph_stub = getUpcallStub(garena, + "get_variation_glyph", // method name + JAVA_INT, // return type + ADDRESS, ADDRESS, JAVA_INT, JAVA_INT, ADDRESS, ADDRESS); // arg types + + get_nominal_glyph_stub = getUpcallStub(garena, + "get_nominal_glyph", // method name + JAVA_INT, // return type + ADDRESS, ADDRESS, JAVA_INT, ADDRESS, ADDRESS); // arg types + + get_h_advance_stub = getUpcallStub(garena, + "get_glyph_h_advance", // method name + JAVA_INT, // return type + ADDRESS, ADDRESS, JAVA_INT, ADDRESS); // arg types + + get_v_advance_stub = getUpcallStub(garena, + "get_glyph_v_advance", // method name + JAVA_INT, // return type + ADDRESS, ADDRESS, JAVA_INT, ADDRESS); // arg types + + get_contour_pt_stub = getUpcallStub(garena, + "get_glyph_contour_point", // method name + JAVA_INT, // return type + ADDRESS, ADDRESS, JAVA_INT, JAVA_INT, ADDRESS, ADDRESS, ADDRESS); // arg types /* Having now created the font upcall stubs, we can call down to create * the native harfbuzz object holding these. From ce9b3b59aa7477cf399716022204c1d5e83676f4 Mon Sep 17 00:00:00 2001 From: Phil Race Date: Wed, 1 Apr 2026 19:10:55 +0000 Subject: [PATCH 112/116] 8380941: Remove AppContext from java.awt.Window implementation Reviewed-by: azvegint, kizune --- .../share/classes/java/awt/Window.java | 85 +++++++------------ 1 file changed, 30 insertions(+), 55 deletions(-) diff --git a/src/java.desktop/share/classes/java/awt/Window.java b/src/java.desktop/share/classes/java/awt/Window.java index b41409a138e..23aefd8860d 100644 --- a/src/java.desktop/share/classes/java/awt/Window.java +++ b/src/java.desktop/share/classes/java/awt/Window.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -64,7 +64,6 @@ import javax.accessibility.AccessibleStateSet; import sun.awt.AWTAccessor; -import sun.awt.AppContext; import sun.awt.DebugSettings; import sun.awt.SunToolkit; import sun.awt.util.IdentityArrayList; @@ -259,7 +258,7 @@ public static enum Type { /** * Contains all the windows that have a peer object associated, * i. e. between addNotify() and removeNotify() calls. The list - * of all Window instances can be obtained from AppContext object. + * of all Window instances can be obtained from {@link #getWindows()} * * @since 1.6 */ @@ -275,7 +274,7 @@ public static enum Type { new Vector>(); /* - * We insert a weak reference into the Vector of all Windows in AppContext + * We insert a weak reference into the Vector of all Windows * instead of 'this' so that garbage collection can still take place * correctly. */ @@ -427,11 +426,9 @@ public static enum Type { static class WindowDisposerRecord implements sun.java2d.DisposerRecord { WeakReference owner; final WeakReference weakThis; - final WeakReference context; - WindowDisposerRecord(AppContext context, Window victim) { + WindowDisposerRecord(Window victim) { weakThis = victim.weakThis; - this.context = new WeakReference(context); } public void updateOwner() { @@ -448,10 +445,7 @@ public void dispose() { parent.removeOwnedWindow(weakThis); } } - AppContext ac = context.get(); - if (null != ac) { - Window.removeFromWindowList(ac, weakThis); - } + Window.removeFromWindowList(weakThis); } } @@ -499,7 +493,7 @@ private void init(GraphicsConfiguration gc) { } modalExclusionType = Dialog.ModalExclusionType.NO_EXCLUDE; - disposerRecord = new WindowDisposerRecord(appContext, this); + disposerRecord = new WindowDisposerRecord(this); sun.java2d.Disposer.addRecord(anchor, disposerRecord); SunToolkit.checkAndSetPolicy(this); @@ -1489,34 +1483,6 @@ static IdentityArrayList getAllUnblockedWindows() { } } - private static Window[] getWindows(AppContext appContext) { - synchronized (Window.class) { - Window[] realCopy; - @SuppressWarnings("unchecked") - Vector> windowList = - (Vector>)appContext.get(Window.class); - if (windowList != null) { - int fullSize = windowList.size(); - int realSize = 0; - Window[] fullCopy = new Window[fullSize]; - for (int i = 0; i < fullSize; i++) { - Window w = windowList.get(i).get(); - if (w != null) { - fullCopy[realSize++] = w; - } - } - if (fullSize != realSize) { - realCopy = Arrays.copyOf(fullCopy, realSize); - } else { - realCopy = fullCopy; - } - } else { - realCopy = new Window[0]; - } - return realCopy; - } - } - /** * Returns an array of all {@code Window}s, both owned and ownerless, * created by this application. @@ -1534,7 +1500,24 @@ private static Window[] getWindows(AppContext appContext) { * @since 1.6 */ public static Window[] getWindows() { - return getWindows(AppContext.getAppContext()); + synchronized (Window.class) { + Window[] realCopy; + int fullSize = windowList.size(); + int realSize = 0; + Window[] fullCopy = new Window[fullSize]; + for (int i = 0; i < fullSize; i++) { + Window w = windowList.get(i).get(); + if (w != null) { + fullCopy[realSize++] = w; + } + } + if (fullSize != realSize) { + realCopy = Arrays.copyOf(fullCopy, realSize); + } else { + realCopy = fullCopy; + } + return realCopy; + } } /** @@ -2746,30 +2729,22 @@ void connectOwnedWindow(Window child) { child.disposerRecord.updateOwner(); } + private static final Vector> windowList = new Vector<>(); + private void addToWindowList() { synchronized (Window.class) { - @SuppressWarnings("unchecked") - Vector> windowList = (Vector>)appContext.get(Window.class); - if (windowList == null) { - windowList = new Vector>(); - appContext.put(Window.class, windowList); - } windowList.add(weakThis); } } - private static void removeFromWindowList(AppContext context, WeakReference weakThis) { + private static void removeFromWindowList(WeakReference weakThis) { synchronized (Window.class) { - @SuppressWarnings("unchecked") - Vector> windowList = (Vector>)context.get(Window.class); - if (windowList != null) { - windowList.remove(weakThis); - } + windowList.remove(weakThis); } } private void removeFromWindowList() { - removeFromWindowList(appContext, weakThis); + removeFromWindowList(weakThis); } /** @@ -2909,7 +2884,7 @@ private void initDeserializedWindow() { weakThis = new WeakReference<>(this); anchor = new Object(); - disposerRecord = new WindowDisposerRecord(appContext, this); + disposerRecord = new WindowDisposerRecord(this); sun.java2d.Disposer.addRecord(anchor, disposerRecord); addToWindowList(); From cddee6d6eb3e048635c380a32bd2f6ebfd2c18b5 Mon Sep 17 00:00:00 2001 From: Daniel Gredler Date: Wed, 1 Apr 2026 20:37:24 +0000 Subject: [PATCH 113/116] 8380028: Fix Page8 of manual test java/awt/print/PrinterJob/PrintTextTest.java on macOS Reviewed-by: prr, psadhukhan --- .../classes/sun/lwawt/macosx/CTextPipe.java | 33 +++++++++++++++---- .../java/awt/geom/AffineTransform.java | 4 +-- .../classes/sun/java2d/SunGraphics2D.java | 4 ++- .../awt/print/PrinterJob/PrintTextTest.java | 4 +-- 4 files changed, 33 insertions(+), 12 deletions(-) diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTextPipe.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTextPipe.java index cf4a6e72136..ba5bb769ad5 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTextPipe.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTextPipe.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ package sun.lwawt.macosx; - import java.awt.*; import java.awt.font.*; @@ -73,12 +72,17 @@ void drawTextAsShape(final SunGraphics2D sg2d, final String s, final double x, f @Override public void drawString(final SunGraphics2D sg2d, final String s, final double x, final double y) { + + FontInfo info = sg2d.getFontInfo(); + double dx = x + info.originX; + double dy = y + info.originY; + final long nativeStrikePtr = getNativeStrikePtr(sg2d); if (OSXSurfaceData.IsSimpleColor(sg2d.paint) && nativeStrikePtr != 0) { final OSXSurfaceData surfaceData = (OSXSurfaceData)sg2d.getSurfaceData(); - surfaceData.drawString(this, sg2d, nativeStrikePtr, s, x, y); + surfaceData.drawString(this, sg2d, nativeStrikePtr, s, dx, dy); } else { - drawTextAsShape(sg2d, s, x, y); + drawTextAsShape(sg2d, s, dx, dy); } } @@ -153,6 +157,15 @@ public void drawGlyphVector(final SunGraphics2D sg2d, final GlyphVector gV, fina final Font prevFont = sg2d.getFont(); sg2d.setFont(gV.getFont()); + int flags = gV.getLayoutFlags(); + boolean positionAdjustments = (flags & GlyphVector.FLAG_HAS_POSITION_ADJUSTMENTS) != 0; + if (positionAdjustments) { + // make sure GV positions are initialized, so they are available later in native code; this + // will already be the case if the user explicitly set the glyph positions, but not if the + // position adjustment flag was set because of a font translation transform or font tracking + gV.getGlyphPosition(0); + } + if (hasSlotData(gV)) { final int length = gV.getNumGlyphs(); float[] positions = gV.getGlyphPositions(0, length, null); @@ -177,12 +190,17 @@ public void drawGlyphVector(final SunGraphics2D sg2d, final GlyphVector gV, fina @Override public void drawChars(final SunGraphics2D sg2d, final char[] data, final int offset, final int length, final int x, final int y) { + + FontInfo info = sg2d.getFontInfo(); + double dx = x + info.originX; + double dy = y + info.originY; + final long nativeStrikePtr = getNativeStrikePtr(sg2d); if (OSXSurfaceData.IsSimpleColor(sg2d.paint) && nativeStrikePtr != 0) { final OSXSurfaceData surfaceData = (OSXSurfaceData)sg2d.getSurfaceData(); - surfaceData.drawUnicodes(this, sg2d, nativeStrikePtr, data, offset, length, x, y); + surfaceData.drawUnicodes(this, sg2d, nativeStrikePtr, data, offset, length, (float) dx, (float) dy); } else { - drawTextAsShape(sg2d, new String(data, offset, length), x, y); + drawTextAsShape(sg2d, new String(data, offset, length), dx, dy); } } @@ -191,7 +209,8 @@ public CTextPipe traceWrap() { } public static final class Tracer extends CTextPipe { - void doDrawString(final SurfaceData sData, final long nativeStrikePtr, final String s, final float x, final float y) { + @Override + public void doDrawString(final SurfaceData sData, final long nativeStrikePtr, final String s, final double x, final double y) { GraphicsPrimitive.tracePrimitive("QuartzDrawString"); super.doDrawString(sData, nativeStrikePtr, s, x, y); } diff --git a/src/java.desktop/share/classes/java/awt/geom/AffineTransform.java b/src/java.desktop/share/classes/java/awt/geom/AffineTransform.java index 9abc55d8e6f..a6869369714 100644 --- a/src/java.desktop/share/classes/java/awt/geom/AffineTransform.java +++ b/src/java.desktop/share/classes/java/awt/geom/AffineTransform.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1137,7 +1137,7 @@ private void stateError() { * The values are stored in the array as * { m00 m10 m01 m11 m02 m12 }. * An array of 4 doubles can also be specified, in which case only the - * first four elements representing the non-transform + * first four elements representing the non-translation * parts of the array are retrieved and the values are stored into * the array as { m00 m10 m01 m11 } * @param flatmatrix the double array used to store the returned diff --git a/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java b/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java index 891a15f24de..d66cd3fe3d5 100644 --- a/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java +++ b/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java @@ -596,7 +596,9 @@ public FontInfo checkFontInfo(FontInfo info, Font font, textAt.scale(ptSize, ptSize); info.originX = (float)textAt.getTranslateX(); info.originY = (float)textAt.getTranslateY(); - textAt.translate(-info.originX, -info.originY); + textAt.setTransform(textAt.getScaleX(), textAt.getShearY(), + textAt.getShearX(), textAt.getScaleY(), + 0, 0); if (transformState >= TRANSFORM_TRANSLATESCALE) { transform.getMatrix(info.devTx = new double[4]); devAt = new AffineTransform(info.devTx); diff --git a/test/jdk/java/awt/print/PrinterJob/PrintTextTest.java b/test/jdk/java/awt/print/PrinterJob/PrintTextTest.java index defca807fc0..0b9663a9e99 100644 --- a/test/jdk/java/awt/print/PrinterJob/PrintTextTest.java +++ b/test/jdk/java/awt/print/PrinterJob/PrintTextTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 6425068 7156751 7157659 8029204 8132890 8148334 8344637 8368702 + * @bug 6425068 7156751 7157659 8029204 8132890 8148334 8344637 8368702 8380028 * @key printer * @summary Confirm that text prints where we expect to the length we expect. * @library /java/awt/regtesthelpers From c18e3a3377e67f50ab065d1ac9365c7d43950fb6 Mon Sep 17 00:00:00 2001 From: Igor Veresov Date: Thu, 2 Apr 2026 00:18:11 +0000 Subject: [PATCH 114/116] 8379819: Creating AOT configuration crashes in MethodTrainingData::prepare Reviewed-by: iklam, kvn --- src/hotspot/share/oops/methodData.cpp | 2 +- src/hotspot/share/oops/trainingData.cpp | 49 ++++++++++++++----- src/hotspot/share/oops/trainingData.hpp | 4 +- .../share/prims/jvmtiRedefineClasses.cpp | 5 ++ .../aotCache/RedefineClassesInProfile.java | 35 ++++++++++++- .../aotCache/test-classes/CustomLoadee.java | 38 ++++++++++++++ 6 files changed, 117 insertions(+), 16 deletions(-) create mode 100644 test/hotspot/jtreg/runtime/cds/appcds/aotCache/test-classes/CustomLoadee.java diff --git a/src/hotspot/share/oops/methodData.cpp b/src/hotspot/share/oops/methodData.cpp index 38bdc33c628..ad1049ffa34 100644 --- a/src/hotspot/share/oops/methodData.cpp +++ b/src/hotspot/share/oops/methodData.cpp @@ -329,7 +329,7 @@ static bool is_excluded(Klass* k) { log_debug(aot, training)("Purged %s from MDO: unloaded class", k->name()->as_C_string()); return true; } else { - bool excluded = SystemDictionaryShared::should_be_excluded(k); + bool excluded = SystemDictionaryShared::should_be_excluded(k) || !SystemDictionaryShared::is_builtin_loader(k->class_loader_data()); if (excluded) { log_debug(aot, training)("Purged %s from MDO: excluded class", k->name()->as_C_string()); } diff --git a/src/hotspot/share/oops/trainingData.cpp b/src/hotspot/share/oops/trainingData.cpp index f52c22ad38a..7976da35374 100644 --- a/src/hotspot/share/oops/trainingData.cpp +++ b/src/hotspot/share/oops/trainingData.cpp @@ -118,10 +118,23 @@ void TrainingData::verify() { } } +static bool is_excluded(InstanceKlass* k) { + if (!k->is_loaded() || k->has_been_redefined()) { + return true; + } + if (CDSConfig::is_at_aot_safepoint()) { + // Check for AOT exclusion only at AOT safe point. + return SystemDictionaryShared::should_be_excluded(k) || !SystemDictionaryShared::is_builtin_loader(k->class_loader_data()); + } + return false; +} + MethodTrainingData* MethodTrainingData::make(const methodHandle& method, bool null_if_not_found, bool use_cache) { - MethodTrainingData* mtd = nullptr; if (!have_data() && !need_data()) { - return mtd; + return nullptr; + } + if (is_excluded(method->method_holder())) { + return nullptr; } // Try grabbing the cached value first. // Cache value is stored in MethodCounters and the following are the @@ -133,6 +146,7 @@ MethodTrainingData* MethodTrainingData::make(const methodHandle& method, bool nu // i.e. null_if_no_found == true, then just return a null. // 3. Cache value is not null. // Return it, the value of training_data_lookup_failed doesn't matter. + MethodTrainingData* mtd = nullptr; MethodCounters* mcs = method->method_counters(); if (mcs != nullptr) { mtd = mcs->method_training_data(); @@ -175,6 +189,7 @@ MethodTrainingData* MethodTrainingData::make(const methodHandle& method, bool nu return nullptr; // allocation failure } td = training_data_set()->install(mtd); + assert(!is_excluded(method->method_holder()), "Should not be excluded"); assert(td == mtd, ""); } else { mtd = nullptr; @@ -376,6 +391,9 @@ void CompileTrainingData::prepare(Visitor& visitor) { } KlassTrainingData* KlassTrainingData::make(InstanceKlass* holder, bool null_if_not_found) { + if (is_excluded(holder)) { + return nullptr; + } Key key(holder); TrainingData* td = CDS_ONLY(have_data() ? lookup_archived_training_data(&key) :) nullptr; KlassTrainingData* ktd = nullptr; @@ -401,6 +419,7 @@ KlassTrainingData* KlassTrainingData::make(InstanceKlass* holder, bool null_if_n } td = training_data_set()->install(ktd); assert(ktd == td, ""); + assert(!is_excluded(holder), "Should not be excluded"); } else { ktd = td->as_KlassTrainingData(); guarantee(ktd->holder() != nullptr, "null holder"); @@ -543,18 +562,24 @@ void TrainingData::cleanup_training_data() { } } +void TrainingData::cleanup_after_redefinition() { + if (need_data()) { + TrainingDataLocker l; + ResourceMark rm; + Visitor visitor(training_data_set()->size()); + training_data_set()->iterate([&](TrainingData* td) { + td->cleanup(visitor); + }); + } +} + void KlassTrainingData::cleanup(Visitor& visitor) { if (visitor.is_visited(this)) { return; } visitor.visit(this); if (has_holder()) { - bool is_excluded = !holder()->is_loaded(); - if (CDSConfig::is_at_aot_safepoint()) { - // Check for AOT exclusion only at AOT safe point. - is_excluded |= SystemDictionaryShared::should_be_excluded(holder()); - } - if (is_excluded) { + if (is_excluded(holder())) { ResourceMark rm; log_debug(aot, training)("Cleanup KTD %s", name()->as_klass_external_name()); _holder = nullptr; @@ -572,12 +597,8 @@ void MethodTrainingData::cleanup(Visitor& visitor) { } visitor.visit(this); if (has_holder()) { - if (CDSConfig::is_at_aot_safepoint() && SystemDictionaryShared::should_be_excluded(holder()->method_holder())) { - // Check for AOT exclusion only at AOT safe point. + if (is_excluded(holder()->method_holder())) { log_debug(aot, training)("Cleanup MTD %s::%s", name()->as_klass_external_name(), signature()->as_utf8()); - if (_final_profile != nullptr && _final_profile->method() != _holder) { - log_warning(aot, training)("Stale MDO for %s::%s", name()->as_klass_external_name(), signature()->as_utf8()); - } _final_profile = nullptr; _final_counters = nullptr; _holder = nullptr; @@ -593,6 +614,7 @@ void MethodTrainingData::cleanup(Visitor& visitor) { } void KlassTrainingData::verify() { + guarantee(!has_holder() || !is_excluded(holder()), "Bad holder"); for (int i = 0; i < comp_dep_count(); i++) { CompileTrainingData* ctd = comp_dep(i); if (!ctd->_init_deps.contains(this)) { @@ -604,6 +626,7 @@ void KlassTrainingData::verify() { } void MethodTrainingData::verify(bool verify_dep_counter) { + guarantee(!has_holder() || !is_excluded(holder()->method_holder()), "Bad holder"); iterate_compiles([&](CompileTrainingData* ctd) { ctd->verify(verify_dep_counter); }); diff --git a/src/hotspot/share/oops/trainingData.hpp b/src/hotspot/share/oops/trainingData.hpp index c549004e76e..bd696f52a8b 100644 --- a/src/hotspot/share/oops/trainingData.hpp +++ b/src/hotspot/share/oops/trainingData.hpp @@ -310,7 +310,7 @@ class TrainingData : public Metadata { static void iterate(Function& fn) { // lambda enabled API TrainingDataLocker l; if (have_data()) { - archived_training_data_dictionary()->iterate(fn); + archived_training_data_dictionary()->iterate_all(fn); } if (need_data()) { training_data_set()->iterate(fn); @@ -431,6 +431,8 @@ class TrainingData : public Metadata { } return nullptr; } + + static void cleanup_after_redefinition(); }; // Training data that is associated with an InstanceKlass diff --git a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp index c594cfc6816..8beddc5d406 100644 --- a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp +++ b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp @@ -53,6 +53,7 @@ #include "oops/method.hpp" #include "oops/oop.inline.hpp" #include "oops/recordComponent.hpp" +#include "oops/trainingData.hpp" #include "prims/jvmtiImpl.hpp" #include "prims/jvmtiRedefineClasses.hpp" #include "prims/jvmtiThreadState.inline.hpp" @@ -274,6 +275,10 @@ void VM_RedefineClasses::doit() { redefine_single_class(current, _class_defs[i].klass, _scratch_classes[i]); } +#if INCLUDE_CDS + TrainingData::cleanup_after_redefinition(); +#endif + // Flush all compiled code that depends on the classes redefined. flush_dependent_code(); diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/RedefineClassesInProfile.java b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/RedefineClassesInProfile.java index f311629b2de..bb1992d5c82 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/RedefineClassesInProfile.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/RedefineClassesInProfile.java @@ -41,7 +41,10 @@ * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar redef1.jar * RedefFoo RedefBar * RedefTaz0 RedefTaz1 RedefTaz2 RedefTaz3 RedefTaz4 - + * + * @compile test-classes/CustomLoadee.java + * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar cust.jar CustomLoadee + * * @run driver RedefineClassHelper * @build RedefineClassesInProfile * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar RedefineClassesInProfileApp Util @@ -49,6 +52,8 @@ */ import java.io.File; +import java.net.URL; +import java.net.URLClassLoader; import jdk.test.lib.cds.SimpleCDSAppTester; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; @@ -89,6 +94,7 @@ public static void main(String... args) throws Exception { out.shouldNotMatch(prefix + "RedefFoo"); out.shouldNotMatch(prefix + "RedefBar"); out.shouldNotMatch(prefix + "RedefTaz"); + out.shouldNotMatch(prefix + "CustomLoadee"); }) .setProductionChecker((OutputAnalyzer out) -> { out.shouldContain("Redefined: class RedefBar"); @@ -104,6 +110,7 @@ class RedefineClassesInProfileApp { public static void main(String[] args) throws Exception { test1(); + test2(); } // test1 @@ -175,4 +182,30 @@ static void redefine(String jarFile, Class c) { throw new RuntimeException("Unexpected failure", t); } } + + // Test 2 -- TrainingData interaction with custom class loaders. + static void test2() throws Exception { + // Do this several times. The AOT cache should contain only one + // copy of CustomLoadee as an "unregistered" class, which will be + // used in the first iteration of this loop. + // + // The JVM should work well even if the cached version of CustomLoadee + // has been unloaded. + for (int i = 0; i < 4; i++) { + test2_inner(); + System.gc(); // trigger unloading of CustomLoadee. + } + } + + static void test2_inner() throws Exception { + // Load a class and run a loop to make sure it's compiled, but + // TrainingData should not record any class/method that are loaded + // by custom class loaders + File custJar = new File("cust.jar"); + URL[] urls = new URL[] {custJar.toURI().toURL()}; + URLClassLoader loader = new URLClassLoader(urls, RedefineClassesInProfileApp.class.getClassLoader()); + Class c = loader.loadClass("CustomLoadee"); + System.out.println(c.newInstance()); + } } + diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/test-classes/CustomLoadee.java b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/test-classes/CustomLoadee.java new file mode 100644 index 00000000000..aa78f2ba57a --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/test-classes/CustomLoadee.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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. + * + */ + +public class CustomLoadee { + public CustomLoadee() { + hotspot2(); + } + + static volatile int x; + static void hotspot2() { + long start = System.currentTimeMillis(); + // run this loop long enough (400ms) for it to be JIT compiled. + while (System.currentTimeMillis() - start < 400) { + x += 1; + } + } +} From fa5ec62405af5ca104ca269d3470e07de690386f Mon Sep 17 00:00:00 2001 From: Dusan Balek Date: Thu, 2 Apr 2026 08:20:47 +0000 Subject: [PATCH 115/116] 8378950: Repeated warnings when annotation processing is happening Co-authored-by: Archie Cobbs Reviewed-by: jlahoda --- .../JavacProcessingEnvironment.java | 15 ++++-- .../APImplicitClassesWarnings.java | 53 +++++++++++++++++-- .../tools/javac/modules/IncubatingTest.java | 46 ++++++++++++++-- .../rounds/OverwriteBetweenCompilations_2.out | 2 - 4 files changed, 103 insertions(+), 13 deletions(-) diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java index 74d082d4b64..809c19d5012 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1104,7 +1104,7 @@ boolean unrecoverableError() { return true; return deferredDiagnosticHandler.getDiagnostics().stream() - .anyMatch(d -> (d.getKind() == Diagnostic.Kind.WARNING && werror) || + .anyMatch(d -> (d.getKind() == Diagnostic.Kind.WARNING && werror && ACCEPT_NON_RECOVERABLE_LINTS.test(d)) || (d.getKind() == Diagnostic.Kind.ERROR && (fatalErrors || !d.isFlagSet(RECOVERABLE)))); } @@ -1195,12 +1195,19 @@ void run(boolean lastRound, boolean errorStatus) { } void showDiagnostics(boolean showAll) { - deferredDiagnosticHandler.reportDeferredDiagnostics(showAll ? ACCEPT_ALL - : ACCEPT_NON_RECOVERABLE); + deferredDiagnosticHandler.reportDeferredDiagnostics( + ACCEPT_NON_RECOVERABLE_LINTS.and(showAll ? ACCEPT_ALL + : ACCEPT_NON_RECOVERABLE)); log.popDiagnosticHandler(deferredDiagnosticHandler); compiler.setDeferredDiagnosticHandler(null); } //where: + private final Predicate ACCEPT_NON_RECOVERABLE_LINTS = + d -> !Optional.of(d) + .map(JCDiagnostic::getLintCategory) + .map(lc -> lc.annotationSuppression || + lc == Lint.LintCategory.INCUBATING) + .orElse(false); private final Predicate ACCEPT_NON_RECOVERABLE = d -> d.getKind() != JCDiagnostic.Kind.ERROR || !d.isFlagSet(DiagnosticFlag.RECOVERABLE) || diff --git a/test/langtools/tools/javac/implicitCompile/APImplicitClassesWarnings.java b/test/langtools/tools/javac/implicitCompile/APImplicitClassesWarnings.java index dc60c6cc78a..8c1e356217c 100644 --- a/test/langtools/tools/javac/implicitCompile/APImplicitClassesWarnings.java +++ b/test/langtools/tools/javac/implicitCompile/APImplicitClassesWarnings.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8378740 + * @bug 8378740 8378950 * @summary Verify warnings are properly suppressed for the combination of * annotation processing and implicit compilation * @library /tools/lib @@ -96,9 +96,7 @@ public interface Implicit {} List expected = List.of( "Use.java:4:5: compiler.warn.has.been.deprecated.for.removal: test.Depr, test", - "Use.java:4:5: compiler.warn.has.been.deprecated.for.removal: test.Depr, test", - "Use.java:4:5: compiler.warn.has.been.deprecated.for.removal: test.Depr, test", - "3 warnings" + "1 warning" ); tb.checkEqual(expected, log); @@ -143,6 +141,53 @@ public interface Implicit {} .writeAll(); } + @Test + public void testCorrectImport() throws Exception { + Path src = base.resolve("src"); + Path classes = base.resolve("classes"); + tb.writeJavaFiles(src, + """ + package test; + + @Deprecated(forRemoval=true) + public class Depr { + public static class Nested {} + } + """, + """ + package test; + import test.Depr.Nested; + public class Use { + Implicit implicit; + Nested nest; + } + """, + """ + package test; + public interface Implicit {} + """); + Files.createDirectories(classes); + + List log = new JavacTask(tb) + .options("-d", classes.toString(), + "-XDrawDiagnostics", + "-implicit:class", + "-sourcepath", src.toString()) + .files(src.resolve("test").resolve("Depr.java"), + src.resolve("test").resolve("Use.java")) + .processors(new ProcessorImpl()) + .run() + .writeAll() + .getOutputLines(Task.OutputKind.DIRECT); + + List expected = List.of( + "Use.java:2:12: compiler.warn.has.been.deprecated.for.removal: test.Depr, test", + "1 warning" + ); + + tb.checkEqual(expected, log); + } + @SupportedAnnotationTypes("*") private static class ProcessorImpl extends AbstractProcessor { @Override diff --git a/test/langtools/tools/javac/modules/IncubatingTest.java b/test/langtools/tools/javac/modules/IncubatingTest.java index 68f615abc04..6ff1a0a29c8 100644 --- a/test/langtools/tools/javac/modules/IncubatingTest.java +++ b/test/langtools/tools/javac/modules/IncubatingTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 8171177 8187591 + * @bug 8171177 8187591 8378950 * @summary Verify that ModuleResolution attribute flags are honored. * @library /tools/lib * @modules jdk.compiler/com.sun.tools.javac.api @@ -46,10 +46,15 @@ import java.util.HashMap; import java.util.List; import java.util.Map; - +import java.util.Set; import java.lang.classfile.*; import java.lang.classfile.attribute.ModuleResolutionAttribute; import java.lang.classfile.constantpool.*; +import javax.annotation.processing.AbstractProcessor; +import javax.annotation.processing.RoundEnvironment; +import javax.annotation.processing.SupportedAnnotationTypes; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.TypeElement; import toolbox.JavacTask; import toolbox.Task; import toolbox.Task.Expect; @@ -242,6 +247,29 @@ public void testIncubating(Path base) throws Exception { .outdir(testModuleClasses) .files(findJavaFiles(testModuleSrc)) .run(Expect.SUCCESS); + + //test with annotation processing + log = new JavacTask(tb) + .options("--module-path", classes.toString(), + "-XDrawDiagnostics", + "-Werror") + .outdir(testModuleClasses) + .files(findJavaFiles(testModuleSrc)) + .processors(new ProcessorImpl()) + .run(Expect.FAIL) + .writeAll() + .getOutputLines(Task.OutputKind.DIRECT); + + expected = Arrays.asList( + "- compiler.warn.incubating.modules: jdk.i", + "- compiler.err.warnings.and.werror", + "1 error", + "1 warning" + ); + + if (!expected.equals(log)) { + throw new AssertionError("Unexpected output: " + log); + } } private void copyJavaBase(Path targetDir) throws IOException { @@ -270,4 +298,16 @@ private void addModuleResolutionAttribute(Path classfile, int resolution_flags) out.write(newBytes); } } + + @SupportedAnnotationTypes("*") + private static class ProcessorImpl extends AbstractProcessor { + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + return false; + } + @Override + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latest(); + } + } } diff --git a/test/langtools/tools/javac/processing/rounds/OverwriteBetweenCompilations_2.out b/test/langtools/tools/javac/processing/rounds/OverwriteBetweenCompilations_2.out index 826e2b4bcb0..431fd3d9079 100644 --- a/test/langtools/tools/javac/processing/rounds/OverwriteBetweenCompilations_2.out +++ b/test/langtools/tools/javac/processing/rounds/OverwriteBetweenCompilations_2.out @@ -53,5 +53,3 @@ public abstract class GeneratedClass extends java.ut public void test(long a); } -- compiler.note.deprecated.filename: OverwriteBetweenCompilationsSource.java -- compiler.note.deprecated.recompile From 2357f93fbb76f1fc517fcc749f45317c76f9681b Mon Sep 17 00:00:00 2001 From: Vicente Romero Date: Thu, 2 Apr 2026 22:57:35 +0000 Subject: [PATCH 116/116] 8381475: Test tools/sincechecker/modules/jdk.compiler/JdkCompilerCheckSince.java fails for DocSourcePositions.java Reviewed-by: mikael --- .../share/classes/com/sun/source/util/DocSourcePositions.java | 2 ++ .../share/classes/com/sun/source/util/SourcePositions.java | 2 ++ .../modules/jdk.compiler/JdkCompilerCheckSince.java | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/jdk.compiler/share/classes/com/sun/source/util/DocSourcePositions.java b/src/jdk.compiler/share/classes/com/sun/source/util/DocSourcePositions.java index d0afd126bf6..4eb6d12fd38 100644 --- a/src/jdk.compiler/share/classes/com/sun/source/util/DocSourcePositions.java +++ b/src/jdk.compiler/share/classes/com/sun/source/util/DocSourcePositions.java @@ -83,6 +83,7 @@ default long getStartPosition(CompilationUnitTree file, DocCommentTree comment, * @param comment the comment tree that encloses the tree for which the * position is being sought * @param tree tree for which a position is sought + * @since 27 */ long getStartPosition(DocCommentTree comment, DocTree tree); @@ -146,6 +147,7 @@ default long getEndPosition(CompilationUnitTree file, DocCommentTree comment, Do * @param comment the comment tree that encloses the tree for which the * position is being sought * @param tree tree for which a position is sought + * @since 27 */ long getEndPosition(DocCommentTree comment, DocTree tree); diff --git a/src/jdk.compiler/share/classes/com/sun/source/util/SourcePositions.java b/src/jdk.compiler/share/classes/com/sun/source/util/SourcePositions.java index 460f4f2a1ce..3ff6fafe58b 100644 --- a/src/jdk.compiler/share/classes/com/sun/source/util/SourcePositions.java +++ b/src/jdk.compiler/share/classes/com/sun/source/util/SourcePositions.java @@ -74,6 +74,7 @@ default long getStartPosition(CompilationUnitTree file, Tree tree) { *

* * @param tree tree for which a position is sought + * @since 27 */ long getStartPosition(Tree tree); @@ -130,6 +131,7 @@ default long getEndPosition(CompilationUnitTree file, Tree tree) { *

* * @param tree tree for which a position is sought + * @since 27 */ long getEndPosition(Tree tree); } diff --git a/test/jdk/tools/sincechecker/modules/jdk.compiler/JdkCompilerCheckSince.java b/test/jdk/tools/sincechecker/modules/jdk.compiler/JdkCompilerCheckSince.java index 5eb819786e9..bf4b906b623 100644 --- a/test/jdk/tools/sincechecker/modules/jdk.compiler/JdkCompilerCheckSince.java +++ b/test/jdk/tools/sincechecker/modules/jdk.compiler/JdkCompilerCheckSince.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8341399 + * @bug 8341399 8381475 * @summary Test for `@since` in jdk.compiler module * @library /test/lib /test/jdk/tools/sincechecker * @run main SinceChecker jdk.compiler