/jre directory? */
- JLI_Snprintf(libjava, sizeof(libjava), "%s/jre/lib/" JAVA_DLL, path);
- if (access(libjava, F_OK) == 0) {
- JLI_StrCat(path, "/jre");
- JLI_TraceLauncher("JRE path is %s\n", path);
- return JNI_TRUE;
- }
}
/* try to find ourselves instead */
diff --git a/src/java.base/share/classes/com/sun/crypto/provider/HKDFKeyDerivation.java b/src/java.base/share/classes/com/sun/crypto/provider/HKDFKeyDerivation.java
new file mode 100644
index 00000000000..a9988bbc115
--- /dev/null
+++ b/src/java.base/share/classes/com/sun/crypto/provider/HKDFKeyDerivation.java
@@ -0,0 +1,414 @@
+/*
+ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.crypto.provider;
+
+import javax.crypto.KDFSpi;
+import javax.crypto.Mac;
+import javax.crypto.SecretKey;
+import javax.crypto.ShortBufferException;
+import javax.crypto.spec.HKDFParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.io.ByteArrayOutputStream;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import javax.crypto.KDFParameters;
+import java.security.NoSuchAlgorithmException;
+import java.security.ProviderException;
+import java.security.spec.AlgorithmParameterSpec;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * KDF implementation for the HKDF function.
+ *
+ * This class implements the HKDF-Extract and HKDF-Expand functions from RFC
+ * 5869. This implementation provides the complete Extract-then-Expand HKDF
+ * function as well as Extract-only and Expand-only variants.
+ *
+ * @spec https://www.rfc-editor.org/info/rfc5869
+ * RFC 5869: HMAC-based Extract-and-Expand Key Derivation Function (HKDF)
+ */
+abstract class HKDFKeyDerivation extends KDFSpi {
+
+ private final int hmacLen;
+ private final String hmacAlgName;
+
+ private enum SupportedHmac {
+ SHA256("HmacSHA256", 32),
+ SHA384("HmacSHA384", 48),
+ SHA512("HmacSHA512", 64);
+
+ private final String hmacAlg;
+ private final int hmacLen;
+ SupportedHmac(String hmacAlg, int hmacLen) {
+ this.hmacAlg = hmacAlg;
+ this.hmacLen = hmacLen;
+ }
+ };
+
+ /**
+ * The sole constructor.
+ *
+ * @param kdfParameters
+ * the initialization parameters (may be {@code null})
+ *
+ * @throws InvalidAlgorithmParameterException
+ * if the initialization parameters are inappropriate for this
+ * {@code KDFSpi}
+ */
+ private HKDFKeyDerivation(SupportedHmac supportedHmac,
+ KDFParameters kdfParameters)
+ throws InvalidAlgorithmParameterException {
+ super(kdfParameters);
+ if (kdfParameters != null) {
+ throw new InvalidAlgorithmParameterException(
+ supportedHmac.hmacAlg + " does not support parameters");
+ }
+ this.hmacAlgName = supportedHmac.hmacAlg;
+ this.hmacLen = supportedHmac.hmacLen;
+ }
+
+ /**
+ * Derive a key, returned as a {@code SecretKey} object.
+ *
+ * @return a derived {@code SecretKey} object of the specified algorithm
+ *
+ * @throws InvalidAlgorithmParameterException
+ * if the information contained within the {@code derivationSpec} is
+ * invalid or if the combination of {@code alg} and the
+ * {@code derivationSpec} results in something invalid
+ * @throws NoSuchAlgorithmException
+ * if {@code alg} is empty
+ * @throws NullPointerException
+ * if {@code alg} is {@code null}
+ */
+ @Override
+ protected SecretKey engineDeriveKey(String alg,
+ AlgorithmParameterSpec derivationSpec)
+ throws InvalidAlgorithmParameterException,
+ NoSuchAlgorithmException {
+
+ if (alg == null) {
+ throw new NullPointerException(
+ "the algorithm for the SecretKey return value must not be"
+ + " null");
+ }
+ if (alg.isEmpty()) {
+ throw new NoSuchAlgorithmException(
+ "the algorithm for the SecretKey return value must not be "
+ + "empty");
+ }
+
+ return new SecretKeySpec(engineDeriveData(derivationSpec), alg);
+
+ }
+
+ /**
+ * Obtain raw data from a key derivation function.
+ *
+ * @return a derived {@code byte[]}
+ *
+ * @throws InvalidAlgorithmParameterException
+ * if the information contained within the {@code KDFParameterSpec}
+ * is invalid or incorrect for the type of key to be derived
+ * @throws UnsupportedOperationException
+ * if the derived keying material is not extractable
+ */
+ @Override
+ protected byte[] engineDeriveData(AlgorithmParameterSpec derivationSpec)
+ throws InvalidAlgorithmParameterException {
+ List ikms, salts;
+ byte[] inputKeyMaterial, salt, pseudoRandomKey, info;
+ int length;
+ if (derivationSpec instanceof HKDFParameterSpec.Extract anExtract) {
+ ikms = anExtract.ikms();
+ salts = anExtract.salts();
+ // we should be able to combine both of the above Lists of key
+ // segments into one SecretKey object each, unless we were passed
+ // something bogus or an unexportable P11 key
+ inputKeyMaterial = null;
+ salt = null;
+ try {
+ inputKeyMaterial = consolidateKeyMaterial(ikms);
+ salt = consolidateKeyMaterial(salts);
+
+ // perform extract
+ return hkdfExtract(inputKeyMaterial, salt);
+ } catch (InvalidKeyException ike) {
+ throw new InvalidAlgorithmParameterException(
+ "an HKDF Extract could not be initialized with the "
+ + "given key or salt material", ike);
+ } catch (NoSuchAlgorithmException nsae) {
+ // This is bubbling up from the getInstance of the Mac/Hmac.
+ // Since we're defining these values internally, it is unlikely.
+ throw new ProviderException(
+ "could not instantiate a Mac with the provided "
+ + "algorithm",
+ nsae);
+ } finally {
+ if (inputKeyMaterial != null) {
+ Arrays.fill(inputKeyMaterial, (byte) 0x00);
+ }
+ if (salt != null) {
+ Arrays.fill(salt, (byte) 0x00);
+ }
+ }
+ } else if (derivationSpec instanceof HKDFParameterSpec.Expand anExpand) {
+ // set this value in the "if"
+ if ((pseudoRandomKey = anExpand.prk().getEncoded()) == null) {
+ throw new AssertionError(
+ "PRK is required for HKDFParameterSpec.Expand");
+ }
+ // set this value in the "if"
+ if ((info = anExpand.info()) == null) {
+ info = new byte[0];
+ }
+ length = anExpand.length();
+ if (length > (hmacLen * 255)) {
+ throw new InvalidAlgorithmParameterException(
+ "Requested length exceeds maximum allowed length");
+ }
+ // perform expand
+ try {
+ return hkdfExpand(pseudoRandomKey, info, length);
+ } catch (InvalidKeyException ike) {
+ throw new InvalidAlgorithmParameterException(
+ "an HKDF Expand could not be initialized with the "
+ + "given keying material", ike);
+ } catch (NoSuchAlgorithmException nsae) {
+ // This is bubbling up from the getInstance of the Mac/Hmac.
+ // Since we're defining these values internally, it is unlikely.
+ throw new ProviderException(
+ "could not instantiate a Mac with the provided "
+ + "algorithm",
+ nsae);
+ } finally {
+ Arrays.fill(pseudoRandomKey, (byte) 0x00);
+ }
+ } else if (derivationSpec instanceof HKDFParameterSpec.ExtractThenExpand anExtractThenExpand) {
+ ikms = anExtractThenExpand.ikms();
+ salts = anExtractThenExpand.salts();
+ // we should be able to combine both of the above Lists of key
+ // segments into one SecretKey object each, unless we were passed
+ // something bogus or an unexportable P11 key
+ inputKeyMaterial = null;
+ salt = null;
+ pseudoRandomKey = null;
+ try {
+ inputKeyMaterial = consolidateKeyMaterial(ikms);
+ salt = consolidateKeyMaterial(salts);
+
+ // set this value in the "if"
+ if ((info = anExtractThenExpand.info()) == null) {
+ info = new byte[0];
+ }
+ length = anExtractThenExpand.length();
+ if (length > (hmacLen * 255)) {
+ throw new InvalidAlgorithmParameterException(
+ "Requested length exceeds maximum allowed length");
+ }
+
+ // perform extract and then expand
+ pseudoRandomKey = hkdfExtract(inputKeyMaterial, salt);
+ return hkdfExpand(pseudoRandomKey, info, length);
+ } catch (InvalidKeyException ike) {
+ throw new InvalidAlgorithmParameterException(
+ "an HKDF ExtractThenExpand could not be initialized "
+ + "with the given key or salt material", ike);
+ } catch (NoSuchAlgorithmException nsae) {
+ // This is bubbling up from the getInstance of the Mac/HMAC.
+ // Since we're defining these values internally, it is unlikely.
+ throw new ProviderException(
+ "could not instantiate a Mac with the provided "
+ + "algorithm",
+ nsae);
+ } finally {
+ if (inputKeyMaterial != null) {
+ Arrays.fill(inputKeyMaterial, (byte) 0x00);
+ }
+ if (salt != null) {
+ Arrays.fill(salt, (byte) 0x00);
+ }
+ if (pseudoRandomKey != null) {
+ Arrays.fill(pseudoRandomKey, (byte) 0x00);
+ }
+ }
+ }
+ throw new InvalidAlgorithmParameterException(
+ "an HKDF derivation requires a valid HKDFParameterSpec");
+ }
+
+ // throws an InvalidKeyException if any key is unextractable
+ private byte[] consolidateKeyMaterial(List keys)
+ throws InvalidKeyException {
+ if (keys != null && !keys.isEmpty()) {
+ ArrayList localKeys = new ArrayList<>(keys);
+ if (localKeys.size() == 1) {
+ // return this element
+ SecretKey checkIt = localKeys.get(0);
+ return CipherCore.getKeyBytes(checkIt);
+ } else {
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ for (SecretKey workItem : localKeys) {
+ os.writeBytes(CipherCore.getKeyBytes(workItem));
+ }
+ // deliberately omitting os.flush(), since we are writing to
+ // memory, and toByteArray() reads like there isn't an explicit
+ // need for this call
+ return os.toByteArray();
+ }
+ } else if (keys != null) {
+ return new byte[0];
+ } else {
+ throw new InvalidKeyException(
+ "List of key segments could not be consolidated");
+ }
+ }
+
+ /**
+ * Perform the HKDF-Extract operation.
+ *
+ * @param inputKeyMaterial
+ * the input keying material used for the HKDF-Extract operation.
+ * @param salt
+ * the salt value used for HKDF-Extract
+ *
+ * @return a byte array containing the pseudorandom key (PRK)
+ *
+ * @throws InvalidKeyException
+ * if an invalid salt was provided through the
+ * {@code HKDFParameterSpec}
+ */
+ private byte[] hkdfExtract(byte[] inputKeyMaterial, byte[] salt)
+ throws InvalidKeyException, NoSuchAlgorithmException {
+
+ // salt will not be null
+ if (salt.length == 0) {
+ salt = new byte[hmacLen];
+ }
+ Mac hmacObj = Mac.getInstance(hmacAlgName);
+ hmacObj.init(new SecretKeySpec(salt, hmacAlgName));
+
+ // inputKeyMaterial will not be null
+ return hmacObj.doFinal(inputKeyMaterial);
+ }
+
+ /**
+ * Perform the HKDF-Expand operation.
+ *
+ * @param prk
+ * the pseudorandom key used for HKDF-Expand
+ * @param info
+ * optional context and application specific information or
+ * {@code null} if no info data is provided.
+ * @param outLen
+ * the length in bytes of the required output
+ *
+ * @return a byte array containing the complete {@code KDF} output. This
+ * will be at least as long as the requested length in the
+ * {@code outLen} parameter, but will be rounded up to the nearest
+ * multiple of the HMAC output length.
+ *
+ * @throws InvalidKeyException
+ * if an invalid PRK was provided through the
+ * {@code HKDFParameterSpec} or derived during the extract phase.
+ */
+ private byte[] hkdfExpand(byte[] prk, byte[] info, int outLen)
+ throws InvalidKeyException, NoSuchAlgorithmException {
+ byte[] kdfOutput;
+
+ if (prk == null || prk.length < hmacLen) {
+ throw new InvalidKeyException(
+ "prk must be at least " + hmacLen + " bytes");
+ }
+
+ SecretKey pseudoRandomKey = new SecretKeySpec(prk, hmacAlgName);
+
+ Mac hmacObj = Mac.getInstance(hmacAlgName);
+
+ // Calculate the number of rounds of HMAC that are needed to
+ // meet the requested data. Then set up the buffers we will need.
+ hmacObj.init(pseudoRandomKey);
+ int rounds = (outLen + hmacLen - 1) / hmacLen;
+ kdfOutput = new byte[outLen];
+ int i = 0;
+ int offset = 0;
+ try {
+ while (i < rounds) {
+ if (i > 0) {
+ hmacObj.update(kdfOutput, offset - hmacLen,
+ hmacLen); // add T(i-1)
+ }
+ hmacObj.update(info); // Add info
+ hmacObj.update((byte) ++i); // Add round number
+ if (i == rounds && (outLen - offset < hmacLen)) {
+ // special handling for last chunk
+ byte[] tmp = hmacObj.doFinal();
+ System.arraycopy(tmp, 0, kdfOutput, offset,
+ outLen - offset);
+ Arrays.fill(tmp, (byte) 0x00);
+ offset = outLen;
+ } else {
+ hmacObj.doFinal(kdfOutput, offset);
+ offset += hmacLen;
+ }
+ }
+ } catch (ShortBufferException sbe) {
+ // This really shouldn't happen given that we've
+ // sized the buffers to their largest possible size up-front,
+ // but just in case...
+ throw new ProviderException(sbe);
+ }
+ return kdfOutput;
+ }
+
+ protected KDFParameters engineGetParameters() {
+ return null;
+ }
+
+ public static final class HKDFSHA256 extends HKDFKeyDerivation {
+ public HKDFSHA256(KDFParameters kdfParameters)
+ throws InvalidAlgorithmParameterException {
+ super(SupportedHmac.SHA256, kdfParameters);
+ }
+ }
+
+ public static final class HKDFSHA384 extends HKDFKeyDerivation {
+ public HKDFSHA384(KDFParameters kdfParameters)
+ throws InvalidAlgorithmParameterException {
+ super(SupportedHmac.SHA384, kdfParameters);
+ }
+ }
+
+ public static final class HKDFSHA512 extends HKDFKeyDerivation {
+ public HKDFSHA512(KDFParameters kdfParameters)
+ throws InvalidAlgorithmParameterException {
+ super(SupportedHmac.SHA512, kdfParameters);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java b/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java
index 61062dd751a..13675372ddd 100644
--- a/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java
+++ b/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java
@@ -504,6 +504,16 @@ void putEntries() {
"com.sun.crypto.provider.DHKeyAgreement",
attrs);
+ /*
+ * Key Derivation engines
+ */
+ ps("KDF", "HKDF-SHA256",
+ "com.sun.crypto.provider.HKDFKeyDerivation$HKDFSHA256");
+ ps("KDF", "HKDF-SHA384",
+ "com.sun.crypto.provider.HKDFKeyDerivation$HKDFSHA384");
+ ps("KDF", "HKDF-SHA512",
+ "com.sun.crypto.provider.HKDFKeyDerivation$HKDFSHA512");
+
/*
* Algorithm Parameter engines
*/
diff --git a/src/java.base/share/classes/java/lang/AbstractStringBuilder.java b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java
index e0c3aa19f54..b40f6274412 100644
--- a/src/java.base/share/classes/java/lang/AbstractStringBuilder.java
+++ b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java
@@ -640,14 +640,11 @@ private AbstractStringBuilder appendNull() {
int count = this.count;
byte[] val = this.value;
if (isLatin1()) {
- val[count++] = 'n';
- val[count++] = 'u';
- val[count++] = 'l';
- val[count++] = 'l';
+ StringLatin1.putCharsAt(val, count, 'n', 'u', 'l', 'l');
} else {
- count = StringUTF16.putCharsAt(val, count, 'n', 'u', 'l', 'l');
+ StringUTF16.putCharsAt(val, count, 'n', 'u', 'l', 'l');
}
- this.count = count;
+ this.count = count + 4;
return this;
}
@@ -772,25 +769,18 @@ public AbstractStringBuilder append(boolean b) {
byte[] val = this.value;
if (isLatin1()) {
if (b) {
- val[count++] = 't';
- val[count++] = 'r';
- val[count++] = 'u';
- val[count++] = 'e';
+ StringLatin1.putCharsAt(val, count, 't', 'r', 'u', 'e');
} else {
- val[count++] = 'f';
- val[count++] = 'a';
- val[count++] = 'l';
- val[count++] = 's';
- val[count++] = 'e';
+ StringLatin1.putCharsAt(val, count, 'f', 'a', 'l', 's', 'e');
}
} else {
if (b) {
- count = StringUTF16.putCharsAt(val, count, 't', 'r', 'u', 'e');
+ StringUTF16.putCharsAt(val, count, 't', 'r', 'u', 'e');
} else {
- count = StringUTF16.putCharsAt(val, count, 'f', 'a', 'l', 's', 'e');
+ StringUTF16.putCharsAt(val, count, 'f', 'a', 'l', 's', 'e');
}
}
- this.count = count;
+ this.count = count + (b ? 4 : 5);
return this;
}
diff --git a/src/java.base/share/classes/java/lang/Class.java b/src/java.base/share/classes/java/lang/Class.java
index 09d2740b306..a91d30fe03f 100644
--- a/src/java.base/share/classes/java/lang/Class.java
+++ b/src/java.base/share/classes/java/lang/Class.java
@@ -152,7 +152,7 @@
* Some methods of class {@code Class} expose whether the declaration of
* a class or interface in Java source code was enclosed within
* another declaration. Other methods describe how a class or interface
- * is situated in a {@index "nest"} . A nest is a set of
+ * is situated in a {@index "nest"} . A nest is a set of
* classes and interfaces, in the same run-time package, that
* allow mutual access to their {@code private} members.
* The classes and interfaces are known as {@index "nestmates"}
diff --git a/src/java.base/share/classes/java/lang/Module.java b/src/java.base/share/classes/java/lang/Module.java
index e4cf4a3a6c3..4d4593b3197 100644
--- a/src/java.base/share/classes/java/lang/Module.java
+++ b/src/java.base/share/classes/java/lang/Module.java
@@ -263,7 +263,7 @@ Module implAddEnableNativeAccess() {
/**
* Returns {@code true} if this module can access
- * restricted methods.
+ * restricted methods.
*
* @return {@code true} if this module can access restricted methods.
* @since 22
diff --git a/src/java.base/share/classes/java/lang/ScopedValue.java b/src/java.base/share/classes/java/lang/ScopedValue.java
index 635fadfa8c8..ac9b598b531 100644
--- a/src/java.base/share/classes/java/lang/ScopedValue.java
+++ b/src/java.base/share/classes/java/lang/ScopedValue.java
@@ -75,34 +75,34 @@
* // @link substring="newInstance" target="#newInstance" :
* private static final ScopedValue NAME = ScopedValue.newInstance();
*
- * // @link substring="runWhere" target="#runWhere(ScopedValue, Object, Runnable)" :
- * ScopedValue.runWhere(NAME, "duke", () -> doSomething());
+ * // @link substring="run" target="Carrier#run(Runnable)" :
+ * ScopedValue.where(NAME, "duke").run(() -> doSomething());
* }
* Code executed directly or indirectly by {@code doSomething}, with access to the field
* {@code NAME}, can invoke {@code NAME.get()} to read the value "{@code duke}". {@code
* NAME} is bound while executing the {@code run} method. It reverts to being unbound when
* the {@code run} method completes.
*
- * The example using {@code runWhere} invokes a method that does not return a result.
- * The {@link #callWhere(ScopedValue, Object, CallableOp) callWhere} method can be used
+ *
The example using {@code run} invokes a method that does not return a result.
+ * The {@link Carrier#call(CallableOp) call} method can be used
* to invoke a method that returns a result.
- * In addition, {@code ScopedValue} defines the {@link #where(ScopedValue, Object)} method
+ * {@code ScopedValue} defines the {@link #where(ScopedValue, Object)} method
* for cases where multiple mappings (of {@code ScopedValue} to value) are accumulated
* in advance of calling a method with all {@code ScopedValue}s bound to their value.
*
*
Bindings are per-thread
*
- * A {@code ScopedValue} binding to a value is per-thread. Invoking {@code xxxWhere}
+ * A {@code ScopedValue} binding to a value is per-thread. Invoking {@code run}
* executes a method with a {@code ScopedValue} bound to a value for the current thread.
* The {@link #get() get} method returns the value bound for the current thread.
*
* In the example, if code executed by one thread invokes this:
* {@snippet lang=java :
- * ScopedValue.runWhere(NAME, "duke1", () -> doSomething());
+ * ScopedValue.where(NAME, "duke1").run(() -> doSomething());
* }
* and code executed by another thread invokes:
* {@snippet lang=java :
- * ScopedValue.runWhere(NAME, "duke2", () -> doSomething());
+ * ScopedValue.where(NAME, "duke2").run(() -> doSomething());
* }
* then code in {@code doSomething} (or any method that it calls) invoking {@code NAME.get()}
* will read the value "{@code duke1}" or "{@code duke2}", depending on which thread is
@@ -129,7 +129,7 @@
*
In the above example, suppose that code executed by {@code doSomething} binds
* {@code NAME} to a new value with:
* {@snippet lang=java :
- * ScopedValue.runWhere(NAME, "duchess", () -> doMore());
+ * ScopedValue.where(NAME, "duchess").run(() -> doMore());
* }
* Code executed directly or indirectly by {@code doMore()} that invokes {@code
* NAME.get()} will read the value "{@code duchess}". When {@code doMore()} completes
@@ -157,14 +157,18 @@
* {@snippet lang=java :
* private static final ScopedValue NAME = ScopedValue.newInstance();
- * ScopedValue.runWhere(NAME, "duke", () -> {
+ * ScopedValue.where(NAME, "duke").run(() -> {
* try (var scope = new StructuredTaskScope()) {
*
- * scope.fork(() -> childTask1());
- * scope.fork(() -> childTask2());
- * scope.fork(() -> childTask3());
+ * // @link substring="fork" target="StructuredTaskScope#fork(java.util.concurrent.Callable)" :
+ * scope.fork(() -> childTask1());
+ * scope.fork(() -> childTask2());
+ * scope.fork(() -> childTask3());
*
- * ...
+ * // @link substring="join" target="StructuredTaskScope#join()" :
+ * scope.join();
+ *
+ * ..
* }
* });
* }
@@ -310,7 +314,7 @@ Object find(ScopedValue> key) {
*/
@PreviewFeature(feature = PreviewFeature.Feature.SCOPED_VALUES)
public static final class Carrier {
- // Bit masks: a 1 in postion n indicates that this set of bound values
+ // Bit masks: a 1 in position n indicates that this set of bound values
// hits that slot in the cache.
final int bitmask;
final ScopedValue> key;
@@ -385,7 +389,7 @@ public T get(ScopedValue key) {
return (T) value;
}
}
- throw new NoSuchElementException();
+ throw new NoSuchElementException("No mapping present");
}
/**
@@ -409,7 +413,6 @@ public T get(ScopedValue key) {
* @return the result
* @throws StructureViolationException if a structure violation is detected
* @throws X if {@code op} completes with an exception
- * @see ScopedValue#callWhere(ScopedValue, Object, CallableOp)
* @since 23
*/
public R call(CallableOp extends R, X> op) throws X {
@@ -458,7 +461,6 @@ private R runWith(Snapshot newSnapshot, CallableOp Carrier where(ScopedValue key, T value) {
return Carrier.of(key, value);
}
- /**
- * Calls a value-returning operation with a {@code ScopedValue} bound to a value
- * in the current thread. When the operation completes (normally or with an
- * exception), the {@code ScopedValue} will revert to being unbound, or revert to
- * its previous value when previously bound, in the current thread. If {@code op}
- * completes with an exception then it propagated by this method.
- *
- * Scoped values are intended to be used in a structured manner . If code
- * invoked directly or indirectly by the operation creates a {@link StructuredTaskScope}
- * but does not {@linkplain StructuredTaskScope#close() close} it, then it is detected
- * as a structure violation when the operation completes (normally or with an
- * exception). In that case, the underlying construct of the {@code StructuredTaskScope}
- * is closed and {@link StructureViolationException} is thrown.
- *
- * @implNote
- * This method is implemented to be equivalent to:
- * {@snippet lang=java :
- * // @link substring="call" target="Carrier#call(CallableOp)" :
- * ScopedValue.where(key, value).call(op);
- * }
- *
- *
- *
- * @param key the {@code ScopedValue} key
- * @param value the value, can be {@code null}
- * @param the type of the value
- * @param the result type
- * @param type of the exception thrown by the operation
- * @param op the operation to call
- * @return the result
- * @throws StructureViolationException if a structure violation is detected
- * @throws X if the operation completes with an exception
- * @since 23
- */
- public static R callWhere(ScopedValue key,
- T value,
- CallableOp extends R, X> op) throws X {
- return where(key, value).call(op);
- }
-
- /**
- * Run an operation with a {@code ScopedValue} bound to a value in the current
- * thread. When the operation completes (normally or with an exception), the
- * {@code ScopedValue} will revert to being unbound, or revert to its previous value
- * when previously bound, in the current thread. If {@code op} completes with an
- * exception then it propagated by this method.
- *
- * Scoped values are intended to be used in a structured manner . If code
- * invoked directly or indirectly by the operation creates a {@link StructuredTaskScope}
- * but does not {@linkplain StructuredTaskScope#close() close} it, then it is detected
- * as a structure violation when the operation completes (normally or with an
- * exception). In that case, the underlying construct of the {@code StructuredTaskScope}
- * is closed and {@link StructureViolationException} is thrown.
- *
- * @implNote
- * This method is implemented to be equivalent to:
- * {@snippet lang=java :
- * // @link substring="run" target="Carrier#run(Runnable)" :
- * ScopedValue.where(key, value).run(op);
- * }
- *
- * @param key the {@code ScopedValue} key
- * @param value the value, can be {@code null}
- * @param the type of the value
- * @param op the operation to call
- * @throws StructureViolationException if a structure violation is detected
- */
- public static void runWhere(ScopedValue key, T value, Runnable op) {
- where(key, value).run(op);
- }
-
private ScopedValue() {
this.hash = generateKey();
}
@@ -642,7 +573,7 @@ public T get() {
private T slowGet() {
var value = findBinding();
if (value == Snapshot.NIL) {
- throw new NoSuchElementException();
+ throw new NoSuchElementException("ScopedValue not bound");
}
Cache.put(this, value);
return (T)value;
diff --git a/src/java.base/share/classes/java/lang/StringLatin1.java b/src/java.base/share/classes/java/lang/StringLatin1.java
index abec36af1d9..c12b8afc21f 100644
--- a/src/java.base/share/classes/java/lang/StringLatin1.java
+++ b/src/java.base/share/classes/java/lang/StringLatin1.java
@@ -32,6 +32,7 @@
import java.util.function.IntConsumer;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
+import jdk.internal.misc.Unsafe;
import jdk.internal.util.ArraysSupport;
import jdk.internal.util.DecimalDigits;
import jdk.internal.vm.annotation.IntrinsicCandidate;
@@ -42,6 +43,8 @@
import static java.lang.String.checkOffset;
final class StringLatin1 {
+ private static final Unsafe UNSAFE = Unsafe.getUnsafe();
+
public static char charAt(byte[] value, int index) {
checkIndex(index, value.length);
return (char)(value[index] & 0xff);
@@ -824,6 +827,27 @@ static Stream lines(byte[] value) {
return StreamSupport.stream(LinesSpliterator.spliterator(value), false);
}
+ static void putCharsAt(byte[] val, int index, int c1, int c2, int c3, int c4) {
+ assert index >= 0 && index + 3 < length(val) : "Trusted caller missed bounds check";
+ // Don't use the putChar method, Its instrinsic will cause C2 unable to combining values into larger stores.
+ long address = Unsafe.ARRAY_BYTE_BASE_OFFSET + index;
+ UNSAFE.putByte(val, address , (byte)(c1));
+ UNSAFE.putByte(val, address + 1, (byte)(c2));
+ UNSAFE.putByte(val, address + 2, (byte)(c3));
+ UNSAFE.putByte(val, address + 3, (byte)(c4));
+ }
+
+ static void putCharsAt(byte[] val, int index, int c1, int c2, int c3, int c4, int c5) {
+ assert index >= 0 && index + 4 < length(val) : "Trusted caller missed bounds check";
+ // Don't use the putChar method, Its instrinsic will cause C2 unable to combining values into larger stores.
+ long address = Unsafe.ARRAY_BYTE_BASE_OFFSET + index;
+ UNSAFE.putByte(val, address , (byte)(c1));
+ UNSAFE.putByte(val, address + 1, (byte)(c2));
+ UNSAFE.putByte(val, address + 2, (byte)(c3));
+ UNSAFE.putByte(val, address + 3, (byte)(c4));
+ UNSAFE.putByte(val, address + 4, (byte)(c5));
+ }
+
public static void putChar(byte[] val, int index, int c) {
//assert (canEncode(c));
val[index] = (byte)(c);
diff --git a/src/java.base/share/classes/java/lang/StringUTF16.java b/src/java.base/share/classes/java/lang/StringUTF16.java
index 000483f29bc..f04b991827f 100644
--- a/src/java.base/share/classes/java/lang/StringUTF16.java
+++ b/src/java.base/share/classes/java/lang/StringUTF16.java
@@ -43,7 +43,6 @@
import static java.lang.String.LATIN1;
final class StringUTF16 {
-
// Return a new byte array for a UTF16-coded string for len chars
// Throw an exception if out of range
public static byte[] newBytesFor(int len) {
@@ -1548,27 +1547,20 @@ public static boolean contentEquals(byte[] value, CharSequence cs, int len) {
return true;
}
- public static int putCharsAt(byte[] value, int i, char c1, char c2, char c3, char c4) {
- int end = i + 4;
- checkBoundsBeginEnd(i, end, value);
- putChar(value, i++, c1);
- putChar(value, i++, c2);
- putChar(value, i++, c3);
- putChar(value, i++, c4);
- assert(i == end);
- return end;
- }
-
- public static int putCharsAt(byte[] value, int i, char c1, char c2, char c3, char c4, char c5) {
- int end = i + 5;
- checkBoundsBeginEnd(i, end, value);
- putChar(value, i++, c1);
- putChar(value, i++, c2);
- putChar(value, i++, c3);
- putChar(value, i++, c4);
- putChar(value, i++, c5);
- assert(i == end);
- return end;
+ static void putCharsAt(byte[] val, int index, int c1, int c2, int c3, int c4) {
+ assert index >= 0 && index + 3 < length(val) : "Trusted caller missed bounds check";
+ putChar(val, index , c1);
+ putChar(val, index + 1, c2);
+ putChar(val, index + 2, c3);
+ putChar(val, index + 3, c4);
+ }
+
+ static void putCharsAt(byte[] val, int index, int c1, int c2, int c3, int c4, int c5) {
+ putChar(val, index , c1);
+ putChar(val, index + 1, c2);
+ putChar(val, index + 2, c3);
+ putChar(val, index + 3, c4);
+ putChar(val, index + 4, c5);
}
public static char charAt(byte[] value, int index) {
diff --git a/src/java.base/share/classes/java/lang/Thread.java b/src/java.base/share/classes/java/lang/Thread.java
index c5134e83324..46f87bdf369 100644
--- a/src/java.base/share/classes/java/lang/Thread.java
+++ b/src/java.base/share/classes/java/lang/Thread.java
@@ -1800,17 +1800,20 @@ boolean getAndClearInterrupt() {
if (com.ibm.oti.vm.VM.isJVMInSingleThreadedMode()) {
return interruptedImpl();
}
- synchronized (interruptLock) {
- boolean oldValue = interrupted;
- // We may have been interrupted the moment after we read the field,
- // so only clear the field if we saw that it was set and will return
- // true; otherwise we could lose an interrupt.
- if (oldValue) {
- interrupted = false;
- clearInterruptEvent();
+ boolean oldValue = interrupted;
+ if (oldValue) {
+ synchronized (interruptLock) {
+ oldValue = interrupted;
+ // We may have been interrupted the moment after we read the field,
+ // so only clear the field if we saw that it was set and will return
+ // true; otherwise we could lose an interrupt.
+ if (oldValue) {
+ interrupted = false;
+ clearInterruptEvent();
+ }
}
- return oldValue;
}
+ return oldValue;
}
/**
diff --git a/src/java.base/share/classes/java/lang/VirtualThread.java b/src/java.base/share/classes/java/lang/VirtualThread.java
index e0adbcb1eb8..7021cc626ff 100644
--- a/src/java.base/share/classes/java/lang/VirtualThread.java
+++ b/src/java.base/share/classes/java/lang/VirtualThread.java
@@ -24,7 +24,7 @@
*/
/*
* ===========================================================================
- * (c) Copyright IBM Corp. 2022, 2023 All Rights Reserved
+ * (c) Copyright IBM Corp. 2022, 2024 All Rights Reserved
* ===========================================================================
*/
package java.lang;
@@ -952,8 +952,11 @@ boolean getAndClearInterrupt() {
disableSuspendAndPreempt();
try {
synchronized (interruptLock) {
- interrupted = false;
- carrierThread.clearInterrupt();
+ oldValue = interrupted;
+ if (oldValue) {
+ interrupted = false;
+ carrierThread.clearInterrupt();
+ }
}
} finally {
enableSuspendAndPreempt();
diff --git a/src/java.base/share/classes/java/lang/foreign/MemorySegment.java b/src/java.base/share/classes/java/lang/foreign/MemorySegment.java
index 74658a5bbf6..cd38bd19227 100644
--- a/src/java.base/share/classes/java/lang/foreign/MemorySegment.java
+++ b/src/java.base/share/classes/java/lang/foreign/MemorySegment.java
@@ -501,7 +501,7 @@
* All the methods that can be used to manipulate zero-length memory segments
* ({@link #reinterpret(long)}, {@link #reinterpret(Arena, Consumer)}, {@link #reinterpret(long, Arena, Consumer)} and
* {@link AddressLayout#withTargetLayout(MemoryLayout)}) are
- * restricted methods, and should
+ * restricted methods, and should
* be used with caution: assigning a segment incorrect spatial and/or temporal bounds
* could result in a VM crash when attempting to access the memory segment.
*
@@ -1307,7 +1307,8 @@ MemorySegment reinterpret(long newSize,
* @param offset offset in bytes (relative to this segment address) at which this
* access operation will occur
* @param charset the charset used to {@linkplain Charset#newDecoder() decode} the
- * string bytes
+ * string bytes. The {@code charset} must be a
+ * {@linkplain StandardCharsets standard charset}
* @return a Java string constructed from the bytes read from the given starting
* address up to (but not including) the first {@code '\0'} terminator
* character (assuming one is found)
@@ -1375,7 +1376,9 @@ MemorySegment reinterpret(long newSize,
* access operation will occur, the final address of this write
* operation can be expressed as {@code address() + offset}
* @param str the Java string to be written into this segment
- * @param charset the charset used to {@linkplain Charset#newEncoder() encode} the string bytes
+ * @param charset the charset used to {@linkplain Charset#newEncoder() encode} the
+ * string bytes. The {@code charset} must be a
+ * {@linkplain StandardCharsets standard charset}
* @throws IndexOutOfBoundsException if {@code offset < 0}
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - (B + N)}, where:
*
diff --git a/src/java.base/share/classes/java/lang/invoke/ClassSpecializer.java b/src/java.base/share/classes/java/lang/invoke/ClassSpecializer.java
index 3c61306f4d6..b49fb861165 100644
--- a/src/java.base/share/classes/java/lang/invoke/ClassSpecializer.java
+++ b/src/java.base/share/classes/java/lang/invoke/ClassSpecializer.java
@@ -33,6 +33,7 @@
import java.lang.classfile.*;
import java.lang.classfile.attribute.ExceptionsAttribute;
+import java.lang.classfile.attribute.RuntimeVisibleAnnotationsAttribute;
import java.lang.classfile.attribute.SourceFileAttribute;
import java.lang.constant.ClassDesc;
import java.lang.constant.MethodTypeDesc;
@@ -78,6 +79,9 @@ abstract class ClassSpecializer.SpeciesDat
private static final ClassDesc CD_LambdaForm = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/invoke/LambdaForm;");
private static final ClassDesc CD_BoundMethodHandle = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/invoke/BoundMethodHandle;");
+ private static final RuntimeVisibleAnnotationsAttribute STABLE_ANNOTATION = RuntimeVisibleAnnotationsAttribute.of(
+ Annotation.of(ConstantUtils.referenceClassDesc(Stable.class))
+ );
private final Class topClass;
private final Class keyType;
@@ -628,7 +632,7 @@ Class extends T> generateConcreteSpeciesCode(String className, ClassSpecialize
byte[] generateConcreteSpeciesCodeFile(String className0, ClassSpecializer.SpeciesData speciesData) {
final ClassDesc classDesc = ClassDesc.of(className0);
final ClassDesc superClassDesc = classDesc(speciesData.deriveSuperClass());
- return ClassFile.of().build(classDesc, new Consumer() {
+ return ClassFile.of().build(classDesc, new Consumer<>() {
@Override
public void accept(ClassBuilder clb) {
clb.withFlags(ACC_FINAL | ACC_SUPER)
@@ -636,7 +640,13 @@ public void accept(ClassBuilder clb) {
.with(SourceFileAttribute.of(classDesc.displayName()))
// emit static types and BMH_SPECIES fields
- .withField(sdFieldName, CD_SPECIES_DATA, ACC_STATIC);
+ .withField(sdFieldName, CD_SPECIES_DATA, new Consumer<>() {
+ @Override
+ public void accept(FieldBuilder fb) {
+ fb.withFlags(ACC_STATIC)
+ .with(STABLE_ANNOTATION);
+ }
+ });
// handy holder for dealing with groups of typed values (ctor arguments and fields)
class Var {
diff --git a/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java b/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java
index ec131d67f2b..ffd368f47c1 100644
--- a/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java
+++ b/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java
@@ -526,7 +526,9 @@ private boolean checkActualReceiver(CodeBuilder cob) {
// Suppress method in backtraces displayed to the user, mark this method as
// a compiled LambdaForm, then either force or prohibit inlining.
public static final RuntimeVisibleAnnotationsAttribute LF_DONTINLINE_ANNOTATIONS = RuntimeVisibleAnnotationsAttribute.of(HIDDEN, LF_COMPILED, DONTINLINE);
+ public static final RuntimeVisibleAnnotationsAttribute LF_DONTINLINE_PROFILE_ANNOTATIONS = RuntimeVisibleAnnotationsAttribute.of(HIDDEN, LF_COMPILED, DONTINLINE, INJECTEDPROFILE);
public static final RuntimeVisibleAnnotationsAttribute LF_FORCEINLINE_ANNOTATIONS = RuntimeVisibleAnnotationsAttribute.of(HIDDEN, LF_COMPILED, FORCEINLINE);
+ public static final RuntimeVisibleAnnotationsAttribute LF_FORCEINLINE_PROFILE_ANNOTATIONS = RuntimeVisibleAnnotationsAttribute.of(HIDDEN, LF_COMPILED, FORCEINLINE, INJECTEDPROFILE);
/**
* Generate an invoker method for the passed {@link LambdaForm}.
@@ -586,7 +588,11 @@ public void accept(CodeBuilder cob) {
if (PROFILE_GWT) {
assert(name.arguments[0] instanceof Name n &&
n.refersTo(MethodHandleImpl.class, "profileBoolean"));
- mb.with(RuntimeVisibleAnnotationsAttribute.of(List.of(INJECTEDPROFILE)));
+ if (lambdaForm.forceInline) {
+ mb.with(LF_FORCEINLINE_PROFILE_ANNOTATIONS);
+ } else {
+ mb.with(LF_DONTINLINE_PROFILE_ANNOTATIONS);
+ }
}
onStack = emitSelectAlternative(cob, name, lambdaForm.names[i+1]);
i++; // skip MH.invokeBasic of the selectAlternative result
diff --git a/src/java.base/share/classes/java/net/Socket.java b/src/java.base/share/classes/java/net/Socket.java
index 309fa7a80d0..5fe6d1e0bb3 100644
--- a/src/java.base/share/classes/java/net/Socket.java
+++ b/src/java.base/share/classes/java/net/Socket.java
@@ -2057,7 +2057,6 @@ public Socket setOption(SocketOption name, T value) throws IOException {
*
* @since 9
*/
- @SuppressWarnings("unchecked")
public T getOption(SocketOption name) throws IOException {
Objects.requireNonNull(name);
if (isClosed())
diff --git a/src/java.base/share/classes/java/security/Provider.java b/src/java.base/share/classes/java/security/Provider.java
index 4de97fe8931..beb3196c6bf 100644
--- a/src/java.base/share/classes/java/security/Provider.java
+++ b/src/java.base/share/classes/java/security/Provider.java
@@ -33,6 +33,7 @@
import jdk.internal.event.SecurityProviderServiceEvent;
+import javax.crypto.KDFParameters;
import javax.security.auth.login.Configuration;
import java.io.*;
import java.security.cert.CertStoreParameters;
@@ -1619,6 +1620,7 @@ private static void addEngine(String name, boolean sp, Class> constructorParam
addEngine("KeyGenerator", false, null);
addEngine("SecretKeyFactory", false, null);
addEngine("KEM", true, null);
+ addEngine("KDF", false, KDFParameters.class);
// JSSE
addEngine("KeyManagerFactory", false, null);
addEngine("SSLContext", false, null);
diff --git a/src/java.base/share/classes/java/util/concurrent/StructuredTaskScope.java b/src/java.base/share/classes/java/util/concurrent/StructuredTaskScope.java
index edb2708934d..17448e9bf3d 100644
--- a/src/java.base/share/classes/java/util/concurrent/StructuredTaskScope.java
+++ b/src/java.base/share/classes/java/util/concurrent/StructuredTaskScope.java
@@ -261,8 +261,8 @@
* {@snippet lang=java :
* private static final ScopedValue USERNAME = ScopedValue.newInstance();
*
- * // @link substring="runWhere" target="ScopedValue#runWhere(ScopedValue, Object, Runnable)" :
- * ScopedValue.runWhere(USERNAME, "duke", () -> {
+ * // @link substring="run" target="ScopedValue.Carrier#run(Runnable)" :
+ * ScopedValue.where(USERNAME, "duke").run(() -> {
* try (var scope = new StructuredTaskScope()) {
*
* scope.fork(() -> childTask()); // @highlight substring="fork"
@@ -1007,9 +1007,9 @@ public static final class ShutdownOnSuccess extends StructuredTaskScope {
*
* Construction captures the current thread's {@linkplain ScopedValue scoped
* value} bindings for inheritance by threads started in the task scope. The
- * Tree Structure section in the class description
- * details how parent-child relations are established implicitly for the purpose
- * of inheritance of scoped value bindings.
+ * {@linkplain StructuredTaskScope##TreeStructure Tree Structure} section
+ * in the class description details how parent-child relations are established
+ * implicitly for the purpose of inheritance of scoped value bindings.
*
* @param name the name of the task scope, can be null
* @param factory the thread factory
@@ -1187,7 +1187,7 @@ public static final class ShutdownOnFailure extends StructuredTaskScope
*
* Construction captures the current thread's {@linkplain ScopedValue scoped
* value} bindings for inheritance by threads started in the task scope. The
- * Tree Structure section in the class description
+ * {@linkplain StructuredTaskScope##TreeStructure Tree Structure} section in the class description
* details how parent-child relations are established implicitly for the purpose
* of inheritance of scoped value bindings.
*
diff --git a/src/java.base/share/classes/javax/crypto/KDF.java b/src/java.base/share/classes/javax/crypto/KDF.java
new file mode 100644
index 00000000000..0ee0904c1c2
--- /dev/null
+++ b/src/java.base/share/classes/javax/crypto/KDF.java
@@ -0,0 +1,697 @@
+/*
+ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. 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 javax.crypto;
+
+import jdk.internal.javac.PreviewFeature;
+import sun.security.jca.GetInstance;
+import sun.security.jca.GetInstance.Instance;
+import sun.security.util.Debug;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.Security;
+import java.security.Provider;
+import java.security.Provider.Service;
+import java.security.spec.AlgorithmParameterSpec;
+import java.util.Iterator;
+import java.util.Objects;
+
+/**
+ * This class provides the functionality of a Key Derivation Function (KDF),
+ * which is a cryptographic algorithm for deriving additional keys from input
+ * keying material (IKM) and (optionally) other data.
+ *
+ * {@code KDF} objects are instantiated with the {@code getInstance} family of
+ * methods.
+ *
+ * The class has two derive methods, {@code deriveKey} and {@code deriveData}.
+ * The {@code deriveKey} method accepts an algorithm name and returns a
+ * {@code SecretKey} object with the specified algorithm. The {@code deriveData}
+ * method returns a byte array of raw data.
+ *
+ * API Usage Example:
+ * {@snippet lang = java:
+ * KDF kdfHkdf = KDF.getInstance("HKDF-SHA256");
+ *
+ * AlgorithmParameterSpec derivationSpec =
+ * HKDFParameterSpec.ofExtract()
+ * .addIKM(ikm)
+ * .addSalt(salt).thenExpand(info, 32);
+ *
+ * SecretKey sKey = kdfHkdf.deriveKey("AES", derivationSpec);
+ *}
+ *
+ *
+ * Unless otherwise documented by an implementation, the methods defined in this
+ * class are not thread-safe. Multiple threads that need to access a single
+ * object concurrently should synchronize amongst themselves and provide the
+ * necessary locking. Multiple threads each manipulating separate objects need
+ * not synchronize.
+ *
+ *
+ * If a provider is not specified when calling one of the {@code getInstance}
+ * methods, the implementation delays the selection of the provider until the
+ * {@code deriveKey} or {@code deriveData} method is called. This is called
+ * delayed provider selection . The primary reason this is done is to
+ * ensure that the selected provider can handle the key material that is passed
+ * to those methods - for example, the key material may reside on a hardware
+ * device that only a specific {@code KDF} provider can utilize. The {@code
+ * getInstance} method returns a {@code KDF} object as long as there exists
+ * at least one registered security provider that implements the algorithm
+ * and supports the optional parameters. The delayed provider selection
+ * process traverses the list of registered security providers, starting with
+ * the most preferred {@code Provider}. The first provider that supports the
+ * specified algorithm, optional parameters, and key material is selected.
+ *
+ * If the {@code getProviderName} or {@code getParameters} method is called
+ * before the {@code deriveKey} or {@code deriveData} methods, the first
+ * provider supporting the {@code KDF} algorithm and optional
+ * {@code KDFParameters} is chosen. This provider may not support the key
+ * material that is subsequently passed to the {@code deriveKey} or
+ * {@code deriveData} methods. Therefore, it is recommended not to call the
+ * {@code getProviderName} or {@code getParameters} methods until after a key
+ * derivation operation. Once a provider is selected, it cannot be changed.
+ *
+ * @see KDFParameters
+ * @see SecretKey
+ * @since 24
+ */
+@PreviewFeature(feature = PreviewFeature.Feature.KEY_DERIVATION)
+public final class KDF {
+
+ private static final Debug pdebug = Debug.getInstance("provider",
+ "Provider");
+ private static final boolean skipDebug = Debug.isOn("engine=")
+ && !Debug.isOn("kdf");
+
+ private record Delegate(KDFSpi spi, Provider provider) {}
+
+ //guarded by 'lock'
+ private Delegate theOne;
+ //guarded by 'lock'
+ private final Delegate candidate;
+
+ // The name of the KDF algorithm.
+ private final String algorithm;
+
+ // Additional KDF configuration parameters
+ private final KDFParameters kdfParameters;
+
+ // remaining services to try in provider selection
+ // null once provider is selected
+ private final Iterator serviceIterator;
+
+ // This lock provides mutual exclusion, preventing multiple threads from
+ // concurrently initializing the same instance (delayed provider selection)
+ // in a way which would corrupt the internal state.
+ private final Object lock = new Object();
+
+
+ // Instantiates a {@code KDF} object. This constructor is called when a
+ // provider is supplied to {@code getInstance}.
+ //
+ // @param delegate the delegate
+ // @param algorithm the algorithm
+ // @param kdfParameters the parameters
+ private KDF(Delegate delegate, String algorithm) {
+ this.theOne = delegate;
+ this.algorithm = algorithm;
+ // note that the parameters are being passed to the impl in getInstance
+ this.kdfParameters = null;
+ this.candidate = null;
+ serviceIterator = null;
+ }
+
+ // Instantiates a {@code KDF} object. This constructor is called when a
+ // provider is not supplied to {@code getInstance}.
+ //
+ // @param firstPairOfSpiAndProv the delegate
+ // @param t the service iterator
+ // @param algorithm the algorithm
+ // @param kdfParameters the algorithm parameters
+ private KDF(Delegate firstPairOfSpiAndProv, Iterator t,
+ String algorithm,
+ KDFParameters kdfParameters) {
+ this.candidate = firstPairOfSpiAndProv;
+ serviceIterator = t;
+ this.algorithm = algorithm;
+ this.kdfParameters = kdfParameters;
+ }
+
+ /**
+ * Returns the algorithm name of this {@code KDF} object.
+ *
+ * @return the algorithm name of this {@code KDF} object
+ */
+ public String getAlgorithm() {
+ return this.algorithm;
+ }
+
+ /**
+ * Returns the name of the provider.
+ *
+ * @return the name of the provider
+ *
+ * @see Delayed Provider
+ * Selection
+ */
+ public String getProviderName() {
+ useFirstSpi();
+ return theOne.provider().getName();
+ }
+
+ /**
+ * Returns the {@code KDFParameters} used with this {@code KDF} object.
+ *
+ * The returned parameters may be the same that were used to initialize
+ * this {@code KDF} object, or may contain additional default or
+ * random parameter values used by the underlying KDF algorithm.
+ * If the required parameters were not supplied and can be generated by
+ * the {@code KDF} object, the generated parameters are returned;
+ * otherwise {@code null} is returned.
+ *
+ * @return the parameters used with this {@code KDF} object, or
+ * {@code null}
+ *
+ * @see Delayed Provider
+ * Selection
+ */
+ public KDFParameters getParameters() {
+ useFirstSpi();
+ return theOne.spi().engineGetParameters();
+ }
+
+ /**
+ * Returns a {@code KDF} object that implements the specified algorithm.
+ *
+ * @implNote The JDK Reference Implementation additionally uses the
+ * {@code jdk.security.provider.preferred}
+ * {@link Security#getProperty(String) Security} property to
+ * determine the preferred provider order for the specified
+ * algorithm. This may be different than the order of providers
+ * returned by
+ * {@link Security#getProviders() Security.getProviders()}.
+ *
+ * @param algorithm
+ * the key derivation algorithm to use. See the {@code KDF} section
+ * in the
+ * Java Security Standard Algorithm Names Specification for
+ * information about standard KDF algorithm names.
+ *
+ * @return a {@code KDF} object
+ *
+ * @throws NoSuchAlgorithmException
+ * if no {@code Provider} supports a {@code KDF} implementation for
+ * the specified algorithm
+ * @throws NullPointerException
+ * if {@code algorithm} is {@code null}
+ * @see Delayed Provider
+ * Selection
+ */
+ public static KDF getInstance(String algorithm)
+ throws NoSuchAlgorithmException {
+ Objects.requireNonNull(algorithm, "algorithm must not be null");
+ try {
+ return getInstance(algorithm, (KDFParameters) null);
+ } catch (InvalidAlgorithmParameterException e) {
+ throw new NoSuchAlgorithmException(
+ "No implementation found using null KDFParameters", e);
+ }
+ }
+
+ /**
+ * Returns a {@code KDF} object that implements the specified algorithm from
+ * the specified security provider. The specified provider must be
+ * registered in the security provider list.
+ *
+ * @param algorithm
+ * the key derivation algorithm to use. See the {@code KDF} section
+ * in the
+ * Java Security Standard Algorithm Names Specification for
+ * information about standard KDF algorithm names.
+ * @param provider
+ * the provider to use for this key derivation
+ *
+ * @return a {@code KDF} object
+ *
+ * @throws NoSuchAlgorithmException
+ * if the specified provider does not support the specified
+ * {@code KDF} algorithm
+ * @throws NoSuchProviderException
+ * if the specified provider is not registered in the security
+ * provider list
+ * @throws NullPointerException
+ * if {@code algorithm} or {@code provider} is {@code null}
+ */
+ public static KDF getInstance(String algorithm, String provider)
+ throws NoSuchAlgorithmException, NoSuchProviderException {
+ Objects.requireNonNull(algorithm, "algorithm must not be null");
+ Objects.requireNonNull(provider, "provider must not be null");
+ try {
+ return getInstance(algorithm, null, provider);
+ } catch (InvalidAlgorithmParameterException e) {
+ throw new NoSuchAlgorithmException(
+ "No implementation found using null KDFParameters", e);
+ }
+ }
+
+ /**
+ * Returns a {@code KDF} object that implements the specified algorithm from
+ * the specified security provider.
+ *
+ * @param algorithm
+ * the key derivation algorithm to use. See the {@code KDF} section
+ * in the
+ * Java Security Standard Algorithm Names Specification for
+ * information about standard KDF algorithm names.
+ * @param provider
+ * the provider to use for this key derivation
+ *
+ * @return a {@code KDF} object
+ *
+ * @throws NoSuchAlgorithmException
+ * if the specified provider does not support the specified
+ * {@code KDF} algorithm
+ * @throws NullPointerException
+ * if {@code algorithm} or {@code provider} is {@code null}
+ */
+ public static KDF getInstance(String algorithm, Provider provider)
+ throws NoSuchAlgorithmException {
+ Objects.requireNonNull(algorithm, "algorithm must not be null");
+ Objects.requireNonNull(provider, "provider must not be null");
+ try {
+ return getInstance(algorithm, null, provider);
+ } catch (InvalidAlgorithmParameterException e) {
+ throw new NoSuchAlgorithmException(
+ "No implementation found using null KDFParameters", e);
+ }
+ }
+
+ /**
+ * Returns a {@code KDF} object that implements the specified algorithm and
+ * is initialized with the specified parameters.
+ *
+ * @implNote The JDK Reference Implementation additionally uses the
+ * {@code jdk.security.provider.preferred}
+ * {@link Security#getProperty(String) Security} property to
+ * determine the preferred provider order for the specified
+ * algorithm. This may be different than the order of providers
+ * returned by
+ * {@link Security#getProviders() Security.getProviders()}.
+ *
+ * @param algorithm
+ * the key derivation algorithm to use. See the {@code KDF} section
+ * in the
+ * Java Security Standard Algorithm Names Specification for
+ * information about standard KDF algorithm names.
+ * @param kdfParameters
+ * the {@code KDFParameters} used to configure the derivation
+ * algorithm or {@code null} if no parameters are provided
+ *
+ * @return a {@code KDF} object
+ *
+ * @throws NoSuchAlgorithmException
+ * if no {@code Provider} supports a {@code KDF} implementation for
+ * the specified algorithm
+ * @throws InvalidAlgorithmParameterException
+ * if at least one {@code Provider} supports a {@code KDF}
+ * implementation for the specified algorithm but none of them
+ * support the specified parameters
+ * @throws NullPointerException
+ * if {@code algorithm} is {@code null}
+ * @see Delayed Provider
+ * Selection
+ */
+ public static KDF getInstance(String algorithm,
+ KDFParameters kdfParameters)
+ throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
+ Objects.requireNonNull(algorithm, "algorithm must not be null");
+ // make sure there is at least one service from a signed provider
+ Iterator t = GetInstance.getServices("KDF", algorithm);
+
+ Delegate d = getNext(t, kdfParameters);
+ return (t.hasNext() ?
+ new KDF(d, t, algorithm, kdfParameters) :
+ new KDF(d, algorithm));
+ }
+
+ /**
+ * Returns a {@code KDF} object that implements the specified algorithm from
+ * the specified provider and is initialized with the specified parameters.
+ * The specified provider must be registered in the security provider list.
+ *
+ * @param algorithm
+ * the key derivation algorithm to use. See the {@code KDF} section
+ * in the
+ * Java Security Standard Algorithm Names Specification for
+ * information about standard KDF algorithm names.
+ * @param kdfParameters
+ * the {@code KDFParameters} used to configure the derivation
+ * algorithm or {@code null} if no parameters are provided
+ * @param provider
+ * the provider to use for this key derivation
+ *
+ * @return a {@code KDF} object
+ *
+ * @throws NoSuchAlgorithmException
+ * if the specified provider does not support the specified
+ * {@code KDF} algorithm
+ * @throws NoSuchProviderException
+ * if the specified provider is not registered in the security
+ * provider list
+ * @throws InvalidAlgorithmParameterException
+ * if the specified provider supports the specified {@code KDF}
+ * algorithm but does not support the specified parameters
+ * @throws NullPointerException
+ * if {@code algorithm} or {@code provider} is {@code null}
+ */
+ public static KDF getInstance(String algorithm,
+ KDFParameters kdfParameters,
+ String provider)
+ throws NoSuchAlgorithmException, NoSuchProviderException,
+ InvalidAlgorithmParameterException {
+ Objects.requireNonNull(algorithm, "algorithm must not be null");
+ Objects.requireNonNull(provider, "provider must not be null");
+ try {
+ Instance instance = GetInstance.getInstance("KDF", KDFSpi.class,
+ algorithm,
+ kdfParameters,
+ provider);
+ if (!JceSecurity.canUseProvider(instance.provider)) {
+ String msg = "JCE cannot authenticate the provider "
+ + instance.provider.getName();
+ throw new NoSuchProviderException(msg);
+ }
+ return new KDF(new Delegate((KDFSpi) instance.impl,
+ instance.provider), algorithm);
+ } catch (NoSuchAlgorithmException nsae) {
+ return handleException(nsae);
+ }
+ }
+
+ /**
+ * Returns a {@code KDF} object that implements the specified algorithm from
+ * the specified provider and is initialized with the specified parameters.
+ *
+ * @param algorithm
+ * the key derivation algorithm to use. See the {@code KDF} section
+ * in the
+ * Java Security Standard Algorithm Names Specification for
+ * information about standard KDF algorithm names.
+ * @param kdfParameters
+ * the {@code KDFParameters} used to configure the derivation
+ * algorithm or {@code null} if no parameters are provided
+ * @param provider
+ * the provider to use for this key derivation
+ *
+ * @return a {@code KDF} object
+ *
+ * @throws NoSuchAlgorithmException
+ * if the specified provider does not support the specified
+ * {@code KDF} algorithm
+ * @throws InvalidAlgorithmParameterException
+ * if the specified provider supports the specified {@code KDF}
+ * algorithm but does not support the specified parameters
+ * @throws NullPointerException
+ * if {@code algorithm} or {@code provider} is {@code null}
+ */
+ public static KDF getInstance(String algorithm,
+ KDFParameters kdfParameters,
+ Provider provider)
+ throws NoSuchAlgorithmException,
+ InvalidAlgorithmParameterException {
+ Objects.requireNonNull(algorithm, "algorithm must not be null");
+ Objects.requireNonNull(provider, "provider must not be null");
+ try {
+ Instance instance = GetInstance.getInstance("KDF", KDFSpi.class,
+ algorithm,
+ kdfParameters,
+ provider);
+ if (!JceSecurity.canUseProvider(instance.provider)) {
+ String msg = "JCE cannot authenticate the provider "
+ + instance.provider.getName();
+ throw new SecurityException(msg);
+ }
+ return new KDF(new Delegate((KDFSpi) instance.impl,
+ instance.provider), algorithm);
+ } catch (NoSuchAlgorithmException nsae) {
+ return handleException(nsae);
+ }
+ }
+
+ private static KDF handleException(NoSuchAlgorithmException e)
+ throws NoSuchAlgorithmException,
+ InvalidAlgorithmParameterException {
+ Throwable cause = e.getCause();
+ if (cause instanceof InvalidAlgorithmParameterException iape) {
+ throw iape;
+ }
+ throw e;
+ }
+
+ /**
+ * Derives a key, returned as a {@code SecretKey} object.
+ *
+ * @param alg
+ * the algorithm of the resultant {@code SecretKey} object
+ * @param derivationSpec
+ * the object describing the inputs to the derivation function
+ *
+ * @return the derived key
+ *
+ * @throws InvalidAlgorithmParameterException
+ * if the information contained within the {@code derivationSpec} is
+ * invalid or if the combination of {@code alg} and the
+ * {@code derivationSpec} results in something invalid
+ * @throws NoSuchAlgorithmException
+ * if {@code alg} is empty or invalid
+ * @throws NullPointerException
+ * if {@code alg} or {@code derivationSpec} is null
+ *
+ * @see Delayed Provider
+ * Selection
+ *
+ */
+ public SecretKey deriveKey(String alg,
+ AlgorithmParameterSpec derivationSpec)
+ throws InvalidAlgorithmParameterException,
+ NoSuchAlgorithmException {
+ if (alg == null) {
+ throw new NullPointerException(
+ "the algorithm for the SecretKey return value must not be"
+ + " null");
+ }
+ if (alg.isEmpty()) {
+ throw new NoSuchAlgorithmException(
+ "the algorithm for the SecretKey return value must not be "
+ + "empty");
+ }
+ Objects.requireNonNull(derivationSpec);
+ if (checkSpiNonNull(theOne)) {
+ return theOne.spi().engineDeriveKey(alg, derivationSpec);
+ } else {
+ return (SecretKey) chooseProvider(alg, derivationSpec);
+ }
+ }
+
+ /**
+ * Derives a key, returns raw data as a byte array.
+ *
+ * @param derivationSpec
+ * the object describing the inputs to the derivation function
+ *
+ * @return the derived key in its raw bytes
+ *
+ * @throws InvalidAlgorithmParameterException
+ * if the information contained within the {@code derivationSpec} is
+ * invalid
+ * @throws UnsupportedOperationException
+ * if the derived keying material is not extractable
+ * @throws NullPointerException
+ * if {@code derivationSpec} is null
+ *
+ * @see Delayed Provider
+ * Selection
+ *
+ */
+ public byte[] deriveData(AlgorithmParameterSpec derivationSpec)
+ throws InvalidAlgorithmParameterException {
+
+ Objects.requireNonNull(derivationSpec);
+ if (checkSpiNonNull(theOne)) {
+ return theOne.spi().engineDeriveData(derivationSpec);
+ } else {
+ try {
+ return (byte[]) chooseProvider(null, derivationSpec);
+ } catch (NoSuchAlgorithmException e) {
+ // this will never be thrown in the deriveData case
+ throw new AssertionError(e);
+ }
+ }
+ }
+
+ /**
+ * Use the firstSpi as the chosen KDFSpi and set the fields accordingly
+ */
+ private void useFirstSpi() {
+ if (checkSpiNonNull(theOne)) return;
+
+ synchronized (lock) {
+ if (!checkSpiNonNull(theOne)) {
+ theOne = candidate;
+ }
+ }
+ }
+
+ /**
+ * Selects the provider which supports the passed {@code algorithm} and
+ * {@code derivationSpec} values, and assigns the global spi and provider
+ * variables if they have not been assigned yet.
+ *
+ * If the spi has already been set, it will just return the result.
+ */
+ private Object chooseProvider(String algorithm,
+ AlgorithmParameterSpec derivationSpec)
+ throws InvalidAlgorithmParameterException,
+ NoSuchAlgorithmException {
+
+ boolean isDeriveData = (algorithm == null);
+
+ synchronized (lock) {
+ if (checkSpiNonNull(theOne)) {
+ return (isDeriveData) ?
+ theOne.spi().engineDeriveData(derivationSpec) :
+ theOne.spi().engineDeriveKey(algorithm, derivationSpec);
+ }
+
+ Exception lastException = null;
+ if (!checkSpiNonNull(candidate)) {
+ throw new AssertionError("Unexpected Error: candidate is null!");
+ }
+ Delegate currOne = candidate;
+ try {
+ while (true) {
+ try {
+ Object result = (isDeriveData) ?
+ currOne.spi().engineDeriveData(derivationSpec) :
+ currOne.spi().engineDeriveKey(algorithm,
+ derivationSpec);
+ // found a working KDFSpi
+ this.theOne = currOne;
+ return result;
+ } catch (Exception e) {
+ if (!skipDebug && pdebug != null) {
+ pdebug.println("A " + this.getAlgorithm()
+ + " derivation cannot be performed "
+ + "using the supplied derivation "
+ + "inputs, using "
+ + currOne.provider().getName()
+ + ". Another Provider will be "
+ + "attempted.");
+ e.printStackTrace(pdebug.getPrintStream());
+ }
+ if (lastException == null) {
+ lastException = e;
+ }
+ // try next one if available
+ assert serviceIterator != null : "serviceIterator was null";
+ currOne = getNext(serviceIterator, kdfParameters);
+ }
+ }
+ } catch (InvalidAlgorithmParameterException e) {
+ throw e; // getNext reached end and have seen IAPE
+ } catch (NoSuchAlgorithmException e) {
+ if (!skipDebug && pdebug != null) {
+ pdebug.println(
+ "All available Providers have been examined "
+ + "without a match for performing the "
+ + this.getAlgorithm()
+ + " derivation using the supplied derivation "
+ + "inputs. Therefore, the caught "
+ + "NoSuchAlgorithmException will be logged, and "
+ + "an InvalidAlgorithmParameterException will "
+ + "then be thrown with the last known Exception.");
+ e.printStackTrace(pdebug.getPrintStream());
+ }
+ // getNext reached end without finding an implementation
+ throw new InvalidAlgorithmParameterException(lastException);
+ }
+ }
+ }
+
+ private static Delegate getNext(Iterator serviceIter,
+ KDFParameters kdfParameters)
+ throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
+ // fetch next one if available
+ boolean hasOne = false;
+ while (serviceIter.hasNext()) {
+ Service s = serviceIter.next();
+ Provider prov = s.getProvider();
+ if (!JceSecurity.canUseProvider(prov)) {
+ // continue to next iteration
+ continue;
+ }
+ hasOne = true;
+ try {
+ Object obj = s.newInstance(kdfParameters);
+ if (!(obj instanceof KDFSpi)) {
+ if (!skipDebug && pdebug != null) {
+ pdebug.println(
+ "obj was not an instance of KDFSpi (should not "
+ + "happen)");
+ }
+ continue;
+ }
+ return new Delegate((KDFSpi) obj, prov);
+ } catch (NoSuchAlgorithmException nsae) {
+ // continue to the next provider
+ if (!skipDebug && pdebug != null) {
+ pdebug.println("A derivation cannot be performed "
+ + "using the supplied KDFParameters, using "
+ + prov.getName()
+ + ". Another Provider will be attempted.");
+ nsae.printStackTrace(pdebug.getPrintStream());
+ }
+ }
+ }
+ if (!skipDebug && pdebug != null) {
+ pdebug.println(
+ "No provider can be found that supports the "
+ + "specified algorithm and parameters");
+ }
+ if (hasOne) throw new InvalidAlgorithmParameterException(
+ "The KDFParameters supplied could not be used in combination "
+ + "with the supplied algorithm for the selected Provider");
+ else throw new NoSuchAlgorithmException(
+ "No available provider supports the specified algorithm");
+ }
+
+ private static boolean checkSpiNonNull(Delegate d) {
+ // d.spi() cannot be null if d != null
+ return (d != null);
+ }
+}
diff --git a/src/java.base/share/classes/javax/crypto/KDFParameters.java b/src/java.base/share/classes/javax/crypto/KDFParameters.java
new file mode 100644
index 00000000000..5f83204f3c4
--- /dev/null
+++ b/src/java.base/share/classes/javax/crypto/KDFParameters.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. 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 javax.crypto;
+
+import jdk.internal.javac.PreviewFeature;
+
+/**
+ * A specification of Key Derivation Function ({@link KDF}) parameters.
+ *
+ * The purpose of this interface is to group (and provide type safety for) all
+ * {@code KDF} parameter specifications. All {@code KDF} parameter
+ * specifications must implement this interface.
+ *
+ * When supplied, the
+ * {@link KDF#getInstance(String, KDFParameters) KDF.getInstance} methods return
+ * a {@code KDF} that is initialized with the specified parameters.
+ *
+ * The {@code KDFParameters} used for initialization are returned by
+ * {@link KDF#getParameters()} and may contain additional default or random
+ * parameter values used by the underlying KDF implementation.
+ *
+ * @see KDF#getInstance(String, KDFParameters)
+ * @see KDF#getParameters()
+ * @see KDF
+ * @since 24
+ */
+@PreviewFeature(feature = PreviewFeature.Feature.KEY_DERIVATION)
+public interface KDFParameters {}
diff --git a/src/java.base/share/classes/javax/crypto/KDFSpi.java b/src/java.base/share/classes/javax/crypto/KDFSpi.java
new file mode 100644
index 00000000000..dcd2029c0c0
--- /dev/null
+++ b/src/java.base/share/classes/javax/crypto/KDFSpi.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. 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 javax.crypto;
+
+import jdk.internal.javac.PreviewFeature;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.NoSuchAlgorithmException;
+import java.security.spec.AlgorithmParameterSpec;
+
+/**
+ * This class defines the Service Provider Interface (SPI ) for the
+ * Key Derivation Function ({@link KDF}) class.
+ *
+ * All the abstract methods in this class must be implemented by each
+ * cryptographic service provider who wishes to supply the implementation of a
+ * particular key derivation function algorithm.
+ *
+ * Implementations must provide a public constructor which accepts a {@code
+ * KDFParameters} object if they depend on the default implementation of
+ * {@code Provider.Service.newInstance} to construct {@code KDFSpi} instances.
+ * The constructor must call {@code super(params)} passing the parameters
+ * supplied. The constructor must also throw an
+ * {@code InvalidAlgorithmParameterException} if the supplied parameters are
+ * inappropriate. If a {@code KDF} object is instantiated with one of the
+ * {@code getInstance} methods that contains a {@code KDFParameters} parameter,
+ * the user-provided {@code KDFParameters} object will be passed to the
+ * constructor of the {@code KDFSpi} implementation. Otherwise, if it is
+ * instantiated with one of the {@code getInstance} methods without a
+ * {@code KDFParameters} parameter, a {@code null} value will be passed to the
+ * constructor.
+ *
+ * Implementations which do not support {@code KDFParameters} must require
+ * {@code null} to be passed, otherwise an
+ * {@code InvalidAlgorithmParameterException} will be thrown. On the other hand,
+ * implementations which require {@code KDFParameters} should throw an
+ * {@code InvalidAlgorithmParameterException} upon receiving a {@code null}
+ * value if default parameters cannot be generated or upon receiving {@code
+ * KDFParameters} which are not supported by the implementation.
+ *
+ * To aid the caller, implementations may return parameters with additional
+ * default values or supply random values as used by the underlying {@code KDF}
+ * algorithm. See {@link KDFSpi#engineGetParameters()} for more details.
+ *
+ * @see KDF
+ * @see KDFParameters
+ * @see KDF#getParameters()
+ * @see SecretKey
+ * @since 24
+ */
+@PreviewFeature(feature = PreviewFeature.Feature.KEY_DERIVATION)
+public abstract class KDFSpi {
+
+ /**
+ * The sole constructor.
+ *
+ * A {@code KDFParameters} object may be specified for KDF algorithms that
+ * support initialization parameters.
+ *
+ * @param kdfParameters
+ * the initialization parameters for the {@code KDF} algorithm (may
+ * be {@code null})
+ *
+ * @throws InvalidAlgorithmParameterException
+ * if the initialization parameters are inappropriate for this
+ * {@code KDFSpi}
+ * @see KDF#getParameters()
+ */
+ protected KDFSpi(KDFParameters kdfParameters)
+ throws InvalidAlgorithmParameterException {}
+
+ /**
+ * Returns the {@code KDFParameters} used with this {@code KDF} object.
+ *
+ * The returned parameters may be the same that were used to initialize
+ * this {@code KDF} object, or may contain additional default or
+ * random parameter values used by the underlying KDF algorithm.
+ * If the required parameters were not supplied and can be generated by
+ * the {@code KDF} object, the generated parameters are returned;
+ * otherwise {@code null} is returned.
+ *
+ * @return the parameters used with this {@code KDF} object, or
+ * {@code null}
+ */
+ protected abstract KDFParameters engineGetParameters();
+
+ /**
+ * Derives a key, returned as a {@code SecretKey} object.
+ *
+ * @implNote If the resultant key is extractable, then its
+ * {@code getEncoded} value should have the same content as the
+ * result of {@code deriveData}.
+ *
+ * @param alg
+ * the algorithm of the resultant {@code SecretKey} object
+ * @param derivationSpec
+ * derivation parameters
+ *
+ * @return the derived key.
+ *
+ * @throws InvalidAlgorithmParameterException
+ * if the information contained within the {@code derivationSpec} is
+ * invalid or if the combination of {@code alg} and the
+ * {@code derivationSpec} results in something invalid
+ * @throws NoSuchAlgorithmException
+ * if {@code alg} is empty or invalid
+ * @throws NullPointerException
+ * if {@code alg} or {@code derivationSpec} is null
+ */
+ protected abstract SecretKey engineDeriveKey(String alg,
+ AlgorithmParameterSpec derivationSpec)
+ throws InvalidAlgorithmParameterException, NoSuchAlgorithmException;
+
+ /**
+ * Derives a key, returns raw data as a byte array.
+ *
+ * @param derivationSpec
+ * derivation parameters
+ *
+ * @return the derived key in its raw bytes.
+ *
+ * @throws InvalidAlgorithmParameterException
+ * if the information contained within the {@code derivationSpec} is
+ * invalid
+ * @throws UnsupportedOperationException
+ * if the derived keying material is not extractable
+ * @throws NullPointerException
+ * if {@code derivationSpec} is null
+ */
+ protected abstract byte[] engineDeriveData(
+ AlgorithmParameterSpec derivationSpec)
+ throws InvalidAlgorithmParameterException;
+
+}
\ No newline at end of file
diff --git a/src/java.base/share/classes/javax/crypto/spec/HKDFParameterSpec.java b/src/java.base/share/classes/javax/crypto/spec/HKDFParameterSpec.java
new file mode 100644
index 00000000000..8f697d12e60
--- /dev/null
+++ b/src/java.base/share/classes/javax/crypto/spec/HKDFParameterSpec.java
@@ -0,0 +1,510 @@
+/*
+ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. 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 javax.crypto.spec;
+
+import jdk.internal.javac.PreviewFeature;
+
+import javax.crypto.SecretKey;
+import java.security.spec.AlgorithmParameterSpec;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Parameters for the combined Extract, Expand, or Extract-then-Expand
+ * operations of the HMAC-based Key Derivation Function (HKDF). The HKDF
+ * function is defined in RFC
+ * 5869 .
+ *
+ * In the Extract and Extract-then-Expand cases, users may call the {@code
+ * addIKM} and/or {@code addSalt} methods repeatedly (and chain these calls).
+ * This provides for use-cases where a portion of the input keying material
+ * (IKM) resides in a non-extractable {@code SecretKey} and the whole IKM
+ * cannot be provided as a single object. The same feature is available for
+ * salts.
+ *
+ * The above feature is particularly useful for "labeled" HKDF Extract used in
+ * TLS 1.3 and HPKE, where the IKM consists of concatenated components, which
+ * may include both byte arrays and (possibly non-extractable) secret keys.
+ *
+ * Examples:
+ * {@snippet lang = java:
+ * // this usage depicts the initialization of an HKDF-Extract AlgorithmParameterSpec
+ * AlgorithmParameterSpec derivationSpec =
+ * HKDFParameterSpec.ofExtract()
+ * .addIKM(label)
+ * .addIKM(ikm)
+ * .addSalt(salt).extractOnly();
+ *}
+ * {@snippet lang = java:
+ * // this usage depicts the initialization of an HKDF-Expand AlgorithmParameterSpec
+ * AlgorithmParameterSpec derivationSpec =
+ * HKDFParameterSpec.expandOnly(prk, info, 32);
+ *}
+ * {@snippet lang = java:
+ * // this usage depicts the initialization of an HKDF-ExtractExpand AlgorithmParameterSpec
+ * AlgorithmParameterSpec derivationSpec =
+ * HKDFParameterSpec.ofExtract()
+ * .addIKM(ikm)
+ * .addSalt(salt).thenExpand(info, 32);
+ *}
+ *
+ * @spec https://www.rfc-editor.org/info/rfc5869
+ * RFC 5869: HMAC-based Extract-and-Expand Key Derivation Function (HKDF)
+ * @see javax.crypto.KDF
+ * @since 24
+ */
+@PreviewFeature(feature = PreviewFeature.Feature.KEY_DERIVATION)
+public interface HKDFParameterSpec extends AlgorithmParameterSpec {
+
+ /**
+ * This {@code Builder} builds {@code Extract} and {@code ExtractThenExpand}
+ * objects.
+ *
+ * The {@code Builder} is initialized via the {@code ofExtract} method of
+ * {@code HKDFParameterSpec}. As stated in the class description,
+ * {@code addIKM} and/or {@code addSalt} may be called as needed. Finally,
+ * an object is "built" by calling either {@code extractOnly} or
+ * {@code thenExpand} for {@code Extract} and {@code ExtractThenExpand}
+ * use-cases respectively. Note that the {@code Builder} is not
+ * thread-safe.
+ */
+ @PreviewFeature(feature = PreviewFeature.Feature.KEY_DERIVATION)
+ final class Builder {
+
+ private List ikms = new ArrayList<>();
+ private List salts = new ArrayList<>();
+
+ private Builder() {}
+
+ /**
+ * Builds an {@code Extract} object from the current state of the
+ * {@code Builder}.
+ *
+ * @return an immutable {@code Extract} object
+ */
+ public Extract extractOnly() {
+ return new Extract(ikms, salts);
+ }
+
+ /**
+ * Builds an {@code ExtractThenExpand} object from the current state of
+ * the {@code Builder}.
+ *
+ * @implNote HKDF implementations will enforce that the length
+ * is not greater than 255 * HMAC length. HKDF implementations
+ * will also enforce that a {code null} info value is treated as
+ * zero-length byte array.
+ *
+ * @param info
+ * the optional context and application specific information
+ * (may be {@code null}); the byte array is cloned to prevent
+ * subsequent modification
+ * @param length
+ * the length of the output keying material (must be greater
+ * than 0)
+ *
+ * @return an immutable {@code ExtractThenExpand} object
+ *
+ * @throws IllegalArgumentException
+ * if {@code length} is not greater than 0
+ */
+ public ExtractThenExpand thenExpand(byte[] info, int length) {
+ return new ExtractThenExpand(
+ extractOnly(), info,
+ length);
+ }
+
+ /**
+ * Adds input keying material (IKM) to the builder.
+ *
+ * Users may call {@code addIKM} multiple times when the input keying
+ * material value is to be assembled piece-meal or if part of the IKM is
+ * to be supplied by a hardware crypto device. The {@code ikms()}
+ * method of the {@code Extract} or {@code ExtractThenExpand} object
+ * that is subsequently built returns the assembled input keying
+ * material as a list of {@code SecretKey} objects.
+ *
+ * @param ikm
+ * the input keying material (IKM) value
+ *
+ * @return this builder
+ *
+ * @throws NullPointerException
+ * if the {@code ikm} argument is null
+ */
+ public Builder addIKM(SecretKey ikm) {
+ Objects.requireNonNull(ikm, "ikm must not be null");
+ ikms.add(ikm);
+ return this;
+ }
+
+ /**
+ * Adds input keying material (IKM) to the builder. Note that an
+ * {@code ikm} byte array of length zero will be discarded.
+ *
+ * Users may call {@code addIKM} multiple times when the input keying
+ * material value is to be assembled piece-meal or if part of the IKM is
+ * to be supplied by a hardware crypto device. The {@code ikms()}
+ * method of the {@code Extract} or {@code ExtractThenExpand} object
+ * that is subsequently built returns the assembled input keying
+ * material as a list of {@code SecretKey} objects.
+ *
+ * @param ikm
+ * the input keying material (IKM) value; the {@code ikm}
+ * byte array will be converted to a {@code SecretKeySpec},
+ * which means that the byte array will be cloned inside the
+ * {@code SecretKeySpec} constructor
+ *
+ * @return this builder
+ *
+ * @throws NullPointerException
+ * if the {@code ikm} argument is null
+ */
+ public Builder addIKM(byte[] ikm) {
+ Objects.requireNonNull(ikm, "ikm must not be null");
+ if (ikm.length != 0) {
+ return addIKM(new SecretKeySpec(ikm, "Generic"));
+ } else {
+ return this;
+ }
+ }
+
+ /**
+ * Adds a salt to the builder.
+ *
+ * Users may call {@code addSalt} multiple times when the salt value is
+ * to be assembled piece-meal or if part of the salt is to be supplied
+ * by a hardware crypto device. The {@code salts()} method of the
+ * {@code Extract} or {@code ExtractThenExpand} object that is
+ * subsequently built returns the assembled salt as a list of
+ * {@code SecretKey} objects.
+ *
+ * @param salt
+ * the salt value
+ *
+ * @return this builder
+ *
+ * @throws NullPointerException
+ * if the {@code salt} is null
+ */
+ public Builder addSalt(SecretKey salt) {
+ Objects.requireNonNull(salt, "salt must not be null");
+ salts.add(salt);
+ return this;
+ }
+
+ /**
+ * Adds a salt to the builder. Note that a {@code salt} byte array of
+ * length zero will be discarded.
+ *
+ * Users may call {@code addSalt} multiple times when the salt value is
+ * to be assembled piece-meal or if part of the salt is to be supplied
+ * by a hardware crypto device. The {@code salts()} method of the
+ * {@code Extract} or {@code ExtractThenExpand} object that is
+ * subsequently built returns the assembled salt as a list of
+ * {@code SecretKey} objects.
+ *
+ * @param salt
+ * the salt value; the {@code salt} byte array will be
+ * converted to a {@code SecretKeySpec}, which means that the
+ * byte array will be cloned inside the {@code SecretKeySpec}
+ * constructor
+ *
+ * @return this builder
+ *
+ * @throws NullPointerException
+ * if the {@code salt} is null
+ */
+ public Builder addSalt(byte[] salt) {
+ Objects.requireNonNull(salt, "salt must not be null");
+ if (salt.length != 0) {
+ return addSalt(new SecretKeySpec(salt, "Generic"));
+ } else {
+ return this;
+ }
+ }
+ }
+
+ /**
+ * Returns a {@code Builder} for building {@code Extract} and
+ * {@code ExtractThenExpand} objects.
+ *
+ * @return a new {@code Builder}
+ */
+ static Builder ofExtract() {
+ return new Builder();
+ }
+
+ /**
+ * Creates an {@code Expand} object.
+ *
+ * @implNote HKDF implementations will enforce that the length is
+ * not greater than 255 * HMAC length. Implementations will also
+ * enforce that the prk argument is at least as many bytes as the
+ * HMAC length. Implementations will also enforce that a {code null}
+ * info value is treated as zero-length byte array.
+ *
+ * @param prk
+ * the pseudorandom key (PRK); must not be {@code null}
+ * @param info
+ * the optional context and application specific information (may be
+ * {@code null}); the byte array is cloned to prevent subsequent
+ * modification
+ * @param length
+ * the length of the output keying material (must be greater than
+ * 0)
+ *
+ * @return an {@code Expand} object
+ *
+ * @throws NullPointerException
+ * if the {@code prk} argument is {@code null}
+ * @throws IllegalArgumentException
+ * if {@code length} is not greater than 0
+ */
+ static Expand expandOnly(SecretKey prk, byte[] info, int length) {
+ if (prk == null) {
+ throw new NullPointerException("prk must not be null");
+ }
+ return new Expand(prk, info, length);
+ }
+
+ /**
+ * Defines the input parameters of an Extract operation as defined in RFC 5869 .
+ */
+ @PreviewFeature(feature = PreviewFeature.Feature.KEY_DERIVATION)
+ final class Extract implements HKDFParameterSpec {
+
+ // HKDF-Extract(salt, IKM) -> PRK
+ private final List ikms;
+ private final List salts;
+
+ private Extract(List ikms, List salts) {
+ this.ikms = List.copyOf(ikms);
+ this.salts = List.copyOf(salts);
+ }
+
+ /**
+ * Returns an unmodifiable {@code List} of input keying material values
+ * in the order they were added. Returns an empty list if there are no
+ * input keying material values.
+ *
+ * Input keying material values added by {@link Builder#addIKM(byte[])}
+ * are converted to a {@code SecretKeySpec} object. Empty arrays are
+ * discarded.
+ *
+ * @implNote An HKDF implementation should concatenate the input
+ * keying materials into a single value to be used in
+ * HKDF-Extract.
+ *
+ * @return the unmodifiable {@code List} of input keying material
+ * values
+ */
+ public List ikms() {
+ return ikms;
+ }
+
+ /**
+ * Returns an unmodifiable {@code List} of salt values in the order they
+ * were added. Returns an empty list if there are no salt values.
+ *
+ * Salt values added by {@link Builder#addSalt(byte[])} are converted to
+ * a {@code SecretKeySpec} object. Empty arrays are discarded.
+ *
+ * @implNote An HKDF implementation should concatenate the salts
+ * into a single value to be used in HKDF-Extract.
+ *
+ * @return the unmodifiable {@code List} of salt values
+ */
+ public List salts() {
+ return salts;
+ }
+
+ }
+
+ /**
+ * Defines the input parameters of an Expand operation as defined in RFC 5869 .
+ */
+ @PreviewFeature(feature = PreviewFeature.Feature.KEY_DERIVATION)
+ final class Expand implements HKDFParameterSpec {
+
+ // HKDF-Expand(PRK, info, L) -> OKM
+ private final SecretKey prk;
+ private final byte[] info;
+ private final int length;
+
+ /**
+ * Constructor that may be used to initialize an {@code Expand} object
+ *
+ * @param prk
+ * the pseudorandom key (PRK); in the case of
+ * {@code ExtractThenExpand}, the {@code prk} argument may be
+ * {@null} since the output of extract phase is used
+ * @param info
+ * the optional context and application specific information
+ * (may be {@code null}); the byte array is cloned to prevent
+ * subsequent modification
+ * @param length
+ * the length of the output keying material
+ *
+ * @throws IllegalArgumentException
+ * if {@code length} not greater than 0
+ */
+ private Expand(SecretKey prk, byte[] info, int length) {
+ // a null prk argument could be indicative of ExtractThenExpand
+ this.prk = prk;
+ this.info = (info == null) ? null : info.clone();
+ if (!(length > 0)) {
+ throw new IllegalArgumentException("length must be > 0");
+ }
+ this.length = length;
+ }
+
+ /**
+ * Returns the pseudorandom key (PRK).
+ *
+ * @return the pseudorandom key
+ */
+ public SecretKey prk() {
+ return prk;
+ }
+
+ /**
+ * Returns the optional context and application specific information.
+ *
+ * @return a clone of the optional context and application specific
+ * information, or {@code null} if not specified
+ */
+ public byte[] info() {
+ return (info == null) ? null : info.clone();
+ }
+
+ /**
+ * Returns the length of the output keying material.
+ *
+ * @return the length of the output keying material
+ */
+ public int length() {
+ return length;
+ }
+
+ }
+
+ /**
+ * Defines the input parameters of an Extract-then-Expand operation as
+ * defined in RFC 5869 .
+ */
+ @PreviewFeature(feature = PreviewFeature.Feature.KEY_DERIVATION)
+ final class ExtractThenExpand implements HKDFParameterSpec {
+ private final Extract ext;
+ private final Expand exp;
+
+ /**
+ * Constructor that may be used to initialize an
+ * {@code ExtractThenExpand} object
+ *
+ * @param ext
+ * a pre-generated {@code Extract}
+ * @param info
+ * the optional context and application specific information
+ * (may be {@code null}); the byte array is cloned to prevent
+ * subsequent modification
+ * @param length
+ * the length of the output keying material
+ *
+ * @throws IllegalArgumentException
+ * if {@code length} is not greater than 0
+ */
+ private ExtractThenExpand(Extract ext, byte[] info, int length) {
+ Objects.requireNonNull(ext, "Extract object must not be null");
+ this.ext = ext;
+ // - null prk argument is ok here (it's a signal)
+ // - {@code Expand} constructor can deal with a null info
+ // - length is checked in {@code Expand} constructor
+ this.exp = new Expand(null, info, length);
+ }
+
+ /**
+ * Returns an unmodifiable {@code List} of input keying material values
+ * in the order they were added. Returns an empty list if there are no
+ * input keying material values.
+ *
+ * Input keying material values added by {@link Builder#addIKM(byte[])}
+ * are converted to a {@code SecretKeySpec} object. Empty arrays are
+ * discarded.
+ *
+ * @implNote An HKDF implementation should concatenate the input
+ * keying materials into a single value to be used in the
+ * HKDF-Extract phase.
+ *
+ * @return the unmodifiable {@code List} of input keying material
+ * values
+ */
+ public List ikms() {
+ return ext.ikms();
+ }
+
+ /**
+ * Returns an unmodifiable {@code List} of salt values in the order they
+ * were added. Returns an empty list if there are no salt values.
+ *
+ * Salt values added by {@link Builder#addSalt(byte[])} are converted to
+ * a {@code SecretKeySpec} object. Empty arrays are discarded.
+ *
+ * @implNote An HKDF implementation should concatenate the salts
+ * into a single value to be used in the HKDF-Extract phase.
+ *
+ * @return the unmodifiable {@code List} of salt values
+ *
+ */
+ public List salts() {
+ return ext.salts();
+ }
+
+ /**
+ * Returns the optional context and application specific information.
+ *
+ * @return a clone of the optional context and application specific
+ * information, or {@code null} if not specified
+ */
+ public byte[] info() {
+ return exp.info();
+ }
+
+ /**
+ * Returns the length of the output keying material.
+ *
+ * @return the length of the output keying material
+ */
+ public int length() {
+ return exp.length();
+ }
+
+ }
+
+}
diff --git a/src/java.base/share/classes/javax/security/auth/Subject.java b/src/java.base/share/classes/javax/security/auth/Subject.java
index feb9e70b752..8815a3b2763 100644
--- a/src/java.base/share/classes/javax/security/auth/Subject.java
+++ b/src/java.base/share/classes/javax/security/auth/Subject.java
@@ -436,7 +436,7 @@ public static T callAs(final Subject subject,
Objects.requireNonNull(action);
if (!SharedSecrets.getJavaLangAccess().allowSecurityManager()) {
try {
- return ScopedValue.callWhere(SCOPED_SUBJECT, subject, action::call);
+ return ScopedValue.where(SCOPED_SUBJECT, subject).call(action::call);
} catch (Exception e) {
throw new CompletionException(e);
}
diff --git a/src/java.base/share/classes/jdk/internal/foreign/ConfinedSession.java b/src/java.base/share/classes/jdk/internal/foreign/ConfinedSession.java
index 432b324c1bd..9b98bf82b5e 100644
--- a/src/java.base/share/classes/jdk/internal/foreign/ConfinedSession.java
+++ b/src/java.base/share/classes/jdk/internal/foreign/ConfinedSession.java
@@ -41,8 +41,7 @@ final class ConfinedSession extends MemorySessionImpl {
private int asyncReleaseCount = 0;
- static final VarHandle ASYNC_RELEASE_COUNT= MhUtil.findVarHandle(
- MethodHandles.lookup(), "asyncReleaseCount", int.class);
+ static final VarHandle ASYNC_RELEASE_COUNT= MhUtil.findVarHandle(MethodHandles.lookup(), "asyncReleaseCount", int.class);
public ConfinedSession(Thread owner) {
super(owner, new ConfinedResourceList());
@@ -52,17 +51,17 @@ public ConfinedSession(Thread owner) {
@ForceInline
public void acquire0() {
checkValidState();
- if (state == MAX_FORKS) {
+ if (acquireCount == MAX_FORKS) {
throw tooManyAcquires();
}
- state++;
+ acquireCount++;
}
@Override
@ForceInline
public void release0() {
if (Thread.currentThread() == owner) {
- state--;
+ acquireCount--;
} else {
// It is possible to end up here in two cases: this session was kept alive by some other confined session
// which is implicitly released (in which case the release call comes from the cleaner thread). Or,
@@ -75,11 +74,11 @@ public void release0() {
void justClose() {
checkValidState();
int asyncCount = (int)ASYNC_RELEASE_COUNT.getVolatile(this);
- if ((state == 0 && asyncCount == 0)
- || ((state - asyncCount) == 0)) {
+ int acquire = acquireCount - asyncCount;
+ if (acquire == 0) {
state = CLOSED;
} else {
- throw alreadyAcquired(state - asyncCount);
+ throw alreadyAcquired(acquire);
}
}
diff --git a/src/java.base/share/classes/jdk/internal/foreign/GlobalSession.java b/src/java.base/share/classes/jdk/internal/foreign/GlobalSession.java
index c075778b5ee..3fc46d6c0bc 100644
--- a/src/java.base/share/classes/jdk/internal/foreign/GlobalSession.java
+++ b/src/java.base/share/classes/jdk/internal/foreign/GlobalSession.java
@@ -42,6 +42,7 @@ non-sealed class GlobalSession extends MemorySessionImpl {
public GlobalSession() {
super(null, null);
+ this.state = NONCLOSEABLE;
}
@Override
@@ -50,11 +51,6 @@ public void release0() {
// do nothing
}
- @Override
- public boolean isCloseable() {
- return false;
- }
-
@Override
@ForceInline
public void acquire0() {
diff --git a/src/java.base/share/classes/jdk/internal/foreign/ImplicitSession.java b/src/java.base/share/classes/jdk/internal/foreign/ImplicitSession.java
index 0eb3642508c..0b79e45960a 100644
--- a/src/java.base/share/classes/jdk/internal/foreign/ImplicitSession.java
+++ b/src/java.base/share/classes/jdk/internal/foreign/ImplicitSession.java
@@ -42,6 +42,7 @@ final class ImplicitSession extends SharedSession {
public ImplicitSession(Cleaner cleaner) {
super();
+ this.state = NONCLOSEABLE;
cleaner.register(this, resourceList);
}
@@ -55,11 +56,6 @@ public void acquire0() {
// do nothing
}
- @Override
- public boolean isCloseable() {
- return false;
- }
-
@Override
public void justClose() {
throw nonCloseable();
diff --git a/src/java.base/share/classes/jdk/internal/foreign/MemorySessionImpl.java b/src/java.base/share/classes/jdk/internal/foreign/MemorySessionImpl.java
index a12b16ca8b4..541a0907e4c 100644
--- a/src/java.base/share/classes/jdk/internal/foreign/MemorySessionImpl.java
+++ b/src/java.base/share/classes/jdk/internal/foreign/MemorySessionImpl.java
@@ -38,6 +38,7 @@
import jdk.internal.misc.ScopedMemoryAccess;
import jdk.internal.invoke.MhUtil;
import jdk.internal.vm.annotation.ForceInline;
+import jdk.internal.vm.annotation.Stable;
/**
* This class manages the temporal bounds associated with a memory segment as well
@@ -55,11 +56,19 @@
public abstract sealed class MemorySessionImpl
implements Scope
permits ConfinedSession, GlobalSession, SharedSession {
+
+ /**
+ * The value of the {@code state} of a {@code MemorySessionImpl}. The only possible transition
+ * is OPEN -> CLOSED. As a result, the states CLOSED and NONCLOSEABLE are stable. This allows
+ * us to annotate {@code state} with {@link Stable} and elide liveness check on non-closeable
+ * constant scopes, such as {@code GLOBAL_SESSION}.
+ */
static final int OPEN = 0;
static final int CLOSED = -1;
+ static final int NONCLOSEABLE = 1;
- static final VarHandle STATE = MhUtil.findVarHandle(
- MethodHandles.lookup(), "state", int.class);
+ static final VarHandle STATE = MhUtil.findVarHandle(MethodHandles.lookup(), "state", int.class);
+ static final VarHandle ACQUIRE_COUNT = MhUtil.findVarHandle(MethodHandles.lookup(), "acquireCount", int.class);
static final int MAX_FORKS = Integer.MAX_VALUE;
@@ -70,7 +79,11 @@ public abstract sealed class MemorySessionImpl
final ResourceList resourceList;
final Thread owner;
- int state = OPEN;
+
+ @Stable
+ int state;
+
+ int acquireCount;
public Arena asArena() {
return new ArenaImpl(this);
@@ -214,8 +227,8 @@ protected Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}
- public boolean isCloseable() {
- return true;
+ public final boolean isCloseable() {
+ return state <= OPEN;
}
/**
diff --git a/src/java.base/share/classes/jdk/internal/foreign/SharedSession.java b/src/java.base/share/classes/jdk/internal/foreign/SharedSession.java
index 6c9666c2b58..b4415ad4959 100644
--- a/src/java.base/share/classes/jdk/internal/foreign/SharedSession.java
+++ b/src/java.base/share/classes/jdk/internal/foreign/SharedSession.java
@@ -44,6 +44,8 @@ sealed class SharedSession extends MemorySessionImpl permits ImplicitSession {
private static final ScopedMemoryAccess SCOPED_MEMORY_ACCESS = ScopedMemoryAccess.getScopedMemoryAccess();
+ private static final int CLOSED_ACQUIRE_COUNT = -1;
+
SharedSession() {
super(null, new SharedResourceList());
}
@@ -53,15 +55,15 @@ sealed class SharedSession extends MemorySessionImpl permits ImplicitSession {
public void acquire0() {
int value;
do {
- value = (int) STATE.getVolatile(this);
- if (value < OPEN) {
+ value = (int) ACQUIRE_COUNT.getVolatile(this);
+ if (value < 0) {
//segment is not open!
- throw alreadyClosed();
+ throw sharedSessionAlreadyClosed();
} else if (value == MAX_FORKS) {
//overflow
throw tooManyAcquires();
}
- } while (!STATE.compareAndSet(this, value, value + 1));
+ } while (!ACQUIRE_COUNT.compareAndSet(this, value, value + 1));
}
@Override
@@ -69,24 +71,35 @@ public void acquire0() {
public void release0() {
int value;
do {
- value = (int) STATE.getVolatile(this);
- if (value <= OPEN) {
+ value = (int) ACQUIRE_COUNT.getVolatile(this);
+ if (value <= 0) {
//cannot get here - we can't close segment twice
- throw alreadyClosed();
+ throw sharedSessionAlreadyClosed();
}
- } while (!STATE.compareAndSet(this, value, value - 1));
+ } while (!ACQUIRE_COUNT.compareAndSet(this, value, value - 1));
}
void justClose() {
- int prevState = (int) STATE.compareAndExchange(this, OPEN, CLOSED);
- if (prevState < 0) {
- throw alreadyClosed();
- } else if (prevState != OPEN) {
- throw alreadyAcquired(prevState);
+ int acquireCount = (int) ACQUIRE_COUNT.compareAndExchange(this, 0, CLOSED_ACQUIRE_COUNT);
+ if (acquireCount < 0) {
+ throw sharedSessionAlreadyClosed();
+ } else if (acquireCount > 0) {
+ throw alreadyAcquired(acquireCount);
}
+
+ STATE.setVolatile(this, CLOSED);
SCOPED_MEMORY_ACCESS.closeScope(this, ALREADY_CLOSED);
}
+ private IllegalStateException sharedSessionAlreadyClosed() {
+ // To avoid the situation where a scope fails to be acquired or closed but still reports as
+ // alive afterward, we wait for the state to change before throwing the exception
+ while ((int) STATE.getVolatile(this) == OPEN) {
+ Thread.onSpinWait();
+ }
+ return alreadyClosed();
+ }
+
/**
* A shared resource list; this implementation has to handle add vs. add races, as well as add vs. cleanup races.
*/
diff --git a/src/java.base/share/classes/jdk/internal/icu/text/BidiBase.java b/src/java.base/share/classes/jdk/internal/icu/text/BidiBase.java
index bfeb0b7e621..9ef6add27df 100644
--- a/src/java.base/share/classes/jdk/internal/icu/text/BidiBase.java
+++ b/src/java.base/share/classes/jdk/internal/icu/text/BidiBase.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 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
@@ -4744,7 +4744,6 @@ private static class TextAttributeConstants {
static final Boolean RUN_DIRECTION_LTR = (jafa == null) ?
Boolean.FALSE : (Boolean)jafa.getTextAttributeConstant("RUN_DIRECTION_LTR");
- @SuppressWarnings("serial")
private static AttributedCharacterIterator.Attribute
getTextAttribute(String name)
{
diff --git a/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java b/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java
index 3586d953380..6c0af7aa93f 100644
--- a/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java
+++ b/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java
@@ -80,7 +80,7 @@ public enum Feature {
@JEP(number=477, title="Implicitly Declared Classes and Instance Main Methods", status="Third Preview")
IMPLICIT_CLASSES,
- @JEP(number=481, title="Scoped Values", status="Third Preview")
+ @JEP(number=487, title="Scoped Values", status="Fourth Preview")
SCOPED_VALUES,
@JEP(number=480, title="Structured Concurrency", status="Third Preview")
STRUCTURED_CONCURRENCY,
@@ -90,6 +90,8 @@ public enum Feature {
STREAM_GATHERERS,
@JEP(number=476, title="Module Import Declarations", status="Preview")
MODULE_IMPORTS,
+ @JEP(number=478, title="Key Derivation Function API", status="Preview")
+ KEY_DERIVATION,
LANGUAGE_MODEL,
// Not used, but required by interim javac with Java 21 bootjdk.
@JEP(number=445, title="Unnamed Classes and Instance Main Methods", status="Deprecated")
diff --git a/src/java.base/share/classes/sun/launcher/LauncherHelper.java b/src/java.base/share/classes/sun/launcher/LauncherHelper.java
index ccb82c84c92..cbcc61e332c 100644
--- a/src/java.base/share/classes/sun/launcher/LauncherHelper.java
+++ b/src/java.base/share/classes/sun/launcher/LauncherHelper.java
@@ -63,6 +63,7 @@
import java.util.Properties;
import java.util.ResourceBundle;
import java.util.Set;
+import java.util.TimeZone;
import java.util.TreeSet;
import java.util.function.Function;
import java.util.jar.Attributes;
@@ -318,6 +319,8 @@ private static void printLocale(boolean verbose) {
Locale.getDefault(Category.DISPLAY).getDisplayName());
ostream.println(INDENT + "default format locale = " +
Locale.getDefault(Category.FORMAT).getDisplayName());
+ ostream.println(INDENT + "default timezone = " +
+ TimeZone.getDefault().getID());
ostream.println(INDENT + "tzdata version = " +
ZoneInfoFile.getVersion());
if (verbose) {
diff --git a/src/java.base/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java b/src/java.base/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java
index 7881a1480c9..27442382ec7 100644
--- a/src/java.base/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java
+++ b/src/java.base/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -50,7 +50,6 @@ class NegotiateAuthentication extends AuthenticationInfo {
@java.io.Serial
private static final long serialVersionUID = 100L;
- @SuppressWarnings("serial") // Not statically typed as Serializable
private final HttpCallerInfo hci;
// These maps are used to manage the GSS availability for different
@@ -71,7 +70,6 @@ class NegotiateAuthentication extends AuthenticationInfo {
}
// The HTTP Negotiate Helper
- @SuppressWarnings("serial") // Not statically typed as Serializable
private Negotiator negotiator = null;
/**
diff --git a/src/java.base/share/classes/sun/security/util/Debug.java b/src/java.base/share/classes/sun/security/util/Debug.java
index f1484145f5c..65e121421b8 100644
--- a/src/java.base/share/classes/sun/security/util/Debug.java
+++ b/src/java.base/share/classes/sun/security/util/Debug.java
@@ -139,7 +139,7 @@ public static void Help() {
System.err.println("engine=");
System.err.println(" only dump output for the specified list");
System.err.println(" of JCA engines. Supported values:");
- System.err.println(" Cipher, KeyAgreement, KeyGenerator,");
+ System.err.println(" Cipher, KDF, KeyAgreement, KeyGenerator,");
System.err.println(" KeyPairGenerator, KeyStore, Mac,");
System.err.println(" MessageDigest, SecureRandom, Signature.");
System.err.println();
diff --git a/src/java.base/unix/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java b/src/java.base/unix/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java
index 050e12e3594..8a2944081d5 100644
--- a/src/java.base/unix/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java
+++ b/src/java.base/unix/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -120,10 +120,8 @@ public String run() {
});
};
- @SuppressWarnings("serial") // Type of field is not Serializable
PasswordAuthentication pw;
- @SuppressWarnings("serial") // Type of field is not Serializable
Client client;
/**
* Create a NTLMAuthentication:
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 82807148224..7d2e73ea915 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, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -139,11 +139,13 @@ class UnixConstants {
#endif
// flags used with openat/unlinkat/etc.
-#if defined(AT_SYMLINK_NOFOLLOW) && defined(AT_REMOVEDIR)
+#if defined(AT_FDCWD) && defined(AT_SYMLINK_NOFOLLOW) && defined(AT_REMOVEDIR)
+ static final int PREFIX_AT_FDCWD = AT_FDCWD;
static final int PREFIX_AT_SYMLINK_NOFOLLOW = AT_SYMLINK_NOFOLLOW;
static final int PREFIX_AT_REMOVEDIR = AT_REMOVEDIR;
#else
// not supported (dummy values will not be used at runtime).
+ static final int PREFIX_AT_FDCWD = 00;
static final int PREFIX_AT_SYMLINK_NOFOLLOW = 00;
static final int PREFIX_AT_REMOVEDIR = 00;
#endif
diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixFileAttributeViews.java b/src/java.base/unix/classes/sun/nio/fs/UnixFileAttributeViews.java
index 94e0f91e812..033deee2f4f 100644
--- a/src/java.base/unix/classes/sun/nio/fs/UnixFileAttributeViews.java
+++ b/src/java.base/unix/classes/sun/nio/fs/UnixFileAttributeViews.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -76,13 +76,16 @@ public void setTimes(FileTime lastModifiedTime,
boolean useFutimes = false;
boolean useFutimens = false;
boolean useLutimes = false;
+ boolean useUtimensat = false;
int fd = -1;
try {
if (!followLinks) {
- useLutimes = lutimesSupported() &&
- UnixFileAttributes.get(file, false).isSymbolicLink();
+ // these path-based syscalls also work if following links
+ if (!(useUtimensat = utimensatSupported())) {
+ useLutimes = lutimesSupported();
+ }
}
- if (!useLutimes) {
+ if (!useUtimensat && !useLutimes) {
fd = file.openForAttributeAccess(followLinks);
if (fd != -1) {
haveFd = true;
@@ -92,8 +95,8 @@ public void setTimes(FileTime lastModifiedTime,
}
}
} catch (UnixException x) {
- if (!(x.errno() == UnixConstants.ENXIO ||
- (x.errno() == UnixConstants.ELOOP && useLutimes))) {
+ if (!(x.errno() == ENXIO ||
+ (x.errno() == ELOOP && (useUtimensat || useLutimes)))) {
x.rethrowAsIOException(file);
}
}
@@ -117,7 +120,7 @@ public void setTimes(FileTime lastModifiedTime,
}
// update times
- TimeUnit timeUnit = useFutimens ?
+ TimeUnit timeUnit = (useFutimens || useUtimensat) ?
TimeUnit.NANOSECONDS : TimeUnit.MICROSECONDS;
long modValue = lastModifiedTime.to(timeUnit);
long accessValue= lastAccessTime.to(timeUnit);
@@ -130,13 +133,16 @@ public void setTimes(FileTime lastModifiedTime,
futimes(fd, accessValue, modValue);
} else if (useLutimes) {
lutimes(file, accessValue, modValue);
+ } else if (useUtimensat) {
+ utimensat(AT_FDCWD, file, accessValue, modValue,
+ followLinks ? 0 : AT_SYMLINK_NOFOLLOW);
} else {
utimes(file, accessValue, modValue);
}
} catch (UnixException x) {
// if futimes/utimes fails with EINVAL and one/both of the times is
// negative then we adjust the value to the epoch and retry.
- if (x.errno() == UnixConstants.EINVAL &&
+ if (x.errno() == EINVAL &&
(modValue < 0L || accessValue < 0L)) {
retry = true;
} else {
@@ -153,6 +159,9 @@ public void setTimes(FileTime lastModifiedTime,
futimes(fd, accessValue, modValue);
} else if (useLutimes) {
lutimes(file, accessValue, modValue);
+ } else if (useUtimensat) {
+ utimensat(AT_FDCWD, file, accessValue, modValue,
+ followLinks ? 0 : AT_SYMLINK_NOFOLLOW);
} else {
utimes(file, accessValue, modValue);
}
diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java b/src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java
index ab8975c6d12..d6d2b9fdcd7 100644
--- a/src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java
+++ b/src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java
@@ -391,6 +391,20 @@ static void lutimes(UnixPath path, long times0, long times1)
private static native void lutimes0(long pathAddress, long times0, long times1)
throws UnixException;
+ /**
+ * utimensat(int fd, const char* path,
+ * const struct timeval times[2], int flags)
+ */
+ static void utimensat(int fd, UnixPath path, long times0, long times1, int flags)
+ throws UnixException
+ {
+ try (NativeBuffer buffer = copyToNativeBuffer(path)) {
+ utimensat0(fd, buffer.address(), times0, times1, flags);
+ }
+ }
+ private static native void utimensat0(int fd, long pathAddress, long times0, long times1, int flags)
+ throws UnixException;
+
/**
* DIR *opendir(const char* dirname)
*/
@@ -557,7 +571,8 @@ static native int flistxattr(int filedes, long listAddress, int size)
private static final int SUPPORTS_FUTIMES = 1 << 2;
private static final int SUPPORTS_FUTIMENS = 1 << 3;
private static final int SUPPORTS_LUTIMES = 1 << 4;
- private static final int SUPPORTS_XATTR = 1 << 5;
+ private static final int SUPPORTS_UTIMENSAT = 1 << 5;
+ private static final int SUPPORTS_XATTR = 1 << 6;
private static final int SUPPORTS_BIRTHTIME = 1 << 16; // other features
private static final int capabilities;
@@ -589,6 +604,13 @@ static boolean lutimesSupported() {
return (capabilities & SUPPORTS_LUTIMES) != 0;
}
+ /**
+ * Supports utimensat
+ */
+ static boolean utimensatSupported() {
+ return (capabilities & SUPPORTS_UTIMENSAT) != 0;
+ }
+
/**
* Supports file birth (creation) time attribute
*/
diff --git a/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c b/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c
index 9a68a12c219..aa46a2470a1 100644
--- a/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c
+++ b/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c
@@ -211,6 +211,8 @@ typedef DIR* fdopendir_func(int);
#if defined(__linux__)
typedef int statx_func(int dirfd, const char *restrict pathname, int flags,
unsigned int mask, struct my_statx *restrict statxbuf);
+typedef int utimensat_func(int dirfd, const char *pathname,
+ const struct timespec[2], int flags);
#endif
static openat_func* my_openat_func = NULL;
@@ -223,6 +225,7 @@ static lutimes_func* my_lutimes_func = NULL;
static fdopendir_func* my_fdopendir_func = NULL;
#if defined(__linux__)
static statx_func* my_statx_func = NULL;
+static utimensat_func* my_utimensat_func = NULL;
#endif
/**
@@ -432,6 +435,10 @@ Java_sun_nio_fs_UnixNativeDispatcher_init(JNIEnv* env, jclass this)
if (my_statx_func != NULL) {
capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_BIRTHTIME;
}
+ my_utimensat_func = (utimensat_func*) dlsym(RTLD_DEFAULT, "utimensat");
+ if (my_utimensat_func != NULL) {
+ capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_UTIMENSAT;
+ }
#endif
/* supports extended attributes */
@@ -976,6 +983,34 @@ Java_sun_nio_fs_UnixNativeDispatcher_lutimes0(JNIEnv* env, jclass this,
}
}
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_utimensat0(JNIEnv* env, jclass this,
+ jint fd, jlong pathAddress, jlong accessTime, jlong modificationTime, jint flags) {
+#if defined(__linux__)
+ int err;
+ struct timespec times[2];
+ const char* path = (const char*)jlong_to_ptr(pathAddress);
+
+ times[0].tv_sec = accessTime / 1000000000;
+ times[0].tv_nsec = accessTime % 1000000000;
+
+ times[1].tv_sec = modificationTime / 1000000000;
+ times[1].tv_nsec = modificationTime % 1000000000;
+
+ if (my_utimensat_func == NULL) {
+ JNU_ThrowInternalError(env, "my_utimensat_func is NULL");
+ return;
+ }
+ RESTARTABLE((*my_utimensat_func)(fd, path, ×[0], flags), err);
+
+ if (err == -1) {
+ throwUnixException(env, errno);
+ }
+#else
+ JNU_ThrowInternalError(env, "should not reach here");
+#endif
+}
+
JNIEXPORT jlong JNICALL
Java_sun_nio_fs_UnixNativeDispatcher_opendir0(JNIEnv* env, jclass this,
jlong pathAddress)
diff --git a/src/java.management/share/classes/com/sun/jmx/mbeanserver/MBeanServerDelegateImpl.java b/src/java.management/share/classes/com/sun/jmx/mbeanserver/MBeanServerDelegateImpl.java
index c4837c8ea89..f5925a25d35 100644
--- a/src/java.management/share/classes/com/sun/jmx/mbeanserver/MBeanServerDelegateImpl.java
+++ b/src/java.management/share/classes/com/sun/jmx/mbeanserver/MBeanServerDelegateImpl.java
@@ -100,7 +100,7 @@ public MBeanServerDelegateImpl () {
super();
delegateInfo =
new MBeanInfo("javax.management.MBeanServerDelegate",
- "Represents the MBean server from the management "+
+ "Represents the MBean server from the management "+
"point of view.",
MBeanServerDelegateImpl.attributeInfos, null,
null,getNotificationInfo());
diff --git a/src/java.management/share/classes/com/sun/jmx/remote/internal/ServerNotifForwarder.java b/src/java.management/share/classes/com/sun/jmx/remote/internal/ServerNotifForwarder.java
index 7ea1e485869..f15c416f296 100644
--- a/src/java.management/share/classes/com/sun/jmx/remote/internal/ServerNotifForwarder.java
+++ b/src/java.management/share/classes/com/sun/jmx/remote/internal/ServerNotifForwarder.java
@@ -169,7 +169,7 @@ public void removeNotificationListener(ObjectName name,
} catch (Exception e) {
// Give back the first exception
//
- if (re != null) {
+ if (re == null) {
re = e;
}
}
diff --git a/src/java.management/share/classes/javax/management/MBeanServerDelegate.java b/src/java.management/share/classes/javax/management/MBeanServerDelegate.java
index 443e9a7a06c..6e089f4164d 100644
--- a/src/java.management/share/classes/javax/management/MBeanServerDelegate.java
+++ b/src/java.management/share/classes/javax/management/MBeanServerDelegate.java
@@ -31,7 +31,7 @@
import com.sun.jmx.mbeanserver.Util;
/**
- * Represents the MBean server from the management point of view.
+ * Represents the MBean server from the management point of view.
* The MBeanServerDelegate MBean emits the MBeanServerNotifications when
* an MBean is registered/unregistered in the MBean server.
*
diff --git a/src/java.management/share/classes/javax/management/Notification.java b/src/java.management/share/classes/javax/management/Notification.java
index 80cf4b464d2..337628aeec8 100644
--- a/src/java.management/share/classes/javax/management/Notification.java
+++ b/src/java.management/share/classes/javax/management/Notification.java
@@ -59,7 +59,7 @@ public class Notification extends EventObject {
/**
* @serialField type String The notification type.
* A string expressed in a dot notation similar to Java properties.
- * An example of a notification type is network.alarm.router
+ * An example of a notification type is com.sun.management.gc.notification
* @serialField sequenceNumber long The notification sequence number.
* A serial number which identify particular instance
* of notification in the context of the notification source.
@@ -83,7 +83,7 @@ public class Notification extends EventObject {
/**
* @serial The notification type.
* A string expressed in a dot notation similar to Java properties.
- * An example of a notification type is network.alarm.router
+ * An example of a notification type is com.sun.management.gc.notification
*/
private String type;
@@ -239,7 +239,7 @@ public void setSequenceNumber(long sequenceNumber) {
* @return The notification type. It's a string expressed in a dot notation
* similar to Java properties. It is recommended that the notification type
* should follow the reverse-domain-name convention used by Java package
- * names. An example of a notification type is com.example.alarm.router.
+ * names. An example of a notification type is com.sun.management.gc.notification
*/
public String getType() {
return type ;
diff --git a/src/java.management/share/classes/javax/management/remote/JMXConnectionNotification.java b/src/java.management/share/classes/javax/management/remote/JMXConnectionNotification.java
index 0ba100ec8b2..b7bb5a3dc8c 100644
--- a/src/java.management/share/classes/javax/management/remote/JMXConnectionNotification.java
+++ b/src/java.management/share/classes/javax/management/remote/JMXConnectionNotification.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -159,12 +159,7 @@ public JMXConnectionNotification(String type,
long sequenceNumber,
String message,
Object userData) {
- /* We don't know whether the parent class (Notification) will
- throw an exception if the type or source is null, because
- JMX 1.2 doesn't specify that. So we make sure it is not
- null, in case it would throw the wrong exception
- (e.g. IllegalArgumentException instead of
- NullPointerException). Likewise for the sequence number. */
+ // Do not pass null source to super, as EventObject will throw IllegalArgumentException.
super((String) nonNull(type),
nonNull(source),
Math.max(0, sequenceNumber),
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java
index 95f8f847923..972d6a1075b 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java
@@ -241,7 +241,7 @@ protected ClassFinder(Context context) {
* available from the module system.
*/
long getSupplementaryFlags(ClassSymbol c) {
- if (jrtIndex == null || !jrtIndex.isInJRT(c.classfile) || c.name == names.module_info) {
+ if (c.name == names.module_info) {
return 0;
}
@@ -257,17 +257,22 @@ long getSupplementaryFlags(ClassSymbol c) {
try {
ModuleSymbol owningModule = packge.modle;
if (owningModule == syms.noModule) {
- JRTIndex.CtSym ctSym = jrtIndex.getCtSym(packge.flatName());
- Profile minProfile = Profile.DEFAULT;
- if (ctSym.proprietary)
- newFlags |= PROPRIETARY;
- if (ctSym.minProfile != null)
- minProfile = Profile.lookup(ctSym.minProfile);
- if (profile != Profile.DEFAULT && minProfile.value > profile.value) {
- newFlags |= NOT_IN_PROFILE;
+ if (jrtIndex != null && jrtIndex.isInJRT(c.classfile)) {
+ JRTIndex.CtSym ctSym = jrtIndex.getCtSym(packge.flatName());
+ Profile minProfile = Profile.DEFAULT;
+ if (ctSym.proprietary)
+ newFlags |= PROPRIETARY;
+ if (ctSym.minProfile != null)
+ minProfile = Profile.lookup(ctSym.minProfile);
+ if (profile != Profile.DEFAULT && minProfile.value > profile.value) {
+ newFlags |= NOT_IN_PROFILE;
+ }
}
} else if (owningModule.name == names.jdk_unsupported) {
newFlags |= PROPRIETARY;
+ } else {
+ // don't accumulate user modules in supplementaryFlags
+ return 0;
}
} catch (IOException ignore) {
}
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java
index 2e29ecda8ad..3d59b5902ea 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java
@@ -1677,6 +1677,12 @@ public boolean isCastable(Type t, Type s, Warner warn) {
// where
class DisjointChecker {
Set> pairsSeen = new HashSet<>();
+ /* there are three cases for ts and ss:
+ * - one is a class and the other one is an interface (case I)
+ * - both are classes (case II)
+ * - both are interfaces (case III)
+ * all those cases are covered in JLS 23, section: "5.1.6.1 Allowed Narrowing Reference Conversion"
+ */
private boolean areDisjoint(ClassSymbol ts, ClassSymbol ss) {
Pair newPair = new Pair<>(ts, ss);
/* if we are seeing the same pair again then there is an issue with the sealed hierarchy
@@ -1684,32 +1690,38 @@ private boolean areDisjoint(ClassSymbol ts, ClassSymbol ss) {
*/
if (!pairsSeen.add(newPair))
return false;
- if (isSubtype(erasure(ts.type), erasure(ss.type))) {
- return false;
- }
- // if both are classes or both are interfaces, shortcut
- if (ts.isInterface() == ss.isInterface() && isSubtype(erasure(ss.type), erasure(ts.type))) {
- return false;
- }
- if (ts.isInterface() && !ss.isInterface()) {
- /* so ts is interface but ss is a class
- * an interface is disjoint from a class if the class is disjoint form the interface
- */
- return areDisjoint(ss, ts);
- }
- // a final class that is not subtype of ss is disjoint
- if (!ts.isInterface() && ts.isFinal()) {
- return true;
- }
- // if at least one is sealed
- if (ts.isSealed() || ss.isSealed()) {
- // permitted subtypes have to be disjoint with the other symbol
- ClassSymbol sealedOne = ts.isSealed() ? ts : ss;
- ClassSymbol other = sealedOne == ts ? ss : ts;
- return sealedOne.getPermittedSubclasses().stream().allMatch(type -> areDisjoint((ClassSymbol)type.tsym, other));
+
+ if (ts.isInterface() != ss.isInterface()) { // case I: one is a class and the other one is an interface
+ ClassSymbol isym = ts.isInterface() ? ts : ss; // isym is the interface and csym the class
+ ClassSymbol csym = isym == ts ? ss : ts;
+ if (!isSubtype(erasure(csym.type), erasure(isym.type))) {
+ if (csym.isFinal()) {
+ return true;
+ } else if (csym.isSealed()) {
+ return areDisjoint(isym, csym.getPermittedSubclasses());
+ } else if (isym.isSealed()) {
+ // if the class is not final and not sealed then it has to be freely extensible
+ return areDisjoint(csym, isym.getPermittedSubclasses());
+ }
+ } // now both are classes or both are interfaces
+ } else if (!ts.isInterface()) { // case II: both are classes
+ return !isSubtype(erasure(ss.type), erasure(ts.type)) && !isSubtype(erasure(ts.type), erasure(ss.type));
+ } else { // case III: both are interfaces
+ if (!isSubtype(erasure(ts.type), erasure(ss.type)) && !isSubtype(erasure(ss.type), erasure(ts.type))) {
+ if (ts.isSealed()) {
+ return areDisjoint(ss, ts.getPermittedSubclasses());
+ } else if (ss.isSealed()) {
+ return areDisjoint(ts, ss.getPermittedSubclasses());
+ }
+ }
}
+ // at this point we haven't been able to statically prove that the classes or interfaces are disjoint
return false;
}
+
+ boolean areDisjoint(ClassSymbol csym, List permittedSubtypes) {
+ return permittedSubtypes.stream().allMatch(psubtype -> areDisjoint(csym, (ClassSymbol) psubtype.tsym));
+ }
}
private TypeRelation isCastable = new TypeRelation() {
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/AttrContext.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/AttrContext.java
index 285e3e5f52c..59b596d4ba3 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/AttrContext.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/AttrContext.java
@@ -155,6 +155,7 @@ AttrContext dup(WriteableScope scope) {
info.preferredTreeForDiagnostics = preferredTreeForDiagnostics;
info.visitingServiceImplementation = visitingServiceImplementation;
info.allowProtectedAccess = allowProtectedAccess;
+ info.isPermitsClause = isPermitsClause;
info.instanceInitializerBlock = instanceInitializerBlock;
return info;
}
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java
index fd4a72bae45..90387f9ac47 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java
@@ -111,6 +111,7 @@ public class Resolve {
private final boolean compactMethodDiags;
private final boolean allowLocalVariableTypeInference;
private final boolean allowYieldStatement;
+ private final boolean allowPrivateMembersInPermitsClause;
final EnumSet verboseResolutionMode;
final boolean dumpMethodReferenceSearchResults;
final boolean dumpStacktraceOnError;
@@ -147,6 +148,7 @@ protected Resolve(Context context) {
Target target = Target.instance(context);
allowLocalVariableTypeInference = Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source);
allowYieldStatement = Feature.SWITCH_EXPRESSION.allowedInSource(source);
+ allowPrivateMembersInPermitsClause = Feature.PRIVATE_MEMBERS_IN_PERMITS_CLAUSE.allowedInSource(source);
polymorphicSignatureScope = WriteableScope.create(syms.noSymbol);
allowModules = Feature.MODULES.allowedInSource(source);
allowRecords = Feature.RECORDS.allowedInSource(source);
@@ -428,6 +430,8 @@ public boolean isAccessible(Env env, Type site, Symbol sym, boolean
||
env.enclClass.sym.outermostClass() ==
sym.owner.outermostClass())
+ ||
+ privateMemberInPermitsClauseIfAllowed(env, sym)
&&
sym.isInheritedIn(site.tsym, types);
case 0:
@@ -461,8 +465,15 @@ public boolean isAccessible(Env env, Type site, Symbol sym, boolean
}
} finally {
env.enclClass.sym = enclosingCsym;
- }
+ }
}
+
+ private boolean privateMemberInPermitsClauseIfAllowed(Env env, Symbol sym) {
+ return allowPrivateMembersInPermitsClause &&
+ env.info.isPermitsClause &&
+ ((JCClassDecl) env.tree).sym.outermostClass() == sym.owner.outermostClass();
+ }
+
//where
/* `sym' is accessible only if not overridden by
* another symbol which is a member of `site'
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransPatterns.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransPatterns.java
index 0e3a2c0b1db..93c4eaa03ee 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransPatterns.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransPatterns.java
@@ -199,7 +199,27 @@ protected TransPatterns(Context context) {
@Override
public void visitTypeTest(JCInstanceOf tree) {
- if (tree.pattern instanceof JCPattern pattern) {
+ // Translates regular instanceof type operation to instanceof pattern operator when
+ // the expression was originally T but was subsequently erased to Object.
+ //
+ // $expr instanceof $primitiveType
+ // =>
+ // $expr instanceof T $temp && $temp instanceof $primitiveType
+ if (tree.erasedExprOriginalType!=null && !types.isSameType(tree.expr.type, tree.erasedExprOriginalType)) {
+ BindingSymbol temp = new BindingSymbol(Flags.FINAL | Flags.SYNTHETIC,
+ names.fromString("temp" + variableIndex++ + target.syntheticNameChar()),
+ tree.erasedExprOriginalType,
+ currentMethodSym);
+
+ JCVariableDecl tempDecl = make.at(tree.pos()).VarDef(temp, null);
+
+ JCTree resultExpr =
+ makeBinary(Tag.AND,
+ make.TypeTest(tree.expr, make.BindingPattern(tempDecl).setType(tree.erasedExprOriginalType)).setType(syms.booleanType),
+ make.TypeTest(make.Ident(tempDecl), tree.pattern).setType(syms.booleanType));
+
+ result = translate(resultExpr);
+ } else if (tree.pattern instanceof JCPattern pattern) {
//first, resolve any record patterns:
JCExpression extraConditions = null;
if (pattern instanceof JCRecordPattern recordPattern) {
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java
index d232f2e6d9f..a0b1ef27255 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java
@@ -813,8 +813,7 @@ public void visitSwitch(JCSwitch tree) {
Type selsuper = types.supertype(tree.selector.type);
boolean enumSwitch = selsuper != null &&
selsuper.tsym == syms.enumSym;
- Type target = enumSwitch ? erasure(tree.selector.type) : syms.intType;
- tree.selector = translate(tree.selector, target);
+ tree.selector = translate(tree.selector, erasure(tree.selector.type));
tree.cases = translateCases(tree.cases);
result = tree;
}
@@ -852,8 +851,7 @@ public void visitSwitchExpression(JCSwitchExpression tree) {
Type selsuper = types.supertype(tree.selector.type);
boolean enumSwitch = selsuper != null &&
selsuper.tsym == syms.enumSym;
- Type target = enumSwitch ? erasure(tree.selector.type) : syms.intType;
- tree.selector = translate(tree.selector, target);
+ tree.selector = translate(tree.selector, erasure(tree.selector.type));
tree.cases = translate(tree.cases, tree.type);
tree.type = erasure(tree.type);
result = retype(tree, tree.type, pt);
@@ -1067,8 +1065,14 @@ public void visitTypeCast(JCTypeCast tree) {
}
public void visitTypeTest(JCInstanceOf tree) {
- tree.expr = translate(tree.expr, null);
tree.pattern = translate(tree.pattern, null);
+ if (tree.pattern.type.isPrimitive()) {
+ tree.erasedExprOriginalType = erasure(tree.expr.type);
+ tree.expr = translate(tree.expr, null);
+ }
+ else {
+ tree.expr = translate(tree.expr, null);
+ }
result = tree;
}
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassFile.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassFile.java
index 7e8b96d5856..c7e71f74d8a 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassFile.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassFile.java
@@ -103,6 +103,7 @@ public class ClassFile {
public static final int MAX_STACK = 0xffff;
public static final int PREVIEW_MINOR_VERSION = 0xffff;
+ public static final int MAX_ANNOTATIONS = 0xffff;
public enum Version {
V45_3(45, 3), // base level for all attributes
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java
index 99ee7cef8b5..b578150f693 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java
@@ -650,11 +650,19 @@ void writeCompoundAttribute(Attribute.Compound c) {
databuf.appendChar(poolWriter.putDescriptor(c.type));
databuf.appendChar(c.values.length());
for (Pair p : c.values) {
+ checkAnnotationArraySizeInternal(p);
databuf.appendChar(poolWriter.putName(p.fst.name));
p.snd.accept(awriter);
}
}
+ private void checkAnnotationArraySizeInternal(Pair p) {
+ if (p.snd instanceof Attribute.Array arrAttr &&
+ arrAttr.values.length > ClassFile.MAX_ANNOTATIONS) {
+ log.error(Errors.AnnotationArrayTooLarge(p.fst.owner));
+ }
+ }
+
void writeTypeAnnotation(Attribute.TypeCompound c) {
writePosition(c.position);
writeCompoundAttribute(c);
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties
index d62f50673bf..611f9475676 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties
@@ -887,6 +887,10 @@ compiler.err.limit.stack=\
compiler.err.limit.string=\
constant string too long
+# 0: symbol
+compiler.err.annotation.array.too.large=\
+ Annotation array element too large in \"{0}\"
+
# 0: string
compiler.err.limit.string.overflow=\
UTF8 representation for string \"{0}...\" is too long for the constant pool
@@ -2241,6 +2245,7 @@ compiler.warn.proc.duplicate.option.name=\
compiler.warn.proc.duplicate.supported.annotation=\
Duplicate supported annotation interface ''{0}'' returned by annotation processor ''{1}''
+
# 0: string
compiler.warn.proc.redundant.types.with.wildcard=\
Annotation processor ''{0}'' redundantly supports both ''*'' and other annotation interfaces
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java
index 6041da6723a..003f70eeecc 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java
@@ -2272,6 +2272,8 @@ public static class JCInstanceOf extends JCExpression implements InstanceOfTree
/**{@code true} if this instanceof test should have
* value {@code true} when the {@code expr} is {@code null}.*/
public boolean allowNull;
+ public Type erasedExprOriginalType;
+
protected JCInstanceOf(JCExpression expr, JCTree pattern) {
this.expr = expr;
this.pattern = pattern;
diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/BiClassValue.java b/src/jdk.dynalink/share/classes/jdk/dynalink/BiClassValue.java
index 0a1b739c493..a1faf464ea6 100644
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/BiClassValue.java
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/BiClassValue.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 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
@@ -113,7 +113,6 @@ T getReverseValue(final Class> c) {
}
private T compute(final VarHandle mapHandle, final Class> c, final Function, T> compute) {
- @SuppressWarnings("unchecked")
Map, T> map = (Map, T>) mapHandle.getVolatile(this);
T value;
T newValue = null;
@@ -128,7 +127,6 @@ private T compute(final VarHandle mapHandle, final Class> c, final Function, T>[] entries = map.entrySet().toArray(new Map.Entry[map.size() + 1]);
entries[map.size()] = Map.entry(c, newValue);
final var newMap = Map.ofEntries(entries);
- @SuppressWarnings("unchecked")
final var witness = (Map, T>) mapHandle.compareAndExchange(this, map, newMap);
if (witness == map) {
value = newValue;
diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/beans/OverloadedDynamicMethod.java b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/OverloadedDynamicMethod.java
index dd771a0ce31..2f3c3315fbf 100644
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/beans/OverloadedDynamicMethod.java
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/OverloadedDynamicMethod.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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
@@ -151,7 +151,7 @@ MethodHandle getInvocation(final CallSiteDescriptor callSiteDescriptor, final Li
// This is typical for very generic signatures at call sites. Typical example: call site specifies
// (Object, Object), and we have a method whose parameter types are (String, int). None of the JLS applicability
// rules will trigger, but we must consider the method, as it can be the right match for a concrete invocation.
- @SuppressWarnings({ "unchecked", "rawtypes" })
+ @SuppressWarnings("unchecked")
final List invokables = (List)methods.clone();
invokables.removeAll(subtypingApplicables.getMethods());
invokables.removeAll(methodInvocationApplicables.getMethods());
diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/TagletWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/TagletWriter.java
index 79b4433a58b..ca1b6ae016b 100644
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/TagletWriter.java
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/TagletWriter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -367,7 +367,6 @@ public Content createAnchorAndSearchIndex(Element element, String tagText, Strin
return createAnchorAndSearchIndex(element, tagText, Text.of(tagText), desc, tree);
}
- @SuppressWarnings("preview")
Content createAnchorAndSearchIndex(Element element, String tagText, Content tagContent, String desc, DocTree tree) {
Content result;
if (context.isFirstSentence && context.inSummary || context.inTags.contains(DocTree.Kind.INDEX)
diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/Checker.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/Checker.java
index 7bc55639501..3669c800a8e 100644
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/Checker.java
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/Checker.java
@@ -678,7 +678,7 @@ void warnIfEmpty(TagStackItem tsi, DocTree endTree) {
//
- @Override @DefinedBy(Api.COMPILER_TREE) @SuppressWarnings("fallthrough")
+ @Override @DefinedBy(Api.COMPILER_TREE)
public Void visitAttribute(AttributeTree tree, Void ignore) {
// for now, ensure we're in an HTML StartElementTree;
// in time, we might check uses of attributes in other tree nodes
diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java
index 4422c2caa27..2a695d876a2 100644
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java
@@ -336,7 +336,6 @@ private void showLines(String message) {
/**
* Main program - external wrapper.
*/
- @SuppressWarnings("deprecation")
Result begin(String... argv) {
// Preprocess @file arguments
List allArgs;
diff --git a/src/jdk.jsobject/share/classes/module-info.java b/src/jdk.jsobject/share/classes/module-info.java
index 22ee6576af3..13ec8943a21 100644
--- a/src/jdk.jsobject/share/classes/module-info.java
+++ b/src/jdk.jsobject/share/classes/module-info.java
@@ -31,7 +31,6 @@
* @deprecated The jdk.jsobject module will be delivered with JavaFX.
*/
@Deprecated(since = "24", forRemoval = true)
-@SuppressWarnings("removal")
module jdk.jsobject {
exports netscape.javascript;
}
diff --git a/src/jdk.jsobject/share/classes/netscape/javascript/JSException.java b/src/jdk.jsobject/share/classes/netscape/javascript/JSException.java
index 7fe8ad8dd04..fe3fd7190e6 100644
--- a/src/jdk.jsobject/share/classes/netscape/javascript/JSException.java
+++ b/src/jdk.jsobject/share/classes/netscape/javascript/JSException.java
@@ -33,7 +33,6 @@
* @deprecated The jdk.jsobject module will be delivered with JavaFX.
*/
@Deprecated(since = "24", forRemoval = true)
-@SuppressWarnings("removal")
public class JSException extends RuntimeException {
private static final long serialVersionUID = 2778103758223661489L;
diff --git a/src/jdk.net/share/classes/jdk/net/Sockets.java b/src/jdk.net/share/classes/jdk/net/Sockets.java
index a8effd8dba6..3d113b562ae 100644
--- a/src/jdk.net/share/classes/jdk/net/Sockets.java
+++ b/src/jdk.net/share/classes/jdk/net/Sockets.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -303,7 +303,6 @@ static boolean isReusePortAvailable() {
return isReusePortAvailable;
}
- @SuppressWarnings("removal")
private static Map,Set>> optionSets() {
Map,Set>> options = new HashMap<>();
boolean incomingNapiIdsupported = PlatformSocketOptions.get().incomingNapiIdSupported();
diff --git a/test/hotspot/gtest/aarch64/aarch64-asmtest.py b/test/hotspot/gtest/aarch64/aarch64-asmtest.py
index 7e9d557d11c..64f3e787356 100644
--- a/test/hotspot/gtest/aarch64/aarch64-asmtest.py
+++ b/test/hotspot/gtest/aarch64/aarch64-asmtest.py
@@ -77,11 +77,29 @@ class FloatRegister(Register):
def __str__(self):
return self.astr("v")
+ def generate(self):
+ self.number = random.randint(0, 31)
+ return self
+
def nextReg(self):
next = FloatRegister()
next.number = (self.number + 1) % 32
return next
+class LowFloatRegister(Register):
+
+ def __str__(self):
+ return self.astr("v")
+
+ def generate(self):
+ self.number = random.randint(0, 15)
+ return self
+
+ def nextReg(self):
+ next = FloatRegister()
+ next.number = (self.number + 1) % 16
+ return next
+
class GeneralRegister(Register):
def __str__(self):
@@ -1271,6 +1289,75 @@ def astr(self):
def aname(self):
return self._name
+class VectorScalarNEONInstruction(Instruction):
+ def __init__(self, args):
+ self._name, self.insname, self.arrangement = args
+
+ def generate(self):
+ vectorLength = {"8B" : 8, "16B" : 16, "4H" : 4, "8H" : 8, "2S" : 2, "4S" : 4, "1D" : 1, "2D" : 2} [self.arrangement]
+ self.elemIndex = random.randrange(0, vectorLength)
+ self.elemSizeSpecifier = self.arrangement[len(self.arrangement) - 1:]
+ self._firstSIMDreg = LowFloatRegister().generate()
+ self.numRegs = 3
+ return self
+
+ def cstr(self):
+ buf = Instruction.cstr(self) + str(self._firstSIMDreg)
+ buf = '%s, __ T%s' % (buf, self.arrangement)
+ current = self._firstSIMDreg
+ for cnt in range(1, self.numRegs - 1):
+ buf = '%s, %s' % (buf, current.nextReg())
+ current = current.nextReg()
+ buf = '%s, %s, %d' % (buf, current.nextReg(), self.elemIndex)
+ return '%s);' % (buf)
+
+ def astr(self):
+ buf = '%s\t%s.%s' % (self.insname, self._firstSIMDreg, self.arrangement)
+ current = self._firstSIMDreg
+ for cnt in range(1, self.numRegs - 1):
+ buf = '%s, %s.%s' % (buf, current.nextReg(), self.arrangement)
+ current = current.nextReg()
+ buf = '%s, %s.%s[%d]' % (buf, current.nextReg(), self.elemSizeSpecifier, self.elemIndex)
+ return buf
+
+ def aname(self):
+ return self._name
+
+class WideningNEONInstruction(Instruction):
+ def __init__(self, args):
+ self._name, self.insname, self.widerArrangement, self.narrowerArrangement = args
+
+ def generate(self):
+ self._firstSIMDreg = FloatRegister().generate()
+ return self
+
+ def cstr(self):
+ buf = Instruction.cstr(self) + str(self._firstSIMDreg)
+ current = self._firstSIMDreg
+ for cnt in range(1, self.numWiderRegs):
+ buf = '%s, %s' % (buf, current.nextReg())
+ current = current.nextReg()
+ buf = '%s, __ T%s' % (buf, self.widerArrangement)
+ for cnt in range(0, self.numNarrowerRegs):
+ buf = '%s, %s' % (buf, current.nextReg())
+ current = current.nextReg()
+ buf = '%s, __ T%s' % (buf, self.narrowerArrangement)
+ return '%s);' % (buf)
+
+ def astr(self):
+ buf = '%s\t%s.%s' % (self.insname, self._firstSIMDreg, self.widerArrangement)
+ current = self._firstSIMDreg
+ for cnt in range(1, self.numWiderRegs):
+ buf = '%s, %s.%s' % (buf, current.nextReg(), self.widerArrangement)
+ current = current.nextReg()
+ for cnt in range(0, self.numNarrowerRegs):
+ buf = '%s, %s.%s' % (buf, current.nextReg(), self.narrowerArrangement)
+ current = current.nextReg()
+ return buf
+
+ def aname(self):
+ return self._name
+
class SHA512SIMDOp(Instruction):
def generate(self):
@@ -1390,6 +1477,10 @@ class TwoRegNEONOp(CommonNEONInstruction):
class ThreeRegNEONOp(TwoRegNEONOp):
numRegs = 3
+class AddWideNEONOp(WideningNEONInstruction):
+ numWiderRegs = 2
+ numNarrowerRegs = 1
+
class NEONFloatCompareWithZero(TwoRegNEONOp):
def __init__(self, args):
self._name = 'fcm'
@@ -1748,6 +1839,17 @@ def generate(kind, names):
["facgt", "facgt", "2D"],
])
+generate(VectorScalarNEONInstruction,
+ [["fmlavs", "fmla", "2S"], ["mulvs", "mul", "4S"],
+ ["fmlavs", "fmla", "2D"],
+ ["fmlsvs", "fmls", "2S"], ["mulvs", "mul", "4S"],
+ ["fmlsvs", "fmls", "2D"],
+ ["fmulxvs", "fmulx", "2S"], ["mulvs", "mul", "4S"],
+ ["fmulxvs", "fmulx", "2D"],
+ ["mulvs", "mul", "4H"], ["mulvs", "mul", "8H"],
+ ["mulvs", "mul", "2S"], ["mulvs", "mul", "4S"],
+ ])
+
neonVectorCompareInstructionPrefix = ['cm', 'fcm']
neonIntegerVectorCompareConditions = ['GT', 'GE', 'EQ', 'HI', 'HS']
neonFloatVectorCompareConditions = ['EQ', 'GT', 'GE']
@@ -2081,6 +2183,15 @@ def generate(kind, names):
generate(SVEReductionOp, [["andv", 0], ["orv", 0], ["eorv", 0], ["smaxv", 0], ["sminv", 0],
["fminv", 2], ["fmaxv", 2], ["fadda", 2], ["uaddv", 0]])
+generate(AddWideNEONOp,
+ [["saddwv", "saddw", "8H", "8B"], ["saddwv2", "saddw2", "8H", "16B"],
+ ["saddwv", "saddw", "4S", "4H"], ["saddwv2", "saddw2", "4S", "8H"],
+ ["saddwv", "saddw", "2D", "2S"], ["saddwv2", "saddw2", "2D", "4S"],
+ ["uaddwv", "uaddw", "8H", "8B"], ["uaddwv2", "uaddw2", "8H", "16B"],
+ ["uaddwv", "uaddw", "4S", "4H"], ["uaddwv2", "uaddw2", "4S", "8H"],
+ ["uaddwv", "uaddw", "2D", "2S"], ["uaddwv2", "uaddw2", "2D", "4S"],
+ ])
+
print "\n __ bind(forth);"
outfile.write("forth:\n")
diff --git a/test/hotspot/gtest/aarch64/asmtest.out.h b/test/hotspot/gtest/aarch64/asmtest.out.h
index b8260aaf932..9805a05c5c1 100644
--- a/test/hotspot/gtest/aarch64/asmtest.out.h
+++ b/test/hotspot/gtest/aarch64/asmtest.out.h
@@ -293,9 +293,9 @@
__ 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(v22, Address(r9, -47)); // ldr s22, [x9, -47]
+ __ ldrs(v23, Address(r9, -47)); // ldr s23, [x9, -47]
__ strd(v11, Address(r0, 9)); // str d11, [x0, 9]
- __ strs(v20, Address(r0, -127)); // str s20, [x0, -127]
+ __ strs(v21, Address(r0, -127)); // str s21, [x0, -127]
// pre
// LoadStoreOp
@@ -314,7 +314,7 @@
__ 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(v17, Address(__ pre(r28, -54))); // str s17, [x28, -54]!
+ __ strs(v18, Address(__ pre(r28, -54))); // str s18, [x28, -54]!
// post
// LoadStoreOp
@@ -331,8 +331,8 @@
__ 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(v17, Address(__ post(r6, 55))); // ldr s17, [x6], 55
- __ strd(v13, Address(__ post(r21, -234))); // str d13, [x21], -234
+ __ 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
// base_plus_reg
@@ -349,9 +349,9 @@
__ 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(v29, Address(r29, r14, Address::sxtw(0))); // ldr d29, [x29, w14, sxtw #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(v24, Address(r8, r13, Address::sxtx(0))); // str d24, [x8, x13, sxtx #0]
+ __ 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]
// base_plus_scaled_offset
@@ -370,7 +370,7 @@
__ 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(v23, Address(r1, 12728)); // str d23, [x1, 12728]
+ __ strd(v24, Address(r1, 12728)); // str d24, [x1, 12728]
__ strs(v3, Address(r20, 6924)); // str s3, [x20, 6924]
// pcrel
@@ -484,63 +484,63 @@
__ umsubl(r13, r10, r7, r5); // umsubl x13, w10, w7, x5
// ThreeRegFloatOp
- __ fabds(v29, v15, v3); // fabd s29, s15, s3
- __ fmuls(v11, v12, v15); // fmul s11, s12, s15
- __ fdivs(v30, v30, v17); // fdiv s30, s30, s17
- __ fadds(v19, v20, v15); // fadd s19, s20, s15
- __ fsubs(v15, v9, v21); // fsub s15, s9, s21
- __ fabdd(v2, v9, v27); // fabd d2, d9, d27
- __ fmuld(v7, v29, v30); // fmul d7, d29, d30
- __ fdivd(v17, v1, v2); // fdiv d17, d1, d2
+ __ fabds(v30, v15, v3); // fabd s30, s15, s3
+ __ fmuls(v12, v12, v16); // fmul s12, s12, s16
+ __ fdivs(v31, v31, v18); // fdiv s31, s31, s18
+ __ fadds(v19, v21, v16); // fadd s19, s21, s16
+ __ fsubs(v15, v10, v21); // fsub s15, s10, s21
+ __ fabdd(v2, v10, v28); // fabd d2, d10, d28
+ __ fmuld(v7, v30, v31); // fmul d7, d30, d31
+ __ fdivd(v18, v1, v2); // fdiv d18, d1, d2
__ faddd(v6, v10, v3); // fadd d6, d10, d3
- __ fsubd(v24, v11, v7); // fsub d24, d11, d7
+ __ fsubd(v25, v11, v7); // fsub d25, d11, d7
// FourRegFloatOp
- __ fmadds(v1, v11, v0, v3); // fmadd s1, s11, s0, s3
- __ fmsubs(v17, v28, v6, v22); // fmsub s17, s28, s6, s22
- __ fnmadds(v6, v0, v27, v26); // fnmadd s6, s0, s27, s26
- __ fnmadds(v2, v5, v7, v28); // fnmadd s2, s5, s7, s28
- __ fmaddd(v11, v25, v13, v11); // fmadd d11, d25, d13, d11
- __ fmsubd(v23, v19, v8, v17); // fmsub d23, d19, d8, d17
- __ fnmaddd(v21, v25, v20, v19); // fnmadd d21, d25, d20, d19
- __ fnmaddd(v17, v2, v29, v22); // fnmadd d17, d2, d29, d22
+ __ fmadds(v1, v12, v0, v3); // fmadd s1, s12, s0, s3
+ __ fmsubs(v19, v29, v6, v23); // fmsub s19, s29, s6, s23
+ __ fnmadds(v6, v0, v28, v27); // fnmadd s6, s0, s28, s27
+ __ fnmadds(v2, v5, v7, v29); // fnmadd s2, s5, s7, s29
+ __ fmaddd(v12, v25, v13, v12); // fmadd d12, d25, d13, d12
+ __ fmsubd(v24, v19, v8, v18); // fmsub d24, d19, d8, d18
+ __ fnmaddd(v22, v26, v21, v20); // fnmadd d22, d26, d21, d20
+ __ fnmaddd(v19, v2, v30, v22); // fnmadd d19, d2, d30, d22
// TwoRegFloatOp
- __ fmovs(v8, v21); // fmov s8, s21
- __ fabss(v19, v20); // fabs s19, s20
- __ fnegs(v11, v17); // fneg s11, s17
- __ fsqrts(v20, v6); // fsqrt s20, s6
- __ fcvts(v15, v3); // fcvt d15, s3
- __ fcvtsh(v3, v28); // fcvt h3, s28
- __ fcvths(v3, v27); // fcvt s3, h27
- __ fmovd(v14, v14); // fmov d14, d14
- __ fabsd(v10, v12); // fabs d10, d12
- __ fnegd(v11, v17); // fneg d11, d17
- __ fsqrtd(v10, v25); // fsqrt d10, d25
+ __ fmovs(v8, v22); // fmov s8, s22
+ __ fabss(v19, v21); // fabs s19, s21
+ __ fnegs(v12, v18); // fneg s12, s18
+ __ fsqrts(v21, v6); // fsqrt s21, s6
+ __ fcvts(v16, v3); // fcvt d16, s3
+ __ fcvtsh(v3, v29); // fcvt h3, s29
+ __ fcvths(v3, v28); // fcvt s3, h28
+ __ fmovd(v15, v14); // fmov d15, d14
+ __ fabsd(v10, v13); // fabs d10, d13
+ __ fnegd(v12, v18); // fneg d12, d18
+ __ fsqrtd(v10, v26); // fsqrt d10, d26
__ fcvtd(v7, v7); // fcvt s7, d7
// FloatConvertOp
- __ fcvtzsw(r14, v28); // fcvtzs w14, s28
- __ fcvtzs(r0, v22); // fcvtzs x0, s22
+ __ fcvtzsw(r14, v29); // fcvtzs w14, s29
+ __ fcvtzs(r0, v23); // fcvtzs x0, s23
__ fcvtzdw(r0, v12); // fcvtzs w0, d12
- __ fcvtzd(r23, v13); // fcvtzs x23, d13
+ __ fcvtzd(r23, v14); // fcvtzs x23, d14
__ scvtfws(v13, r7); // scvtf s13, w7
- __ scvtfs(v14, r7); // scvtf s14, x7
- __ scvtfwd(v8, r20); // scvtf d8, w20
- __ scvtfd(v17, r28); // scvtf d17, x28
+ __ scvtfs(v15, r7); // scvtf s15, x7
+ __ scvtfwd(v9, r20); // scvtf d9, w20
+ __ scvtfd(v19, r28); // scvtf d19, x28
__ fcvtassw(r30, v16); // fcvtas w30, s16
__ fcvtasd(r2, v9); // fcvtas x2, d9
- __ fcvtmssw(r16, v20); // fcvtms w16, s20
+ __ fcvtmssw(r16, v21); // fcvtms w16, s21
__ fcvtmsd(r29, v4); // fcvtms x29, d4
- __ fmovs(r1, v26); // fmov w1, s26
- __ fmovd(r24, v23); // fmov x24, d23
+ __ fmovs(r1, v27); // fmov w1, s27
+ __ fmovd(r24, v24); // fmov x24, d24
__ fmovs(v14, r21); // fmov s14, w21
- __ fmovd(v12, r5); // fmov d12, x5
+ __ fmovd(v13, r5); // fmov d13, x5
// TwoRegFloatOp
- __ fcmps(v12, v24); // fcmp s12, s24
- __ fcmpd(v24, v29); // fcmp d24, d29
- __ fcmps(v27, 0.0); // fcmp s27, #0.0
+ __ fcmps(v12, v25); // fcmp s12, s25
+ __ fcmpd(v25, v30); // fcmp d25, d30
+ __ fcmps(v28, 0.0); // fcmp s28, #0.0
__ fcmpd(v21, 0.0); // fcmp d21, #0.0
// LoadStorePairOp
@@ -573,250 +573,265 @@
// LdStNEONOp
__ ld1(v0, __ T8B, Address(r11)); // ld1 {v0.8B}, [x11]
__ ld1(v16, v17, __ T16B, Address(__ post(r26, 32))); // ld1 {v16.16B, v17.16B}, [x26], 32
- __ ld1(v21, v22, v23, __ T1D, Address(__ post(r26, r17))); // ld1 {v21.1D, v22.1D, v23.1D}, [x26], x17
- __ ld1(v26, v27, v28, v29, __ T8H, Address(__ post(r29, 64))); // ld1 {v26.8H, v27.8H, v28.8H, v29.8H}, [x29], 64
- __ ld1r(v21, __ T8B, Address(r6)); // ld1r {v21.8B}, [x6]
- __ ld1r(v13, __ T4S, Address(__ post(r29, 4))); // ld1r {v13.4S}, [x29], 4
- __ ld1r(v21, __ T1D, Address(__ post(r12, r16))); // ld1r {v21.1D}, [x12], x16
+ __ ld1(v22, v23, v24, __ T1D, Address(__ post(r26, r17))); // ld1 {v22.1D, v23.1D, v24.1D}, [x26], x17
+ __ ld1(v27, v28, v29, v30, __ T8H, Address(__ post(r29, 64))); // ld1 {v27.8H, v28.8H, v29.8H, v30.8H}, [x29], 64
+ __ ld1r(v22, __ T8B, Address(r6)); // ld1r {v22.8B}, [x6]
+ __ ld1r(v14, __ T4S, Address(__ post(r29, 4))); // ld1r {v14.4S}, [x29], 4
+ __ ld1r(v22, __ T1D, Address(__ post(r12, r16))); // ld1r {v22.1D}, [x12], x16
__ ld2(v1, v2, __ T2D, Address(r0)); // ld2 {v1.2D, v2.2D}, [x0]
- __ ld2(v9, v10, __ T4H, Address(__ post(r21, 16))); // ld2 {v9.4H, v10.4H}, [x21], 16
+ __ ld2(v10, v11, __ T4H, Address(__ post(r21, 16))); // ld2 {v10.4H, v11.4H}, [x21], 16
__ ld2r(v7, v8, __ T16B, Address(r25)); // ld2r {v7.16B, v8.16B}, [x25]
- __ ld2r(v8, v9, __ T2S, Address(__ post(r9, 8))); // ld2r {v8.2S, v9.2S}, [x9], 8
+ __ ld2r(v9, v10, __ T2S, Address(__ post(r9, 8))); // ld2r {v9.2S, v10.2S}, [x9], 8
__ ld2r(v9, v10, __ T2D, Address(__ post(r12, r14))); // ld2r {v9.2D, v10.2D}, [x12], x14
__ ld3(v7, v8, v9, __ T4S, Address(__ post(r4, r17))); // ld3 {v7.4S, v8.4S, v9.4S}, [x4], x17
__ ld3(v23, v24, v25, __ T2S, Address(r17)); // ld3 {v23.2S, v24.2S, v25.2S}, [x17]
- __ ld3r(v3, v4, v5, __ T8H, Address(r22)); // ld3r {v3.8H, v4.8H, v5.8H}, [x22]
- __ ld3r(v12, v13, v14, __ T4S, Address(__ post(r2, 12))); // ld3r {v12.4S, v13.4S, v14.4S}, [x2], 12
- __ ld3r(v15, v16, v17, __ T1D, Address(__ post(r10, r12))); // ld3r {v15.1D, v16.1D, v17.1D}, [x10], x12
+ __ ld3r(v4, v5, v6, __ T8H, Address(r22)); // ld3r {v4.8H, v5.8H, v6.8H}, [x22]
+ __ ld3r(v13, v14, v15, __ T4S, Address(__ post(r2, 12))); // ld3r {v13.4S, v14.4S, v15.4S}, [x2], 12
+ __ ld3r(v16, v17, v18, __ T1D, Address(__ post(r10, r12))); // ld3r {v16.1D, v17.1D, v18.1D}, [x10], x12
__ ld4(v4, v5, v6, v7, __ T8H, Address(__ post(r2, 64))); // ld4 {v4.8H, v5.8H, v6.8H, v7.8H}, [x2], 64
__ ld4(v6, v7, v8, v9, __ T8B, Address(__ post(r20, r11))); // ld4 {v6.8B, v7.8B, v8.8B, v9.8B}, [x20], x11
- __ ld4r(v11, v12, v13, v14, __ T8B, Address(r12)); // ld4r {v11.8B, v12.8B, v13.8B, v14.8B}, [x12]
- __ ld4r(v15, v16, v17, v18, __ T4H, Address(__ post(r17, 8))); // ld4r {v15.4H, v16.4H, v17.4H, v18.4H}, [x17], 8
+ __ ld4r(v12, v13, v14, v15, __ T8B, Address(r12)); // ld4r {v12.8B, v13.8B, v14.8B, v15.8B}, [x12]
+ __ ld4r(v16, v17, v18, v19, __ T4H, Address(__ post(r17, 8))); // ld4r {v16.4H, v17.4H, v18.4H, v19.4H}, [x17], 8
__ ld4r(v14, v15, v16, v17, __ T2S, Address(__ post(r25, r16))); // ld4r {v14.2S, v15.2S, v16.2S, v17.2S}, [x25], x16
// NEONReduceInstruction
__ addv(v20, __ T8B, v21); // addv b20, v21.8B
__ addv(v1, __ T16B, v2); // addv b1, v2.16B
- __ addv(v22, __ T4H, v23); // addv h22, v23.4H
+ __ addv(v23, __ T4H, v24); // addv h23, v24.4H
__ addv(v30, __ T8H, v31); // addv h30, v31.8H
__ addv(v14, __ T4S, v15); // addv s14, v15.4S
__ smaxv(v2, __ T8B, v3); // smaxv b2, v3.8B
__ smaxv(v6, __ T16B, v7); // smaxv b6, v7.16B
__ smaxv(v3, __ T4H, v4); // smaxv h3, v4.4H
- __ smaxv(v7, __ T8H, v8); // smaxv h7, v8.8H
- __ smaxv(v24, __ T4S, v25); // smaxv s24, v25.4S
+ __ smaxv(v8, __ T8H, v9); // smaxv h8, v9.8H
+ __ smaxv(v25, __ T4S, v26); // smaxv s25, v26.4S
__ fmaxv(v0, __ T4S, v1); // fmaxv s0, v1.4S
__ sminv(v27, __ T8B, v28); // sminv b27, v28.8B
- __ uminv(v29, __ T8B, v30); // uminv b29, v30.8B
+ __ uminv(v30, __ T8B, v31); // uminv b30, v31.8B
__ sminv(v5, __ T16B, v6); // sminv b5, v6.16B
__ uminv(v5, __ T16B, v6); // uminv b5, v6.16B
- __ sminv(v29, __ T4H, v30); // sminv h29, v30.4H
+ __ sminv(v30, __ T4H, v31); // sminv h30, v31.4H
__ uminv(v11, __ T4H, v12); // uminv h11, v12.4H
__ sminv(v25, __ T8H, v26); // sminv h25, v26.8H
__ uminv(v0, __ T8H, v1); // uminv h0, v1.8H
- __ sminv(v30, __ T4S, v31); // sminv s30, v31.4S
+ __ sminv(v31, __ T4S, v0); // sminv s31, v0.4S
__ uminv(v0, __ T4S, v1); // uminv s0, v1.4S
- __ fminv(v17, __ T4S, v18); // fminv s17, v18.4S
- __ fmaxp(v28, v29, __ S); // fmaxp s28, v29.2S
- __ fmaxp(v25, v26, __ D); // fmaxp d25, v26.2D
+ __ fminv(v19, __ T4S, v20); // fminv s19, v20.4S
+ __ fmaxp(v29, v30, __ S); // fmaxp s29, v30.2S
+ __ fmaxp(v26, v27, __ D); // fmaxp d26, v27.2D
__ fminp(v9, v10, __ S); // fminp s9, v10.2S
- __ fminp(v25, v26, __ D); // fminp d25, v26.2D
+ __ fminp(v26, v27, __ D); // fminp d26, v27.2D
// NEONFloatCompareWithZero
__ fcm(Assembler::GT, v12, __ T2S, v13); // fcmgt v12.2S, v13.2S, #0.0
__ fcm(Assembler::GT, v15, __ T4S, v16); // fcmgt v15.4S, v16.4S, #0.0
__ fcm(Assembler::GT, v11, __ T2D, v12); // fcmgt v11.2D, v12.2D, #0.0
- __ fcm(Assembler::GE, v10, __ T2S, v11); // fcmge v10.2S, v11.2S, #0.0
- __ fcm(Assembler::GE, v17, __ T4S, v18); // fcmge v17.4S, v18.4S, #0.0
- __ fcm(Assembler::GE, v24, __ T2D, v25); // fcmge v24.2D, v25.2D, #0.0
- __ fcm(Assembler::EQ, v21, __ T2S, v22); // fcmeq v21.2S, v22.2S, #0.0
- __ fcm(Assembler::EQ, v23, __ T4S, v24); // fcmeq v23.4S, v24.4S, #0.0
+ __ fcm(Assembler::GE, v11, __ T2S, v12); // fcmge v11.2S, v12.2S, #0.0
+ __ fcm(Assembler::GE, v18, __ T4S, v19); // fcmge v18.4S, v19.4S, #0.0
+ __ fcm(Assembler::GE, v25, __ T2D, v26); // fcmge v25.2D, v26.2D, #0.0
+ __ fcm(Assembler::EQ, v22, __ T2S, v23); // fcmeq v22.2S, v23.2S, #0.0
+ __ fcm(Assembler::EQ, v24, __ T4S, v25); // fcmeq v24.4S, v25.4S, #0.0
__ fcm(Assembler::EQ, v0, __ T2D, v1); // fcmeq v0.2D, v1.2D, #0.0
- __ fcm(Assembler::LT, v16, __ T2S, v17); // fcmlt v16.2S, v17.2S, #0.0
- __ fcm(Assembler::LT, v10, __ T4S, v11); // fcmlt v10.4S, v11.4S, #0.0
+ __ fcm(Assembler::LT, v17, __ T2S, v18); // fcmlt v17.2S, v18.2S, #0.0
+ __ fcm(Assembler::LT, v11, __ T4S, v12); // fcmlt v11.4S, v12.4S, #0.0
__ fcm(Assembler::LT, v6, __ T2D, v7); // fcmlt v6.2D, v7.2D, #0.0
- __ fcm(Assembler::LE, v28, __ T2S, v29); // fcmle v28.2S, v29.2S, #0.0
+ __ fcm(Assembler::LE, v29, __ T2S, v30); // fcmle v29.2S, v30.2S, #0.0
__ fcm(Assembler::LE, v6, __ T4S, v7); // fcmle v6.4S, v7.4S, #0.0
__ fcm(Assembler::LE, v5, __ T2D, v6); // fcmle v5.2D, v6.2D, #0.0
// TwoRegNEONOp
__ absr(v5, __ T8B, v6); // abs v5.8B, v6.8B
- __ absr(v20, __ T16B, v21); // abs v20.16B, v21.16B
- __ absr(v17, __ T4H, v18); // abs v17.4H, v18.4H
- __ absr(v15, __ T8H, v16); // abs v15.8H, v16.8H
- __ absr(v17, __ T2S, v18); // abs v17.2S, v18.2S
- __ absr(v29, __ T4S, v30); // abs v29.4S, v30.4S
- __ absr(v26, __ T2D, v27); // abs v26.2D, v27.2D
+ __ absr(v21, __ T16B, v22); // abs v21.16B, v22.16B
+ __ absr(v19, __ T4H, v20); // abs v19.4H, v20.4H
+ __ absr(v16, __ T8H, v17); // abs v16.8H, v17.8H
+ __ absr(v18, __ T2S, v19); // abs v18.2S, v19.2S
+ __ absr(v30, __ T4S, v31); // abs v30.4S, v31.4S
+ __ absr(v27, __ T2D, v28); // abs v27.2D, v28.2D
__ fabs(v28, __ T2S, v29); // fabs v28.2S, v29.2S
__ fabs(v1, __ T4S, v2); // fabs v1.4S, v2.4S
- __ fabs(v27, __ T2D, v28); // fabs v27.2D, v28.2D
- __ fneg(v0, __ T2S, v1); // fneg v0.2S, v1.2S
+ __ fabs(v28, __ T2D, v29); // fabs v28.2D, v29.2D
+ __ fneg(v1, __ T2S, v2); // fneg v1.2S, v2.2S
__ fneg(v20, __ T4S, v21); // fneg v20.4S, v21.4S
- __ fneg(v28, __ T2D, v29); // fneg v28.2D, v29.2D
- __ fsqrt(v15, __ T2S, v16); // fsqrt v15.2S, v16.2S
- __ fsqrt(v12, __ T4S, v13); // fsqrt v12.4S, v13.4S
+ __ fneg(v29, __ T2D, v30); // fneg v29.2D, v30.2D
+ __ fsqrt(v16, __ T2S, v17); // fsqrt v16.2S, v17.2S
+ __ fsqrt(v13, __ T4S, v14); // fsqrt v13.4S, v14.4S
__ fsqrt(v10, __ T2D, v11); // fsqrt v10.2D, v11.2D
- __ notr(v28, __ T8B, v29); // not v28.8B, v29.8B
- __ notr(v28, __ T16B, v29); // not v28.16B, v29.16B
+ __ notr(v29, __ T8B, v30); // not v29.8B, v30.8B
+ __ notr(v29, __ T16B, v30); // not v29.16B, v30.16B
// ThreeRegNEONOp
__ andr(v19, __ T8B, v20, v21); // and v19.8B, v20.8B, v21.8B
__ andr(v22, __ T16B, v23, v24); // and v22.16B, v23.16B, v24.16B
__ orr(v10, __ T8B, v11, v12); // orr v10.8B, v11.8B, v12.8B
__ orr(v4, __ T16B, v5, v6); // orr v4.16B, v5.16B, v6.16B
- __ eor(v30, __ T8B, v31, v0); // eor v30.8B, v31.8B, v0.8B
- __ eor(v20, __ T16B, v21, v22); // eor v20.16B, v21.16B, v22.16B
+ __ eor(v31, __ T8B, v0, v1); // eor v31.8B, v0.8B, v1.8B
+ __ eor(v21, __ T16B, v22, v23); // eor v21.16B, v22.16B, v23.16B
__ addv(v8, __ T8B, v9, v10); // add v8.8B, v9.8B, v10.8B
- __ addv(v30, __ T16B, v31, v0); // add v30.16B, v31.16B, v0.16B
- __ addv(v17, __ T4H, v18, v19); // add v17.4H, v18.4H, v19.4H
+ __ addv(v31, __ T16B, v0, v1); // add v31.16B, v0.16B, v1.16B
+ __ addv(v19, __ T4H, v20, v21); // add v19.4H, v20.4H, v21.4H
__ addv(v10, __ T8H, v11, v12); // add v10.8H, v11.8H, v12.8H
- __ addv(v27, __ T2S, v28, v29); // add v27.2S, v28.2S, v29.2S
+ __ addv(v28, __ T2S, v29, v30); // add v28.2S, v29.2S, v30.2S
__ addv(v2, __ T4S, v3, v4); // add v2.4S, v3.4S, v4.4S
- __ addv(v24, __ T2D, v25, v26); // add v24.2D, v25.2D, v26.2D
- __ fadd(v4, __ T2S, v5, v6); // fadd v4.2S, v5.2S, v6.2S
+ __ addv(v25, __ T2D, v26, v27); // add v25.2D, v26.2D, v27.2D
+ __ fadd(v5, __ T2S, v6, v7); // fadd v5.2S, v6.2S, v7.2S
__ fadd(v3, __ T4S, v4, v5); // fadd v3.4S, v4.4S, v5.4S
__ fadd(v8, __ T2D, v9, v10); // fadd v8.2D, v9.2D, v10.2D
__ subv(v22, __ T8B, v23, v24); // sub v22.8B, v23.8B, v24.8B
- __ subv(v17, __ T16B, v18, v19); // sub v17.16B, v18.16B, v19.16B
+ __ subv(v19, __ T16B, v20, v21); // sub v19.16B, v20.16B, v21.16B
__ subv(v13, __ T4H, v14, v15); // sub v13.4H, v14.4H, v15.4H
- __ subv(v4, __ T8H, v5, v6); // sub v4.8H, v5.8H, v6.8H
- __ subv(v28, __ T2S, v29, v30); // sub v28.2S, v29.2S, v30.2S
- __ subv(v23, __ T4S, v24, v25); // sub v23.4S, v24.4S, v25.4S
+ __ subv(v5, __ T8H, v6, v7); // sub v5.8H, v6.8H, v7.8H
+ __ subv(v29, __ T2S, v30, v31); // sub v29.2S, v30.2S, v31.2S
+ __ subv(v24, __ T4S, v25, v26); // sub v24.4S, v25.4S, v26.4S
__ subv(v21, __ T2D, v22, v23); // sub v21.2D, v22.2D, v23.2D
- __ fsub(v25, __ T2S, v26, v27); // fsub v25.2S, v26.2S, v27.2S
+ __ fsub(v26, __ T2S, v27, v28); // fsub v26.2S, v27.2S, v28.2S
__ fsub(v24, __ T4S, v25, v26); // fsub v24.4S, v25.4S, v26.4S
__ fsub(v3, __ T2D, v4, v5); // fsub v3.2D, v4.2D, v5.2D
- __ mulv(v23, __ T8B, v24, v25); // mul v23.8B, v24.8B, v25.8B
+ __ mulv(v24, __ T8B, v25, v26); // mul v24.8B, v25.8B, v26.8B
__ mulv(v26, __ T16B, v27, v28); // mul v26.16B, v27.16B, v28.16B
__ mulv(v23, __ T4H, v24, v25); // mul v23.4H, v24.4H, v25.4H
- __ mulv(v14, __ T8H, v15, v16); // mul v14.8H, v15.8H, v16.8H
+ __ mulv(v15, __ T8H, v16, v17); // mul v15.8H, v16.8H, v17.8H
__ mulv(v21, __ T2S, v22, v23); // mul v21.2S, v22.2S, v23.2S
__ mulv(v3, __ T4S, v4, v5); // mul v3.4S, v4.4S, v5.4S
- __ fabd(v23, __ T2S, v24, v25); // fabd v23.2S, v24.2S, v25.2S
+ __ fabd(v24, __ T2S, v25, v26); // fabd v24.2S, v25.2S, v26.2S
__ fabd(v8, __ T4S, v9, v10); // fabd v8.4S, v9.4S, v10.4S
- __ fabd(v24, __ T2D, v25, v26); // fabd v24.2D, v25.2D, v26.2D
- __ faddp(v19, __ T2S, v20, v21); // faddp v19.2S, v20.2S, v21.2S
- __ faddp(v15, __ T4S, v16, v17); // faddp v15.4S, v16.4S, v17.4S
- __ faddp(v16, __ T2D, v17, v18); // faddp v16.2D, v17.2D, v18.2D
+ __ fabd(v25, __ T2D, v26, v27); // fabd v25.2D, v26.2D, v27.2D
+ __ faddp(v20, __ T2S, v21, v22); // faddp v20.2S, v21.2S, v22.2S
+ __ faddp(v16, __ T4S, v17, v18); // faddp v16.4S, v17.4S, v18.4S
+ __ faddp(v17, __ T2D, v18, v19); // faddp v17.2D, v18.2D, v19.2D
__ fmul(v2, __ T2S, v3, v4); // fmul v2.2S, v3.2S, v4.2S
__ fmul(v1, __ T4S, v2, v3); // fmul v1.4S, v2.4S, v3.4S
__ fmul(v0, __ T2D, v1, v2); // fmul v0.2D, v1.2D, v2.2D
__ mlav(v24, __ T4H, v25, v26); // mla v24.4H, v25.4H, v26.4H
__ mlav(v4, __ T8H, v5, v6); // mla v4.8H, v5.8H, v6.8H
__ mlav(v3, __ T2S, v4, v5); // mla v3.2S, v4.2S, v5.2S
- __ mlav(v11, __ T4S, v12, v13); // mla v11.4S, v12.4S, v13.4S
- __ fmla(v30, __ T2S, v31, v0); // fmla v30.2S, v31.2S, v0.2S
- __ fmla(v27, __ T4S, v28, v29); // fmla v27.4S, v28.4S, v29.4S
- __ fmla(v9, __ T2D, v10, v11); // fmla v9.2D, v10.2D, v11.2D
- __ mlsv(v25, __ T4H, v26, v27); // mls v25.4H, v26.4H, v27.4H
+ __ mlav(v12, __ T4S, v13, v14); // mla v12.4S, v13.4S, v14.4S
+ __ fmla(v31, __ T2S, v0, v1); // fmla v31.2S, v0.2S, v1.2S
+ __ fmla(v28, __ T4S, v29, v30); // fmla v28.4S, v29.4S, v30.4S
+ __ fmla(v10, __ T2D, v11, v12); // fmla v10.2D, v11.2D, v12.2D
+ __ mlsv(v26, __ T4H, v27, v28); // mls v26.4H, v27.4H, v28.4H
__ mlsv(v2, __ T8H, v3, v4); // mls v2.8H, v3.8H, v4.8H
__ mlsv(v12, __ T2S, v13, v14); // mls v12.2S, v13.2S, v14.2S
- __ mlsv(v17, __ T4S, v18, v19); // mls v17.4S, v18.4S, v19.4S
- __ fmls(v30, __ T2S, v31, v0); // fmls v30.2S, v31.2S, v0.2S
+ __ mlsv(v18, __ T4S, v19, v20); // mls v18.4S, v19.4S, v20.4S
+ __ fmls(v31, __ T2S, v0, v1); // fmls v31.2S, v0.2S, v1.2S
__ fmls(v1, __ T4S, v2, v3); // fmls v1.4S, v2.4S, v3.4S
- __ fmls(v12, __ T2D, v13, v14); // fmls v12.2D, v13.2D, v14.2D
- __ fdiv(v28, __ T2S, v29, v30); // fdiv v28.2S, v29.2S, v30.2S
+ __ fmls(v13, __ T2D, v14, v15); // fmls v13.2D, v14.2D, v15.2D
+ __ fdiv(v29, __ T2S, v30, v31); // fdiv v29.2S, v30.2S, v31.2S
__ fdiv(v0, __ T4S, v1, v2); // fdiv v0.4S, v1.4S, v2.4S
- __ fdiv(v17, __ T2D, v18, v19); // fdiv v17.2D, v18.2D, v19.2D
+ __ fdiv(v19, __ T2D, v20, v21); // fdiv v19.2D, v20.2D, v21.2D
__ maxv(v12, __ T8B, v13, v14); // smax v12.8B, v13.8B, v14.8B
__ maxv(v17, __ T16B, v18, v19); // smax v17.16B, v18.16B, v19.16B
- __ maxv(v21, __ T4H, v22, v23); // smax v21.4H, v22.4H, v23.4H
- __ maxv(v12, __ T8H, v13, v14); // smax v12.8H, v13.8H, v14.8H
- __ maxv(v27, __ T2S, v28, v29); // smax v27.2S, v28.2S, v29.2S
- __ maxv(v29, __ T4S, v30, v31); // smax v29.4S, v30.4S, v31.4S
- __ smaxp(v30, __ T8B, v31, v0); // smaxp v30.8B, v31.8B, v0.8B
+ __ maxv(v22, __ T4H, v23, v24); // smax v22.4H, v23.4H, v24.4H
+ __ maxv(v13, __ T8H, v14, v15); // smax v13.8H, v14.8H, v15.8H
+ __ maxv(v28, __ T2S, v29, v30); // smax v28.2S, v29.2S, v30.2S
+ __ maxv(v30, __ T4S, v31, v0); // smax v30.4S, v31.4S, v0.4S
+ __ smaxp(v31, __ T8B, v0, v1); // smaxp v31.8B, v0.8B, v1.8B
__ smaxp(v1, __ T16B, v2, v3); // smaxp v1.16B, v2.16B, v3.16B
- __ smaxp(v25, __ T4H, v26, v27); // smaxp v25.4H, v26.4H, v27.4H
- __ smaxp(v27, __ T8H, v28, v29); // smaxp v27.8H, v28.8H, v29.8H
+ __ smaxp(v26, __ T4H, v27, v28); // smaxp v26.4H, v27.4H, v28.4H
+ __ smaxp(v28, __ T8H, v29, v30); // smaxp v28.8H, v29.8H, v30.8H
__ smaxp(v4, __ T2S, v5, v6); // smaxp v4.2S, v5.2S, v6.2S
- __ smaxp(v29, __ T4S, v30, v31); // smaxp v29.4S, v30.4S, v31.4S
- __ fmax(v3, __ T2S, v4, v5); // fmax v3.2S, v4.2S, v5.2S
+ __ smaxp(v30, __ T4S, v31, v0); // smaxp v30.4S, v31.4S, v0.4S
+ __ fmax(v4, __ T2S, v5, v6); // fmax v4.2S, v5.2S, v6.2S
__ fmax(v6, __ T4S, v7, v8); // fmax v6.4S, v7.4S, v8.4S
- __ fmax(v29, __ T2D, v30, v31); // fmax v29.2D, v30.2D, v31.2D
- __ minv(v25, __ T8B, v26, v27); // smin v25.8B, v26.8B, v27.8B
- __ minv(v17, __ T16B, v18, v19); // smin v17.16B, v18.16B, v19.16B
- __ minv(v8, __ T4H, v9, v10); // smin v8.4H, v9.4H, v10.4H
- __ minv(v7, __ T8H, v8, v9); // smin v7.8H, v8.8H, v9.8H
+ __ fmax(v30, __ T2D, v31, v0); // fmax v30.2D, v31.2D, v0.2D
+ __ minv(v26, __ T8B, v27, v28); // smin v26.8B, v27.8B, v28.8B
+ __ minv(v18, __ T16B, v19, v20); // smin v18.16B, v19.16B, v20.16B
+ __ minv(v9, __ T4H, v10, v11); // smin v9.4H, v10.4H, v11.4H
+ __ minv(v8, __ T8H, v9, v10); // smin v8.8H, v9.8H, v10.8H
__ minv(v12, __ T2S, v13, v14); // smin v12.2S, v13.2S, v14.2S
__ minv(v0, __ T4S, v1, v2); // smin v0.4S, v1.4S, v2.4S
- __ sminp(v19, __ T8B, v20, v21); // sminp v19.8B, v20.8B, v21.8B
+ __ sminp(v20, __ T8B, v21, v22); // sminp v20.8B, v21.8B, v22.8B
__ sminp(v1, __ T16B, v2, v3); // sminp v1.16B, v2.16B, v3.16B
- __ sminp(v23, __ T4H, v24, v25); // sminp v23.4H, v24.4H, v25.4H
+ __ sminp(v24, __ T4H, v25, v26); // sminp v24.4H, v25.4H, v26.4H
__ sminp(v2, __ T8H, v3, v4); // sminp v2.8H, v3.8H, v4.8H
__ sminp(v0, __ T2S, v1, v2); // sminp v0.2S, v1.2S, v2.2S
- __ sminp(v8, __ T4S, v9, v10); // sminp v8.4S, v9.4S, v10.4S
- __ fmin(v23, __ T2S, v24, v25); // fmin v23.2S, v24.2S, v25.2S
- __ fmin(v25, __ T4S, v26, v27); // fmin v25.4S, v26.4S, v27.4S
- __ fmin(v15, __ T2D, v16, v17); // fmin v15.2D, v16.2D, v17.2D
- __ facgt(v29, __ T2S, v30, v31); // facgt v29.2S, v30.2S, v31.2S
+ __ sminp(v9, __ T4S, v10, v11); // sminp v9.4S, v10.4S, v11.4S
+ __ fmin(v24, __ T2S, v25, v26); // fmin v24.2S, v25.2S, v26.2S
+ __ fmin(v26, __ T4S, v27, v28); // fmin v26.4S, v27.4S, v28.4S
+ __ fmin(v16, __ T2D, v17, v18); // fmin v16.2D, v17.2D, v18.2D
+ __ facgt(v30, __ T2S, v31, v0); // facgt v30.2S, v31.2S, v0.2S
__ facgt(v3, __ T4S, v4, v5); // facgt v3.4S, v4.4S, v5.4S
__ facgt(v10, __ T2D, v11, v12); // facgt v10.2D, v11.2D, v12.2D
+// VectorScalarNEONInstruction
+ __ fmlavs(v5, __ T2S, v6, v7, 1); // fmla v5.2S, v6.2S, v7.S[1]
+ __ mulvs(v9, __ T4S, v10, v11, 0); // mul v9.4S, v10.4S, v11.S[0]
+ __ fmlavs(v5, __ T2D, v6, v7, 0); // fmla v5.2D, v6.2D, v7.D[0]
+ __ fmlsvs(v5, __ T2S, v6, v7, 0); // fmls v5.2S, v6.2S, v7.S[0]
+ __ mulvs(v8, __ T4S, v9, v10, 1); // mul v8.4S, v9.4S, v10.S[1]
+ __ fmlsvs(v5, __ T2D, v6, v7, 0); // fmls v5.2D, v6.2D, v7.D[0]
+ __ fmulxvs(v6, __ T2S, v7, v8, 0); // fmulx v6.2S, v7.2S, v8.S[0]
+ __ mulvs(v6, __ T4S, v7, v8, 1); // mul v6.4S, v7.4S, v8.S[1]
+ __ fmulxvs(v3, __ T2D, v4, v5, 0); // fmulx v3.2D, v4.2D, v5.D[0]
+ __ mulvs(v13, __ T4H, v14, v15, 2); // mul v13.4H, v14.4H, v15.H[2]
+ __ mulvs(v2, __ T8H, v3, v4, 4); // mul v2.8H, v3.8H, v4.H[4]
+ __ mulvs(v2, __ T2S, v3, v4, 0); // mul v2.2S, v3.2S, v4.S[0]
+ __ mulvs(v9, __ T4S, v10, v11, 1); // mul v9.4S, v10.4S, v11.S[1]
+
// NEONVectorCompare
- __ cm(Assembler::GT, v22, __ T8B, v23, v24); // cmgt v22.8B, v23.8B, v24.8B
- __ cm(Assembler::GT, v10, __ T16B, v11, v12); // cmgt v10.16B, v11.16B, v12.16B
- __ cm(Assembler::GT, v4, __ T4H, v5, v6); // cmgt v4.4H, v5.4H, v6.4H
- __ cm(Assembler::GT, v17, __ T8H, v18, v19); // cmgt v17.8H, v18.8H, v19.8H
- __ cm(Assembler::GT, v1, __ T2S, v2, v3); // cmgt v1.2S, v2.2S, v3.2S
- __ cm(Assembler::GT, v11, __ T4S, v12, v13); // cmgt v11.4S, v12.4S, v13.4S
- __ cm(Assembler::GT, v7, __ T2D, v8, v9); // cmgt v7.2D, v8.2D, v9.2D
- __ cm(Assembler::GE, v10, __ T8B, v11, v12); // cmge v10.8B, v11.8B, v12.8B
- __ cm(Assembler::GE, v15, __ T16B, v16, v17); // cmge v15.16B, v16.16B, v17.16B
- __ cm(Assembler::GE, v16, __ T4H, v17, v18); // cmge v16.4H, v17.4H, v18.4H
- __ cm(Assembler::GE, v2, __ T8H, v3, v4); // cmge v2.8H, v3.8H, v4.8H
- __ cm(Assembler::GE, v9, __ T2S, v10, v11); // cmge v9.2S, v10.2S, v11.2S
- __ cm(Assembler::GE, v11, __ T4S, v12, v13); // cmge v11.4S, v12.4S, v13.4S
- __ cm(Assembler::GE, v12, __ T2D, v13, v14); // cmge v12.2D, v13.2D, v14.2D
- __ cm(Assembler::EQ, v14, __ T8B, v15, v16); // cmeq v14.8B, v15.8B, v16.8B
- __ cm(Assembler::EQ, v13, __ T16B, v14, v15); // cmeq v13.16B, v14.16B, v15.16B
- __ cm(Assembler::EQ, v2, __ T4H, v3, v4); // cmeq v2.4H, v3.4H, v4.4H
- __ cm(Assembler::EQ, v6, __ T8H, v7, v8); // cmeq v6.8H, v7.8H, v8.8H
- __ cm(Assembler::EQ, v19, __ T2S, v20, v21); // cmeq v19.2S, v20.2S, v21.2S
- __ cm(Assembler::EQ, v25, __ T4S, v26, v27); // cmeq v25.4S, v26.4S, v27.4S
- __ cm(Assembler::EQ, v15, __ T2D, v16, v17); // cmeq v15.2D, v16.2D, v17.2D
- __ cm(Assembler::HI, v4, __ T8B, v5, v6); // cmhi v4.8B, v5.8B, v6.8B
- __ cm(Assembler::HI, v2, __ T16B, v3, v4); // cmhi v2.16B, v3.16B, v4.16B
- __ cm(Assembler::HI, v4, __ T4H, v5, v6); // cmhi v4.4H, v5.4H, v6.4H
- __ cm(Assembler::HI, v11, __ T8H, v12, v13); // cmhi v11.8H, v12.8H, v13.8H
- __ cm(Assembler::HI, v17, __ T2S, v18, v19); // cmhi v17.2S, v18.2S, v19.2S
- __ cm(Assembler::HI, v20, __ T4S, v21, v22); // cmhi v20.4S, v21.4S, v22.4S
- __ cm(Assembler::HI, v16, __ T2D, v17, v18); // cmhi v16.2D, v17.2D, v18.2D
- __ cm(Assembler::HS, v17, __ T8B, v18, v19); // cmhs v17.8B, v18.8B, v19.8B
- __ cm(Assembler::HS, v10, __ T16B, v11, v12); // cmhs v10.16B, v11.16B, v12.16B
- __ cm(Assembler::HS, v20, __ T4H, v21, v22); // cmhs v20.4H, v21.4H, v22.4H
- __ cm(Assembler::HS, v22, __ T8H, v23, v24); // cmhs v22.8H, v23.8H, v24.8H
- __ cm(Assembler::HS, v12, __ T2S, v13, v14); // cmhs v12.2S, v13.2S, v14.2S
- __ cm(Assembler::HS, v25, __ T4S, v26, v27); // cmhs v25.4S, v26.4S, v27.4S
- __ cm(Assembler::HS, v23, __ T2D, v24, v25); // cmhs v23.2D, v24.2D, v25.2D
- __ fcm(Assembler::EQ, v28, __ T2S, v29, v30); // fcmeq v28.2S, v29.2S, v30.2S
- __ fcm(Assembler::EQ, v14, __ T4S, v15, v16); // fcmeq v14.4S, v15.4S, v16.4S
- __ fcm(Assembler::EQ, v10, __ T2D, v11, v12); // fcmeq v10.2D, v11.2D, v12.2D
- __ fcm(Assembler::GT, v24, __ T2S, v25, v26); // fcmgt v24.2S, v25.2S, v26.2S
- __ fcm(Assembler::GT, v1, __ T4S, v2, v3); // fcmgt v1.4S, v2.4S, v3.4S
- __ fcm(Assembler::GT, v11, __ T2D, v12, v13); // fcmgt v11.2D, v12.2D, v13.2D
- __ fcm(Assembler::GE, v30, __ T2S, v31, v0); // fcmge v30.2S, v31.2S, v0.2S
- __ fcm(Assembler::GE, v10, __ T4S, v11, v12); // fcmge v10.4S, v11.4S, v12.4S
- __ fcm(Assembler::GE, v15, __ T2D, v16, v17); // fcmge v15.2D, v16.2D, v17.2D
+ __ cm(Assembler::GT, v21, __ T8B, v22, v23); // cmgt v21.8B, v22.8B, v23.8B
+ __ cm(Assembler::GT, v16, __ T16B, v17, v18); // cmgt v16.16B, v17.16B, v18.16B
+ __ cm(Assembler::GT, v18, __ T4H, v19, v20); // cmgt v18.4H, v19.4H, v20.4H
+ __ cm(Assembler::GT, v11, __ T8H, v12, v13); // cmgt v11.8H, v12.8H, v13.8H
+ __ cm(Assembler::GT, v21, __ T2S, v22, v23); // cmgt v21.2S, v22.2S, v23.2S
+ __ cm(Assembler::GT, v23, __ T4S, v24, v25); // cmgt v23.4S, v24.4S, v25.4S
+ __ cm(Assembler::GT, v12, __ T2D, v13, v14); // cmgt v12.2D, v13.2D, v14.2D
+ __ cm(Assembler::GE, v26, __ T8B, v27, v28); // cmge v26.8B, v27.8B, v28.8B
+ __ cm(Assembler::GE, v23, __ T16B, v24, v25); // cmge v23.16B, v24.16B, v25.16B
+ __ cm(Assembler::GE, v28, __ T4H, v29, v30); // cmge v28.4H, v29.4H, v30.4H
+ __ cm(Assembler::GE, v14, __ T8H, v15, v16); // cmge v14.8H, v15.8H, v16.8H
+ __ cm(Assembler::GE, v11, __ T2S, v12, v13); // cmge v11.2S, v12.2S, v13.2S
+ __ cm(Assembler::GE, v24, __ T4S, v25, v26); // cmge v24.4S, v25.4S, v26.4S
+ __ cm(Assembler::GE, v1, __ T2D, v2, v3); // cmge v1.2D, v2.2D, v3.2D
+ __ cm(Assembler::EQ, v12, __ T8B, v13, v14); // cmeq v12.8B, v13.8B, v14.8B
+ __ cm(Assembler::EQ, v31, __ T16B, v0, v1); // cmeq v31.16B, v0.16B, v1.16B
+ __ cm(Assembler::EQ, v10, __ T4H, v11, v12); // cmeq v10.4H, v11.4H, v12.4H
+ __ cm(Assembler::EQ, v16, __ T8H, v17, v18); // cmeq v16.8H, v17.8H, v18.8H
+ __ cm(Assembler::EQ, v7, __ T2S, v8, v9); // cmeq v7.2S, v8.2S, v9.2S
+ __ cm(Assembler::EQ, v2, __ T4S, v3, v4); // cmeq v2.4S, v3.4S, v4.4S
+ __ cm(Assembler::EQ, v3, __ T2D, v4, v5); // cmeq v3.2D, v4.2D, v5.2D
+ __ cm(Assembler::HI, v13, __ T8B, v14, v15); // cmhi v13.8B, v14.8B, v15.8B
+ __ cm(Assembler::HI, v19, __ T16B, v20, v21); // cmhi v19.16B, v20.16B, v21.16B
+ __ cm(Assembler::HI, v17, __ T4H, v18, v19); // cmhi v17.4H, v18.4H, v19.4H
+ __ cm(Assembler::HI, v16, __ T8H, v17, v18); // cmhi v16.8H, v17.8H, v18.8H
+ __ cm(Assembler::HI, v3, __ T2S, v4, v5); // cmhi v3.2S, v4.2S, v5.2S
+ __ cm(Assembler::HI, v1, __ T4S, v2, v3); // cmhi v1.4S, v2.4S, v3.4S
+ __ cm(Assembler::HI, v11, __ T2D, v12, v13); // cmhi v11.2D, v12.2D, v13.2D
+ __ cm(Assembler::HS, v30, __ T8B, v31, v0); // cmhs v30.8B, v31.8B, v0.8B
+ __ cm(Assembler::HS, v5, __ T16B, v6, v7); // cmhs v5.16B, v6.16B, v7.16B
+ __ cm(Assembler::HS, v8, __ T4H, v9, v10); // cmhs v8.4H, v9.4H, v10.4H
+ __ cm(Assembler::HS, v15, __ T8H, v16, v17); // cmhs v15.8H, v16.8H, v17.8H
+ __ cm(Assembler::HS, v29, __ T2S, v30, v31); // cmhs v29.2S, v30.2S, v31.2S
+ __ cm(Assembler::HS, v30, __ T4S, v31, v0); // cmhs v30.4S, v31.4S, v0.4S
+ __ cm(Assembler::HS, v0, __ T2D, v1, v2); // cmhs v0.2D, v1.2D, v2.2D
+ __ fcm(Assembler::EQ, v20, __ T2S, v21, v22); // fcmeq v20.2S, v21.2S, v22.2S
+ __ fcm(Assembler::EQ, v7, __ T4S, v8, v9); // fcmeq v7.4S, v8.4S, v9.4S
+ __ fcm(Assembler::EQ, v20, __ T2D, v21, v22); // fcmeq v20.2D, v21.2D, v22.2D
+ __ fcm(Assembler::GT, v23, __ T2S, v24, v25); // fcmgt v23.2S, v24.2S, v25.2S
+ __ fcm(Assembler::GT, v28, __ T4S, v29, v30); // fcmgt v28.4S, v29.4S, v30.4S
+ __ fcm(Assembler::GT, v21, __ T2D, v22, v23); // fcmgt v21.2D, v22.2D, v23.2D
+ __ fcm(Assembler::GE, v27, __ T2S, v28, v29); // fcmge v27.2S, v28.2S, v29.2S
+ __ fcm(Assembler::GE, v25, __ T4S, v26, v27); // fcmge v25.4S, v26.4S, v27.4S
+ __ fcm(Assembler::GE, v5, __ T2D, v6, v7); // fcmge v5.2D, v6.2D, v7.2D
// SVEComparisonWithZero
- __ sve_fcm(Assembler::EQ, p3, __ S, p3, z2, 0.0); // fcmeq p3.s, p3/z, z2.s, #0.0
- __ sve_fcm(Assembler::GT, p9, __ D, p0, z16, 0.0); // fcmgt p9.d, p0/z, z16.d, #0.0
- __ sve_fcm(Assembler::GE, p0, __ D, p1, z11, 0.0); // fcmge p0.d, p1/z, z11.d, #0.0
- __ sve_fcm(Assembler::LT, p4, __ D, p7, z14, 0.0); // fcmlt p4.d, p7/z, z14.d, #0.0
- __ sve_fcm(Assembler::LE, p0, __ S, p5, z20, 0.0); // fcmle p0.s, p5/z, z20.s, #0.0
- __ sve_fcm(Assembler::NE, p11, __ D, p6, z27, 0.0); // fcmne p11.d, p6/z, z27.d, #0.0
+ __ sve_fcm(Assembler::EQ, p0, __ D, p7, z23, 0.0); // fcmeq p0.d, p7/z, z23.d, #0.0
+ __ sve_fcm(Assembler::GT, p2, __ S, p7, z12, 0.0); // fcmgt p2.s, p7/z, z12.s, #0.0
+ __ sve_fcm(Assembler::GE, p7, __ D, p7, z29, 0.0); // fcmge p7.d, p7/z, z29.d, #0.0
+ __ sve_fcm(Assembler::LT, p9, __ S, p3, z31, 0.0); // fcmlt p9.s, p3/z, z31.s, #0.0
+ __ sve_fcm(Assembler::LE, p9, __ D, p6, z31, 0.0); // fcmle p9.d, p6/z, z31.d, #0.0
+ __ sve_fcm(Assembler::NE, p10, __ S, p2, z16, 0.0); // fcmne p10.s, p2/z, z16.s, #0.0
// SVEComparisonWithImm
- __ sve_cmp(Assembler::EQ, p12, __ B, p5, z4, 0); // cmpeq p12.b, p5/z, z4.b, #0
- __ sve_cmp(Assembler::GT, p15, __ H, p2, z5, 12); // cmpgt p15.h, p2/z, z5.h, #12
- __ sve_cmp(Assembler::GE, p7, __ S, p7, z28, 3); // cmpge p7.s, p7/z, z28.s, #3
- __ sve_cmp(Assembler::LT, p15, __ H, p4, z5, 15); // cmplt p15.h, p4/z, z5.h, #15
- __ sve_cmp(Assembler::LE, p9, __ S, p4, z26, -4); // cmple p9.s, p4/z, z26.s, #-4
- __ sve_cmp(Assembler::NE, p5, __ B, p7, z9, 1); // cmpne p5.b, p7/z, z9.b, #1
- __ sve_cmp(Assembler::HS, p13, __ D, p1, z27, 43); // cmphs p13.d, p1/z, z27.d, #43
- __ sve_cmp(Assembler::HI, p10, __ B, p6, z9, 70); // cmphi p10.b, p6/z, z9.b, #70
- __ sve_cmp(Assembler::LS, p8, __ B, p7, z22, 61); // cmpls p8.b, p7/z, z22.b, #61
- __ sve_cmp(Assembler::LO, p11, __ S, p5, z17, 11); // cmplo p11.s, p5/z, z17.s, #11
+ __ sve_cmp(Assembler::EQ, p4, __ D, p4, z6, 11); // cmpeq p4.d, p4/z, z6.d, #11
+ __ sve_cmp(Assembler::GT, p14, __ B, p2, z30, 4); // cmpgt p14.b, p2/z, z30.b, #4
+ __ sve_cmp(Assembler::GE, p5, __ D, p4, z4, 1); // cmpge p5.d, p4/z, z4.d, #1
+ __ sve_cmp(Assembler::LT, p11, __ D, p3, z3, 6); // cmplt p11.d, p3/z, z3.d, #6
+ __ sve_cmp(Assembler::LE, p9, __ S, p0, z19, -1); // cmple p9.s, p0/z, z19.s, #-1
+ __ sve_cmp(Assembler::NE, p3, __ S, p2, z12, -3); // cmpne p3.s, p2/z, z12.s, #-3
+ __ sve_cmp(Assembler::HS, p11, __ D, p4, z1, 20); // cmphs p11.d, p4/z, z1.d, #20
+ __ sve_cmp(Assembler::HI, p8, __ S, p5, z2, 53); // cmphi p8.s, p5/z, z2.s, #53
+ __ sve_cmp(Assembler::LS, p5, __ D, p6, z21, 49); // cmpls p5.d, p6/z, z21.d, #49
+ __ sve_cmp(Assembler::LO, p13, __ B, p7, z3, 97); // cmplo p13.b, p7/z, z3.b, #97
// SpecialCases
__ ccmn(zr, zr, 3u, Assembler::LE); // ccmn xzr, xzr, #3, LE
@@ -1071,215 +1086,229 @@
__ fmovd(v0, -1.0625); // fmov d0, #-1.0625
// LSEOp
- __ swp(Assembler::xword, r15, r6, r12); // swp x15, x6, [x12]
- __ ldadd(Assembler::xword, r16, r11, r13); // ldadd x16, x11, [x13]
- __ ldbic(Assembler::xword, r23, r1, r30); // ldclr x23, x1, [x30]
- __ ldeor(Assembler::xword, r19, r5, r17); // ldeor x19, x5, [x17]
- __ ldorr(Assembler::xword, r2, r16, r22); // ldset x2, x16, [x22]
- __ ldsmin(Assembler::xword, r13, r10, r21); // ldsmin x13, x10, [x21]
- __ ldsmax(Assembler::xword, r29, r27, r12); // ldsmax x29, x27, [x12]
- __ ldumin(Assembler::xword, r27, r3, r1); // ldumin x27, x3, [x1]
- __ ldumax(Assembler::xword, zr, r24, r19); // ldumax xzr, x24, [x19]
+ __ swp(Assembler::xword, r19, r17, r9); // swp x19, x17, [x9]
+ __ ldadd(Assembler::xword, r28, r27, r15); // ldadd x28, x27, [x15]
+ __ ldbic(Assembler::xword, r7, r21, r23); // ldclr x7, x21, [x23]
+ __ ldeor(Assembler::xword, zr, r25, r2); // ldeor xzr, x25, [x2]
+ __ ldorr(Assembler::xword, zr, r27, r15); // ldset xzr, x27, [x15]
+ __ ldsmin(Assembler::xword, r10, r23, r19); // ldsmin x10, x23, [x19]
+ __ ldsmax(Assembler::xword, r3, r16, r0); // ldsmax x3, x16, [x0]
+ __ ldumin(Assembler::xword, r25, r26, r23); // ldumin x25, x26, [x23]
+ __ ldumax(Assembler::xword, r2, r16, r12); // ldumax x2, x16, [x12]
// LSEOp
- __ swpa(Assembler::xword, r17, r9, r28); // swpa x17, x9, [x28]
- __ ldadda(Assembler::xword, r27, r15, r7); // ldadda x27, x15, [x7]
- __ ldbica(Assembler::xword, r21, r23, sp); // ldclra x21, x23, [sp]
- __ ldeora(Assembler::xword, r25, r2, sp); // ldeora x25, x2, [sp]
- __ ldorra(Assembler::xword, r27, r16, r10); // ldseta x27, x16, [x10]
- __ ldsmina(Assembler::xword, r23, r19, r3); // ldsmina x23, x19, [x3]
- __ ldsmaxa(Assembler::xword, r16, r0, r25); // ldsmaxa x16, x0, [x25]
- __ ldumina(Assembler::xword, r26, r23, r2); // ldumina x26, x23, [x2]
- __ ldumaxa(Assembler::xword, r16, r12, r4); // ldumaxa x16, x12, [x4]
+ __ swpa(Assembler::xword, r4, r28, r30); // swpa x4, x28, [x30]
+ __ ldadda(Assembler::xword, r29, r16, r27); // ldadda x29, x16, [x27]
+ __ ldbica(Assembler::xword, r6, r9, r29); // ldclra x6, x9, [x29]
+ __ ldeora(Assembler::xword, r16, r7, r4); // ldeora x16, x7, [x4]
+ __ ldorra(Assembler::xword, r7, r15, r9); // ldseta x7, x15, [x9]
+ __ ldsmina(Assembler::xword, r23, r8, r2); // ldsmina x23, x8, [x2]
+ __ ldsmaxa(Assembler::xword, r28, r21, sp); // ldsmaxa x28, x21, [sp]
+ __ ldumina(Assembler::xword, r5, r27, r0); // ldumina x5, x27, [x0]
+ __ ldumaxa(Assembler::xword, r17, r15, r4); // ldumaxa x17, x15, [x4]
// LSEOp
- __ swpal(Assembler::xword, r28, r30, r29); // swpal x28, x30, [x29]
- __ ldaddal(Assembler::xword, r16, r27, r6); // ldaddal x16, x27, [x6]
- __ ldbical(Assembler::xword, r9, r29, r15); // ldclral x9, x29, [x15]
- __ ldeoral(Assembler::xword, r7, r4, r7); // ldeoral x7, x4, [x7]
- __ ldorral(Assembler::xword, r15, r9, r23); // ldsetal x15, x9, [x23]
- __ ldsminal(Assembler::xword, r8, r2, r28); // ldsminal x8, x2, [x28]
- __ ldsmaxal(Assembler::xword, r21, zr, r5); // ldsmaxal x21, xzr, [x5]
- __ lduminal(Assembler::xword, r27, r0, r17); // lduminal x27, x0, [x17]
- __ ldumaxal(Assembler::xword, r15, r4, r26); // ldumaxal x15, x4, [x26]
+ __ swpal(Assembler::xword, r26, r8, r28); // swpal x26, x8, [x28]
+ __ ldaddal(Assembler::xword, r22, r27, r27); // ldaddal x22, x27, [x27]
+ __ ldbical(Assembler::xword, r25, r23, r0); // ldclral x25, x23, [x0]
+ __ ldeoral(Assembler::xword, r4, r6, r15); // ldeoral x4, x6, [x15]
+ __ ldorral(Assembler::xword, r0, r4, r15); // ldsetal x0, x4, [x15]
+ __ ldsminal(Assembler::xword, r1, r10, r7); // ldsminal x1, x10, [x7]
+ __ ldsmaxal(Assembler::xword, r5, r10, r28); // ldsmaxal x5, x10, [x28]
+ __ lduminal(Assembler::xword, r7, r20, r23); // lduminal x7, x20, [x23]
+ __ ldumaxal(Assembler::xword, r21, r6, r11); // ldumaxal x21, x6, [x11]
// LSEOp
- __ swpl(Assembler::xword, r8, r28, r22); // swpl x8, x28, [x22]
- __ ldaddl(Assembler::xword, r27, r27, r25); // ldaddl x27, x27, [x25]
- __ ldbicl(Assembler::xword, r23, r0, r4); // ldclrl x23, x0, [x4]
- __ ldeorl(Assembler::xword, r6, r16, r0); // ldeorl x6, x16, [x0]
- __ ldorrl(Assembler::xword, r4, r15, r1); // ldsetl x4, x15, [x1]
- __ ldsminl(Assembler::xword, r10, r7, r5); // ldsminl x10, x7, [x5]
- __ ldsmaxl(Assembler::xword, r10, r28, r7); // ldsmaxl x10, x28, [x7]
- __ lduminl(Assembler::xword, r20, r23, r21); // lduminl x20, x23, [x21]
- __ ldumaxl(Assembler::xword, r6, r11, r8); // ldumaxl x6, x11, [x8]
+ __ swpl(Assembler::xword, r8, r17, sp); // swpl x8, x17, [sp]
+ __ ldaddl(Assembler::xword, r6, r17, r2); // ldaddl x6, x17, [x2]
+ __ ldbicl(Assembler::xword, r12, r30, r29); // ldclrl x12, x30, [x29]
+ __ ldeorl(Assembler::xword, r3, r27, r22); // ldeorl x3, x27, [x22]
+ __ ldorrl(Assembler::xword, r29, r14, r13); // ldsetl x29, x14, [x13]
+ __ ldsminl(Assembler::xword, r28, r17, r24); // ldsminl x28, x17, [x24]
+ __ ldsmaxl(Assembler::xword, r5, r2, r14); // ldsmaxl x5, x2, [x14]
+ __ lduminl(Assembler::xword, r10, r16, r11); // lduminl x10, x16, [x11]
+ __ ldumaxl(Assembler::xword, r27, r23, r12); // ldumaxl x27, x23, [x12]
// LSEOp
- __ swp(Assembler::word, r17, zr, r6); // swp w17, wzr, [x6]
- __ ldadd(Assembler::word, r17, r2, r12); // ldadd w17, w2, [x12]
- __ ldbic(Assembler::word, r30, r29, r3); // ldclr w30, w29, [x3]
- __ ldeor(Assembler::word, r27, r22, r29); // ldeor w27, w22, [x29]
- __ ldorr(Assembler::word, r14, r13, r28); // ldset w14, w13, [x28]
- __ ldsmin(Assembler::word, r17, r24, r5); // ldsmin w17, w24, [x5]
- __ ldsmax(Assembler::word, r2, r14, r10); // ldsmax w2, w14, [x10]
- __ ldumin(Assembler::word, r16, r11, r27); // ldumin w16, w11, [x27]
- __ ldumax(Assembler::word, r23, r12, r4); // ldumax w23, w12, [x4]
+ __ swp(Assembler::word, r4, r22, r17); // swp w4, w22, [x17]
+ __ ldadd(Assembler::word, r4, r1, r19); // ldadd w4, w1, [x19]
+ __ ldbic(Assembler::word, r16, r16, r13); // ldclr w16, w16, [x13]
+ __ ldeor(Assembler::word, r14, r12, r2); // ldeor w14, w12, [x2]
+ __ ldorr(Assembler::word, r17, r3, r21); // ldset w17, w3, [x21]
+ __ ldsmin(Assembler::word, r23, r5, r6); // ldsmin w23, w5, [x6]
+ __ ldsmax(Assembler::word, r7, r19, r13); // ldsmax w7, w19, [x13]
+ __ ldumin(Assembler::word, r28, r17, r16); // ldumin w28, w17, [x16]
+ __ ldumax(Assembler::word, r6, r2, r29); // ldumax w6, w2, [x29]
// LSEOp
- __ swpa(Assembler::word, r22, r17, r4); // swpa w22, w17, [x4]
- __ ldadda(Assembler::word, r1, r19, r16); // ldadda w1, w19, [x16]
- __ ldbica(Assembler::word, r16, r13, r14); // ldclra w16, w13, [x14]
- __ ldeora(Assembler::word, r12, r2, r17); // ldeora w12, w2, [x17]
- __ ldorra(Assembler::word, r3, r21, r23); // ldseta w3, w21, [x23]
- __ ldsmina(Assembler::word, r5, r6, r7); // ldsmina w5, w6, [x7]
- __ ldsmaxa(Assembler::word, r19, r13, r28); // ldsmaxa w19, w13, [x28]
- __ ldumina(Assembler::word, r17, r16, r6); // ldumina w17, w16, [x6]
- __ ldumaxa(Assembler::word, r2, r29, r3); // ldumaxa w2, w29, [x3]
+ __ swpa(Assembler::word, r3, r4, r6); // swpa w3, w4, [x6]
+ __ ldadda(Assembler::word, r16, r20, r13); // ldadda w16, w20, [x13]
+ __ ldbica(Assembler::word, r12, r20, r8); // ldclra w12, w20, [x8]
+ __ ldeora(Assembler::word, r25, r20, r19); // ldeora w25, w20, [x19]
+ __ ldorra(Assembler::word, r0, r11, r24); // ldseta w0, w11, [x24]
+ __ ldsmina(Assembler::word, r6, r20, sp); // ldsmina w6, w20, [sp]
+ __ ldsmaxa(Assembler::word, r14, r16, r6); // ldsmaxa w14, w16, [x6]
+ __ ldumina(Assembler::word, r0, r7, r15); // ldumina w0, w7, [x15]
+ __ ldumaxa(Assembler::word, r19, r26, r9); // ldumaxa w19, w26, [x9]
// LSEOp
- __ swpal(Assembler::word, r4, r6, r15); // swpal w4, w6, [x15]
- __ ldaddal(Assembler::word, r20, r13, r12); // ldaddal w20, w13, [x12]
- __ ldbical(Assembler::word, r20, r8, r25); // ldclral w20, w8, [x25]
- __ ldeoral(Assembler::word, r20, r19, r0); // ldeoral w20, w19, [x0]
- __ ldorral(Assembler::word, r11, r24, r6); // ldsetal w11, w24, [x6]
- __ ldsminal(Assembler::word, r20, zr, r14); // ldsminal w20, wzr, [x14]
- __ ldsmaxal(Assembler::word, r16, r6, r0); // ldsmaxal w16, w6, [x0]
- __ lduminal(Assembler::word, r7, r15, r19); // lduminal w7, w15, [x19]
- __ ldumaxal(Assembler::word, r26, r9, r10); // ldumaxal w26, w9, [x10]
+ __ swpal(Assembler::word, r10, r23, r21); // swpal w10, w23, [x21]
+ __ ldaddal(Assembler::word, r22, r28, r2); // ldaddal w22, w28, [x2]
+ __ ldbical(Assembler::word, r3, r15, r19); // ldclral w3, w15, [x19]
+ __ ldeoral(Assembler::word, r20, r7, r4); // ldeoral w20, w7, [x4]
+ __ ldorral(Assembler::word, r29, r7, r0); // ldsetal w29, w7, [x0]
+ __ ldsminal(Assembler::word, r9, r16, r20); // ldsminal w9, w16, [x20]
+ __ ldsmaxal(Assembler::word, r23, r4, r16); // ldsmaxal w23, w4, [x16]
+ __ lduminal(Assembler::word, r10, r23, r11); // lduminal w10, w23, [x11]
+ __ ldumaxal(Assembler::word, r25, r6, sp); // ldumaxal w25, w6, [sp]
// LSEOp
- __ swpl(Assembler::word, r23, r21, r22); // swpl w23, w21, [x22]
- __ ldaddl(Assembler::word, r28, r2, r3); // ldaddl w28, w2, [x3]
- __ ldbicl(Assembler::word, r15, r19, r20); // ldclrl w15, w19, [x20]
- __ ldeorl(Assembler::word, r7, r4, r29); // ldeorl w7, w4, [x29]
- __ ldorrl(Assembler::word, r7, r0, r9); // ldsetl w7, w0, [x9]
- __ ldsminl(Assembler::word, r16, r20, r23); // ldsminl w16, w20, [x23]
- __ ldsmaxl(Assembler::word, r4, r16, r10); // ldsmaxl w4, w16, [x10]
- __ lduminl(Assembler::word, r23, r11, r25); // lduminl w23, w11, [x25]
- __ ldumaxl(Assembler::word, r6, zr, r16); // ldumaxl w6, wzr, [x16]
+ __ swpl(Assembler::word, r16, r13, r23); // swpl w16, w13, [x23]
+ __ ldaddl(Assembler::word, r12, r1, r14); // ldaddl w12, w1, [x14]
+ __ ldbicl(Assembler::word, r9, r21, r16); // ldclrl w9, w21, [x16]
+ __ ldeorl(Assembler::word, r26, r15, r4); // ldeorl w26, w15, [x4]
+ __ ldorrl(Assembler::word, r4, r16, r8); // ldsetl w4, w16, [x8]
+ __ ldsminl(Assembler::word, r6, r30, r4); // ldsminl w6, w30, [x4]
+ __ ldsmaxl(Assembler::word, r29, r17, r29); // ldsmaxl w29, w17, [x29]
+ __ lduminl(Assembler::word, r26, r9, r15); // lduminl w26, w9, [x15]
+ __ ldumaxl(Assembler::word, r2, r11, r29); // ldumaxl w2, w11, [x29]
// SHA3SIMDOp
- __ bcax(v13, __ T16B, v22, v11, v1); // bcax v13.16B, v22.16B, v11.16B, v1.16B
- __ eor3(v13, __ T16B, v8, v20, v16); // eor3 v13.16B, v8.16B, v20.16B, v16.16B
- __ rax1(v25, __ T2D, v15, v4); // rax1 v25.2D, v15.2D, v4.2D
- __ xar(v4, __ T2D, v17, v8, 13); // xar v4.2D, v17.2D, v8.2D, #13
+ __ bcax(v3, __ T16B, v7, v1, v27); // bcax v3.16B, v7.16B, v1.16B, v27.16B
+ __ eor3(v21, __ T16B, v18, v14, v8); // eor3 v21.16B, v18.16B, v14.16B, v8.16B
+ __ rax1(v18, __ T2D, v22, v25); // rax1 v18.2D, v22.2D, v25.2D
+ __ xar(v5, __ T2D, v20, v21, 37); // xar v5.2D, v20.2D, v21.2D, #37
// SHA512SIMDOp
- __ sha512h(v29, __ T2D, v4, v28); // sha512h q29, q4, v28.2D
- __ sha512h2(v16, __ T2D, v29, v26); // sha512h2 q16, q29, v26.2D
- __ sha512su0(v9, __ T2D, v14); // sha512su0 v9.2D, v14.2D
- __ sha512su1(v2, __ T2D, v11, v28); // sha512su1 v2.2D, v11.2D, v28.2D
+ __ sha512h(v23, __ T2D, v16, v30); // sha512h q23, q16, v30.2D
+ __ sha512h2(v20, __ T2D, v20, v0); // sha512h2 q20, q20, v0.2D
+ __ sha512su0(v4, __ T2D, v19); // sha512su0 v4.2D, v19.2D
+ __ sha512su1(v24, __ T2D, v4, v20); // sha512su1 v24.2D, v4.2D, v20.2D
// SVEBinaryImmOp
- __ sve_add(z3, __ B, 10u); // add z3.b, z3.b, #0xa
- __ sve_sub(z26, __ S, 150u); // sub z26.s, z26.s, #0x96
- __ sve_and(z14, __ H, 57343u); // and z14.h, z14.h, #0xdfff
- __ sve_eor(z24, __ B, 191u); // eor z24.b, z24.b, #0xbf
- __ sve_orr(z17, __ S, 4294966791u); // orr z17.s, z17.s, #0xfffffe07
+ __ sve_add(z4, __ D, 210u); // add z4.d, z4.d, #0xd2
+ __ sve_sub(z19, __ B, 71u); // sub z19.b, z19.b, #0x47
+ __ sve_and(z8, __ H, 49663u); // and z8.h, z8.h, #0xc1ff
+ __ sve_eor(z31, __ S, 4294967231u); // eor z31.s, z31.s, #0xffffffbf
+ __ sve_orr(z1, __ H, 16368u); // orr z1.h, z1.h, #0x3ff0
// SVEBinaryImmOp
- __ sve_add(z20, __ S, 3u); // add z20.s, z20.s, #0x3
- __ sve_sub(z4, __ S, 196u); // sub z4.s, z4.s, #0xc4
- __ sve_and(z4, __ S, 4286578691u); // and z4.s, z4.s, #0xff800003
- __ sve_eor(z25, __ S, 33553408u); // eor z25.s, z25.s, #0x1fffc00
- __ sve_orr(z8, __ H, 49663u); // orr z8.h, z8.h, #0xc1ff
+ __ sve_add(z0, __ H, 61u); // add z0.h, z0.h, #0x3d
+ __ sve_sub(z24, __ S, 36u); // sub z24.s, z24.s, #0x24
+ __ sve_and(z27, __ B, 243u); // and z27.b, z27.b, #0xf3
+ __ sve_eor(z24, __ H, 65534u); // eor z24.h, z24.h, #0xfffe
+ __ sve_orr(z22, __ S, 4294967293u); // orr z22.s, z22.s, #0xfffffffd
// SVEBinaryImmOp
- __ sve_add(z30, __ S, 36u); // add z30.s, z30.s, #0x24
- __ sve_sub(z30, __ B, 85u); // sub z30.b, z30.b, #0x55
- __ sve_and(z19, __ H, 4032u); // and z19.h, z19.h, #0xfc0
- __ sve_eor(z7, __ D, 274877904896u); // eor z7.d, z7.d, #0x3ffffff800
- __ sve_orr(z27, __ B, 243u); // orr z27.b, z27.b, #0xf3
+ __ sve_add(z29, __ H, 113u); // add z29.h, z29.h, #0x71
+ __ sve_sub(z20, __ B, 165u); // sub z20.b, z20.b, #0xa5
+ __ sve_and(z28, __ H, 32256u); // and z28.h, z28.h, #0x7e00
+ __ sve_eor(z12, __ S, 4287102855u); // eor z12.s, z12.s, #0xff87ff87
+ __ sve_orr(z9, __ S, 3825205247u); // orr z9.s, z9.s, #0xe3ffffff
// SVEBinaryImmOp
- __ sve_add(z23, __ H, 132u); // add z23.h, z23.h, #0x84
- __ sve_sub(z30, __ S, 183u); // sub z30.s, z30.s, #0xb7
- __ sve_and(z20, __ D, 4503599627354112u); // and z20.d, z20.d, #0xfffffffffc000
- __ sve_eor(z13, __ S, 4042322160u); // eor z13.s, z13.s, #0xf0f0f0f0
- __ sve_orr(z28, __ H, 32256u); // orr z28.h, z28.h, #0x7e00
+ __ sve_add(z18, __ S, 41u); // add z18.s, z18.s, #0x29
+ __ sve_sub(z0, __ B, 98u); // sub z0.b, z0.b, #0x62
+ __ sve_and(z8, __ H, 32768u); // and z8.h, z8.h, #0x8000
+ __ sve_eor(z4, __ H, 508u); // eor z4.h, z4.h, #0x1fc
+ __ sve_orr(z0, __ H, 64512u); // orr z0.h, z0.h, #0xfc00
// SVEBinaryImmOp
- __ sve_add(z11, __ S, 13u); // add z11.s, z11.s, #0xd
- __ sve_sub(z24, __ H, 159u); // sub z24.h, z24.h, #0x9f
- __ sve_and(z13, __ S, 2151677951u); // and z13.s, z13.s, #0x803fffff
- __ sve_eor(z4, __ B, 124u); // eor z4.b, z4.b, #0x7c
- __ sve_orr(z7, __ H, 32768u); // orr z7.h, z7.h, #0x8000
+ __ sve_add(z3, __ B, 79u); // add z3.b, z3.b, #0x4f
+ __ sve_sub(z19, __ D, 84u); // sub z19.d, z19.d, #0x54
+ __ sve_and(z24, __ B, 62u); // and z24.b, z24.b, #0x3e
+ __ sve_eor(z24, __ D, 18428729675200069887u); // eor z24.d, z24.d, #0xffc00000000000ff
+ __ sve_orr(z11, __ D, 17296056810822168583u); // orr z11.d, z11.d, #0xf007f007f007f007
// SVEBinaryImmOp
- __ sve_add(z4, __ H, 243u); // add z4.h, z4.h, #0xf3
- __ sve_sub(z5, __ B, 86u); // sub z5.b, z5.b, #0x56
- __ sve_and(z21, __ D, 8064u); // and z21.d, z21.d, #0x1f80
- __ sve_eor(z9, __ S, 130023424u); // eor z9.s, z9.s, #0x7c00000
- __ sve_orr(z24, __ B, 62u); // orr z24.b, z24.b, #0x3e
+ __ sve_add(z31, __ S, 115u); // add z31.s, z31.s, #0x73
+ __ sve_sub(z3, __ D, 134u); // sub z3.d, z3.d, #0x86
+ __ sve_and(z22, __ S, 4042322160u); // and z22.s, z22.s, #0xf0f0f0f0
+ __ sve_eor(z3, __ B, 225u); // eor z3.b, z3.b, #0xe1
+ __ sve_orr(z9, __ S, 4164941887u); // orr z9.s, z9.s, #0xf83ff83f
// SVEVectorOp
- __ sve_add(z23, __ S, z28, z13); // add z23.s, z28.s, z13.s
- __ sve_sub(z10, __ S, z26, z12); // sub z10.s, z26.s, z12.s
- __ sve_fadd(z30, __ S, z17, z14); // fadd z30.s, z17.s, z14.s
- __ sve_fmul(z29, __ D, z16, z21); // fmul z29.d, z16.d, z21.d
- __ sve_fsub(z7, __ S, z19, z2); // fsub z7.s, z19.s, z2.s
- __ sve_abs(z26, __ S, p4, z9); // abs z26.s, p4/m, z9.s
- __ sve_add(z17, __ B, p5, z0); // add z17.b, p5/m, z17.b, z0.b
- __ sve_and(z2, __ B, p6, z14); // and z2.b, p6/m, z2.b, z14.b
- __ sve_asr(z11, __ S, p5, z14); // asr z11.s, p5/m, z11.s, z14.s
- __ sve_bic(z29, __ B, p3, z3); // bic z29.b, p3/m, z29.b, z3.b
- __ sve_clz(z22, __ D, p2, z3); // clz z22.d, p2/m, z3.d
- __ sve_cnt(z27, __ S, p0, z19); // cnt z27.s, p0/m, z19.s
- __ sve_eor(z7, __ H, p6, z21); // eor z7.h, p6/m, z7.h, z21.h
- __ sve_lsl(z5, __ B, p2, z25); // lsl z5.b, p2/m, z5.b, z25.b
- __ sve_lsr(z21, __ B, p4, z17); // lsr z21.b, p4/m, z21.b, z17.b
- __ sve_mul(z3, __ H, p2, z19); // mul z3.h, p2/m, z3.h, z19.h
- __ sve_neg(z7, __ S, p3, z14); // neg z7.s, p3/m, z14.s
- __ sve_not(z17, __ D, p2, z13); // not z17.d, p2/m, z13.d
- __ sve_orr(z17, __ H, p7, z17); // orr z17.h, p7/m, z17.h, z17.h
- __ sve_rbit(z15, __ S, p3, z26); // rbit z15.s, p3/m, z26.s
- __ sve_revb(z27, __ H, p5, z7); // revb z27.h, p5/m, z7.h
- __ sve_smax(z5, __ H, p7, z27); // smax z5.h, p7/m, z5.h, z27.h
- __ sve_smin(z0, __ S, p3, z24); // smin z0.s, p3/m, z0.s, z24.s
- __ sve_sub(z20, __ S, p0, z3); // sub z20.s, p0/m, z20.s, z3.s
- __ sve_fabs(z25, __ D, p1, z25); // fabs z25.d, p1/m, z25.d
- __ sve_fadd(z17, __ S, p4, z1); // fadd z17.s, p4/m, z17.s, z1.s
- __ sve_fdiv(z14, __ S, p7, z13); // fdiv z14.s, p7/m, z14.s, z13.s
- __ sve_fmax(z17, __ D, p0, z30); // fmax z17.d, p0/m, z17.d, z30.d
- __ sve_fmin(z22, __ S, p5, z29); // fmin z22.s, p5/m, z22.s, z29.s
- __ sve_fmul(z8, __ S, p0, z0); // fmul z8.s, p0/m, z8.s, z0.s
- __ sve_fneg(z23, __ D, p5, z0); // fneg z23.d, p5/m, z0.d
- __ sve_frintm(z25, __ S, p6, z23); // frintm z25.s, p6/m, z23.s
- __ sve_frintn(z21, __ S, p5, z1); // frintn z21.s, p5/m, z1.s
- __ sve_frintp(z10, __ D, p5, z11); // frintp z10.d, p5/m, z11.d
- __ sve_fsqrt(z23, __ D, p6, z8); // fsqrt z23.d, p6/m, z8.d
- __ sve_fsub(z17, __ D, p5, z19); // fsub z17.d, p5/m, z17.d, z19.d
- __ sve_fmad(z4, __ D, p5, z13, z30); // fmad z4.d, p5/m, z13.d, z30.d
- __ sve_fmla(z30, __ D, p7, z25, z17); // fmla z30.d, p7/m, z25.d, z17.d
- __ sve_fmls(z14, __ D, p2, z12, z28); // fmls z14.d, p2/m, z12.d, z28.d
- __ sve_fmsb(z5, __ S, p0, z13, z13); // fmsb z5.s, p0/m, z13.s, z13.s
- __ sve_fnmad(z7, __ S, p2, z11, z19); // fnmad z7.s, p2/m, z11.s, z19.s
- __ sve_fnmsb(z25, __ D, p3, z2, z3); // fnmsb z25.d, p3/m, z2.d, z3.d
- __ sve_fnmla(z0, __ D, p5, z5, z20); // fnmla z0.d, p5/m, z5.d, z20.d
- __ sve_fnmls(z28, __ S, p3, z13, z8); // fnmls z28.s, p3/m, z13.s, z8.s
- __ sve_mla(z29, __ B, p0, z14, z27); // mla z29.b, p0/m, z14.b, z27.b
- __ sve_mls(z3, __ H, p6, z8, z24); // mls z3.h, p6/m, z8.h, z24.h
- __ sve_and(z1, z25, z10); // and z1.d, z25.d, z10.d
- __ sve_eor(z1, z20, z25); // eor z1.d, z20.d, z25.d
- __ sve_orr(z28, z19, z16); // orr z28.d, z19.d, z16.d
- __ sve_bic(z27, z13, z1); // bic z27.d, z13.d, z1.d
- __ sve_uzp1(z11, __ B, z9, z1); // uzp1 z11.b, z9.b, z1.b
- __ sve_uzp2(z1, __ H, z27, z26); // uzp2 z1.h, z27.h, z26.h
- __ sve_fabd(z2, __ D, p1, z29); // fabd z2.d, p1/m, z2.d, z29.d
- __ sve_bext(z24, __ D, z2, z2); // bext z24.d, z2.d, z2.d
- __ sve_bdep(z3, __ H, z25, z28); // bdep z3.h, z25.h, z28.h
- __ sve_eor3(z3, z22, z13); // eor3 z3.d, z3.d, z22.d, z13.d
+ __ sve_add(z0, __ D, z4, z2); // add z0.d, z4.d, z2.d
+ __ sve_sub(z14, __ S, z6, z11); // sub z14.s, z6.s, z11.s
+ __ sve_fadd(z14, __ S, z17, z30); // fadd z14.s, z17.s, z30.s
+ __ sve_fmul(z3, __ S, z3, z23); // fmul z3.s, z3.s, z23.s
+ __ sve_fsub(z3, __ S, z24, z28); // fsub z3.s, z24.s, z28.s
+ __ sve_abs(z19, __ D, p5, z7); // abs z19.d, p5/m, z7.d
+ __ sve_add(z21, __ H, p3, z5); // add z21.h, p3/m, z21.h, z5.h
+ __ sve_and(z26, __ S, p1, z22); // and z26.s, p1/m, z26.s, z22.s
+ __ sve_asr(z17, __ H, p0, z3); // asr z17.h, p0/m, z17.h, z3.h
+ __ sve_bic(z20, __ H, p3, z8); // bic z20.h, p3/m, z20.h, z8.h
+ __ sve_clz(z14, __ H, p4, z17); // clz z14.h, p4/m, z17.h
+ __ sve_cnt(z13, __ D, p6, z18); // cnt z13.d, p6/m, z18.d
+ __ sve_eor(z19, __ H, p2, z16); // eor z19.h, p2/m, z19.h, z16.h
+ __ sve_lsl(z27, __ S, p5, z28); // lsl z27.s, p5/m, z27.s, z28.s
+ __ sve_lsr(z8, __ D, p2, z5); // lsr z8.d, p2/m, z8.d, z5.d
+ __ sve_mul(z28, __ H, p2, z0); // mul z28.h, p2/m, z28.h, z0.h
+ __ sve_neg(z25, __ B, p5, z21); // neg z25.b, p5/m, z21.b
+ __ sve_not(z3, __ B, p5, z26); // not z3.b, p5/m, z26.b
+ __ sve_orr(z26, __ S, p7, z19); // orr z26.s, p7/m, z26.s, z19.s
+ __ sve_rbit(z1, __ D, p3, z14); // rbit z1.d, p3/m, z14.d
+ __ sve_revb(z14, __ H, p0, z18); // revb z14.h, p0/m, z18.h
+ __ sve_smax(z31, __ S, p5, z23); // smax z31.s, p5/m, z31.s, z23.s
+ __ sve_smin(z30, __ B, p3, z8); // smin z30.b, p3/m, z30.b, z8.b
+ __ sve_sub(z0, __ S, p3, z23); // sub z0.s, p3/m, z0.s, z23.s
+ __ sve_fabs(z0, __ D, p4, z26); // fabs z0.d, p4/m, z26.d
+ __ sve_fadd(z24, __ D, p3, z22); // fadd z24.d, p3/m, z24.d, z22.d
+ __ sve_fdiv(z2, __ D, p0, z11); // fdiv z2.d, p0/m, z2.d, z11.d
+ __ sve_fmax(z12, __ D, p5, z24); // fmax z12.d, p5/m, z12.d, z24.d
+ __ sve_fmin(z9, __ D, p7, z17); // fmin z9.d, p7/m, z9.d, z17.d
+ __ sve_fmul(z20, __ D, p5, z4); // fmul z20.d, p5/m, z20.d, z4.d
+ __ sve_fneg(z13, __ D, p7, z22); // fneg z13.d, p7/m, z22.d
+ __ sve_frintm(z31, __ D, p6, z18); // frintm z31.d, p6/m, z18.d
+ __ sve_frintn(z15, __ D, p2, z13); // frintn z15.d, p2/m, z13.d
+ __ sve_frintp(z20, __ S, p1, z1); // frintp z20.s, p1/m, z1.s
+ __ sve_fsqrt(z14, __ S, p0, z7); // fsqrt z14.s, p0/m, z7.s
+ __ sve_fsub(z12, __ D, p4, z4); // fsub z12.d, p4/m, z12.d, z4.d
+ __ sve_fmad(z15, __ S, p0, z3, z30); // fmad z15.s, p0/m, z3.s, z30.s
+ __ sve_fmla(z20, __ D, p1, z20, z31); // fmla z20.d, p1/m, z20.d, z31.d
+ __ sve_fmls(z13, __ D, p3, z9, z14); // fmls z13.d, p3/m, z9.d, z14.d
+ __ sve_fmsb(z1, __ S, p3, z28, z3); // fmsb z1.s, p3/m, z28.s, z3.s
+ __ sve_fnmad(z26, __ S, p2, z25, z9); // fnmad z26.s, p2/m, z25.s, z9.s
+ __ sve_fnmsb(z26, __ D, p2, z14, z1); // fnmsb z26.d, p2/m, z14.d, z1.d
+ __ sve_fnmla(z26, __ D, p1, z29, z20); // fnmla z26.d, p1/m, z29.d, z20.d
+ __ sve_fnmls(z6, __ D, p7, z13, z1); // fnmls z6.d, p7/m, z13.d, z1.d
+ __ sve_mla(z11, __ B, p2, z1, z1); // mla z11.b, p2/m, z1.b, z1.b
+ __ sve_mls(z27, __ B, p6, z15, z2); // mls z27.b, p6/m, z15.b, z2.b
+ __ sve_and(z30, z17, z25); // and z30.d, z17.d, z25.d
+ __ sve_eor(z2, z24, z3); // eor z2.d, z24.d, z3.d
+ __ sve_orr(z29, z13, z3); // orr z29.d, z13.d, z3.d
+ __ sve_bic(z14, z16, z28); // bic z14.d, z16.d, z28.d
+ __ sve_uzp1(z4, __ S, z11, z27); // uzp1 z4.s, z11.s, z27.s
+ __ sve_uzp2(z2, __ D, z16, z1); // uzp2 z2.d, z16.d, z1.d
+ __ sve_fabd(z7, __ D, p5, z31); // fabd z7.d, p5/m, z7.d, z31.d
+ __ sve_bext(z16, __ S, z10, z22); // bext z16.s, z10.s, z22.s
+ __ sve_bdep(z29, __ B, z7, z22); // bdep z29.b, z7.b, z22.b
+ __ sve_eor3(z12, z24, z11); // eor3 z12.d, z12.d, z24.d, z11.d
// SVEReductionOp
- __ sve_andv(v27, __ H, p4, z4); // andv h27, p4, z4.h
- __ sve_orv(v26, __ S, p4, z2); // orv s26, p4, z2.s
- __ sve_eorv(v1, __ S, p7, z7); // eorv s1, p7, z7.s
- __ sve_smaxv(v30, __ H, p7, z16); // smaxv h30, p7, z16.h
- __ sve_sminv(v21, __ B, p4, z28); // sminv b21, p4, z28.b
- __ sve_fminv(v21, __ D, p1, z12); // fminv d21, p1, z12.d
- __ sve_fmaxv(v11, __ S, p2, z10); // fmaxv s11, p2, z10.s
- __ sve_fadda(v0, __ D, p1, z22); // fadda d0, p1, d0, z22.d
- __ sve_uaddv(v20, __ H, p1, z3); // uaddv d20, p1, z3.h
+ __ sve_andv(v11, __ B, p2, z0); // andv b11, p2, z0.b
+ __ sve_orv(v23, __ B, p5, z20); // orv b23, p5, z20.b
+ __ sve_eorv(v3, __ B, p3, z15); // eorv b3, p3, z15.b
+ __ sve_smaxv(v30, __ B, p6, z27); // smaxv b30, p6, z27.b
+ __ sve_sminv(v21, __ D, p6, z10); // sminv d21, p6, z10.d
+ __ sve_fminv(v3, __ S, p6, z4); // fminv s3, p6, z4.s
+ __ sve_fmaxv(v6, __ S, p0, z21); // fmaxv s6, p0, z21.s
+ __ sve_fadda(v25, __ D, p6, z30); // fadda d25, p6, d25, z30.d
+ __ sve_uaddv(v31, __ H, p4, z1); // uaddv d31, p4, z1.h
+
+// AddWideNEONOp
+ __ saddwv(v12, v13, __ T8H, v14, __ T8B); // saddw v12.8H, v13.8H, v14.8B
+ __ saddwv2(v30, v31, __ T8H, v0, __ T16B); // saddw2 v30.8H, v31.8H, v0.16B
+ __ saddwv(v13, v14, __ T4S, v15, __ T4H); // saddw v13.4S, v14.4S, v15.4H
+ __ saddwv2(v8, v9, __ T4S, v10, __ T8H); // saddw2 v8.4S, v9.4S, v10.8H
+ __ saddwv(v25, v26, __ T2D, v27, __ T2S); // saddw v25.2D, v26.2D, v27.2S
+ __ saddwv2(v29, v30, __ T2D, v31, __ T4S); // saddw2 v29.2D, v30.2D, v31.4S
+ __ uaddwv(v1, v2, __ T8H, v3, __ T8B); // uaddw v1.8H, v2.8H, v3.8B
+ __ uaddwv2(v31, v0, __ T8H, v1, __ T16B); // uaddw2 v31.8H, v0.8H, v1.16B
+ __ uaddwv(v23, v24, __ T4S, v25, __ T4H); // uaddw v23.4S, v24.4S, v25.4H
+ __ uaddwv2(v31, v0, __ T4S, v1, __ T8H); // uaddw2 v31.4S, v0.4S, v1.8H
+ __ uaddwv(v20, v21, __ T2D, v22, __ T2S); // uaddw v20.2D, v21.2D, v22.2S
+ __ uaddwv2(v0, v1, __ T2D, v2, __ T4S); // uaddw2 v0.2D, v1.2D, v2.4S
__ bind(forth);
@@ -1298,30 +1327,30 @@
0x9101a1a0, 0xb10a5cc8, 0xd10810aa, 0xf10fd061,
0x120cb166, 0x321764bc, 0x52174681, 0x720c0227,
0x9241018e, 0xb25a2969, 0xd278b411, 0xf26aad01,
- 0x14000000, 0x17ffffd7, 0x14000428, 0x94000000,
- 0x97ffffd4, 0x94000425, 0x3400000a, 0x34fffa2a,
- 0x3400844a, 0x35000008, 0x35fff9c8, 0x350083e8,
- 0xb400000b, 0xb4fff96b, 0xb400838b, 0xb500001d,
- 0xb5fff91d, 0xb500833d, 0x10000013, 0x10fff8b3,
- 0x100082d3, 0x90000013, 0x36300016, 0x3637f836,
- 0x36308256, 0x3758000c, 0x375ff7cc, 0x375881ec,
+ 0x14000000, 0x17ffffd7, 0x14000441, 0x94000000,
+ 0x97ffffd4, 0x9400043e, 0x3400000a, 0x34fffa2a,
+ 0x3400876a, 0x35000008, 0x35fff9c8, 0x35008708,
+ 0xb400000b, 0xb4fff96b, 0xb40086ab, 0xb500001d,
+ 0xb5fff91d, 0xb500865d, 0x10000013, 0x10fff8b3,
+ 0x100085f3, 0x90000013, 0x36300016, 0x3637f836,
+ 0x36308576, 0x3758000c, 0x375ff7cc, 0x3758850c,
0x128313a0, 0x528a32c7, 0x7289173b, 0x92ab3acc,
0xd2a0bf94, 0xf2c285e8, 0x9358722f, 0x330e652f,
0x53067f3b, 0x93577c53, 0xb34a1aac, 0xd35a4016,
0x13946c63, 0x93c3dbc8, 0x54000000, 0x54fff5a0,
- 0x54007fc0, 0x54000001, 0x54fff541, 0x54007f61,
- 0x54000002, 0x54fff4e2, 0x54007f02, 0x54000002,
- 0x54fff482, 0x54007ea2, 0x54000003, 0x54fff423,
- 0x54007e43, 0x54000003, 0x54fff3c3, 0x54007de3,
- 0x54000004, 0x54fff364, 0x54007d84, 0x54000005,
- 0x54fff305, 0x54007d25, 0x54000006, 0x54fff2a6,
- 0x54007cc6, 0x54000007, 0x54fff247, 0x54007c67,
- 0x54000008, 0x54fff1e8, 0x54007c08, 0x54000009,
- 0x54fff189, 0x54007ba9, 0x5400000a, 0x54fff12a,
- 0x54007b4a, 0x5400000b, 0x54fff0cb, 0x54007aeb,
- 0x5400000c, 0x54fff06c, 0x54007a8c, 0x5400000d,
- 0x54fff00d, 0x54007a2d, 0x5400000e, 0x54ffefae,
- 0x540079ce, 0x5400000f, 0x54ffef4f, 0x5400796f,
+ 0x540082e0, 0x54000001, 0x54fff541, 0x54008281,
+ 0x54000002, 0x54fff4e2, 0x54008222, 0x54000002,
+ 0x54fff482, 0x540081c2, 0x54000003, 0x54fff423,
+ 0x54008163, 0x54000003, 0x54fff3c3, 0x54008103,
+ 0x54000004, 0x54fff364, 0x540080a4, 0x54000005,
+ 0x54fff305, 0x54008045, 0x54000006, 0x54fff2a6,
+ 0x54007fe6, 0x54000007, 0x54fff247, 0x54007f87,
+ 0x54000008, 0x54fff1e8, 0x54007f28, 0x54000009,
+ 0x54fff189, 0x54007ec9, 0x5400000a, 0x54fff12a,
+ 0x54007e6a, 0x5400000b, 0x54fff0cb, 0x54007e0b,
+ 0x5400000c, 0x54fff06c, 0x54007dac, 0x5400000d,
+ 0x54fff00d, 0x54007d4d, 0x5400000e, 0x54ffefae,
+ 0x54007cee, 0x5400000f, 0x54ffef4f, 0x54007c8f,
0xd40658e1, 0xd4014d22, 0xd4046543, 0xd4273f60,
0xd44cad80, 0xd503201f, 0xd503203f, 0xd503205f,
0xd503209f, 0xd50320bf, 0xd503219f, 0xd50323bf,
@@ -1346,23 +1375,23 @@
0xb81b1022, 0x381ea354, 0x79002fd7, 0xf85cf39a,
0xb8580309, 0x385e218c, 0x784051e1, 0x389e11d8,
0x789fa1f8, 0x79c01865, 0xb881131b, 0xfc5dd3ad,
- 0xbc5d1136, 0xfc00900b, 0xbc181014, 0xf818ec7d,
+ 0xbc5d1137, 0xfc00900b, 0xbc181015, 0xf818ec7d,
0xb81b8c91, 0x381efc40, 0x78007c3d, 0xf857beb0,
0xb8413dd4, 0x385fddd6, 0x78409e2f, 0x389eddea,
0x789e7d94, 0x78de3d55, 0xb8805c13, 0xfc5cadc0,
- 0xbc428c23, 0xfc1a2dc4, 0xbc1caf91, 0xf81475f6,
+ 0xbc428c23, 0xfc1a2dc4, 0xbc1caf92, 0xf81475f6,
0xb81f95d1, 0x381e757e, 0x78014561, 0xf8402436,
0xb85896e2, 0x385f4763, 0x785db4f0, 0x3880374f,
0x789e25e7, 0x78dd0563, 0xb88166f9, 0xfc529540,
- 0xbc4374d1, 0xfc1166ad, 0xbc1ba6c0, 0xf820ea7b,
+ 0xbc4374d3, 0xfc1166ae, 0xbc1ba6c0, 0xf820ea7b,
0xb82d68c8, 0x38367a04, 0x782f4b59, 0xf878c8a4,
0xb8674a24, 0x386b78f1, 0x78776bc0, 0x38a15aca,
- 0x78bedbd5, 0x78fcd94b, 0xb8aa4a7c, 0xfc6ecbbd,
- 0xbc65d8a8, 0xfc2de918, 0xbc3a7b11, 0xf91f1193,
+ 0x78bedbd5, 0x78fcd94b, 0xb8aa4a7c, 0xfc6ecbbe,
+ 0xbc65d8a8, 0xfc2de919, 0xbc3a7b11, 0xf91f1193,
0xb91ed5f7, 0x391ec9bd, 0x79182ceb, 0xf95d4b0a,
0xb9581010, 0x395fc034, 0x795fb221, 0x399d8731,
0x799efb3b, 0x79dd1a2e, 0xb998e4ea, 0xfd583723,
- 0xbd5ea12c, 0xfd18dc37, 0xbd1b0e83, 0x58ffdaa2,
+ 0xbd5ea12c, 0xfd18dc38, 0xbd1b0e83, 0x58ffdaa2,
0x1800001d, 0xf885d1c0, 0xd8ffda40, 0xf8a77820,
0xf9980220, 0x1a030301, 0x3a140311, 0x5a0d000b,
0x7a07015c, 0x9a1001e4, 0xba140182, 0xda0d01bd,
@@ -1383,187 +1412,193 @@
0x9ad521f7, 0x9adb263c, 0x9ac0286a, 0x9ac92f27,
0x9bdd7de6, 0x9b427d4f, 0x1b0b2cf1, 0x1b1ddcf7,
0x9b0b2f6e, 0x9b0cbf04, 0x9b2b728e, 0x9b2cdd6d,
- 0x9bae275e, 0x9ba7954d, 0x7ea3d5fd, 0x1e2f098b,
- 0x1e311bde, 0x1e2f2a93, 0x1e35392f, 0x7efbd522,
- 0x1e7e0ba7, 0x1e621831, 0x1e632946, 0x1e673978,
- 0x1f000d61, 0x1f06db91, 0x1f3b6806, 0x1f2770a2,
- 0x1f4d2f2b, 0x1f48c677, 0x1f744f35, 0x1f7d5851,
- 0x1e2042a8, 0x1e20c293, 0x1e21422b, 0x1e21c0d4,
- 0x1e22c06f, 0x1e23c383, 0x1ee24363, 0x1e6041ce,
- 0x1e60c18a, 0x1e61422b, 0x1e61c32a, 0x1e6240e7,
- 0x1e38038e, 0x9e3802c0, 0x1e780180, 0x9e7801b7,
- 0x1e2200ed, 0x9e2200ee, 0x1e620288, 0x9e620391,
- 0x1e24021e, 0x9e640122, 0x1e300290, 0x9e70009d,
- 0x1e260341, 0x9e6602f8, 0x1e2702ae, 0x9e6700ac,
- 0x1e382180, 0x1e7d2300, 0x1e202368, 0x1e6022a8,
+ 0x9bae275e, 0x9ba7954d, 0x7ea3d5fe, 0x1e30098c,
+ 0x1e321bff, 0x1e302ab3, 0x1e35394f, 0x7efcd542,
+ 0x1e7f0bc7, 0x1e621832, 0x1e632946, 0x1e673979,
+ 0x1f000d81, 0x1f06dfb3, 0x1f3c6c06, 0x1f2774a2,
+ 0x1f4d332c, 0x1f48ca78, 0x1f755356, 0x1f7e5853,
+ 0x1e2042c8, 0x1e20c2b3, 0x1e21424c, 0x1e21c0d5,
+ 0x1e22c070, 0x1e23c3a3, 0x1ee24383, 0x1e6041cf,
+ 0x1e60c1aa, 0x1e61424c, 0x1e61c34a, 0x1e6240e7,
+ 0x1e3803ae, 0x9e3802e0, 0x1e780180, 0x9e7801d7,
+ 0x1e2200ed, 0x9e2200ef, 0x1e620289, 0x9e620393,
+ 0x1e24021e, 0x9e640122, 0x1e3002b0, 0x9e70009d,
+ 0x1e260361, 0x9e660318, 0x1e2702ae, 0x9e6700ad,
+ 0x1e392180, 0x1e7e2320, 0x1e202388, 0x1e6022a8,
0x293a1796, 0x29426e73, 0x697c68fc, 0xa93d0486,
0xa97b5eba, 0x29b47934, 0x29c2534d, 0x69f62dbd,
0xa9bd54bb, 0xa9c503c6, 0x28a63e13, 0x28e25d2c,
0x68c469e0, 0xa8b34748, 0xa8f51c59, 0x28264433,
0x285036c0, 0xa8005f7d, 0xa872290b, 0x0c407160,
- 0x4cdfa350, 0x0cd16f55, 0x4cdf27ba, 0x0d40c0d5,
- 0x4ddfcbad, 0x0dd0cd95, 0x4c408c01, 0x0cdf86a9,
- 0x4d60c327, 0x0dffc928, 0x4deecd89, 0x4cd14887,
- 0x0c404a37, 0x4d40e6c3, 0x4ddfe84c, 0x0dcced4f,
- 0x4cdf0444, 0x0ccb0286, 0x0d60e18b, 0x0dffe62f,
- 0x0df0eb2e, 0x0e31bab4, 0x4e31b841, 0x0e71baf6,
+ 0x4cdfa350, 0x0cd16f56, 0x4cdf27bb, 0x0d40c0d6,
+ 0x4ddfcbae, 0x0dd0cd96, 0x4c408c01, 0x0cdf86aa,
+ 0x4d60c327, 0x0dffc929, 0x4deecd89, 0x4cd14887,
+ 0x0c404a37, 0x4d40e6c4, 0x4ddfe84d, 0x0dcced50,
+ 0x4cdf0444, 0x0ccb0286, 0x0d60e18c, 0x0dffe630,
+ 0x0df0eb2e, 0x0e31bab4, 0x4e31b841, 0x0e71bb17,
0x4e71bbfe, 0x4eb1b9ee, 0x0e30a862, 0x4e30a8e6,
- 0x0e70a883, 0x4e70a907, 0x4eb0ab38, 0x6e30f820,
- 0x0e31ab9b, 0x2e31abdd, 0x4e31a8c5, 0x6e31a8c5,
- 0x0e71abdd, 0x2e71a98b, 0x4e71ab59, 0x6e71a820,
- 0x4eb1abfe, 0x6eb1a820, 0x6eb0fa51, 0x7e30fbbc,
- 0x7e70fb59, 0x7eb0f949, 0x7ef0fb59, 0x0ea0c9ac,
- 0x4ea0ca0f, 0x4ee0c98b, 0x2ea0c96a, 0x6ea0ca51,
- 0x6ee0cb38, 0x0ea0dad5, 0x4ea0db17, 0x4ee0d820,
- 0x0ea0ea30, 0x4ea0e96a, 0x4ee0e8e6, 0x2ea0dbbc,
- 0x6ea0d8e6, 0x6ee0d8c5, 0x0e20b8c5, 0x4e20bab4,
- 0x0e60ba51, 0x4e60ba0f, 0x0ea0ba51, 0x4ea0bbdd,
- 0x4ee0bb7a, 0x0ea0fbbc, 0x4ea0f841, 0x4ee0fb9b,
- 0x2ea0f820, 0x6ea0fab4, 0x6ee0fbbc, 0x2ea1fa0f,
- 0x6ea1f9ac, 0x6ee1f96a, 0x2e205bbc, 0x6e205bbc,
+ 0x0e70a883, 0x4e70a928, 0x4eb0ab59, 0x6e30f820,
+ 0x0e31ab9b, 0x2e31abfe, 0x4e31a8c5, 0x6e31a8c5,
+ 0x0e71abfe, 0x2e71a98b, 0x4e71ab59, 0x6e71a820,
+ 0x4eb1a81f, 0x6eb1a820, 0x6eb0fa93, 0x7e30fbdd,
+ 0x7e70fb7a, 0x7eb0f949, 0x7ef0fb7a, 0x0ea0c9ac,
+ 0x4ea0ca0f, 0x4ee0c98b, 0x2ea0c98b, 0x6ea0ca72,
+ 0x6ee0cb59, 0x0ea0daf6, 0x4ea0db38, 0x4ee0d820,
+ 0x0ea0ea51, 0x4ea0e98b, 0x4ee0e8e6, 0x2ea0dbdd,
+ 0x6ea0d8e6, 0x6ee0d8c5, 0x0e20b8c5, 0x4e20bad5,
+ 0x0e60ba93, 0x4e60ba30, 0x0ea0ba72, 0x4ea0bbfe,
+ 0x4ee0bb9b, 0x0ea0fbbc, 0x4ea0f841, 0x4ee0fbbc,
+ 0x2ea0f841, 0x6ea0fab4, 0x6ee0fbdd, 0x2ea1fa30,
+ 0x6ea1f9cd, 0x6ee1f96a, 0x2e205bdd, 0x6e205bdd,
0x0e351e93, 0x4e381ef6, 0x0eac1d6a, 0x4ea61ca4,
- 0x2e201ffe, 0x6e361eb4, 0x0e2a8528, 0x4e2087fe,
- 0x0e738651, 0x4e6c856a, 0x0ebd879b, 0x4ea48462,
- 0x4efa8738, 0x0e26d4a4, 0x4e25d483, 0x4e6ad528,
- 0x2e3886f6, 0x6e338651, 0x2e6f85cd, 0x6e6684a4,
- 0x2ebe87bc, 0x6eb98717, 0x6ef786d5, 0x0ebbd759,
- 0x4ebad738, 0x4ee5d483, 0x0e399f17, 0x4e3c9f7a,
- 0x0e799f17, 0x4e709dee, 0x0eb79ed5, 0x4ea59c83,
- 0x2eb9d717, 0x6eaad528, 0x6efad738, 0x2e35d693,
- 0x6e31d60f, 0x6e72d630, 0x2e24dc62, 0x6e23dc41,
+ 0x2e211c1f, 0x6e371ed5, 0x0e2a8528, 0x4e21841f,
+ 0x0e758693, 0x4e6c856a, 0x0ebe87bc, 0x4ea48462,
+ 0x4efb8759, 0x0e27d4c5, 0x4e25d483, 0x4e6ad528,
+ 0x2e3886f6, 0x6e358693, 0x2e6f85cd, 0x6e6784c5,
+ 0x2ebf87dd, 0x6eba8738, 0x6ef786d5, 0x0ebcd77a,
+ 0x4ebad738, 0x4ee5d483, 0x0e3a9f38, 0x4e3c9f7a,
+ 0x0e799f17, 0x4e719e0f, 0x0eb79ed5, 0x4ea59c83,
+ 0x2ebad738, 0x6eaad528, 0x6efbd759, 0x2e36d6b4,
+ 0x6e32d630, 0x6e73d651, 0x2e24dc62, 0x6e23dc41,
0x6e62dc20, 0x0e7a9738, 0x4e6694a4, 0x0ea59483,
- 0x4ead958b, 0x0e20cffe, 0x4e3dcf9b, 0x4e6bcd49,
- 0x2e7b9759, 0x6e649462, 0x2eae95ac, 0x6eb39651,
- 0x0ea0cffe, 0x4ea3cc41, 0x4eeecdac, 0x2e3effbc,
- 0x6e22fc20, 0x6e73fe51, 0x0e2e65ac, 0x4e336651,
- 0x0e7766d5, 0x4e6e65ac, 0x0ebd679b, 0x4ebf67dd,
- 0x0e20a7fe, 0x4e23a441, 0x0e7ba759, 0x4e7da79b,
- 0x0ea6a4a4, 0x4ebfa7dd, 0x0e25f483, 0x4e28f4e6,
- 0x4e7ff7dd, 0x0e3b6f59, 0x4e336e51, 0x0e6a6d28,
- 0x4e696d07, 0x0eae6dac, 0x4ea26c20, 0x0e35ae93,
- 0x4e23ac41, 0x0e79af17, 0x4e64ac62, 0x0ea2ac20,
- 0x4eaaad28, 0x0eb9f717, 0x4ebbf759, 0x4ef1f60f,
- 0x2ebfefdd, 0x6ea5ec83, 0x6eeced6a, 0x0e3836f6,
- 0x4e2c356a, 0x0e6634a4, 0x4e733651, 0x0ea33441,
- 0x4ead358b, 0x4ee93507, 0x0e2c3d6a, 0x4e313e0f,
- 0x0e723e30, 0x4e643c62, 0x0eab3d49, 0x4ead3d8b,
- 0x4eee3dac, 0x2e308dee, 0x6e2f8dcd, 0x2e648c62,
- 0x6e688ce6, 0x2eb58e93, 0x6ebb8f59, 0x6ef18e0f,
- 0x2e2634a4, 0x6e243462, 0x2e6634a4, 0x6e6d358b,
- 0x2eb33651, 0x6eb636b4, 0x6ef23630, 0x2e333e51,
- 0x6e2c3d6a, 0x2e763eb4, 0x6e783ef6, 0x2eae3dac,
- 0x6ebb3f59, 0x6ef93f17, 0x0e3ee7bc, 0x4e30e5ee,
- 0x4e6ce56a, 0x2ebae738, 0x6ea3e441, 0x6eede58b,
- 0x2e20e7fe, 0x6e2ce56a, 0x6e71e60f, 0x65922c43,
- 0x65d02219, 0x65d02560, 0x65d13dc4, 0x65913690,
- 0x65d33b6b, 0x2500948c, 0x254c08bf, 0x25831f87,
- 0x254f30af, 0x259c3359, 0x25019d35, 0x24eac76d,
- 0x2431993a, 0x242f7ed8, 0x24a2f62b, 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, 0x4e21c862, 0x4e61b8a4,
- 0x05a08020, 0x05104fe0, 0x05505001, 0x05906fe2,
- 0x05d03005, 0x05101fea, 0x05901feb, 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,
- 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, 0x05271e11, 0x6545e891,
- 0x6585e891, 0x65c5e891, 0x6545c891, 0x6585c891,
- 0x65c5c891, 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, 0xf82f8186,
- 0xf83001ab, 0xf83713c1, 0xf8332225, 0xf82232d0,
- 0xf82d52aa, 0xf83d419b, 0xf83b7023, 0xf83f6278,
- 0xf8b18389, 0xf8bb00ef, 0xf8b513f7, 0xf8b923e2,
- 0xf8bb3150, 0xf8b75073, 0xf8b04320, 0xf8ba7057,
- 0xf8b0608c, 0xf8fc83be, 0xf8f000db, 0xf8e911fd,
- 0xf8e720e4, 0xf8ef32e9, 0xf8e85382, 0xf8f540bf,
- 0xf8fb7220, 0xf8ef6344, 0xf86882dc, 0xf87b033b,
- 0xf8771080, 0xf8662010, 0xf864302f, 0xf86a50a7,
- 0xf86a40fc, 0xf87472b7, 0xf866610b, 0xb83180df,
- 0xb8310182, 0xb83e107d, 0xb83b23b6, 0xb82e338d,
- 0xb83150b8, 0xb822414e, 0xb830736b, 0xb837608c,
- 0xb8b68091, 0xb8a10213, 0xb8b011cd, 0xb8ac2222,
- 0xb8a332f5, 0xb8a550e6, 0xb8b3438d, 0xb8b170d0,
- 0xb8a2607d, 0xb8e481e6, 0xb8f4018d, 0xb8f41328,
- 0xb8f42013, 0xb8eb30d8, 0xb8f451df, 0xb8f04006,
- 0xb8e7726f, 0xb8fa6149, 0xb87782d5, 0xb87c0062,
- 0xb86f1293, 0xb86723a4, 0xb8673120, 0xb87052f4,
- 0xb8644150, 0xb877732b, 0xb866621f, 0xce2b06cd,
- 0xce14410d, 0xce648df9, 0xce883624, 0xce7c809d,
- 0xce7a87b0, 0xcec081c9, 0xce7c8962, 0x2520c143,
- 0x25a1d2da, 0x058015ce, 0x05400ed8, 0x0500bb31,
- 0x25a0c074, 0x25a1d884, 0x05804944, 0x0540b1d9,
- 0x05001548, 0x25a0c49e, 0x2521cabe, 0x058054b3,
- 0x0543ab47, 0x050026bb, 0x2560d097, 0x25a1d6fe,
- 0x058394b4, 0x0540266d, 0x05003cbc, 0x25a0c1ab,
- 0x2561d3f8, 0x05800acd, 0x05403684, 0x05000c07,
- 0x2560de64, 0x2521cac5, 0x0583c8b5, 0x05405089,
- 0x05003e98, 0x04ad0397, 0x04ac074a, 0x658e023e,
- 0x65d50a1d, 0x65820667, 0x0496b13a, 0x04001411,
- 0x041a19c2, 0x049095cb, 0x041b0c7d, 0x04d9a876,
- 0x049aa27b, 0x04591aa7, 0x04138b25, 0x04119235,
- 0x04500a63, 0x0497adc7, 0x04dea9b1, 0x04581e31,
- 0x05a78f4f, 0x056494fb, 0x04481f65, 0x048a0f00,
- 0x04810074, 0x04dca739, 0x65809031, 0x658d9dae,
- 0x65c683d1, 0x658797b6, 0x65828008, 0x04ddb417,
- 0x6582baf9, 0x6580b435, 0x65c1b56a, 0x65cdb917,
- 0x65c19671, 0x65fe95a4, 0x65f11f3e, 0x65fc298e,
- 0x65ada1a5, 0x65b3c967, 0x65e3ec59, 0x65f454a0,
- 0x65a86dbc, 0x041b41dd, 0x04587903, 0x042a3321,
- 0x04b93281, 0x0470327c, 0x04e131bb, 0x0521692b,
- 0x057a6f61, 0x65c887a2, 0x45c2b058, 0x455cb723,
- 0x043639a3, 0x045a309b, 0x0498305a, 0x04993ce1,
- 0x04483e1e, 0x040a3395, 0x65c72595, 0x6586294b,
- 0x65d826c0, 0x04412474,
+ 0x4eae95ac, 0x0e21cc1f, 0x4e3ecfbc, 0x4e6ccd6a,
+ 0x2e7c977a, 0x6e649462, 0x2eae95ac, 0x6eb49672,
+ 0x0ea1cc1f, 0x4ea3cc41, 0x4eefcdcd, 0x2e3fffdd,
+ 0x6e22fc20, 0x6e75fe93, 0x0e2e65ac, 0x4e336651,
+ 0x0e7866f6, 0x4e6f65cd, 0x0ebe67bc, 0x4ea067fe,
+ 0x0e21a41f, 0x4e23a441, 0x0e7ca77a, 0x4e7ea7bc,
+ 0x0ea6a4a4, 0x4ea0a7fe, 0x0e26f4a4, 0x4e28f4e6,
+ 0x4e60f7fe, 0x0e3c6f7a, 0x4e346e72, 0x0e6b6d49,
+ 0x4e6a6d28, 0x0eae6dac, 0x4ea26c20, 0x0e36aeb4,
+ 0x4e23ac41, 0x0e7aaf38, 0x4e64ac62, 0x0ea2ac20,
+ 0x4eabad49, 0x0ebaf738, 0x4ebcf77a, 0x4ef2f630,
+ 0x2ea0effe, 0x6ea5ec83, 0x6eeced6a, 0x0fa710c5,
+ 0x4f8b8149, 0x4fc710c5, 0x0f8750c5, 0x4faa8128,
+ 0x4fc750c5, 0x2f8890e6, 0x4fa880e6, 0x6fc59083,
+ 0x0f6f81cd, 0x4f448862, 0x0f848062, 0x4fab8149,
+ 0x0e3736d5, 0x4e323630, 0x0e743672, 0x4e6d358b,
+ 0x0eb736d5, 0x4eb93717, 0x4eee35ac, 0x0e3c3f7a,
+ 0x4e393f17, 0x0e7e3fbc, 0x4e703dee, 0x0ead3d8b,
+ 0x4eba3f38, 0x4ee33c41, 0x2e2e8dac, 0x6e218c1f,
+ 0x2e6c8d6a, 0x6e728e30, 0x2ea98d07, 0x6ea48c62,
+ 0x6ee58c83, 0x2e2f35cd, 0x6e353693, 0x2e733651,
+ 0x6e723630, 0x2ea53483, 0x6ea33441, 0x6eed358b,
+ 0x2e203ffe, 0x6e273cc5, 0x2e6a3d28, 0x6e713e0f,
+ 0x2ebf3fdd, 0x6ea03ffe, 0x6ee23c20, 0x0e36e6b4,
+ 0x4e29e507, 0x4e76e6b4, 0x2eb9e717, 0x6ebee7bc,
+ 0x6ef7e6d5, 0x2e3de79b, 0x6e3be759, 0x6e67e4c5,
+ 0x65d23ee0, 0x65903d92, 0x65d03fa7, 0x65912fe9,
+ 0x65d13bf9, 0x65932a0a, 0x25cb90c4, 0x25040bde,
+ 0x25c11085, 0x25c62c6b, 0x259f2279, 0x259d8993,
+ 0x24e5102b, 0x24ad5458, 0x24ec7ab5, 0x24387c6d,
+ 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, 0x4e21c862,
+ 0x4e61b8a4, 0x05a08020, 0x05104fe0, 0x05505001,
+ 0x05906fe2, 0x05d03005, 0x05101fea, 0x05901feb,
+ 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, 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, 0x05271e11,
+ 0x6545e891, 0x6585e891, 0x65c5e891, 0x6545c891,
+ 0x6585c891, 0x65c5c891, 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,
+ 0xf8338131, 0xf83c01fb, 0xf82712f5, 0xf83f2059,
+ 0xf83f31fb, 0xf82a5277, 0xf8234010, 0xf83972fa,
+ 0xf8226190, 0xf8a483dc, 0xf8bd0370, 0xf8a613a9,
+ 0xf8b02087, 0xf8a7312f, 0xf8b75048, 0xf8bc43f5,
+ 0xf8a5701b, 0xf8b1608f, 0xf8fa8388, 0xf8f6037b,
+ 0xf8f91017, 0xf8e421e6, 0xf8e031e4, 0xf8e150ea,
+ 0xf8e5438a, 0xf8e772f4, 0xf8f56166, 0xf86883f1,
+ 0xf8660051, 0xf86c13be, 0xf86322db, 0xf87d31ae,
+ 0xf87c5311, 0xf86541c2, 0xf86a7170, 0xf87b6197,
+ 0xb8248236, 0xb8240261, 0xb83011b0, 0xb82e204c,
+ 0xb83132a3, 0xb83750c5, 0xb82741b3, 0xb83c7211,
+ 0xb82663a2, 0xb8a380c4, 0xb8b001b4, 0xb8ac1114,
+ 0xb8b92274, 0xb8a0330b, 0xb8a653f4, 0xb8ae40d0,
+ 0xb8a071e7, 0xb8b3613a, 0xb8ea82b7, 0xb8f6005c,
+ 0xb8e3126f, 0xb8f42087, 0xb8fd3007, 0xb8e95290,
+ 0xb8f74204, 0xb8ea7177, 0xb8f963e6, 0xb87082ed,
+ 0xb86c01c1, 0xb8691215, 0xb87a208f, 0xb8643110,
+ 0xb866509e, 0xb87d43b1, 0xb87a71e9, 0xb86263ab,
+ 0xce216ce3, 0xce0e2255, 0xce798ed2, 0xce959685,
+ 0xce7e8217, 0xce608694, 0xcec08264, 0xce748898,
+ 0x25e0da44, 0x2521c8f3, 0x05801548, 0x0540cbdf,
+ 0x05006521, 0x2560c7a0, 0x25a1c498, 0x058026bb,
+ 0x05407dd8, 0x0500f3d6, 0x2560ce3d, 0x2521d4b4,
+ 0x05803cbc, 0x05404d6c, 0x05001b89, 0x25a0c532,
+ 0x2521cc40, 0x05800c08, 0x054074c4, 0x050034a0,
+ 0x2520c9e3, 0x25e1ca93, 0x05803e98, 0x05425238,
+ 0x050024cb, 0x25a0ce7f, 0x25e1d0c3, 0x05802676,
+ 0x05401e63, 0x05002d49, 0x04e20080, 0x04ab04ce,
+ 0x659e022e, 0x65970863, 0x659c0703, 0x04d6b4f3,
+ 0x04400cb5, 0x049a06da, 0x04508071, 0x045b0d14,
+ 0x0459b22e, 0x04daba4d, 0x04590a13, 0x0493979b,
+ 0x04d188a8, 0x0450081c, 0x0417b6b9, 0x041eb743,
+ 0x04981e7a, 0x05e78dc1, 0x0564824e, 0x048816ff,
+ 0x040a0d1e, 0x04810ee0, 0x04dcb340, 0x65c08ed8,
+ 0x65cd8162, 0x65c6970c, 0x65c79e29, 0x65c29494,
+ 0x04ddbecd, 0x65c2ba5f, 0x65c0a9af, 0x6581a434,
+ 0x658da0ee, 0x65c1908c, 0x65be806f, 0x65ff0694,
+ 0x65ee2d2d, 0x65a3af81, 0x65a9cb3a, 0x65e1e9da,
+ 0x65f447ba, 0x65e17da6, 0x0401482b, 0x040279fb,
+ 0x0439323e, 0x04a33302, 0x046331bd, 0x04fc320e,
+ 0x05bb6964, 0x05e16e02, 0x65c897e7, 0x4596b150,
+ 0x4516b4fd, 0x0438396c, 0x041a280b, 0x04183697,
+ 0x04192de3, 0x04083b7e, 0x04ca3955, 0x65873883,
+ 0x658622a6, 0x65d83bd9, 0x0441303f, 0x0e2e11ac,
+ 0x4e2013fe, 0x0e6f11cd, 0x4e6a1128, 0x0ebb1359,
+ 0x4ebf13dd, 0x2e231041, 0x6e21101f, 0x2e791317,
+ 0x6e61101f, 0x2eb612b4, 0x6ea21020,
};
// END Generated code -- do not edit
diff --git a/test/hotspot/gtest/gc/shared/test_preservedMarks.cpp b/test/hotspot/gtest/gc/shared/test_preservedMarks.cpp
index af3263d8e87..0b438572b2d 100644
--- a/test/hotspot/gtest/gc/shared/test_preservedMarks.cpp
+++ b/test/hotspot/gtest/gc/shared/test_preservedMarks.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,59 +23,48 @@
#include "precompiled.hpp"
#include "gc/shared/preservedMarks.inline.hpp"
+#include "gc/shared/fullGCForwarding.inline.hpp"
#include "oops/oop.inline.hpp"
#include "unittest.hpp"
-// Class to create a "fake" oop with a mark that will
-// return true for calls to must_be_preserved().
-class FakeOop {
- oopDesc _oop;
-
-public:
- FakeOop() : _oop() { _oop.set_mark(originalMark()); }
-
- oop get_oop() { return &_oop; }
- markWord mark() { return _oop.mark(); }
- void set_mark(markWord m) { _oop.set_mark(m); }
- void forward_to(oop obj) {
- markWord m = markWord::encode_pointer_as_mark(obj);
- _oop.set_mark(m);
- }
-
- static markWord originalMark() { return markWord(markWord::lock_mask_in_place); }
- static markWord changedMark() { return markWord((uintptr_t)0x4711 << markWord::hash_shift); }
-};
+static markWord originalMark() { return markWord(markWord::lock_mask_in_place); }
+static markWord changedMark() { return markWord(0x4711); }
#define ASSERT_MARK_WORD_EQ(a, b) ASSERT_EQ((a).value(), (b).value())
TEST_VM(PreservedMarks, iterate_and_restore) {
PreservedMarks pm;
- FakeOop o1;
- FakeOop o2;
- FakeOop o3;
- FakeOop o4;
+
+ HeapWord fakeheap[32] = { nullptr };
+ HeapWord* heap = align_up(fakeheap, 8 * sizeof(HeapWord));
+ FullGCForwarding::initialize(MemRegion(&heap[0], &heap[16]));
+
+ oop o1 = cast_to_oop(&heap[0]); o1->set_mark(originalMark());
+ oop o2 = cast_to_oop(&heap[2]); o2->set_mark(originalMark());
+ oop o3 = cast_to_oop(&heap[4]); o3->set_mark(originalMark());
+ oop o4 = cast_to_oop(&heap[6]); o4->set_mark(originalMark());
// Make sure initial marks are correct.
- ASSERT_MARK_WORD_EQ(o1.mark(), FakeOop::originalMark());
- ASSERT_MARK_WORD_EQ(o2.mark(), FakeOop::originalMark());
- ASSERT_MARK_WORD_EQ(o3.mark(), FakeOop::originalMark());
- ASSERT_MARK_WORD_EQ(o4.mark(), FakeOop::originalMark());
+ ASSERT_MARK_WORD_EQ(o1->mark(), originalMark());
+ ASSERT_MARK_WORD_EQ(o2->mark(), originalMark());
+ ASSERT_MARK_WORD_EQ(o3->mark(), originalMark());
+ ASSERT_MARK_WORD_EQ(o4->mark(), originalMark());
// Change the marks and verify change.
- o1.set_mark(FakeOop::changedMark());
- o2.set_mark(FakeOop::changedMark());
- ASSERT_MARK_WORD_EQ(o1.mark(), FakeOop::changedMark());
- ASSERT_MARK_WORD_EQ(o2.mark(), FakeOop::changedMark());
+ o1->set_mark(changedMark());
+ o2->set_mark(changedMark());
+ ASSERT_MARK_WORD_EQ(o1->mark(), changedMark());
+ ASSERT_MARK_WORD_EQ(o2->mark(), changedMark());
// Push o1 and o2 to have their marks preserved.
- pm.push_if_necessary(o1.get_oop(), o1.mark());
- pm.push_if_necessary(o2.get_oop(), o2.mark());
+ pm.push_if_necessary(o1, o1->mark());
+ pm.push_if_necessary(o2, o2->mark());
// Fake a move from o1->o3 and o2->o4.
- o1.forward_to(o3.get_oop());
- o2.forward_to(o4.get_oop());
- ASSERT_EQ(o1.get_oop()->forwardee(), o3.get_oop());
- ASSERT_EQ(o2.get_oop()->forwardee(), o4.get_oop());
+ FullGCForwarding::forward_to(o1, o3);
+ FullGCForwarding::forward_to(o2, o4);
+ ASSERT_EQ(FullGCForwarding::forwardee(o1), o3);
+ ASSERT_EQ(FullGCForwarding::forwardee(o2), o4);
// Adjust will update the PreservedMarks stack to
// make sure the mark is updated at the new location.
pm.adjust_during_full_gc();
@@ -83,6 +72,6 @@ TEST_VM(PreservedMarks, iterate_and_restore) {
// Restore all preserved and verify that the changed
// mark is now present at o3 and o4.
pm.restore();
- ASSERT_MARK_WORD_EQ(o3.mark(), FakeOop::changedMark());
- ASSERT_MARK_WORD_EQ(o4.mark(), FakeOop::changedMark());
+ ASSERT_MARK_WORD_EQ(o3->mark(), changedMark());
+ ASSERT_MARK_WORD_EQ(o4->mark(), changedMark());
}
diff --git a/test/hotspot/gtest/metaspace/metaspaceGtestContexts.hpp b/test/hotspot/gtest/metaspace/metaspaceGtestContexts.hpp
index f1a3ac0141a..8a5aabf6cec 100644
--- a/test/hotspot/gtest/metaspace/metaspaceGtestContexts.hpp
+++ b/test/hotspot/gtest/metaspace/metaspaceGtestContexts.hpp
@@ -37,10 +37,14 @@ using metaspace::chunklevel_t;
using namespace metaspace::chunklevel;
class MetaspaceGtestContext : public metaspace::MetaspaceTestContext {
+ int _num_arenas_created;
public:
MetaspaceGtestContext(size_t commit_limit = 0, size_t reserve_limit = 0) :
- metaspace::MetaspaceTestContext("gtest-metaspace-context", commit_limit, reserve_limit)
- {}
+ metaspace::MetaspaceTestContext("gtest-metaspace-context", commit_limit, reserve_limit),
+ _num_arenas_created(0) {}
+
+ int num_arenas_created() const { return _num_arenas_created; }
+ void inc_num_arenas_created() { _num_arenas_created ++; }
};
class ChunkGtestContext : public MetaspaceGtestContext {
diff --git a/test/hotspot/gtest/metaspace/test_binlist.cpp b/test/hotspot/gtest/metaspace/test_binlist.cpp
index dd26d858e24..df12b40c30f 100644
--- a/test/hotspot/gtest/metaspace/test_binlist.cpp
+++ b/test/hotspot/gtest/metaspace/test_binlist.cpp
@@ -26,12 +26,14 @@
#include "precompiled.hpp"
#include "memory/metaspace/binList.hpp"
#include "memory/metaspace/counters.hpp"
+#include "memory/metaspace/metablock.hpp"
//#define LOG_PLEASE
#include "metaspaceGtestCommon.hpp"
using metaspace::BinList32;
using metaspace::BinListImpl;
using metaspace::MemRangeCounter;
+using metaspace::MetaBlock;
#define CHECK_BL_CONTENT(bl, expected_num, expected_size) { \
EXPECT_EQ(bl.count(), (unsigned)expected_num); \
@@ -43,6 +45,19 @@ using metaspace::MemRangeCounter;
} \
}
+template
+struct TestedBinList : public BinListImpl {
+ typedef BinListImpl ListType;
+ void add_block(MetaWord* p, size_t word_size) {
+ ListType::add_block(MetaBlock(p, word_size));
+ }
+ MetaWord* remove_block(size_t requested_size, size_t* real_size) {
+ MetaBlock result = ListType::remove_block(requested_size);
+ (*real_size) = result.word_size();
+ return result.base();
+ }
+};
+
template
struct BinListBasicTest {
@@ -206,14 +221,14 @@ struct BinListBasicTest {
template const size_t BinListBasicTest::maxws = BINLISTTYPE::MaxWordSize;
-TEST_VM(metaspace, BinList_basic_1) { BinListBasicTest< BinListImpl<1> >::basic_test(); }
-TEST_VM(metaspace, BinList_basic_8) { BinListBasicTest< BinListImpl<8> >::basic_test(); }
-TEST_VM(metaspace, BinList_basic_32) { BinListBasicTest::basic_test(); }
+TEST_VM(metaspace, BinList_basic_1) { BinListBasicTest< TestedBinList<1> >::basic_test(); }
+TEST_VM(metaspace, BinList_basic_8) { BinListBasicTest< TestedBinList<8> >::basic_test(); }
+TEST_VM(metaspace, BinList_basic_32) { BinListBasicTest< TestedBinList<32> >::basic_test(); }
-TEST_VM(metaspace, BinList_basic_2_1) { BinListBasicTest< BinListImpl<1> >::basic_test_2(); }
-TEST_VM(metaspace, BinList_basic_2_8) { BinListBasicTest< BinListImpl<8> >::basic_test_2(); }
-TEST_VM(metaspace, BinList_basic_2_32) { BinListBasicTest::basic_test_2(); }
+TEST_VM(metaspace, BinList_basic_2_1) { BinListBasicTest< TestedBinList<1> >::basic_test_2(); }
+TEST_VM(metaspace, BinList_basic_2_8) { BinListBasicTest< TestedBinList<8> >::basic_test_2(); }
+TEST_VM(metaspace, BinList_basic_2_32) { BinListBasicTest< TestedBinList<32> >::basic_test_2(); }
-TEST_VM(metaspace, BinList_basic_rand_1) { BinListBasicTest< BinListImpl<1> >::random_test(); }
-TEST_VM(metaspace, BinList_basic_rand_8) { BinListBasicTest< BinListImpl<8> >::random_test(); }
-TEST_VM(metaspace, BinList_basic_rand_32) { BinListBasicTest::random_test(); }
+TEST_VM(metaspace, BinList_basic_rand_1) { BinListBasicTest< TestedBinList<1> >::random_test(); }
+TEST_VM(metaspace, BinList_basic_rand_8) { BinListBasicTest< TestedBinList<8> >::random_test(); }
+TEST_VM(metaspace, BinList_basic_rand_32) { BinListBasicTest< TestedBinList<32> >::random_test(); }
diff --git a/test/hotspot/gtest/metaspace/test_blocktree.cpp b/test/hotspot/gtest/metaspace/test_blocktree.cpp
index 50ec021ec11..05a3025f529 100644
--- a/test/hotspot/gtest/metaspace/test_blocktree.cpp
+++ b/test/hotspot/gtest/metaspace/test_blocktree.cpp
@@ -26,16 +26,29 @@
#include "precompiled.hpp"
#include "memory/metaspace/blockTree.hpp"
#include "memory/metaspace/counters.hpp"
+#include "memory/metaspace/metablock.hpp"
#include "memory/resourceArea.hpp"
// #define LOG_PLEASE
#include "metaspaceGtestCommon.hpp"
using metaspace::BlockTree;
using metaspace::MemRangeCounter;
+using metaspace::MetaBlock;
+
+struct TestedBlockTree : public BlockTree {
+ void add_block(MetaWord* p, size_t word_size) {
+ BlockTree::add_block(MetaBlock(p, word_size));
+ }
+ MetaWord* remove_block(size_t requested_size, size_t* real_size) {
+ MetaBlock result = BlockTree::remove_block(requested_size);
+ (*real_size) = result.word_size();
+ return result.base();
+ }
+};
// Small helper. Given a 0-terminated array of sizes, a feeder buffer and a tree,
// add blocks of these sizes to the tree in the order they appear in the array.
-static void create_nodes(const size_t sizes[], FeederBuffer& fb, BlockTree& bt) {
+static void create_nodes(const size_t sizes[], FeederBuffer& fb, TestedBlockTree& bt) {
for (int i = 0; sizes[i] > 0; i ++) {
size_t s = sizes[i];
MetaWord* p = fb.get(s);
@@ -55,7 +68,7 @@ static void create_nodes(const size_t sizes[], FeederBuffer& fb, BlockTree& bt)
TEST_VM(metaspace, BlockTree_basic) {
- BlockTree bt;
+ TestedBlockTree bt;
CHECK_BT_CONTENT(bt, 0, 0);
size_t real_size = 0;
@@ -112,7 +125,7 @@ static size_t helper_find_nearest_fit(const size_t sizes[], size_t request_size)
// for a request size and check that it is the expected result.
static void test_find_nearest_fit_with_tree(const size_t sizes[], size_t request_size) {
- BlockTree bt;
+ TestedBlockTree bt;
FeederBuffer fb(4 * K);
create_nodes(sizes, fb, bt);
@@ -155,7 +168,7 @@ TEST_VM(metaspace, BlockTree_find_nearest_fit) {
0 // stop
};
- BlockTree bt;
+ TestedBlockTree bt;
FeederBuffer fb(4 * K);
create_nodes(sizes, fb, bt);
@@ -170,7 +183,7 @@ TEST_VM(metaspace, BlockTree_find_nearest_fit) {
// should exercise the list-part of the tree.
TEST_VM(metaspace, BlockTree_basic_siblings)
{
- BlockTree bt;
+ TestedBlockTree bt;
FeederBuffer fb(4 * K);
CHECK_BT_CONTENT(bt, 0, 0);
@@ -204,7 +217,7 @@ TEST_VM(metaspace, BlockTree_print_test) {
0 // stop
};
- BlockTree bt;
+ TestedBlockTree bt;
FeederBuffer fb(4 * K);
create_nodes(sizes, fb, bt);
@@ -222,7 +235,7 @@ TEST_VM_ASSERT_MSG(metaspace, BlockTree_overwriter_test, ".*failed: Invalid node
static const size_t sizes1[] = { 30, 17, 0 };
static const size_t sizes2[] = { 12, 12, 0 };
- BlockTree bt;
+ TestedBlockTree bt;
FeederBuffer fb(4 * K);
// some nodes...
@@ -249,7 +262,7 @@ class BlockTreeTest {
FeederBuffer _fb;
- BlockTree _bt[2];
+ TestedBlockTree _bt[2];
MemRangeCounter _cnt[2];
RandSizeGenerator _rgen;
@@ -356,7 +369,7 @@ class BlockTreeTest {
void drain_all() {
for (int which = 0; which < 2; which++) {
- BlockTree* bt = _bt + which;
+ TestedBlockTree* bt = _bt + which;
size_t last_size = 0;
while (!bt->is_empty()) {
diff --git a/test/hotspot/gtest/metaspace/test_clms.cpp b/test/hotspot/gtest/metaspace/test_clms.cpp
new file mode 100644
index 00000000000..efe83c415e0
--- /dev/null
+++ b/test/hotspot/gtest/metaspace/test_clms.cpp
@@ -0,0 +1,409 @@
+/*
+ * Copyright (c) 2024 Red Hat, Inc. All rights reserved.
+ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "memory/classLoaderMetaspace.hpp"
+#include "memory/metaspace/freeBlocks.hpp"
+#include "memory/metaspace/metablock.inline.hpp"
+#include "memory/metaspace/metaspaceArena.hpp"
+#include "memory/metaspace/metaspaceSettings.hpp"
+#include "memory/metaspace/metaspaceStatistics.hpp"
+#include "memory/metaspace.hpp"
+#include "oops/klass.hpp"
+#include "runtime/mutex.hpp"
+#include "utilities/debug.hpp"
+#include "utilities/align.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+#ifdef _LP64
+
+#define LOG_PLEASE
+#include "metaspaceGtestCommon.hpp"
+#include "metaspaceGtestContexts.hpp"
+#include "metaspaceGtestRangeHelpers.hpp"
+#include "metaspaceGtestSparseArray.hpp"
+
+#define HANDLE_FAILURE \
+ if (testing::Test::HasFailure()) { \
+ return; \
+ }
+
+namespace metaspace {
+
+class ClmsTester {
+
+ Mutex _lock;
+ MetaspaceContext* _class_context;
+ MetaspaceContext* _nonclass_context;
+ ClassLoaderMetaspace* _clms;
+ const size_t _klass_arena_alignment_words;
+ unsigned _num_allocations;
+
+ struct Deltas {
+ int num_chunks_delta;
+ ssize_t used_words_delta;
+ int num_freeblocks_delta;
+ ssize_t freeblocks_words_delta;
+ };
+
+ Deltas calc_deltas(const ArenaStats& before, const ArenaStats& after) {
+ Deltas d;
+ d.num_chunks_delta = after.totals()._num - before.totals()._num;
+ d.used_words_delta = after.totals()._used_words - before.totals()._used_words;
+ d.num_freeblocks_delta = (int)after._free_blocks_num - (int)before._free_blocks_num;
+ d.freeblocks_words_delta = after._free_blocks_word_size - before._free_blocks_word_size;
+ return d;
+ }
+
+public:
+
+ ClmsTester(size_t klass_alignment_words, Metaspace::MetaspaceType space_type,
+ MetaspaceContext* class_context, MetaspaceContext* nonclass_context)
+ : _lock(Monitor::nosafepoint, "CLMSTest_lock"),
+ _class_context(class_context), _nonclass_context(nonclass_context),
+ _clms(nullptr), _klass_arena_alignment_words(klass_alignment_words), _num_allocations(0) {
+ _clms = new ClassLoaderMetaspace(&_lock, space_type, nonclass_context, class_context, klass_alignment_words);
+ }
+
+ ~ClmsTester() {
+ delete _clms;
+ EXPECT_EQ(_class_context->used_words(), (size_t)0);
+ EXPECT_EQ(_nonclass_context->used_words(), (size_t)0);
+ }
+
+ MetaBlock allocate_and_check(size_t word_size, bool is_class) {
+
+ // take stats before allocation
+ ClmsStats stats_before;
+ _clms->add_to_statistics(&stats_before);
+
+ // allocate
+ MetaWord* p = _clms->allocate(word_size, is_class ? Metaspace::ClassType : Metaspace::NonClassType);
+ _num_allocations ++;
+
+ // take stats after allocation
+ ClmsStats stats_after;
+ _clms->add_to_statistics(&stats_after);
+
+ // for less verbose testing:
+ const ArenaStats& ca_before = stats_before._arena_stats_class;
+ const ArenaStats& ca_after = stats_after._arena_stats_class;
+ const ArenaStats& nca_before = stats_before._arena_stats_nonclass;
+ const ArenaStats& nca_after = stats_after._arena_stats_nonclass;
+
+ // deltas
+ const Deltas d_ca = calc_deltas(ca_before, ca_after);
+ const Deltas d_nca = calc_deltas(nca_before, nca_after);
+
+#define EXPECT_FREEBLOCKS_UNCHANGED(arena_prefix) \
+ EXPECT_EQ(d_##arena_prefix.num_freeblocks_delta, 0); \
+ EXPECT_EQ(d_##arena_prefix.freeblocks_words_delta, (ssize_t)0);
+
+#define EXPECT_ARENA_UNCHANGED(arena_prefix) \
+ EXPECT_EQ(d_##arena_prefix.num_chunks_delta, 0); \
+ EXPECT_EQ(d_##arena_prefix.used_words_delta, (ssize_t)0);
+
+ if (p != nullptr) {
+
+ MetaBlock bl(p, word_size);
+
+ if (is_class) {
+
+ EXPECT_TRUE(bl.is_aligned_base(_klass_arena_alignment_words));
+
+ if (_num_allocations == 1) {
+ // first allocation: nonclass arena unchanged, class arena grows by 1 chunk and wordsize,
+ // class arena freeblocks unchanged
+ EXPECT_ARENA_UNCHANGED(nca);
+ EXPECT_FREEBLOCKS_UNCHANGED(nca);
+ EXPECT_EQ(d_ca.num_chunks_delta, 1);
+ EXPECT_EQ((size_t)d_ca.used_words_delta, word_size);
+ EXPECT_FREEBLOCKS_UNCHANGED(ca);
+ return bl;
+ }
+
+ // Had this been taken from class arena freeblocks?
+ if (d_ca.num_freeblocks_delta == -1) {
+ // the class arena freeblocks should have gone down, and the non-class arena freeblocks may have gone
+ // up in case the block was larger than required
+ const size_t wordsize_block_taken = (size_t)(-d_ca.freeblocks_words_delta);
+ EXPECT_GE(wordsize_block_taken, word_size); // the block we took must be at least allocation size
+ const size_t expected_freeblock_remainder = wordsize_block_taken - word_size;
+ if (expected_freeblock_remainder > 0) {
+ // the remainder, if it existed, should have been added to nonclass freeblocks
+ EXPECT_EQ(d_nca.num_freeblocks_delta, 1);
+ EXPECT_EQ((size_t)d_nca.freeblocks_words_delta, expected_freeblock_remainder);
+ }
+ // finally, nothing should have happened in the arenas proper.
+ EXPECT_ARENA_UNCHANGED(ca);
+ EXPECT_ARENA_UNCHANGED(nca);
+ return bl;
+ }
+
+ // block was taken from class arena proper
+
+ // We expect allocation waste due to alignment, should have been added to the freeblocks
+ // of nonclass arena. Allocation waste can be 0. If no chunk turnover happened, it must be
+ // smaller than klass alignment, otherwise it can get as large as a commit granule.
+ const size_t max_expected_allocation_waste =
+ d_ca.num_chunks_delta == 0 ? (_klass_arena_alignment_words - 1) : Settings::commit_granule_words();
+ EXPECT_GE(d_ca.num_chunks_delta, 0);
+ EXPECT_LE(d_ca.num_chunks_delta, 1);
+ EXPECT_GE((size_t)d_ca.used_words_delta, word_size);
+ EXPECT_LE((size_t)d_ca.used_words_delta, word_size + max_expected_allocation_waste);
+ EXPECT_FREEBLOCKS_UNCHANGED(ca);
+ EXPECT_ARENA_UNCHANGED(nca);
+ if (max_expected_allocation_waste > 0) {
+ EXPECT_GE(d_nca.num_freeblocks_delta, 0);
+ EXPECT_LE(d_nca.num_freeblocks_delta, 1);
+ EXPECT_GE(d_nca.freeblocks_words_delta, 0);
+ EXPECT_LE((size_t)d_nca.freeblocks_words_delta, max_expected_allocation_waste);
+ } else {
+ EXPECT_FREEBLOCKS_UNCHANGED(nca);
+ }
+ return bl;
+ // end: is_class
+ } else {
+ // Nonclass arena allocation.
+ // Allocation waste can happen:
+ // - if we allocate from nonclass freeblocks, the block remainder
+ // - if we allocate from arena proper, by chunk turnover
+
+ if (d_nca.freeblocks_words_delta < 0) {
+ // We allocated a block from the nonclass arena freeblocks.
+ const size_t wordsize_block_taken = (size_t)(-d_nca.freeblocks_words_delta);
+ EXPECT_EQ(wordsize_block_taken, word_size);
+ // The number of blocks may or may not have decreased (depending on whether there
+ // was a wastage block)
+ EXPECT_GE(d_nca.num_chunks_delta, -1);
+ EXPECT_LE(d_nca.num_chunks_delta, 0);
+ EXPECT_ARENA_UNCHANGED(nca);
+ EXPECT_ARENA_UNCHANGED(ca);
+ EXPECT_FREEBLOCKS_UNCHANGED(ca);
+ return bl;
+ }
+
+ // We don't expect alignment waste. Only wastage happens at chunk turnover.
+ const size_t max_expected_allocation_waste =
+ d_nca.num_chunks_delta == 0 ? 0 : Settings::commit_granule_words();
+ EXPECT_ARENA_UNCHANGED(ca);
+ EXPECT_FREEBLOCKS_UNCHANGED(ca);
+ EXPECT_GE(d_nca.num_chunks_delta, 0);
+ EXPECT_LE(d_nca.num_chunks_delta, 1);
+ EXPECT_GE((size_t)d_nca.used_words_delta, word_size);
+ EXPECT_LE((size_t)d_nca.used_words_delta, word_size + max_expected_allocation_waste);
+ if (max_expected_allocation_waste == 0) {
+ EXPECT_FREEBLOCKS_UNCHANGED(nca);
+ }
+ }
+ return bl;
+
+ } // end: allocation successful
+
+ // allocation failed.
+ EXPECT_ARENA_UNCHANGED(ca);
+ EXPECT_FREEBLOCKS_UNCHANGED(ca);
+ EXPECT_ARENA_UNCHANGED(nca);
+ EXPECT_FREEBLOCKS_UNCHANGED(nca);
+
+ return MetaBlock();
+ }
+
+ MetaBlock allocate_expect_success(size_t word_size, bool is_class) {
+ MetaBlock bl = allocate_and_check(word_size, is_class);
+ EXPECT_TRUE(bl.is_nonempty());
+ return bl;
+ }
+
+ MetaBlock allocate_expect_failure(size_t word_size, bool is_class) {
+ MetaBlock bl = allocate_and_check(word_size, is_class);
+ EXPECT_TRUE(bl.is_empty());
+ return bl;
+ }
+
+ void deallocate_and_check(MetaBlock bl) {
+
+ // take stats before deallocation
+ ClmsStats stats_before;
+ _clms->add_to_statistics(&stats_before);
+
+ // allocate
+ _clms->deallocate(bl.base(), bl.word_size());
+
+ // take stats after deallocation
+ ClmsStats stats_after;
+ _clms->add_to_statistics(&stats_after);
+
+ // for less verbose testing:
+ const ArenaStats& ca_before = stats_before._arena_stats_class;
+ const ArenaStats& ca_after = stats_after._arena_stats_class;
+ const ArenaStats& nca_before = stats_before._arena_stats_nonclass;
+ const ArenaStats& nca_after = stats_after._arena_stats_nonclass;
+
+ // deltas
+ // deltas
+ const Deltas d_ca = calc_deltas(ca_before, ca_after);
+ const Deltas d_nca = calc_deltas(nca_before, nca_after);
+
+ EXPECT_ARENA_UNCHANGED(ca);
+ EXPECT_ARENA_UNCHANGED(nca);
+ // Depending on whether the returned block was suitable for Klass,
+ // it may have gone to either the non-class freelist or the class freelist
+ if (d_ca.num_freeblocks_delta == 1) {
+ EXPECT_EQ(d_ca.num_freeblocks_delta, 1);
+ EXPECT_EQ((size_t)d_ca.freeblocks_words_delta, bl.word_size());
+ EXPECT_FREEBLOCKS_UNCHANGED(nca);
+ } else {
+ EXPECT_EQ(d_nca.num_freeblocks_delta, 1);
+ EXPECT_EQ((size_t)d_nca.freeblocks_words_delta, bl.word_size());
+ EXPECT_FREEBLOCKS_UNCHANGED(ca);
+ }
+ }
+};
+
+static constexpr size_t klass_size = sizeof(Klass) / BytesPerWord;
+
+static void basic_test(size_t klass_arena_alignment) {
+ MetaspaceGtestContext class_context, nonclass_context;
+ {
+ ClmsTester tester(klass_arena_alignment, Metaspace::StandardMetaspaceType, class_context.context(), nonclass_context.context());
+
+ MetaBlock bl1 = tester.allocate_expect_success(klass_size, true);
+ HANDLE_FAILURE;
+
+ MetaBlock bl2 = tester.allocate_expect_success(klass_size, true);
+ HANDLE_FAILURE;
+
+ tester.deallocate_and_check(bl1);
+ HANDLE_FAILURE;
+
+ MetaBlock bl3 = tester.allocate_expect_success(klass_size, true);
+ HANDLE_FAILURE;
+
+ MetaBlock bl4 = tester.allocate_expect_success(Metaspace::min_allocation_word_size, false);
+ HANDLE_FAILURE;
+
+ MetaBlock bl5 = tester.allocate_expect_success(K, false);
+ HANDLE_FAILURE;
+
+ tester.deallocate_and_check(bl5);
+ HANDLE_FAILURE;
+
+ MetaBlock bl6 = tester.allocate_expect_success(K, false);
+ HANDLE_FAILURE;
+
+ EXPECT_EQ(bl5, bl6); // should have gotten the same block back from freelist
+ }
+ EXPECT_EQ(class_context.used_words(), (size_t)0);
+ EXPECT_EQ(nonclass_context.used_words(), (size_t)0);
+ // we should have used exactly one commit granule (64K), not more, for each context
+ EXPECT_EQ(class_context.committed_words(), Settings::commit_granule_words());
+ EXPECT_EQ(nonclass_context.committed_words(), Settings::commit_granule_words());
+}
+
+#define TEST_BASIC_N(n) \
+TEST_VM(metaspace, CLMS_basics_##n) { \
+ basic_test(n); \
+}
+
+TEST_BASIC_N(1)
+TEST_BASIC_N(4)
+TEST_BASIC_N(16)
+TEST_BASIC_N(32)
+TEST_BASIC_N(128)
+
+static void test_random(size_t klass_arena_alignment) {
+ MetaspaceGtestContext class_context, nonclass_context;
+ constexpr int max_allocations = 1024;
+ const SizeRange nonclass_alloc_range(Metaspace::min_allocation_alignment_words, 1024);
+ const SizeRange class_alloc_range(klass_size, 1024);
+ const IntRange one_out_of_ten(0, 10);
+ for (int runs = 9; runs >= 0; runs--) {
+ {
+ ClmsTester tester(64, Metaspace::StandardMetaspaceType, class_context.context(), nonclass_context.context());
+ struct LifeBlock {
+ MetaBlock bl;
+ bool is_class;
+ };
+ LifeBlock life_allocations[max_allocations];
+ for (int i = 0; i < max_allocations; i++) {
+ life_allocations[i].bl.reset();
+ }
+
+ unsigned num_class_allocs = 0, num_nonclass_allocs = 0, num_class_deallocs = 0, num_nonclass_deallocs = 0;
+ for (int i = 0; i < 5000; i ++) {
+ const int slot = IntRange(0, max_allocations).random_value();
+ if (life_allocations[slot].bl.is_empty()) {
+ const bool is_class = one_out_of_ten.random_value() == 0;
+ const size_t word_size =
+ is_class ? class_alloc_range.random_value() : nonclass_alloc_range.random_value();
+ MetaBlock bl = tester.allocate_expect_success(word_size, is_class);
+ HANDLE_FAILURE;
+ life_allocations[slot].bl = bl;
+ life_allocations[slot].is_class = is_class;
+ if (is_class) {
+ num_class_allocs ++;
+ } else {
+ num_nonclass_allocs ++;
+ }
+ } else {
+ tester.deallocate_and_check(life_allocations[slot].bl);
+ HANDLE_FAILURE;
+ life_allocations[slot].bl.reset();
+ if (life_allocations[slot].is_class) {
+ num_class_deallocs ++;
+ } else {
+ num_nonclass_deallocs ++;
+ }
+ }
+ }
+ LOG("num class allocs: %u, num nonclass allocs: %u, num class deallocs: %u, num nonclass deallocs: %u",
+ num_class_allocs, num_nonclass_allocs, num_class_deallocs, num_nonclass_deallocs);
+ }
+ EXPECT_EQ(class_context.used_words(), (size_t)0);
+ EXPECT_EQ(nonclass_context.used_words(), (size_t)0);
+ constexpr float fragmentation_factor = 3.0f;
+ const size_t max_expected_nonclass_committed = max_allocations * nonclass_alloc_range.highest() * fragmentation_factor;
+ const size_t max_expected_class_committed = max_allocations * class_alloc_range.highest() * fragmentation_factor;
+ // we should have used exactly one commit granule (64K), not more, for each context
+ EXPECT_LT(class_context.committed_words(), max_expected_class_committed);
+ EXPECT_LT(nonclass_context.committed_words(), max_expected_nonclass_committed);
+ }
+}
+
+#define TEST_RANDOM_N(n) \
+TEST_VM(metaspace, CLMS_random_##n) { \
+ test_random(n); \
+}
+
+TEST_RANDOM_N(1)
+TEST_RANDOM_N(4)
+TEST_RANDOM_N(16)
+TEST_RANDOM_N(32)
+TEST_RANDOM_N(128)
+
+} // namespace metaspace
+
+#endif // _LP64
diff --git a/test/hotspot/gtest/metaspace/test_freeblocks.cpp b/test/hotspot/gtest/metaspace/test_freeblocks.cpp
index fbf2e822c11..239729bc696 100644
--- a/test/hotspot/gtest/metaspace/test_freeblocks.cpp
+++ b/test/hotspot/gtest/metaspace/test_freeblocks.cpp
@@ -26,10 +26,13 @@
#include "precompiled.hpp"
#include "memory/metaspace/counters.hpp"
#include "memory/metaspace/freeBlocks.hpp"
+#include "memory/metaspace/metablock.hpp"
+
//#define LOG_PLEASE
#include "metaspaceGtestCommon.hpp"
using metaspace::FreeBlocks;
+using metaspace::MetaBlock;
using metaspace::SizeCounter;
#define CHECK_CONTENT(fb, num_blocks_expected, word_size_expected) \
@@ -43,199 +46,21 @@ using metaspace::SizeCounter;
EXPECT_EQ(fb.count(), (int)num_blocks_expected); \
}
-class FreeBlocksTest {
-
- FeederBuffer _fb;
- FreeBlocks _freeblocks;
-
- // random generator for block feeding
- RandSizeGenerator _rgen_feeding;
-
- // random generator for allocations (and, hence, deallocations)
- RandSizeGenerator _rgen_allocations;
-
- SizeCounter _allocated_words;
-
- struct allocation_t {
- allocation_t* next;
- size_t word_size;
- MetaWord* p;
- };
-
- // Array of the same size as the pool max capacity; holds the allocated elements.
- allocation_t* _allocations;
-
- int _num_allocs;
- int _num_deallocs;
- int _num_feeds;
-
- bool feed_some() {
- size_t word_size = _rgen_feeding.get();
- MetaWord* p = _fb.get(word_size);
- if (p != nullptr) {
- _freeblocks.add_block(p, word_size);
- return true;
- }
- return false;
- }
-
- bool deallocate_top() {
-
- allocation_t* a = _allocations;
- if (a != nullptr) {
- _allocations = a->next;
- check_marked_range(a->p, a->word_size);
- _freeblocks.add_block(a->p, a->word_size);
- delete a;
- DEBUG_ONLY(_freeblocks.verify();)
- return true;
- }
- return false;
- }
-
- void deallocate_all() {
- while (deallocate_top());
- }
-
- bool allocate() {
-
- size_t word_size = MAX2(_rgen_allocations.get(), _freeblocks.MinWordSize);
- MetaWord* p = _freeblocks.remove_block(word_size);
- if (p != nullptr) {
- _allocated_words.increment_by(word_size);
- allocation_t* a = new allocation_t;
- a->p = p; a->word_size = word_size;
- a->next = _allocations;
- _allocations = a;
- DEBUG_ONLY(_freeblocks.verify();)
- mark_range(p, word_size);
- return true;
- }
- return false;
- }
-
- void test_all_marked_ranges() {
- for (allocation_t* a = _allocations; a != nullptr; a = a->next) {
- check_marked_range(a->p, a->word_size);
- }
- }
-
- void test_loop() {
- // We loop and in each iteration execute one of three operations:
- // - allocation from fbl
- // - deallocation to fbl of a previously allocated block
- // - feeding a new larger block into the fbl (mimicks chunk retiring)
- // When we have fed all large blocks into the fbl (feedbuffer empty), we
- // switch to draining the fbl completely (only allocs)
- bool forcefeed = false;
- bool draining = false;
- bool stop = false;
- int iter = 25000; // safety stop
- while (!stop && iter > 0) {
- iter --;
- int surprise = (int)os::random() % 10;
- if (!draining && (surprise >= 7 || forcefeed)) {
- forcefeed = false;
- if (feed_some()) {
- _num_feeds++;
- } else {
- // We fed all input memory into the fbl. Now lets proceed until the fbl is drained.
- draining = true;
- }
- } else if (!draining && surprise < 1) {
- deallocate_top();
- _num_deallocs++;
- } else {
- if (allocate()) {
- _num_allocs++;
- } else {
- if (draining) {
- stop = _freeblocks.total_size() < 512;
- } else {
- forcefeed = true;
- }
- }
- }
- if ((iter % 1000) == 0) {
- DEBUG_ONLY(_freeblocks.verify();)
- test_all_marked_ranges();
- LOG("a %d (" SIZE_FORMAT "), d %d, f %d", _num_allocs, _allocated_words.get(), _num_deallocs, _num_feeds);
-#ifdef LOG_PLEASE
- _freeblocks.print(tty, true);
- tty->cr();
-#endif
- }
- }
-
- // Drain
-
- }
-
-public:
-
- FreeBlocksTest(size_t avg_alloc_size) :
- _fb(512 * K), _freeblocks(),
- _rgen_feeding(128, 4096),
- _rgen_allocations(avg_alloc_size / 4, avg_alloc_size * 2, 0.01f, avg_alloc_size / 3, avg_alloc_size * 30),
- _allocations(nullptr),
- _num_allocs(0),
- _num_deallocs(0),
- _num_feeds(0)
- {
- CHECK_CONTENT(_freeblocks, 0, 0);
- // some initial feeding
- _freeblocks.add_block(_fb.get(1024), 1024);
- CHECK_CONTENT(_freeblocks, 1, 1024);
- }
-
- ~FreeBlocksTest() {
- deallocate_all();
- }
-
- static void test_small_allocations() {
- FreeBlocksTest test(10);
- test.test_loop();
- }
-
- static void test_medium_allocations() {
- FreeBlocksTest test(30);
- test.test_loop();
- }
-
- static void test_large_allocations() {
- FreeBlocksTest test(150);
- test.test_loop();
- }
-
-};
-
TEST_VM(metaspace, freeblocks_basics) {
FreeBlocks fbl;
MetaWord tmp[1024];
CHECK_CONTENT(fbl, 0, 0);
- fbl.add_block(tmp, 1024);
+ MetaBlock bl(tmp, 1024);
+ fbl.add_block(bl);
DEBUG_ONLY(fbl.verify();)
ASSERT_FALSE(fbl.is_empty());
CHECK_CONTENT(fbl, 1, 1024);
- MetaWord* p = fbl.remove_block(1024);
- EXPECT_EQ(p, tmp);
+ MetaBlock bl2 = fbl.remove_block(1024);
+ ASSERT_EQ(bl, bl2);
DEBUG_ONLY(fbl.verify();)
CHECK_CONTENT(fbl, 0, 0);
}
-
-TEST_VM(metaspace, freeblocks_small) {
- FreeBlocksTest::test_small_allocations();
-}
-
-TEST_VM(metaspace, freeblocks_medium) {
- FreeBlocksTest::test_medium_allocations();
-}
-
-TEST_VM(metaspace, freeblocks_large) {
- FreeBlocksTest::test_large_allocations();
-}
-
diff --git a/test/hotspot/gtest/metaspace/test_metablock.cpp b/test/hotspot/gtest/metaspace/test_metablock.cpp
new file mode 100644
index 00000000000..af103a2b462
--- /dev/null
+++ b/test/hotspot/gtest/metaspace/test_metablock.cpp
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2020, 2024, 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.
+ *
+ * This code is free software; you can redistribute 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 "precompiled.hpp"
+#include "memory/metaspace/metablock.inline.hpp"
+//#define LOG_PLEASE
+#include "metaspaceGtestCommon.hpp"
+
+using metaspace::MetaBlock;
+
+
+#define CHECK_BLOCK_EMPTY(block) { \
+ EXPECT_TRUE(block.is_empty()); \
+ DEBUG_ONLY(block.verify()); \
+}
+
+#define CHECK_BLOCK(block, expected_base, expected_size) { \
+ EXPECT_EQ(block.base(), (MetaWord*)expected_base); \
+ EXPECT_EQ((size_t)expected_size, block.word_size()); \
+ EXPECT_EQ(block.end(), expected_base + expected_size); \
+ DEBUG_ONLY(block.verify()); \
+}
+
+static constexpr uintptr_t large_pointer = NOT_LP64(0x99999990) LP64_ONLY(0x9999999999999990ULL);
+
+TEST(metaspace, MetaBlock_1) {
+ MetaBlock bl;
+ CHECK_BLOCK_EMPTY(bl);
+}
+
+TEST(metaspace, MetaBlock_2) {
+ MetaWord* const p = (MetaWord*)large_pointer;
+ constexpr size_t s = G;
+ MetaBlock bl(p, s);
+ CHECK_BLOCK(bl, p, s);
+}
+
+TEST(metaspace, MetaBlock_3) {
+ MetaWord* const p = (MetaWord*)large_pointer;
+ MetaBlock bl(p, 0);
+ CHECK_BLOCK_EMPTY(bl);
+}
+
+TEST_VM(metaspace, MetaBlock_4) {
+ MetaWord* const p = (MetaWord*)large_pointer;
+ MetaBlock bl(p, G);
+ CHECK_BLOCK(bl, p, G);
+
+ MetaBlock bl_copy = bl, bl2;
+
+ bl2 = bl.split_off_tail(M);
+ CHECK_BLOCK(bl, p, G - M);
+ CHECK_BLOCK(bl2, p + G - M, M);
+
+ bl = bl_copy;
+
+bl.print_on(tty);
+bl2.print_on(tty);
+ bl2 = bl.split_off_tail(G);
+ bl.print_on(tty);
+ bl2.print_on(tty);
+
+ ASSERT_EQ(bl2, bl_copy);
+ ASSERT_TRUE(bl.is_empty());
+
+ bl = bl_copy;
+
+ bl2 = bl.split_off_tail(0);
+ ASSERT_EQ(bl, bl_copy);
+ ASSERT_TRUE(bl2.is_empty());
+
+ MetaBlock empty;
+ bl = empty.split_off_tail(0);
+ ASSERT_TRUE(bl.is_empty());
+}
diff --git a/test/hotspot/gtest/metaspace/test_metaspaceUtils.cpp b/test/hotspot/gtest/metaspace/test_metaspaceUtils.cpp
index 9f6ac9e988a..8a46f71be5d 100644
--- a/test/hotspot/gtest/metaspace/test_metaspaceUtils.cpp
+++ b/test/hotspot/gtest/metaspace/test_metaspaceUtils.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 2024, 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.
*
@@ -28,7 +28,7 @@
#include "memory/metaspaceUtils.hpp"
#include "unittest.hpp"
-TEST_VM(MetaspaceUtils, reserved) {
+TEST_VM(metaspace, MetaspaceUtils_reserved) {
size_t reserved = MetaspaceUtils::reserved_bytes();
EXPECT_GT(reserved, 0UL);
@@ -37,7 +37,7 @@ TEST_VM(MetaspaceUtils, reserved) {
EXPECT_LE(reserved_metadata, reserved);
}
-TEST_VM(MetaspaceUtils, reserved_compressed_class_pointers) {
+TEST_VM(metaspace, MetaspaceUtils_reserved_compressed_class_pointers) {
if (!UseCompressedClassPointers) {
return;
}
@@ -49,7 +49,7 @@ TEST_VM(MetaspaceUtils, reserved_compressed_class_pointers) {
EXPECT_LE(reserved_class, reserved);
}
-TEST_VM(MetaspaceUtils, committed) {
+TEST_VM(metaspace, MetaspaceUtils_committed) {
size_t committed = MetaspaceUtils::committed_bytes();
EXPECT_GT(committed, 0UL);
@@ -61,7 +61,7 @@ TEST_VM(MetaspaceUtils, committed) {
EXPECT_LE(committed_metadata, committed);
}
-TEST_VM(MetaspaceUtils, committed_compressed_class_pointers) {
+TEST_VM(metaspace, MetaspaceUtils_committed_compressed_class_pointers) {
if (!UseCompressedClassPointers) {
return;
}
@@ -73,7 +73,7 @@ TEST_VM(MetaspaceUtils, committed_compressed_class_pointers) {
EXPECT_LE(committed_class, committed);
}
-TEST_VM(MetaspaceUtils, non_compressed_class_pointers) {
+TEST_VM(metaspace, MetaspaceUtils_non_compressed_class_pointers) {
if (UseCompressedClassPointers) {
return;
}
@@ -99,7 +99,7 @@ static void check_metaspace_stats_are_not_null(const MetaspaceStats& stats) {
EXPECT_GT(stats.used(), 0UL);
}
-TEST_VM(MetaspaceUtils, get_statistics) {
+TEST_VM(MetaspaceUtils, MetaspaceUtils_get_statistics) {
MetaspaceCombinedStats combined_stats = MetaspaceUtils::get_combined_statistics();
check_metaspace_stats_are_not_null(combined_stats);
check_metaspace_stats_are_consistent(combined_stats);
diff --git a/test/hotspot/gtest/metaspace/test_metaspacearena.cpp b/test/hotspot/gtest/metaspace/test_metaspacearena.cpp
index 2e5a6d40ce7..2f7627ccffe 100644
--- a/test/hotspot/gtest/metaspace/test_metaspacearena.cpp
+++ b/test/hotspot/gtest/metaspace/test_metaspacearena.cpp
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2023 SAP SE. All rights reserved.
+ * Copyright (c) 2023 Red Hat, Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -28,98 +29,125 @@
#include "memory/metaspace/commitLimiter.hpp"
#include "memory/metaspace/counters.hpp"
#include "memory/metaspace/internalStats.hpp"
+#include "memory/metaspace/freeBlocks.hpp"
+#include "memory/metaspace/metablock.inline.hpp"
#include "memory/metaspace/metaspaceArena.hpp"
#include "memory/metaspace/metaspaceArenaGrowthPolicy.hpp"
+#include "memory/metaspace/metachunkList.hpp"
#include "memory/metaspace/metaspaceCommon.hpp"
#include "memory/metaspace/metaspaceSettings.hpp"
#include "memory/metaspace/metaspaceStatistics.hpp"
+#include "memory/metaspace.hpp"
#include "utilities/debug.hpp"
#include "utilities/globalDefinitions.hpp"
-//#define LOG_PLEASE
+#define LOG_PLEASE
#include "metaspaceGtestCommon.hpp"
#include "metaspaceGtestContexts.hpp"
#include "metaspaceGtestRangeHelpers.hpp"
-using metaspace::AllocationAlignmentByteSize;
-using metaspace::ArenaGrowthPolicy;
-using metaspace::CommitLimiter;
-using metaspace::InternalStats;
-using metaspace::MemRangeCounter;
-using metaspace::MetaspaceArena;
-using metaspace::SizeAtomicCounter;
-using metaspace::Settings;
-using metaspace::ArenaStats;
+#define HANDLE_FAILURE \
+ if (testing::Test::HasFailure()) { \
+ return; \
+ }
+
+namespace metaspace {
+
+class MetaspaceArenaTestFriend {
+ const MetaspaceArena* const _arena;
+public:
+ MetaspaceArenaTestFriend(const MetaspaceArena* arena) : _arena(arena) {}
+ const MetachunkList& chunks() const { return _arena->_chunks; }
+ const FreeBlocks* fbl() const { return _arena->_fbl; }
+};
class MetaspaceArenaTestHelper {
MetaspaceGtestContext& _context;
+ const ArenaGrowthPolicy* const _growth_policy;
- const ArenaGrowthPolicy* _growth_policy;
- SizeAtomicCounter _used_words_counter;
MetaspaceArena* _arena;
- void initialize(const ArenaGrowthPolicy* growth_policy, const char* name = "gtest-MetaspaceArena") {
- _growth_policy = growth_policy;
- _arena = new MetaspaceArena(&_context.cm(), _growth_policy, &_used_words_counter, name);
- DEBUG_ONLY(_arena->verify());
- }
-
public:
- // Create a helper; growth policy for arena is determined by the given spacetype|class tupel
- MetaspaceArenaTestHelper(MetaspaceGtestContext& helper,
- Metaspace::MetaspaceType space_type, bool is_class,
- const char* name = "gtest-MetaspaceArena") :
- _context(helper)
- {
- initialize(ArenaGrowthPolicy::policy_for_space_type(space_type, is_class), name);
- }
-
// Create a helper; growth policy is directly specified
MetaspaceArenaTestHelper(MetaspaceGtestContext& helper, const ArenaGrowthPolicy* growth_policy,
- const char* name = "gtest-MetaspaceArena") :
- _context(helper)
+ size_t allocation_alignment_words = Metaspace::min_allocation_alignment_words) :
+ _context(helper), _growth_policy(growth_policy), _arena(nullptr)
{
- initialize(growth_policy, name);
+ _arena = new MetaspaceArena(_context.context(), _growth_policy, allocation_alignment_words, "gtest-MetaspaceArena");
+ DEBUG_ONLY(_arena->verify());
+ _context.inc_num_arenas_created();
}
+
+ // Create a helper; growth policy for arena is determined by the given spacetype|class tupel
+ MetaspaceArenaTestHelper(MetaspaceGtestContext& helper,
+ Metaspace::MetaspaceType space_type, bool is_class,
+ size_t allocation_alignment_words = Metaspace::min_allocation_alignment_words) :
+ MetaspaceArenaTestHelper(helper, ArenaGrowthPolicy::policy_for_space_type(space_type, is_class), allocation_alignment_words)
+ {}
+
~MetaspaceArenaTestHelper() {
delete_arena_with_tests();
}
- const CommitLimiter& limiter() const { return _context.commit_limiter(); }
MetaspaceArena* arena() const { return _arena; }
- SizeAtomicCounter& used_words_counter() { return _used_words_counter; }
// Note: all test functions return void due to gtests limitation that we cannot use ASSERT
// in non-void returning tests.
void delete_arena_with_tests() {
if (_arena != nullptr) {
- size_t used_words_before = _used_words_counter.get();
- size_t committed_words_before = limiter().committed_words();
+ size_t used_words_before = _context.used_words();
+ size_t committed_words_before = _context.committed_words();
DEBUG_ONLY(_arena->verify());
delete _arena;
_arena = nullptr;
- size_t used_words_after = _used_words_counter.get();
- size_t committed_words_after = limiter().committed_words();
- ASSERT_0(used_words_after);
+ size_t used_words_after = _context.used_words();
+ size_t committed_words_after = _context.committed_words();
+ assert(_context.num_arenas_created() >= 1, "Sanity");
+ if (_context.num_arenas_created() == 1) {
+ ASSERT_0(used_words_after);
+ } else {
+ ASSERT_LE(used_words_after, used_words_before);
+ }
ASSERT_LE(committed_words_after, committed_words_before);
}
}
void usage_numbers_with_test(size_t* p_used, size_t* p_committed, size_t* p_capacity) const {
- _arena->usage_numbers(p_used, p_committed, p_capacity);
- if (p_used != nullptr) {
- if (p_committed != nullptr) {
- ASSERT_GE(*p_committed, *p_used);
- }
- // Since we own the used words counter, it should reflect our usage number 1:1
- ASSERT_EQ(_used_words_counter.get(), *p_used);
+ size_t arena_used = 0, arena_committed = 0, arena_reserved = 0;
+ _arena->usage_numbers(&arena_used, &arena_committed, &arena_reserved);
+ EXPECT_GE(arena_committed, arena_used);
+ EXPECT_GE(arena_reserved, arena_committed);
+
+ size_t context_used = _context.used_words();
+ size_t context_committed = _context.committed_words();
+ size_t context_reserved = _context.reserved_words();
+ EXPECT_GE(context_committed, context_used);
+ EXPECT_GE(context_reserved, context_committed);
+
+ // If only one arena uses the context, usage numbers must match.
+ if (_context.num_arenas_created() == 1) {
+ EXPECT_EQ(context_used, arena_used);
+ } else {
+ assert(_context.num_arenas_created() > 1, "Sanity");
+ EXPECT_GE(context_used, arena_used);
}
- if (p_committed != nullptr && p_capacity != nullptr) {
- ASSERT_GE(*p_capacity, *p_committed);
+
+ // commit, reserve numbers don't have to match since free chunks may exist
+ EXPECT_GE(context_committed, arena_committed);
+ EXPECT_GE(context_reserved, arena_reserved);
+
+ if (p_used) {
+ *p_used = arena_used;
+ }
+ if (p_committed) {
+ *p_committed = arena_committed;
+ }
+ if (p_capacity) {
+ *p_capacity = arena_reserved;
}
}
@@ -142,23 +170,33 @@ class MetaspaceArenaTestHelper {
ASSERT_NULL(dummy);
}
- // Allocate; it may or may not work; return value in *p_return_value
void allocate_from_arena_with_tests(MetaWord** p_return_value, size_t word_size) {
+ MetaBlock result, wastage;
+ allocate_from_arena_with_tests(word_size, result, wastage);
+ if (wastage.is_nonempty()) {
+ _arena->deallocate(wastage);
+ wastage.reset();
+ }
+ (*p_return_value) = result.base();
+ }
+
+ // Allocate; it may or may not work; return value in *p_return_value
+ void allocate_from_arena_with_tests(size_t word_size, MetaBlock& result, MetaBlock& wastage) {
// Note: usage_numbers walks all chunks in use and counts.
size_t used = 0, committed = 0, capacity = 0;
usage_numbers_with_test(&used, &committed, &capacity);
- size_t possible_expansion = limiter().possible_expansion_words();
+ size_t possible_expansion = _context.commit_limiter().possible_expansion_words();
- MetaWord* p = _arena->allocate(word_size);
+ result = _arena->allocate(word_size, wastage);
SOMETIMES(DEBUG_ONLY(_arena->verify();))
size_t used2 = 0, committed2 = 0, capacity2 = 0;
usage_numbers_with_test(&used2, &committed2, &capacity2);
- if (p == nullptr) {
+ if (result.is_empty()) {
// Allocation failed.
ASSERT_LT(possible_expansion, word_size);
ASSERT_EQ(used, used2);
@@ -166,7 +204,8 @@ class MetaspaceArenaTestHelper {
ASSERT_EQ(capacity, capacity2);
} else {
// Allocation succeeded. Should be correctly aligned.
- ASSERT_TRUE(is_aligned(p, AllocationAlignmentByteSize));
+ ASSERT_TRUE(result.is_aligned_base(_arena->allocation_alignment_words()));
+
// used: may go up or may not (since our request may have been satisfied from the freeblocklist
// whose content already counts as used).
// committed: may go up, may not
@@ -175,8 +214,6 @@ class MetaspaceArenaTestHelper {
ASSERT_GE(committed2, committed);
ASSERT_GE(capacity2, capacity);
}
-
- *p_return_value = p;
}
// Allocate; it may or may not work; but caller does not care for the result value
@@ -189,7 +226,7 @@ class MetaspaceArenaTestHelper {
size_t used = 0, committed = 0, capacity = 0;
usage_numbers_with_test(&used, &committed, &capacity);
- _arena->deallocate(p, word_size);
+ _arena->deallocate(MetaBlock(p, word_size));
SOMETIMES(DEBUG_ONLY(_arena->verify();))
@@ -209,9 +246,13 @@ class MetaspaceArenaTestHelper {
return stats;
}
+ MetaspaceArenaTestFriend internal_access() const {
+ return MetaspaceArenaTestFriend (_arena);
+ }
+
// Convenience method to return number of chunks in arena (including current chunk)
int get_number_of_chunks() const {
- return get_arena_statistics().totals()._num;
+ return internal_access().chunks().count();
}
};
@@ -391,23 +432,28 @@ TEST_VM(metaspace, MetaspaceArena_deallocate) {
MetaWord* p1 = nullptr;
helper.allocate_from_arena_with_tests_expect_success(&p1, s);
+ ASSERT_FALSE(HasFailure());
size_t used1 = 0, capacity1 = 0;
helper.usage_numbers_with_test(&used1, nullptr, &capacity1);
+ ASSERT_FALSE(HasFailure());
ASSERT_EQ(used1, s);
helper.deallocate_with_tests(p1, s);
size_t used2 = 0, capacity2 = 0;
helper.usage_numbers_with_test(&used2, nullptr, &capacity2);
+ ASSERT_FALSE(HasFailure());
ASSERT_EQ(used1, used2);
ASSERT_EQ(capacity2, capacity2);
MetaWord* p2 = nullptr;
helper.allocate_from_arena_with_tests_expect_success(&p2, s);
+ ASSERT_FALSE(HasFailure());
size_t used3 = 0, capacity3 = 0;
helper.usage_numbers_with_test(&used3, nullptr, &capacity3);
+ ASSERT_FALSE(HasFailure());
ASSERT_EQ(used3, used2);
ASSERT_EQ(capacity3, capacity2);
@@ -450,6 +496,7 @@ static void test_recover_from_commit_limit_hit() {
helper1.allocate_from_arena_with_tests_expect_success(1);
helper2.allocate_from_arena_with_tests_expect_success(1);
allocated_from_1_and_2 += 2;
+ HANDLE_FAILURE
}
// Now, allocating from helper3, creep up on the limit
@@ -494,11 +541,11 @@ static void test_controlled_growth(Metaspace::MetaspaceType type, bool is_class,
// have different initial capacities.
MetaspaceGtestContext context;
- MetaspaceArenaTestHelper smhelper(context, type, is_class, "Grower");
+ MetaspaceArenaTestHelper smhelper(context, type, is_class);
const Metaspace::MetaspaceType other_type =
(type == Metaspace::StandardMetaspaceType) ? Metaspace::ClassMirrorHolderMetaspaceType : Metaspace::StandardMetaspaceType;
- MetaspaceArenaTestHelper smhelper_harrasser(context, other_type, true, "Harasser");
+ MetaspaceArenaTestHelper smhelper_harrasser(context, other_type, true);
size_t used = 0, committed = 0, capacity = 0;
const size_t alloc_words = 16;
@@ -561,12 +608,14 @@ static void test_controlled_growth(Metaspace::MetaspaceType type, bool is_class,
}
smhelper.allocate_from_arena_with_tests_expect_success(alloc_words);
+ HANDLE_FAILURE
words_allocated += metaspace::get_raw_word_size_for_requested_word_size(alloc_words);
num_allocated++;
size_t used2 = 0, committed2 = 0, capacity2 = 0;
smhelper.arena()->usage_numbers(&used2, &committed2, &capacity2);
+ HANDLE_FAILURE
// used should not grow larger than what we allocated, plus possible overhead.
ASSERT_GE(used2, used);
@@ -608,6 +657,10 @@ static void test_controlled_growth(Metaspace::MetaspaceType type, bool is_class,
}
+ // No FBL should exist, we did not deallocate
+ ASSERT_EQ(smhelper.internal_access().fbl(), (FreeBlocks*)nullptr);
+ ASSERT_EQ(smhelper_harrasser.internal_access().fbl(), (FreeBlocks*)nullptr);
+
// After all this work, we should see an increase in number of chunk-in-place-enlargements
// (this especially is vulnerable to regression: the decisions of when to do in-place-enlargements are somewhat
// complicated, see MetaspaceArena::attempt_enlarge_current_chunk())
@@ -691,7 +744,8 @@ TEST_VM(metaspace, MetaspaceArena_growth_boot_nc_not_inplace) {
// block should be reused by the next allocation).
static void test_repeatedly_allocate_and_deallocate(bool is_topmost) {
// Test various sizes, including (important) the max. possible block size = 1 root chunk
- for (size_t blocksize = Metaspace::max_allocation_word_size(); blocksize >= 1; blocksize /= 2) {
+ for (size_t blocksize = Metaspace::max_allocation_word_size();
+ blocksize >= Metaspace::min_allocation_word_size; blocksize /= 2) {
size_t used1 = 0, used2 = 0, committed1 = 0, committed2 = 0;
MetaWord* p = nullptr, *p2 = nullptr;
@@ -703,6 +757,7 @@ static void test_repeatedly_allocate_and_deallocate(bool is_topmost) {
if (!is_topmost) {
// another one on top, size does not matter.
helper.allocate_from_arena_with_tests_expect_success(0x10);
+ HANDLE_FAILURE
}
// Measure
@@ -712,6 +767,7 @@ static void test_repeatedly_allocate_and_deallocate(bool is_topmost) {
for (int i = 0; i < 5; i ++) {
helper.deallocate_with_tests(p, blocksize);
helper.allocate_from_arena_with_tests_expect_success(&p2, blocksize);
+ HANDLE_FAILURE
// We should get the same pointer back.
EXPECT_EQ(p2, p);
}
@@ -730,3 +786,120 @@ TEST_VM(metaspace, MetaspaceArena_test_repeatedly_allocate_and_deallocate_top_al
TEST_VM(metaspace, MetaspaceArena_test_repeatedly_allocate_and_deallocate_nontop_allocation) {
test_repeatedly_allocate_and_deallocate(false);
}
+
+static void test_random_aligned_allocation(size_t arena_alignment_words, SizeRange range) {
+ // We let the arena use 4K chunks, unless the alloc size is larger.
+ chunklevel_t level = CHUNK_LEVEL_4K;
+ const ArenaGrowthPolicy policy (&level, 1);
+ const size_t chunk_word_size = word_size_for_level(level);
+
+ size_t expected_used = 0;
+
+ MetaspaceGtestContext context;
+ MetaspaceArenaTestHelper helper(context, &policy, arena_alignment_words);
+
+ size_t last_alloc_size = 0;
+ unsigned num_allocations = 0;
+
+ const size_t max_used = MIN2(MAX2(chunk_word_size * 10, (range.highest() * 100)),
+ LP64_ONLY(64) NOT_LP64(16) * M); // word size!
+ while (expected_used < max_used) {
+
+ const int chunks_before = helper.get_number_of_chunks();
+
+ MetaBlock result, wastage;
+ size_t alloc_words = range.random_value();
+ NOT_LP64(alloc_words = align_up(alloc_words, Metaspace::min_allocation_alignment_words));
+ helper.allocate_from_arena_with_tests(alloc_words, result, wastage);
+
+ ASSERT_TRUE(result.is_nonempty());
+ ASSERT_TRUE(result.is_aligned_base(arena_alignment_words));
+ ASSERT_EQ(result.word_size(), alloc_words);
+
+ expected_used += alloc_words + wastage.word_size();
+ const int chunks_now = helper.get_number_of_chunks();
+ ASSERT_GE(chunks_now, chunks_before);
+ ASSERT_LE(chunks_now, chunks_before + 1);
+
+ // Estimate wastage:
+ // Guessing at wastage is somewhat simple since we don't expect to ever use the fbl (we
+ // don't deallocate). Therefore, wastage can only be caused by alignment gap or by
+ // salvaging an old chunk before a new chunk is added.
+ const bool expect_alignment_gap = !is_aligned(last_alloc_size, arena_alignment_words);
+ const bool new_chunk_added = chunks_now > chunks_before;
+
+ if (num_allocations == 0) {
+ // expect no wastage if its the first allocation in the arena
+ ASSERT_TRUE(wastage.is_empty());
+ } else {
+ if (expect_alignment_gap) {
+ // expect wastage if the alignment requires it
+ ASSERT_TRUE(wastage.is_nonempty());
+ }
+ }
+
+ if (wastage.is_nonempty()) {
+ // If we have wastage, we expect it to be either too small or unaligned. That would not be true
+ // for wastage from the fbl, which could have any size; however, in this test we don't deallocate,
+ // so we don't expect wastage from the fbl.
+ if (wastage.is_aligned_base(arena_alignment_words)) {
+ ASSERT_LT(wastage.word_size(), alloc_words);
+ }
+ if (new_chunk_added) {
+ // chunk turnover: no more wastage than size of a commit granule, since we salvage the
+ // committed remainder of the old chunk.
+ ASSERT_LT(wastage.word_size(), Settings::commit_granule_words());
+ } else {
+ // No chunk turnover: no more wastage than what alignment requires.
+ ASSERT_LT(wastage.word_size(), arena_alignment_words);
+ }
+ }
+
+ // Check stats too
+ size_t used, committed, reserved;
+ helper.usage_numbers_with_test(&used, &committed, &reserved);
+ ASSERT_EQ(used, expected_used);
+
+ // No FBL should exist, we did not deallocate
+ ASSERT_EQ(helper.internal_access().fbl(), (FreeBlocks*)nullptr);
+
+ HANDLE_FAILURE
+
+ last_alloc_size = alloc_words;
+ num_allocations ++;
+ }
+ LOG("allocs: %u", num_allocations);
+}
+
+#define TEST_ARENA_WITH_ALIGNMENT_SMALL_RANGE(al) \
+TEST_VM(metaspace, MetaspaceArena_test_random_small_aligned_allocation_##al) { \
+ static const SizeRange range(Metaspace::min_allocation_word_size, 128); \
+ test_random_aligned_allocation(al, range); \
+}
+
+#ifdef _LP64
+TEST_ARENA_WITH_ALIGNMENT_SMALL_RANGE(1);
+#endif
+TEST_ARENA_WITH_ALIGNMENT_SMALL_RANGE(2);
+TEST_ARENA_WITH_ALIGNMENT_SMALL_RANGE(8);
+TEST_ARENA_WITH_ALIGNMENT_SMALL_RANGE(32);
+TEST_ARENA_WITH_ALIGNMENT_SMALL_RANGE(128);
+TEST_ARENA_WITH_ALIGNMENT_SMALL_RANGE(MIN_CHUNK_WORD_SIZE);
+
+#define TEST_ARENA_WITH_ALIGNMENT_LARGE_RANGE(al) \
+TEST_VM(metaspace, MetaspaceArena_test_random_large_aligned_allocation_##al) { \
+ static const SizeRange range(Metaspace::max_allocation_word_size() / 2, \
+ Metaspace::max_allocation_word_size()); \
+ test_random_aligned_allocation(al, range); \
+}
+
+#ifdef _LP64
+TEST_ARENA_WITH_ALIGNMENT_LARGE_RANGE(1);
+#endif
+TEST_ARENA_WITH_ALIGNMENT_LARGE_RANGE(2);
+TEST_ARENA_WITH_ALIGNMENT_LARGE_RANGE(8);
+TEST_ARENA_WITH_ALIGNMENT_LARGE_RANGE(32);
+TEST_ARENA_WITH_ALIGNMENT_LARGE_RANGE(128);
+TEST_ARENA_WITH_ALIGNMENT_LARGE_RANGE(MIN_CHUNK_WORD_SIZE);
+
+} // namespace metaspace
diff --git a/test/hotspot/gtest/metaspace/test_metaspacearena_stress.cpp b/test/hotspot/gtest/metaspace/test_metaspacearena_stress.cpp
index bb536dfd0e2..950f21fb92f 100644
--- a/test/hotspot/gtest/metaspace/test_metaspacearena_stress.cpp
+++ b/test/hotspot/gtest/metaspace/test_metaspacearena_stress.cpp
@@ -26,8 +26,10 @@
#include "precompiled.hpp"
#include "memory/metaspace/chunkManager.hpp"
#include "memory/metaspace/counters.hpp"
+#include "memory/metaspace/metablock.hpp"
#include "memory/metaspace/metaspaceArena.hpp"
#include "memory/metaspace/metaspaceArenaGrowthPolicy.hpp"
+#include "memory/metaspace/metaspaceContext.hpp"
#include "memory/metaspace/metaspaceSettings.hpp"
#include "memory/metaspace/metaspaceStatistics.hpp"
#include "runtime/mutexLocker.hpp"
@@ -43,7 +45,9 @@ using metaspace::ArenaGrowthPolicy;
using metaspace::ChunkManager;
using metaspace::IntCounter;
using metaspace::MemRangeCounter;
+using metaspace::MetaBlock;
using metaspace::MetaspaceArena;
+using metaspace::MetaspaceContext;
using metaspace::SizeAtomicCounter;
using metaspace::ArenaStats;
using metaspace::InUseChunkStats;
@@ -124,16 +128,14 @@ class MetaspaceArenaTestBed : public CHeapObj {
MetaspaceArena* arena() { return _arena; }
- MetaspaceArenaTestBed(ChunkManager* cm, const ArenaGrowthPolicy* alloc_sequence,
- SizeAtomicCounter* used_words_counter, SizeRange allocation_range) :
- _arena(nullptr),
- _allocation_range(allocation_range),
- _size_of_last_failed_allocation(0),
- _allocations(nullptr),
- _alloc_count(),
- _dealloc_count()
+ MetaspaceArenaTestBed(MetaspaceContext* context, const ArenaGrowthPolicy* growth_policy,
+ size_t allocation_alignment_words, SizeRange allocation_range)
+ : _arena(nullptr)
+ , _allocation_range(allocation_range)
+ , _size_of_last_failed_allocation(0)
+ , _allocations(nullptr)
{
- _arena = new MetaspaceArena(cm, alloc_sequence, used_words_counter, "gtest-MetaspaceArenaTestBed-sm");
+ _arena = new MetaspaceArena(context, growth_policy, Metaspace::min_allocation_alignment_words, "gtest-MetaspaceArenaTestBed-sm");
}
~MetaspaceArenaTestBed() {
@@ -163,13 +165,20 @@ class MetaspaceArenaTestBed : public CHeapObj {
// Allocate a random amount. Return false if the allocation failed.
bool checked_random_allocate() {
size_t word_size = 1 + _allocation_range.random_value();
- MetaWord* p = _arena->allocate(word_size);
- if (p != nullptr) {
- EXPECT_TRUE(is_aligned(p, AllocationAlignmentByteSize));
+ MetaBlock wastage;
+ MetaBlock bl = _arena->allocate(word_size, wastage);
+ // We only expect wastage if either alignment was not met or the chunk remainder
+ // was not large enough.
+ if (wastage.is_nonempty()) {
+ _arena->deallocate(wastage);
+ wastage.reset();
+ }
+ if (bl.is_nonempty()) {
+ EXPECT_TRUE(is_aligned(bl.base(), AllocationAlignmentByteSize));
allocation_t* a = NEW_C_HEAP_OBJ(allocation_t, mtInternal);
a->word_size = word_size;
- a->p = p;
+ a->p = bl.base();
a->mark();
a->next = _allocations;
_allocations = a;
@@ -193,7 +202,7 @@ class MetaspaceArenaTestBed : public CHeapObj {
}
if (a != nullptr && a->p != nullptr) {
a->verify();
- _arena->deallocate(a->p, a->word_size);
+ _arena->deallocate(MetaBlock(a->p, a->word_size));
_dealloc_count.add(a->word_size);
a->p = nullptr; a->word_size = 0;
if ((_dealloc_count.count() % 20) == 0) {
@@ -218,8 +227,8 @@ class MetaspaceArenaTest {
void create_new_test_bed_at(int slotindex, const ArenaGrowthPolicy* growth_policy, SizeRange allocation_range) {
DEBUG_ONLY(_testbeds.check_slot_is_null(slotindex));
- MetaspaceArenaTestBed* bed = new MetaspaceArenaTestBed(&_context.cm(), growth_policy,
- &_used_words_counter, allocation_range);
+ MetaspaceArenaTestBed* bed = new MetaspaceArenaTestBed(_context.context(), growth_policy,
+ Metaspace::min_allocation_alignment_words, allocation_range);
_testbeds.set_at(slotindex, bed);
_num_beds.increment();
}
diff --git a/test/hotspot/gtest/oops/test_arrayOop.cpp b/test/hotspot/gtest/oops/test_arrayOop.cpp
index e67e6e6c13b..5670aedafc1 100644
--- a/test/hotspot/gtest/oops/test_arrayOop.cpp
+++ b/test/hotspot/gtest/oops/test_arrayOop.cpp
@@ -82,7 +82,23 @@ TEST_VM(arrayOopDesc, narrowOop) {
TEST_VM(arrayOopDesc, base_offset) {
#ifdef _LP64
- if (UseCompressedClassPointers) {
+ if (UseCompactObjectHeaders) {
+ EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_BOOLEAN), 12);
+ EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_BYTE), 12);
+ EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_SHORT), 12);
+ EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_CHAR), 12);
+ EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_INT), 12);
+ EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_FLOAT), 12);
+ EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_LONG), 16);
+ EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_DOUBLE), 16);
+ if (UseCompressedOops) {
+ EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_OBJECT), 12);
+ EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_ARRAY), 12);
+ } else {
+ EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_OBJECT), 16);
+ EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_ARRAY), 16);
+ }
+ } else if (UseCompressedClassPointers) {
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);
diff --git a/test/hotspot/gtest/oops/test_compressedKlass.cpp b/test/hotspot/gtest/oops/test_compressedKlass.cpp
index b2fc5064581..48026f46852 100644
--- a/test/hotspot/gtest/oops/test_compressedKlass.cpp
+++ b/test/hotspot/gtest/oops/test_compressedKlass.cpp
@@ -36,6 +36,7 @@ TEST_VM(CompressedKlass, basics) {
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());
+
switch (CompressedKlassPointers::shift()) {
case 0:
ASSERT_EQ(CompressedKlassPointers::encoding_range_end() - CompressedKlassPointers::base(), (ptrdiff_t)(4 * G));
@@ -44,10 +45,23 @@ TEST_VM(CompressedKlass, basics) {
ASSERT_EQ(CompressedKlassPointers::encoding_range_end() - CompressedKlassPointers::base(), (ptrdiff_t)(32 * G));
break;
default:
- ShouldNotReachHere();
+ const size_t expected_size = nth_bit(CompressedKlassPointers::narrow_klass_pointer_bits() + CompressedKlassPointers::shift());
+ ASSERT_EQ(CompressedKlassPointers::encoding_range_end() - CompressedKlassPointers::base(), (ptrdiff_t)expected_size);
}
}
+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;
@@ -68,12 +82,29 @@ TEST_VM(CompressedKlass, test_too_high_address) {
ASSERT_FALSE(CompressedKlassPointers::is_encodable(high));
}
+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));
+ // Try word-aligned, but not sufficiently aligned
+ if (alignment > BytesPerWord) {
+ addr = CompressedKlassPointers::klass_range_start() + BytesPerWord;
+ ASSERT_FALSE(CompressedKlassPointers::is_encodable(addr));
+ }
+ addr = CompressedKlassPointers::klass_range_end() - 1;
+ ASSERT_FALSE(CompressedKlassPointers::is_encodable(addr));
+}
+
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));
- addr = CompressedKlassPointers::klass_range_end() - 1;
+ addr = CompressedKlassPointers::klass_range_end() - alignment;
ASSERT_TRUE(CompressedKlassPointers::is_encodable(addr));
}
diff --git a/test/hotspot/gtest/oops/test_objArrayOop.cpp b/test/hotspot/gtest/oops/test_objArrayOop.cpp
index 60cf6242dd5..deb4919ce46 100644
--- a/test/hotspot/gtest/oops/test_objArrayOop.cpp
+++ b/test/hotspot/gtest/oops/test_objArrayOop.cpp
@@ -28,29 +28,36 @@
TEST_VM(objArrayOop, osize) {
static const struct {
- int objal; bool ccp; bool coops; int result;
+ int objal; bool ccp; bool coops; bool coh; int result;
} x[] = {
-// ObjAligInB, UseCCP, UseCoops, object size in heap words
+// ObjAligInB, UseCCP, UseCoops, UseCOH, object size in heap words
#ifdef _LP64
- { 8, false, false, 4 }, // 20 byte header, 8 byte oops
- { 8, false, true, 3 }, // 20 byte header, 4 byte oops
- { 8, true, false, 3 }, // 16 byte header, 8 byte oops
- { 8, true, true, 3 }, // 16 byte header, 4 byte oops
- { 16, false, false, 4 }, // 20 byte header, 8 byte oops, 16-byte align
- { 16, false, true, 4 }, // 20 byte header, 4 byte oops, 16-byte align
- { 16, true, false, 4 }, // 16 byte header, 8 byte oops, 16-byte align
- { 16, true, true, 4 }, // 16 byte header, 4 byte oops, 16-byte align
- { 256, false, false, 32 }, // 20 byte header, 8 byte oops, 256-byte align
- { 256, false, true, 32 }, // 20 byte header, 4 byte oops, 256-byte align
- { 256, true, false, 32 }, // 16 byte header, 8 byte oops, 256-byte align
- { 256, true, true, 32 }, // 16 byte header, 4 byte oops, 256-byte align
+ { 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
#else
- { 8, false, false, 4 }, // 12 byte header, 4 byte oops, wordsize 4
+ { 8, false, false, false, 4 }, // 12 byte header, 4 byte oops, wordsize 4
#endif
- { -1, false, false, -1 }
+ { -1, false, 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].ccp == UseCompressedClassPointers && x[i].coops == UseCompressedOops &&
+ x[i].coh == UseCompactObjectHeaders) {
EXPECT_EQ(objArrayOopDesc::object_size(1), (size_t)x[i].result);
}
}
diff --git a/test/hotspot/gtest/oops/test_typeArrayOop.cpp b/test/hotspot/gtest/oops/test_typeArrayOop.cpp
index a7565a23d58..b8c55867077 100644
--- a/test/hotspot/gtest/oops/test_typeArrayOop.cpp
+++ b/test/hotspot/gtest/oops/test_typeArrayOop.cpp
@@ -36,7 +36,11 @@ TEST_VM(typeArrayOopDesc, bool_at_put) {
char* addr = align_up(mem, 16);
typeArrayOop o = (typeArrayOop) cast_to_oop(addr);
- o->set_klass(Universe::boolArrayKlass());
+ if (UseCompactObjectHeaders) {
+ o->set_mark(Universe::boolArrayKlass()->prototype_header());
+ } else {
+ o->set_klass(Universe::boolArrayKlass());
+ }
o->set_length(10);
diff --git a/test/hotspot/gtest/opto/test_no_overflow_int.cpp b/test/hotspot/gtest/opto/test_no_overflow_int.cpp
new file mode 100644
index 00000000000..7b4b4259bb8
--- /dev/null
+++ b/test/hotspot/gtest/opto/test_no_overflow_int.cpp
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * 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 "precompiled.hpp"
+#include "opto/noOverflowInt.hpp"
+#include "unittest.hpp"
+
+static void check_jlong(const jlong val) {
+ const NoOverflowInt x(val);
+
+ if (val > max_jint || min_jint > val) {
+ ASSERT_TRUE(x.is_NaN());
+ } else {
+ ASSERT_FALSE(x.is_NaN());
+ ASSERT_EQ(x.value(), val);
+ }
+}
+
+TEST_VM(opto, NoOverflowInt_check_jlong) {
+ jlong start = (jlong)min_jint - 10000LL;
+ jlong end = (jlong)max_jint + 10000LL;
+ for (jlong i = start; i < end; i+= 1000LL) {
+ check_jlong(i);
+ }
+
+ check_jlong((jlong)min_jint - 1LL);
+ check_jlong((jlong)min_jint);
+ check_jlong((jlong)min_jint + 1LL);
+ check_jlong((jlong)max_jint - 1LL);
+ check_jlong((jlong)max_jint);
+ check_jlong((jlong)max_jint + 1LL);
+
+ const NoOverflowInt nan;
+ ASSERT_TRUE(nan.is_NaN());
+}
+
+TEST_VM(opto, NoOverflowInt_add_sub) {
+ const NoOverflowInt nan;
+ const NoOverflowInt zero(0);
+ const NoOverflowInt one(1);
+ const NoOverflowInt two(2);
+ const NoOverflowInt big(1 << 30);
+
+ ASSERT_EQ((one + two).value(), 3);
+ ASSERT_EQ((one - two).value(), -1);
+ ASSERT_TRUE((nan + one).is_NaN());
+ ASSERT_TRUE((one + nan).is_NaN());
+ ASSERT_TRUE((nan + nan).is_NaN());
+ ASSERT_TRUE((nan - one).is_NaN());
+ ASSERT_TRUE((one - nan).is_NaN());
+ ASSERT_TRUE((nan - nan).is_NaN());
+
+ ASSERT_EQ((big + one).value(), (1 << 30) + 1);
+ ASSERT_TRUE((big + big).is_NaN());
+ ASSERT_EQ((big - one).value(), (1 << 30) - 1);
+ ASSERT_EQ((big - big).value(), 0);
+
+ ASSERT_EQ((big - one + big).value(), max_jint);
+ ASSERT_EQ((zero - big - big).value(), min_jint);
+ ASSERT_TRUE((zero - big - big - one).is_NaN());
+}
+
+TEST_VM(opto, NoOverflowInt_mul) {
+ const NoOverflowInt nan;
+ const NoOverflowInt zero(0);
+ const NoOverflowInt one(1);
+ const NoOverflowInt two(2);
+ const NoOverflowInt big(1 << 30);
+
+ ASSERT_EQ((one * two).value(), 2);
+ ASSERT_TRUE((nan * one).is_NaN());
+ ASSERT_TRUE((one * nan).is_NaN());
+ ASSERT_TRUE((nan * nan).is_NaN());
+
+ ASSERT_EQ((big * one).value(), (1 << 30));
+ ASSERT_EQ((one * big).value(), (1 << 30));
+ ASSERT_EQ((big * zero).value(), 0);
+ ASSERT_EQ((zero * big).value(), 0);
+ ASSERT_TRUE((big * big).is_NaN());
+ ASSERT_TRUE((big * two).is_NaN());
+
+ ASSERT_EQ(((big - one) * two).value(), max_jint - 1);
+ ASSERT_EQ(((one - big) * two).value(), min_jint + 2);
+ ASSERT_EQ(((zero - big) * two).value(), min_jint);
+ ASSERT_TRUE(((big + one) * two).is_NaN());
+ ASSERT_TRUE(((zero - big - one) * two).is_NaN());
+}
+
+TEST_VM(opto, NoOverflowInt_lshift) {
+ const NoOverflowInt nan;
+ const NoOverflowInt zero(0);
+ const NoOverflowInt one(1);
+ const NoOverflowInt two(2);
+ const NoOverflowInt big(1 << 30);
+
+ for (int i = 0; i < 31; i++) {
+ ASSERT_EQ((one << NoOverflowInt(i)).value(), 1LL << i);
+ }
+ for (int i = 31; i < 1000; i++) {
+ ASSERT_TRUE((one << NoOverflowInt(i)).is_NaN());
+ }
+ for (int i = -1000; i < 0; i++) {
+ ASSERT_TRUE((one << NoOverflowInt(i)).is_NaN());
+ }
+
+ ASSERT_EQ((NoOverflowInt(3) << NoOverflowInt(2)).value(), 3 * 4);
+ ASSERT_EQ((NoOverflowInt(11) << NoOverflowInt(5)).value(), 11 * 32);
+ ASSERT_EQ((NoOverflowInt(-13) << NoOverflowInt(4)).value(), -13 * 16);
+}
+
+TEST_VM(opto, NoOverflowInt_misc) {
+ const NoOverflowInt nan;
+ const NoOverflowInt zero(0);
+ const NoOverflowInt one(1);
+ const NoOverflowInt two(2);
+ const NoOverflowInt big(1 << 30);
+
+ // operator==
+ ASSERT_FALSE(nan == nan);
+ ASSERT_FALSE(nan == zero);
+ ASSERT_FALSE(zero == nan);
+ ASSERT_TRUE(zero == zero);
+ ASSERT_TRUE(one == one);
+ ASSERT_TRUE((one + two) == (two + one));
+ ASSERT_TRUE((big + two) == (two + big));
+ ASSERT_FALSE((big + big) == (big + big));
+ ASSERT_TRUE((big - one + big) == (big - one + big));
+
+ // abs
+ for (int i = 0; i < (1 << 31); i += 1024) {
+ ASSERT_EQ(NoOverflowInt(i).abs().value(), i);
+ ASSERT_EQ(NoOverflowInt(-i).abs().value(), i);
+ }
+ ASSERT_EQ(NoOverflowInt(max_jint).abs().value(), max_jint);
+ ASSERT_EQ(NoOverflowInt(min_jint + 1).abs().value(), max_jint);
+ ASSERT_TRUE(NoOverflowInt(min_jint).abs().is_NaN());
+ ASSERT_TRUE(NoOverflowInt(nan).abs().is_NaN());
+
+ // is_multiple_of
+ ASSERT_TRUE(one.is_multiple_of(one));
+ ASSERT_FALSE(one.is_multiple_of(nan));
+ ASSERT_FALSE(nan.is_multiple_of(one));
+ ASSERT_FALSE(nan.is_multiple_of(nan));
+ for (int i = 0; i < (1 << 31); i += 1023) {
+ ASSERT_TRUE(NoOverflowInt(i).is_multiple_of(one));
+ ASSERT_TRUE(NoOverflowInt(-i).is_multiple_of(one));
+ ASSERT_FALSE(NoOverflowInt(i).is_multiple_of(zero));
+ ASSERT_FALSE(NoOverflowInt(-i).is_multiple_of(zero));
+ }
+ ASSERT_TRUE(NoOverflowInt(33 * 7).is_multiple_of(NoOverflowInt(33)));
+ ASSERT_TRUE(NoOverflowInt(13 * 5).is_multiple_of(NoOverflowInt(5)));
+ ASSERT_FALSE(NoOverflowInt(7).is_multiple_of(NoOverflowInt(5)));
+}
+
diff --git a/test/hotspot/jtreg/ProblemList-zgc.txt b/test/hotspot/jtreg/ProblemList-zgc.txt
index 7b2978ba491..0d4cfe1cbb6 100644
--- a/test/hotspot/jtreg/ProblemList-zgc.txt
+++ b/test/hotspot/jtreg/ProblemList-zgc.txt
@@ -116,3 +116,11 @@ serviceability/sa/sadebugd/RunCommandOnServerTest.java 8307393 generic-
serviceability/sa/sadebugd/SADebugDTest.java 8307393 generic-all
vmTestbase/gc/gctests/MemoryEaterMT/MemoryEaterMT.java 8289582 windows-x64
+
+compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/DataPatchTest.java 8343233 generic-all
+compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/InterpreterFrameSizeTest.java 8343233 generic-aarch64
+compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/MaxOopMapStackOffsetTest.java 8343233 generic-aarch64
+compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/NativeCallTest.java 8343233 generic-aarch64
+compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleCodeInstallationTest.java 8343233 generic-aarch64
+compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleDebugInfoTest.java 8343233 generic-aarch64
+compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/VirtualObjectDebugInfoTest.java 8343233 generic-aarch64
diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt
index 70497e6eaae..70b8c8eb85a 100644
--- a/test/hotspot/jtreg/ProblemList.txt
+++ b/test/hotspot/jtreg/ProblemList.txt
@@ -116,6 +116,10 @@ runtime/StackGuardPages/TestStackGuardPagesNative.java 8303612 linux-all
runtime/ErrorHandling/MachCodeFramesInErrorFile.java 8313315 linux-ppc64le
runtime/cds/appcds/customLoader/HelloCustom_JFR.java 8241075 linux-all,windows-x64
+# Fails with +UseCompactObjectHeaders on aarch64
+runtime/cds/appcds/SharedBaseAddress.java 8340212 linux-aarch64,macosx-aarch64
+runtime/cds/SharedBaseAddress.java 8340212 linux-aarch64,macosx-aarch64
+
applications/jcstress/copy.java 8229852 linux-all
containers/docker/TestJcmd.java 8278102 linux-all
diff --git a/test/hotspot/jtreg/TEST.groups b/test/hotspot/jtreg/TEST.groups
index 2b0b3236a5b..7ff9d800352 100644
--- a/test/hotspot/jtreg/TEST.groups
+++ b/test/hotspot/jtreg/TEST.groups
@@ -42,10 +42,6 @@ hotspot_compiler_xcomp = \
:hotspot_compiler \
-:tier1_compiler_not_xcomp
-hotspot_compiler_all_gcs = \
- :hotspot_compiler \
- -compiler/jvmci
-
hotspot_gc = \
gc
@@ -469,6 +465,7 @@ hotspot_appcds_dynamic = \
-runtime/cds/appcds/jcmd/JCmdTestStaticDump.java \
-runtime/cds/appcds/jcmd/JCmdTestDynamicDump.java \
-runtime/cds/appcds/jcmd/JCmdTestFileSafety.java \
+ -runtime/cds/appcds/jvmti/redefineClasses/OldClassAndRedefineClass.java \
-runtime/cds/appcds/lambdaForm/DefaultClassListLFInvokers.java \
-runtime/cds/appcds/methodHandles \
-runtime/cds/appcds/sharedStrings \
diff --git a/test/hotspot/jtreg/compiler/c2/TestCastX2NotProcessedIGVN.java b/test/hotspot/jtreg/compiler/c2/TestCastX2NotProcessedIGVN.java
new file mode 100644
index 00000000000..6ab45af39c5
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/c2/TestCastX2NotProcessedIGVN.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2024, Red Hat, Inc. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.c2;
+
+import compiler.lib.ir_framework.*;
+import jdk.internal.misc.Unsafe;
+
+/*
+ * @test
+ * @bug 8343068
+ * @summary C2: CastX2P Ideal transformation not always applied
+ * @modules java.base/jdk.internal.misc
+ * @library /test/lib /
+ * @run driver compiler.c2.TestCastX2NotProcessedIGVN
+ */
+
+public class TestCastX2NotProcessedIGVN {
+ private static final Unsafe UNSAFE = Unsafe.getUnsafe();
+ static int size = 1024;
+ static long base = UNSAFE.allocateMemory(4 * size);
+
+
+ public static void main(String[] args) {
+ TestFramework.runWithFlags("--add-modules", "java.base", "--add-exports", "java.base/jdk.internal.misc=ALL-UNNAMED");
+ }
+
+ @Test
+ @IR(failOn = IRNode.ADD_L, counts = {IRNode.ADD_P, "1"})
+ public static byte test1(long base) {
+ int offset = 0;
+ do {
+ offset++;
+ } while (offset < 100);
+ long longOffset = ((long) offset) * 2;
+ return UNSAFE.getByte(null, base + longOffset);
+ }
+
+ @Run(test = "test1")
+ public static void test1Runner() {
+ test1(base);
+ }
+
+ @Test
+ @IR(counts = {IRNode.LOAD_VECTOR_I, "> 1"})
+ public static int test2(int stop, int[] array) {
+ int v = 0;
+ stop = Math.min(stop, Integer.MAX_VALUE / 4);
+ for (int i = 0; i < stop; i++) {
+ long offset = ((long)i) * 4;
+ array[i] = UNSAFE.getInt(null, offset + base);
+ }
+ return v;
+ }
+
+ @Run(test = "test2")
+ public static void test2Runner() {
+ test2(size, new int[size]);
+ }
+}
diff --git a/test/hotspot/jtreg/compiler/c2/TestMatcherTwoImmOffsets.java b/test/hotspot/jtreg/compiler/c2/TestMatcherTwoImmOffsets.java
new file mode 100644
index 00000000000..16b9dc079a4
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/c2/TestMatcherTwoImmOffsets.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8339303
+ * @summary Test that the matcher does not create dead nodes when matching
+ * address expressions with two immediate offsets.
+ * @requires os.maxMemory > 4G
+ *
+ * @run main/othervm -Xmx4g -Xbatch -XX:-TieredCompilation
+ * -XX:CompileOnly=compiler.c2.TestMatcherTwoImmOffsets::test
+ * compiler.c2.TestMatcherTwoImmOffsets
+ */
+
+package compiler.c2;
+
+public class TestMatcherTwoImmOffsets {
+ static final int[] a1 = new int[10];
+ int[] a2;
+ static TestMatcherTwoImmOffsets o = new TestMatcherTwoImmOffsets();
+
+ public static void test() {
+ for (int i = 0; i < 10; i++) {
+ for (int j = 0; j < 100; j++) {
+ int[][] nArray = new int[10][];
+ for (int k = 0; k < nArray.length; k++) {}
+ }
+ for (long j = 1L; j < 3L; j++) {
+ a1[(int) j]--;
+ }
+ o.a2 = a1;
+ }
+ }
+
+ public static void main(String[] args) {
+ for (int i = 0; i < 10; i++) {
+ test();
+ }
+ }
+}
diff --git a/test/hotspot/jtreg/compiler/c2/TestMergeStores.java b/test/hotspot/jtreg/compiler/c2/TestMergeStores.java
index a94004d8e26..c8e8bd337ad 100644
--- a/test/hotspot/jtreg/compiler/c2/TestMergeStores.java
+++ b/test/hotspot/jtreg/compiler/c2/TestMergeStores.java
@@ -33,7 +33,7 @@
/*
* @test
- * @bug 8318446 8331054 8331311
+ * @bug 8318446 8331054 8331311 8335392
* @summary Test merging of consecutive stores
* @modules java.base/jdk.internal.misc
* @library /test/lib /
@@ -42,7 +42,7 @@
/*
* @test
- * @bug 8318446 8331054 8331311
+ * @bug 8318446 8331054 8331311 8335392
* @summary Test merging of consecutive stores
* @modules java.base/jdk.internal.misc
* @library /test/lib /
@@ -75,6 +75,17 @@ public class TestMergeStores {
long vL1;
long vL2;
+ static int zero0 = 0;
+ static int zero1 = 0;
+ static int zero2 = 0;
+ static int zero3 = 0;
+ static int zero4 = 0;
+ static int zero5 = 0;
+ static int zero6 = 0;
+ static int zero7 = 0;
+ static int zero8 = 0;
+ static int zero9 = 0;
+
interface TestFunction {
Object[] run(boolean isWarmUp, int rnd);
}
@@ -154,6 +165,15 @@ public TestMergeStores() {
testGroups.get("test7BE").put("test7RBE", (_,_) -> { return test7RBE(aB.clone(), offset1, vI1); });
testGroups.get("test7BE").put("test7aBE", (_,_) -> { return test7aBE(aB.clone(), offset1, vI1); });
+ testGroups.put("test10", new HashMap());
+ testGroups.get("test10").put("test10R", (_,_) -> { return test10R(aB.clone()); });
+ testGroups.get("test10").put("test10a", (_,_) -> { return test10a(aB.clone()); });
+ testGroups.get("test10").put("test10b", (_,_) -> { return test10b(aB.clone()); });
+ testGroups.get("test10").put("test10c", (_,_) -> { return test10c(aB.clone()); });
+ testGroups.get("test10").put("test10d", (_,_) -> { return test10d(aB.clone()); });
+ testGroups.get("test10").put("test10e", (_,_) -> { return test10e(aB.clone()); });
+ testGroups.get("test10").put("test10f", (_,_) -> { return test10f(aB.clone()); });
+
testGroups.put("test100", new HashMap());
testGroups.get("test100").put("test100R", (_,_) -> { return test100R(aS.clone(), offset1); });
testGroups.get("test100").put("test100a", (_,_) -> { return test100a(aS.clone(), offset1); });
@@ -234,6 +254,10 @@ public TestMergeStores() {
testGroups.get("test600").put("test600R", (_,i) -> { return test600R(aB.clone(), aI.clone(), i); });
testGroups.get("test600").put("test600a", (_,i) -> { return test600a(aB.clone(), aI.clone(), i); });
+ testGroups.put("test601", new HashMap());
+ testGroups.get("test601").put("test601R", (_,i) -> { return test601R(aB.clone(), aI.clone(), i, offset1); });
+ testGroups.get("test601").put("test601a", (_,i) -> { return test601a(aB.clone(), aI.clone(), i, offset1); });
+
testGroups.put("test700", new HashMap());
testGroups.get("test700").put("test700R", (_,i) -> { return test700R(aI.clone(), i); });
testGroups.get("test700").put("test700a", (_,i) -> { return test700a(aI.clone(), i); });
@@ -274,6 +298,12 @@ public TestMergeStores() {
"test5a",
"test6a",
"test7a",
+ "test10a",
+ "test10b",
+ "test10c",
+ "test10d",
+ "test10e",
+ "test10f",
"test7aBE",
"test100a",
"test101a",
@@ -292,6 +322,7 @@ public TestMergeStores() {
"test501aBE",
"test502aBE",
"test600a",
+ "test601a",
"test700a",
"test800a",
"test800aBE"})
@@ -611,9 +642,8 @@ static Object[] test1e(byte[] a) {
}
@Test
- // Disabled by JDK-8335390, to be enabled again by JDK-8335392.
- // @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"},
- // applyIf = {"UseUnalignedAccesses", "true"})
+ @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"},
+ applyIf = {"UseUnalignedAccesses", "true"})
static Object[] test1f(byte[] a) {
UNSAFE.putByte(a, UNSAFE.ARRAY_BYTE_BASE_OFFSET + 0, (byte)0xbe);
UNSAFE.putByte(a, UNSAFE.ARRAY_BYTE_BASE_OFFSET + 1, (byte)0xba);
@@ -1124,6 +1154,145 @@ static Object[] test7aBE(byte[] a, int offset1, int v1) {
return new Object[]{ a };
}
+ @DontCompile
+ static Object[] test10R(byte[] a) {
+ int zero = zero0 + zero1 + zero2 + zero3 + zero4
+ + zero5 + zero6 + zero7 + zero8 + zero9;
+ a[zero + 0] = 'h';
+ a[zero + 1] = 'e';
+ a[zero + 2] = 'l';
+ a[zero + 3] = 'l';
+ a[zero + 4] = 'o';
+ a[zero + 5] = ' ';
+ a[zero + 6] = ':';
+ a[zero + 7] = ')';
+ return new Object[]{ a };
+ }
+
+ @Test
+ @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "8", // no merge
+ IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0",
+ IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0",
+ IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"})
+ static Object[] test10a(byte[] a) {
+ // We have 11 summands: 10x zero variable + 1x array base.
+ // Parsing only allows 10 summands -> does not merge the stores.
+ int zero = zero0 + zero1 + zero2 + zero3 + zero4
+ + zero5 + zero6 + zero7 + zero8 + zero9;
+ a[zero + 0] = 'h';
+ a[zero + 1] = 'e';
+ a[zero + 2] = 'l';
+ a[zero + 3] = 'l';
+ a[zero + 4] = 'o';
+ a[zero + 5] = ' ';
+ a[zero + 6] = ':';
+ a[zero + 7] = ')';
+ return new Object[]{ a };
+ }
+
+ @Test
+ @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", // 1 left in uncommon trap path of RangeCheck
+ IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0",
+ IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0",
+ IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, // all merged
+ applyIf = {"UseUnalignedAccesses", "true"})
+ static Object[] test10b(byte[] a) {
+ int zero = zero0 + zero1 + zero2 + zero3 + zero4
+ + zero5 + zero6 + zero7 + zero8;
+ // We have 10 summands: 9x zero variable + 1x array base.
+ // Parsing allows 10 summands, so this should merge the stores.
+ a[zero + 0] = 'h';
+ a[zero + 1] = 'e';
+ a[zero + 2] = 'l';
+ a[zero + 3] = 'l';
+ a[zero + 4] = 'o';
+ a[zero + 5] = ' ';
+ a[zero + 6] = ':';
+ a[zero + 7] = ')';
+ return new Object[]{ a };
+ }
+
+ @Test
+ @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", // 1 left in uncommon trap path of RangeCheck
+ IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0",
+ IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0",
+ IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, // all merged
+ applyIf = {"UseUnalignedAccesses", "true"})
+ static Object[] test10c(byte[] a) {
+ int zero = 7 * zero0 + 7 * zero1 + 7 * zero2 + 7 * zero3 + 7 * zero4
+ + 7 * zero5 + 7 * zero6 + 7 * zero7 + 7 * zero8;
+ // The "7 * zero" is split into "zero << 3 - zero". But the parsing combines it again, lowering the summand count.
+ // We have 10 summands: 9x zero variable + 1x array base.
+ // Parsing allows 10 summands, so this should merge the stores.
+ a[zero + 0] = 'h';
+ a[zero + 1] = 'e';
+ a[zero + 2] = 'l';
+ a[zero + 3] = 'l';
+ a[zero + 4] = 'o';
+ a[zero + 5] = ' ';
+ a[zero + 6] = ':';
+ a[zero + 7] = ')';
+ return new Object[]{ a };
+ }
+
+ @Test
+ @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0",
+ IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0",
+ IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0",
+ IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, // all merged
+ applyIf = {"UseUnalignedAccesses", "true"})
+ static Object[] test10d(byte[] a) {
+ // Summand is subtracted from itself -> scale = 0 -> should be removed from list.
+ UNSAFE.putByte(a, UNSAFE.ARRAY_BYTE_BASE_OFFSET + (long)(zero0 + 0) - zero0, (byte)'h');
+ UNSAFE.putByte(a, UNSAFE.ARRAY_BYTE_BASE_OFFSET + (long)(zero0 + 1) - zero0, (byte)'e');
+ UNSAFE.putByte(a, UNSAFE.ARRAY_BYTE_BASE_OFFSET + (long)(zero0 + 2) - zero0, (byte)'l');
+ UNSAFE.putByte(a, UNSAFE.ARRAY_BYTE_BASE_OFFSET + (long)(zero0 + 3) - zero0, (byte)'l');
+ UNSAFE.putByte(a, UNSAFE.ARRAY_BYTE_BASE_OFFSET + (long)(zero0 + 4) - zero0, (byte)'o');
+ UNSAFE.putByte(a, UNSAFE.ARRAY_BYTE_BASE_OFFSET + (long)(zero0 + 5) - zero0, (byte)' ');
+ UNSAFE.putByte(a, UNSAFE.ARRAY_BYTE_BASE_OFFSET + (long)(zero0 + 6) - zero0, (byte)':');
+ UNSAFE.putByte(a, UNSAFE.ARRAY_BYTE_BASE_OFFSET + (long)(zero0 + 7) - zero0, (byte)')');
+ return new Object[]{ a };
+ }
+
+ @Test
+ @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0",
+ IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0",
+ IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0",
+ IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, // all merged
+ applyIf = {"UseUnalignedAccesses", "true"})
+ static Object[] test10e(byte[] a) {
+ // Summand is subtracted from itself -> scale = 0 -> should be removed from list. Thus equal to if not present at all.
+ UNSAFE.putByte(a, UNSAFE.ARRAY_BYTE_BASE_OFFSET + (long)(zero0 + 0) - zero0, (byte)'h');
+ UNSAFE.putByte(a, UNSAFE.ARRAY_BYTE_BASE_OFFSET + (long)(zero0 + 1) - zero0, (byte)'e');
+ UNSAFE.putByte(a, UNSAFE.ARRAY_BYTE_BASE_OFFSET + (long)(zero0 + 2) - zero0, (byte)'l');
+ UNSAFE.putByte(a, UNSAFE.ARRAY_BYTE_BASE_OFFSET + (long)(zero0 + 3) - zero0, (byte)'l');
+ UNSAFE.putByte(a, UNSAFE.ARRAY_BYTE_BASE_OFFSET + 4, (byte)'o');
+ UNSAFE.putByte(a, UNSAFE.ARRAY_BYTE_BASE_OFFSET + 5, (byte)' ');
+ UNSAFE.putByte(a, UNSAFE.ARRAY_BYTE_BASE_OFFSET + 6, (byte)':');
+ UNSAFE.putByte(a, UNSAFE.ARRAY_BYTE_BASE_OFFSET + 7, (byte)')');
+ return new Object[]{ a };
+ }
+
+ @Test
+ @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "8", // no merge
+ IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0",
+ IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0",
+ IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"})
+ static Object[] test10f(byte[] a) {
+ int big = 1 << 29;
+ // Adding up the scales overflows -> no merge.
+ long offset = zero9 * big + zero9 * big + zero9 * big + zero9 * big;
+ UNSAFE.putByte(a, UNSAFE.ARRAY_BYTE_BASE_OFFSET + offset + 0, (byte)'h');
+ UNSAFE.putByte(a, UNSAFE.ARRAY_BYTE_BASE_OFFSET + offset + 1, (byte)'e');
+ UNSAFE.putByte(a, UNSAFE.ARRAY_BYTE_BASE_OFFSET + offset + 2, (byte)'l');
+ UNSAFE.putByte(a, UNSAFE.ARRAY_BYTE_BASE_OFFSET + offset + 3, (byte)'l');
+ UNSAFE.putByte(a, UNSAFE.ARRAY_BYTE_BASE_OFFSET + offset + 4, (byte)'o');
+ UNSAFE.putByte(a, UNSAFE.ARRAY_BYTE_BASE_OFFSET + offset + 5, (byte)' ');
+ UNSAFE.putByte(a, UNSAFE.ARRAY_BYTE_BASE_OFFSET + offset + 6, (byte)':');
+ UNSAFE.putByte(a, UNSAFE.ARRAY_BYTE_BASE_OFFSET + offset + 7, (byte)')');
+ return new Object[]{ a };
+ }
+
@DontCompile
static Object[] test100R(short[] a, int offset) {
a[offset + 0] = (short)0x0100;
@@ -1560,15 +1729,12 @@ static Object[] test400R(int[] a) {
}
@Test
- // We must be careful with mismatched accesses on arrays:
- // An int-array can have about 2x max_int size, and hence if we address bytes in it, we can have int-overflows.
- // We might consider addresses (x + 0) and (x + 1) as adjacent, even if x = max_int, and therefore the second
- // address overflows and is not adjacent at all.
- // Therefore, we should only consider stores that have the same size as the element type of the array.
- @IR(counts = {IRNode.STORE_B_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "8", // no merging
+ // All constants are known, and AddI can be converted to AddL safely, hence the stores can be merged.
+ @IR(counts = {IRNode.STORE_B_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0",
IRNode.STORE_C_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0",
IRNode.STORE_I_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0",
- IRNode.STORE_L_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"})
+ IRNode.STORE_L_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, // all merged
+ applyIf = {"UseUnalignedAccesses", "true"})
static Object[] test400a(int[] a) {
UNSAFE.putByte(a, UNSAFE.ARRAY_INT_BASE_OFFSET + 0, (byte)0xbe);
UNSAFE.putByte(a, UNSAFE.ARRAY_INT_BASE_OFFSET + 1, (byte)0xba);
@@ -1858,7 +2024,11 @@ static Object[] test600R(byte[] aB, int[] aI, int i) {
}
@Test
- @IR(counts = {IRNode.STORE_B_OF_CLASS, "bottom\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "8"}) // note: bottom type
+ @IR(counts = {IRNode.STORE_B_OF_CLASS, "bottom\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0",
+ IRNode.STORE_C_OF_CLASS, "bottom\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0",
+ IRNode.STORE_I_OF_CLASS, "bottom\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0",
+ IRNode.STORE_L_OF_CLASS, "bottom\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, // all merged
+ applyIf = {"UseUnalignedAccesses", "true"})
static Object[] test600a(byte[] aB, int[] aI, int i) {
Object a = null;
long base = 0;
@@ -1869,7 +2039,7 @@ static Object[] test600a(byte[] aB, int[] aI, int i) {
a = aI;
base = UNSAFE.ARRAY_INT_BASE_OFFSET;
}
- // array a is an aryptr, but its element type is unknown, i.e. bottom.
+ // Array type is unknown, i.e. bottom[]. But all AddI can be safely converted to AddL -> safe to merge.
UNSAFE.putByte(a, base + 0, (byte)0xbe);
UNSAFE.putByte(a, base + 1, (byte)0xba);
UNSAFE.putByte(a, base + 2, (byte)0xad);
@@ -1881,6 +2051,63 @@ static Object[] test600a(byte[] aB, int[] aI, int i) {
return new Object[]{ aB, aI };
}
+ @DontCompile
+ static Object[] test601R(byte[] aB, int[] aI, int i, int offset1) {
+ Object a = null;
+ long base = 0;
+ if (i % 2 == 0) {
+ a = aB;
+ base = UNSAFE.ARRAY_BYTE_BASE_OFFSET;
+ } else {
+ a = aI;
+ base = UNSAFE.ARRAY_INT_BASE_OFFSET;
+ }
+ UNSAFE.putByte(a, base + (offset1 + 0), (byte)0xbe);
+ UNSAFE.putByte(a, base + (offset1 + 1), (byte)0xba);
+ UNSAFE.putByte(a, base + (offset1 + 2), (byte)0xad);
+ UNSAFE.putByte(a, base + (offset1 + 3), (byte)0xba);
+ UNSAFE.putByte(a, base + (offset1 + 4), (byte)0xef);
+ UNSAFE.putByte(a, base + (offset1 + 5), (byte)0xbe);
+ UNSAFE.putByte(a, base + (offset1 + 6), (byte)0xad);
+ UNSAFE.putByte(a, base + (offset1 + 7), (byte)0xde);
+ return new Object[]{ aB, aI };
+ }
+
+ @Test
+ @IR(counts = {IRNode.STORE_B_OF_CLASS, "bottom\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "8", // nothing merged
+ IRNode.STORE_C_OF_CLASS, "bottom\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0",
+ IRNode.STORE_I_OF_CLASS, "bottom\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0",
+ IRNode.STORE_L_OF_CLASS, "bottom\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"},
+ applyIfPlatform = {"64-bit", "true"})
+ @IR(counts = {IRNode.STORE_B_OF_CLASS, "bottom\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0",
+ IRNode.STORE_C_OF_CLASS, "bottom\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0",
+ IRNode.STORE_I_OF_CLASS, "bottom\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0",
+ IRNode.STORE_L_OF_CLASS, "bottom\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, // all merged
+ applyIf = {"UseUnalignedAccesses", "true"},
+ applyIfPlatform = {"32-bit", "true"})
+ static Object[] test601a(byte[] aB, int[] aI, int i, int offset1) {
+ Object a = null;
+ long base = 0;
+ if (i % 2 == 0) {
+ a = aB;
+ base = UNSAFE.ARRAY_BYTE_BASE_OFFSET;
+ } else {
+ a = aI;
+ base = UNSAFE.ARRAY_INT_BASE_OFFSET;
+ }
+ // Array type is unknown, i.e. bottom[]. Hence we do not know the element size of the array.
+ // Thus, on 64-bits systems merging is not safe, there could be overflows.
+ UNSAFE.putByte(a, base + (offset1 + 0), (byte)0xbe);
+ UNSAFE.putByte(a, base + (offset1 + 1), (byte)0xba);
+ UNSAFE.putByte(a, base + (offset1 + 2), (byte)0xad);
+ UNSAFE.putByte(a, base + (offset1 + 3), (byte)0xba);
+ UNSAFE.putByte(a, base + (offset1 + 4), (byte)0xef);
+ UNSAFE.putByte(a, base + (offset1 + 5), (byte)0xbe);
+ UNSAFE.putByte(a, base + (offset1 + 6), (byte)0xad);
+ UNSAFE.putByte(a, base + (offset1 + 7), (byte)0xde);
+ return new Object[]{ aB, aI };
+ }
+
@DontCompile
static Object[] test700R(int[] a, long v1) {
a[0] = (int)(v1 >> -1);
diff --git a/test/hotspot/jtreg/compiler/c2/TestMergeStoresMemorySegment.java b/test/hotspot/jtreg/compiler/c2/TestMergeStoresMemorySegment.java
new file mode 100644
index 00000000000..a5302d1b515
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/c2/TestMergeStoresMemorySegment.java
@@ -0,0 +1,426 @@
+/*
+ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.c2;
+
+import compiler.lib.ir_framework.*;
+import jdk.test.lib.Utils;
+import java.nio.ByteBuffer;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Random;
+import java.lang.foreign.*;
+
+/*
+ * @test id=byte-array
+ * @bug 8335392
+ * @summary Test MergeStores optimization for MemorySegment
+ * @library /test/lib /
+ * @run driver compiler.c2.TestMergeStoresMemorySegment ByteArray
+ */
+
+/*
+ * @test id=char-array
+ * @bug 8335392
+ * @summary Test MergeStores optimization for MemorySegment
+ * @library /test/lib /
+ * @run driver compiler.c2.TestMergeStoresMemorySegment CharArray
+ */
+
+/*
+ * @test id=short-array
+ * @bug 8335392
+ * @summary Test MergeStores optimization for MemorySegment
+ * @library /test/lib /
+ * @run driver compiler.c2.TestMergeStoresMemorySegment ShortArray
+ */
+
+/*
+ * @test id=int-array
+ * @bug 8335392
+ * @summary Test MergeStores optimization for MemorySegment
+ * @library /test/lib /
+ * @run driver compiler.c2.TestMergeStoresMemorySegment IntArray
+ */
+
+/*
+ * @test id=long-array
+ * @bug 8335392
+ * @summary Test MergeStores optimization for MemorySegment
+ * @library /test/lib /
+ * @run driver compiler.c2.TestMergeStoresMemorySegment LongArray
+ */
+
+/*
+ * @test id=float-array
+ * @bug 8335392
+ * @summary Test MergeStores optimization for MemorySegment
+ * @library /test/lib /
+ * @run driver compiler.c2.TestMergeStoresMemorySegment FloatArray
+ */
+
+/*
+ * @test id=double-array
+ * @bug 8335392
+ * @summary Test MergeStores optimization for MemorySegment
+ * @library /test/lib /
+ * @run driver compiler.c2.TestMergeStoresMemorySegment DoubleArray
+ */
+
+/*
+ * @test id=byte-buffer
+ * @bug 8335392
+ * @summary Test MergeStores optimization for MemorySegment
+ * @library /test/lib /
+ * @run driver compiler.c2.TestMergeStoresMemorySegment ByteBuffer
+ */
+
+/*
+ * @test id=byte-buffer-direct
+ * @bug 8335392
+ * @summary Test MergeStores optimization for MemorySegment
+ * @library /test/lib /
+ * @run driver compiler.c2.TestMergeStoresMemorySegment ByteBufferDirect
+ */
+
+/*
+ * @test id=native
+ * @bug 8335392
+ * @summary Test MergeStores optimization for MemorySegment
+ * @library /test/lib /
+ * @run driver compiler.c2.TestMergeStoresMemorySegment Native
+ */
+
+// FAILS: mixed providers currently do not merge stores. Maybe there is some inlining issue.
+// /*
+// * @test id=mixed-array
+// * @bug 8335392
+// * @summary Test MergeStores optimization for MemorySegment
+// * @library /test/lib /
+// * @run driver compiler.c2.TestMergeStoresMemorySegment MixedArray
+// */
+//
+// /*
+// * @test id=MixedBuffer
+// * @bug 8335392
+// * @summary Test MergeStores optimization for MemorySegment
+// * @library /test/lib /
+// * @run driver compiler.c2.TestMergeStoresMemorySegment MixedBuffer
+// */
+//
+// /*
+// * @test id=mixed
+// * @bug 8335392
+// * @summary Test MergeStores optimization for MemorySegment
+// * @library /test/lib /
+// * @run driver compiler.c2.TestMergeStoresMemorySegment Mixed
+// */
+
+public class TestMergeStoresMemorySegment {
+ public static void main(String[] args) {
+ for (String unaligned : new String[]{"-XX:-UseUnalignedAccesses", "-XX:+UseUnalignedAccesses"}) {
+ TestFramework framework = new TestFramework(TestMergeStoresMemorySegmentImpl.class);
+ framework.addFlags("-DmemorySegmentProviderNameForTestVM=" + args[0], unaligned);
+ framework.start();
+ }
+ }
+}
+
+class TestMergeStoresMemorySegmentImpl {
+ static final int BACKING_SIZE = 1024 * 8;
+ static final Random RANDOM = Utils.getRandomInstance();
+
+ private static final String START = "(\\d+(\\s){2}(";
+ private static final String MID = ".*)+(\\s){2}===.*";
+ private static final String END = ")";
+
+ // Custom Regex: allows us to only match Store that come from MemorySegment internals.
+ private static final String REGEX_STORE_B_TO_MS_FROM_B = START + "StoreB" + MID + END + "ScopedMemoryAccess::putByteInternal";
+ private static final String REGEX_STORE_C_TO_MS_FROM_B = START + "StoreC" + MID + END + "ScopedMemoryAccess::putByteInternal";
+ private static final String REGEX_STORE_I_TO_MS_FROM_B = START + "StoreI" + MID + END + "ScopedMemoryAccess::putByteInternal";
+ private static final String REGEX_STORE_L_TO_MS_FROM_B = START + "StoreL" + MID + END + "ScopedMemoryAccess::putByteInternal";
+
+ interface TestFunction {
+ Object[] run();
+ }
+
+ interface MemorySegmentProvider {
+ MemorySegment newMemorySegment();
+ }
+
+ static MemorySegmentProvider provider;
+
+ static {
+ String providerName = System.getProperty("memorySegmentProviderNameForTestVM");
+ provider = switch (providerName) {
+ case "ByteArray" -> TestMergeStoresMemorySegmentImpl::newMemorySegmentOfByteArray;
+ case "CharArray" -> TestMergeStoresMemorySegmentImpl::newMemorySegmentOfCharArray;
+ case "ShortArray" -> TestMergeStoresMemorySegmentImpl::newMemorySegmentOfShortArray;
+ case "IntArray" -> TestMergeStoresMemorySegmentImpl::newMemorySegmentOfIntArray;
+ case "LongArray" -> TestMergeStoresMemorySegmentImpl::newMemorySegmentOfLongArray;
+ case "FloatArray" -> TestMergeStoresMemorySegmentImpl::newMemorySegmentOfFloatArray;
+ case "DoubleArray" -> TestMergeStoresMemorySegmentImpl::newMemorySegmentOfDoubleArray;
+ case "ByteBuffer" -> TestMergeStoresMemorySegmentImpl::newMemorySegmentOfByteBuffer;
+ case "ByteBufferDirect" -> TestMergeStoresMemorySegmentImpl::newMemorySegmentOfByteBufferDirect;
+ case "Native" -> TestMergeStoresMemorySegmentImpl::newMemorySegmentOfNative;
+ case "MixedArray" -> TestMergeStoresMemorySegmentImpl::newMemorySegmentOfMixedArray;
+ case "MixedBuffer" -> TestMergeStoresMemorySegmentImpl::newMemorySegmentOfMixedBuffer;
+ case "Mixed" -> TestMergeStoresMemorySegmentImpl::newMemorySegmentOfMixed;
+ default -> throw new RuntimeException("Test argument not recognized: " + providerName);
+ };
+ }
+
+ // List of tests
+ Map tests = new HashMap<>();
+
+ // List of golden values, the results from the first run before compilation
+ Map golds = new HashMap<>();
+
+ public TestMergeStoresMemorySegmentImpl () {
+ // Generate two MemorySegments as inputs
+ MemorySegment a = newMemorySegment();
+ MemorySegment b = newMemorySegment();
+ fillRandom(a);
+ fillRandom(b);
+
+ // Future Work: add more test cases. For now, the issue seems to be that
+ // RangeCheck smearing does not remove the RangeChecks, thus
+ // we can only ever merge two stores.
+ //
+ // Ideas for more test cases, once they are better optimized:
+ //
+ // Have about 3 variables, each either int or long. Add all in int or
+ // long. Give them different scales. Compute the address in the same
+ // expression or separately. Use different element store sizes (BCIL).
+ //
+ tests.put("test_xxx", () -> test_xxx(copy(a), 5, 11, 31));
+ tests.put("test_yyy", () -> test_yyy(copy(a), 5, 11, 31));
+ tests.put("test_zzz", () -> test_zzz(copy(a), 5, 11, 31));
+
+ // Compute gold value for all test methods before compilation
+ for (Map.Entry entry : tests.entrySet()) {
+ String name = entry.getKey();
+ TestFunction test = entry.getValue();
+ Object[] gold = test.run();
+ golds.put(name, gold);
+ }
+ }
+
+ MemorySegment newMemorySegment() {
+ return provider.newMemorySegment();
+ }
+
+ MemorySegment copy(MemorySegment src) {
+ MemorySegment dst = newMemorySegment();
+ MemorySegment.copy(src, 0, dst, 0, src.byteSize());
+ return dst;
+ }
+
+ static MemorySegment newMemorySegmentOfByteArray() {
+ return MemorySegment.ofArray(new byte[BACKING_SIZE]);
+ }
+
+ static MemorySegment newMemorySegmentOfCharArray() {
+ return MemorySegment.ofArray(new char[BACKING_SIZE / 2]);
+ }
+
+ static MemorySegment newMemorySegmentOfShortArray() {
+ return MemorySegment.ofArray(new short[BACKING_SIZE / 2]);
+ }
+
+ static MemorySegment newMemorySegmentOfIntArray() {
+ return MemorySegment.ofArray(new int[BACKING_SIZE / 4]);
+ }
+
+ static MemorySegment newMemorySegmentOfLongArray() {
+ return MemorySegment.ofArray(new long[BACKING_SIZE / 8]);
+ }
+
+ static MemorySegment newMemorySegmentOfFloatArray() {
+ return MemorySegment.ofArray(new float[BACKING_SIZE / 4]);
+ }
+
+ static MemorySegment newMemorySegmentOfDoubleArray() {
+ return MemorySegment.ofArray(new double[BACKING_SIZE / 8]);
+ }
+
+ static MemorySegment newMemorySegmentOfByteBuffer() {
+ return MemorySegment.ofBuffer(ByteBuffer.allocate(BACKING_SIZE));
+ }
+
+ static MemorySegment newMemorySegmentOfByteBufferDirect() {
+ return MemorySegment.ofBuffer(ByteBuffer.allocateDirect(BACKING_SIZE));
+ }
+
+ static MemorySegment newMemorySegmentOfNative() {
+ // Auto arena: GC decides when there is no reference to the MemorySegment,
+ // and then it deallocates the backing memory.
+ return Arena.ofAuto().allocate(BACKING_SIZE, 1);
+ }
+
+ static MemorySegment newMemorySegmentOfMixedArray() {
+ switch(RANDOM.nextInt(7)) {
+ case 0 -> { return newMemorySegmentOfByteArray(); }
+ case 1 -> { return newMemorySegmentOfCharArray(); }
+ case 2 -> { return newMemorySegmentOfShortArray(); }
+ case 3 -> { return newMemorySegmentOfIntArray(); }
+ case 4 -> { return newMemorySegmentOfLongArray(); }
+ case 5 -> { return newMemorySegmentOfFloatArray(); }
+ default -> { return newMemorySegmentOfDoubleArray(); }
+ }
+ }
+
+ static MemorySegment newMemorySegmentOfMixedBuffer() {
+ switch (RANDOM.nextInt(2)) {
+ case 0 -> { return newMemorySegmentOfByteBuffer(); }
+ default -> { return newMemorySegmentOfByteBufferDirect(); }
+ }
+ }
+
+ static MemorySegment newMemorySegmentOfMixed() {
+ switch (RANDOM.nextInt(3)) {
+ case 0 -> { return newMemorySegmentOfMixedArray(); }
+ case 1 -> { return newMemorySegmentOfMixedBuffer(); }
+ default -> { return newMemorySegmentOfNative(); }
+ }
+ }
+
+ static void fillRandom(MemorySegment data) {
+ for (int i = 0; i < (int)data.byteSize(); i += 8) {
+ data.set(ValueLayout.JAVA_LONG_UNALIGNED, i, RANDOM.nextLong());
+ }
+ }
+
+
+ static void verify(String name, Object[] gold, Object[] result) {
+ if (gold.length != result.length) {
+ throw new RuntimeException("verify " + name + ": not the same number of outputs: gold.length = " +
+ gold.length + ", result.length = " + result.length);
+ }
+ for (int i = 0; i < gold.length; i++) {
+ Object g = gold[i];
+ Object r = result[i];
+ if (g == r) {
+ throw new RuntimeException("verify " + name + ": should be two separate objects (with identical content):" +
+ " gold[" + i + "] == result[" + i + "]");
+ }
+
+ if (!(g instanceof MemorySegment && r instanceof MemorySegment)) {
+ throw new RuntimeException("verify " + name + ": only MemorySegment supported, i=" + i);
+ }
+
+ MemorySegment mg = (MemorySegment)g;
+ MemorySegment mr = (MemorySegment)r;
+
+ if (mg.byteSize() != mr.byteSize()) {
+ throw new RuntimeException("verify " + name + ": MemorySegment must have same byteSize:" +
+ " gold[" + i + "].byteSize = " + mg.byteSize() +
+ " result[" + i + "].byteSize = " + mr.byteSize());
+ }
+
+ for (int j = 0; j < (int)mg.byteSize(); j++) {
+ byte vg = mg.get(ValueLayout.JAVA_BYTE, j);
+ byte vr = mr.get(ValueLayout.JAVA_BYTE, j);
+ if (vg != vr) {
+ throw new RuntimeException("verify " + name + ": MemorySegment must have same content:" +
+ " gold[" + i + "][" + j + "] = " + vg +
+ " result[" + i + "][" + j + "] = " + vr);
+ }
+ }
+ }
+ }
+
+ @Run(test = { "test_xxx", "test_yyy", "test_zzz" })
+ void runTests() {
+ for (Map.Entry entry : tests.entrySet()) {
+ String name = entry.getKey();
+ TestFunction test = entry.getValue();
+ // Recall gold value from before compilation
+ Object[] gold = golds.get(name);
+ // Compute new result
+ Object[] result = test.run();
+ // Compare gold and new result
+ verify(name, gold, result);
+ }
+ }
+
+ @Test
+ @IR(counts = {REGEX_STORE_B_TO_MS_FROM_B, "<=5", // 4x RC
+ REGEX_STORE_C_TO_MS_FROM_B, ">=3", // 4x merged
+ REGEX_STORE_I_TO_MS_FROM_B, "0",
+ REGEX_STORE_L_TO_MS_FROM_B, "0"},
+ phase = CompilePhase.PRINT_IDEAL,
+ applyIf = {"UseUnalignedAccesses", "true"})
+ static Object[] test_xxx(MemorySegment a, int xI, int yI, int zI) {
+ // All RangeChecks remain -> RC smearing not good enough?
+ a.set(ValueLayout.JAVA_BYTE, (long)(xI + yI + zI + 0), (byte)'h');
+ a.set(ValueLayout.JAVA_BYTE, (long)(xI + yI + zI + 1), (byte)'e');
+ a.set(ValueLayout.JAVA_BYTE, (long)(xI + yI + zI + 2), (byte)'l');
+ a.set(ValueLayout.JAVA_BYTE, (long)(xI + yI + zI + 3), (byte)'l');
+ a.set(ValueLayout.JAVA_BYTE, (long)(xI + yI + zI + 4), (byte)'o');
+ a.set(ValueLayout.JAVA_BYTE, (long)(xI + yI + zI + 5), (byte)' ');
+ a.set(ValueLayout.JAVA_BYTE, (long)(xI + yI + zI + 6), (byte)':');
+ a.set(ValueLayout.JAVA_BYTE, (long)(xI + yI + zI + 7), (byte)')');
+ return new Object[]{ a };
+ }
+
+ @Test
+ @IR(counts = {REGEX_STORE_B_TO_MS_FROM_B, "<=5", // 4x RC
+ REGEX_STORE_C_TO_MS_FROM_B, ">=3", // 4x merged
+ REGEX_STORE_I_TO_MS_FROM_B, "0",
+ REGEX_STORE_L_TO_MS_FROM_B, "0"},
+ phase = CompilePhase.PRINT_IDEAL,
+ applyIf = {"UseUnalignedAccesses", "true"})
+ static Object[] test_yyy(MemorySegment a, int xI, int yI, int zI) {
+ // All RangeChecks remain -> RC smearing not good enough?
+ a.set(ValueLayout.JAVA_BYTE, (long)(xI) + (long)(yI) + (long)(zI) + 0L, (byte)'h');
+ a.set(ValueLayout.JAVA_BYTE, (long)(xI) + (long)(yI) + (long)(zI) + 1L, (byte)'e');
+ a.set(ValueLayout.JAVA_BYTE, (long)(xI) + (long)(yI) + (long)(zI) + 2L, (byte)'l');
+ a.set(ValueLayout.JAVA_BYTE, (long)(xI) + (long)(yI) + (long)(zI) + 3L, (byte)'l');
+ a.set(ValueLayout.JAVA_BYTE, (long)(xI) + (long)(yI) + (long)(zI) + 4L, (byte)'o');
+ a.set(ValueLayout.JAVA_BYTE, (long)(xI) + (long)(yI) + (long)(zI) + 5L, (byte)' ');
+ a.set(ValueLayout.JAVA_BYTE, (long)(xI) + (long)(yI) + (long)(zI) + 6L, (byte)':');
+ a.set(ValueLayout.JAVA_BYTE, (long)(xI) + (long)(yI) + (long)(zI) + 7L, (byte)')');
+ return new Object[]{ a };
+ }
+
+ @Test
+ @IR(counts = {REGEX_STORE_B_TO_MS_FROM_B, "<=5", // 4x RC
+ REGEX_STORE_C_TO_MS_FROM_B, ">=3", // 4x merged
+ REGEX_STORE_I_TO_MS_FROM_B, "0",
+ REGEX_STORE_L_TO_MS_FROM_B, "0"},
+ phase = CompilePhase.PRINT_IDEAL,
+ applyIf = {"UseUnalignedAccesses", "true"})
+ static Object[] test_zzz(MemorySegment a, long xL, long yL, long zL) {
+ // All RangeChecks remain -> RC smearing not good enough?
+ a.set(ValueLayout.JAVA_BYTE, xL + yL + zL + 0L, (byte)'h');
+ a.set(ValueLayout.JAVA_BYTE, xL + yL + zL + 1L, (byte)'e');
+ a.set(ValueLayout.JAVA_BYTE, xL + yL + zL + 2L, (byte)'l');
+ a.set(ValueLayout.JAVA_BYTE, xL + yL + zL + 3L, (byte)'l');
+ a.set(ValueLayout.JAVA_BYTE, xL + yL + zL + 4L, (byte)'o');
+ a.set(ValueLayout.JAVA_BYTE, xL + yL + zL + 5L, (byte)' ');
+ a.set(ValueLayout.JAVA_BYTE, xL + yL + zL + 6L, (byte)':');
+ a.set(ValueLayout.JAVA_BYTE, xL + yL + zL + 7L, (byte)')');
+ return new Object[]{ a };
+ }
+}
diff --git a/test/hotspot/jtreg/compiler/c2/TestMergeStoresUnsafeArrayPointer.java b/test/hotspot/jtreg/compiler/c2/TestMergeStoresUnsafeArrayPointer.java
index dbfdfe68957..3b65272c3c7 100644
--- a/test/hotspot/jtreg/compiler/c2/TestMergeStoresUnsafeArrayPointer.java
+++ b/test/hotspot/jtreg/compiler/c2/TestMergeStoresUnsafeArrayPointer.java
@@ -52,6 +52,10 @@ public class TestMergeStoresUnsafeArrayPointer {
static final long ANCHOR = BYTE_SIZE / 2;
static int four = 4;
+ static int max_int = Integer.MAX_VALUE;
+ static int min_int = Integer.MIN_VALUE;
+ static int val_2_to_30 = (1 << 30);
+ static int large_by_53 = (int)((1L << 31) / 53L + 1L);
public static void main(String[] args) {
System.out.println("Allocate big array of SIZE = " + SIZE);
@@ -95,6 +99,103 @@ public static void main(String[] args) {
}
}
+ val = 0;
+ System.out.println("test3");
+ for (int i = 0; i < 100_000; i++) {
+ testClear(big);
+ test3(big, ANCHOR);
+ long sum = testSum(big);
+ if (i == 0) {
+ val = sum;
+ } else {
+ if (sum != val) {
+ System.out.println("ERROR: test3 had wrong value: " + val + " != " + sum);
+ errors++;
+ break;
+ }
+ }
+ }
+
+ val = 0;
+ System.out.println("test4");
+ for (int i = 0; i < 100_000; i++) {
+ testClear(big);
+ test4(big, ANCHOR);
+ long sum = testSum(big);
+ if (i == 0) {
+ val = sum;
+ } else {
+ if (sum != val) {
+ System.out.println("ERROR: test4 had wrong value: " + val + " != " + sum);
+ errors++;
+ break;
+ }
+ }
+ }
+
+ val = 0;
+ System.out.println("test5");
+ for (int i = 0; i < 100_000; i++) {
+ testClear(big);
+ test5(big, ANCHOR);
+ long sum = testSum(big);
+ if (i == 0) {
+ val = sum;
+ } else {
+ if (sum != val) {
+ System.out.println("ERROR: test5 had wrong value: " + val + " != " + sum);
+ errors++;
+ break;
+ }
+ }
+ }
+
+ val = 0;
+ System.out.println("test6");
+ for (int i = 0; i < 100_000; i++) {
+ testClear(big);
+ test6(big, ANCHOR);
+ long sum = testSum(big);
+ if (i == 0) {
+ val = sum;
+ } else {
+ if (sum != val) {
+ System.out.println("ERROR: test6 had wrong value: " + val + " != " + sum);
+ errors++;
+ break;
+ }
+ }
+ }
+
+ val = 0;
+ System.out.println("test7");
+ for (int i = 0; i < 100_000; i++) {
+ testClear(big);
+ test7(big, ANCHOR);
+ long sum = testSum(big);
+ if (i == 0) {
+ val = sum;
+ } else {
+ if (sum != val) {
+ System.out.println("ERROR: test7 had wrong value: " + val + " != " + sum);
+ errors++;
+ break;
+ }
+ }
+ }
+
+ // No result verification here. We only want to make sure we do not hit asserts.
+ System.out.println("test8 and test9");
+ for (int i = 0; i < 100_000; i++) {
+ test8a(big, ANCHOR);
+ test8b(big, ANCHOR);
+ test8c(big, ANCHOR);
+ test8d(big, ANCHOR);
+ test9a(big, ANCHOR);
+ test9b(big, ANCHOR);
+ test9c(big, ANCHOR);
+ }
+
if (errors > 0) {
throw new RuntimeException("ERRORS: " + errors);
}
@@ -129,4 +230,95 @@ static void test2(int[] a, long anchor) {
UNSAFE.putInt(a, base + 0 + (long)(four + Integer.MAX_VALUE), 0x42424242);
UNSAFE.putInt(a, base + Integer.MAX_VALUE + (long)(four + 4 ), 0x66666666);
}
+
+ // Test: if MergeStores is applied this can lead to wrong results
+ // -> AddI needs overflow check.
+ static void test3(int[] a, long anchor) {
+ long base = UNSAFE.ARRAY_INT_BASE_OFFSET + anchor;
+ UNSAFE.putInt(a, base + (long)(max_int + 0), 0x42424242);
+ UNSAFE.putInt(a, base + (long)(max_int + 4), 0x66666666);
+ }
+
+ // Test: "max_int - four" cannot be parsed further, but would not make a difference here.
+ static void test4(int[] a, long anchor) {
+ long base = UNSAFE.ARRAY_INT_BASE_OFFSET + anchor;
+ UNSAFE.putInt(a, base + (long)(min_int - four) + 0, 0x42424242);
+ UNSAFE.putInt(a, base + (long)(min_int - four) + 4, 0x66666666);
+ }
+
+ // Test: if MergeStores is applied this can lead to wrong results
+ // -> SubI needs overflow check.
+ static void test5(int[] a, long anchor) {
+ long base = UNSAFE.ARRAY_INT_BASE_OFFSET + anchor;
+ UNSAFE.putInt(a, base + (long)(min_int) - (long)(four) + 0, 0x42424242); // no overflow
+ UNSAFE.putInt(a, base + (long)(min_int - four) + 4, 0x66666666); // overflow
+ }
+
+ // Test: if MergeStores is applied this can lead to wrong results
+ // -> LShiftI needs overflow check.
+ static void test6(int[] a, long anchor) {
+ long base = UNSAFE.ARRAY_INT_BASE_OFFSET + anchor;
+ UNSAFE.putInt(a, base + (long)(2 * val_2_to_30) + 0, 0x42424242); // overflow
+ UNSAFE.putInt(a, base + 2L * (long)(val_2_to_30) + 4, 0x66666666); // no overflow
+ }
+
+ // Test: if MergeStores is applied this can lead to wrong results
+ // -> MulI needs overflow check.
+ static void test7(int[] a, long anchor) {
+ long base = UNSAFE.ARRAY_INT_BASE_OFFSET + anchor;
+ UNSAFE.putInt(a, base + (long)(53 * large_by_53) + 0, 0x42424242); // overflow
+ UNSAFE.putInt(a, base + 53L * (long)(large_by_53) + 4, 0x66666666); // no overflow
+ }
+
+ // Test: check if large distance leads to assert
+ static void test8a(int[] a, long anchor) {
+ long base = UNSAFE.ARRAY_INT_BASE_OFFSET + anchor;
+ UNSAFE.putByte(a, base + (1L << 11) + 0, (byte)42);
+ UNSAFE.putByte(a, base + (1L << 11) + (1L << 30), (byte)11);
+ }
+
+ // Test: check if large distance leads to assert
+ static void test8b(int[] a, long anchor) {
+ long base = UNSAFE.ARRAY_INT_BASE_OFFSET + anchor;
+ UNSAFE.putByte(a, base + (1L << 11) + (1L << 30), (byte)11);
+ UNSAFE.putByte(a, base + (1L << 11) + 0, (byte)42);
+ }
+
+ // Test: check if large distance leads to assert
+ static void test8c(int[] a, long anchor) {
+ long base = UNSAFE.ARRAY_INT_BASE_OFFSET + anchor;
+ UNSAFE.putByte(a, base - (1L << 11) - 0, (byte)42);
+ UNSAFE.putByte(a, base - (1L << 11) - (1L << 30), (byte)11);
+ }
+
+ // Test: check if large distance leads to assert
+ static void test8d(int[] a, long anchor) {
+ long base = UNSAFE.ARRAY_INT_BASE_OFFSET + anchor;
+ UNSAFE.putByte(a, base - (1L << 11) - (1L << 30), (byte)11);
+ UNSAFE.putByte(a, base - (1L << 11) - 0, (byte)42);
+ }
+
+ // Test: check if large distance leads to assert
+ // case: bad distance: NaN
+ static void test9a(int[] a, long anchor) {
+ long base = UNSAFE.ARRAY_INT_BASE_OFFSET + anchor;
+ UNSAFE.putByte(a, base - 100, (byte)42);
+ UNSAFE.putByte(a, base - 100 + (1L << 31), (byte)11);
+ }
+
+ // Test: check if large distance leads to assert
+ // case: just before NaN, it is still a valid distance for MemPointer aliasing.
+ static void test9b(int[] a, long anchor) {
+ long base = UNSAFE.ARRAY_INT_BASE_OFFSET + anchor;
+ UNSAFE.putByte(a, base - 100, (byte)42);
+ UNSAFE.putByte(a, base - 100 + (1L << 31) - 1, (byte)11);
+ }
+
+ // Test: check if large distance leads to assert
+ // case: constant too large
+ static void test9c(int[] a, long anchor) {
+ long base = UNSAFE.ARRAY_INT_BASE_OFFSET + anchor;
+ UNSAFE.putByte(a, base, (byte)42);
+ UNSAFE.putByte(a, base + (1L << 31), (byte)11);
+ }
}
diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizationMismatchedAccess.java b/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizationMismatchedAccess.java
index 2d17753ba94..b511476bf52 100644
--- a/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizationMismatchedAccess.java
+++ b/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizationMismatchedAccess.java
@@ -153,6 +153,8 @@ static private void runAndVerify3(Runnable test, int offset) {
@Test
@IR(counts = { IRNode.LOAD_VECTOR_L, ">=1", IRNode.STORE_VECTOR, ">=1" },
+ // This test fails with compact headers, but only with UseSSE<=3.
+ applyIf = { "UseCompactObjectHeaders", "false" },
applyIfCPUFeatureOr = {"sse2", "true", "asimd", "true"},
applyIfPlatform = {"64-bit", "true"})
// 32-bit: offsets are badly aligned (UNSAFE.ARRAY_BYTE_BASE_OFFSET is 4 byte aligned, but not 8 byte aligned).
@@ -165,6 +167,8 @@ public static void testByteLong1a(byte[] dest, long[] src) {
@Test
@IR(counts = { IRNode.LOAD_VECTOR_L, ">=1", IRNode.STORE_VECTOR, ">=1" },
+ // This test fails with compact headers, but only with UseSSE<=3.
+ applyIf = { "UseCompactObjectHeaders", "false" },
applyIfCPUFeatureOr = {"sse2", "true", "asimd", "true"},
applyIfPlatform = {"64-bit", "true"})
// 32-bit: address has ConvL2I for cast of long to address, not supported.
@@ -176,6 +180,8 @@ public static void testByteLong1b(byte[] dest, long[] src) {
@Test
@IR(counts = { IRNode.LOAD_VECTOR_L, ">=1", IRNode.STORE_VECTOR, ">=1" },
+ // This test fails with compact headers, but only with UseSSE<=3.
+ applyIf = { "UseCompactObjectHeaders", "false" },
applyIfCPUFeatureOr = {"sse2", "true", "asimd", "true"})
public static void testByteLong1c(byte[] dest, long[] src) {
long base = 64; // make sure it is big enough and 8 byte aligned (required for 32-bit)
@@ -186,6 +192,8 @@ public static void testByteLong1c(byte[] dest, long[] src) {
@Test
@IR(counts = { IRNode.LOAD_VECTOR_L, ">=1", IRNode.STORE_VECTOR, ">=1" },
+ // This test fails with compact headers, but only with UseSSE<=3.
+ applyIf = { "UseCompactObjectHeaders", "false" },
applyIfCPUFeatureOr = {"sse2", "true", "asimd", "true"},
applyIfPlatform = {"64-bit", "true"})
// 32-bit: address has ConvL2I for cast of long to address, not supported.
@@ -235,6 +243,8 @@ public static void testByteLong2_runner() {
@Test
@IR(counts = { IRNode.LOAD_VECTOR_L, ">=1", IRNode.STORE_VECTOR, ">=1" },
+ // This test fails with compact headers, but only with UseSSE<=3.
+ applyIf = { "UseCompactObjectHeaders", "false" },
applyIfCPUFeatureOr = {"sse2", "true", "asimd", "true"},
applyIfPlatform = {"64-bit", "true"})
// 32-bit: offsets are badly aligned (UNSAFE.ARRAY_BYTE_BASE_OFFSET is 4 byte aligned, but not 8 byte aligned).
@@ -247,6 +257,8 @@ public static void testByteLong3a(byte[] dest, long[] src) {
@Test
@IR(counts = { IRNode.LOAD_VECTOR_L, ">=1", IRNode.STORE_VECTOR, ">=1" },
+ // This test fails with compact headers, but only with UseSSE<=3.
+ applyIf = { "UseCompactObjectHeaders", "false" },
applyIfCPUFeatureOr = {"sse2", "true", "asimd", "true"},
applyIfPlatform = {"64-bit", "true"})
// 32-bit: address has ConvL2I for cast of long to address, not supported.
@@ -298,6 +310,8 @@ public static void testByteLong4_runner() {
@Test
@IR(counts = { IRNode.LOAD_VECTOR_L, ">=1", IRNode.STORE_VECTOR, ">=1" },
+ // This test fails with compact headers, but only with UseSSE<=3.
+ applyIf = { "UseCompactObjectHeaders", "false" },
applyIfCPUFeatureOr = {"sse2", "true", "asimd", "true"},
applyIfPlatform = {"64-bit", "true"})
// 32-bit: offsets are badly aligned (UNSAFE.ARRAY_BYTE_BASE_OFFSET is 4 byte aligned, but not 8 byte aligned).
@@ -310,6 +324,8 @@ public static void testByteLong5a(byte[] dest, long[] src, int start, int stop)
@Test
@IR(counts = { IRNode.LOAD_VECTOR_L, ">=1", IRNode.STORE_VECTOR, ">=1" },
+ // This test fails with compact headers, but only with UseSSE<=3.
+ applyIf = { "UseCompactObjectHeaders", "false" },
applyIfCPUFeatureOr = {"sse2", "true", "asimd", "true"},
applyIfPlatform = {"64-bit", "true"})
// 32-bit: address has ConvL2I for cast of long to address, not supported.
@@ -328,6 +344,8 @@ public static void testByteLong5_runner() {
@Test
@IR(counts = { IRNode.LOAD_VECTOR_L, ">=1", IRNode.STORE_VECTOR, ">=1" },
+ // This test fails with compact headers, but only with UseSSE<=3.
+ applyIf = { "UseCompactObjectHeaders", "false" },
applyIfCPUFeatureOr = {"sse2", "true", "asimd", "true"},
applyIfPlatform = {"64-bit", "true"})
// 32-bit: offsets are badly aligned (UNSAFE.ARRAY_BYTE_BASE_OFFSET is 4 byte aligned, but not 8 byte aligned).
@@ -340,6 +358,8 @@ public static void testByteByte1a(byte[] dest, byte[] src) {
@Test
@IR(counts = { IRNode.LOAD_VECTOR_L, ">=1", IRNode.STORE_VECTOR, ">=1" },
+ // This test fails with compact headers, but only with UseSSE<=3.
+ applyIf = { "UseCompactObjectHeaders", "false" },
applyIfCPUFeatureOr = {"sse2", "true", "asimd", "true"},
applyIfPlatform = {"64-bit", "true"})
// 32-bit: address has ConvL2I for cast of long to address, not supported.
@@ -357,6 +377,8 @@ public static void testByteByte1_runner() {
@Test
@IR(counts = { IRNode.LOAD_VECTOR_L, ">=1", IRNode.STORE_VECTOR, ">=1" },
+ // This test fails with compact headers, but only with UseSSE<=3.
+ applyIf = { "UseCompactObjectHeaders", "false" },
applyIfCPUFeatureOr = {"sse2", "true", "asimd", "true"},
applyIfPlatform = {"64-bit", "true"})
// 32-bit: offsets are badly aligned (UNSAFE.ARRAY_BYTE_BASE_OFFSET is 4 byte aligned, but not 8 byte aligned).
@@ -369,6 +391,8 @@ public static void testByteByte2a(byte[] dest, byte[] src) {
@Test
@IR(counts = { IRNode.LOAD_VECTOR_L, ">=1", IRNode.STORE_VECTOR, ">=1" },
+ // This test fails with compact headers, but only with UseSSE<=3.
+ applyIf = { "UseCompactObjectHeaders", "false" },
applyIfCPUFeatureOr = {"sse2", "true", "asimd", "true"},
applyIfPlatform = {"64-bit", "true"})
// 32-bit: address has ConvL2I for cast of long to address, not supported.
diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizationNotRun.java b/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizationNotRun.java
index 5968b7221c7..d61b8c658d6 100644
--- a/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizationNotRun.java
+++ b/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizationNotRun.java
@@ -51,7 +51,9 @@ public static void main(String[] args) {
static long[] longArray = new long[size];
@Test
- @IR(counts = { IRNode.LOAD_VECTOR_L, ">=1", IRNode.STORE_VECTOR, ">=1" })
+ @IR(counts = { IRNode.LOAD_VECTOR_L, ">=1", IRNode.STORE_VECTOR, ">=1" },
+ // This test fails with compact headers, but only with UseSSE<=3.
+ applyIf = { "UseCompactObjectHeaders", "false" })
public static void test(byte[] dest, long[] src) {
for (int i = 0; i < src.length; i++) {
if ((i < 0) || (8 > sizeBytes - i)) {
diff --git a/test/hotspot/jtreg/compiler/escapeAnalysis/TestReduceAllocationAndNonReduciblePhi.java b/test/hotspot/jtreg/compiler/escapeAnalysis/TestReduceAllocationAndNonReduciblePhi.java
new file mode 100644
index 00000000000..d5593a3af41
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/escapeAnalysis/TestReduceAllocationAndNonReduciblePhi.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8340454
+ * @summary Check that Reduce Allocation Merges doesn't crash when
+ * a reducible Phi becomes irreducible after the last of
+ * its SR inputs is flagged as NSR.
+ * @run main/othervm -XX:CompileCommand=dontinline,*TestReduceAllocationAndNonReduciblePhi*::test
+ * -XX:CompileCommand=compileonly,*TestReduceAllocationAndNonReduciblePhi*::test
+ * -XX:CompileCommand=compileonly,*Picture*::*
+ * -XX:CompileCommand=compileonly,*Point*::*
+ * -XX:CompileCommand=inline,*Picture*::*
+ * -XX:CompileCommand=inline,*Point*::*
+ * -XX:CompileCommand=exclude,*::dummy*
+ * -Xbatch
+ * -server
+ * compiler.escapeAnalysis.TestReduceAllocationAndNonReduciblePhi
+ *
+ * @run main compiler.escapeAnalysis.TestReduceAllocationAndNonReduciblePhi
+ */
+
+package compiler.escapeAnalysis;
+
+public class TestReduceAllocationAndNonReduciblePhi {
+ public static void main(String args[]) {
+ int result = 0;
+
+ for (int i = 0; i < 20000; i++) {
+ result += test(i % 2 == 0, i % 3);
+ }
+
+ System.out.println("Result is = " + result);
+ }
+
+ public static int test(boolean flag1, int pos) {
+ Point p0 = new Point();
+ Point p1 = flag1 ? null : p0;
+
+ Picture pic = new Picture();
+ pic.p = p0;
+
+ Picture[] ps = new Picture[5];
+ ps[pos] = pic;
+
+ return p1 != null ? dummy1() : dummy2();
+ }
+
+ public static int dummy1() { return 1; }
+
+ public static int dummy2() { return 2; }
+
+ private static class Picture {
+ public Point p;
+ }
+
+ private static class Point { }
+}
diff --git a/test/hotspot/jtreg/compiler/intrinsics/bmi/BMITestRunner.java b/test/hotspot/jtreg/compiler/intrinsics/bmi/BMITestRunner.java
index 159e471e3fc..b005d767287 100644
--- a/test/hotspot/jtreg/compiler/intrinsics/bmi/BMITestRunner.java
+++ b/test/hotspot/jtreg/compiler/intrinsics/bmi/BMITestRunner.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -122,6 +122,10 @@ public static OutputAnalyzer runTest(Class extends Expr> expr,
List vmOpts = new LinkedList();
Collections.addAll(vmOpts, additionalVMOpts);
+ // Hide timestamps from warnings (e.g. due to potential CDS
+ // saved/runtime state mismatch), to avoid false positives when
+ // comparing output across runs.
+ vmOpts.add("-Xlog:all=warning:stdout:level,tags");
//setup mode-specific options
switch (testVMMode) {
diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java
index 762e07f4549..9b8713934b0 100644
--- a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java
+++ b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java
@@ -226,6 +226,11 @@ public class IRNode {
beforeMatchingNameRegex(ADD_L, "AddL");
}
+ public static final String ADD_P = PREFIX + "ADD_P" + POSTFIX;
+ static {
+ beforeMatchingNameRegex(ADD_P, "AddP");
+ }
+
public static final String ADD_VD = VECTOR_PREFIX + "ADD_VD" + POSTFIX;
static {
vectorNode(ADD_VD, "AddVD", TYPE_DOUBLE);
diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java b/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java
index 88fe5617a93..efcacdaa361 100644
--- a/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java
+++ b/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java
@@ -142,7 +142,8 @@ public class TestFramework {
"UseZbb",
"UseRVV",
"Xlog",
- "LogCompilation"
+ "LogCompilation",
+ "UseCompactObjectHeaders"
)
);
diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestAlignVector.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestAlignVector.java
index c77f4f6fa2e..efd328dc5cc 100644
--- a/test/hotspot/jtreg/compiler/loopopts/superword/TestAlignVector.java
+++ b/test/hotspot/jtreg/compiler/loopopts/superword/TestAlignVector.java
@@ -398,6 +398,7 @@ static Object[] test0(byte[] a, byte[] b, byte mask) {
@IR(counts = {IRNode.LOAD_VECTOR_B, "> 0",
IRNode.AND_VB, "> 0",
IRNode.STORE_VECTOR, "> 0"},
+ applyIf = {"UseCompactObjectHeaders", "false"},
applyIfPlatform = {"64-bit", "true"},
applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true"})
static Object[] test1(byte[] a, byte[] b, byte mask) {
@@ -706,7 +707,7 @@ static Object[] test10c(short[] a, short[] b, short mask) {
@IR(counts = {IRNode.LOAD_VECTOR_S, IRNode.VECTOR_SIZE_4, "> 0",
IRNode.AND_VS, IRNode.VECTOR_SIZE_4, "> 0",
IRNode.STORE_VECTOR, "> 0"},
- applyIf = {"MaxVectorSize", ">=16"},
+ applyIfAnd = {"MaxVectorSize", ">=16", "UseCompactObjectHeaders", "false"},
applyIfPlatform = {"64-bit", "true"},
applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true"})
static Object[] test10d(short[] a, short[] b, short mask) {
@@ -1001,6 +1002,7 @@ static Object[] test13aIL(int[] a, long[] b) {
IRNode.ADD_VB, "> 0",
IRNode.ADD_VI, "> 0",
IRNode.STORE_VECTOR, "> 0"},
+ applyIf = {"UseCompactObjectHeaders", "false"},
applyIfPlatform = {"64-bit", "true"},
applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true"})
static Object[] test13aIB(int[] a, byte[] b) {
@@ -1017,6 +1019,7 @@ static Object[] test13aIB(int[] a, byte[] b) {
IRNode.ADD_VI, "> 0",
IRNode.ADD_VS, "> 0",
IRNode.STORE_VECTOR, "> 0"},
+ applyIf = {"UseCompactObjectHeaders", "false"},
applyIfPlatform = {"64-bit", "true"},
applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true"})
static Object[] test13aIS(int[] a, short[] b) {
@@ -1037,6 +1040,7 @@ static Object[] test13aIS(int[] a, short[] b) {
IRNode.ADD_VI, "> 0",
IRNode.ADD_VL, "> 0",
IRNode.STORE_VECTOR, "> 0"},
+ applyIf = {"UseCompactObjectHeaders", "false"},
applyIfPlatform = {"64-bit", "true"},
applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true"})
static Object[] test13aBSIL(byte[] a, short[] b, int[] c, long[] d) {
@@ -1072,6 +1076,7 @@ static Object[] test13bIL(int[] a, long[] b) {
IRNode.ADD_VB, "> 0",
IRNode.ADD_VI, "> 0",
IRNode.STORE_VECTOR, "> 0"},
+ applyIf = {"UseCompactObjectHeaders", "false"},
applyIfPlatform = {"64-bit", "true"},
applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true"})
static Object[] test13bIB(int[] a, byte[] b) {
@@ -1088,6 +1093,7 @@ static Object[] test13bIB(int[] a, byte[] b) {
IRNode.ADD_VI, "> 0",
IRNode.ADD_VS, "> 0",
IRNode.STORE_VECTOR, "> 0"},
+ applyIf = {"UseCompactObjectHeaders", "false"},
applyIfPlatform = {"64-bit", "true"},
applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true"})
static Object[] test13bIS(int[] a, short[] b) {
@@ -1108,6 +1114,7 @@ static Object[] test13bIS(int[] a, short[] b) {
IRNode.ADD_VI, "> 0",
IRNode.ADD_VL, "> 0",
IRNode.STORE_VECTOR, "> 0"},
+ applyIf = {"UseCompactObjectHeaders", "false"},
applyIfPlatform = {"64-bit", "true"},
applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true"})
static Object[] test13bBSIL(byte[] a, short[] b, int[] c, long[] d) {
diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestEliminateAllocationWithCastP2XUse.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestEliminateAllocationWithCastP2XUse.java
new file mode 100644
index 00000000000..416781d1b00
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/loopopts/superword/TestEliminateAllocationWithCastP2XUse.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.loopopts.superword;
+
+/*
+ * @test
+ * @bug 8342498
+ * @summary Test SuperWord, when it aligns to field-store, and the corresponding allocation is eliminated.
+ * @run driver compiler.loopopts.superword.TestEliminateAllocationWithCastP2XUse
+ * @run main/othervm -Xbatch
+ * -XX:-SplitIfBlocks -XX:LoopMaxUnroll=8
+ * -XX:+UnlockDiagnosticVMOptions -XX:DominatorSearchLimit=45
+ * compiler.loopopts.superword.TestEliminateAllocationWithCastP2XUse
+ */
+
+public class TestEliminateAllocationWithCastP2XUse {
+ public static void main(String args[]) {
+ byte[] a = new byte[10_000];
+ for (int i = 0; i < 10000; i++) {
+ test(a);
+ }
+ }
+
+ // Summary:
+ // - Some B allocations are detected as NoEscape, but cannot be removed because of a field load.
+ // - The field loads cannot be LoadNode::split_through_phi because DominatorSearchLimit is too low
+ // for the dominates query to look through some IfNode / IfProj path.
+ // - We go into loop-opts.
+ // - In theory, the Stores of B::offset would be moved out of the loop. But we disable
+ // PhaseIdealLoop::try_move_store_after_loop by setting -XX:-SplitIfBlocks.
+ // - The field loads are folded away because of some MaxUnroll trick, where the val constant folds to 1.
+ // - SuperWord eventually kicks in, and vectorizes the array stores.
+ // - Since some vectorization has happened, SuperWord wants to align the main loop with a memory reference
+ // in the loop. The code here is not very smart, and just picks the memory reference that occurs the
+ // most often. But the B::offset stores occur more often than the array stores, and so we align to
+ // one of the B::offset stores. This inserts a CastP2X under the CheckCastPP of the B allocation.
+ // - Once loop opts is over, we eventually go into macro expansion.
+ // - During macro expansion, we now discover that the Allocations were marked NoEscape, and that by now
+ // there are no field loads any more: yay, we can remove the allocation!
+ // - ... except that there is the CastP2X from SuperWord alignment ...
+ // - The Allocation removal code wants to pattern match the CastP2X as part of a GC barrier, but then
+ // the pattern does not conform to the expecatation - it is after all from SuperWord. This leads to
+ // an assert, and SIGSEGV in product, at least with G1GC.
+ public static long test(byte[] a) {
+ // Delay val == 1 until loop-opts, with MaxUnroll trick.
+ int val = 0;
+ for (int i = 0; i < 4; i++) {
+ if ((i % 2) == 0) {
+ val = 1;
+ }
+ }
+ // during loop opts, we learn val == 1
+ // But we don't know that during EscapeAnalysis (EA) yet.
+
+ // 9 Allocations, discovered as NoEscape during EA.
+ B b1 = new B();
+ B b2 = new B();
+ B b3 = new B();
+ B b4 = new B();
+ B b5 = new B();
+ B b6 = new B();
+ B b7 = new B();
+ B b8 = new B();
+ B b9 = new B();
+
+ // Some path of IfNode / IfProj.
+ // Only folds away once we know val == 1
+ // This delays the LoadNode::split_through_phi, because it needs a dominates call
+ // to succeed, but it cannot look through this path because we set -XX:DominatorSearchLimit=45
+ // i.e. just a little too low to be able to look through.
+ // Without the LoadNode::split_through_phi before the end of EA, the Allocation cannot yet be
+ // removed, due to a "Field load", i.e. that Load for B::offset.
+ // But later, this path can actually fold away, when we know that val == 1. At that point,
+ // also the Load from B::offset folds away because LoadNode::split_through_phi succeeds
+ // At that point the B allocations have no Loads any more, and can be removed... but this only
+ // happens at macro expansion, after all loop opts.
+ if (val == 1010) { throw new RuntimeException("never"); }
+ if (val == 1020) { throw new RuntimeException("never"); }
+ if (val == 1030) { throw new RuntimeException("never"); }
+ if (val == 1040) { throw new RuntimeException("never"); }
+ if (val == 1060) { throw new RuntimeException("never"); }
+ if (val == 1070) { throw new RuntimeException("never"); }
+ if (val == 1080) { throw new RuntimeException("never"); }
+ if (val == 1090) { throw new RuntimeException("never"); }
+
+ if (val == 2010) { throw new RuntimeException("never"); }
+ if (val == 2020) { throw new RuntimeException("never"); }
+ if (val == 2030) { throw new RuntimeException("never"); }
+ if (val == 2040) { throw new RuntimeException("never"); }
+ if (val == 2060) { throw new RuntimeException("never"); }
+ if (val == 2070) { throw new RuntimeException("never"); }
+ if (val == 2080) { throw new RuntimeException("never"); }
+ if (val == 2090) { throw new RuntimeException("never"); }
+
+ if (val == 3010) { throw new RuntimeException("never"); }
+ if (val == 3020) { throw new RuntimeException("never"); }
+ if (val == 3030) { throw new RuntimeException("never"); }
+ if (val == 3040) { throw new RuntimeException("never"); }
+ if (val == 3060) { throw new RuntimeException("never"); }
+ if (val == 3070) { throw new RuntimeException("never"); }
+ if (val == 3080) { throw new RuntimeException("never"); }
+ if (val == 3090) { throw new RuntimeException("never"); }
+
+ if (val == 4010) { throw new RuntimeException("never"); }
+ if (val == 4020) { throw new RuntimeException("never"); }
+ if (val == 4030) { throw new RuntimeException("never"); }
+ if (val == 4040) { throw new RuntimeException("never"); }
+ if (val == 4060) { throw new RuntimeException("never"); }
+ if (val == 4070) { throw new RuntimeException("never"); }
+ if (val == 4080) { throw new RuntimeException("never"); }
+ if (val == 4090) { throw new RuntimeException("never"); }
+
+ long mulVal = 1;
+ for (int i = 0; i < a.length; i++) {
+ mulVal *= 3;
+ // We do some vector store, so that SuperWord succeeds, and creates the
+ // alignment code, which emits the CastP2X.
+ a[i]++;
+ // But we also have 9 Stores for the B::offset.
+ // SuperWord now sees more of these stores than of the array stores, and picks
+ // one of the B::offset stores as the alignment reference... creating a CastP2X
+ // for the CheckCastPP of the B allocation.
+ b1.offset = mulVal;
+ b2.offset = mulVal;
+ b3.offset = mulVal;
+ b4.offset = mulVal;
+ b5.offset = mulVal;
+ b6.offset = mulVal;
+ b7.offset = mulVal;
+ b8.offset = mulVal;
+ b9.offset = mulVal;
+ }
+
+ // This folds the loads away, once we know val == 1
+ // That happens during loop-opts, so after EA, but before macro expansion.
+ long ret = 0;
+ if (val == 42) {
+ ret = b1.offset +
+ b2.offset +
+ b3.offset +
+ b4.offset +
+ b5.offset +
+ b6.offset +
+ b7.offset +
+ b8.offset +
+ b9.offset;
+ }
+
+ return ret;
+ }
+
+ static class B {
+ // Add padding so that the old SuperWord::can_create_pairs accepts the field store to B.offset
+ long pad1 = 0; // at 16
+ long pad2 = 0; // at 24
+ long pad3 = 0; // at 32
+ long pad4 = 0; // at 40
+ long pad5 = 0; // at 48
+ long pad6 = 0; // at 56
+ long offset = 0; // offset at 64 bytes
+ }
+}
diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestMulAddS2I.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestMulAddS2I.java
index fb99fc5983a..9aaa7cdd8a9 100644
--- a/test/hotspot/jtreg/compiler/loopopts/superword/TestMulAddS2I.java
+++ b/test/hotspot/jtreg/compiler/loopopts/superword/TestMulAddS2I.java
@@ -163,11 +163,13 @@ public static int[] testc(int[] out) {
@Test
@IR(applyIfCPUFeature = {"sse2", "true"},
applyIfPlatform = {"64-bit", "true"},
+ applyIf = { "UseCompactObjectHeaders", "false" },
counts = {IRNode.MUL_ADD_S2I, "> 0", IRNode.MUL_ADD_VS2VI, "> 0"})
@IR(applyIfCPUFeature = {"asimd", "true"},
- applyIf = {"MaxVectorSize", "16"}, // AD file requires vector_length = 16
+ applyIfAnd = {"MaxVectorSize", "16", "UseCompactObjectHeaders", "false"}, // AD file requires vector_length = 16
counts = {IRNode.MUL_ADD_S2I, "> 0", IRNode.MUL_ADD_VS2VI, "> 0"})
@IR(applyIfCPUFeature = {"avx512_vnni", "true"},
+ applyIf = { "UseCompactObjectHeaders", "false" },
counts = {IRNode.MUL_ADD_S2I, "> 0", IRNode.MUL_ADD_VS2VI_VNNI, "> 0"})
public static int[] testd(int[] out) {
for (int i = 0; i < ITER-2; i+=2) {
@@ -181,11 +183,13 @@ public static int[] testd(int[] out) {
@Test
@IR(applyIfCPUFeature = {"sse2", "true"},
applyIfPlatform = {"64-bit", "true"},
+ applyIf = { "UseCompactObjectHeaders", "false" },
counts = {IRNode.MUL_ADD_S2I, "> 0", IRNode.MUL_ADD_VS2VI, "> 0"})
@IR(applyIfCPUFeature = {"asimd", "true"},
- applyIf = {"MaxVectorSize", "16"}, // AD file requires vector_length = 16
+ applyIfAnd = {"MaxVectorSize", "16", "UseCompactObjectHeaders", "false" }, // AD file requires vector_length = 16
counts = {IRNode.MUL_ADD_S2I, "> 0", IRNode.MUL_ADD_VS2VI, "> 0"})
@IR(applyIfCPUFeature = {"avx512_vnni", "true"},
+ applyIf = { "UseCompactObjectHeaders", "false" },
counts = {IRNode.MUL_ADD_S2I, "> 0", IRNode.MUL_ADD_VS2VI_VNNI, "> 0"})
public static int[] teste(int[] out) {
for (int i = 0; i < ITER-2; i+=2) {
@@ -199,11 +203,13 @@ public static int[] teste(int[] out) {
@Test
@IR(applyIfCPUFeature = {"sse2", "true"},
applyIfPlatform = {"64-bit", "true"},
+ applyIf = { "UseCompactObjectHeaders", "false" },
counts = {IRNode.MUL_ADD_S2I, "> 0", IRNode.MUL_ADD_VS2VI, "> 0"})
@IR(applyIfCPUFeature = {"asimd", "true"},
- applyIf = {"MaxVectorSize", "16"}, // AD file requires vector_length = 16
+ applyIfAnd = {"MaxVectorSize", "16", "UseCompactObjectHeaders", "false" }, // AD file requires vector_length = 16
counts = {IRNode.MUL_ADD_S2I, "> 0", IRNode.MUL_ADD_VS2VI, "> 0"})
@IR(applyIfCPUFeature = {"avx512_vnni", "true"},
+ applyIf = { "UseCompactObjectHeaders", "false" },
counts = {IRNode.MUL_ADD_S2I, "> 0", IRNode.MUL_ADD_VS2VI_VNNI, "> 0"})
public static int[] testf(int[] out) {
for (int i = 0; i < ITER-2; i+=2) {
@@ -217,11 +223,13 @@ public static int[] testf(int[] out) {
@Test
@IR(applyIfCPUFeature = {"sse2", "true"},
applyIfPlatform = {"64-bit", "true"},
+ applyIf = { "UseCompactObjectHeaders", "false" },
counts = {IRNode.MUL_ADD_S2I, "> 0", IRNode.MUL_ADD_VS2VI, "> 0"})
@IR(applyIfCPUFeature = {"asimd", "true"},
- applyIf = {"MaxVectorSize", "16"}, // AD file requires vector_length = 16
+ applyIfAnd = {"MaxVectorSize", "16", "UseCompactObjectHeaders", "false" }, // AD file requires vector_length = 16
counts = {IRNode.MUL_ADD_S2I, "> 0", IRNode.MUL_ADD_VS2VI, "> 0"})
@IR(applyIfCPUFeature = {"avx512_vnni", "true"},
+ applyIf = { "UseCompactObjectHeaders", "false" },
counts = {IRNode.MUL_ADD_S2I, "> 0", IRNode.MUL_ADD_VS2VI_VNNI, "> 0"})
public static int[] testg(int[] out) {
for (int i = 0; i < ITER-2; i+=2) {
@@ -235,11 +243,13 @@ public static int[] testg(int[] out) {
@Test
@IR(applyIfCPUFeature = {"sse2", "true"},
applyIfPlatform = {"64-bit", "true"},
+ applyIf = { "UseCompactObjectHeaders", "false" },
counts = {IRNode.MUL_ADD_S2I, "> 0", IRNode.MUL_ADD_VS2VI, "> 0"})
@IR(applyIfCPUFeature = {"asimd", "true"},
- applyIf = {"MaxVectorSize", "16"}, // AD file requires vector_length = 16
+ applyIfAnd = {"MaxVectorSize", "16", "UseCompactObjectHeaders", "false" }, // AD file requires vector_length = 16
counts = {IRNode.MUL_ADD_S2I, "> 0", IRNode.MUL_ADD_VS2VI, "> 0"})
@IR(applyIfCPUFeature = {"avx512_vnni", "true"},
+ applyIf = { "UseCompactObjectHeaders", "false" },
counts = {IRNode.MUL_ADD_S2I, "> 0", IRNode.MUL_ADD_VS2VI_VNNI, "> 0"})
public static int[] testh(int[] out) {
for (int i = 0; i < ITER-2; i+=2) {
diff --git a/test/hotspot/jtreg/compiler/loopstripmining/TestIdenticalDominatingCLE.java b/test/hotspot/jtreg/compiler/loopstripmining/TestIdenticalDominatingCLE.java
new file mode 100644
index 00000000000..371c0fb2bc5
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/loopstripmining/TestIdenticalDominatingCLE.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2024, Red Hat, Inc. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8340532
+ * @summary C2: assert(is_OuterStripMinedLoop()) failed: invalid node class: IfTrue
+ * @requires vm.compiler2.enabled
+ * @run main/othervm -XX:CompileOnly=TestIdenticalDominatingCLE::* -XX:CompileThreshold=100 -Xcomp -XX:-TieredCompilation
+ * -XX:-RangeCheckElimination -XX:LoopMaxUnroll=0 TestIdenticalDominatingCLE
+ *
+ */
+
+
+public class TestIdenticalDominatingCLE {
+ boolean bFld;
+ long lFld;
+ float[][] fArr = new float[6][6];
+
+ public static void main(String[] var0) {
+ TestIdenticalDominatingCLE t = new TestIdenticalDominatingCLE();
+ t.test();
+ }
+
+ void test() {
+ int i = 0;
+ do {
+ for (int j = 0; j < 2; j++) {
+ float f = fArr[j][3] / Float.valueOf((float)1.318095814E9);
+ switch (i) {
+ case 1:
+ if (bFld ^ bFld) {
+ } else {
+ for (int k = 0; k < 600; k++) {
+ }
+ }
+ break;
+ default:
+ if (bFld) {
+ }
+ }
+ }
+ lFld = ++i;
+ } while (i < 6);
+ }
+}
diff --git a/test/hotspot/jtreg/compiler/patches/java.base/java/lang/Helper.java b/test/hotspot/jtreg/compiler/patches/java.base/java/lang/Helper.java
index a24d7b98ada..5ecc01aa2bc 100644
--- a/test/hotspot/jtreg/compiler/patches/java.base/java/lang/Helper.java
+++ b/test/hotspot/jtreg/compiler/patches/java.base/java/lang/Helper.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -133,11 +133,17 @@ public static boolean contentEquals(byte[] value, CharSequence cs, int len) {
}
public static int putCharsAt(byte[] value, int i, char c1, char c2, char c3, char c4) {
- return StringUTF16.putCharsAt(value, i, c1, c2, c3, c4);
+ int end = i + 4;
+ StringUTF16.checkBoundsBeginEnd(i, end, value);
+ StringUTF16.putCharsAt(value, i, c1, c2, c3, c4);
+ return end;
}
public static int putCharsAt(byte[] value, int i, char c1, char c2, char c3, char c4, char c5) {
- return StringUTF16.putCharsAt(value, i, c1, c2, c3, c4, c5);
+ int end = i + 5;
+ StringUTF16.checkBoundsBeginEnd(i, end, value);
+ StringUTF16.putCharsAt(value, i, c1, c2, c3, c4, c5);
+ return end;
}
public static char charAt(byte[] value, int index) {
diff --git a/test/hotspot/jtreg/compiler/vectorization/TestReplicateAtConv.java b/test/hotspot/jtreg/compiler/vectorization/TestReplicateAtConv.java
new file mode 100644
index 00000000000..e77b474bf66
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/vectorization/TestReplicateAtConv.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2024, Red Hat, Inc. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8341834
+ * @summary C2 compilation fails with "bad AD file" due to Replicate
+ * @run main/othervm -XX:CompileCommand=compileonly,TestReplicateAtConv::test -Xcomp TestReplicateAtConv
+ */
+
+public class TestReplicateAtConv {
+ public static long val = 0;
+
+ public static void test() {
+ int array[] = new int[500];
+
+ for (int i = 0; i < 100; i++) {
+ for (long l = 100; l > i; l--) {
+ val = 42 + (l + i);
+ array[(int)l] = (int)l - (int)val;
+ }
+ }
+ }
+
+ public static void main(String[] args) {
+ test();
+ }
+}
diff --git a/test/hotspot/jtreg/compiler/vectorization/runner/LoopCombinedOpTest.java b/test/hotspot/jtreg/compiler/vectorization/runner/LoopCombinedOpTest.java
index cddc5207d42..16d04102082 100644
--- a/test/hotspot/jtreg/compiler/vectorization/runner/LoopCombinedOpTest.java
+++ b/test/hotspot/jtreg/compiler/vectorization/runner/LoopCombinedOpTest.java
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2022, 2023, Arm Limited. All rights reserved.
- * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -223,6 +223,8 @@ public int[] multipleOpsWith2DifferentTypesAndConstant() {
@Test
@IR(applyIfCPUFeatureOr = {"asimd", "true", "sse2", "true"},
+ // This test fails with compact headers, but only with UseSSE<=3.
+ applyIf = { "UseCompactObjectHeaders", "false" },
counts = {IRNode.STORE_VECTOR, ">0"})
public int[] multipleOpsWith2DifferentTypesAndInvariant() {
short[] res1 = new short[SIZE];
@@ -236,6 +238,8 @@ public int[] multipleOpsWith2DifferentTypesAndInvariant() {
@Test
@IR(applyIfCPUFeatureOr = {"asimd", "true", "sse2", "true"},
+ // This test fails with compact headers, but only with UseSSE<=3.
+ applyIf = { "UseCompactObjectHeaders", "false" },
counts = {IRNode.STORE_VECTOR, ">0"})
public int[] multipleOpsWith2DifferentTypesAndComplexExpression() {
short[] res1 = new short[SIZE];
diff --git a/test/hotspot/jtreg/compiler/whitebox/TestCompileAbstractMethod.java b/test/hotspot/jtreg/compiler/whitebox/TestCompileAbstractMethod.java
new file mode 100644
index 00000000000..47478d6e0ad
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/whitebox/TestCompileAbstractMethod.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @summary Verify WhiteBox compile abstract method doesn't hit assert.
+ * @requires vm.compiler2.enabled
+ * @requires vm.compMode != "Xcomp"
+ * @library /test/lib /
+ * @build jdk.test.whitebox.WhiteBox
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
+ *
+ * @run main/othervm -ea -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:-BackgroundCompilation TestCompileAbstractMethod
+ *
+ */
+
+import jdk.test.whitebox.WhiteBox;
+import java.lang.reflect.Method;
+import compiler.whitebox.CompilerWhiteBoxTest;
+
+public class TestCompileAbstractMethod {
+ private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
+
+ public static void main(String[] args) throws NoSuchMethodException {
+ Method m1 = A.class.getDeclaredMethod("run");
+ assert m1 != null;
+ if (WHITE_BOX.enqueueMethodForCompilation(m1, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION)) {
+ throw new RuntimeException("Abstract method should not be enqueued");
+ }
+ }
+
+ abstract class A {
+ public abstract void run();
+ }
+}
diff --git a/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java b/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java
index d37bf567381..2a7886a2106 100644
--- a/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java
+++ b/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -259,7 +259,6 @@ private void testConcurrentRefinementLogs() throws Exception {
LogMessageWithLevel exhFailureMessages[] = new LogMessageWithLevel[] {
new LogMessageWithLevel("Recalculate Used Memory \\(ms\\):", Level.DEBUG),
- new LogMessageWithLevel("Restore Preserved Marks \\(ms\\):", Level.DEBUG),
new LogMessageWithLevel("Restore Evacuation Failed Regions \\(ms\\):", Level.DEBUG),
new LogMessageWithLevel("Process Evacuation Failed Regions \\(ms\\):", Level.DEBUG),
new LogMessageWithLevel("Evacuation Failed Regions:", Level.DEBUG),
diff --git a/test/hotspot/jtreg/gc/g1/plab/TestPLABPromotion.java b/test/hotspot/jtreg/gc/g1/plab/TestPLABPromotion.java
index 2e7ebc2370f..88d11c10fa0 100644
--- a/test/hotspot/jtreg/gc/g1/plab/TestPLABPromotion.java
+++ b/test/hotspot/jtreg/gc/g1/plab/TestPLABPromotion.java
@@ -32,7 +32,7 @@
* @modules java.management
* @build jdk.test.whitebox.WhiteBox
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
- * @run main/timeout=240 gc.g1.plab.TestPLABPromotion
+ * @run main/othervm/timeout=240 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI gc.g1.plab.TestPLABPromotion
*/
package gc.g1.plab;
@@ -48,12 +48,15 @@
import jdk.test.lib.Platform;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
+import jdk.test.whitebox.WhiteBox;
/**
* Test checks PLAB promotion of different size objects.
*/
public class TestPLABPromotion {
+ private static final boolean COMPACT_HEADERS = Platform.is64bit() && WhiteBox.getWhiteBox().getBooleanVMFlag("UseCompactObjectHeaders");
+
// GC ID with survivor PLAB statistics
private final static long GC_ID_SURVIVOR_STATS = 1l;
// GC ID with old PLAB statistics
@@ -74,7 +77,7 @@ public class TestPLABPromotion {
private static final int PLAB_SIZE_HIGH = 65536;
private static final int OBJECT_SIZE_SMALL = 10 * HEAP_WORD_SIZE;
private static final int OBJECT_SIZE_MEDIUM = 128 * HEAP_WORD_SIZE;
- private static final int OBJECT_SIZE_HIGH = 3072 * HEAP_WORD_SIZE;
+ private static final int OBJECT_SIZE_HIGH = (COMPACT_HEADERS ? 3266 : 3250) * HEAP_WORD_SIZE;
private static final int GC_NUM_SMALL = 1;
private static final int GC_NUM_MEDIUM = 3;
private static final int GC_NUM_HIGH = 7;
diff --git a/test/hotspot/jtreg/gtest/CompressedKlassGtest.java b/test/hotspot/jtreg/gtest/CompressedKlassGtest.java
index e6377a8570d..fce30285312 100644
--- a/test/hotspot/jtreg/gtest/CompressedKlassGtest.java
+++ b/test/hotspot/jtreg/gtest/CompressedKlassGtest.java
@@ -35,5 +35,26 @@
* @library /test/lib
* @modules java.base/jdk.internal.misc
* java.xml
- * @run main/native GTestWrapper --gtest_filter=CompressedKlass* -Xlog:metaspace* -Xmx6g -Xms128m -Xshare:off -XX:CompressedClassSpaceSize=128m
+ * @run main/native GTestWrapper --gtest_filter=CompressedKlass* -XX:+UnlockExperimentalVMOptions -XX:-UseCompactObjectHeaders -Xlog:metaspace* -Xmx6g -Xms128m -Xshare:off -XX:CompressedClassSpaceSize=128m
+ */
+
+/* @test id=ccp_off
+ * @library /test/lib
+ * @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
+ * @modules java.base/jdk.internal.misc
+ * java.xml
+ * @run main/native GTestWrapper --gtest_filter=CompressedKlass* -XX:+UnlockExperimentalVMOptions -XX:+UseCompactObjectHeaders -Xlog:metaspace* -Xmx6g -Xms128m -Xshare:off -XX:CompressedClassSpaceSize=128m
+ */
+
+/* @test id=use-zero-based-encoding-coh-large-class-space
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * java.xml
+ * @run main/native GTestWrapper --gtest_filter=CompressedKlass* -XX:+UnlockExperimentalVMOptions -XX:+UseCompactObjectHeaders -Xlog:metaspace* -Xmx6g -Xms128m -Xshare:off -XX:CompressedClassSpaceSize=4g
*/
diff --git a/test/hotspot/jtreg/gtest/MetaspaceGtests.java b/test/hotspot/jtreg/gtest/MetaspaceGtests.java
index f1f811d6a71..fac88588e31 100644
--- a/test/hotspot/jtreg/gtest/MetaspaceGtests.java
+++ b/test/hotspot/jtreg/gtest/MetaspaceGtests.java
@@ -49,3 +49,14 @@
* @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
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * java.xml
+ * @requires vm.bits == 64
+ * @requires vm.flagless
+ * @requires vm.debug
+ * @run main/native GTestWrapper --gtest_filter=metaspace* -XX:+UnlockExperimentalVMOptions -XX:+UseCompactObjectHeaders
+ */
diff --git a/test/hotspot/jtreg/gtest/MetaspaceUtilsGtests.java b/test/hotspot/jtreg/gtest/MetaspaceUtilsGtests.java
index 7a9b1c8dfb3..e69de29bb2d 100644
--- a/test/hotspot/jtreg/gtest/MetaspaceUtilsGtests.java
+++ b/test/hotspot/jtreg/gtest/MetaspaceUtilsGtests.java
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-/*
- * Note: This runs the metaspace utils related parts of gtest in configurations which
- * are not tested explicitly in the standard gtests.
- *
- */
-
-/* @test
- * @bug 8264008
- * @summary Run metaspace utils related gtests with compressed class pointers off
- * @requires vm.bits == 64
- * @library /test/lib
- * @modules java.base/jdk.internal.misc
- * java.xml
- * @requires vm.flagless
- * @run main/native GTestWrapper --gtest_filter=MetaspaceUtils* -XX:-UseCompressedClassPointers
- */
diff --git a/test/hotspot/jtreg/runtime/CompressedOops/CompressedCPUSpecificClassSpaceReservation.java b/test/hotspot/jtreg/runtime/CompressedOops/CompressedCPUSpecificClassSpaceReservation.java
index f1b4c7143b4..574a680aceb 100644
--- a/test/hotspot/jtreg/runtime/CompressedOops/CompressedCPUSpecificClassSpaceReservation.java
+++ b/test/hotspot/jtreg/runtime/CompressedOops/CompressedCPUSpecificClassSpaceReservation.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -56,6 +56,7 @@ private static void do_test(boolean CDS) throws IOException {
"-Xshare:" + (CDS ? "on" : "off"),
"-Xmx128m",
"-XX:CompressedClassSpaceSize=128m",
+ "-XX:+UnlockExperimentalVMOptions", "-XX:-UseCompactObjectHeaders",
"-Xlog:metaspace*", "-Xlog:metaspace+map=trace", "-Xlog:os+map=trace",
"-XX:+SimulateFullAddressSpace", // So that no resevation attempt will succeed
"-version");
diff --git a/test/hotspot/jtreg/runtime/CompressedOops/CompressedClassPointers.java b/test/hotspot/jtreg/runtime/CompressedOops/CompressedClassPointers.java
index 4feadfb5565..e4b6f2a0548 100644
--- a/test/hotspot/jtreg/runtime/CompressedOops/CompressedClassPointers.java
+++ b/test/hotspot/jtreg/runtime/CompressedOops/CompressedClassPointers.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -46,6 +46,7 @@ public class CompressedClassPointers {
static final String logging_option = "-Xlog:gc+metaspace=trace,metaspace=info,cds=trace";
static final String reserveCCSAnywhere = "Reserving compressed class space anywhere";
+ static final String usesCompactObjectHeadersPat = "UseCompactObjectHeaders 1";
// Returns true if we are to test the narrow klass base; we only do this on
// platforms where we can be reasonably shure that we get reproducable placement).
@@ -57,6 +58,11 @@ static boolean testNarrowKlassBase() {
}
+ // Returns true if the output indicates that the VM uses compact object headers
+ static boolean usesCompactObjectHeaders(OutputAnalyzer output) {
+ return output.getOutput().contains(usesCompactObjectHeadersPat);
+ }
+
// Returns true if the output indicates that the ccs is reserved anywhere.
static boolean isCCSReservedAnywhere(OutputAnalyzer output) {
if (output.getOutput().contains(reserveCCSAnywhere)) {
@@ -221,7 +227,7 @@ public static void smallHeapTestNoCoop() throws Exception {
"-Xlog:cds=trace",
"-XX:+VerifyBeforeGC", "-version");
OutputAnalyzer output = new OutputAnalyzer(pb.start());
- if (!isCCSReservedAnywhere(output)) {
+ if (!isCCSReservedAnywhere(output) && !usesCompactObjectHeaders(output)) {
output.shouldContain("Narrow klass base: 0x0000000000000000");
}
output.shouldHaveExitValue(0);
@@ -239,10 +245,10 @@ public static void smallHeapTestWith1GNoCoop() throws Exception {
"-Xlog:cds=trace",
"-XX:+VerifyBeforeGC", "-version");
OutputAnalyzer output = new OutputAnalyzer(pb.start());
- if (!isCCSReservedAnywhere(output)) {
+ if (!isCCSReservedAnywhere(output) && !usesCompactObjectHeaders(output)) {
output.shouldContain("Narrow klass base: 0x0000000000000000");
}
- if (!Platform.isAArch64() && !Platform.isPPC()) {
+ if (!Platform.isAArch64() && !usesCompactObjectHeaders(output) && !Platform.isPPC()) {
// Currently relax this test for Aarch64 and ppc.
output.shouldContain("Narrow klass shift: 0");
}
@@ -261,10 +267,10 @@ public static void largeHeapTestNoCoop() throws Exception {
"-Xlog:cds=trace",
"-XX:+VerifyBeforeGC", "-version");
OutputAnalyzer output = new OutputAnalyzer(pb.start());
- if (!isCCSReservedAnywhere(output)) {
+ if (!isCCSReservedAnywhere(output) && !usesCompactObjectHeaders(output)) {
output.shouldContain("Narrow klass base: 0x0000000000000000");
}
- if (!Platform.isAArch64() && !Platform.isPPC()) {
+ if (!Platform.isAArch64() && !usesCompactObjectHeaders(output) && !Platform.isPPC()) {
// Currently relax this test for Aarch64 and ppc.
output.shouldContain("Narrow klass shift: 0");
}
diff --git a/test/hotspot/jtreg/runtime/CompressedOops/CompressedClassPointersEncodingScheme.java b/test/hotspot/jtreg/runtime/CompressedOops/CompressedClassPointersEncodingScheme.java
index 070c856a322..665c4cb8b9f 100644
--- a/test/hotspot/jtreg/runtime/CompressedOops/CompressedClassPointersEncodingScheme.java
+++ b/test/hotspot/jtreg/runtime/CompressedOops/CompressedClassPointersEncodingScheme.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -42,13 +42,16 @@
public class CompressedClassPointersEncodingScheme {
- private static void test(long forceAddress, long classSpaceSize, long expectedEncodingBase, int expectedEncodingShift) throws IOException {
+ private static void test(long forceAddress, boolean COH, long classSpaceSize, long expectedEncodingBase, int expectedEncodingShift) throws IOException {
String forceAddressString = String.format("0x%016X", forceAddress).toLowerCase();
String expectedEncodingBaseString = String.format("0x%016X", expectedEncodingBase).toLowerCase();
ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(
"-Xshare:off", // to make CompressedClassSpaceBaseAddress work
"-XX:+UnlockDiagnosticVMOptions",
"-XX:-UseCompressedOops", // keep VM from optimizing heap location
+ "-XX:+UnlockExperimentalVMOptions",
+ "-XX:" + (COH ? "+" : "-") + "UseCompactObjectHeaders",
+ "-XX:" + (COH ? "+" : "-") + "UseObjectMonitorTable",
"-XX:CompressedClassSpaceBaseAddress=" + forceAddress,
"-XX:CompressedClassSpaceSize=" + classSpaceSize,
"-Xmx128m",
@@ -60,7 +63,8 @@ private static void test(long forceAddress, long classSpaceSize, long expectedEn
// We ignore cases where we were not able to map at the force address
if (output.contains("reserving class space failed")) {
- throw new SkippedException("Skipping because we cannot force ccs to " + forceAddressString);
+ System.out.println("Skipping because we cannot force ccs to " + forceAddressString);
+ return;
}
output.shouldHaveExitValue(0);
@@ -73,9 +77,51 @@ private static void test(long forceAddress, long classSpaceSize, long expectedEn
public static void main(String[] args) throws Exception {
// Test ccs nestling right at the end of the 4G range
// Expecting base=0, shift=0
- test(4 * G - 128 * M, 128 * M, 0, 0);
+ test(4 * G - 128 * M, false, 128 * M, 0, 0);
+ // Test ccs nestling right at the end of the 32G range
+ // Expecting:
+ // - non-aarch64: base=0, shift=3
+ // - aarch64: base to start of class range, shift 0
+ if (Platform.isAArch64()) {
+ // The best we can do on aarch64 is to be *near* the end of the 32g range, since a valid encoding base
+ // on aarch64 must be 4G aligned, and the max. class space size is 3G.
+ long forceAddress = 0x7_0000_0000L; // 28g, and also a valid EOR immediate
+ test(forceAddress, false, 3 * G, forceAddress, 0);
+ } else {
+ test(32 * G - 128 * M, false, 128 * M, 0, 3);
+ }
+
+ // Test ccs starting *below* 4G, but extending upwards beyond 4G. All platforms except aarch64 should pick
+ // zero based encoding. On aarch64, this test is excluded since the only valid mode would be XOR, but bit
+ // pattern for base and bit pattern would overlap.
+ if (!Platform.isAArch64()) {
+ test(4 * G - 128 * M, false, 2 * 128 * M, 0, 3);
+ }
// add more...
+ // Compact Object Header Mode:
+ // On aarch64 and x64 we expect the VM to chose the smallest possible shift value needed to cover
+ // the encoding range. We expect the encoding Base to start at the class space start - but to enforce that,
+ // we choose a high address.
+ if (Platform.isAArch64() || Platform.isX64() || Platform.isRISCV64()) {
+ long forceAddress = 32 * G;
+
+ long ccsSize = 128 * M;
+ int expectedShift = 6;
+ test(forceAddress, true, ccsSize, forceAddress, expectedShift);
+
+ ccsSize = 512 * M;
+ expectedShift = 8;
+ test(forceAddress, true, ccsSize, forceAddress, expectedShift);
+
+ ccsSize = G;
+ expectedShift = 9;
+ test(forceAddress, true, ccsSize, forceAddress, expectedShift);
+
+ ccsSize = 3 * G;
+ expectedShift = 10;
+ test(forceAddress, true, ccsSize, forceAddress, expectedShift);
+ }
}
}
diff --git a/test/hotspot/jtreg/runtime/FieldLayout/ArrayBaseOffsets.java b/test/hotspot/jtreg/runtime/FieldLayout/ArrayBaseOffsets.java
index b679e866ac8..e69de29bb2d 100644
--- a/test/hotspot/jtreg/runtime/FieldLayout/ArrayBaseOffsets.java
+++ b/test/hotspot/jtreg/runtime/FieldLayout/ArrayBaseOffsets.java
@@ -1,113 +0,0 @@
-/*
- * Copyright Amazon.com Inc. or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test id=with-coops-no-ccp
- * @library /test/lib
- * @requires vm.bits == "64"
- * @modules java.base/jdk.internal.misc
- * @run main/othervm -XX:+UseCompressedOops -XX:-UseCompressedClassPointers ArrayBaseOffsets
- */
-/*
- * @test id=with-coops-with-ccp
- * @library /test/lib
- * @requires vm.bits == "64"
- * @requires vm.opt.UseCompressedClassPointers != false
- * @modules java.base/jdk.internal.misc
- * @run main/othervm -XX:+UseCompressedOops -XX:+UseCompressedClassPointers ArrayBaseOffsets
- */
-/*
- * @test id=no-coops-no-ccp
- * @library /test/lib
- * @requires vm.bits == "64"
- * @modules java.base/jdk.internal.misc
- * @run main/othervm -XX:-UseCompressedOops -XX:-UseCompressedClassPointers ArrayBaseOffsets
- */
-/*
- * @test id=no-coops-with-ccp
- * @library /test/lib
- * @requires vm.bits == "64"
- * @requires vm.opt.UseCompressedClassPointers != false
- * @modules java.base/jdk.internal.misc
- * @run main/othervm -XX:-UseCompressedOops -XX:+UseCompressedClassPointers ArrayBaseOffsets
- */
-/*
- * @test id=32bit
- * @library /test/lib
- * @requires vm.bits == "32"
- * @modules java.base/jdk.internal.misc
- * @run main/othervm ArrayBaseOffsets
- */
-
-import jdk.internal.misc.Unsafe;
-
-import java.lang.management.ManagementFactory;
-import java.lang.management.RuntimeMXBean;
-import java.util.List;
-
-import jdk.test.lib.Asserts;
-import jdk.test.lib.Platform;
-
-public class ArrayBaseOffsets {
-
- private static final boolean COOP;
- private static final boolean CCP;
-
- static {
- if (Platform.is64bit()) {
- RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
- List vmargs = runtime.getInputArguments();
- CCP = !vmargs.contains("-XX:-UseCompressedClassPointers");
- COOP = System.getProperty("java.vm.compressedOopsMode") != null;
- } else {
- COOP = CCP = false;
- }
- }
-
- static public void main(String[] args) {
- Unsafe unsafe = Unsafe.getUnsafe();
- int intOffset, longOffset;
- if (Platform.is64bit()) {
- if (CCP) {
- intOffset = 16;
- longOffset = 16;
- } else {
- intOffset = 20;
- longOffset = 24;
- }
- } else {
- intOffset = 12;
- longOffset = 16;
- }
- Asserts.assertEquals(unsafe.arrayBaseOffset(boolean[].class), intOffset, "Misplaced boolean array base");
- Asserts.assertEquals(unsafe.arrayBaseOffset(byte[].class), intOffset, "Misplaced byte array base");
- Asserts.assertEquals(unsafe.arrayBaseOffset(char[].class), intOffset, "Misplaced char array base");
- Asserts.assertEquals(unsafe.arrayBaseOffset(short[].class), intOffset, "Misplaced short array base");
- Asserts.assertEquals(unsafe.arrayBaseOffset(int[].class), intOffset, "Misplaced int array base");
- Asserts.assertEquals(unsafe.arrayBaseOffset(long[].class), longOffset, "Misplaced long array base");
- Asserts.assertEquals(unsafe.arrayBaseOffset(float[].class), intOffset, "Misplaced float array base");
- Asserts.assertEquals(unsafe.arrayBaseOffset(double[].class), longOffset, "Misplaced double array base");
- int expectedObjArrayOffset = (COOP || !Platform.is64bit()) ? intOffset : longOffset;
- Asserts.assertEquals(unsafe.arrayBaseOffset(Object[].class), expectedObjArrayOffset, "Misplaced object array base");
- }
-}
diff --git a/test/hotspot/jtreg/runtime/FieldLayout/BaseOffsets.java b/test/hotspot/jtreg/runtime/FieldLayout/BaseOffsets.java
new file mode 100644
index 00000000000..e4f88b5d8d5
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/FieldLayout/BaseOffsets.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test id=with-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:+UnlockExperimentalVMOptions -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:+UnlockExperimentalVMOptions -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:+UnlockExperimentalVMOptions -XX:+UseCompressedOops -XX:-UseCompressedClassPointers -XX:-UseCompactObjectHeaders BaseOffsets
+ */
+/*
+ * @test id=no-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:+UnlockExperimentalVMOptions -XX:-UseCompressedOops -XX:-UseCompressedClassPointers -XX:-UseCompactObjectHeaders BaseOffsets
+ */
+/*
+ * @test id=with-coop--with-coh
+ * @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:+UnlockExperimentalVMOptions -XX:+UseCompressedOops -XX:+UseCompactObjectHeaders BaseOffsets
+ */
+/*
+ * @test id=no-coops-with-coh
+ * @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:+UnlockExperimentalVMOptions -XX:-UseCompressedOops -XX:+UseCompactObjectHeaders BaseOffsets
+ */
+/*
+ * @test id=32bit
+ * @library /test/lib /
+ * @requires vm.bits == "32"
+ * @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 BaseOffsets
+ */
+
+import java.lang.reflect.Field;
+import java.util.Arrays;
+import java.util.Comparator;
+import jdk.internal.misc.Unsafe;
+
+import jdk.test.lib.Asserts;
+import jdk.test.lib.Platform;
+import jdk.test.whitebox.WhiteBox;
+
+public class BaseOffsets {
+
+ static class LIClass {
+ public int i;
+ }
+
+ public static final WhiteBox WB = WhiteBox.getWhiteBox();
+
+ static final long INT_OFFSET;
+ static final int INT_ARRAY_OFFSET;
+ static final int LONG_ARRAY_OFFSET;
+ static {
+ if (!Platform.is64bit() || WB.getBooleanVMFlag("UseCompactObjectHeaders")) {
+ INT_OFFSET = 8;
+ INT_ARRAY_OFFSET = 12;
+ LONG_ARRAY_OFFSET = 16;
+ } else if (WB.getBooleanVMFlag("UseCompressedClassPointers")) {
+ INT_OFFSET = 12;
+ INT_ARRAY_OFFSET = 16;
+ LONG_ARRAY_OFFSET = 16;
+ } else {
+ INT_OFFSET = 16;
+ INT_ARRAY_OFFSET = 20;
+ LONG_ARRAY_OFFSET = 24;
+ }
+ }
+
+ static public void main(String[] args) {
+ Unsafe unsafe = Unsafe.getUnsafe();
+ Class c = LIClass.class;
+ Field[] fields = c.getFields();
+ for (int i = 0; i < fields.length; i++) {
+ long offset = unsafe.objectFieldOffset(fields[i]);
+ if (fields[i].getType() == int.class) {
+ Asserts.assertEquals(offset, INT_OFFSET, "Misplaced int field");
+ } else {
+ Asserts.fail("Unexpected field type");
+ }
+ }
+
+ Asserts.assertEquals(unsafe.arrayBaseOffset(boolean[].class), INT_ARRAY_OFFSET, "Misplaced boolean array base");
+ Asserts.assertEquals(unsafe.arrayBaseOffset(byte[].class), INT_ARRAY_OFFSET, "Misplaced byte array base");
+ Asserts.assertEquals(unsafe.arrayBaseOffset(char[].class), INT_ARRAY_OFFSET, "Misplaced char array base");
+ Asserts.assertEquals(unsafe.arrayBaseOffset(short[].class), INT_ARRAY_OFFSET, "Misplaced short array base");
+ Asserts.assertEquals(unsafe.arrayBaseOffset(int[].class), INT_ARRAY_OFFSET, "Misplaced int array base");
+ Asserts.assertEquals(unsafe.arrayBaseOffset(long[].class), LONG_ARRAY_OFFSET, "Misplaced long array base");
+ Asserts.assertEquals(unsafe.arrayBaseOffset(float[].class), INT_ARRAY_OFFSET, "Misplaced float array base");
+ Asserts.assertEquals(unsafe.arrayBaseOffset(double[].class), LONG_ARRAY_OFFSET, "Misplaced double array base");
+ boolean narrowOops = System.getProperty("java.vm.compressedOopsMode") != null ||
+ !Platform.is64bit();
+ int expected_objary_offset = narrowOops ? INT_ARRAY_OFFSET : LONG_ARRAY_OFFSET;
+ Asserts.assertEquals(unsafe.arrayBaseOffset(Object[].class), expected_objary_offset, "Misplaced object array base");
+ }
+}
diff --git a/test/hotspot/jtreg/runtime/cds/DeterministicDump.java b/test/hotspot/jtreg/runtime/cds/DeterministicDump.java
index cc8d8c2b1dd..6b6431c0e5e 100644
--- a/test/hotspot/jtreg/runtime/cds/DeterministicDump.java
+++ b/test/hotspot/jtreg/runtime/cds/DeterministicDump.java
@@ -50,8 +50,10 @@ public static void main(String[] args) throws Exception {
public static void doTest(boolean compressed) throws Exception {
ArrayList baseArgs = new ArrayList<>();
- // Use the same heap size as make/Images.gmk
+ // Try to reduce indeterminism of GC heap sizing and evacuation.
baseArgs.add("-Xmx128M");
+ baseArgs.add("-Xms128M");
+ baseArgs.add("-Xmn120M");
if (Platform.is64bit()) {
// This option is available only on 64-bit.
@@ -80,7 +82,7 @@ static String dump(ArrayList args, String... more) throws Exception {
String mapName = logName + ".map";
CDSOptions opts = (new CDSOptions())
.addPrefix("-Xint") // Override any -Xmixed/-Xcomp flags from jtreg -vmoptions
- .addPrefix("-Xlog:cds=debug")
+ .addPrefix("-Xlog:cds=debug,gc=debug")
.addPrefix("-Xlog:cds+map*=trace:file=" + mapName + ":none:filesize=0")
.setArchiveName(archiveName)
.addSuffix(args)
diff --git a/test/hotspot/jtreg/runtime/cds/TestDefaultArchiveLoading.java b/test/hotspot/jtreg/runtime/cds/TestDefaultArchiveLoading.java
new file mode 100644
index 00000000000..590f22feed7
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/cds/TestDefaultArchiveLoading.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2024, Red Hat, Inc. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test id=nocoops_nocoh
+ * @summary Test Loading of default archives in all configurations
+ * @requires vm.cds
+ * @requires vm.bits == 64
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * java.management
+ * @run driver TestDefaultArchiveLoading nocoops_nocoh
+ */
+
+/**
+ * @test id=nocoops_coh
+ * @summary Test Loading of default archives in all configurations (requires --enable-cds-archive-coh)
+ * @requires vm.cds
+ * @requires vm.bits == 64
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * java.management
+ * @run driver TestDefaultArchiveLoading nocoops_coh
+ */
+
+/**
+ * @test id=coops_nocoh
+ * @summary Test Loading of default archives in all configurations
+ * @requires vm.cds
+ * @requires vm.bits == 64
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * java.management
+ * @run driver TestDefaultArchiveLoading coops_nocoh
+ */
+
+/**
+ * @test id=coops_coh
+ * @summary Test Loading of default archives in all configurations (requires --enable-cds-archive-coh)
+ * @requires vm.cds
+ * @requires vm.bits == 64
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * java.management
+ * @run driver TestDefaultArchiveLoading coops_coh
+ */
+
+import jdk.test.lib.Platform;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+import jtreg.SkippedException;
+
+public class TestDefaultArchiveLoading {
+ public static void main(String[] args) throws Exception {
+
+ if (args.length != 1) {
+ throw new RuntimeException("Expected argument");
+ }
+
+ String archiveSuffix;
+ char coh, coops;
+
+ switch (args[0]) {
+ case "nocoops_nocoh":
+ coh = coops = '-';
+ archiveSuffix = "_nocoops";
+ break;
+ case "nocoops_coh":
+ coops = '-';
+ coh = '+';
+ archiveSuffix = "_nocoops_coh";
+ break;
+ case "coops_nocoh":
+ coops = '+';
+ coh = '-';
+ archiveSuffix = "";
+ break;
+ case "coops_coh":
+ coh = coops = '+';
+ archiveSuffix = "_coh";
+ break;
+ default: throw new RuntimeException("Invalid argument " + args[0]);
+ }
+
+ ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(
+ "-XX:+UnlockExperimentalVMOptions",
+ "-XX:" + coh + "UseCompactObjectHeaders",
+ "-XX:" + coops + "UseCompressedOops",
+ "-Xlog:cds",
+ "-Xshare:on", // fail if we cannot load archive
+ "-version");
+
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+ output.shouldHaveExitValue(0);
+
+ output.shouldContain("classes" + archiveSuffix + ".jsa");
+
+ }
+}
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/TestZGCWithCDS.java b/test/hotspot/jtreg/runtime/cds/appcds/TestZGCWithCDS.java
index 89fc346ffbb..e2e0f1bdf77 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/TestZGCWithCDS.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/TestZGCWithCDS.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 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
@@ -42,12 +42,15 @@ public class TestZGCWithCDS {
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 static void main(String... args) throws Exception {
+ String compactHeaders = "-XX:+UseCompactObjectHeaders";
String helloJar = JarBuilder.build("hello", "Hello");
System.out.println("0. Dump with ZGC");
OutputAnalyzer out = TestCommon
.dump(helloJar,
new String[] {"Hello"},
"-XX:+UseZGC",
+ "-XX:+UnlockExperimentalVMOptions",
+ compactHeaders,
"-Xlog:cds");
out.shouldContain("Dumping shared data to file:");
out.shouldHaveExitValue(0);
@@ -56,6 +59,8 @@ public static void main(String... args) throws Exception {
out = TestCommon
.exec(helloJar,
"-XX:+UseZGC",
+ "-XX:+UnlockExperimentalVMOptions",
+ compactHeaders,
"-Xlog:cds",
"Hello");
out.shouldContain(HELLO);
@@ -67,6 +72,8 @@ public static void main(String... args) throws Exception {
"-XX:-UseZGC",
"-XX:+UseCompressedOops", // in case turned off by vmoptions
"-XX:+UseCompressedClassPointers", // by jtreg
+ "-XX:+UnlockExperimentalVMOptions",
+ compactHeaders,
"-Xlog:cds",
"Hello");
out.shouldContain(UNABLE_TO_USE_ARCHIVE);
@@ -79,6 +86,8 @@ public static void main(String... args) throws Exception {
"-XX:+UseSerialGC",
"-XX:-UseCompressedOops",
"-XX:-UseCompressedClassPointers",
+ "-XX:+UnlockExperimentalVMOptions",
+ compactHeaders,
"-Xlog:cds",
"Hello");
out.shouldContain(UNABLE_TO_USE_ARCHIVE);
@@ -91,6 +100,8 @@ public static void main(String... args) throws Exception {
"-XX:+UseSerialGC",
"-XX:-UseCompressedOops",
"-XX:+UseCompressedClassPointers",
+ "-XX:+UnlockExperimentalVMOptions",
+ compactHeaders,
"-Xlog:cds",
"Hello");
out.shouldContain(HELLO);
@@ -102,6 +113,8 @@ public static void main(String... args) throws Exception {
"-XX:+UseSerialGC",
"-XX:+UseCompressedOops",
"-XX:-UseCompressedClassPointers",
+ "-XX:+UnlockExperimentalVMOptions",
+ compactHeaders,
"-Xlog:cds",
"Hello");
out.shouldContain(UNABLE_TO_USE_ARCHIVE);
@@ -114,6 +127,8 @@ public static void main(String... args) throws Exception {
"-XX:+UseSerialGC",
"-XX:+UseCompressedOops",
"-XX:+UseCompressedClassPointers",
+ "-XX:+UnlockExperimentalVMOptions",
+ compactHeaders,
"-Xlog:cds",
"Hello");
out.shouldContain(UNABLE_TO_USE_ARCHIVE);
@@ -127,6 +142,8 @@ public static void main(String... args) throws Exception {
"-XX:+UseSerialGC",
"-XX:-UseCompressedOops",
"-XX:+UseCompressedClassPointers",
+ "-XX:+UnlockExperimentalVMOptions",
+ compactHeaders,
"-Xlog:cds");
out.shouldContain("Dumping shared data to file:");
out.shouldHaveExitValue(0);
@@ -135,6 +152,8 @@ public static void main(String... args) throws Exception {
out = TestCommon
.exec(helloJar,
"-XX:+UseZGC",
+ "-XX:+UnlockExperimentalVMOptions",
+ compactHeaders,
"-Xlog:cds",
"Hello");
out.shouldContain(HELLO);
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchiveNoDefaultArchive.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchiveNoDefaultArchive.java
index 46e08c7b754..133f44521d5 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchiveNoDefaultArchive.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchiveNoDefaultArchive.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -144,6 +144,7 @@ public static void main(String[] args) throws Exception {
private static void removeDefaultArchives(String java_home_dst, String variant) {
removeDefaultArchive(java_home_dst, variant, "");
removeDefaultArchive(java_home_dst, variant, "_nocoops");
+ removeDefaultArchive(java_home_dst, variant, "_coh");
}
private static void removeDefaultArchive(String java_home_dst, String variant, String suffix) {
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/addmods/AddmodsOption.java b/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/addmods/AddmodsOption.java
index 4bc779899ac..114dd6b9f3a 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/addmods/AddmodsOption.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/addmods/AddmodsOption.java
@@ -28,12 +28,19 @@
* @requires vm.cds.write.archived.java.heap
* @requires vm.flagless
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds
- * @run driver AddmodsOption
+ * @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 AddmodsOption
*/
import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.whitebox.WhiteBox;
public class AddmodsOption {
+
+ private static final WhiteBox WB = WhiteBox.getWhiteBox();
+ private static final boolean isJVMCISupported = (WB.getBooleanVMFlag("EnableJVMCI") != null);
+
public static void main(String[] args) throws Exception {
final String moduleOption = "jdk.httpserver/sun.net.httpserver.simpleserver.Main";
final String incubatorModule = "jdk.incubator.vector";
@@ -42,7 +49,7 @@ public static void main(String[] args) throws Exception {
final String allSystem = "ALL-SYSTEM";
final String allModulePath = "ALL-MODULE-PATH";
final String loggingOption = "-Xlog:cds=debug,cds+module=debug,cds+heap=info,module=trace";
- final String versionPattern = "java.[0-9][0-9][-].*";
+ final String versionPattern = "java.[0-9][0-9].*";
final String subgraphCannotBeUsed = "subgraph jdk.internal.module.ArchivedBootLayer cannot be used because full module graph is disabled";
final String warningIncubator = "WARNING: Using incubator modules: jdk.incubator.vector";
String archiveName = TestCommon.getNewArchiveName("addmods-option");
@@ -136,31 +143,33 @@ public static void main(String[] args) throws Exception {
.shouldContain("subgraph jdk.internal.module.ArchivedBootLayer is not recorde")
.shouldHaveExitValue(0);
- // dump an archive with JVMCI option which indirectly adds the
- // jdk.internal.vm.ci module using the --add-modules option
- archiveName = TestCommon.getNewArchiveName("jvmci-module");
- TestCommon.setCurrentArchiveName(archiveName);
- oa = TestCommon.dumpBaseArchive(
- archiveName,
- loggingOption,
- "-XX:+UnlockExperimentalVMOptions",
- "-XX:+EagerJVMCI", "-XX:+UseJVMCICompiler",
- "-version");
- oa.shouldHaveExitValue(0);
-
- // run with the JVMCI option
- oa = TestCommon.execCommon(
- loggingOption,
- "-XX:+UnlockExperimentalVMOptions",
- "-XX:+EagerJVMCI", "-XX:+UseJVMCICompiler",
- "-version");
- try {
- oa.shouldHaveExitValue(0)
- .shouldMatch("cds,module.*Restored from archive: entry.0x.*name jdk.internal.vm.ci");
- } catch (RuntimeException re) {
- // JVMCI compile may not be available
- oa.shouldHaveExitValue(1)
- .shouldContain("Cannot use JVMCI compiler: No JVMCI compiler found");
+ if (isJVMCISupported) {
+ // dump an archive with JVMCI option which indirectly adds the
+ // jdk.internal.vm.ci module using the --add-modules option
+ archiveName = TestCommon.getNewArchiveName("jvmci-module");
+ TestCommon.setCurrentArchiveName(archiveName);
+ oa = TestCommon.dumpBaseArchive(
+ archiveName,
+ loggingOption,
+ "-XX:+UnlockExperimentalVMOptions",
+ "-XX:+EagerJVMCI", "-XX:+UseJVMCICompiler",
+ "-version");
+ oa.shouldHaveExitValue(0);
+
+ // run with the JVMCI option
+ oa = TestCommon.execCommon(
+ loggingOption,
+ "-XX:+UnlockExperimentalVMOptions",
+ "-XX:+EagerJVMCI", "-XX:+UseJVMCICompiler",
+ "-version");
+ try {
+ oa.shouldHaveExitValue(0)
+ .shouldMatch("cds,module.*Restored from archive: entry.0x.*name jdk.internal.vm.ci");
+ } catch (RuntimeException re) {
+ // JVMCI compile may not be available
+ oa.shouldHaveExitValue(1)
+ .shouldContain("Cannot use JVMCI compiler: No JVMCI compiler found");
+ }
}
// dump an archive with multiple modules in -add-modules
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/NewChild.java b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/NewChild.java
new file mode 100644
index 00000000000..b11eb9717f1
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/NewChild.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+public class NewChild extends OldSuper {
+ // Does not override BootSuper::doit()
+}
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/OldClassAndRedefineClass.java b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/OldClassAndRedefineClass.java
new file mode 100644
index 00000000000..242a78ca024
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/OldClassAndRedefineClass.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/*
+ * @test
+ * @bug 8342303
+ * @summary Test loading of shared old class when another class has been redefined.
+ * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds /test/hotspot/jtreg/runtime/cds/appcds/test-classes /test/hotspot/jtreg/runtime/cds/appcds/jvmti
+ * @requires vm.cds.write.archived.java.heap
+ * @requires vm.jvmti
+ * @build jdk.test.whitebox.WhiteBox
+ * OldClassAndRedefineClassApp
+ * @compile ../../test-classes/OldSuper.jasm
+ * ../../test-classes/ChildOldSuper.java
+ * ../../test-classes/Hello.java
+ * @run driver RedefineClassHelper
+ * @run driver OldClassAndRedefineClass
+ */
+
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.helpers.ClassFileInstaller;
+
+public class OldClassAndRedefineClass {
+ public static String appClasses[] = {
+ "OldClassAndRedefineClassApp",
+ "OldSuper",
+ "ChildOldSuper",
+ "Hello",
+ };
+ public static String sharedClasses[] = TestCommon.concat(appClasses);
+
+ public static void main(String[] args) throws Throwable {
+ runTest();
+ }
+
+ public static void runTest() throws Throwable {
+ String appJar =
+ ClassFileInstaller.writeJar("OldClassAndRedefineClassApp.jar", appClasses);
+
+ String agentCmdArg = "-javaagent:redefineagent.jar";
+
+ OutputAnalyzer out = TestCommon.testDump(appJar, sharedClasses, "-Xlog:cds,cds+class=debug");
+ out.shouldMatch("klasses.*OldSuper.[*][*].unlinked")
+ .shouldMatch("klasses.*ChildOldSuper.[*][*].unlinked");
+
+ out = TestCommon.exec(
+ appJar,
+ "-XX:+UnlockDiagnosticVMOptions",
+ "-XX:+AllowArchivingWithJavaAgent",
+ "-XX:+WhiteBoxAPI",
+ "-Xlog:cds,class+load",
+ agentCmdArg,
+ "OldClassAndRedefineClassApp");
+ out.shouldContain("[class,load] OldSuper source: shared objects file")
+ .shouldContain("[class,load] ChildOldSuper source: shared objects file")
+ .shouldContain("[class,load] Hello source: __VM_RedefineClasses__");
+ }
+}
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/OldClassAndRedefineClassApp.java b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/OldClassAndRedefineClassApp.java
new file mode 100644
index 00000000000..2c460ccb027
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/OldClassAndRedefineClassApp.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+public class OldClassAndRedefineClassApp {
+
+ public static void main(String args[]) throws Throwable {
+ ClassLoader appClassLoader = ClassLoader.getSystemClassLoader();
+
+ System.out.println("Main: loading OldSuper");
+ // Load an old class (version 49), but not linking it.
+ Class.forName("OldSuper", false, appClassLoader);
+
+ // Redefine a class unrelated to the above old class.
+ System.out.println("INFO: instrumentation = " + RedefineClassHelper.instrumentation);
+ Class> c = Class.forName("Hello", false, appClassLoader);
+ byte[] bytes = c.getClassLoader().getResourceAsStream(c.getName().replace('.', '/') + ".class").readAllBytes();
+ RedefineClassHelper.redefineClass(c, bytes);
+
+ System.out.println("Main: loading ChildOldSuper");
+ // Load and link a subclass of the above old class.
+ // This will in turn link the old class and initializes its vtable, etc.
+ Class.forName("ChildOldSuper");
+ }
+}
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/RedefineBootClassApp.java b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/RedefineBootClassApp.java
new file mode 100644
index 00000000000..92642c467d2
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/RedefineBootClassApp.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+import java.io.File;
+
+public class RedefineBootClassApp {
+ public static void main(String args[]) throws Throwable {
+ File bootJar = new File(args[0]);
+
+ Class> superCls = Class.forName("BootSuper", false, null);
+ System.out.println("BootSuper>> loader = " + superCls.getClassLoader());
+
+ {
+ BootSuper obj = (BootSuper)superCls.newInstance();
+ System.out.println("(before transform) BootSuper>> doit() = " + obj.doit());
+ }
+
+ // Redefine the class
+ byte[] bytes = Util.getClassFileFromJar(bootJar, "BootSuper");
+ Util.replace(bytes, "Hello", "HELLO");
+ RedefineClassHelper.redefineClass(superCls, bytes);
+
+ {
+ BootSuper obj = (BootSuper)superCls.newInstance();
+ String s = obj.doit();
+ System.out.println("(after transform) BootSuper>> doit() = " + s);
+ if (!s.equals("HELLO")) {
+ throw new RuntimeException("BootSuper doit() should be HELLO but got " + s);
+ }
+ }
+
+ Class> childCls = Class.forName("BootChild", false, null);
+ System.out.println("BootChild>> loader = " + childCls.getClassLoader());
+
+
+ {
+ BootSuper obj = (BootSuper)childCls.newInstance();
+ String s = obj.doit();
+ System.out.println("(after transform) BootChild>> doit() = " + s);
+ if (!s.equals("HELLO")) {
+ throw new RuntimeException("BootChild doit() should be HELLO but got " + s);
+ }
+ }
+ }
+}
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/RedefineBootClassTest.java b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/RedefineBootClassTest.java
new file mode 100644
index 00000000000..bc14ec996f5
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/RedefineBootClassTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/*
+ * @test
+ * @bug 8342303
+ * @summary Redefine a shared super class loaded by the boot loader. The vtable of its archived child class must be updated
+ * @library /test/lib
+ * /test/hotspot/jtreg/runtime/cds/appcds
+ * /test/hotspot/jtreg/runtime/cds/appcds/test-classes
+ * /test/hotspot/jtreg/runtime/cds/appcds/jvmti
+ * @requires vm.jvmti
+ * @build RedefineBootClassTest
+ * RedefineBootClassApp
+ * BootSuper BootChild
+ * @run driver RedefineClassHelper
+ * @run driver RedefineBootClassTest
+ */
+
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.helpers.ClassFileInstaller;
+
+public class RedefineBootClassTest {
+ public static String bootClasses[] = {
+ "BootSuper",
+ "BootChild",
+ };
+ public static String appClasses[] = {
+ "RedefineBootClassApp",
+ "Util",
+ };
+ public static String sharedClasses[] = TestCommon.concat(bootClasses, appClasses);
+
+ public static void main(String[] args) throws Throwable {
+ runTest();
+ }
+
+ public static void runTest() throws Throwable {
+ String bootJar =
+ ClassFileInstaller.writeJar("RedefineClassBoot.jar", bootClasses);
+ String appJar =
+ ClassFileInstaller.writeJar("RedefineClassApp.jar", appClasses);
+
+ String bootCP = "-Xbootclasspath/a:" + bootJar;
+ String agentCmdArg = "-javaagent:redefineagent.jar";
+
+ TestCommon.testDump(appJar, sharedClasses, bootCP, "-Xlog:cds,cds+class=debug");
+
+ OutputAnalyzer out = TestCommon.execAuto("-cp", appJar,
+ bootCP,
+ "-XX:+UnlockDiagnosticVMOptions",
+ "-Xlog:cds=info,class+load",
+ agentCmdArg,
+ "RedefineBootClassApp", bootJar);
+ out.reportDiagnosticSummary();
+ TestCommon.checkExec(out);
+ }
+}
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/RedefineOldSuperApp.java b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/RedefineOldSuperApp.java
new file mode 100644
index 00000000000..c60edfd2891
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/RedefineOldSuperApp.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+import java.io.File;
+
+public class RedefineOldSuperApp {
+ public static void main(String args[]) throws Throwable {
+ File bootJar = new File(args[0]);
+ ClassLoader appClassLoader = ClassLoader.getSystemClassLoader();
+
+ Class> superCls = Class.forName("OldSuper", false, appClassLoader);
+ System.out.println("OldSuper>> loader = " + superCls.getClassLoader());
+
+ {
+ OldSuper obj = (OldSuper)superCls.newInstance();
+ System.out.println("(before transform) OldSuper>> doit() = " + obj.doit());
+ }
+
+ // Redefine the class
+ byte[] bytes = Util.getClassFileFromJar(bootJar, "OldSuper");
+ Util.replace(bytes, "Hello", "HELLO");
+ RedefineClassHelper.redefineClass(superCls, bytes);
+
+ {
+ OldSuper obj = (OldSuper)superCls.newInstance();
+ String s = obj.doit();
+ System.out.println("(after transform) OldSuper>> doit() = " + s);
+ if (!s.equals("HELLO")) {
+ throw new RuntimeException("OldSuper doit() should be HELLO but got " + s);
+ }
+ }
+
+ Class> childCls = Class.forName("NewChild", false, appClassLoader);
+ System.out.println("NewChild>> loader = " + childCls.getClassLoader());
+
+
+ {
+ OldSuper obj = (OldSuper)childCls.newInstance();
+ String s = obj.doit();
+ System.out.println("(after transform) NewChild>> doit() = " + s);
+ if (!s.equals("HELLO")) {
+ throw new RuntimeException("NewChild doit() should be HELLO but got " + s);
+ }
+ }
+ }
+}
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/RedefineOldSuperTest.java b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/RedefineOldSuperTest.java
new file mode 100644
index 00000000000..a0c8fa7a448
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/RedefineOldSuperTest.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/*
+ * @test
+ * @bug 8342303
+ * @summary Redefine a shared old super class loaded by the app loader. The vtable of its archived child class must be updated
+ * @library /test/lib
+ * /test/hotspot/jtreg/runtime/cds/appcds
+ * /test/hotspot/jtreg/runtime/cds/appcds/test-classes
+ * /test/hotspot/jtreg/runtime/cds/appcds/jvmti
+ * @requires vm.jvmti
+ * @compile ../../test-classes/OldSuper.jasm
+ * @build RedefineOldSuperTest
+ * RedefineOldSuperApp
+ * NewChild
+ * @run driver RedefineClassHelper
+ * @run driver RedefineOldSuperTest
+ */
+
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.helpers.ClassFileInstaller;
+
+public class RedefineOldSuperTest {
+ public static String appClasses[] = {
+ "OldSuper",
+ "NewChild",
+ "RedefineOldSuperApp",
+ "Util",
+ };
+ public static String sharedClasses[] = TestCommon.concat(appClasses);
+
+ public static void main(String[] args) throws Throwable {
+ runTest();
+ }
+
+ public static void runTest() throws Throwable {
+ String appJar =
+ ClassFileInstaller.writeJar("RedefineClassApp.jar", appClasses);
+
+ String agentCmdArg = "-javaagent:redefineagent.jar";
+
+ TestCommon.testDump(appJar, sharedClasses, "-Xlog:cds,cds+class=debug");
+
+ OutputAnalyzer out = TestCommon.execAuto("-cp", appJar,
+ "-XX:+UnlockDiagnosticVMOptions",
+ "-Xlog:cds=info,class+load",
+ agentCmdArg,
+ "RedefineOldSuperApp", appJar);
+ out.reportDiagnosticSummary();
+ TestCommon.checkExec(out);
+ }
+}
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/redefineClass/RedefineBasicTest.java b/test/hotspot/jtreg/runtime/cds/appcds/redefineClass/RedefineBasicTest.java
index acbd0c948be..fbdec462e09 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/redefineClass/RedefineBasicTest.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/redefineClass/RedefineBasicTest.java
@@ -30,7 +30,7 @@
* @requires vm.jvmti
* @library /test/lib /test/hotspot/jtreg/serviceability/jvmti/RedefineClasses /test/hotspot/jtreg/runtime/cds/appcds
* @run driver RedefineClassHelper
- * @build jdk.test.whitebox.WhiteBox RedefineBasic
+ * @build jdk.test.whitebox.WhiteBox jdk.test.lib.compiler.InMemoryJavaCompiler RedefineBasic
* @run driver RedefineBasicTest
*/
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/redefineClass/RedefineRunningMethods_Shared.java b/test/hotspot/jtreg/runtime/cds/appcds/redefineClass/RedefineRunningMethods_Shared.java
index 039aaef11cd..62bd62662a0 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/redefineClass/RedefineRunningMethods_Shared.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/redefineClass/RedefineRunningMethods_Shared.java
@@ -30,7 +30,7 @@
* @requires vm.jvmti
* @library /test/lib /test/hotspot/jtreg/serviceability/jvmti/RedefineClasses /test/hotspot/jtreg/runtime/cds/appcds
* @run driver RedefineClassHelper
- * @build jdk.test.whitebox.WhiteBox
+ * @build jdk.test.whitebox.WhiteBox jdk.test.lib.compiler.InMemoryJavaCompiler
* @compile RedefineRunningMethods_SharedHelper.java
* @run driver RedefineRunningMethods_Shared
*/
diff --git a/test/hotspot/jtreg/runtime/logging/RedefineClasses.java b/test/hotspot/jtreg/runtime/logging/RedefineClasses.java
index 34c8900e616..714c05174eb 100644
--- a/test/hotspot/jtreg/runtime/logging/RedefineClasses.java
+++ b/test/hotspot/jtreg/runtime/logging/RedefineClasses.java
@@ -30,6 +30,7 @@
* @modules java.compiler
* java.instrument
* @requires vm.jvmti
+ * @build jdk.test.lib.compiler.InMemoryJavaCompiler
* @run main RedefineClassHelper
* @run main/othervm -Xmx256m -XX:MaxMetaspaceSize=64m -javaagent:redefineagent.jar -Xlog:all=trace:file=all.log RedefineClasses
*/
diff --git a/test/hotspot/jtreg/serviceability/jvmti/GetMethodDeclaringClass/libTestUnloadedClass.cpp b/test/hotspot/jtreg/serviceability/jvmti/GetMethodDeclaringClass/libTestUnloadedClass.cpp
index c32b787d578..ad7708ba55d 100644
--- a/test/hotspot/jtreg/serviceability/jvmti/GetMethodDeclaringClass/libTestUnloadedClass.cpp
+++ b/test/hotspot/jtreg/serviceability/jvmti/GetMethodDeclaringClass/libTestUnloadedClass.cpp
@@ -39,9 +39,9 @@ static std::atomic ring_buffer[BUFFER_SIZE];
void get_method_details(jmethodID method) {
jclass method_class;
- char *class_name = NULL;
+ char *class_name = nullptr;
if (_jvmti->GetMethodDeclaringClass(method, &method_class) == JVMTI_ERROR_NONE) {
- if (_jvmti->GetClassSignature(method_class, &class_name, NULL) == JVMTI_ERROR_NONE) {
+ if (_jvmti->GetClassSignature(method_class, &class_name, nullptr) == JVMTI_ERROR_NONE) {
_jvmti->Deallocate((unsigned char *)class_name);
}
}
@@ -49,14 +49,14 @@ void get_method_details(jmethodID method) {
void* read_ringbuffer(void* arg) {
JNIEnv *env;
- _jvm->AttachCurrentThreadAsDaemon((void **)&env, NULL);
+ _jvm->AttachCurrentThreadAsDaemon((void **)&env, nullptr);
for (;;) {
jmethodID id = ring_buffer[rand() % BUFFER_SIZE].load(std::memory_order_relaxed);
if (id != (jmethodID)0) {
get_method_details(id);
}
}
- return NULL;
+ return nullptr;
}
static void JNICALL ClassPrepareCallback(jvmtiEnv *jvmti_env,
@@ -66,8 +66,8 @@ static void JNICALL ClassPrepareCallback(jvmtiEnv *jvmti_env,
static bool reader_created = false;
static int ring_buffer_idx = 0;
- char *class_name = NULL;
- if (jvmti_env->GetClassSignature(klass, &class_name, NULL) != JVMTI_ERROR_NONE) {
+ char *class_name = nullptr;
+ if (jvmti_env->GetClassSignature(klass, &class_name, nullptr) != JVMTI_ERROR_NONE) {
return;
}
// We only care MyClass and only one thread loads it
@@ -79,7 +79,7 @@ static void JNICALL ClassPrepareCallback(jvmtiEnv *jvmti_env,
if (!reader_created) {
pthread_t tid;
- pthread_create(&tid, NULL, read_ringbuffer, NULL);
+ pthread_create(&tid, nullptr, read_ringbuffer, nullptr);
reader_created = true;
}
@@ -119,7 +119,7 @@ JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved)
}
// Enable the ClassPrepare event
- error = _jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_CLASS_PREPARE, NULL);
+ error = _jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_CLASS_PREPARE, nullptr);
if (error != JVMTI_ERROR_NONE) {
fprintf(stderr, "Error enabling ClassPrepare event: %d\n", error);
return JNI_ERR;
diff --git a/test/hotspot/jtreg/serviceability/jvmti/vthread/VThreadEventTest/libVThreadEventTest.cpp b/test/hotspot/jtreg/serviceability/jvmti/vthread/VThreadEventTest/libVThreadEventTest.cpp
index 477ede9f30a..1e272d0b02d 100644
--- a/test/hotspot/jtreg/serviceability/jvmti/vthread/VThreadEventTest/libVThreadEventTest.cpp
+++ b/test/hotspot/jtreg/serviceability/jvmti/vthread/VThreadEventTest/libVThreadEventTest.cpp
@@ -123,13 +123,13 @@ Agent_OnAttach(JavaVM *vm, char *options, void *reserved) {
}
clazz = env->FindClass("VThreadEventTest");
- if (clazz == NULL) {
+ if (clazz == nullptr) {
LOG("FindClass failed\n");
return JNI_ERR;
}
mid = env->GetStaticMethodID(clazz, "agentStarted", "()V");
- if (mid == NULL) {
+ if (mid == nullptr) {
LOG("GetStaticMethodID failed\n");
return JNI_ERR;
}
diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbLongConstant.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbLongConstant.java
index bcf93498574..1f039eb73b5 100644
--- a/test/hotspot/jtreg/serviceability/sa/ClhsdbLongConstant.java
+++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbLongConstant.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -93,12 +93,12 @@ private static void checkForTruncation(String longConstantOutput) throws Excepti
// ...
// longConstant VM_Version::CPU_SHA 17179869184
// longConstant markWord::age_shift 3
- // longConstant markWord::hash_mask_in_place 549755813632
+ // longConstant markWord::hash_mask_in_place 4398046509056
// ...
checkLongValue("markWord::hash_mask_in_place",
longConstantOutput,
- Platform.is64bit() ? 549755813632L: 4294967168L);
+ Platform.is64bit() ? 4398046509056L: 4294967168L);
String arch = System.getProperty("os.arch");
if (arch.equals("amd64") || arch.equals("i386") || arch.equals("x86")) {
diff --git a/test/jdk/ProblemList-shenandoah.txt b/test/jdk/ProblemList-shenandoah.txt
new file mode 100644
index 00000000000..063795d69e8
--- /dev/null
+++ b/test/jdk/ProblemList-shenandoah.txt
@@ -0,0 +1,60 @@
+#
+# 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.
+#
+
+#############################################################################
+#
+# List of quarantined tests for testing with Shenandoah.
+#
+#############################################################################
+
+# Quiet all LeakProfiler tests
+
+jdk/jfr/api/consumer/TestRecordingFileWrite.java 8342951 generic-all
+jdk/jfr/event/oldobject/TestAllocationTime.java 8342951 generic-all
+jdk/jfr/event/oldobject/TestArrayInformation.java 8342951 generic-all
+jdk/jfr/event/oldobject/TestCircularReference.java 8342951 generic-all
+jdk/jfr/event/oldobject/TestClassLoaderLeak.java 8342951 generic-all
+jdk/jfr/event/oldobject/TestFieldInformation.java 8342951 generic-all
+jdk/jfr/event/oldobject/TestG1.java 8342951 generic-all
+jdk/jfr/event/oldobject/TestHeapDeep.java 8342951 generic-all
+jdk/jfr/event/oldobject/TestHeapShallow.java 8342951 generic-all
+jdk/jfr/event/oldobject/TestLargeRootSet.java 8342951 generic-all
+jdk/jfr/event/oldobject/TestLastKnownHeapUsage.java 8342951 generic-all
+jdk/jfr/event/oldobject/TestListenerLeak.java 8342951 generic-all
+jdk/jfr/event/oldobject/TestMetadataRetention.java 8342951 generic-all
+jdk/jfr/event/oldobject/TestObjectAge.java 8342951 generic-all
+jdk/jfr/event/oldobject/TestObjectDescription.java 8342951 generic-all
+jdk/jfr/event/oldobject/TestObjectSize.java 8342951 generic-all
+jdk/jfr/event/oldobject/TestParallel.java 8342951 generic-all
+jdk/jfr/event/oldobject/TestReferenceChainLimit.java 8342951 generic-all
+jdk/jfr/event/oldobject/TestSanityDefault.java 8342951 generic-all
+jdk/jfr/event/oldobject/TestSerial.java 8342951 generic-all
+jdk/jfr/event/oldobject/TestShenandoah.java 8342951 generic-all
+jdk/jfr/event/oldobject/TestThreadLocalLeak.java 8342951 generic-all
+jdk/jfr/event/oldobject/TestZ.java 8342951 generic-all
+jdk/jfr/jcmd/TestJcmdDump.java 8342951 generic-all
+jdk/jfr/jcmd/TestJcmdDumpPathToGCRoots.java 8342951 generic-all
+jdk/jfr/jcmd/TestJcmdStartPathToGCRoots.java 8342951 generic-all
+jdk/jfr/jvm/TestWaste.java 8342951 generic-all
+jdk/jfr/startupargs/TestOldObjectQueueSize.java 8342951 generic-all
+
diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt
index 4fa2301e2e4..dc467b17cec 100644
--- a/test/jdk/ProblemList.txt
+++ b/test/jdk/ProblemList.txt
@@ -518,6 +518,8 @@ java/lang/invoke/LFCaching/LFMultiThreadCachingTest.java 8151492 generic-
java/lang/invoke/LFCaching/LFGarbageCollectedTest.java 8078602 generic-all
java/lang/invoke/lambda/LambdaFileEncodingSerialization.java 8249079 linux-all
java/lang/invoke/RicochetTest.java 8251969 generic-all
+java/lang/Thread/jni/AttachCurrentThread/AttachTest.java#id0 8343244 generic-all
+java/lang/Thread/jni/AttachCurrentThread/AttachTest.java#id1 8343244 generic-all
java/lang/ModuleLayer/LayerControllerTest.java 8337048 generic-all
java/lang/ModuleLayer/BasicLayerTest.java 8337048 generic-all
@@ -779,6 +781,7 @@ jdk/incubator/vector/LoadJsvmlTest.java 8305390 windows-
# jdk_jfr
jdk/jfr/event/compiler/TestCodeSweeper.java 8338127 generic-all
+jdk/jfr/event/oldobject/TestShenandoah.java 8342951 generic-all
jdk/jfr/event/runtime/TestResidentSetSizeEvent.java 8309846 aix-ppc64
jdk/jfr/jvm/TestWaste.java 8282427 generic-all
@@ -818,6 +821,7 @@ java/awt/image/VolatileImage/VolatileImageConfigurationTest.java 8171069 macosx-
java/awt/Modal/InvisibleParentTest/InvisibleParentTest.java 8172245 linux-all
java/awt/Frame/FrameStateTest/FrameStateTest.java 8203920 macosx-all,linux-all
java/awt/print/PrinterJob/ScaledText/ScaledText.java 8231226 macosx-all
+java/awt/print/PrinterJob/PrintTextTest.java 8148334 generic-all
java/awt/font/TextLayout/TestJustification.java 8250791 macosx-all
java/awt/TrayIcon/DragEventSource/DragEventSource.java 8252242 macosx-all
java/awt/FileDialog/DefaultFocusOwner/DefaultFocusOwner.java 7187728 macosx-all,linux-all
diff --git a/test/jdk/TEST.groups b/test/jdk/TEST.groups
index 2a4c7d72f65..fc2a3cd5eb1 100644
--- a/test/jdk/TEST.groups
+++ b/test/jdk/TEST.groups
@@ -678,4 +678,4 @@ jdk_core_no_security = \
# Set of tests for `@since` checks in source code documentation
jdk_since_checks = \
- tools/sincechecker/modules/java_base/CheckSince_javaBase.java
+ tools/sincechecker/
diff --git a/test/jdk/com/sun/crypto/provider/KDF/HKDFBasicFunctionsTest.java b/test/jdk/com/sun/crypto/provider/KDF/HKDFBasicFunctionsTest.java
new file mode 100644
index 00000000000..2697ba57641
--- /dev/null
+++ b/test/jdk/com/sun/crypto/provider/KDF/HKDFBasicFunctionsTest.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8331008
+ * @summary basic HKDF operations
+ * @library /test/lib
+ * @enablePreview
+ */
+
+import java.util.HexFormat;
+import javax.crypto.KDF;
+import javax.crypto.spec.HKDFParameterSpec;
+import jdk.test.lib.Asserts;
+
+public class HKDFBasicFunctionsTest {
+ public static void main(String[] args) throws Exception {
+ var ikm = HexFormat.of().parseHex("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b");
+ var salt = HexFormat.of().parseHex("000102030405060708090a0b0c");
+ var info = HexFormat.of().parseHex("f0f1f2f3f4f5f6f7f8f9");
+ var len = 42;
+
+ var kdf = KDF.getInstance("HKDF-SHA256");
+ var expectedPrk = HexFormat.of().parseHex("077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5");
+ var expectedOkm = HexFormat.of().parseHex("3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865");
+
+ var extractOnly = HKDFParameterSpec.ofExtract().addIKM(ikm).addSalt(salt).extractOnly();
+ var prk = kdf.deriveKey("PRK", extractOnly);
+ var expandOnly = HKDFParameterSpec.expandOnly(prk, info, len);
+ var okm1 = kdf.deriveKey("OKM", expandOnly);
+ var extractAndExpand = HKDFParameterSpec.ofExtract().addIKM(ikm).addSalt(salt).thenExpand(info, len);
+ var okm2 = kdf.deriveKey("OKM", extractAndExpand);
+
+ Asserts.assertEqualsByteArray(prk.getEncoded(), expectedPrk,
+ "the PRK must match the expected value");
+
+ Asserts.assertEqualsByteArray(okm1.getEncoded(), expectedOkm,
+ "the OKM must match the expected value "
+ + "(expand)");
+
+ Asserts.assertEqualsByteArray(okm2.getEncoded(), expectedOkm,
+ "the OKM must match the expected value "
+ + "(extract expand)");
+
+ // test empty extract
+ test(HKDFParameterSpec.ofExtract().extractOnly());
+ // test expand with empty info
+ test(HKDFParameterSpec.ofExtract().thenExpand(new byte[0], 32));
+ // test expand with null info
+ test(HKDFParameterSpec.ofExtract().thenExpand(null, 32));
+ // test extract with zero-length salt
+ test(HKDFParameterSpec.ofExtract().addIKM(ikm).addSalt(new byte[0]).extractOnly());
+ }
+
+ static void test(HKDFParameterSpec p) throws Exception {
+ var kdf = KDF.getInstance("HKDF-SHA256");
+ System.out.println(HexFormat.of().formatHex(kdf.deriveData(p)));
+ }
+}
diff --git a/test/jdk/com/sun/crypto/provider/KDF/HKDFExhaustiveTest.java b/test/jdk/com/sun/crypto/provider/KDF/HKDFExhaustiveTest.java
new file mode 100644
index 00000000000..fd33337a3c0
--- /dev/null
+++ b/test/jdk/com/sun/crypto/provider/KDF/HKDFExhaustiveTest.java
@@ -0,0 +1,564 @@
+/*
+ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8331008
+ * @summary KDF API tests
+ * @library /test/lib
+ * @run main/othervm -Djava.security.egd=file:/dev/urandom -Djava.security.debug=provider,engine=kdf HKDFExhaustiveTest
+ * @enablePreview
+ */
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.Provider;
+import java.security.Security;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.InvalidParameterSpecException;
+import java.util.ArrayList;
+import java.util.List;
+import javax.crypto.KDF;
+import javax.crypto.KDFParameters;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.HKDFParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import jdk.test.lib.Asserts;
+import jdk.test.lib.Utils;
+
+public class HKDFExhaustiveTest {
+
+ private static final String JDK_HKDF_SHA256 = "HKDF-SHA256";
+ private static final String JDK_HKDF_SHA384 = "HKDF-SHA384";
+ private static final String JDK_HKDF_SHA512 = "HKDF-SHA512";
+ private static final String[] KDF_ALGORITHMS = {
+ JDK_HKDF_SHA256, JDK_HKDF_SHA384, JDK_HKDF_SHA512
+ };
+ private static final String SUNJCE = "SunJCE";
+
+ // SECRET_KEY_SPEC_KEYS and RAW_DATA holds valid values for IKM and SALTS
+ private static final List SECRET_KEY_SPEC_KEYS =
+ List.of(
+ new SecretKeySpec(new byte[] {0}, "HKDF-IKM"),
+ new SecretKeySpec("IKM".getBytes(), "HKDF-IKM"));
+ private static final List RAW_DATA = List.of(new byte[] {0}, "RAW".getBytes());
+
+ private static final byte[] EMPTY = new byte[0];
+ private static final int SHORT_LENGTH = 42;
+ private static final int LARGE_LENGTH = 1000;
+ private static final int NEGATIVE_LENGTH = -1;
+
+ static class TestKDFParams implements KDFParameters {}
+
+ private static final KdfVerifier KdfGetInstanceVerifier =
+ (a, p, s) -> {
+
+ // Test KDF getInstance methods, all should have same algo and provider
+ KDF k1 = KDF.getInstance(a);
+ KDF k2 = KDF.getInstance(a, p);
+ KDF k3 = KDF.getInstance(a, Security.getProvider(p));
+ Asserts.assertEquals(k1.getAlgorithm(), k2.getAlgorithm());
+ Asserts.assertEquals(k2.getAlgorithm(), k3.getAlgorithm());
+ Asserts.assertEquals(k1.getProviderName(), k2.getProviderName());
+ Asserts.assertEquals(k2.getProviderName(), k3.getProviderName());
+ Asserts.assertEquals(k1.getParameters(), k2.getParameters());
+ Asserts.assertEquals(k2.getParameters(), k3.getParameters());
+
+ // Test KDF getInstance methods with parameters
+ KDFParameters spec = (KDFParameters) s;
+ k1 = KDF.getInstance(a, spec);
+ k2 = KDF.getInstance(a, spec, p);
+ k3 = KDF.getInstance(a, spec, Security.getProvider(p));
+ Asserts.assertEquals(k1.getAlgorithm(), k2.getAlgorithm());
+ Asserts.assertEquals(k2.getAlgorithm(), k3.getAlgorithm());
+ Asserts.assertEquals(k1.getProviderName(), k2.getProviderName());
+ Asserts.assertEquals(k2.getProviderName(), k3.getProviderName());
+ Asserts.assertEquals(k1.getParameters(), k2.getParameters());
+ Asserts.assertEquals(k2.getParameters(), k3.getParameters());
+ };
+
+ private static final KdfExtractVerifier KdfExtractVerifierImpl =
+ (ikm, salt) -> {
+ // ofExtract
+ HKDFParameterSpec.Builder hkdfParameterSpecBuilder = HKDFParameterSpec.ofExtract();
+ addIkmAndSalt(hkdfParameterSpecBuilder, ikm, salt);
+
+ // extractOnly - it is possible to have empty key param so skip when length is 0
+ HKDFParameterSpec.Extract parameterSpec = hkdfParameterSpecBuilder.extractOnly();
+ checkIKMSaltPresence(ikm, salt, parameterSpec);
+
+ return parameterSpec;
+ };
+
+ private static final KdfExpandVerifier KdfExpandVerifierImpl =
+ (prk, info, len) -> {
+ // Expand
+ HKDFParameterSpec.Expand parameterSpec = HKDFParameterSpec.expandOnly(prk, info, len);
+
+ Asserts.assertEqualsByteArray(prk.getEncoded(), parameterSpec.prk().getEncoded());
+ Asserts.assertEqualsByteArray(info, parameterSpec.info());
+ Asserts.assertEquals(len, parameterSpec.length());
+
+ return parameterSpec;
+ };
+
+ private static final KdfExtThenExpVerifier
+ KdfExtThenExpVerifierImpl =
+ (ikm, salt, info, len) -> {
+ // ofExtract
+ HKDFParameterSpec.Builder hkdfParameterSpecBuilder = HKDFParameterSpec.ofExtract();
+ addIkmAndSalt(hkdfParameterSpecBuilder, ikm, salt);
+
+ // thenExpand
+ HKDFParameterSpec.ExtractThenExpand parameterSpec =
+ hkdfParameterSpecBuilder.thenExpand(info, len);
+ checkIKMSaltPresence(ikm, salt, parameterSpec);
+
+ // Validate info and length
+ Asserts.assertEqualsByteArray(info, parameterSpec.info());
+ Asserts.assertEquals(len, parameterSpec.length());
+
+ return parameterSpec;
+ };
+ private static final DeriveComparator<
+ KDF, HKDFParameterSpec, HKDFParameterSpec, String, SecretKey, Integer>
+ deriveComparatorImpl =
+ (hk, lhs, rhs, t, s, len) -> {
+ // deriveKey using two passed in HKDFParameterSpec and compare
+ byte[] skUsingLhs = hk.deriveKey(t, lhs).getEncoded();
+ byte[] skUsingRhs = hk.deriveKey(t, rhs).getEncoded();
+
+ // compare deriveData and keys using same HKDFParameterSpec are equal
+ Asserts.assertEqualsByteArray(skUsingLhs, skUsingRhs);
+ Asserts.assertEqualsByteArray(hk.deriveData(lhs), skUsingLhs);
+ Asserts.assertEqualsByteArray(hk.deriveData(lhs), skUsingRhs);
+ Asserts.assertEqualsByteArray(hk.deriveData(lhs), hk.deriveData(rhs));
+
+ // if 'len < 0' then deriveKey()/deriveData() length check is not required
+ if (len >= 0) {
+ Asserts.assertEquals(skUsingLhs.length, len);
+ }
+
+ // Compare with if SecretKey is passed in parameter
+ if (s != null) {
+ Asserts.assertEqualsByteArray(skUsingLhs, s.getEncoded());
+ }
+ };
+ // Passed in HKDFParameterSpec returned from different methods and algorithms a1, a2.
+ // Keys and data derived should be equal.
+ private static final DeriveVerifier
+ deriveVerifierImpl =
+ (hk, lhs, rhs, a1, a2) -> {
+ SecretKey sk1 = hk.deriveKey(a1, lhs);
+ SecretKey sk2 = hk.deriveKey(a2, rhs);
+ Asserts.assertEqualsByteArray(sk1.getEncoded(), sk2.getEncoded());
+
+ byte[] bk1 = hk.deriveData(lhs);
+ Asserts.assertEqualsByteArray(bk1, sk1.getEncoded());
+ };
+
+ private static void checkIKMSaltPresence(
+ Object ikm, Object salt, HKDFParameterSpec parameterSpec) {
+ final List ikms;
+ final List salts;
+ if (parameterSpec instanceof HKDFParameterSpec.Extract) {
+ ikms = ((HKDFParameterSpec.Extract) parameterSpec).ikms();
+ salts = ((HKDFParameterSpec.Extract) parameterSpec).salts();
+ } else { // must be HKDFParameterSpec.ExtractThenExpand
+ ikms = ((HKDFParameterSpec.ExtractThenExpand) parameterSpec).ikms();
+ salts = ((HKDFParameterSpec.ExtractThenExpand) parameterSpec).salts();
+ }
+ if ((ikm instanceof SecretKey) || ((byte[]) ikm).length != 0) {
+ Asserts.assertTrue(ikms.contains(getSecretKey(ikm)));
+ }
+
+ if ((salt instanceof SecretKey) || ((byte[]) salt).length != 0) {
+ Asserts.assertTrue(salts.contains(getSecretKey(salt)));
+ }
+ }
+
+ private static SecretKey getSecretKey(Object data) {
+ return (data instanceof SecretKey)
+ ? (SecretKey) data
+ : new SecretKeySpec((byte[]) data, "Generic");
+ }
+
+ private static void addIkmAndSalt(
+ HKDFParameterSpec.Builder hkdfParameterSpecBuilder, Object ikm, Object salt) {
+ if (ikm instanceof SecretKey) {
+ hkdfParameterSpecBuilder.addIKM((SecretKey) ikm);
+ } else {
+ hkdfParameterSpecBuilder.addIKM((byte[]) ikm);
+ }
+
+ if (salt instanceof SecretKey) {
+ hkdfParameterSpecBuilder.addSalt((SecretKey) salt);
+ } else {
+ hkdfParameterSpecBuilder.addSalt((byte[]) salt);
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ System.out.println("Starting Test '" + HKDFExhaustiveTest.class.getName() + "'");
+
+ // Test KDF.getInstance methods
+ System.out.println("Testing getInstance methods");
+ testGetInstanceMethods();
+ testGetInstanceNegative();
+
+ /* Executing following test cases with one supported algorithm is sufficient */
+ KDF hk = KDF.getInstance(KDF_ALGORITHMS[0]);
+
+ // Test extract
+ System.out.println("Testing extract method");
+ testExtractMethod(hk);
+
+ System.out.println("Testing deriveKey and deriveData with extract method");
+ testDeriveKeyDataWithExtract(hk);
+
+ // Test expand
+ System.out.println("Testing expand method");
+ testExpandMethod(hk);
+
+ System.out.println("Testing deriveKey and deriveData with expand method");
+ testDeriveKeyDataWithExpand(hk);
+
+ // Test ExtractThenExpand
+ System.out.println("Testing extractThenExpand method");
+ testExtractExpandMethod(hk);
+
+ System.out.println("Testing deriveKey and deriveData with extExpand method");
+ testDeriveKeyDataWithExtExpand(hk);
+
+ System.out.println("Test executed successfully.");
+ }
+
+ private static void testGetInstanceMethods()
+ throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, NoSuchProviderException {
+ // POSITIVE TestCase: KDF getInstance methods test
+ for (String algo : KDF_ALGORITHMS) {
+ KdfGetInstanceVerifier.test(algo, SUNJCE, null);
+ }
+ }
+
+ private static void testGetInstanceNegative() {
+ final String INVALID_STRING = "INVALID";
+ final Provider SUNJCE_PROVIDER = Security.getProvider(SUNJCE);
+
+ // getInstance(String algorithm)
+ Utils.runAndCheckException(() -> KDF.getInstance(null), NullPointerException.class);
+ Utils.runAndCheckException(
+ () -> KDF.getInstance(INVALID_STRING), NoSuchAlgorithmException.class);
+
+ // getInstance(String algorithm, String provider)
+ Utils.runAndCheckException(() -> KDF.getInstance(null, SUNJCE), NullPointerException.class);
+ Utils.runAndCheckException(
+ () -> KDF.getInstance(INVALID_STRING, SUNJCE), NoSuchAlgorithmException.class);
+ Utils.runAndCheckException(
+ () -> KDF.getInstance(KDF_ALGORITHMS[0], (String) null), NullPointerException.class);
+ Utils.runAndCheckException(
+ () -> KDF.getInstance(KDF_ALGORITHMS[0], INVALID_STRING), NoSuchProviderException.class);
+
+ // getInstance(String algorithm, Provider provider)
+ Utils.runAndCheckException(
+ () -> KDF.getInstance(null, SUNJCE_PROVIDER), NullPointerException.class);
+ Utils.runAndCheckException(
+ () -> KDF.getInstance(INVALID_STRING, SUNJCE_PROVIDER), NoSuchAlgorithmException.class);
+ Utils.runAndCheckException(
+ () -> KDF.getInstance(KDF_ALGORITHMS[0], (Provider) null), NullPointerException.class);
+
+ // getInstance(String algorithm, KDFParameters kdfParameters)
+ // null spec is a valid case but different class is not
+ Utils.runAndCheckException(
+ () -> KDF.getInstance(null, (KDFParameters) null), NullPointerException.class);
+ Utils.runAndCheckException(
+ () -> KDF.getInstance(INVALID_STRING, (KDFParameters) null),
+ NoSuchAlgorithmException.class);
+
+ // getInstance(String algorithm, KDFParameters kdfParameters, String provider)
+ Utils.runAndCheckException(
+ () -> KDF.getInstance(null, null, SUNJCE), NullPointerException.class);
+ Utils.runAndCheckException(
+ () -> KDF.getInstance(INVALID_STRING, null, SUNJCE), NoSuchAlgorithmException.class);
+ Utils.runAndCheckException(
+ () -> KDF.getInstance(KDF_ALGORITHMS[0], null, (String) null), NullPointerException.class);
+ Utils.runAndCheckException(
+ () -> KDF.getInstance(KDF_ALGORITHMS[0], null, INVALID_STRING),
+ NoSuchProviderException.class);
+ Utils.runAndCheckException(
+ () -> KDF.getInstance(KDF_ALGORITHMS[0], new TestKDFParams(), SUNJCE),
+ InvalidAlgorithmParameterException.class);
+ Utils.runAndCheckException(
+ () -> KDF.getInstance(KDF_ALGORITHMS[0], new TestKDFParams(), SUNJCE_PROVIDER),
+ InvalidAlgorithmParameterException.class);
+
+ // getInstance(String algorithm, KDFParameters kdfParameters, Provider provider)
+ Utils.runAndCheckException(
+ () -> KDF.getInstance(null, null, SUNJCE_PROVIDER), NullPointerException.class);
+ Utils.runAndCheckException(
+ () -> KDF.getInstance(INVALID_STRING, null, SUNJCE_PROVIDER),
+ NoSuchAlgorithmException.class);
+ Utils.runAndCheckException(
+ () -> KDF.getInstance(KDF_ALGORITHMS[0], null, (Provider) null),
+ NullPointerException.class);
+ }
+
+ private static void testExtractMethod(KDF hk)
+ throws InvalidAlgorithmParameterException,
+ InvalidParameterSpecException,
+ NoSuchAlgorithmException {
+ List ikmSaltTestData = new ArrayList<>();
+ ikmSaltTestData.add(null);
+ ikmSaltTestData.add(EMPTY);
+ ikmSaltTestData.add(RAW_DATA.getFirst());
+ ikmSaltTestData.add(SECRET_KEY_SPEC_KEYS.getFirst());
+
+ for (Object ikm : ikmSaltTestData) {
+ for (Object salt : ikmSaltTestData) {
+ // NEGATIVE Testcase: expects NullPointerException
+ if (ikm == null || salt == null) {
+ Utils.runAndCheckException(
+ () -> KdfExtractVerifierImpl.extract(ikm, salt), NullPointerException.class);
+ } else {
+ // POSITIVE Testcase: Extract - Empty bytes for IKM/SALT
+ HKDFParameterSpec ext1 = KdfExtractVerifierImpl.extract(ikm, salt);
+ HKDFParameterSpec ext2 = KdfExtractVerifierImpl.extract(ikm, salt);
+ deriveComparatorImpl.deriveAndCompare(hk, ext1, ext2, "PRK", null, NEGATIVE_LENGTH);
+ }
+ }
+ }
+ }
+
+ private static void testDeriveKeyDataWithExtract(KDF hk)
+ throws InvalidAlgorithmParameterException,
+ InvalidParameterSpecException,
+ NoSuchAlgorithmException {
+ // POSITIVE TestCase: Extract - Derive keys/data with unknown algorithm name
+ deriveVerifierImpl.derive(
+ hk,
+ KdfExtractVerifierImpl.extract(SECRET_KEY_SPEC_KEYS.getFirst(), RAW_DATA.getFirst()),
+ KdfExtractVerifierImpl.extract(SECRET_KEY_SPEC_KEYS.getFirst(), RAW_DATA.getFirst()),
+ "XYZ",
+ "ABC");
+
+ // NEGATIVE TestCase: Extract - {null, ""} algo to derive key
+ Utils.runAndCheckException(
+ () ->
+ hk.deriveKey(
+ null,
+ KdfExtractVerifierImpl.extract(
+ SECRET_KEY_SPEC_KEYS.getFirst(), RAW_DATA.getFirst())),
+ NullPointerException.class);
+ Utils.runAndCheckException(
+ () ->
+ hk.deriveKey(
+ "",
+ KdfExtractVerifierImpl.extract(
+ SECRET_KEY_SPEC_KEYS.getFirst(), RAW_DATA.getFirst())),
+ NoSuchAlgorithmException.class);
+ }
+
+ private static void testExpandMethod(KDF hk)
+ throws InvalidAlgorithmParameterException,
+ InvalidParameterSpecException,
+ NoSuchAlgorithmException {
+ SecretKey prk =
+ hk.deriveKey(
+ "PRK",
+ KdfExtractVerifierImpl.extract(SECRET_KEY_SPEC_KEYS.get(1), RAW_DATA.getFirst()));
+
+ // Test extExp with {null, EMPTY} info and {SHORT_LENGTH, LARGE_LENGTH} length
+ for (byte[] info : new byte[][] {null, EMPTY}) {
+ for (int length : new Integer[] {SHORT_LENGTH, LARGE_LENGTH}) {
+ HKDFParameterSpec exp1 = KdfExpandVerifierImpl.expand(prk, info, length);
+ HKDFParameterSpec exp2 = KdfExpandVerifierImpl.expand(prk, info, length);
+ deriveComparatorImpl.deriveAndCompare(hk, exp1, exp2, "OKM", null, length);
+ }
+ }
+
+ // NEGATIVE TestCase: Expand - PRK=null
+ Utils.runAndCheckException(
+ () -> KdfExpandVerifierImpl.expand(null, RAW_DATA.getFirst(), SHORT_LENGTH),
+ NullPointerException.class);
+
+ // NEGATIVE TestCase: Expand - Derive keys/data of negative length
+ Utils.runAndCheckException(
+ () ->
+ KdfExpandVerifierImpl.expand(
+ SECRET_KEY_SPEC_KEYS.getFirst(), RAW_DATA.getFirst(), NEGATIVE_LENGTH),
+ IllegalArgumentException.class);
+
+ // NEGATIVE TestCase: Expand - PRK value too short
+ Utils.runAndCheckException(
+ () ->
+ hk.deriveKey(
+ "OKM",
+ KdfExpandVerifierImpl.expand(
+ new SecretKeySpec(new byte[] {0x00}, "PRK"), null, 32)),
+ InvalidAlgorithmParameterException.class);
+
+ // NEGATIVE TestCase: Expand - length greater than 255 > hmacLen
+ Utils.runAndCheckException(
+ () -> hk.deriveKey("OKM", KdfExpandVerifierImpl.expand(prk, null, 8162)),
+ InvalidAlgorithmParameterException.class);
+ }
+
+ private static void testDeriveKeyDataWithExpand(KDF hk)
+ throws InvalidAlgorithmParameterException,
+ NoSuchAlgorithmException,
+ InvalidParameterSpecException {
+ SecretKey prk =
+ hk.deriveKey(
+ "PRK",
+ KdfExtractVerifierImpl.extract(SECRET_KEY_SPEC_KEYS.get(1), RAW_DATA.getFirst()));
+
+ // POSITIVE TestCase: Expand - Derive keys/data with unknown algorithm name
+ deriveVerifierImpl.derive(
+ hk,
+ KdfExpandVerifierImpl.expand(prk, RAW_DATA.getFirst(), SHORT_LENGTH),
+ KdfExpandVerifierImpl.expand(prk, RAW_DATA.getFirst(), SHORT_LENGTH),
+ "XYZ",
+ "ABC");
+
+ // NEGATIVE TestCase: Expand - PRK is not derived
+ Utils.runAndCheckException(
+ () ->
+ hk.deriveKey(
+ "PRK",
+ KdfExpandVerifierImpl.expand(
+ SECRET_KEY_SPEC_KEYS.get(1), RAW_DATA.getFirst(), SHORT_LENGTH)),
+ InvalidAlgorithmParameterException.class);
+ }
+
+ private static void testExtractExpandMethod(KDF hk)
+ throws InvalidAlgorithmParameterException,
+ InvalidParameterSpecException,
+ NoSuchAlgorithmException {
+ // Test extExp with {null, EMPTY} info and {SHORT_LENGTH, LARGE_LENGTH} length
+ for (byte[] info : new byte[][] {null, EMPTY}) {
+ for (int length : new Integer[] {SHORT_LENGTH, LARGE_LENGTH}) {
+ HKDFParameterSpec extractExpand1 =
+ KdfExtThenExpVerifierImpl.extExp(
+ RAW_DATA.getFirst(), RAW_DATA.getFirst(), info, length);
+ HKDFParameterSpec extractExpand2 =
+ KdfExtThenExpVerifierImpl.extExp(
+ RAW_DATA.getFirst(), RAW_DATA.getFirst(), info, length);
+ deriveComparatorImpl.deriveAndCompare(
+ hk, extractExpand1, extractExpand2, "OKM", null, length);
+ }
+ }
+
+ // NEGATIVE TestCases: ExtractExpand
+ List ikmSaltTestData = new ArrayList<>();
+ ikmSaltTestData.add(null);
+ ikmSaltTestData.add(RAW_DATA.getFirst());
+ ikmSaltTestData.add(SECRET_KEY_SPEC_KEYS.getFirst());
+
+ for (Object ikm : ikmSaltTestData) {
+ for (Object salt : ikmSaltTestData) {
+ if (ikm == null || salt == null) {
+ // ikm and/or salt are null, expect NullPointerException
+ Utils.runAndCheckException(
+ () -> KdfExtThenExpVerifierImpl.extExp(ikm, salt, RAW_DATA.getFirst(), SHORT_LENGTH),
+ NullPointerException.class);
+ } else {
+ // ikm and salt are not null, test with negative length
+ Utils.runAndCheckException(
+ () ->
+ KdfExtThenExpVerifierImpl.extExp(ikm, salt, RAW_DATA.getFirst(), NEGATIVE_LENGTH),
+ IllegalArgumentException.class);
+ }
+ }
+ }
+
+ // NEGATIVE TestCase: ExtractThenExpand - length greater than 255 > hmacLen
+ Utils.runAndCheckException(
+ () -> hk.deriveKey("OKM", HKDFParameterSpec.ofExtract().thenExpand(null, 8162)),
+ InvalidAlgorithmParameterException.class);
+ }
+
+ private static void testDeriveKeyDataWithExtExpand(KDF hk)
+ throws InvalidAlgorithmParameterException,
+ InvalidParameterSpecException,
+ NoSuchAlgorithmException {
+ // POSITIVE TestCase: ExtractExpand - Derive keys/data with unknown algorithm names
+ deriveVerifierImpl.derive(
+ hk,
+ KdfExtThenExpVerifierImpl.extExp(
+ SECRET_KEY_SPEC_KEYS.getFirst(),
+ RAW_DATA.getFirst(),
+ RAW_DATA.getFirst(),
+ SHORT_LENGTH),
+ KdfExtThenExpVerifierImpl.extExp(
+ SECRET_KEY_SPEC_KEYS.getFirst(),
+ RAW_DATA.getFirst(),
+ RAW_DATA.getFirst(),
+ SHORT_LENGTH),
+ "XYZ",
+ "ABC");
+ }
+
+ @FunctionalInterface
+ private interface KdfVerifier {
+ void test(A a, P p, S s)
+ throws NoSuchAlgorithmException,
+ NoSuchProviderException,
+ InvalidAlgorithmParameterException;
+ }
+
+ @FunctionalInterface
+ private interface KdfExtractVerifier {
+ HKDFParameterSpec extract(K k, S s);
+ }
+
+ @FunctionalInterface
+ private interface KdfExpandVerifier {
+ HKDFParameterSpec expand(P p, I i, L l);
+ }
+
+ @FunctionalInterface
+ private interface KdfExtThenExpVerifier {
+ HKDFParameterSpec extExp(K k, S s, I i, L l);
+ }
+
+ @FunctionalInterface
+ private interface DeriveComparator {
+ void deriveAndCompare(HK hk, L lh, R rh, T t, S s, LN l)
+ throws InvalidParameterSpecException,
+ InvalidAlgorithmParameterException,
+ NoSuchAlgorithmException;
+ }
+
+ @FunctionalInterface
+ private interface DeriveVerifier {
+ void derive(HK hk, L lh, R rh, A1 a1, A2 a2)
+ throws InvalidParameterSpecException,
+ InvalidAlgorithmParameterException,
+ NoSuchAlgorithmException;
+ }
+
+ private static class KDFAlgorithmParameterSpec implements AlgorithmParameterSpec {
+ public KDFAlgorithmParameterSpec() {}
+ }
+}
diff --git a/test/jdk/com/sun/crypto/provider/KDF/HKDFKnownAnswerTests.java b/test/jdk/com/sun/crypto/provider/KDF/HKDFKnownAnswerTests.java
new file mode 100644
index 00000000000..358ffa794fd
--- /dev/null
+++ b/test/jdk/com/sun/crypto/provider/KDF/HKDFKnownAnswerTests.java
@@ -0,0 +1,282 @@
+/*
+ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8331008
+ * @run main HKDFKnownAnswerTests
+ * @summary Tests for HKDF Expand and Extract Key Derivation Functions
+ * @enablePreview
+ */
+
+import javax.crypto.KDF;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.HKDFParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.Key;
+import java.security.NoSuchAlgorithmException;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.InvalidParameterSpecException;
+import java.util.Arrays;
+import java.util.HexFormat;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Objects;
+
+public class HKDFKnownAnswerTests {
+ public static class TestData {
+ public TestData(String name, String algStr, String ikmStr,
+ String saltStr, String infoStr, int oLen,
+ String expPrkStr,
+ String expOkmStr) {
+ testName = Objects.requireNonNull(name);
+ algName = Objects.requireNonNull(algStr);
+ ikm = HexFormat.of().parseHex(Objects.requireNonNull(ikmStr));
+ if ((outLen = oLen) <= 0) {
+ throw new IllegalArgumentException(
+ "Output length must be greater than 0");
+ }
+ expectedPRK = HexFormat.of().parseHex(Objects.requireNonNull(expPrkStr));
+ expectedOKM = HexFormat.of().parseHex(Objects.requireNonNull(expOkmStr));
+
+ // Non-mandatory fields - may be null
+ salt = (saltStr != null) ? HexFormat.of().parseHex(saltStr) : new byte[0];
+ info = (infoStr != null) ? HexFormat.of().parseHex(infoStr) : null;
+ }
+
+ public final String testName;
+ public final String algName;
+ public final byte[] ikm;
+ public final byte[] salt;
+ public final byte[] info;
+ public final int outLen;
+ public final byte[] expectedPRK;
+ public final byte[] expectedOKM;
+ }
+
+ public static final List testList = new LinkedList() {{
+ add(new TestData("RFC 5869 Test Case 1", "HKDF-SHA256",
+ "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
+ "000102030405060708090a0b0c",
+ "f0f1f2f3f4f5f6f7f8f9",
+ 42,
+ "077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5",
+ "3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf" +
+ "34007208d5b887185865"));
+ add(new TestData("RFC 5869 Test Case 2", "HKDF-SHA256",
+ "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" +
+ "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" +
+ "404142434445464748494a4b4c4d4e4f",
+ "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f" +
+ "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f" +
+ "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf",
+ "b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecf" +
+ "d0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeef" +
+ "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
+ 82,
+ "06a6b88c5853361a06104c9ceb35b45cef760014904671014a193f40c15fc244",
+ "b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c" +
+ "59045a99cac7827271cb41c65e590e09da3275600c2f09b8367793a9aca3db71" +
+ "cc30c58179ec3e87c14c01d5c1f3434f1d87"));
+ add(new TestData("RFC 5869 Test Case 3", "HKDF-SHA256",
+ "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
+ new String(new byte[0]), null, 42,
+ "19ef24a32c717b167f33a91d6f648bdf96596776afdb6377ac434c1c293ccb04",
+ "8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d" +
+ "9d201395faa4b61a96c8"));
+ }};
+
+ public static void main(String args[]) throws Exception {
+ int testsPassed = 0;
+
+ int testNo = 0;
+ for (TestData test : testList) {
+ System.out.println("*** Test " + ++testNo + ": " +
+ test.testName);
+ if (runVector(test)) {
+ testsPassed++;
+ }
+ }
+
+ System.out.println("Total tests: " + testList.size() +
+ ", Passed: " + testsPassed + ", Failed: " +
+ (testList.size() - testsPassed));
+ if (testsPassed != testList.size()) {
+ throw new RuntimeException("One or more tests failed. " +
+ "Check output for details");
+ }
+ }
+
+ private static boolean runVector(TestData testData)
+ throws InvalidParameterSpecException,
+ InvalidAlgorithmParameterException,
+ NoSuchAlgorithmException {
+ String kdfName, prfName;
+ KDF kdfHkdf, kdfExtract, kdfExpand;
+ boolean result = true;
+ SecretKey actualPRK;
+ SecretKey actualOKM;
+ byte[] deriveData;
+
+ try {
+ kdfHkdf = KDF.getInstance(testData.algName);
+ kdfExtract = KDF.getInstance(testData.algName);
+ kdfExpand = KDF.getInstance(testData.algName);
+ } catch (NoSuchAlgorithmException nsae) {
+ InvalidParameterSpecException exc =
+ new InvalidParameterSpecException();
+ exc.initCause(nsae);
+ throw exc;
+ }
+
+ // Set up the input keying material
+ SecretKey ikmKey = new SecretKeySpec(testData.ikm, "HKDF-IKM");
+
+ // *** HKDF-Extract-only testing
+ // Create KDFParameterSpec for the Extract-only operation
+ AlgorithmParameterSpec derivationSpecExtract =
+ HKDFParameterSpec.ofExtract().addIKM(ikmKey)
+ .addSalt(testData.salt)
+ .extractOnly();
+ actualPRK = kdfExtract.deriveKey("Generic", derivationSpecExtract);
+
+ // Re-run the KDF to give us raw output data
+ deriveData = kdfExtract.deriveData(derivationSpecExtract);
+
+ System.out.println("* HKDF-Extract-Only:");
+ result &= compareKeyAndData(actualPRK, deriveData,
+ testData.expectedPRK);
+
+ // *** HKDF Expand-Only testing
+ // For these tests, we'll use the actualPRK as the input key
+ // Create KDFParameterSpec for key output and raw byte output
+ AlgorithmParameterSpec derivationSpecExpand = HKDFParameterSpec.expandOnly(
+ actualPRK, testData.info,
+ testData.outLen);
+ actualOKM = kdfExpand.deriveKey("Generic", derivationSpecExpand);
+
+ // Re-run the KDF to give us raw output data
+ deriveData = kdfExpand.deriveData(derivationSpecExpand);
+
+ System.out.println("* HKDF-Expand-Only:");
+ result &= compareKeyAndData(actualOKM, deriveData,
+ testData.expectedOKM);
+
+ // *** HKDF Extract-then-Expand testing
+ // We can reuse the KDFParameterSpec from the Expand-only test
+
+ // Use the KDF to make us a key
+ AlgorithmParameterSpec derivationSpecExtractExpand =
+ HKDFParameterSpec.ofExtract().addIKM(ikmKey)
+ .addSalt(testData.salt)
+ .thenExpand(testData.info,
+ testData.outLen);
+ actualOKM = kdfHkdf.deriveKey("Generic", derivationSpecExtractExpand);
+
+ // Re-run the KDF to give us raw output data
+ deriveData = kdfHkdf.deriveData(derivationSpecExtractExpand);
+
+ System.out.println("* HKDF-Extract-then-Expand:");
+ result &= compareKeyAndData(actualOKM, deriveData,
+ testData.expectedOKM);
+
+ return result;
+ }
+
+ /**
+ * Compare key-based and data-based productions from the KDF against an
+ * expected output value.
+ *
+ * @param outKey
+ * the KDF output in key form
+ * @param outData
+ * the KDF output as raw bytes
+ * @param expectedOut
+ * the expected value
+ *
+ * @return true if the underlying data for outKey, outData and expectedOut
+ * are the same.
+ */
+ private static boolean compareKeyAndData(Key outKey, byte[] outData,
+ byte[] expectedOut) {
+ boolean result = true;
+
+ if (Arrays.equals(outKey.getEncoded(), expectedOut)) {
+ System.out.println("\t* Key output: Pass");
+ } else {
+ result = false;
+ System.out.println("\t* Key output: FAIL");
+ System.out.println("Expected:\n" +
+ dumpHexBytes(expectedOut, 16, "\n", " "));
+ System.out.println("Actual:\n" +
+ dumpHexBytes(outKey.getEncoded(), 16, "\n",
+ " "));
+ System.out.println();
+ }
+
+ if (Arrays.equals(outData, expectedOut)) {
+ System.out.println("\t* Data output: Pass");
+ } else {
+ result = false;
+ System.out.println("\t* Data output: FAIL");
+ System.out.println("Expected:\n" +
+ dumpHexBytes(expectedOut, 16, "\n", " "));
+ System.out.println("Actual:\n" +
+ dumpHexBytes(outData, 16, "\n", " "));
+ System.out.println();
+ }
+
+ return result;
+ }
+
+ /**
+ * Dump the hex bytes of a buffer into string form.
+ *
+ * @param data
+ * The array of bytes to dump to stdout.
+ * @param itemsPerLine
+ * The number of bytes to display per line if the {@code lineDelim}
+ * character is blank then all bytes will be printed on a single line.
+ * @param lineDelim
+ * The delimiter between lines
+ * @param itemDelim
+ * The delimiter between bytes
+ *
+ * @return The hexdump of the byte array
+ */
+ private static String dumpHexBytes(byte[] data, int itemsPerLine,
+ String lineDelim, String itemDelim) {
+ StringBuilder sb = new StringBuilder();
+ if (data != null) {
+ for (int i = 0; i < data.length; i++) {
+ if (i % itemsPerLine == 0 && i != 0) {
+ sb.append(lineDelim);
+ }
+ sb.append(String.format("%02X", data[i])).append(itemDelim);
+ }
+ }
+
+ return sb.toString();
+ }
+}
diff --git a/test/jdk/com/sun/crypto/provider/KDF/HKDFSaltIKMTest.java b/test/jdk/com/sun/crypto/provider/KDF/HKDFSaltIKMTest.java
new file mode 100644
index 00000000000..1cd0feab614
--- /dev/null
+++ b/test/jdk/com/sun/crypto/provider/KDF/HKDFSaltIKMTest.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8331008
+ * @summary addIKM and addSalt consistency checks
+ * @library /test/lib
+ * @enablePreview
+ */
+
+import jdk.test.lib.Asserts;
+import jdk.test.lib.security.SeededSecureRandom;
+
+import javax.crypto.KDF;
+import javax.crypto.spec.HKDFParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.io.ByteArrayOutputStream;
+import java.util.Arrays;
+
+public class HKDFSaltIKMTest {
+ static String[] NAMES = {"HKDF-SHA256", "HKDF-SHA384", "HKDF-SHA512"};
+ public static void main(String[] args) throws Exception {
+ var r = SeededSecureRandom.one();
+ var atlast = 0;
+ KDF kdf = null;
+ var alg = "";
+ for (var i = 0; i < 1_000_000; i++) {
+ if (kdf == null || r.nextBoolean()) {
+ alg = NAMES[r.nextInt(3)];
+ kdf = KDF.getInstance(alg); // randomly recreate KDF object
+ }
+ var b = HKDFParameterSpec.ofExtract();
+ var salts = new ByteArrayOutputStream(); // accumulate salt fragments
+ var ikms = new ByteArrayOutputStream(); // accumulate ikm fragments
+ while (r.nextBoolean()) {
+ if (r.nextBoolean()) {
+ var ikm = r.nBytes(r.nextInt(10));
+ if (r.nextBoolean() && ikm.length > 0) {
+ b.addIKM(new SecretKeySpec(ikm, "X"));
+ } else {
+ b.addIKM(ikm);
+ }
+ ikms.writeBytes(ikm);
+ } else {
+ var salt = r.nBytes(r.nextInt(10));
+ if (r.nextBoolean() && salt.length > 0) {
+ b.addSalt(new SecretKeySpec(salt, "X"));
+ } else {
+ b.addSalt(salt);
+ }
+ salts.writeBytes(salt);
+ }
+ }
+ var info = r.nextBoolean() ? null : r.nBytes(r.nextInt(100));
+ var l = r.nextInt(200) + 1;
+ var kdf2 = r.nextBoolean() ? kdf : KDF.getInstance(alg);
+ var k1 = kdf2.deriveData(HKDFParameterSpec.ofExtract().addIKM(ikms.toByteArray())
+ .addSalt(salts.toByteArray()).thenExpand(info, l));
+ atlast = Arrays.hashCode(k1) + 17 * atlast;
+ if (r.nextBoolean()) {
+ var k2 = kdf.deriveData(b.thenExpand(info, l));
+ Asserts.assertEqualsByteArray(k1, k2);
+ } else {
+ var prk = kdf.deriveKey("PRK", b.extractOnly());
+ var k2 = kdf.deriveData(HKDFParameterSpec.expandOnly(prk, info, l));
+ Asserts.assertEqualsByteArray(k1, k2);
+ }
+ }
+ System.out.println(atlast);
+ }
+}
\ No newline at end of file
diff --git a/test/jdk/java/awt/Graphics2D/ScaledTransform/ScaledTransform.java b/test/jdk/java/awt/Graphics2D/ScaledTransform/ScaledTransform.java
index 6a256914527..44487a57200 100644
--- a/test/jdk/java/awt/Graphics2D/ScaledTransform/ScaledTransform.java
+++ b/test/jdk/java/awt/Graphics2D/ScaledTransform/ScaledTransform.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -21,6 +21,7 @@
* questions.
*/
import java.awt.Dialog;
+import java.awt.EventQueue;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
@@ -29,63 +30,93 @@
import java.awt.GraphicsEnvironment;
import java.awt.Panel;
import java.awt.geom.AffineTransform;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
/*
* @test
* @bug 8069361
* @key headful
* @summary SunGraphics2D.getDefaultTransform() does not include scale factor
- * @author Alexander Scherbatiy
- * @run main ScaledTransform
+ * @run main/timeout=300 ScaledTransform
*/
public class ScaledTransform {
- private static volatile boolean passed = false;
+ private static volatile CountDownLatch painted;
+ private static volatile boolean passed;
+ private static volatile Dialog dialog;
+ private static volatile long startTime;
+ private static volatile long endTime;
- public static void main(String[] args) {
+ public static void main(String[] args) throws Exception {
GraphicsEnvironment ge = GraphicsEnvironment.
getLocalGraphicsEnvironment();
- if (ge.isHeadlessInstance()) {
- return;
- }
-
for (GraphicsDevice gd : ge.getScreenDevices()) {
- for (GraphicsConfiguration gc : gd.getConfigurations()) {
- testScaleFactor(gc);
+ System.out.println("Screen = " + gd);
+ test(gd.getDefaultConfiguration());
+ /* Don't want to run too long. Test the default and up to 10 more */
+ GraphicsConfiguration[] configs = gd.getConfigurations();
+ for (int c = 0; c < configs.length && c < 10; c++) {
+ test(configs[c]);
}
}
}
- private static void testScaleFactor(final GraphicsConfiguration gc) {
- final Dialog dialog = new Dialog((Frame) null, "Test", true, gc);
-
+ static void test(GraphicsConfiguration gc) throws Exception {
try {
- dialog.setSize(100, 100);
- Panel panel = new Panel() {
-
- @Override
- public void paint(Graphics g) {
- if (g instanceof Graphics2D) {
- AffineTransform gcTx = gc.getDefaultTransform();
- AffineTransform gTx
- = ((Graphics2D) g).getTransform();
- passed = gcTx.getScaleX() == gTx.getScaleX()
- && gcTx.getScaleY() == gTx.getScaleY();
- } else {
- passed = true;
- }
- dialog.setVisible(false);
- }
- };
- dialog.add(panel);
- dialog.setVisible(true);
-
+ /* reset vars for each run */
+ passed = false;
+ dialog = null;
+ painted = new CountDownLatch(1);
+ EventQueue.invokeLater(() -> showDialog(gc));
+ startTime = System.currentTimeMillis();
+ endTime = startTime;
+ if (!painted.await(5, TimeUnit.SECONDS)) {
+ throw new RuntimeException("Panel is not painted!");
+ }
+ System.out.println("Time to paint = " + (endTime - startTime) + "ms.");
if (!passed) {
throw new RuntimeException("Transform is not scaled!");
}
} finally {
- dialog.dispose();
+ EventQueue.invokeAndWait(() -> disposeDialog());
}
}
+
+ private static void showDialog(final GraphicsConfiguration gc) {
+ System.out.println("Creating dialog for gc=" + gc + " with tx=" + gc.getDefaultTransform());
+ dialog = new Dialog((Frame) null, "ScaledTransform", true, gc);
+ dialog.setSize(300, 100);
+
+ Panel panel = new Panel() {
+
+ @Override
+ public void paint(Graphics g) {
+ System.out.println("Painting panel");
+ if (g instanceof Graphics2D g2d) {
+ AffineTransform gcTx = gc.getDefaultTransform();
+ AffineTransform gTx = g2d.getTransform();
+ System.out.println("GTX = " + gTx);
+ passed = (gcTx.getScaleX() == gTx.getScaleX()) &&
+ (gcTx.getScaleY() == gTx.getScaleY());
+ } else {
+ passed = true;
+ }
+ endTime = System.currentTimeMillis();
+ painted.countDown();
+ System.out.println("Painted panel");
+ }
+ };
+ dialog.add(panel);
+ dialog.setVisible(true);
+ }
+
+ private static void disposeDialog() {
+ if (dialog != null) {
+ System.out.println("Disposing dialog");
+ dialog.setVisible(false);
+ dialog.dispose();
+ }
+ }
}
diff --git a/test/jdk/java/awt/print/Dialog/PrintDlgPageable.java b/test/jdk/java/awt/print/Dialog/PrintDlgPageable.java
index eadd3cf9cb6..ba13ea96825 100644
--- a/test/jdk/java/awt/print/Dialog/PrintDlgPageable.java
+++ b/test/jdk/java/awt/print/Dialog/PrintDlgPageable.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,105 +25,98 @@
* @test
* @bug 4869502 4869539
* @key printer
- * @summary Confirm that ToPage is populated for argument =2. Range is disabled for argument = 0.
- * @run main/manual PrintDlgPageable
+ * @summary Confirm that ToPage is populated for argument = 2. Range is disabled for argument = 0.
+ * @library /java/awt/regtesthelpers
+ * @build PassFailJFrame
+ * @run main/manual PrintDlgPageable 0
+ * @run main/manual PrintDlgPageable 2
*/
-import java.awt.*;
-import java.awt.print.*;
-import java.util.Locale;
-import javax.print.*;
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.print.PageFormat;
+import java.awt.print.Pageable;
+import java.awt.print.Printable;
+import java.awt.print.PrinterJob;
+import java.awt.print.PrinterException;
+
+public class PrintDlgPageable implements Printable {
-class PrintDlgPageable implements Printable {
public static int arg;
- /**
- * Constructor
- */
- public PrintDlgPageable() {
- super();
+ public PrintDlgPageable() {
+ super();
+ }
+
+ public static void main(String[] args) throws Exception {
+ if (args.length < 1) {
+ System.out.println("usage: java PrintDlgPageable { 0 | 2}");
+ return;
}
- /**
- * Starts the application.
- */
- public static void main(java.lang.String[] args) {
- if (args.length < 1) {
- System.out.println("usage: java PrintDlgPageable { 0 | 2}");
- return;
- }
- arg = Integer.parseInt(args[0]);
- PrintDlgPageable pd = new PrintDlgPageable();
- PrinterJob pj = PrinterJob.getPrinterJob();
- PageableHandler handler = new PageableHandler();
- pj.setPageable(handler);
-
- System.out.println("open PrintDialog..");
- if (pj.printDialog()) {
- try {
- System.out.println("About to print the data ...");
- pj.print();
- System.out.println("Printed");
- }
- catch (PrinterException pe) {
- pe.printStackTrace();
- }
- }
+ arg = Integer.parseInt(args[0]);
+ String INSTRUCTIONS = " A pagedialog will be shown.";
+
+ if (arg == 0) {
+ INSTRUCTIONS += "\n Confirm that page range is disabled.";
+ } else if (arg == 2) {
+ INSTRUCTIONS += "\n Confirm ToPage is populated with pagerange 2";
}
+ INSTRUCTIONS += "\nCancel the print dialog. Press PASS if it so seen else press FAIL.";
+
+ PrinterJob pj = PrinterJob.getPrinterJob();
+ PageableHandler handler = new PageableHandler();
+ pj.setPageable(handler);
+
+ PassFailJFrame passFailJFrame = PassFailJFrame.builder()
+ .title("Instructions")
+ .instructions(INSTRUCTIONS)
+ .columns(35)
+ .build();
- //printable interface
- public int print(Graphics g, PageFormat pf, int pi) throws
-PrinterException {
-
- /*if (pi > 0) {
- System.out.println("pi is greater than 0");
- return Printable.NO_SUCH_PAGE;
- }*/
- // Simply draw two rectangles
- Graphics2D g2 = (Graphics2D)g;
- g2.setColor(Color.black);
- g2.translate(pf.getImageableX(), pf.getImageableY());
- g2.drawRect(1,1,200,300);
- g2.drawRect(1,1,25,25);
- System.out.println("print method called "+pi + " Orientation "+pf.getOrientation());
- return Printable.PAGE_EXISTS;
+ if (pj.printDialog()) {
+ try {
+ pj.print();
+ } catch (PrinterException pe) {
+ pe.printStackTrace();
+ }
}
+ passFailJFrame.awaitAndCheck();
+ }
+
+ //printable interface
+ public int print(Graphics g, PageFormat pf, int pi) throws PrinterException {
+
+ // Simply draw two rectangles
+ Graphics2D g2 = (Graphics2D) g;
+ g2.setColor(Color.black);
+ g2.translate(pf.getImageableX(), pf.getImageableY());
+ g2.drawRect(1, 1, 200, 300);
+ g2.drawRect(1, 1, 25, 25);
+ return Printable.PAGE_EXISTS;
+ }
}
class PageableHandler implements Pageable {
- PageFormat pf = new PageFormat();
+ PageFormat pf = new PageFormat();
- public int getNumberOfPages() {
- return PrintDlgPageable.arg;
- //return 0;
- }
+ public int getNumberOfPages() {
+ return PrintDlgPageable.arg;
+ }
- public Printable getPrintable(int pageIndex) {
- return new PrintDlgPageable();
- }
+ public Printable getPrintable(int pageIndex) {
+ return new PrintDlgPageable();
+ }
- public PageFormat getPageFormat(int pageIndex) {
- System.out.println("getPageFormat called "+pageIndex);
- if (pageIndex == 0) {
- pf.setOrientation(PageFormat.PORTRAIT);
- System.out.println("Orientation returned from Pageable "+findOrientation(pf.getOrientation()));
- return pf;
- } else {
- pf.setOrientation(PageFormat.LANDSCAPE);
- System.out.println("Orientation returned from Pageable "+findOrientation(pf.getOrientation()));
- return pf;
- }
+ public PageFormat getPageFormat(int pageIndex) {
+ if (pageIndex == 0) {
+ pf.setOrientation(PageFormat.PORTRAIT);
+ return pf;
+ } else {
+ pf.setOrientation(PageFormat.LANDSCAPE);
+ return pf;
}
+ }
- public String findOrientation(int orient) {
- if (orient == PageFormat.LANDSCAPE) {
- return "LANDSCAPE";
- }else if (orient == PageFormat.PORTRAIT) {
- return "PORTRAIT";
- } else if (orient == PageFormat.REVERSE_LANDSCAPE) {
- return "REVERSE LANDSCAPE";
- } else {
- return null;
- }
- }
}
diff --git a/test/jdk/java/awt/print/PrinterJob/PrintTextTest.java b/test/jdk/java/awt/print/PrinterJob/PrintTextTest.java
index 95bf177aa2f..f2ec4e15a8a 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, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -21,193 +21,207 @@
* questions.
*/
-/**
+/*
* @test
* @bug 6425068 7157659 8132890
* @key printer
* @summary Confirm that text prints where we expect to the length we expect.
- * @run main/manual=yesno PrintTextTest
+ * @library /java/awt/regtesthelpers
+ * @build PassFailJFrame
+ * @run main/manual PrintTextTest
*/
-import java.awt.*;
-import java.awt.event.*;
-import java.text.*;
-import java.util.*;
-import java.awt.font.*;
-import java.awt.geom.*;
-import java.awt.print.*;
-import javax.swing.*;
-
-public class PrintTextTest extends Component implements Printable {
-
- static int preferredSize;
- Font textFont;
- AffineTransform gxTx;
- String page;
- boolean useFM;
-
- public static void main(String args[]) {
- String[] instructions =
- {
- "This tests that printed text renders similarly to on-screen",
- "under a variety of APIs and graphics and font transforms",
- "Print to your preferred printer. Collect the output.",
- "Refer to the onscreen buttons to cycle through the on-screen",
- "content",
- "For each page, confirm that the printed content corresponds to",
- "the on-screen rendering for that *same* page.",
- "Some cases may look odd but its intentional. Verify",
- "it looks the same on screen and on the printer.",
- "Note that text does not scale linearly from screen to printer",
- "so some differences are normal and not a bug.",
- "The easiest way to spot real problems is to check that",
- "any underlines are the same length as the underlined text",
- "and that any rotations are the same in each case.",
- "Note that each on-screen page is printed in both portrait",
- "and landscape mode",
- "So for example, Page 1/Portrait, and Page 1/Landscape when",
- "rotated to view properly, should both match Page 1 on screen.",
- };
- Sysout.createDialogWithInstructions(instructions);
-
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.GraphicsEnvironment;
+import java.awt.RenderingHints;
+import java.awt.font.FontRenderContext;
+import java.awt.font.GlyphVector;
+import java.awt.font.TextLayout;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
+import java.awt.print.Book;
+import java.awt.print.PageFormat;
+import java.awt.print.Printable;
+import java.awt.print.PrinterException;
+import java.awt.print.PrinterJob;
+import java.text.AttributedCharacterIterator;
+import java.text.AttributedString;
+import java.util.HashMap;
+
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JTabbedPane;
+
+public class PrintTextTest {
+
+ static final String INSTRUCTIONS = """
+ This tests that printed text renders similarly to on-screen under a variety
+ of APIs and graphics and font transforms.
+ 1. Print to your preferred printer.
+ 2. Collect the output.
+ 3. Refer to the onscreen buttons to cycle through the on-screen content.
+ 4. For each page, confirm that the printed content corresponds to the
+ on-screen rendering for that *same* page. Some cases may look odd but
+ its intentional. Verify it looks the same on screen and on the printer.
+ Note that text does not scale linearly from screen to printer so some
+ differences are normal and not a bug.
+ The easiest way to spot real problems is to check that any underlines are
+ the same length as the underlined text and that any rotations are the same
+ in each case.
+ Note that each on-screen page is printed in both portrait and landscape mode.
+ So for example, Page 1/Portrait, and Page 1/Landscape when rotated to view
+ properly, should both match Page 1 on screen.
+ """;
+
+ public static void main(String[] args) throws Exception {
PrinterJob pjob = PrinterJob.getPrinterJob();
PageFormat portrait = pjob.defaultPage();
portrait.setOrientation(PageFormat.PORTRAIT);
- preferredSize = (int)portrait.getImageableWidth();
+ int preferredSize = (int) portrait.getImageableWidth();
PageFormat landscape = pjob.defaultPage();
landscape.setOrientation(PageFormat.LANDSCAPE);
Book book = new Book();
- JTabbedPane p = new JTabbedPane();
+ JTabbedPane pane = new JTabbedPane();
int page = 1;
- Font font = new Font("Dialog", Font.PLAIN, 18);
- String name = "Page " + new Integer(page++);
- PrintTextTest ptt = new PrintTextTest(name, font, null, false);
- p.add(name, ptt);
- book.append(ptt, portrait);
- book.append(ptt, landscape);
-
- font = new Font("Dialog", Font.PLAIN, 18);
- name = "Page " + new Integer(page++);
- ptt = new PrintTextTest(name, font, null, true);
- p.add(name, ptt);
- book.append(ptt, portrait);
- book.append(ptt, landscape);
+ Font font = new Font(Font.DIALOG, Font.PLAIN, 18);
+ String name = "Page " + page++;
+ PrintText pt = new PrintText(name, font, null, false, preferredSize);
+ pane.addTab(name, pt);
+ book.append(pt, portrait);
+ book.append(pt, landscape);
+
+ font = new Font(Font.DIALOG, Font.PLAIN, 18);
+ name = "Page " + page++;
+ pt = new PrintText(name, font, null, true, preferredSize);
+ pane.addTab(name, pt);
+ book.append(pt, portrait);
+ book.append(pt, landscape);
font = getPhysicalFont();
- name = "Page " + new Integer(page++);
- ptt = new PrintTextTest(name, font, null, false);
- p.add(name, ptt);
- book.append(ptt, portrait);
- book.append(ptt, landscape);
+ name = "Page " + page++;
+ pt = new PrintText(name, font, null, false, preferredSize);
+ pane.addTab(name, pt);
+ book.append(pt, portrait);
+ book.append(pt, landscape);
font = getPhysicalFont();
AffineTransform rotTx = AffineTransform.getRotateInstance(0.15);
- rotTx.translate(60,0);
- name = "Page " + new Integer(page++);
- ptt = new PrintTextTest(name, font, rotTx, false);
- p.add(name, ptt);
- book.append(ptt, portrait);
- book.append(ptt, landscape);
-
- font = new Font("Dialog", Font.PLAIN, 18);
+ rotTx.translate(60, 0);
+ name = "Page " + page++;
+ pt = new PrintText(name, font, rotTx, false, preferredSize);
+ pane.addTab(name, pt);
+ book.append(pt, portrait);
+ book.append(pt, landscape);
+
+ font = new Font(Font.DIALOG, Font.PLAIN, 18);
AffineTransform scaleTx = AffineTransform.getScaleInstance(1.25, 1.25);
- name = "Page " + new Integer(page++);
- ptt = new PrintTextTest(name, font, scaleTx, false);
- p.add(name, ptt);
- book.append(ptt, portrait);
- book.append(ptt, landscape);
+ name = "Page " + page++;
+ pt = new PrintText(name, font, scaleTx, false, preferredSize);
+ pane.addTab(name, pt);
+ book.append(pt, portrait);
+ book.append(pt, landscape);
- font = new Font("Dialog", Font.PLAIN, 18);
+ font = new Font(Font.DIALOG, Font.PLAIN, 18);
scaleTx = AffineTransform.getScaleInstance(-1.25, 1.25);
- scaleTx.translate(-preferredSize/1.25, 0);
- name = "Page " + new Integer(page++);
- ptt = new PrintTextTest(name, font, scaleTx, false);
- p.add(name, ptt);
- book.append(ptt, portrait);
- book.append(ptt, landscape);
-
- font = new Font("Dialog", Font.PLAIN, 18);
+ scaleTx.translate(-preferredSize / 1.25, 0);
+ name = "Page " + page++;
+ pt = new PrintText(name, font, scaleTx, false, preferredSize);
+ pane.addTab(name, pt);
+ book.append(pt, portrait);
+ book.append(pt, landscape);
+
+ font = new Font(Font.DIALOG, Font.PLAIN, 18);
scaleTx = AffineTransform.getScaleInstance(1.25, -1.25);
- scaleTx.translate(0, -preferredSize/1.25);
- name = "Page " + new Integer(page++);
- ptt = new PrintTextTest(name, font, scaleTx, false);
- p.add(name, ptt);
- book.append(ptt, portrait);
- book.append(ptt, landscape);
+ scaleTx.translate(0, -preferredSize / 1.25);
+ name = "Page " + page++;
+ pt = new PrintText(name, font, scaleTx, false, preferredSize);
+ pane.addTab(name, pt);
+ book.append(pt, portrait);
+ book.append(pt, landscape);
font = font.deriveFont(rotTx);
- name = "Page " + new Integer(page++);
- ptt = new PrintTextTest(name, font, null, false);
- p.add(ptt, BorderLayout.CENTER);
- p.add(name, ptt);
- book.append(ptt, portrait);
- book.append(ptt, landscape);
-
- font = new Font("Monospaced", Font.PLAIN, 12);
- name = "Page " + new Integer(page++);
- ptt = new PrintTextTest(name, font, null, false);
- p.add(ptt, BorderLayout.CENTER);
- p.add(name, ptt);
- book.append(ptt, portrait);
- book.append(ptt, landscape);
+ name = "Page " + page++;
+ pt = new PrintText(name, font, null, false, preferredSize);
+ pane.addTab(name, pt);
+ book.append(pt, portrait);
+ book.append(pt, landscape);
+
+ font = new Font(Font.MONOSPACED, Font.PLAIN, 12);
+ name = "Page " + page++;
+ pt = new PrintText(name, font, null, false, preferredSize);
+ pane.addTab(name, pt);
+ book.append(pt, portrait);
+ book.append(pt, landscape);
Font xfont = font.deriveFont(AffineTransform.getScaleInstance(1.5, 1));
- name = "Page " + new Integer(page++);
- ptt = new PrintTextTest(name, xfont, null, false);
- p.add(ptt, BorderLayout.CENTER);
- p.add(name, ptt);
- book.append(ptt, portrait);
- book.append(ptt, landscape);
+ name = "Page " + page++;
+ pt = new PrintText(name, xfont, null, false, preferredSize);
+ pane.addTab(name, pt);
+ book.append(pt, portrait);
+ book.append(pt, landscape);
Font yfont = font.deriveFont(AffineTransform.getScaleInstance(1, 1.5));
- name = "Page " + new Integer(page++);
- ptt = new PrintTextTest(name, yfont, null, false);
- p.add(ptt, BorderLayout.CENTER);
- p.add(name, ptt);
- book.append(ptt, portrait);
- book.append(ptt, landscape);
+ name = "Page " + page++;
+ pt = new PrintText(name, yfont, null, false, preferredSize);
+ pane.addTab(name, pt);
+ book.append(pt, portrait);
+ book.append(pt, landscape);
if (System.getProperty("os.name").startsWith("Windows")) {
font = new Font("MS Gothic", Font.PLAIN, 12);
- name = "Page " + new Integer(page++);
- ptt = new PrintJAText(name, font, null, true);
- p.add(ptt, BorderLayout.CENTER);
- p.add(name, ptt);
- book.append(ptt, portrait);
- book.append(ptt, landscape);
+ name = "Page " + page++;
+ pt = new PrintJapaneseText(name, font, null, true, preferredSize);
+ pane.addTab(name, pt);
+ book.append(pt, portrait);
+ book.append(pt, landscape);
font = new Font("MS Gothic", Font.PLAIN, 12);
- name = "Page " + new Integer(page++);
+ name = "Page " + page++;
rotTx = AffineTransform.getRotateInstance(0.15);
- ptt = new PrintJAText(name, font, rotTx, true);
- p.add(ptt, BorderLayout.CENTER);
- p.add(name, ptt);
- book.append(ptt, portrait);
- book.append(ptt, landscape);
+ pt = new PrintJapaneseText(name, font, rotTx, true, preferredSize);
+ pane.addTab(name, pt);
+ book.append(pt, portrait);
+ book.append(pt, landscape);
}
pjob.setPageable(book);
- JFrame f = new JFrame();
- f.add(BorderLayout.CENTER, p);
- f.addWindowListener(new WindowAdapter() {
- public void windowClosing(WindowEvent e) {System.exit(0);}
+ JButton printButton = new JButton("Print");
+ printButton.addActionListener(event -> {
+ try {
+ if (pjob.printDialog()) {
+ pjob.print();
+ }
+ } catch (PrinterException e) {
+ throw new RuntimeException(e.getMessage(), e);
+ }
});
+
+ JFrame f = new JFrame("PrintTextTest");
+ f.add(BorderLayout.CENTER, pane);
+ f.add(BorderLayout.SOUTH, printButton);
f.pack();
- f.show();
- try {
- if (pjob.printDialog()) {
- pjob.print();
- }
- } catch (PrinterException e) {
- throw new RuntimeException(e.getMessage());
- }
+ PassFailJFrame.builder()
+ .title("PrintTextTest")
+ .instructions(INSTRUCTIONS)
+ .testTimeOut(10)
+ .columns(60)
+ .testUI(f)
+ .build()
+ .awaitAndCheck();
}
// The test needs a physical font that supports Latin.
@@ -221,338 +235,228 @@ private static Font getPhysicalFont() {
String[] names = ge.getAvailableFontFamilyNames();
for (String n : names) {
- switch (n.toLowerCase()) {
- case "dialog":
- case "dialoginput":
- case "serif":
- case "sansserif":
- case "monospaced":
- break;
+ switch (n) {
+ case Font.DIALOG:
+ case Font.DIALOG_INPUT:
+ case Font.SERIF:
+ case Font.SANS_SERIF:
+ case Font.MONOSPACED:
+ continue;
default:
Font f = new Font(n, Font.PLAIN, 18);
if (f.canDisplayUpTo("AZaz09") == -1) {
physicalFont = f;
return f;
}
- }
+ }
}
physicalFont = new Font(Font.DIALOG, Font.PLAIN, 18);
return physicalFont;
}
- public PrintTextTest(String page, Font font, AffineTransform gxTx,
- boolean fm) {
- this.page = page;
- textFont = font;
- this.gxTx = gxTx;
- this.useFM = fm;
- setBackground(Color.white);
- }
-
- public static AttributedCharacterIterator getIterator(String s) {
- return new AttributedString(s).getIterator();
- }
-
- static String orient(PageFormat pf) {
- if (pf.getOrientation() == PageFormat.PORTRAIT) {
- return "Portrait";
- } else {
- return "Landscape";
+ private static class PrintText extends Component implements Printable {
+
+ protected final Font textFont;
+ protected final AffineTransform gxTx;
+ protected final String page;
+ protected final boolean useFM;
+ protected final int preferredSize;
+
+ public PrintText(String page, Font font, AffineTransform gxTx, boolean fm, int size) {
+ this.page = page;
+ this.textFont = font;
+ this.gxTx = gxTx;
+ this.useFM = fm;
+ this.preferredSize = size;
+ setBackground(Color.WHITE);
}
- }
- public int print(Graphics g, PageFormat pf, int pageIndex) {
-
- Graphics2D g2d = (Graphics2D)g;
- g2d.translate(pf.getImageableX(), pf.getImageableY());
- g.drawString(page+" "+orient(pf),50,20);
- g.translate(0, 25);
- paint(g);
- return PAGE_EXISTS;
- }
-
- public Dimension getMinimumSize() {
- return getPreferredSize();
- }
-
- public Dimension getPreferredSize() {
- return new Dimension(preferredSize, preferredSize);
- }
-
- public void paint(Graphics g) {
-
- /* fill with white before any transformation is applied */
- g.setColor(Color.white);
- g.fillRect(0, 0, getSize().width, getSize().height);
-
-
- Graphics2D g2d = (Graphics2D) g;
- if (gxTx != null) {
- g2d.transform(gxTx);
+ private static AttributedCharacterIterator getIterator(String s) {
+ return new AttributedString(s).getIterator();
}
- if (useFM) {
- g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
- RenderingHints.VALUE_FRACTIONALMETRICS_ON);
- }
-
- g.setFont(textFont);
- FontMetrics fm = g.getFontMetrics();
- String s;
- int LS = 30;
- int ix=10, iy=LS+10;
- g.setColor(Color.black);
-
- s = "drawString(String str, int x, int y)";
- g.drawString(s, ix, iy);
- if (!textFont.isTransformed()) {
- g.drawLine(ix, iy+1, ix+fm.stringWidth(s), iy+1);
+ private static String orient(PageFormat pf) {
+ if (pf.getOrientation() == PageFormat.PORTRAIT) {
+ return "Portrait";
+ } else {
+ return "Landscape";
+ }
}
- iy += LS;
- s = "drawString(AttributedCharacterIterator iterator, int x, int y)";
- g.drawString(getIterator(s), ix, iy);
-
- iy += LS;
- s = "\tdrawChars(\t\r\nchar[], int off, int len, int x, int y\t)";
- g.drawChars(s.toCharArray(), 0, s.length(), ix, iy);
- if (!textFont.isTransformed()) {
- g.drawLine(ix, iy+1, ix+fm.stringWidth(s), iy+1);
+ @Override
+ public int print(Graphics g, PageFormat pf, int pageIndex) {
+ Graphics2D g2d = (Graphics2D) g;
+ g2d.translate(pf.getImageableX(), pf.getImageableY());
+ g.drawString(page + " " + orient(pf), 50, 20);
+ g.translate(0, 25);
+ paint(g);
+ return PAGE_EXISTS;
}
- iy += LS;
- s = "drawBytes(byte[], int off, int len, int x, int y)";
- byte data[] = new byte[s.length()];
- for (int i = 0; i < data.length; i++) {
- data[i] = (byte) s.charAt(i);
+ @Override
+ public Dimension getMinimumSize() {
+ return getPreferredSize();
}
- g.drawBytes(data, 0, data.length, ix, iy);
- Font f = g2d.getFont();
- FontRenderContext frc = g2d.getFontRenderContext();
-
- iy += LS;
- s = "drawString(String s, float x, float y)";
- g2d.drawString(s, (float) ix, (float) iy);
- if (!textFont.isTransformed()) {
- g.drawLine(ix, iy+1, ix+fm.stringWidth(s), iy+1);
+ @Override
+ public Dimension getPreferredSize() {
+ return new Dimension(preferredSize, preferredSize);
}
- iy += LS;
- s = "drawString(AttributedCharacterIterator iterator, "+
- "float x, float y)";
- g2d.drawString(getIterator(s), (float) ix, (float) iy);
-
- iy += LS;
- s = "drawGlyphVector(GlyphVector g, float x, float y)";
- GlyphVector gv = f.createGlyphVector(frc, s);
- g2d.drawGlyphVector(gv, ix, iy);
- Point2D adv = gv.getGlyphPosition(gv.getNumGlyphs());
- if (!textFont.isTransformed()) {
- g.drawLine(ix, iy+1, ix+(int)adv.getX(), iy+1);
- }
+ @Override
+ public void paint(Graphics g) {
- iy += LS;
- s = "GlyphVector with position adjustments";
-
- gv = f.createGlyphVector(frc, s);
- int ng = gv.getNumGlyphs();
- adv = gv.getGlyphPosition(ng);
- for (int i=0; i(), frc);
+ tl.draw(g2d, ix, iy);
- String text = TEXT + TEXT + TEXT;
- g.setColor(Color.black);
- int y = 20;
- float origSize = 7f;
- for (int i=0;i<11;i++) {
- float size = origSize+(i*0.1f);
- g2d.translate(0, size+6);
- Font f = textFont.deriveFont(size);
- g2d.setFont(f);
- FontMetrics fontMetrics = g2d.getFontMetrics();
- int stringWidth = fontMetrics.stringWidth(text);
- g.drawLine(0, y+1, stringWidth, y+1);
- g.drawString(text, 0, y);
- y +=10;
+ iy += LS;
+ s = "TextLayout 2: \u0924\u094d\u0930 \u0915\u0948\u0930\u0947 End.";
+ tl = new TextLayout(s, f, frc);
+ tl.draw(g2d, ix, iy);
}
}
-}
-
-class Sysout
- {
- private static TestDialog dialog;
- public static void createDialogWithInstructions( String[] instructions )
- {
- dialog = new TestDialog( new Frame(), "Instructions" );
- dialog.printInstructions( instructions );
- dialog.show();
- println( "Any messages for the tester will display here." );
- }
+ private static class PrintJapaneseText extends PrintText {
- public static void createDialog( )
- {
- dialog = new TestDialog( new Frame(), "Instructions" );
- String[] defInstr = { "Instructions will appear here. ", "" } ;
- dialog.printInstructions( defInstr );
- dialog.show();
- println( "Any messages for the tester will display here." );
- }
+ public PrintJapaneseText(String page, Font font, AffineTransform gxTx, boolean fm, int size) {
+ super(page, font, gxTx, fm, size);
+ }
+ private static final String TEXT =
+ "\u3042\u3044\u3046\u3048\u304a\u30a4\u30ed\u30cf" +
+ "\u30cb\u30db\u30d8\u30c8\u4e00\u4e01\u4e02\u4e05\uff08";
- public static void printInstructions( String[] instructions )
- {
- dialog.printInstructions( instructions );
- }
+ @Override
+ public void paint(Graphics g) {
+ g.setColor(Color.WHITE);
+ g.fillRect(0, 0, getSize().width, getSize().height);
- public static void println( String messageIn )
- {
- dialog.displayMessage( messageIn );
- }
+ Graphics2D g2d = (Graphics2D) g;
+ if (gxTx != null) {
+ g2d.transform(gxTx);
+ }
+ if (useFM) {
+ g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
+ RenderingHints.VALUE_FRACTIONALMETRICS_ON);
+ }
- }// Sysout class
-
-/**
- This is part of the standard test machinery. It provides a place for the
- test instructions to be displayed, and a place for interactive messages
- to the user to be displayed.
- To have the test instructions displayed, see Sysout.
- To have a message to the user be displayed, see Sysout.
- Do not call anything in this dialog directly.
- */
-class TestDialog extends Dialog
- {
-
- TextArea instructionsText;
- TextArea messageText;
- int maxStringLength = 80;
-
- //DO NOT call this directly, go through Sysout
- public TestDialog( Frame frame, String name )
- {
- super( frame, name );
- int scrollBoth = TextArea.SCROLLBARS_BOTH;
- instructionsText = new TextArea( "", 20, maxStringLength, scrollBoth );
- add( "North", instructionsText );
-
- messageText = new TextArea( "", 5, maxStringLength, scrollBoth );
- add("South", messageText);
-
- pack();
-
- show();
- }// TestDialog()
-
- //DO NOT call this directly, go through Sysout
- public void printInstructions( String[] instructions )
- {
- //Clear out any current instructions
- instructionsText.setText( "" );
-
- //Go down array of instruction strings
-
- String printStr, remainingStr;
- for( int i=0; i < instructions.length; i++ )
- {
- //chop up each into pieces maxSringLength long
- remainingStr = instructions[ i ];
- while( remainingStr.length() > 0 )
- {
- //if longer than max then chop off first max chars to print
- if( remainingStr.length() >= maxStringLength )
- {
- //Try to chop on a word boundary
- int posOfSpace = remainingStr.
- lastIndexOf( ' ', maxStringLength - 1 );
-
- if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1;
-
- printStr = remainingStr.substring( 0, posOfSpace + 1 );
- remainingStr = remainingStr.substring( posOfSpace + 1 );
- }
- //else just print
- else
- {
- printStr = remainingStr;
- remainingStr = "";
- }
-
- instructionsText.append( printStr + "\n" );
-
- }// while
-
- }// for
-
- }//printInstructions()
-
- //DO NOT call this directly, go through Sysout
- public void displayMessage( String messageIn )
- {
- messageText.append( messageIn + "\n" );
+ String text = TEXT + TEXT + TEXT;
+ g.setColor(Color.BLACK);
+ int y = 20;
+ float origSize = 7f;
+ for (int i = 0; i < 11; i++) {
+ float size = origSize + (i * 0.1f);
+ g2d.translate(0, size + 6);
+ Font f = textFont.deriveFont(size);
+ g2d.setFont(f);
+ FontMetrics fontMetrics = g2d.getFontMetrics();
+ int stringWidth = fontMetrics.stringWidth(text);
+ g.drawLine(0, y + 1, stringWidth, y + 1);
+ g.drawString(text, 0, y);
+ y += 10;
+ }
+ }
}
-
-}// TestDialog class
+}
diff --git a/test/jdk/java/foreign/TestMemorySession.java b/test/jdk/java/foreign/TestMemorySession.java
index 617951f6b6b..e5b4ca74027 100644
--- a/test/jdk/java/foreign/TestMemorySession.java
+++ b/test/jdk/java/foreign/TestMemorySession.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 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
@@ -28,12 +28,6 @@
*/
import java.lang.foreign.Arena;
-
-import jdk.internal.foreign.MemorySessionImpl;
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
-import static org.testng.Assert.*;
-
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
@@ -41,6 +35,11 @@
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;
import java.util.stream.IntStream;
+import jdk.internal.foreign.MemorySessionImpl;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.*;
public class TestMemorySession {
@@ -319,6 +318,70 @@ public void testIsCloseableBy(ArenaSupplier arenaSupplier) {
assertEquals(sessionImpl.isCloseableBy(otherThread), isCloseableByOther);
}
+ /**
+ * Test that a thread failing to acquire a scope will not observe it as alive afterwards.
+ */
+ @Test
+ public void testAcquireCloseRace() throws InterruptedException {
+ int iteration = 1000;
+ AtomicInteger lock = new AtomicInteger();
+ boolean[] result = new boolean[1];
+ lock.set(-2);
+ MemorySessionImpl[] scopes = new MemorySessionImpl[iteration];
+ for (int i = 0; i < iteration; i++) {
+ scopes[i] = MemorySessionImpl.toMemorySession(Arena.ofShared());
+ }
+
+ // This thread tries to close the scopes
+ Thread t1 = new Thread(() -> {
+ for (int i = 0; i < iteration; i++) {
+ MemorySessionImpl scope = scopes[i];
+ while (true) {
+ try {
+ scope.close();
+ break;
+ } catch (IllegalStateException e) {}
+ }
+ // Keep the 2 threads operating on the same scope
+ int k = lock.getAndAdd(1) + 1;
+ while (k != i * 2) {
+ Thread.onSpinWait();
+ k = lock.get();
+ }
+ }
+ });
+
+ // This thread tries to acquire the scopes, then check if it is alive after an acquire failure
+ Thread t2 = new Thread(() -> {
+ for (int i = 0; i < iteration; i++) {
+ MemorySessionImpl scope = scopes[i];
+ while (true) {
+ try {
+ scope.acquire0();
+ } catch (IllegalStateException e) {
+ if (scope.isAlive()) {
+ result[0] = true;
+ }
+ break;
+ }
+ scope.release0();
+ }
+ // Keep the 2 threads operating on the same scope
+ int k = lock.getAndAdd(1) + 1;
+ while (k != i * 2) {
+ Thread.onSpinWait();
+ k = lock.get();
+ }
+ }
+ });
+
+ t1.start();
+ t2.start();
+ t1.join();
+ t2.join();
+ assertFalse(result[0]);
+ }
+
private void waitSomeTime() {
try {
Thread.sleep(10);
diff --git a/test/jdk/java/lang/ScopedValue/ScopedValueAPI.java b/test/jdk/java/lang/ScopedValue/ScopedValueAPI.java
index 615f8472e4f..3cb96533cc4 100644
--- a/test/jdk/java/lang/ScopedValue/ScopedValueAPI.java
+++ b/test/jdk/java/lang/ScopedValue/ScopedValueAPI.java
@@ -48,7 +48,7 @@ private static Stream factories() {
}
/**
- * Test that runWhere invokes the Runnable's run method.
+ * Test that where invokes the Runnable's run method.
*/
@ParameterizedTest
@MethodSource("factories")
@@ -56,13 +56,13 @@ void testRunWhere(ThreadFactory factory) throws Exception {
test(factory, () -> {
class Box { static boolean executed; }
ScopedValue name = ScopedValue.newInstance();
- ScopedValue.runWhere(name, "duke", () -> { Box.executed = true; });
+ ScopedValue.where(name, "duke").run(() -> { Box.executed = true; });
assertTrue(Box.executed);
});
}
/**
- * Test runWhere when the run method throws an exception.
+ * Test where when the run method throws an exception.
*/
@ParameterizedTest
@MethodSource("factories")
@@ -71,7 +71,7 @@ void testRunWhereThrows(ThreadFactory factory) throws Exception {
class FooException extends RuntimeException { }
ScopedValue name = ScopedValue.newInstance();
Runnable op = () -> { throw new FooException(); };
- assertThrows(FooException.class, () -> ScopedValue.runWhere(name, "duke", op));
+ assertThrows(FooException.class, () -> ScopedValue.where(name, "duke").run(op));
assertFalse(name.isBound());
});
}
@@ -84,7 +84,7 @@ class FooException extends RuntimeException { }
void testCallWhere(ThreadFactory factory) throws Exception {
test(factory, () -> {
ScopedValue name = ScopedValue.newInstance();
- String result = ScopedValue.callWhere(name, "duke", name::get);
+ String result = ScopedValue.where(name, "duke").call(name::get);
assertEquals("duke", result);
});
}
@@ -99,7 +99,7 @@ void testCallWhereThrows(ThreadFactory factory) throws Exception {
class FooException extends RuntimeException { }
ScopedValue name = ScopedValue.newInstance();
CallableOp op = () -> { throw new FooException(); };
- assertThrows(FooException.class, () -> ScopedValue.callWhere(name, "duke", op));
+ assertThrows(FooException.class, () -> ScopedValue.where(name, "duke").call(op));
assertFalse(name.isBound());
});
}
@@ -116,8 +116,8 @@ void testGet(ThreadFactory factory) throws Exception {
assertThrows(NoSuchElementException.class, name1::get);
assertThrows(NoSuchElementException.class, name2::get);
- // runWhere
- ScopedValue.runWhere(name1, "duke", () -> {
+ // where
+ ScopedValue.where(name1, "duke").run(() -> {
assertEquals("duke", name1.get());
assertThrows(NoSuchElementException.class, name2::get);
@@ -126,7 +126,7 @@ void testGet(ThreadFactory factory) throws Exception {
assertThrows(NoSuchElementException.class, name2::get);
// callWhere
- ScopedValue.callWhere(name1, "duke", () -> {
+ ScopedValue.where(name1, "duke").call(() -> {
assertEquals("duke", name1.get());
assertThrows(NoSuchElementException.class, name2::get);
return null;
@@ -148,8 +148,8 @@ void testIsBound(ThreadFactory factory) throws Exception {
assertFalse(name1.isBound());
assertFalse(name2.isBound());
- // runWhere
- ScopedValue.runWhere(name1, "duke", () -> {
+ // where
+ ScopedValue.where(name1, "duke").run(() -> {
assertTrue(name1.isBound());
assertFalse(name2.isBound());
});
@@ -157,7 +157,7 @@ void testIsBound(ThreadFactory factory) throws Exception {
assertFalse(name2.isBound());
// callWhere
- ScopedValue.callWhere(name1, "duke", () -> {
+ ScopedValue.where(name1, "duke").call(() -> {
assertTrue(name1.isBound());
assertFalse(name2.isBound());
return null;
@@ -178,14 +178,14 @@ void testOrElse(ThreadFactory factory) throws Exception {
assertNull(name.orElse(null));
assertEquals("default", name.orElse("default"));
- // runWhere
- ScopedValue.runWhere(name, "duke", () -> {
+ // where
+ ScopedValue.where(name, "duke").run(() -> {
assertEquals("duke", name.orElse(null));
assertEquals("duke", name.orElse("default"));
});
// callWhere
- ScopedValue.callWhere(name, "duke", () -> {
+ ScopedValue.where(name, "duke").call(() -> {
assertEquals("duke", name.orElse(null));
assertEquals("duke", name.orElse("default"));
return null;
@@ -204,13 +204,13 @@ class FooException extends RuntimeException { }
ScopedValue name = ScopedValue.newInstance();
assertThrows(FooException.class, () -> name.orElseThrow(FooException::new));
- // runWhere
- ScopedValue.runWhere(name, "duke", () -> {
+ // where
+ ScopedValue.where(name, "duke").run(() -> {
assertEquals("duke", name.orElseThrow(FooException::new));
});
// callWhere
- ScopedValue.callWhere(name, "duke", () -> {
+ ScopedValue.where(name, "duke").call(() -> {
assertEquals("duke", name.orElseThrow(FooException::new));
return null;
});
@@ -259,12 +259,12 @@ void testRebinding(ThreadFactory factory) throws Exception {
test(factory, () -> {
ScopedValue name = ScopedValue.newInstance();
- // runWhere
- ScopedValue.runWhere(name, "duke", () -> {
+ // where
+ ScopedValue.where(name, "duke").run(() -> {
assertTrue(name.isBound());
assertEquals("duke", name.get());
- ScopedValue.runWhere(name, "duchess", () -> {
+ ScopedValue.where(name, "duchess").run(() -> {
assertTrue(name.isBound());
assertEquals("duchess", name.get());
});
@@ -275,11 +275,11 @@ void testRebinding(ThreadFactory factory) throws Exception {
assertFalse(name.isBound());
// callWhere
- ScopedValue.callWhere(name, "duke", () -> {
+ ScopedValue.where(name, "duke").call(() -> {
assertTrue(name.isBound());
assertEquals("duke", name.get());
- ScopedValue.callWhere(name, "duchess", () -> {
+ ScopedValue.where(name, "duchess").call(() -> {
assertTrue(name.isBound());
assertEquals("duchess", name.get());
return null;
@@ -302,12 +302,12 @@ void testRebindingFromNull(ThreadFactory factory) throws Exception {
test(factory, () -> {
ScopedValue name = ScopedValue.newInstance();
- // runWhere
- ScopedValue.runWhere(name, null, () -> {
+ // where
+ ScopedValue.where(name, null).run(() -> {
assertTrue(name.isBound());
assertNull(name.get());
- ScopedValue.runWhere(name, "duchess", () -> {
+ ScopedValue.where(name, "duchess").run(() -> {
assertTrue(name.isBound());
assertTrue("duchess".equals(name.get()));
});
@@ -318,11 +318,11 @@ void testRebindingFromNull(ThreadFactory factory) throws Exception {
assertFalse(name.isBound());
// callWhere
- ScopedValue.callWhere(name, null, () -> {
+ ScopedValue.where(name, null).call(() -> {
assertTrue(name.isBound());
assertNull(name.get());
- ScopedValue.callWhere(name, "duchess", () -> {
+ ScopedValue.where(name, "duchess").call(() -> {
assertTrue(name.isBound());
assertTrue("duchess".equals(name.get()));
return null;
@@ -345,12 +345,12 @@ void testRebindingToNull(ThreadFactory factory) throws Exception {
test(factory, () -> {
ScopedValue name = ScopedValue.newInstance();
- // runWhere
- ScopedValue.runWhere(name, "duke", () -> {
+ // where
+ ScopedValue.where(name, "duke").run(() -> {
assertTrue(name.isBound());
assertEquals("duke", name.get());
- ScopedValue.runWhere(name, null, () -> {
+ ScopedValue.where(name, null).run(() -> {
assertTrue(name.isBound());
assertNull(name.get());
});
@@ -361,11 +361,11 @@ void testRebindingToNull(ThreadFactory factory) throws Exception {
assertFalse(name.isBound());
// callWhere
- ScopedValue.callWhere(name, "duke", () -> {
+ ScopedValue.where(name, "duke").call(() -> {
assertTrue(name.isBound());
assertEquals("duke", name.get());
- ScopedValue.callWhere(name, null, () -> {
+ ScopedValue.where(name, null).call(() -> {
assertTrue(name.isBound());
assertNull(name.get());
return null;
@@ -410,11 +410,11 @@ void testNullPointerException() {
assertThrows(NullPointerException.class, () -> ScopedValue.where(null, "duke"));
- assertThrows(NullPointerException.class, () -> ScopedValue.runWhere(null, "duke", () -> { }));
- assertThrows(NullPointerException.class, () -> ScopedValue.runWhere(name, "duke", null));
+ assertThrows(NullPointerException.class, () -> ScopedValue.where(null, "duke").run(() -> { }));
+ assertThrows(NullPointerException.class, () -> ScopedValue.where(name, "duke").run(null));
- assertThrows(NullPointerException.class, () -> ScopedValue.callWhere(null, "duke", () -> ""));
- assertThrows(NullPointerException.class, () -> ScopedValue.callWhere(name, "duke", null));
+ assertThrows(NullPointerException.class, () -> ScopedValue.where(null, "duke").call(() -> ""));
+ assertThrows(NullPointerException.class, () -> ScopedValue.where(name, "duke").call(null));
assertThrows(NullPointerException.class, () -> name.orElseThrow(null));
diff --git a/test/jdk/java/lang/instrument/GetObjectSizeIntrinsicsTest.java b/test/jdk/java/lang/instrument/GetObjectSizeIntrinsicsTest.java
index 22c5069f3e7..1e473ccd974 100644
--- a/test/jdk/java/lang/instrument/GetObjectSizeIntrinsicsTest.java
+++ b/test/jdk/java/lang/instrument/GetObjectSizeIntrinsicsTest.java
@@ -301,6 +301,7 @@
public class GetObjectSizeIntrinsicsTest extends ASimpleInstrumentationTestCase {
+ private static final boolean COMPACT_HEADERS = Platform.is64bit() && WhiteBox.getWhiteBox().getBooleanVMFlag("UseCompactObjectHeaders");
static final Boolean COMPRESSED_OOPS = WhiteBox.getWhiteBox().getBooleanVMFlag("UseCompressedOops");
static final long REF_SIZE = (COMPRESSED_OOPS == null || COMPRESSED_OOPS == true) ? 4 : 8;
@@ -374,15 +375,25 @@ private static long roundUp(long v, long a) {
return (v + a - 1) / a * a;
}
+ private static long expectedSmallObjSize() {
+ long size;
+ if (!Platform.is64bit() || COMPACT_HEADERS) {
+ size = 8;
+ } else {
+ size = 16;
+ }
+ return roundUp(size, OBJ_ALIGN);
+ }
+
private void testSize_newObject() {
- long expected = roundUp(Platform.is64bit() ? 16 : 8, OBJ_ALIGN);
+ long expected = expectedSmallObjSize();
for (int c = 0; c < ITERS; c++) {
assertEquals(expected, fInst.getObjectSize(new Object()));
}
}
private void testSize_localObject() {
- long expected = roundUp(Platform.is64bit() ? 16 : 8, OBJ_ALIGN);
+ long expected = expectedSmallObjSize();
Object o = new Object();
for (int c = 0; c < ITERS; c++) {
assertEquals(expected, fInst.getObjectSize(o));
@@ -392,7 +403,7 @@ private void testSize_localObject() {
static Object staticO = new Object();
private void testSize_fieldObject() {
- long expected = roundUp(Platform.is64bit() ? 16 : 8, OBJ_ALIGN);
+ long expected = expectedSmallObjSize();
for (int c = 0; c < ITERS; c++) {
assertEquals(expected, fInst.getObjectSize(staticO));
}
diff --git a/test/jdk/java/net/HttpURLConnection/HttpURLConnectionExpect100Test.java b/test/jdk/java/net/HttpURLConnection/HttpURLConnectionExpect100Test.java
index 2a858d32fc2..96bef099da2 100644
--- a/test/jdk/java/net/HttpURLConnection/HttpURLConnectionExpect100Test.java
+++ b/test/jdk/java/net/HttpURLConnection/HttpURLConnectionExpect100Test.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -82,9 +82,9 @@ public void expect100ContinueHitCountTest() throws Exception {
conn.setRequestProperty("Expect", "100-continue");
sendRequest(conn);
getHeaderField(conn);
- assertEquals(1, server.getServerHitCount());
// Server rejects the expect 100-continue request with 417 response
assertEquals(417, conn.getResponseCode());
+ assertEquals(1, server.getServerHitCount());
}
@Test
@@ -99,12 +99,12 @@ public void defaultRequestHitCountTest() throws Exception {
conn.setRequestMethod("PUT");
sendRequest(conn);
getHeaderField(conn);
- assertEquals(1, server.getServerHitCount());
assertEquals(200, conn.getResponseCode());
try ( InputStream in = conn.getInputStream()) {
byte[] data = in.readAllBytes();
assertEquals(RESPONSE.length(), data.length);
}
+ assertEquals(1, server.getServerHitCount());
}
private void sendRequest(final HttpURLConnection conn) throws Exception {
@@ -116,6 +116,7 @@ private void sendRequest(final HttpURLConnection conn) throws Exception {
os.flush();
} catch (IOException e) {
// intentional, server will reject the expect 100
+ System.err.println("Got expected exception: " + e);
}
}
@@ -179,7 +180,7 @@ void close() {
@Override
public void run() {
Socket client;
- try {
+ try (ss) {
while (isRunning) {
client = ss.accept();
System.out.println(client.getRemoteSocketAddress().toString());
@@ -191,29 +192,16 @@ public void run() {
if (isRunning) {
throw new RuntimeException(ex);
}
- } finally {
- if (ss != null && !ss.isClosed()) {
- try {
- ss.close();
- } catch (IOException ex) {
- //ignore
- }
- }
}
}
private void handleConnection(Socket client) throws IOException {
- try ( BufferedReader in = new BufferedReader(
+ try (client; BufferedReader in = new BufferedReader(
new InputStreamReader(client.getInputStream()));
PrintStream out = new PrintStream(client.getOutputStream())) {
handle_connection(in, out);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
- } finally {
- try {
- client.close();
- } catch (IOException e) {
- }
}
}
@@ -230,6 +218,10 @@ private void handle_connection(BufferedReader in, PrintStream out)
} else {
defaultResponse(out);
}
+ // wait until the client closes the socket
+ while (line != null) {
+ line = in.readLine();
+ }
}
private void rejectExpect100Continue(PrintStream out) {
diff --git a/test/jdk/java/net/httpclient/ManyRequests2.java b/test/jdk/java/net/httpclient/ManyRequests2.java
index b0d17fe9bca..69ce475eca2 100644
--- a/test/jdk/java/net/httpclient/ManyRequests2.java
+++ b/test/jdk/java/net/httpclient/ManyRequests2.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -33,16 +33,16 @@
* @compile ../../../com/sun/net/httpserver/EchoHandler.java
* @compile ../../../com/sun/net/httpserver/FileServerHandler.java
* @build ManyRequests ManyRequests2
- * @run main/othervm/timeout=40 -Dtest.XFixed=true
+ * @run main/othervm/timeout=400 -Dsun.net.httpserver.idleInterval=400 -Dtest.XFixed=true
* -Djdk.tracePinnedThreads=full
* -Djdk.httpclient.HttpClient.log=channel ManyRequests2
- * @run main/othervm/timeout=40 -Dtest.XFixed=true -Dtest.insertDelay=true
+ * @run main/othervm/timeout=400 -Dsun.net.httpserver.idleInterval=400 -Dtest.XFixed=true -Dtest.insertDelay=true
* -Djdk.tracePinnedThreads=full
* -Djdk.httpclient.HttpClient.log=channel ManyRequests2
- * @run main/othervm/timeout=40 -Dtest.XFixed=true -Dtest.chunkSize=64
+ * @run main/othervm/timeout=400 -Dsun.net.httpserver.idleInterval=400 -Dtest.XFixed=true -Dtest.chunkSize=64
* -Djdk.tracePinnedThreads=full
* -Djdk.httpclient.HttpClient.log=channel ManyRequests2
- * @run main/othervm/timeout=400 -Djdk.internal.httpclient.debug=true
+ * @run main/othervm/timeout=400 -Dsun.net.httpserver.idleInterval=400 -Djdk.internal.httpclient.debug=true
* -Djdk.tracePinnedThreads=full
* -Djdk.httpclient.HttpClient.log=channel
* -Dtest.XFixed=true -Dtest.insertDelay=true
diff --git a/test/jdk/java/nio/file/attribute/BasicFileAttributeView/SetTimesNanos.java b/test/jdk/java/nio/file/attribute/BasicFileAttributeView/SetTimesNanos.java
index 0c07c9ab9db..d71b9407bbc 100644
--- a/test/jdk/java/nio/file/attribute/BasicFileAttributeView/SetTimesNanos.java
+++ b/test/jdk/java/nio/file/attribute/BasicFileAttributeView/SetTimesNanos.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -22,10 +22,13 @@
*/
/* @test
- * @bug 8181493 8231174
+ * @bug 8181493 8231174 8343417
* @summary Verify that nanosecond precision is maintained for file timestamps
* @requires (os.family == "linux") | (os.family == "mac") | (os.family == "windows")
+ * @library ../.. /test/lib
+ * @build jdk.test.lib.Platform
* @modules java.base/sun.nio.fs:+open
+ * @run main SetTimesNanos
*/
import java.io.IOException;
@@ -36,15 +39,19 @@
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.BasicFileAttributeView;
import java.nio.file.attribute.FileTime;
+import java.util.List;
import java.util.Set;
-import java.util.concurrent.TimeUnit;
+
+import static java.nio.file.LinkOption.*;
+import static java.util.concurrent.TimeUnit.*;
+
+import jdk.test.lib.Platform;
+import jtreg.SkippedException;
public class SetTimesNanos {
- private static final boolean IS_WINDOWS =
- System.getProperty("os.name").startsWith("Windows");
public static void main(String[] args) throws Exception {
- if (!IS_WINDOWS) {
+ if (!Platform.isWindows()) {
// Check whether futimens() system call is supported
Class unixNativeDispatcherClass =
Class.forName("sun.nio.fs.UnixNativeDispatcher");
@@ -52,8 +59,7 @@ public static void main(String[] args) throws Exception {
unixNativeDispatcherClass.getDeclaredMethod("futimensSupported");
futimensSupported.setAccessible(true);
if (!(boolean)futimensSupported.invoke(null)) {
- System.err.println("futimens() not supported; skipping test");
- return;
+ throw new SkippedException("futimens() not supported");
}
}
@@ -63,30 +69,34 @@ public static void main(String[] args) throws Exception {
System.out.format("FileStore: \"%s\" on %s (%s)%n",
dir, store.name(), store.type());
- Set testedTypes = IS_WINDOWS ?
+ Set testedTypes = Platform.isWindows() ?
Set.of("NTFS") : Set.of("apfs", "ext4", "xfs", "zfs");
if (!testedTypes.contains(store.type())) {
- System.err.format("%s not in %s; skipping test", store.type(), testedTypes);
- return;
+ throw new SkippedException(store.type() + " not in " + testedTypes);
}
testNanos(dir);
Path file = Files.createFile(dir.resolve("test.dat"));
testNanos(file);
+
+ if (Platform.isLinux()) {
+ testNanosLink(false);
+ testNanosLink(true);
+ }
}
private static void testNanos(Path path) throws IOException {
// Set modification and access times
// Time stamp = "2017-01-01 01:01:01.123456789";
long timeNanos = 1_483_261_261L*1_000_000_000L + 123_456_789L;
- FileTime pathTime = FileTime.from(timeNanos, TimeUnit.NANOSECONDS);
+ FileTime pathTime = FileTime.from(timeNanos, NANOSECONDS);
BasicFileAttributeView view =
Files.getFileAttributeView(path, BasicFileAttributeView.class);
view.setTimes(pathTime, pathTime, null);
// Windows file time resolution is 100ns so truncate
- if (IS_WINDOWS) {
+ if (Platform.isWindows()) {
timeNanos = 100L*(timeNanos/100L);
}
@@ -99,7 +109,7 @@ private static void testNanos(Path path) throws IOException {
FileTime[] times = new FileTime[] {attrs.lastModifiedTime(),
attrs.lastAccessTime()};
for (int i = 0; i < timeNames.length; i++) {
- long nanos = times[i].to(TimeUnit.NANOSECONDS);
+ long nanos = times[i].to(NANOSECONDS);
if (nanos != timeNanos) {
throw new RuntimeException("Expected " + timeNames[i] +
" timestamp to be '" + timeNanos + "', but was '" +
@@ -107,4 +117,42 @@ private static void testNanos(Path path) throws IOException {
}
}
}
+
+ private static void testNanosLink(boolean absolute) throws IOException {
+ System.out.println("absolute: " + absolute);
+
+ var target = Path.of("target");
+ var symlink = Path.of("symlink");
+ if (absolute)
+ symlink = symlink.toAbsolutePath();
+
+ try {
+ Files.createFile(target);
+ Files.createSymbolicLink(symlink, target);
+
+ var newTime = FileTime.from(1730417633157646106L, NANOSECONDS);
+ System.out.println("newTime: " + newTime.to(NANOSECONDS));
+
+ for (Path p : List.of(target, symlink)) {
+ System.out.println("p: " + p);
+
+ var view = Files.getFileAttributeView(p,
+ BasicFileAttributeView.class, NOFOLLOW_LINKS);
+ view.setTimes(newTime, newTime, null);
+ var attrs = view.readAttributes();
+
+ if (!attrs.lastAccessTime().equals(newTime))
+ throw new RuntimeException("Last access time "
+ + attrs.lastAccessTime()
+ + " != " + newTime);
+ if (!attrs.lastAccessTime().equals(newTime))
+ throw new RuntimeException("Last modified time "
+ + attrs.lastModifiedTime()
+ + " != " + newTime);
+ }
+ } finally {
+ Files.deleteIfExists(target);
+ Files.deleteIfExists(symlink);
+ }
+ }
}
diff --git a/test/jdk/java/util/concurrent/StructuredTaskScope/WithScopedValue.java b/test/jdk/java/util/concurrent/StructuredTaskScope/WithScopedValue.java
index 1d6e5e06af3..e119756d916 100644
--- a/test/jdk/java/util/concurrent/StructuredTaskScope/WithScopedValue.java
+++ b/test/jdk/java/util/concurrent/StructuredTaskScope/WithScopedValue.java
@@ -54,7 +54,7 @@ private static Stream factories() {
@MethodSource("factories")
void testForkInheritsScopedValue1(ThreadFactory factory) throws Exception {
ScopedValue name = ScopedValue.newInstance();
- String value = ScopedValue.callWhere(name, "x", () -> {
+ String value = ScopedValue.where(name, "x").call(() -> {
try (var scope = new StructuredTaskScope(null, factory)) {
Subtask subtask = scope.fork(() -> {
return name.get(); // child should read "x"
@@ -73,7 +73,7 @@ void testForkInheritsScopedValue1(ThreadFactory factory) throws Exception {
@MethodSource("factories")
void testForkInheritsScopedValue2(ThreadFactory factory) throws Exception {
ScopedValue name = ScopedValue.newInstance();
- String value = ScopedValue.callWhere(name, "x", () -> {
+ String value = ScopedValue.where(name, "x").call(() -> {
try (var scope1 = new StructuredTaskScope(null, factory)) {
Subtask subtask1 = scope1.fork(() -> {
try (var scope2 = new StructuredTaskScope(null, factory)) {
@@ -98,13 +98,13 @@ void testForkInheritsScopedValue2(ThreadFactory factory) throws Exception {
@MethodSource("factories")
void testForkInheritsScopedValue3(ThreadFactory factory) throws Exception {
ScopedValue name = ScopedValue.newInstance();
- String value = ScopedValue.callWhere(name, "x", () -> {
+ String value = ScopedValue.where(name, "x").call(() -> {
try (var scope1 = new StructuredTaskScope(null, factory)) {
Subtask subtask1 = scope1.fork(() -> {
assertEquals(name.get(), "x"); // child should read "x"
// rebind name to "y"
- String grandchildValue = ScopedValue.callWhere(name, "y", () -> {
+ String grandchildValue = ScopedValue.where(name, "y").call(() -> {
try (var scope2 = new StructuredTaskScope(null, factory)) {
Subtask subtask2 = scope2.fork(() -> {
return name.get(); // grandchild should read "y"
@@ -136,7 +136,7 @@ class Box {
var box = new Box();
try {
try {
- ScopedValue.runWhere(name, "x", () -> {
+ ScopedValue.where(name, "x").run(() -> {
box.scope = new StructuredTaskScope();
});
fail();
@@ -167,7 +167,7 @@ class Box {
void testStructureViolation2() throws Exception {
ScopedValue name = ScopedValue.newInstance();
try (var scope = new StructuredTaskScope()) {
- ScopedValue.runWhere(name, "x", () -> {
+ ScopedValue.where(name, "x").run(() -> {
assertThrows(StructureViolationException.class, scope::close);
});
}
@@ -180,7 +180,7 @@ void testStructureViolation2() throws Exception {
void testStructureViolation3() throws Exception {
ScopedValue name = ScopedValue.newInstance();
try (var scope = new StructuredTaskScope()) {
- ScopedValue.runWhere(name, "x", () -> {
+ ScopedValue.where(name, "x").run(() -> {
assertThrows(StructureViolationException.class,
() -> scope.fork(() -> "foo"));
});
@@ -196,9 +196,9 @@ void testStructureViolation4() throws Exception {
ScopedValue name2 = ScopedValue.newInstance();
// rebind
- ScopedValue.runWhere(name1, "x", () -> {
+ ScopedValue.where(name1, "x").run(() -> {
try (var scope = new StructuredTaskScope()) {
- ScopedValue.runWhere(name1, "y", () -> {
+ ScopedValue.where(name1, "y").run(() -> {
assertThrows(StructureViolationException.class,
() -> scope.fork(() -> "foo"));
});
@@ -206,9 +206,9 @@ void testStructureViolation4() throws Exception {
});
// new binding
- ScopedValue.runWhere(name1, "x", () -> {
+ ScopedValue.where(name1, "x").run(() -> {
try (var scope = new StructuredTaskScope()) {
- ScopedValue.runWhere(name2, "y", () -> {
+ ScopedValue.where(name2, "y").run(() -> {
assertThrows(StructureViolationException.class,
() -> scope.fork(() -> "foo"));
});
diff --git a/test/jdk/java/util/concurrent/tck/JSR166TestCase.java b/test/jdk/java/util/concurrent/tck/JSR166TestCase.java
index 19897fa0785..784b160b134 100644
--- a/test/jdk/java/util/concurrent/tck/JSR166TestCase.java
+++ b/test/jdk/java/util/concurrent/tck/JSR166TestCase.java
@@ -39,7 +39,7 @@
* @summary Conformance testing variant of JSR-166 tck tests.
* @build *
* @modules java.management java.base/jdk.internal.util
- * @run junit/othervm/timeout=1000 JSR166TestCase
+ * @run junit/othervm/timeout=1000 -Xdump:system+java+snap:events=systhrow,filter=java/lang/Exception,msg_filter=*JUnit* JSR166TestCase
*/
/*
@@ -48,7 +48,7 @@
* with java security manager set to allow.
* @build *
* @modules java.management java.base/jdk.internal.util
- * @run junit/othervm/timeout=1000 -Djava.security.manager=allow JSR166TestCase
+ * @run junit/othervm/timeout=1000 -Xdump:system+java+snap:events=systhrow,filter=java/lang/Exception,msg_filter=*JUnit* -Djava.security.manager=allow JSR166TestCase
*/
/*
@@ -62,6 +62,7 @@
* --add-opens java.base/java.lang=ALL-UNNAMED
* -Djsr166.testImplementationDetails=true
* -Djava.util.concurrent.ForkJoinPool.common.parallelism=0
+ * -Xdump:system+java+snap:events=systhrow,filter=java/lang/Exception,msg_filter=*JUnit*
* JSR166TestCase
* @run junit/othervm/timeout=1000
* --add-opens java.base/java.util.concurrent=ALL-UNNAMED
@@ -69,6 +70,7 @@
* -Djsr166.testImplementationDetails=true
* -Djava.util.concurrent.ForkJoinPool.common.parallelism=1
* -Djava.util.secureRandomSeed=true
+ * -Xdump:system+java+snap:events=systhrow,filter=java/lang/Exception,msg_filter=*JUnit*
* JSR166TestCase
*/
@@ -83,11 +85,13 @@
* --add-opens java.base/java.util.concurrent=ALL-UNNAMED
* --add-opens java.base/java.lang=ALL-UNNAMED
* -Djsr166.testImplementationDetails=true
+ * -Xdump:system+java+snap:events=systhrow,filter=java/lang/Exception,msg_filter=*JUnit*
* JSR166TestCase
* @run junit/othervm/timeout=1000/policy=tck.policy
* --add-opens java.base/java.util.concurrent=ALL-UNNAMED
* --add-opens java.base/java.lang=ALL-UNNAMED
* -Djsr166.testImplementationDetails=true
+ * -Xdump:system+java+snap:events=systhrow,filter=java/lang/Exception,msg_filter=*JUnit*
* JSR166TestCase
*/
diff --git a/test/jdk/javax/crypto/KDF/KDFDelayedProviderSyncTest.java b/test/jdk/javax/crypto/KDF/KDFDelayedProviderSyncTest.java
new file mode 100644
index 00000000000..f4ddd726d0c
--- /dev/null
+++ b/test/jdk/javax/crypto/KDF/KDFDelayedProviderSyncTest.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8331008
+ * @library /test/lib
+ * @run testng KDFDelayedProviderSyncTest
+ * @summary multi-threading test for KDF
+ * @enablePreview
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.crypto.KDF;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.HKDFParameterSpec;
+import java.math.BigInteger;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.NoSuchAlgorithmException;
+import java.security.spec.AlgorithmParameterSpec;
+import java.util.HexFormat;
+
+public class KDFDelayedProviderSyncTest {
+ KDF kdfUnderTest;
+ byte[] ikm = new BigInteger("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
+ 16).toByteArray();
+ byte[] salt = new BigInteger("000102030405060708090a0b0c",
+ 16).toByteArray();
+ byte[] info = new BigInteger("f0f1f2f3f4f5f6f7f8f9", 16).toByteArray();
+ AlgorithmParameterSpec derivationSpec =
+ HKDFParameterSpec.ofExtract().addIKM(ikm).addSalt(salt).thenExpand(
+ info, 42);
+ String expectedResult =
+ "666b33562ebc5e2f041774192e0534efca06f82a5fca17ec8c6ae1b9f5466adba1d77d06480567ddd2d1";
+
+ @BeforeClass
+ public void setUp() throws NoSuchAlgorithmException {
+ kdfUnderTest = KDF.getInstance("HKDF-SHA256");
+ }
+
+ @Test(threadPoolSize = 50, invocationCount = 100)
+ public void testDerive()
+ throws InvalidAlgorithmParameterException, NoSuchAlgorithmException {
+ SecretKey result = kdfUnderTest.deriveKey("Generic", derivationSpec);
+ assert (HexFormat.of().formatHex(result.getEncoded()).equals(
+ expectedResult));
+
+ byte[] resultData = kdfUnderTest.deriveData(derivationSpec);
+ assert (HexFormat.of().formatHex(resultData).equals(expectedResult));
+ }
+}
diff --git a/test/jdk/javax/crypto/KDF/KDFDelayedProviderTest.java b/test/jdk/javax/crypto/KDF/KDFDelayedProviderTest.java
new file mode 100644
index 00000000000..edebae217f2
--- /dev/null
+++ b/test/jdk/javax/crypto/KDF/KDFDelayedProviderTest.java
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8331008
+ * @library /test/lib /test/jdk/security/unsignedjce
+ * @build java.base/javax.crypto.ProviderVerifier
+ * @run main/othervm KDFDelayedProviderTest
+ * @summary delayed provider selection
+ * @enablePreview
+ */
+
+import jdk.test.lib.Asserts;
+
+import javax.crypto.KDF;
+import javax.crypto.KDFSpi;
+import javax.crypto.SecretKey;
+import java.security.InvalidAlgorithmParameterException;
+import javax.crypto.KDFParameters;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.security.Security;
+import java.security.spec.AlgorithmParameterSpec;
+import java.util.Objects;
+
+public class KDFDelayedProviderTest {
+ public static void main(String[] args) throws Exception {
+ Security.addProvider(new Provider1());
+ Security.addProvider(new Provider2());
+ Security.addProvider(new Provider3());
+ KDF kdf;
+
+ kdf = KDF.getInstance("X", new KDFParameters() {});
+ kdf.deriveData(new AlgorithmParameterSpec() {});
+ Asserts.assertEquals(kdf.getProviderName(), "P1");
+
+ kdf = KDF.getInstance("X");
+ kdf.deriveData(new MyDerivationSpec() {});
+ Asserts.assertEquals(kdf.getProviderName(), "P2");
+
+ kdf = KDF.getInstance("X");
+ kdf.deriveData(new AlgorithmParameterSpec() {});
+ Asserts.assertEquals(kdf.getProviderName(), "P3");
+
+ boolean thrown = true;
+ try {
+ kdf = KDF.getInstance("Y");
+ thrown = false;
+ } catch(Exception nsae) {
+ // Expected exception
+ Asserts.assertTrue(nsae instanceof NoSuchAlgorithmException);
+ System.out.println("Expected NoSuchAlgorithmException");
+ }
+ Asserts.assertTrue(thrown);
+
+ thrown = true;
+ try {
+ kdf = KDF.getInstance("HKDF-SHA256", new MyKDFParameters());
+ thrown = false;
+ } catch (Exception iape) {
+ // Expected exception
+ Asserts.assertTrue(iape instanceof InvalidAlgorithmParameterException);
+ System.out.println("Expected InvalidAlgorithmParameterException");
+ }
+ Asserts.assertTrue(thrown);
+
+ thrown = true;
+ try {
+ kdf = KDF.getInstance("HKDF-SHA256");
+ kdf.deriveData(new MyDerivationSpec());
+ thrown = false;
+ } catch (Exception iape) {
+ // Expected exception
+ Asserts.assertTrue(iape instanceof InvalidAlgorithmParameterException);
+ System.out.println("Expected InvalidAlgorithmParameterException");
+ }
+ Asserts.assertTrue(thrown);
+ }
+
+ public static class Provider1 extends Provider {
+ public Provider1() {
+ super("P1", "1", "1");
+ put("KDF.X", KDF1.class.getName());
+ }
+ }
+
+ // KDF1 requires a params at getInstance()
+ public static class KDF1 extends KDF0 {
+ public KDF1(KDFParameters e) throws InvalidAlgorithmParameterException {
+ super(Objects.requireNonNull(e));
+ }
+ }
+
+ public static class Provider2 extends Provider {
+ public Provider2() {
+ super("P2", "1", "1");
+ put("KDF.X", KDF2.class.getName());
+ }
+ }
+
+ // KDF2 requires input to be a specific type
+ public static class KDF2 extends KDF0 {
+ public KDF2(KDFParameters e)
+ throws InvalidAlgorithmParameterException {
+ super(null);
+ }
+
+ @Override
+ protected byte[] engineDeriveData(
+ AlgorithmParameterSpec derivationSpec)
+ throws InvalidAlgorithmParameterException {
+ if (derivationSpec instanceof MyDerivationSpec) {
+ return null;
+ } else {
+ throw new InvalidAlgorithmParameterException();
+ }
+ }
+ }
+
+ public static class Provider3 extends Provider {
+ public Provider3() {
+ super("P3", "1", "1");
+ put("KDF.X", KDF3.class.getName());
+ }
+ }
+
+ // KDF3 doesn't care about anything
+ public static class KDF3 extends KDF0 {
+ public KDF3(KDFParameters e) throws InvalidAlgorithmParameterException {
+ super(null);
+ }
+ }
+
+ public abstract static class KDF0 extends KDFSpi {
+ public KDF0(KDFParameters a) throws InvalidAlgorithmParameterException {
+ super(a);
+ }
+
+ protected SecretKey engineDeriveKey(String alg,
+ AlgorithmParameterSpec derivationSpec)
+ throws InvalidAlgorithmParameterException {
+ return null;
+ }
+
+ protected byte[] engineDeriveData(
+ AlgorithmParameterSpec derivationSpec)
+ throws InvalidAlgorithmParameterException {
+ return new byte[0];
+ }
+
+ protected KDFParameters engineGetParameters(){
+ return null;
+ }
+ }
+
+ static class MyDerivationSpec implements AlgorithmParameterSpec {}
+
+ static class MyKDFParameters implements KDFParameters {}
+}
diff --git a/test/jdk/javax/crypto/KDF/KDFDelayedProviderThreadingTest.java b/test/jdk/javax/crypto/KDF/KDFDelayedProviderThreadingTest.java
new file mode 100644
index 00000000000..7b91badef95
--- /dev/null
+++ b/test/jdk/javax/crypto/KDF/KDFDelayedProviderThreadingTest.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8331008
+ * @library /test/lib /test/jdk/security/unsignedjce
+ * @build java.base/javax.crypto.ProviderVerifier
+ * @run main/othervm KDFDelayedProviderThreadingTest
+ * @summary delayed provider selection threading test
+ * @enablePreview
+ */
+
+import jdk.test.lib.Asserts;
+
+import javax.crypto.KDF;
+import javax.crypto.KDFParameters;
+import javax.crypto.KDFSpi;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.HKDFParameterSpec;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.Provider;
+import java.security.Security;
+import java.security.spec.AlgorithmParameterSpec;
+import java.util.Arrays;
+
+public class KDFDelayedProviderThreadingTest {
+ /// This number of iterations is enough to see a case where the threads
+ /// arrange themselves such that both `deriveData` attempts cause "ERROR",
+ /// which is still a passing case.
+ static final int ITERATIONS = 10000;
+ static int threadOrderReversalCounter = 0;
+ static final String ERROR = "ERROR";
+ static volatile String out;
+ static final HKDFParameterSpec input
+ = HKDFParameterSpec.ofExtract().extractOnly();
+
+ static String derive(KDF kdf) {
+ try {
+ return Arrays.toString(kdf.deriveData(input));
+ } catch (Exception e) {
+ return ERROR;
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ Security.insertProviderAt(new P(), 1);
+ for (int i = 0; i < ITERATIONS; i++) {
+ test();
+ }
+
+ // If the value of threadOrderReversalCounter is consistently zero,
+ // then this test may need to be adjusted for newer hardware to ensure
+ // a thorough test. This didn't seem fitting for a check, such as
+ // `Asserts.assertTrue(threadOrderReversalCounter > 0);`, since we
+ // may not want to start failing the test right away when running on
+ // better hardware someday.
+ System.out.println("Also tested atypical threading condition "
+ + threadOrderReversalCounter + "/" + ITERATIONS
+ + " iterations (depends on hardware specs/utilization).");
+ }
+
+ static void test() throws Exception {
+ var k = KDF.getInstance("HKDF-SHA256");
+ var t1 = new Thread(() -> out = derive(k));
+ var t2 = new Thread(() -> k.getProviderName());
+ t1.start();
+ t2.start();
+ t1.join();
+ t2.join();
+
+ String out2 = derive(k);
+ Asserts.assertEquals(out, out2);
+ if (out.length() < 10) { // "error"
+ threadOrderReversalCounter++;
+ }
+ }
+
+ public static class P extends Provider {
+ public P() {
+ super("ME", "1", "ME");
+ put("KDF.HKDF-SHA256", K.class.getName());
+ }
+ }
+
+ public static class K extends KDFSpi {
+
+ public K(KDFParameters p) throws InvalidAlgorithmParameterException {
+ super(p);
+ }
+
+ @Override
+ protected KDFParameters engineGetParameters() {
+ return null;
+ }
+
+ @Override
+ protected SecretKey engineDeriveKey(String alg,
+ AlgorithmParameterSpec derivationSpec)
+ throws InvalidAlgorithmParameterException {
+ throw new InvalidAlgorithmParameterException();
+ }
+
+ @Override
+ protected byte[] engineDeriveData(AlgorithmParameterSpec derivationSpec)
+ throws InvalidAlgorithmParameterException {
+ throw new InvalidAlgorithmParameterException();
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/jdk/javax/management/remote/mandatory/connection/DeadLockTest.java b/test/jdk/javax/management/remote/mandatory/connection/DeadLockTest.java
index 0526f86b4a1..677341aacb1 100644
--- a/test/jdk/javax/management/remote/mandatory/connection/DeadLockTest.java
+++ b/test/jdk/javax/management/remote/mandatory/connection/DeadLockTest.java
@@ -27,6 +27,10 @@
* @summary test on a client notification deadlock.
* @author Shanliang JIANG
*
+ * @requires vm.compMode != "Xcomp"
+ * @comment Running with -Xcomp is likely to cause a timeout while establishing the connection
+ * (RMI: java.rmi.NoSuchObjectException: no such object in table).
+ *
* @run clean DeadLockTest
* @run build DeadLockTest
* @run main DeadLockTest
@@ -139,7 +143,7 @@ public void handleNotification(Notification n, Object h) {
try {
conn.getDefaultDomain();
} catch (IOException ioe) {
- // Greate !
+ // OK
}
synchronized(this) {
diff --git a/test/jdk/javax/print/StreamPrintingOrientation.java b/test/jdk/javax/print/StreamPrintingOrientation.java
index d7736aa4f62..77dd8f4cae0 100644
--- a/test/jdk/javax/print/StreamPrintingOrientation.java
+++ b/test/jdk/javax/print/StreamPrintingOrientation.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -24,95 +24,109 @@
/*
* @test
* @bug 4904236
- * @summary You would see a cross-platform print dialog being popped up. Check whether orientation is shown as LANDSCAPE. Click 'OK'. 'streamexample.ps' will be created in the same dir where this application was executed. Pass if the orientation in the ps file is landscape.
- * @run main/manual StreamPrintingOrientation
+ * @key printer
+ * @summary StreamPrintService ignores the PrintReqAttrSet when printing through 2D Printing
+ * @run main StreamPrintingOrientation
*/
-import java.awt.*;
-import java.awt.print.*;
-import javax.print.*;
-import javax.print.attribute.standard.*;
-import javax.print.attribute.*;
-import java.io.FileOutputStream;
import java.io.File;
-import java.util.Locale;
+import java.io.FileOutputStream;
+import java.nio.file.Files;
+
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.print.PageFormat;
+import java.awt.print.Printable;
+import java.awt.print.PrinterException;
+import java.awt.print.PrinterJob;
+import javax.print.attribute.Attribute;
+import javax.print.PrintService;
+import javax.print.StreamPrintServiceFactory;
+import javax.print.attribute.standard.Copies;
+import javax.print.attribute.standard.JobName;
+import javax.print.attribute.standard.OrientationRequested;
+import javax.print.attribute.HashPrintRequestAttributeSet;
+
+public class StreamPrintingOrientation implements Printable {
+
+ public static void main(String[] args) throws Exception {
+ StreamPrintingOrientation pd = new StreamPrintingOrientation();
+ PrinterJob pj = PrinterJob.getPrinterJob();
+ HashPrintRequestAttributeSet prSet = new HashPrintRequestAttributeSet();
+ PrintService service = null;
+
+ FileOutputStream fos = null;
+ String mType = "application/postscript";
-class StreamPrintingOrientation implements Printable {
- /**
- * Constructor
- */
- public StreamPrintingOrientation() {
- super();
+ File fl = new File("stream_landscape.ps");
+ fl.deleteOnExit();
+ fos = new FileOutputStream(fl);
+ StreamPrintServiceFactory[] factories = PrinterJob.lookupStreamPrintServices(mType);
+ if (factories.length > 0) {
+ service = factories[0].getPrintService(fos);
}
- /**
- * Starts the application.
- */
- public static void main(java.lang.String[] args) {
- StreamPrintingOrientation pd = new StreamPrintingOrientation();
- PrinterJob pj = PrinterJob.getPrinterJob();
- HashPrintRequestAttributeSet prSet = new HashPrintRequestAttributeSet();
- PrintService service = null;
- FileOutputStream fos = null;
- File f = null, f1 = null;
- String mType = "application/postscript";
+ if (service != null) {
+ System.out.println("Stream Print Service " + service);
+ pj.setPrintService(service);
+ } else {
+ throw new RuntimeException("No stream Print Service available.");
+ }
+
+ pj.setPrintable(pd);
+ prSet.add(OrientationRequested.LANDSCAPE);
+ prSet.add(new Copies(1));
+ prSet.add(new JobName("orientation test", null));
+ System.out.println("open PrintDialog..");
- try {
- f = new File("streamexample.ps");
- fos = new FileOutputStream(f);
- StreamPrintServiceFactory[] factories = PrinterJob.lookupStreamPrintServices(mType);
- if (factories.length > 0)
- service = factories[0].getPrintService(fos);
+ System.out.println("\nValues in attr set passed to print method");
+ Attribute attr[] = prSet.toArray();
+ for (int x = 0; x < attr.length; x++) {
+ System.out.println("Name " + attr[x].getName() + " " + attr[x]);
+ }
+ System.out.println("About to print the data ...");
+ if (service != null) {
+ System.out.println("TEST: calling Print");
+ pj.print(prSet);
+ System.out.println("TEST: Printed");
+ }
- if (service != null) {
- System.out.println("Stream Print Service "+service);
- pj.setPrintService(service);
- } else {
- throw new RuntimeException("No stream Print Service available.");
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
+ File fp = new File("stream_portrait.ps");
+ fp.deleteOnExit();
+ fos = new FileOutputStream(fp);
+ if (factories.length > 0) {
+ service = factories[0].getPrintService(fos);
+ }
- pj.setPrintable(pd);
- prSet.add(OrientationRequested.LANDSCAPE);
- prSet.add(new Copies(3));
- prSet.add(new JobName("orientation test", null));
- System.out.println("open PrintDialog..");
- if (pj.printDialog(prSet)) {
- try {
- System.out.println("\nValues in attr set passed to print method");
- Attribute attr[] = prSet.toArray();
- for (int x = 0; x < attr.length; x ++) {
- System.out.println("Name "+attr[x].getName()+" "+attr[x]);
- }
- System.out.println("About to print the data ...");
- if (service != null) {
- System.out.println("TEST: calling Print");
- pj.print(prSet);
- System.out.println("TEST: Printed");
- }
- }
- catch (PrinterException pe) {
- pe.printStackTrace();
- }
- }
+ pj.setPrintService(service);
+ pj.setPrintable(pd);
+ prSet.add(OrientationRequested.PORTRAIT);
+ prSet.add(new Copies(1));
+ prSet.add(new JobName("orientation test", null));
+ if (service != null) {
+ pj.print(prSet);
+ }
+ if (Files.mismatch(fl.toPath(), fp.toPath()) == -1) {
+ throw new RuntimeException("Printing stream orientation is same " +
+ "for both PORTRAIT and LANDSCAPE");
}
+ }
- //printable interface
- public int print(Graphics g, PageFormat pf, int pi) throws PrinterException {
+ //printable interface
+ public int print(Graphics g, PageFormat pf, int pi) throws PrinterException {
- if (pi > 0) {
- return Printable.NO_SUCH_PAGE;
- }
- // Simply draw two rectangles
- Graphics2D g2 = (Graphics2D)g;
- g2.setColor(Color.black);
- g2.translate(pf.getImageableX(), pf.getImageableY());
- System.out.println("StreamPrinting Test Width "+pf.getWidth()+" Height "+pf.getHeight());
- g2.drawRect(1,1,200,300);
- g2.drawRect(1,1,25,25);
- return Printable.PAGE_EXISTS;
+ if (pi > 0) {
+ return Printable.NO_SUCH_PAGE;
}
+ // Simply draw two rectangles
+ Graphics2D g2 = (Graphics2D) g;
+ g2.setColor(Color.black);
+ g2.translate(pf.getImageableX(), pf.getImageableY());
+ System.out.println("StreamPrinting Test Width " + pf.getWidth() + " Height " + pf.getHeight());
+ g2.drawRect(1, 1, 200, 300);
+ g2.drawRect(1, 1, 25, 25);
+ return Printable.PAGE_EXISTS;
+ }
}
diff --git a/test/jdk/jdk/internal/misc/ThreadFlock/WithScopedValue.java b/test/jdk/jdk/internal/misc/ThreadFlock/WithScopedValue.java
index f2bfd241722..19b829bc7e8 100644
--- a/test/jdk/jdk/internal/misc/ThreadFlock/WithScopedValue.java
+++ b/test/jdk/jdk/internal/misc/ThreadFlock/WithScopedValue.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 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
@@ -53,7 +53,7 @@ private static Stream factories() {
@MethodSource("factories")
void testInheritsScopedValue(ThreadFactory factory) throws Exception {
ScopedValue name = ScopedValue.newInstance();
- String value = ScopedValue.callWhere(name, "duke", () -> {
+ String value = ScopedValue.where(name, "duke").call(() -> {
var result = new AtomicReference();
try (var flock = ThreadFlock.open(null)) {
Thread thread = factory.newThread(() -> {
@@ -79,7 +79,7 @@ class Box {
}
var box = new Box();
try {
- ScopedValue.runWhere(name, "x1", () -> {
+ ScopedValue.where(name, "x1").run(() -> {
box.flock1 = ThreadFlock.open(null);
box.flock2 = ThreadFlock.open(null);
});
@@ -97,11 +97,11 @@ class Box {
void testStructureViolation2() {
ScopedValue name = ScopedValue.newInstance();
try (var flock1 = ThreadFlock.open("flock1")) {
- ScopedValue.runWhere(name, "x1", () -> {
+ ScopedValue.where(name, "x1").run(() -> {
try (var flock2 = ThreadFlock.open("flock2")) {
- ScopedValue.runWhere(name, "x2", () -> {
+ ScopedValue.where(name, "x2").run(() -> {
try (var flock3 = ThreadFlock.open("flock3")) {
- ScopedValue.runWhere(name, "x3", () -> {
+ ScopedValue.where(name, "x3").run(() -> {
var flock4 = ThreadFlock.open("flock4");
try {
@@ -129,11 +129,11 @@ void testStructureViolation2() {
void testStructureViolation3() {
ScopedValue name = ScopedValue.newInstance();
try (var flock1 = ThreadFlock.open("flock1")) {
- ScopedValue.runWhere(name, "x1", () -> {
+ ScopedValue.where(name, "x1").run(() -> {
try (var flock2 = ThreadFlock.open("flock2")) {
- ScopedValue.runWhere(name, "x2", () -> {
+ ScopedValue.where(name, "x2").run(() -> {
try (var flock3 = ThreadFlock.open("flock3")) {
- ScopedValue.runWhere(name, "x3", () -> {
+ ScopedValue.where(name, "x3").run(() -> {
var flock4 = ThreadFlock.open("flock4");
try {
@@ -161,11 +161,11 @@ void testStructureViolation3() {
void testStructureViolation4() {
ScopedValue name = ScopedValue.newInstance();
try (var flock1 = ThreadFlock.open("flock1")) {
- ScopedValue.runWhere(name, "x1", () -> {
+ ScopedValue.where(name, "x1").run(() -> {
try (var flock2 = ThreadFlock.open("flock2")) {
- ScopedValue.runWhere(name, "x2", () -> {
+ ScopedValue.where(name, "x2").run(() -> {
try (var flock3 = ThreadFlock.open("flock3")) {
- ScopedValue.runWhere(name, "x3", () -> {
+ ScopedValue.where(name, "x3").run(() -> {
var flock4 = ThreadFlock.open("flock4");
try {
@@ -193,7 +193,7 @@ void testStructureViolation4() {
void testStructureViolation5(ThreadFactory factory) throws Exception {
ScopedValue name = ScopedValue.newInstance();
try (var flock = ThreadFlock.open(null)) {
- ScopedValue.runWhere(name, "duke", () -> {
+ ScopedValue.where(name, "duke").run(() -> {
Thread thread = factory.newThread(() -> { });
assertThrows(StructureViolationException.class, () -> flock.start(thread));
});
@@ -207,9 +207,9 @@ void testStructureViolation5(ThreadFactory factory) throws Exception {
@MethodSource("factories")
void testStructureViolation6(ThreadFactory factory) throws Exception {
ScopedValue name = ScopedValue.newInstance();
- ScopedValue.runWhere(name, "duke", () -> {
+ ScopedValue.where(name, "duke").run(() -> {
try (var flock = ThreadFlock.open(null)) {
- ScopedValue.runWhere(name, "duchess", () -> {
+ ScopedValue.where(name, "duchess").run(() -> {
Thread thread = factory.newThread(() -> { });
assertThrows(StructureViolationException.class, () -> flock.start(thread));
});
diff --git a/test/jdk/security/unsignedjce/java.base/javax/crypto/ProviderVerifier.java b/test/jdk/security/unsignedjce/java.base/javax/crypto/ProviderVerifier.java
new file mode 100644
index 00000000000..03e3e9904cc
--- /dev/null
+++ b/test/jdk/security/unsignedjce/java.base/javax/crypto/ProviderVerifier.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2007, 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. 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 javax.crypto;
+
+import java.io.IOException;
+import java.net.URL;
+import java.security.Provider;
+
+/**
+ * This class is included here to enable testing of Delayed Provider Selection
+ * by certain KDF tests. It only stubs out the necessary methods.
+ *
+ * @since 24
+ */
+final class ProviderVerifier {
+
+ private final CryptoPermissions appPerms = null;
+
+ /**
+ * Creates a {@code ProviderVerifier} object to verify the given URL.
+ *
+ * @param jarURL the JAR file to be verified.
+ * @param savePerms if {@code true}, save the permissions allowed by the
+ * exemption mechanism
+ */
+ ProviderVerifier(URL jarURL, boolean savePerms) {
+ this(jarURL, null, savePerms);
+ }
+
+ /**
+ * Creates a {@code ProviderVerifier} object to verify the given URL.
+ *
+ * @param jarURL the JAR file to be verified
+ * @param provider the corresponding provider.
+ * @param savePerms if {@code true}, save the permissions allowed by the
+ * exemption mechanism
+ */
+ ProviderVerifier(URL jarURL, Provider provider, boolean savePerms) {
+ // The URL for the JAR file we want to verify.
+ }
+
+ /**
+ * Only a stub is needed for the Delayed Provider Selection test.
+ */
+ void verify() throws IOException { return; }
+
+ /**
+ * Verify that the provided certs include the
+ * framework signing certificate.
+ *
+ * @param certs the list of certs to be checked.
+ * @throws Exception if the list of certs did not contain
+ * the framework signing certificate
+ */
+ static void verifyPolicySigned(java.security.cert.Certificate[] certs)
+ throws Exception {
+ }
+
+ /**
+ * Returns {@code true} if the given provider is JDK trusted crypto provider
+ * if the implementation supports fast-path verification.
+ */
+ static boolean isTrustedCryptoProvider(Provider provider) {
+ return false;
+ }
+
+ /**
+ * Returns the permissions which are bundled with the JAR file,
+ * aka the "cryptoperms" file.
+ *
+ * NOTE: if this {@code ProviderVerifier} instance is constructed
+ * with "savePerms" equal to {@code false}, then this method would always
+ * return {@code null}.
+ */
+ CryptoPermissions getPermissions() {
+ return appPerms;
+ }
+}
diff --git a/test/jdk/sun/security/pkcs11/PKCS11Test.java b/test/jdk/sun/security/pkcs11/PKCS11Test.java
index 9cb29eb8507..63d486756e6 100644
--- a/test/jdk/sun/security/pkcs11/PKCS11Test.java
+++ b/test/jdk/sun/security/pkcs11/PKCS11Test.java
@@ -54,12 +54,14 @@
import java.util.ServiceConfigurationError;
import java.util.ServiceLoader;
import java.util.Set;
+import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import jdk.test.lib.Platform;
+import jdk.test.lib.Utils;
import jdk.test.lib.artifacts.Artifact;
import jdk.test.lib.artifacts.ArtifactResolver;
import jdk.test.lib.artifacts.ArtifactResolverException;
@@ -496,14 +498,13 @@ public static String getNssConfig() throws Exception {
return null;
}
- String base = getBase();
-
+ String nssConfigDir = copyNssFiles();
String libfile = libdir + System.mapLibraryName(nss_library);
String customDBdir = System.getProperty("CUSTOM_DB_DIR");
String dbdir = (customDBdir != null) ?
customDBdir :
- base + SEP + "nss" + SEP + "db";
+ nssConfigDir + SEP + "db";
// NSS always wants forward slashes for the config path
dbdir = dbdir.replace('\\', '/');
@@ -513,7 +514,7 @@ public static String getNssConfig() throws Exception {
System.setProperty("pkcs11test.nss.db", dbdir);
return (customConfig != null) ?
customConfig :
- base + SEP + "nss" + SEP + customConfigName;
+ nssConfigDir + SEP + customConfigName;
}
// Generate a vector of supported elliptic curves of a given provider
@@ -796,6 +797,31 @@ private static Path findNSSLibrary(Path path, Path libraryName) throws IOExcepti
}
}
+ //Copy the nss config files to the current directory for tests. Returns the destination path
+ private static String copyNssFiles() throws Exception {
+ String nss = "nss";
+ String db = "db";
+ Path nssDirSource = Path.of(getBase()).resolve(nss);
+ Path nssDirDestination = Path.of(".").resolve(nss);
+
+ // copy files from nss directory
+ copyFiles(nssDirSource, nssDirDestination);
+ // copy files from nss/db directory
+ copyFiles(nssDirSource.resolve(db), nssDirDestination.resolve(db));
+ return nssDirDestination.toString();
+ }
+
+ private static void copyFiles(Path dirSource, Path dirDestination) throws IOException {
+ List sourceFiles = Arrays
+ .stream(dirSource.toFile().listFiles())
+ .filter(File::isFile)
+ .map(File::toPath)
+ .collect(Collectors.toList());
+ List destFiles = Utils.copyFiles(sourceFiles, dirDestination,
+ StandardCopyOption.REPLACE_EXISTING);
+ destFiles.forEach((Path file) -> file.toFile().setWritable(true));
+ }
+
public abstract void main(Provider p) throws Exception;
protected boolean skipTest(Provider p) {
diff --git a/test/jdk/sun/security/pkcs11/Provider/MultipleLogins.sh b/test/jdk/sun/security/pkcs11/Provider/MultipleLogins.sh
index 56a4fd6b806..ada0ab7d59a 100644
--- a/test/jdk/sun/security/pkcs11/Provider/MultipleLogins.sh
+++ b/test/jdk/sun/security/pkcs11/Provider/MultipleLogins.sh
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2021, 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
@@ -27,6 +27,7 @@
# @library /test/lib/
# @build jdk.test.lib.util.ForceGC
# jdk.test.lib.Platform
+# jdk.test.lib.Utils
# @run shell MultipleLogins.sh
# set a few environment variables so that the shell-script can run stand-alone
diff --git a/test/jdk/tools/jlink/plugins/CDSPluginTest.java b/test/jdk/tools/jlink/plugins/CDSPluginTest.java
index d50b1c88a21..c9766183297 100644
--- a/test/jdk/tools/jlink/plugins/CDSPluginTest.java
+++ b/test/jdk/tools/jlink/plugins/CDSPluginTest.java
@@ -26,6 +26,7 @@
import jdk.test.lib.JDKToolFinder;
import jdk.test.lib.Platform;
import jdk.test.lib.process.*;
+import jdk.test.whitebox.WhiteBox;
import tests.Helper;
@@ -44,11 +45,12 @@
* jdk.jlink/jdk.tools.jimage
* jdk.compiler
* @build tests.*
- * @run main CDSPluginTest
+ * @build jdk.test.whitebox.WhiteBox
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. CDSPluginTest
*/
public class CDSPluginTest {
-
public static void main(String[] args) throws Throwable {
if (!Platform.isDefaultCDSArchiveSupported())
@@ -75,12 +77,19 @@ public static void main(String[] args) throws Throwable {
}
subDir += "server" + sep;
+ WhiteBox wb = WhiteBox.getWhiteBox();
+ boolean COMPACT_HEADERS = Platform.is64bit() &&
+ wb.getBooleanVMFlag("UseCompactObjectHeaders") &&
+ wb.isDefaultVMFlag("UseCompactObjectHeaders");
+
+ String suffix = COMPACT_HEADERS ? "_coh.jsa" : ".jsa";
+
if (Platform.isAArch64() || Platform.isX64()) {
helper.checkImage(image, module, null, null,
- new String[] { subDir + "classes.jsa", subDir + "classes_nocoops.jsa" });
+ new String[] { subDir + "classes" + suffix, subDir + "classes_nocoops" + suffix });
} else {
helper.checkImage(image, module, null, null,
- new String[] { subDir + "classes.jsa" });
+ new String[] { subDir + "classes" + suffix });
}
}
}
diff --git a/test/jdk/tools/jpackage/TEST.properties b/test/jdk/tools/jpackage/TEST.properties
index ab013166faa..e01036f0ed3 100644
--- a/test/jdk/tools/jpackage/TEST.properties
+++ b/test/jdk/tools/jpackage/TEST.properties
@@ -10,3 +10,6 @@ maxOutputSize=2000000
# }
# but conditionals are not supported by jtreg configuration files.
exclusiveAccess.dirs=share windows
+
+modules=jdk.jpackage/jdk.jpackage.internal:+open \
+ java.base/jdk.internal.util
diff --git a/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/DirectoryContentVerifierTest.java b/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/DirectoryContentVerifierTest.java
deleted file mode 100644
index cf910445abf..00000000000
--- a/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/DirectoryContentVerifierTest.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.jpackage.test;
-
-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.List;
-import java.util.Set;
-import java.util.function.BiConsumer;
-import static java.util.stream.Collectors.toSet;
-import java.util.stream.Stream;
-import jdk.jpackage.test.Annotations.Parameters;
-import jdk.jpackage.test.Annotations.Test;
-import static jdk.jpackage.test.DirectoryContentVerifierTest.AssertType.CONTAINS;
-import static jdk.jpackage.test.DirectoryContentVerifierTest.AssertType.MATCH;
-import jdk.jpackage.test.TKit.DirectoryContentVerifier;
-import static jdk.jpackage.test.TKit.assertAssert;
-
-/*
- * @test
- * @summary Test TKit.DirectoryContentVerifier from jpackage test library
- * @library /test/jdk/tools/jpackage/helpers
- * @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
- * @compile DirectoryContentVerifierTest.java
- * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
- * --jpt-run=jdk.jpackage.test.DirectoryContentVerifierTest
- */
-public class DirectoryContentVerifierTest {
-
- enum AssertType {
- MATCH(DirectoryContentVerifier::match),
- CONTAINS(DirectoryContentVerifier::contains),
- ;
-
- AssertType(BiConsumer> assertFunc) {
- this.assertFunc = assertFunc;
- }
-
- private final BiConsumer> assertFunc;
- }
-
- private static ArgsBuilder buildArgs() {
- return new ArgsBuilder();
- }
-
- private static class ArgsBuilder {
-
- void applyTo(List data) {
- data.add(new Object[]{expectedPaths, actualPaths, assertOp, success});
- }
-
- void applyVariantsTo(List data) {
- applyTo(data);
- boolean pathGroupsEqual = List.of(expectedPaths).equals(List.of(actualPaths));
- if (assertOp == MATCH) {
- if (!pathGroupsEqual) {
- data.add(new Object[]{actualPaths, expectedPaths, MATCH, success});
- }
- if (success) {
- data.add(new Object[]{expectedPaths, actualPaths, CONTAINS, success});
- if (!pathGroupsEqual) {
- data.add(new Object[]{actualPaths, expectedPaths, CONTAINS, success});
- }
- }
- }
- }
-
- ArgsBuilder expectedPaths(String... paths) {
- expectedPaths = paths;
- return this;
- }
-
- ArgsBuilder actualPaths(String... paths) {
- actualPaths = paths;
- return this;
- }
-
- ArgsBuilder assertOp(AssertType v) {
- assertOp = v;
- return this;
- }
-
- ArgsBuilder expectFail() {
- success = false;
- return this;
- }
-
- private String[] expectedPaths = new String[0];
- private String[] actualPaths = new String[0];
- private AssertType assertOp = MATCH;
- private boolean success = true;
- }
-
- @Parameters
- public static Collection input() {
- List data = new ArrayList<>();
- buildArgs().applyVariantsTo(data);
- buildArgs().actualPaths("foo").assertOp(CONTAINS).applyTo(data);
- buildArgs().actualPaths("zoo").expectFail().applyVariantsTo(data);
- buildArgs().actualPaths("boo").expectedPaths("boo").applyVariantsTo(data);
- if (TKit.isWindows()) {
- buildArgs().actualPaths("moo").expectedPaths("Moo").applyVariantsTo(data);
- } else {
- buildArgs().actualPaths("moo").expectedPaths("Moo").expectFail().applyVariantsTo(data);
- }
- buildArgs().actualPaths("hello").expectedPaths().expectFail().applyVariantsTo(data);
- buildArgs().actualPaths("123").expectedPaths("456").expectFail().applyVariantsTo(data);
- buildArgs().actualPaths("a", "b", "c").expectedPaths("b", "a", "c").applyVariantsTo(data);
- buildArgs().actualPaths("AA", "BB", "CC").expectedPaths("BB", "AA").expectFail().applyVariantsTo(data);
- buildArgs().actualPaths("AA", "BB", "CC").expectedPaths("BB", "AA").assertOp(CONTAINS).applyTo(data);
- buildArgs().actualPaths("AA", "BB", "CC").expectedPaths("BB", "DD", "AA").expectFail().assertOp(CONTAINS).applyTo(data);
- buildArgs().actualPaths("AA", "BB", "CC").expectedPaths("BB", "DD", "AA").expectFail().applyTo(data);
- return data;
- }
-
- public DirectoryContentVerifierTest(String[] expectedPaths, String[] actualPaths,
- AssertType assertOp, Boolean success) {
- this.expectedPaths = conv(expectedPaths);
- this.actualPaths = conv(actualPaths);
- this.assertOp = assertOp;
- this.success = success;
- }
-
- @Test
- public void test() {
- TKit.withTempDirectory("basedir", this::test);
- }
-
- private void test(Path basedir) throws IOException {
- for (var path : actualPaths) {
- Files.createFile(basedir.resolve(path));
- }
-
- var testee = TKit.assertDirectoryContent(basedir);
-
- assertAssert(success, () -> assertOp.assertFunc.accept(testee, expectedPaths));
- }
-
- private static Set conv(String... paths) {
- return Stream.of(paths).map(Path::of).collect(toSet());
- }
-
- private final Set expectedPaths;
- private final Set actualPaths;
- private final AssertType assertOp;
- private final boolean success;
-}
diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java
index d4219704934..9b25c9058d1 100644
--- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java
+++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java
@@ -897,8 +897,9 @@ public JPackageCommand setAppLayoutAsserts(AppLayoutAssert ... asserts) {
}
public JPackageCommand excludeAppLayoutAsserts(AppLayoutAssert... asserts) {
- return setAppLayoutAsserts(Stream.of(asserts).filter(Predicate.not(
- appLayoutAsserts::contains)).toArray(AppLayoutAssert[]::new));
+ var asSet = Set.of(asserts);
+ return setAppLayoutAsserts(appLayoutAsserts.stream().filter(Predicate.not(
+ asSet::contains)).toArray(AppLayoutAssert[]::new));
}
JPackageCommand assertAppLayout() {
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 8068e1d858f..63afb6cf9f7 100644
--- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacHelper.java
+++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacHelper.java
@@ -259,7 +259,7 @@ static PackageHandlers createPkgPackageHandlers() {
}
static void verifyBundleStructure(JPackageCommand cmd) {
- Path bundleRoot;
+ final Path bundleRoot;
if (cmd.isImagePackageType()) {
bundleRoot = cmd.outputBundle();
} else {
@@ -268,8 +268,26 @@ static void verifyBundleStructure(JPackageCommand cmd) {
}
TKit.assertDirectoryContent(bundleRoot).match(Path.of("Contents"));
- TKit.assertDirectoryContent(bundleRoot.resolve("Contents")).match(
- cmd.isRuntime() ? RUNTIME_BUNDLE_CONTENTS : APP_BUNDLE_CONTENTS);
+
+ final var contentsDir = bundleRoot.resolve("Contents");
+ final var expectedContentsItems = cmd.isRuntime() ? RUNTIME_BUNDLE_CONTENTS : APP_BUNDLE_CONTENTS;
+
+ var contentsVerifier = TKit.assertDirectoryContent(contentsDir);
+ if (!cmd.hasArgument("--app-content")) {
+ contentsVerifier.match(expectedContentsItems);
+ } else {
+ // Additional content added to the bundle.
+ // Verify there is no period (.) char in the names of additional directories if any.
+ contentsVerifier.contains(expectedContentsItems);
+ contentsVerifier = contentsVerifier.removeAll(expectedContentsItems);
+ contentsVerifier.match(contentsVerifier.items().stream().filter(path -> {
+ if (Files.isDirectory(contentsDir.resolve(path))) {
+ return !path.getFileName().toString().contains(".");
+ } else {
+ return true;
+ }
+ }).collect(toSet()));
+ }
}
static String getBundleName(JPackageCommand cmd) {
diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java
index ca1224aafd7..02841a1a713 100644
--- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java
+++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java
@@ -61,6 +61,7 @@
import java.util.stream.Collectors;
import static java.util.stream.Collectors.toSet;
import java.util.stream.Stream;
+import jdk.internal.util.OperatingSystem;
import jdk.jpackage.test.Functional.ExceptionBox;
import jdk.jpackage.test.Functional.ThrowingConsumer;
import jdk.jpackage.test.Functional.ThrowingRunnable;
@@ -68,8 +69,6 @@
public final class TKit {
- private static final String OS = System.getProperty("os.name").toLowerCase();
-
public static final Path TEST_SRC_ROOT = Functional.identity(() -> {
Path root = Path.of(System.getProperty("test.src"));
@@ -176,15 +175,15 @@ static String getCurrentDefaultAppName() {
}
public static boolean isWindows() {
- return (OS.contains("win"));
+ return OperatingSystem.isWindows();
}
public static boolean isOSX() {
- return (OS.contains("mac"));
+ return OperatingSystem.isMacOS();
}
public static boolean isLinux() {
- return ((OS.contains("nix") || OS.contains("nux")));
+ return OperatingSystem.isLinux();
}
public static boolean isLinuxAPT() {
@@ -786,7 +785,7 @@ public void match(Set expected) {
baseDir, format(comm.common), format(comm.unique1), format(comm.unique2)));
} else if (!comm.unique1.isEmpty()) {
error(String.format(
- "assertDirectoryContentEquals%s: Expected %s. Unexpected %s",
+ "assertDirectoryContentEquals(%s): Expected %s. Unexpected %s",
baseDir, format(comm.common), format(comm.unique1)));
} else if (!comm.unique2.isEmpty()) {
error(String.format(
@@ -818,12 +817,20 @@ public void contains(Set expected) {
}
}
- public DirectoryContentVerifier removeAll(Path ... paths) {
+ public DirectoryContentVerifier removeAll(Collection paths) {
Set newContent = new HashSet<>(content);
- newContent.removeAll(List.of(paths));
+ newContent.removeAll(paths);
return new DirectoryContentVerifier(baseDir, newContent);
}
+ public DirectoryContentVerifier removeAll(Path ... paths) {
+ return removeAll(List.of(paths));
+ }
+
+ public Set items() {
+ return content;
+ }
+
private DirectoryContentVerifier(Path baseDir, Set contents) {
this.baseDir = baseDir;
this.content = contents;
diff --git a/test/jdk/tools/jpackage/linux/AppAboutUrlTest.java b/test/jdk/tools/jpackage/linux/AppAboutUrlTest.java
index e3812b0fcee..0d8f0ec4805 100644
--- a/test/jdk/tools/jpackage/linux/AppAboutUrlTest.java
+++ b/test/jdk/tools/jpackage/linux/AppAboutUrlTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 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
@@ -44,13 +44,12 @@
/*
* @test
* @summary jpackage with --about-url
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @key jpackagePlatformPackage
* @build jdk.jpackage.test.*
* @build AppAboutUrlTest
* @requires (os.family == "linux")
* @requires (jpackage.test.SQETest == null)
- * @modules jdk.jpackage/jdk.jpackage.internal
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=AppAboutUrlTest
*/
@@ -58,13 +57,12 @@
/*
* @test
* @summary jpackage with --about-url
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @key jpackagePlatformPackage
* @build jdk.jpackage.test.*
* @build AppAboutUrlTest
* @requires (os.family == "linux")
* @requires (jpackage.test.SQETest != null)
- * @modules jdk.jpackage/jdk.jpackage.internal
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=AppAboutUrlTest.test
*/
diff --git a/test/jdk/tools/jpackage/linux/AppCategoryTest.java b/test/jdk/tools/jpackage/linux/AppCategoryTest.java
index d52b537604d..5fd34ab3bfd 100644
--- a/test/jdk/tools/jpackage/linux/AppCategoryTest.java
+++ b/test/jdk/tools/jpackage/linux/AppCategoryTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -43,12 +43,11 @@
/*
* @test
* @summary jpackage with --linux-app-category
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @key jpackagePlatformPackage
* @build jdk.jpackage.test.*
* @build AppCategoryTest
* @requires (os.family == "linux")
- * @modules jdk.jpackage/jdk.jpackage.internal
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=AppCategoryTest
*/
diff --git a/test/jdk/tools/jpackage/linux/LicenseTypeTest.java b/test/jdk/tools/jpackage/linux/LicenseTypeTest.java
index 5a8837a424e..f949284112d 100644
--- a/test/jdk/tools/jpackage/linux/LicenseTypeTest.java
+++ b/test/jdk/tools/jpackage/linux/LicenseTypeTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -38,12 +38,11 @@
/*
* @test
* @summary jpackage with --linux-rpm-license-type
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @key jpackagePlatformPackage
* @build jdk.jpackage.test.*
* @build LicenseTypeTest
* @requires (os.family == "linux")
- * @modules jdk.jpackage/jdk.jpackage.internal
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=LicenseTypeTest
*/
diff --git a/test/jdk/tools/jpackage/linux/LinuxBundleNameTest.java b/test/jdk/tools/jpackage/linux/LinuxBundleNameTest.java
index 269f176b368..e39af0fb765 100644
--- a/test/jdk/tools/jpackage/linux/LinuxBundleNameTest.java
+++ b/test/jdk/tools/jpackage/linux/LinuxBundleNameTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -43,12 +43,11 @@
/*
* @test
* @summary jpackage with --linux-package-name
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @key jpackagePlatformPackage
* @build jdk.jpackage.test.*
* @build LinuxBundleNameTest
* @requires (os.family == "linux")
- * @modules jdk.jpackage/jdk.jpackage.internal
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=LinuxBundleNameTest
*/
diff --git a/test/jdk/tools/jpackage/linux/LinuxResourceTest.java b/test/jdk/tools/jpackage/linux/LinuxResourceTest.java
index f38e0763d28..5a460b39ed7 100644
--- a/test/jdk/tools/jpackage/linux/LinuxResourceTest.java
+++ b/test/jdk/tools/jpackage/linux/LinuxResourceTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -33,10 +33,9 @@
/*
* @test
* @summary jpackage with --resource-dir
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @build jdk.jpackage.test.*
* @requires (os.family == "linux")
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile LinuxResourceTest.java
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=LinuxResourceTest
diff --git a/test/jdk/tools/jpackage/linux/LinuxWeirdOutputDirTest.java b/test/jdk/tools/jpackage/linux/LinuxWeirdOutputDirTest.java
index 4ce3c1a4614..a30c1724611 100644
--- a/test/jdk/tools/jpackage/linux/LinuxWeirdOutputDirTest.java
+++ b/test/jdk/tools/jpackage/linux/LinuxWeirdOutputDirTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 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
@@ -30,9 +30,8 @@
* @summary jpackage with values of --dest parameter breaking jpackage launcher
* @requires (os.family == "linux")
* @bug 8268974
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile LinuxWeirdOutputDirTest.java
* @run main/othervm/timeout=540 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=LinuxWeirdOutputDirTest
diff --git a/test/jdk/tools/jpackage/linux/MaintainerTest.java b/test/jdk/tools/jpackage/linux/MaintainerTest.java
index aac4317a26b..a257a5ff92d 100644
--- a/test/jdk/tools/jpackage/linux/MaintainerTest.java
+++ b/test/jdk/tools/jpackage/linux/MaintainerTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -39,12 +39,11 @@
/*
* @test
* @summary jpackage with --linux-deb-maintainer
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @key jpackagePlatformPackage
* @build jdk.jpackage.test.*
* @build MaintainerTest
* @requires (os.family == "linux")
- * @modules jdk.jpackage/jdk.jpackage.internal
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=MaintainerTest
*/
diff --git a/test/jdk/tools/jpackage/linux/PackageDepsTest.java b/test/jdk/tools/jpackage/linux/PackageDepsTest.java
index 457d8f01592..1a69582fc84 100644
--- a/test/jdk/tools/jpackage/linux/PackageDepsTest.java
+++ b/test/jdk/tools/jpackage/linux/PackageDepsTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -46,11 +46,10 @@
/*
* @test
* @summary jpackage with --linux-package-deps
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @key jpackagePlatformPackage
* @build jdk.jpackage.test.*
* @requires (os.family == "linux")
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile PackageDepsTest.java
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=PackageDepsTest
diff --git a/test/jdk/tools/jpackage/linux/ReleaseTest.java b/test/jdk/tools/jpackage/linux/ReleaseTest.java
index 1396e76e583..7516b660f4a 100644
--- a/test/jdk/tools/jpackage/linux/ReleaseTest.java
+++ b/test/jdk/tools/jpackage/linux/ReleaseTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -43,13 +43,12 @@
/*
* @test
* @summary jpackage with --linux-app-release
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @key jpackagePlatformPackage
* @build jdk.jpackage.test.*
* @build ReleaseTest
* @requires (os.family == "linux")
* @requires (jpackage.test.SQETest == null)
- * @modules jdk.jpackage/jdk.jpackage.internal
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=ReleaseTest
*/
@@ -57,13 +56,12 @@
/*
* @test
* @summary jpackage with --linux-app-release
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @key jpackagePlatformPackage
* @build jdk.jpackage.test.*
* @build ReleaseTest
* @requires (os.family == "linux")
* @requires (jpackage.test.SQETest != null)
- * @modules jdk.jpackage/jdk.jpackage.internal
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=ReleaseTest.test
*/
diff --git a/test/jdk/tools/jpackage/linux/ServiceAndDesktopTest.java b/test/jdk/tools/jpackage/linux/ServiceAndDesktopTest.java
index b047ce3e8f4..581190ad341 100644
--- a/test/jdk/tools/jpackage/linux/ServiceAndDesktopTest.java
+++ b/test/jdk/tools/jpackage/linux/ServiceAndDesktopTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -39,12 +39,11 @@
/*
* @test
* @summary jpackage with desktop integration and services on Linux
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @key jpackagePlatformPackage
* @requires jpackage.test.SQETest == null
* @build jdk.jpackage.test.*
* @requires (os.family == "linux")
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile ServiceAndDesktopTest.java
* @run main/othervm/timeout=720 jdk.jpackage.test.Main
* --jpt-run=ServiceAndDesktopTest
diff --git a/test/jdk/tools/jpackage/linux/ShortcutHintTest.java b/test/jdk/tools/jpackage/linux/ShortcutHintTest.java
index 812a1941333..01e89075138 100644
--- a/test/jdk/tools/jpackage/linux/ShortcutHintTest.java
+++ b/test/jdk/tools/jpackage/linux/ShortcutHintTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -53,12 +53,11 @@
/*
* @test
* @summary jpackage with --linux-shortcut
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @key jpackagePlatformPackage
* @requires jpackage.test.SQETest == null
* @build jdk.jpackage.test.*
* @requires (os.family == "linux")
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile ShortcutHintTest.java
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=ShortcutHintTest
@@ -67,12 +66,11 @@
/*
* @test
* @summary jpackage with --linux-shortcut
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @key jpackagePlatformPackage
* @build jdk.jpackage.test.*
* @requires (os.family == "linux")
* @requires jpackage.test.SQETest != null
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile ShortcutHintTest.java
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=ShortcutHintTest.testBasic
diff --git a/test/jdk/tools/jpackage/linux/UpgradeTest.java b/test/jdk/tools/jpackage/linux/UpgradeTest.java
index 1a4234db86f..4bf13476eb5 100644
--- a/test/jdk/tools/jpackage/linux/UpgradeTest.java
+++ b/test/jdk/tools/jpackage/linux/UpgradeTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -32,11 +32,10 @@
/*
* @test
* @summary Linux upgrade testing
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @key jpackagePlatformPackage
* @build jdk.jpackage.test.*
* @requires (os.family == "linux")
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile UpgradeTest.java
* @run main/othervm/timeout=360 jdk.jpackage.test.Main
* --jpt-run=UpgradeTest
diff --git a/test/jdk/tools/jpackage/linux/jdk/jpackage/tests/UsrTreeTest.java b/test/jdk/tools/jpackage/linux/jdk/jpackage/tests/UsrTreeTest.java
index 13237cc5aa3..819ea8f245a 100644
--- a/test/jdk/tools/jpackage/linux/jdk/jpackage/tests/UsrTreeTest.java
+++ b/test/jdk/tools/jpackage/linux/jdk/jpackage/tests/UsrTreeTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -40,12 +40,11 @@
/*
* @test
* @summary jpackage command run installing app in /usr directory tree
- * @library ../../../../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @key jpackagePlatformPackage
* @requires jpackage.test.SQETest == null
* @requires (os.family == "linux")
* @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile UsrTreeTest.java
* @run main/othervm/timeout=720 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=UsrTreeTest
diff --git a/test/jdk/tools/jpackage/macosx/ArgumentsFilteringTest.java b/test/jdk/tools/jpackage/macosx/ArgumentsFilteringTest.java
index 9eae8c8d556..9b57cd7fbe5 100644
--- a/test/jdk/tools/jpackage/macosx/ArgumentsFilteringTest.java
+++ b/test/jdk/tools/jpackage/macosx/ArgumentsFilteringTest.java
@@ -36,9 +36,8 @@
/*
* @test
* @summary jpackage with -psn
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile ArgumentsFilteringTest.java
* @requires (os.family == "mac")
* @run main/othervm/timeout=540 -Xmx512m jdk.jpackage.test.Main
diff --git a/test/jdk/tools/jpackage/macosx/DmgContentTest.java b/test/jdk/tools/jpackage/macosx/DmgContentTest.java
index fcedc3c3bdc..fefbe229ec5 100644
--- a/test/jdk/tools/jpackage/macosx/DmgContentTest.java
+++ b/test/jdk/tools/jpackage/macosx/DmgContentTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,28 +25,22 @@
import jdk.jpackage.test.JPackageCommand;
import jdk.jpackage.test.PackageTest;
import jdk.jpackage.test.PackageType;
-import jdk.jpackage.test.MacHelper;
import jdk.jpackage.test.TKit;
-import jdk.jpackage.test.Annotations.Parameter;
import jdk.jpackage.test.Annotations.Parameters;
import jdk.jpackage.test.Annotations.Test;
import java.util.Collection;
-import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
/*
* @test
* @summary jpackage with --type dmg --mac-dmg-content
- * @library ../helpers
- * @library /test/lib
- * @library base
+ * @library /test/jdk/tools/jpackage/helpers
* @key jpackagePlatformPackage
* @build jdk.jpackage.test.*
* @build DmgContentTest
- * @modules jdk.jpackage/jdk.jpackage.internal
* @requires (os.family == "mac")
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=DmgContentTest
diff --git a/test/jdk/tools/jpackage/macosx/HostArchPkgTest.java b/test/jdk/tools/jpackage/macosx/HostArchPkgTest.java
index 7d510c0a819..69e1cd6c42a 100644
--- a/test/jdk/tools/jpackage/macosx/HostArchPkgTest.java
+++ b/test/jdk/tools/jpackage/macosx/HostArchPkgTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 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
@@ -28,6 +28,7 @@
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;
+import jdk.internal.util.Architecture;
import jdk.jpackage.test.JPackageCommand;
import jdk.jpackage.test.PackageTest;
import jdk.jpackage.test.PackageType;
@@ -42,9 +43,8 @@
/*
* @test
* @summary jpackage test to validate "hostArchitectures" attribute
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile HostArchPkgTest.java
* @requires (os.family == "mac")
* @key jpackagePlatformPackage
@@ -74,7 +74,7 @@ private static void verifyHostArch(JPackageCommand cmd) throws Exception {
"/installer-gui-script/options/@hostArchitectures",
doc, XPathConstants.STRING);
- if ("aarch64".equals(System.getProperty("os.arch"))) {
+ if (Architecture.isAARCH64()) {
TKit.assertEquals(v, "arm64",
"Check value of \"hostArchitectures\" attribute");
} else {
diff --git a/test/jdk/tools/jpackage/macosx/MacAppStoreJlinkOptionsTest.java b/test/jdk/tools/jpackage/macosx/MacAppStoreJlinkOptionsTest.java
index 8b1cec04ab9..1501fd15d8f 100644
--- a/test/jdk/tools/jpackage/macosx/MacAppStoreJlinkOptionsTest.java
+++ b/test/jdk/tools/jpackage/macosx/MacAppStoreJlinkOptionsTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -33,11 +33,9 @@
/*
* @test
* @summary jpackage with --mac-app-store and --jlink-options
- * @library ../helpers
- * @library /test/lib
+ * @library /test/jdk/tools/jpackage/helpers
* @build jdk.jpackage.test.*
* @build MacAppStoreJLinkOptionsTest
- * @modules jdk.jpackage/jdk.jpackage.internal
* @requires (os.family == "mac")
* @run main/othervm/timeout=540 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=MacAppStoreJLinkOptionsTest
diff --git a/test/jdk/tools/jpackage/macosx/MacAppStoreRuntimeTest.java b/test/jdk/tools/jpackage/macosx/MacAppStoreRuntimeTest.java
index ea2cee77b4e..ab8b8590b33 100644
--- a/test/jdk/tools/jpackage/macosx/MacAppStoreRuntimeTest.java
+++ b/test/jdk/tools/jpackage/macosx/MacAppStoreRuntimeTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -43,11 +43,9 @@
/*
* @test
* @summary jpackage with --mac-app-store and --runtime-image
- * @library ../helpers
- * @library /test/lib
+ * @library /test/jdk/tools/jpackage/helpers
* @build jdk.jpackage.test.*
* @build MacAppStoreRuntimeTest
- * @modules jdk.jpackage/jdk.jpackage.internal
* @requires (os.family == "mac")
* @run main/othervm -Xmx512m jdk.jpackage.test.Main
* --jpt-run=MacAppStoreRuntimeTest
diff --git a/test/jdk/tools/jpackage/macosx/MacFileAssociationsTest.java b/test/jdk/tools/jpackage/macosx/MacFileAssociationsTest.java
index 0bf972cf51b..01c9e48b5fd 100644
--- a/test/jdk/tools/jpackage/macosx/MacFileAssociationsTest.java
+++ b/test/jdk/tools/jpackage/macosx/MacFileAssociationsTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -40,10 +40,9 @@
/*
* @test
* @summary jpackage with --file-associations and mac specific file association args
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @build jdk.jpackage.test.*
* @build MacFileAssociationsTest
- * @modules jdk.jpackage/jdk.jpackage.internal
* @requires (os.family == "mac")
* @run main/othervm -Xmx512m jdk.jpackage.test.Main
* --jpt-run=MacFileAssociationsTest
diff --git a/test/jdk/tools/jpackage/macosx/MacPropertiesTest.java b/test/jdk/tools/jpackage/macosx/MacPropertiesTest.java
index 9d4324e2222..5482a3ea508 100644
--- a/test/jdk/tools/jpackage/macosx/MacPropertiesTest.java
+++ b/test/jdk/tools/jpackage/macosx/MacPropertiesTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -35,10 +35,9 @@
/*
* @test
* @summary jpackage with --mac-package-name, --mac-package-identifier
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @build jdk.jpackage.test.*
* @requires (os.family == "mac")
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile MacPropertiesTest.java
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=MacPropertiesTest
diff --git a/test/jdk/tools/jpackage/macosx/NameWithSpaceTest.java b/test/jdk/tools/jpackage/macosx/NameWithSpaceTest.java
index ac505e5ca81..ea95ad964f3 100644
--- a/test/jdk/tools/jpackage/macosx/NameWithSpaceTest.java
+++ b/test/jdk/tools/jpackage/macosx/NameWithSpaceTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -38,9 +38,8 @@
/*
* @test
* @summary jpackage test with name containing spaces
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile NameWithSpaceTest.java
* @requires (os.family == "mac")
* @key jpackagePlatformPackage
diff --git a/test/jdk/tools/jpackage/macosx/SigningAppImageTest.java b/test/jdk/tools/jpackage/macosx/SigningAppImageTest.java
index 65793baa096..959f6d710b6 100644
--- a/test/jdk/tools/jpackage/macosx/SigningAppImageTest.java
+++ b/test/jdk/tools/jpackage/macosx/SigningAppImageTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -45,7 +45,7 @@
/*
* @test
* @summary jpackage with --type app-image --mac-sign
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @library /test/lib
* @library base
* @build SigningBase
@@ -53,7 +53,6 @@
* @build jtreg.SkippedException
* @build jdk.jpackage.test.*
* @build SigningAppImageTest
- * @modules jdk.jpackage/jdk.jpackage.internal
* @requires (os.family == "mac")
* @run main/othervm/timeout=720 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=SigningAppImageTest
diff --git a/test/jdk/tools/jpackage/macosx/SigningAppImageTwoStepsTest.java b/test/jdk/tools/jpackage/macosx/SigningAppImageTwoStepsTest.java
index cf479d9ba94..b8763d82e36 100644
--- a/test/jdk/tools/jpackage/macosx/SigningAppImageTwoStepsTest.java
+++ b/test/jdk/tools/jpackage/macosx/SigningAppImageTwoStepsTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -46,7 +46,7 @@
/*
* @test
* @summary jpackage with --type app-image --app-image "appImage" --mac-sign
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @library /test/lib
* @library base
* @build SigningBase
@@ -54,7 +54,6 @@
* @build jtreg.SkippedException
* @build jdk.jpackage.test.*
* @build SigningAppImageTwoStepsTest
- * @modules jdk.jpackage/jdk.jpackage.internal
* @requires (os.family == "mac")
* @run main/othervm/timeout=720 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=SigningAppImageTwoStepsTest
diff --git a/test/jdk/tools/jpackage/macosx/SigningOptionsTest.java b/test/jdk/tools/jpackage/macosx/SigningOptionsTest.java
index 9d6cd6472ba..c5df2c1b31b 100644
--- a/test/jdk/tools/jpackage/macosx/SigningOptionsTest.java
+++ b/test/jdk/tools/jpackage/macosx/SigningOptionsTest.java
@@ -31,14 +31,13 @@
/*
* @test
* @summary Test jpackage signing options errors
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @library /test/lib
* @library base
* @build SigningBase
* @build SigningCheck
* @build jtreg.SkippedException
* @build SigningOptionsTest
- * @modules jdk.jpackage/jdk.jpackage.internal
* @requires (os.family == "mac")
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=SigningOptionsTest
@@ -48,14 +47,13 @@
/*
* @test
* @summary Test jpackage signing options errors
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @library /test/lib
* @library base
* @build SigningBase
* @build SigningCheck
* @build jtreg.SkippedException
* @build SigningOptionsTest
- * @modules jdk.jpackage/jdk.jpackage.internal
* @requires (os.family == "mac")
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=SigningOptionsTest
diff --git a/test/jdk/tools/jpackage/macosx/SigningPackageFromTwoStepAppImageTest.java b/test/jdk/tools/jpackage/macosx/SigningPackageFromTwoStepAppImageTest.java
index 48f5dca8986..0f4f2e77476 100644
--- a/test/jdk/tools/jpackage/macosx/SigningPackageFromTwoStepAppImageTest.java
+++ b/test/jdk/tools/jpackage/macosx/SigningPackageFromTwoStepAppImageTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -50,7 +50,7 @@
/*
* @test
* @summary jpackage with --type pkg,dmg --app-image
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @library /test/lib
* @library base
* @key jpackagePlatformPackage
@@ -59,7 +59,6 @@
* @build jtreg.SkippedException
* @build jdk.jpackage.test.*
* @build SigningPackageFromTwoStepAppImageTest
- * @modules jdk.jpackage/jdk.jpackage.internal
* @requires (os.family == "mac")
* @run main/othervm/timeout=720 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=SigningPackageFromTwoStepAppImageTest
diff --git a/test/jdk/tools/jpackage/macosx/SigningPackageTest.java b/test/jdk/tools/jpackage/macosx/SigningPackageTest.java
index c555b0386cd..621fac1cd19 100644
--- a/test/jdk/tools/jpackage/macosx/SigningPackageTest.java
+++ b/test/jdk/tools/jpackage/macosx/SigningPackageTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -48,7 +48,7 @@
/*
* @test
* @summary jpackage with --type pkg,dmg --mac-sign
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @library /test/lib
* @library base
* @key jpackagePlatformPackage
@@ -57,7 +57,6 @@
* @build jtreg.SkippedException
* @build jdk.jpackage.test.*
* @build SigningPackageTest
- * @modules jdk.jpackage/jdk.jpackage.internal
* @requires (os.family == "mac")
* @run main/othervm/timeout=720 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=SigningPackageTest
diff --git a/test/jdk/tools/jpackage/macosx/SigningPackageTwoStepTest.java b/test/jdk/tools/jpackage/macosx/SigningPackageTwoStepTest.java
index a34f7921b91..65211e8c29e 100644
--- a/test/jdk/tools/jpackage/macosx/SigningPackageTwoStepTest.java
+++ b/test/jdk/tools/jpackage/macosx/SigningPackageTwoStepTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -51,7 +51,7 @@
/*
* @test
* @summary jpackage with --type pkg,dmg --app-image
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @library /test/lib
* @library base
* @key jpackagePlatformPackage
@@ -60,7 +60,6 @@
* @build jtreg.SkippedException
* @build jdk.jpackage.test.*
* @build SigningPackageTwoStepTest
- * @modules jdk.jpackage/jdk.jpackage.internal
* @requires (os.family == "mac")
* @run main/othervm/timeout=720 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=SigningPackageTwoStepTest
diff --git a/test/jdk/tools/jpackage/share/AddLShortcutTest.java b/test/jdk/tools/jpackage/share/AddLShortcutTest.java
index 8883cfa82f3..92784abd5cc 100644
--- a/test/jdk/tools/jpackage/share/AddLShortcutTest.java
+++ b/test/jdk/tools/jpackage/share/AddLShortcutTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 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
@@ -44,12 +44,10 @@
* @test
* @summary jpackage with --add-launcher
* @key jpackagePlatformPackage
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile AddLShortcutTest.java
* @run main/othervm/timeout=540 -Xmx512m
- * --add-opens jdk.jpackage/jdk.jpackage.internal=ALL-UNNAMED
* jdk.jpackage.test.Main
* --jpt-run=AddLShortcutTest
*/
diff --git a/test/jdk/tools/jpackage/share/AddLauncherTest.java b/test/jdk/tools/jpackage/share/AddLauncherTest.java
index 4a24183647d..ae774b86f3a 100644
--- a/test/jdk/tools/jpackage/share/AddLauncherTest.java
+++ b/test/jdk/tools/jpackage/share/AddLauncherTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -48,12 +48,10 @@
* @summary jpackage with --add-launcher
* @key jpackagePlatformPackage
* @requires (jpackage.test.SQETest != null)
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile AddLauncherTest.java
* @run main/othervm/timeout=360 -Xmx512m
- * --add-opens jdk.jpackage/jdk.jpackage.internal=ALL-UNNAMED
* jdk.jpackage.test.Main
* --jpt-run=AddLauncherTest.test
*/
@@ -63,12 +61,10 @@
* @summary jpackage with --add-launcher
* @key jpackagePlatformPackage
* @requires (jpackage.test.SQETest == null)
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile AddLauncherTest.java
* @run main/othervm/timeout=540 -Xmx512m
- * --add-opens jdk.jpackage/jdk.jpackage.internal=ALL-UNNAMED
* jdk.jpackage.test.Main
* --jpt-run=AddLauncherTest
*/
diff --git a/test/jdk/tools/jpackage/share/AppContentTest.java b/test/jdk/tools/jpackage/share/AppContentTest.java
index 94362530751..e056070a5fc 100644
--- a/test/jdk/tools/jpackage/share/AppContentTest.java
+++ b/test/jdk/tools/jpackage/share/AppContentTest.java
@@ -45,13 +45,10 @@
/*
* @test
* @summary jpackage with --app-content option
- * @library ../helpers
- * @library /test/lib
+ * @library /test/jdk/tools/jpackage/helpers
* @key jpackagePlatformPackage
* @build jdk.jpackage.test.*
* @build AppContentTest
- * @modules jdk.jpackage/jdk.jpackage.internal
- * @modules java.base/jdk.internal.util
* @run main/othervm/timeout=720 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=AppContentTest
*/
diff --git a/test/jdk/tools/jpackage/share/AppImagePackageTest.java b/test/jdk/tools/jpackage/share/AppImagePackageTest.java
index 949e68faae2..62d5e974f86 100644
--- a/test/jdk/tools/jpackage/share/AppImagePackageTest.java
+++ b/test/jdk/tools/jpackage/share/AppImagePackageTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -43,10 +43,9 @@
* @test
* @summary jpackage with --app-image
* @key jpackagePlatformPackage
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @requires (jpackage.test.SQETest == null)
* @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile AppImagePackageTest.java
* @run main/othervm/timeout=540 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=AppImagePackageTest
diff --git a/test/jdk/tools/jpackage/share/AppLauncherEnvTest.java b/test/jdk/tools/jpackage/share/AppLauncherEnvTest.java
index cc52b285fbe..a16ff9c18f9 100644
--- a/test/jdk/tools/jpackage/share/AppLauncherEnvTest.java
+++ b/test/jdk/tools/jpackage/share/AppLauncherEnvTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 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
@@ -39,12 +39,9 @@
/*
* @test
* @summary Tests values of environment variables altered by jpackage launcher
- * @library ../helpers
- * @library /test/lib
- * @build AppLauncherEnvTest
+ * @library /test/jdk/tools/jpackage/helpers
* @build jdk.jpackage.test.*
* @build AppLauncherEnvTest
- * @modules jdk.jpackage/jdk.jpackage.internal
* @run main/othervm -Xmx512m jdk.jpackage.test.Main
* --jpt-run=AppLauncherEnvTest
*/
diff --git a/test/jdk/tools/jpackage/share/ArgumentsTest.java b/test/jdk/tools/jpackage/share/ArgumentsTest.java
index f630d7f7168..3be6c36a25c 100644
--- a/test/jdk/tools/jpackage/share/ArgumentsTest.java
+++ b/test/jdk/tools/jpackage/share/ArgumentsTest.java
@@ -46,9 +46,8 @@
/*
* @test
* @summary jpackage create image with --arguments test
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile ArgumentsTest.java
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=ArgumentsTest
diff --git a/test/jdk/tools/jpackage/share/EmptyFolderTest.java b/test/jdk/tools/jpackage/share/EmptyFolderTest.java
index 230d8a039ea..40a4db03d6f 100644
--- a/test/jdk/tools/jpackage/share/EmptyFolderTest.java
+++ b/test/jdk/tools/jpackage/share/EmptyFolderTest.java
@@ -37,12 +37,10 @@
/*
* @test
* @summary jpackage for package with input containing empty folders
- * @library ../helpers
- * @library /test/lib
+ * @library /test/jdk/tools/jpackage/helpers
* @key jpackagePlatformPackage
* @build jdk.jpackage.test.*
* @build EmptyFolderTest
- * @modules jdk.jpackage/jdk.jpackage.internal
* @run main/othervm/timeout=720 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=EmptyFolderTest.testPackage
*/
@@ -50,11 +48,9 @@
/*
* @test
* @summary jpackage for app image with input containing empty folders
- * @library ../helpers
- * @library /test/lib
+ * @library /test/jdk/tools/jpackage/helpers
* @build jdk.jpackage.test.*
* @build EmptyFolderTest
- * @modules jdk.jpackage/jdk.jpackage.internal
* @run main/othervm -Xmx512m jdk.jpackage.test.Main
* --jpt-run=EmptyFolderTest.testAppImage
*/
diff --git a/test/jdk/tools/jpackage/share/FileAssociationsTest.java b/test/jdk/tools/jpackage/share/FileAssociationsTest.java
index 326258df600..a06ea82bcba 100644
--- a/test/jdk/tools/jpackage/share/FileAssociationsTest.java
+++ b/test/jdk/tools/jpackage/share/FileAssociationsTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -57,11 +57,10 @@
/*
* @test
* @summary jpackage with --file-associations
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @key jpackagePlatformPackage
* @requires jpackage.test.SQETest == null
* @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile FileAssociationsTest.java
* @run main/othervm/timeout=540 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=FileAssociationsTest
@@ -70,11 +69,10 @@
/*
* @test
* @summary jpackage with --file-associations
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @key jpackagePlatformPackage
* @requires jpackage.test.SQETest != null
* @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile FileAssociationsTest.java
* @run main/othervm/timeout=540 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=FileAssociationsTest.test
diff --git a/test/jdk/tools/jpackage/share/IconTest.java b/test/jdk/tools/jpackage/share/IconTest.java
index 254823d1227..2d6469f5f2e 100644
--- a/test/jdk/tools/jpackage/share/IconTest.java
+++ b/test/jdk/tools/jpackage/share/IconTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -49,12 +49,10 @@
/*
* @test
* @summary jpackage create image and package with custom icons for the main and additional launcher
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile IconTest.java
* @run main/othervm/timeout=540 -Xmx512m
- * --add-opens jdk.jpackage/jdk.jpackage.internal=ALL-UNNAMED
* jdk.jpackage.test.Main
* --jpt-run=IconTest
*/
diff --git a/test/jdk/tools/jpackage/share/InOutPathTest.java b/test/jdk/tools/jpackage/share/InOutPathTest.java
index 699d88e3189..f8cb983bd16 100644
--- a/test/jdk/tools/jpackage/share/InOutPathTest.java
+++ b/test/jdk/tools/jpackage/share/InOutPathTest.java
@@ -47,9 +47,8 @@
/*
* @test
* @summary Test jpackage command line with overlapping input and output paths
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile InOutPathTest.java
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=InOutPathTest
@@ -73,11 +72,20 @@ public static Collection input() {
data.addAll(additionalContentInput(packageTypes, "--app-content"));
}
- data.addAll(List.of(new Object[][]{
- {PackageType.IMAGE.toString(), wrap(cmd -> {
- additionalContent(cmd, "--app-content", cmd.outputBundle());
- }, "--app-content same as output bundle")},
- }));
+ if (!TKit.isOSX()) {
+ data.addAll(List.of(new Object[][]{
+ {PackageType.IMAGE.toString(), wrap(cmd -> {
+ additionalContent(cmd, "--app-content", cmd.outputBundle());
+ }, "--app-content same as output bundle")},
+ }));
+ } else {
+ var contentsFolder = "Contents/MacOS";
+ data.addAll(List.of(new Object[][]{
+ {PackageType.IMAGE.toString(), wrap(cmd -> {
+ additionalContent(cmd, "--app-content", cmd.outputBundle().resolve(contentsFolder));
+ }, String.format("--app-content same as the \"%s\" folder in the output bundle", contentsFolder))},
+ }));
+ }
if (TKit.isOSX()) {
data.addAll(additionalContentInput(PackageType.MAC_DMG.toString(),
@@ -173,6 +181,16 @@ private static void runTest(Set packageTypes,
if (isAppImageValid(cmd)) {
verifyAppImage(cmd);
}
+
+ if (cmd.hasArgument("--app-content")) {
+ // `--app-content` can be set to the app image directory which
+ // should not exist before jpackage is executed:
+ // jpackage --name Foo --dest output --app-content output/Foo
+ // Verify the directory exists after jpackage execution.
+ // At least this will catch the case when the value of
+ // `--app-content` option refers to a path unrelated to jpackage I/O.
+ TKit.assertDirectoryExists(Path.of(cmd.getArgumentValue("--app-content")));
+ }
} else {
new PackageTest()
.forTypes(packageTypes)
diff --git a/test/jdk/tools/jpackage/share/InstallDirTest.java b/test/jdk/tools/jpackage/share/InstallDirTest.java
index 1f969149c68..7047f35e87b 100644
--- a/test/jdk/tools/jpackage/share/InstallDirTest.java
+++ b/test/jdk/tools/jpackage/share/InstallDirTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -54,11 +54,10 @@
/*
* @test
* @summary jpackage with --install-dir
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @key jpackagePlatformPackage
* @build jdk.jpackage.test.*
* @compile InstallDirTest.java
- * @modules jdk.jpackage/jdk.jpackage.internal
* @run main/othervm/timeout=540 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=InstallDirTest.testCommon
*/
@@ -66,11 +65,10 @@
/*
* @test
* @summary jpackage with --install-dir
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @key jpackagePlatformPackage
* @build jdk.jpackage.test.*
* @compile InstallDirTest.java
- * @modules jdk.jpackage/jdk.jpackage.internal
* @requires (os.family == "linux")
* @requires (jpackage.test.SQETest == null)
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
diff --git a/test/jdk/tools/jpackage/share/LicenseTest.java b/test/jdk/tools/jpackage/share/LicenseTest.java
index 4211386f243..b0eef94fa7c 100644
--- a/test/jdk/tools/jpackage/share/LicenseTest.java
+++ b/test/jdk/tools/jpackage/share/LicenseTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -63,11 +63,10 @@
/*
* @test
* @summary jpackage with --license-file
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @key jpackagePlatformPackage
* @build jdk.jpackage.test.*
* @compile LicenseTest.java
- * @modules jdk.jpackage/jdk.jpackage.internal
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=LicenseTest.testCommon
*/
@@ -75,13 +74,12 @@
/*
* @test
* @summary jpackage with --license-file
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @key jpackagePlatformPackage
* @build jdk.jpackage.test.*
* @compile LicenseTest.java
* @requires (os.family == "linux")
* @requires (jpackage.test.SQETest == null)
- * @modules jdk.jpackage/jdk.jpackage.internal
* @run main/othervm/timeout=1440 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=LicenseTest.testCustomDebianCopyright
* --jpt-run=LicenseTest.testCustomDebianCopyrightSubst
diff --git a/test/jdk/tools/jpackage/share/MultiLauncherTwoPhaseTest.java b/test/jdk/tools/jpackage/share/MultiLauncherTwoPhaseTest.java
index 030abe99fdf..34962b77ca0 100644
--- a/test/jdk/tools/jpackage/share/MultiLauncherTwoPhaseTest.java
+++ b/test/jdk/tools/jpackage/share/MultiLauncherTwoPhaseTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 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
@@ -43,14 +43,11 @@
/*
* @test
* @summary Multiple launchers in two phases
- * @library ../helpers
- * @library /test/lib
+ * @library /test/jdk/tools/jpackage/helpers
* @key jpackagePlatformPackage
* @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile MultiLauncherTwoPhaseTest.java
* @run main/othervm/timeout=360 -Xmx512m
- * --add-opens jdk.jpackage/jdk.jpackage.internal=ALL-UNNAMED
* jdk.jpackage.test.Main
* --jpt-run=MultiLauncherTwoPhaseTest
*/
diff --git a/test/jdk/tools/jpackage/share/MultiNameTwoPhaseTest.java b/test/jdk/tools/jpackage/share/MultiNameTwoPhaseTest.java
index 7b3f484d62d..870804661a7 100644
--- a/test/jdk/tools/jpackage/share/MultiNameTwoPhaseTest.java
+++ b/test/jdk/tools/jpackage/share/MultiNameTwoPhaseTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 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
@@ -41,12 +41,10 @@
/*
* @test
* @summary Multiple names in two phases
- * @library ../helpers
- * @library /test/lib
+ * @library /test/jdk/tools/jpackage/helpers
* @key jpackagePlatformPackage
* @requires (jpackage.test.SQETest == null)
* @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile MultiNameTwoPhaseTest.java
* @run main/othervm/timeout=540 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=MultiNameTwoPhaseTest
diff --git a/test/jdk/tools/jpackage/share/PerUserCfgTest.java b/test/jdk/tools/jpackage/share/PerUserCfgTest.java
index 9d249a1458a..0fff7eb3a2d 100644
--- a/test/jdk/tools/jpackage/share/PerUserCfgTest.java
+++ b/test/jdk/tools/jpackage/share/PerUserCfgTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -43,12 +43,11 @@
/*
* @test
* @summary pre-user configuration of app launchers
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @key jpackagePlatformPackage
* @requires jpackage.test.SQETest == null
* @build jdk.jpackage.test.*
* @compile PerUserCfgTest.java
- * @modules jdk.jpackage/jdk.jpackage.internal
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=PerUserCfgTest
*/
diff --git a/test/jdk/tools/jpackage/share/RuntimeImageSymbolicLinksTest.java b/test/jdk/tools/jpackage/share/RuntimeImageSymbolicLinksTest.java
index 1726fe3eac6..0e48df630af 100644
--- a/test/jdk/tools/jpackage/share/RuntimeImageSymbolicLinksTest.java
+++ b/test/jdk/tools/jpackage/share/RuntimeImageSymbolicLinksTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -47,11 +47,10 @@
/*
* @test
* @summary jpackage with --runtime-image
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @key jpackagePlatformPackage
* @requires (os.family != "windows")
* @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile RuntimeImageSymbolicLinksTest.java
* @run main/othervm/timeout=1400 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=RuntimeImageSymbolicLinksTest
diff --git a/test/jdk/tools/jpackage/share/RuntimeImageTest.java b/test/jdk/tools/jpackage/share/RuntimeImageTest.java
index 64908b6ac99..f3751c9ee47 100644
--- a/test/jdk/tools/jpackage/share/RuntimeImageTest.java
+++ b/test/jdk/tools/jpackage/share/RuntimeImageTest.java
@@ -32,10 +32,9 @@
/*
* @test
* @summary jpackage with --runtime-image
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @key jpackagePlatformPackage
* @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile RuntimeImageTest.java
* @run main/othervm/timeout=1400 jdk.jpackage.test.Main
* --jpt-run=RuntimeImageTest
diff --git a/test/jdk/tools/jpackage/share/RuntimePackageTest.java b/test/jdk/tools/jpackage/share/RuntimePackageTest.java
index da58ed3a73c..0b505babcc5 100644
--- a/test/jdk/tools/jpackage/share/RuntimePackageTest.java
+++ b/test/jdk/tools/jpackage/share/RuntimePackageTest.java
@@ -55,11 +55,10 @@
/*
* @test
* @summary jpackage with --runtime-image
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @key jpackagePlatformPackage
* @build jdk.jpackage.test.*
* @requires (jpackage.test.SQETest == null)
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile RuntimePackageTest.java
* @run main/othervm/timeout=1400 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=RuntimePackageTest
@@ -68,11 +67,10 @@
/*
* @test
* @summary jpackage with --runtime-image
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @key jpackagePlatformPackage
* @build jdk.jpackage.test.*
* @requires (jpackage.test.SQETest != null)
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile RuntimePackageTest.java
* @run main/othervm/timeout=720 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=RuntimePackageTest.test
diff --git a/test/jdk/tools/jpackage/share/ServiceTest.java b/test/jdk/tools/jpackage/share/ServiceTest.java
index 4cf96b62cd2..f1ff65d18b1 100644
--- a/test/jdk/tools/jpackage/share/ServiceTest.java
+++ b/test/jdk/tools/jpackage/share/ServiceTest.java
@@ -44,13 +44,13 @@
/*
* @test
* @summary Launcher as service packaging test
- * @library ../helpers
- * @key jpackagePlatformPackage
+ * @library /test/jdk/tools/jpackage/helpers
+ * @library /test/lib
* @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
+ * @build jtreg.SkippedException
+ * @key jpackagePlatformPackage
* @compile ServiceTest.java
* @run main/othervm/timeout=360 -Xmx512m
- * --add-opens jdk.jpackage/jdk.jpackage.internal=ALL-UNNAMED
* jdk.jpackage.test.Main
* --jpt-run=ServiceTest
*/
diff --git a/test/jdk/tools/jpackage/share/SimplePackageTest.java b/test/jdk/tools/jpackage/share/SimplePackageTest.java
index d2e8da31c03..e3945b668e0 100644
--- a/test/jdk/tools/jpackage/share/SimplePackageTest.java
+++ b/test/jdk/tools/jpackage/share/SimplePackageTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -40,10 +40,9 @@
/*
* @test
* @summary Simple jpackage command run
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @key jpackagePlatformPackage
* @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile SimplePackageTest.java
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=SimplePackageTest
diff --git a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/AppVersionTest.java b/test/jdk/tools/jpackage/share/jdk/jpackage/tests/AppVersionTest.java
index f137fabf3d6..d4f28ec17be 100644
--- a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/AppVersionTest.java
+++ b/test/jdk/tools/jpackage/share/jdk/jpackage/tests/AppVersionTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -42,9 +42,8 @@
/*
* @test
* @summary jpackage application version testing
- * @library ../../../../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile AppVersionTest.java
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=jdk.jpackage.tests.AppVersionTest
diff --git a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/BasicTest.java b/test/jdk/tools/jpackage/share/jdk/jpackage/tests/BasicTest.java
index 8d62dc291b4..1222fa95949 100644
--- a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/BasicTest.java
+++ b/test/jdk/tools/jpackage/share/jdk/jpackage/tests/BasicTest.java
@@ -50,9 +50,8 @@
/*
* @test
* @summary jpackage basic testing
- * @library ../../../../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile BasicTest.java
* @run main/othervm/timeout=720 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=jdk.jpackage.tests.BasicTest
diff --git a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/CookedRuntimeTest.java b/test/jdk/tools/jpackage/share/jdk/jpackage/tests/CookedRuntimeTest.java
index f61fff69fe6..cfb6ec13ccf 100644
--- a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/CookedRuntimeTest.java
+++ b/test/jdk/tools/jpackage/share/jdk/jpackage/tests/CookedRuntimeTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 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
@@ -42,9 +42,8 @@
/*
* @test
* @summary test '--runtime-image' option of jpackage
- * @library ../../../../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile CookedRuntimeTest.java
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=jdk.jpackage.tests.CookedRuntimeTest
diff --git a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/DotInNameTest.java b/test/jdk/tools/jpackage/share/jdk/jpackage/tests/DotInNameTest.java
index 87c9381bd2d..73be2c2e47a 100644
--- a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/DotInNameTest.java
+++ b/test/jdk/tools/jpackage/share/jdk/jpackage/tests/DotInNameTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 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
@@ -33,9 +33,8 @@
/*
* @test
* @summary jpackage create image with --java-options test
- * @library ../../../../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile DotInNameTest.java
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=jdk.jpackage.tests.DotInNameTest
diff --git a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/ErrorTest.java b/test/jdk/tools/jpackage/share/jdk/jpackage/tests/ErrorTest.java
index 8fcd3c8a730..57603809607 100644
--- a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/ErrorTest.java
+++ b/test/jdk/tools/jpackage/share/jdk/jpackage/tests/ErrorTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 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
@@ -33,9 +33,8 @@
/*
* @test
* @summary Test jpackage output for erroneous input
- * @library ../../../../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile ErrorTest.java
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=jdk.jpackage.tests.ErrorTest
@@ -45,9 +44,8 @@
/*
* @test
* @summary Test jpackage output for erroneous input
- * @library ../../../../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile ErrorTest.java
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=jdk.jpackage.tests.ErrorTest
diff --git a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/JLinkOptionsTest.java b/test/jdk/tools/jpackage/share/jdk/jpackage/tests/JLinkOptionsTest.java
index 40e143763fd..dce60890aba 100644
--- a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/JLinkOptionsTest.java
+++ b/test/jdk/tools/jpackage/share/jdk/jpackage/tests/JLinkOptionsTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 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
@@ -33,9 +33,8 @@
/*
* @test
* @summary jpackage application version testing
- * @library ../../../../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile JLinkOptionsTest.java
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=jdk.jpackage.tests.JLinkOptionsTest
diff --git a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/JavaOptionsEqualsTest.java b/test/jdk/tools/jpackage/share/jdk/jpackage/tests/JavaOptionsEqualsTest.java
index c63892a2ca0..e1c809dadd3 100644
--- a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/JavaOptionsEqualsTest.java
+++ b/test/jdk/tools/jpackage/share/jdk/jpackage/tests/JavaOptionsEqualsTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -35,9 +35,8 @@
/*
* @test
* @summary jpackage create image with --java-options test
- * @library ../../../../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile JavaOptionsEqualsTest.java
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=jdk.jpackage.tests.JavaOptionsEqualsTest
@@ -47,9 +46,8 @@
/*
* @test
* @summary jpackage create image with --java-options test
- * @library ../../../../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile JavaOptionsEqualsTest.java
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=jdk.jpackage.tests.JavaOptionsEqualsTest
diff --git a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/JavaOptionsTest.java b/test/jdk/tools/jpackage/share/jdk/jpackage/tests/JavaOptionsTest.java
index ab2f7a3d15d..cee455271aa 100644
--- a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/JavaOptionsTest.java
+++ b/test/jdk/tools/jpackage/share/jdk/jpackage/tests/JavaOptionsTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -35,9 +35,8 @@
/*
* @test
* @summary jpackage create image with --java-options test
- * @library ../../../../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile JavaOptionsTest.java
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=jdk.jpackage.tests.JavaOptionsTest
diff --git a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/MainClassTest.java b/test/jdk/tools/jpackage/share/jdk/jpackage/tests/MainClassTest.java
index 3b8eea86639..641d0fd00bb 100644
--- a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/MainClassTest.java
+++ b/test/jdk/tools/jpackage/share/jdk/jpackage/tests/MainClassTest.java
@@ -52,9 +52,8 @@
/*
* @test
* @summary test different settings of main class name for jpackage
- * @library ../../../../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile MainClassTest.java
* @run main/othervm/timeout=720 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=jdk.jpackage.tests.MainClassTest
diff --git a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/ModulePathTest.java b/test/jdk/tools/jpackage/share/jdk/jpackage/tests/ModulePathTest.java
index 1c5ead2ad65..c42a24ec310 100644
--- a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/ModulePathTest.java
+++ b/test/jdk/tools/jpackage/share/jdk/jpackage/tests/ModulePathTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -44,9 +44,8 @@
/*
* @test
* @summary jpackage with --module-path testing
- * @library ../../../../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile ModulePathTest.java
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=jdk.jpackage.tests.ModulePathTest
diff --git a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/ModulePathTest2.java b/test/jdk/tools/jpackage/share/jdk/jpackage/tests/ModulePathTest2.java
index 7bfe998014c..7b1ec2f5b63 100644
--- a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/ModulePathTest2.java
+++ b/test/jdk/tools/jpackage/share/jdk/jpackage/tests/ModulePathTest2.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -36,9 +36,8 @@
/*
* @test
* @summary jpackage with --module-path testing
- * @library ../../../../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile ModulePathTest2.java
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=jdk.jpackage.tests.ModulePathTest2
diff --git a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/ModulePathTest3.java b/test/jdk/tools/jpackage/share/jdk/jpackage/tests/ModulePathTest3.java
index 662b2633207..d6fca043920 100644
--- a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/ModulePathTest3.java
+++ b/test/jdk/tools/jpackage/share/jdk/jpackage/tests/ModulePathTest3.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 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
@@ -49,9 +49,8 @@
/*
* @test
* @summary jpackage for app's module linked in external runtime
- * @library ../../../../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile ModulePathTest3.java
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=jdk.jpackage.tests.ModulePathTest3
diff --git a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/MultipleJarAppTest.java b/test/jdk/tools/jpackage/share/jdk/jpackage/tests/MultipleJarAppTest.java
index 3ce9f62d8d2..38878929006 100644
--- a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/MultipleJarAppTest.java
+++ b/test/jdk/tools/jpackage/share/jdk/jpackage/tests/MultipleJarAppTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -33,9 +33,8 @@
/*
* @test
* @summary jpackage application packed in multiple jars
- * @library ../../../../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile MultipleJarAppTest.java
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=jdk.jpackage.tests.MultipleJarAppTest
diff --git a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/NoMPathRuntimeTest.java b/test/jdk/tools/jpackage/share/jdk/jpackage/tests/NoMPathRuntimeTest.java
index fea6324e46b..4a9aef7860d 100644
--- a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/NoMPathRuntimeTest.java
+++ b/test/jdk/tools/jpackage/share/jdk/jpackage/tests/NoMPathRuntimeTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 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
@@ -43,9 +43,8 @@
/*
* @test
* @summary test '--runtime-image' option of jpackage
- * @library ../../../../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile NoMPathRuntimeTest.java
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=jdk.jpackage.tests.NoMPathRuntimeTest
diff --git a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/NonExistentTest.java b/test/jdk/tools/jpackage/share/jdk/jpackage/tests/NonExistentTest.java
index 3790c9002ca..8ca18af356c 100644
--- a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/NonExistentTest.java
+++ b/test/jdk/tools/jpackage/share/jdk/jpackage/tests/NonExistentTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 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
@@ -33,9 +33,8 @@
/*
* @test
* @summary jpackage application version testing
- * @library ../../../../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile NonExistentTest.java
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=jdk.jpackage.tests.NonExistentTest
diff --git a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/PredefinedAppImageErrorTest.java b/test/jdk/tools/jpackage/share/jdk/jpackage/tests/PredefinedAppImageErrorTest.java
index d03c7cf28df..b01a78120db 100644
--- a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/PredefinedAppImageErrorTest.java
+++ b/test/jdk/tools/jpackage/share/jdk/jpackage/tests/PredefinedAppImageErrorTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -37,9 +37,8 @@
/*
* @test
* @summary Test jpackage output for erroneous input with --type "app-image" and --app-image
- * @library ../../../../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile PredefinedAppImageErrorTest.java
*
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
diff --git a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/UnicodeArgsTest.java b/test/jdk/tools/jpackage/share/jdk/jpackage/tests/UnicodeArgsTest.java
index 7b945f08731..29722086eec 100644
--- a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/UnicodeArgsTest.java
+++ b/test/jdk/tools/jpackage/share/jdk/jpackage/tests/UnicodeArgsTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 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
@@ -33,9 +33,8 @@
/*
* @test
* @summary test how app launcher handles unicode command line arguments
- * @library ../../../../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile UnicodeArgsTest.java
* @requires (os.family == "windows")
* @run main/othervm/timeout=720 -Xmx512m jdk.jpackage.test.Main
diff --git a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/VendorTest.java b/test/jdk/tools/jpackage/share/jdk/jpackage/tests/VendorTest.java
index eb469ea130a..b6e8f44dbf8 100644
--- a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/VendorTest.java
+++ b/test/jdk/tools/jpackage/share/jdk/jpackage/tests/VendorTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 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
@@ -54,12 +54,11 @@
/*
* @test
* @summary Test --vendor jpackage command option
- * @library ../../../../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @key jpackagePlatformPackage
* @requires (os.family == "windows")
* @requires jpackage.test.SQETest != null
* @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile VendorTest.java
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=jdk.jpackage.tests.VendorTest
@@ -68,12 +67,11 @@
/*
* @test
* @summary Test --vendor jpackage command option
- * @library ../../../../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @key jpackagePlatformPackage
* @requires (os.family != "mac")
* @requires jpackage.test.SQETest == null
* @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile VendorTest.java
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=jdk.jpackage.tests.VendorTest
diff --git a/test/jdk/tools/jpackage/windows/Win8282351Test.java b/test/jdk/tools/jpackage/windows/Win8282351Test.java
index 3b38b9e7f96..17ea5e7d9ab 100644
--- a/test/jdk/tools/jpackage/windows/Win8282351Test.java
+++ b/test/jdk/tools/jpackage/windows/Win8282351Test.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -39,11 +39,10 @@
/*
* @test
* @summary Test case for JDK-8248254
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @build jdk.jpackage.test.*
* @build Win8282351Test
* @requires (os.family == "windows")
- * @modules jdk.jpackage/jdk.jpackage.internal
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=Win8282351Test
*/
diff --git a/test/jdk/tools/jpackage/windows/Win8301247Test.java b/test/jdk/tools/jpackage/windows/Win8301247Test.java
index f61bb2b6e53..b0c11147a17 100644
--- a/test/jdk/tools/jpackage/windows/Win8301247Test.java
+++ b/test/jdk/tools/jpackage/windows/Win8301247Test.java
@@ -38,11 +38,10 @@
/*
* @test
* @summary Test case for JDK-8301247
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @build jdk.jpackage.test.*
* @build Win8301247Test
* @requires (os.family == "windows")
- * @modules jdk.jpackage/jdk.jpackage.internal
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=Win8301247Test
*/
diff --git a/test/jdk/tools/jpackage/windows/WinChildProcessTest.java b/test/jdk/tools/jpackage/windows/WinChildProcessTest.java
index a61191d8a4e..5565d3dc503 100644
--- a/test/jdk/tools/jpackage/windows/WinChildProcessTest.java
+++ b/test/jdk/tools/jpackage/windows/WinChildProcessTest.java
@@ -25,12 +25,10 @@
* @bug 8325203
* @summary Test that Jpackage windows executable application kills the launched 3rd party application
* when System.exit(0) is invoked along with terminating java program.
- * @library ../helpers
- * @library /test/lib
+ * @library /test/jdk/tools/jpackage/helpers
* @requires os.family == "windows"
* @build jdk.jpackage.test.*
* @build WinChildProcessTest
- * @modules jdk.jpackage/jdk.jpackage.internal
* @run main/othervm -Xmx512m jdk.jpackage.test.Main
* --jpt-run=WinChildProcessTest
*
diff --git a/test/jdk/tools/jpackage/windows/WinConsoleTest.java b/test/jdk/tools/jpackage/windows/WinConsoleTest.java
index 7a4e9ccfa5a..6a1e94a8e83 100644
--- a/test/jdk/tools/jpackage/windows/WinConsoleTest.java
+++ b/test/jdk/tools/jpackage/windows/WinConsoleTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -34,10 +34,9 @@
/*
* @test
* @summary jpackage with --win-console
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @build jdk.jpackage.test.*
* @requires (os.family == "windows")
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile WinConsoleTest.java
*
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
diff --git a/test/jdk/tools/jpackage/windows/WinDirChooserTest.java b/test/jdk/tools/jpackage/windows/WinDirChooserTest.java
index 355b89dba3e..a4db21dc618 100644
--- a/test/jdk/tools/jpackage/windows/WinDirChooserTest.java
+++ b/test/jdk/tools/jpackage/windows/WinDirChooserTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -36,12 +36,11 @@
/*
* @test
* @summary jpackage with --win-dir-chooser
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @key jpackagePlatformPackage
* @build jdk.jpackage.test.*
* @build WinDirChooserTest
* @requires (os.family == "windows")
- * @modules jdk.jpackage/jdk.jpackage.internal
* @run main/othervm/timeout=540 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=WinDirChooserTest
*/
diff --git a/test/jdk/tools/jpackage/windows/WinInstallerIconTest.java b/test/jdk/tools/jpackage/windows/WinInstallerIconTest.java
index 63194d6b256..f104abc9f5e 100644
--- a/test/jdk/tools/jpackage/windows/WinInstallerIconTest.java
+++ b/test/jdk/tools/jpackage/windows/WinInstallerIconTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 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
@@ -38,12 +38,11 @@
/*
* @test
* @summary jpackage with --icon parameter for exe installer
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @key jpackagePlatformPackage
* @build jdk.jpackage.test.*
* @build WinInstallerIconTest
* @requires (os.family == "windows")
- * @modules jdk.jpackage/jdk.jpackage.internal
* @run main/othervm/timeout=540 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=WinInstallerIconTest
*/
diff --git a/test/jdk/tools/jpackage/windows/WinInstallerUiTest.java b/test/jdk/tools/jpackage/windows/WinInstallerUiTest.java
index 99c6eb490d5..c6489ab68cf 100644
--- a/test/jdk/tools/jpackage/windows/WinInstallerUiTest.java
+++ b/test/jdk/tools/jpackage/windows/WinInstallerUiTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 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
@@ -39,12 +39,11 @@
/*
* @test
* @summary jpackage with --win-dir-chooser, --win-shortcut-prompt and --license parameters
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @key jpackagePlatformPackage
* @build jdk.jpackage.test.*
* @build WinInstallerUiTest
* @requires (os.family == "windows")
- * @modules jdk.jpackage/jdk.jpackage.internal
* @run main/othervm/timeout=720 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=WinInstallerUiTest
*/
diff --git a/test/jdk/tools/jpackage/windows/WinL10nTest.java b/test/jdk/tools/jpackage/windows/WinL10nTest.java
index a868fd5f051..d951b6f8832 100644
--- a/test/jdk/tools/jpackage/windows/WinL10nTest.java
+++ b/test/jdk/tools/jpackage/windows/WinL10nTest.java
@@ -42,12 +42,11 @@
/*
* @test
* @summary Custom l10n of msi installers in jpackage
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @key jpackagePlatformPackage
* @requires (jpackage.test.SQETest == null)
* @build jdk.jpackage.test.*
* @requires (os.family == "windows")
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile WinL10nTest.java
* @run main/othervm/timeout=1440 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=WinL10nTest
diff --git a/test/jdk/tools/jpackage/windows/WinLongVersionTest.java b/test/jdk/tools/jpackage/windows/WinLongVersionTest.java
index 5181a89e6b6..0d52da65630 100644
--- a/test/jdk/tools/jpackage/windows/WinLongVersionTest.java
+++ b/test/jdk/tools/jpackage/windows/WinLongVersionTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -70,12 +70,11 @@
/*
* @test
* @summary jpackage with long version number
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @key jpackagePlatformPackage
* @requires (jpackage.test.SQETest != null)
* @build jdk.jpackage.test.*
* @requires (os.family == "windows")
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile WinLongVersionTest.java
* @run main/othervm/timeout=540 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=WinLongVersionTest.test
@@ -84,12 +83,11 @@
/*
* @test
* @summary jpackage with long version number
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @key jpackagePlatformPackage
* @requires (jpackage.test.SQETest == null)
* @build jdk.jpackage.test.*
* @requires (os.family == "windows")
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile WinLongVersionTest.java
* @run main/othervm/timeout=540 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=WinLongVersionTest
diff --git a/test/jdk/tools/jpackage/windows/WinMenuGroupTest.java b/test/jdk/tools/jpackage/windows/WinMenuGroupTest.java
index 5950418f609..bdf5cf2f0a5 100644
--- a/test/jdk/tools/jpackage/windows/WinMenuGroupTest.java
+++ b/test/jdk/tools/jpackage/windows/WinMenuGroupTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -39,11 +39,10 @@
/*
* @test
* @summary jpackage with --win-menu and --win-menu-group
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @key jpackagePlatformPackage
* @build jdk.jpackage.test.*
* @requires (os.family == "windows")
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile WinMenuGroupTest.java
* @run main/othervm/timeout=540 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=WinMenuGroupTest
diff --git a/test/jdk/tools/jpackage/windows/WinMenuTest.java b/test/jdk/tools/jpackage/windows/WinMenuTest.java
index a28d28e24ec..8bacaa05470 100644
--- a/test/jdk/tools/jpackage/windows/WinMenuTest.java
+++ b/test/jdk/tools/jpackage/windows/WinMenuTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -36,11 +36,10 @@
/*
* @test
* @summary jpackage with --win-menu
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @key jpackagePlatformPackage
* @build jdk.jpackage.test.*
* @requires (os.family == "windows")
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile WinMenuTest.java
* @run main/othervm/timeout=540 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=WinMenuTest
diff --git a/test/jdk/tools/jpackage/windows/WinNoRestartTest.java b/test/jdk/tools/jpackage/windows/WinNoRestartTest.java
index 02b24591e92..c76f68476db 100644
--- a/test/jdk/tools/jpackage/windows/WinNoRestartTest.java
+++ b/test/jdk/tools/jpackage/windows/WinNoRestartTest.java
@@ -36,12 +36,11 @@
* @bug 8340311
* @summary Test that jpackage windows app launcher doesn't create child process
* if `win.norestart` property is set in the corresponding .cfg file
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @library /test/lib
* @requires os.family == "windows"
* @build jdk.jpackage.test.*
* @build WinNoRestartTest
- * @modules jdk.jpackage/jdk.jpackage.internal
* @run main/othervm -Xmx512m jdk.jpackage.test.Main
* --jpt-run=WinNoRestartTest
*/
diff --git a/test/jdk/tools/jpackage/windows/WinPerUserInstallTest.java b/test/jdk/tools/jpackage/windows/WinPerUserInstallTest.java
index 5d97bb9357e..48fca9644ea 100644
--- a/test/jdk/tools/jpackage/windows/WinPerUserInstallTest.java
+++ b/test/jdk/tools/jpackage/windows/WinPerUserInstallTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -37,11 +37,10 @@
/*
* @test
* @summary jpackage with --win-per-user-install, --win-menu, --win-menu-group
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @key jpackagePlatformPackage
* @build jdk.jpackage.test.*
* @requires (os.family == "windows")
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile WinPerUserInstallTest.java
* @run main/othervm/timeout=540 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=WinPerUserInstallTest
diff --git a/test/jdk/tools/jpackage/windows/WinRenameTest.java b/test/jdk/tools/jpackage/windows/WinRenameTest.java
index 4b0f8cdfe18..59107c43921 100644
--- a/test/jdk/tools/jpackage/windows/WinRenameTest.java
+++ b/test/jdk/tools/jpackage/windows/WinRenameTest.java
@@ -32,12 +32,11 @@
/*
* @test
* @summary jpackage test app can run after changing executable's extension
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @key jpackagePlatformPackage
* @build jdk.jpackage.test.*
* @build WinRenameTest
* @requires (os.family == "windows")
- * @modules jdk.jpackage/jdk.jpackage.internal
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=WinRenameTest
*/
diff --git a/test/jdk/tools/jpackage/windows/WinResourceTest.java b/test/jdk/tools/jpackage/windows/WinResourceTest.java
index 34111723457..72e805d0a48 100644
--- a/test/jdk/tools/jpackage/windows/WinResourceTest.java
+++ b/test/jdk/tools/jpackage/windows/WinResourceTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -40,10 +40,9 @@
/*
* @test
* @summary jpackage with --resource-dir
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @build jdk.jpackage.test.*
* @requires (os.family == "windows")
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile WinResourceTest.java
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=WinResourceTest
diff --git a/test/jdk/tools/jpackage/windows/WinScriptTest.java b/test/jdk/tools/jpackage/windows/WinScriptTest.java
index 775102cd014..296da482bb0 100644
--- a/test/jdk/tools/jpackage/windows/WinScriptTest.java
+++ b/test/jdk/tools/jpackage/windows/WinScriptTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -37,10 +37,9 @@
/*
* @test usage of scripts from resource dir
* @summary jpackage with
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @build jdk.jpackage.test.*
* @requires (os.family == "windows")
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile WinScriptTest.java
* @run main/othervm/timeout=720 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=WinScriptTest
diff --git a/test/jdk/tools/jpackage/windows/WinShortcutPromptTest.java b/test/jdk/tools/jpackage/windows/WinShortcutPromptTest.java
index 6c27b6852eb..e202f7e5d2a 100644
--- a/test/jdk/tools/jpackage/windows/WinShortcutPromptTest.java
+++ b/test/jdk/tools/jpackage/windows/WinShortcutPromptTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 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
@@ -37,12 +37,11 @@
/*
* @test
* @summary jpackage with --win-shortcut-prompt, --win-menu and --win-shortcut parameters
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @key jpackagePlatformPackage
* @build jdk.jpackage.test.*
* @build WinShortcutPromptTest
* @requires (os.family == "windows")
- * @modules jdk.jpackage/jdk.jpackage.internal
* @run main/othervm/timeout=720 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=WinShortcutPromptTest
*/
diff --git a/test/jdk/tools/jpackage/windows/WinShortcutTest.java b/test/jdk/tools/jpackage/windows/WinShortcutTest.java
index 3efa8b68817..1d2e7e762a5 100644
--- a/test/jdk/tools/jpackage/windows/WinShortcutTest.java
+++ b/test/jdk/tools/jpackage/windows/WinShortcutTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -37,11 +37,10 @@
/*
* @test
* @summary jpackage with --win-shortcut
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @key jpackagePlatformPackage
* @build jdk.jpackage.test.*
* @requires (os.family == "windows")
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile WinShortcutTest.java
* @run main/othervm/timeout=540 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=WinShortcutTest
diff --git a/test/jdk/tools/jpackage/windows/WinUpgradeUUIDTest.java b/test/jdk/tools/jpackage/windows/WinUpgradeUUIDTest.java
index 968ed94b345..c48803cfb5f 100644
--- a/test/jdk/tools/jpackage/windows/WinUpgradeUUIDTest.java
+++ b/test/jdk/tools/jpackage/windows/WinUpgradeUUIDTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -46,12 +46,11 @@
/*
* @test
* @summary jpackage with --win-upgrade-uuid and --app-version
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @key jpackagePlatformPackage
* @requires (jpackage.test.SQETest != null)
* @build jdk.jpackage.test.*
* @requires (os.family == "windows")
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile WinUpgradeUUIDTest.java
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=WinUpgradeUUIDTest.test
@@ -60,12 +59,11 @@
/*
* @test
* @summary jpackage with --win-upgrade-uuid and --app-version
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @key jpackagePlatformPackage
* @requires (jpackage.test.SQETest == null)
* @build jdk.jpackage.test.*
* @requires (os.family == "windows")
- * @modules jdk.jpackage/jdk.jpackage.internal
* @compile WinUpgradeUUIDTest.java
* @run main/othervm/timeout=540 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=WinUpgradeUUIDTest
diff --git a/test/jdk/tools/jpackage/windows/WinUrlTest.java b/test/jdk/tools/jpackage/windows/WinUrlTest.java
index 208d16d931a..f2e9528594b 100644
--- a/test/jdk/tools/jpackage/windows/WinUrlTest.java
+++ b/test/jdk/tools/jpackage/windows/WinUrlTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -40,12 +40,11 @@
* @test
* @summary jpackage with --about-url, --win-update-url and --win-help-url
* parameters
- * @library ../helpers
+ * @library /test/jdk/tools/jpackage/helpers
* @key jpackagePlatformPackage
* @build jdk.jpackage.test.*
* @build WinUrlTest
* @requires (os.family == "windows")
- * @modules jdk.jpackage/jdk.jpackage.internal
* @run main/othervm/timeout=720 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=WinUrlTest
*/
diff --git a/test/jdk/tools/launcher/Settings.java b/test/jdk/tools/launcher/Settings.java
index 2b581be5b26..fe5a9c3b157 100644
--- a/test/jdk/tools/launcher/Settings.java
+++ b/test/jdk/tools/launcher/Settings.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
/*
* @test
- * @bug 6994753 7123582 8305950 8281658 8310201 8311653
+ * @bug 6994753 7123582 8305950 8281658 8310201 8311653 8343804
* @summary tests -XshowSettings options
* @modules jdk.compiler
* jdk.zipfs
@@ -80,6 +80,7 @@ static void checkNotContains(TestResult tr, String str) {
private static final String SYSTEM_SETTINGS = "Operating System Metrics:";
private static final String METRICS_NOT_AVAILABLE_MSG = "No metrics available for this platform";
private static final String STACKSIZE_SETTINGS = "Stack Size:";
+ private static final String TIMEZONE_SETTINGS = "default timezone";
private static final String TZDATA_SETTINGS = "tzdata version";
private static final String ERR_MSG = "Unrecognized showSettings option:";
@@ -96,6 +97,7 @@ static void containsAllOptions(TestResult tr) {
checkNotContains(tr, SEC_SUMMARY_PROPS_SETTINGS);
checkContains(tr, SEC_PROVIDER_SETTINGS);
checkContains(tr, SEC_TLS_SETTINGS);
+ checkContains(tr, TIMEZONE_SETTINGS);
checkContains(tr, TZDATA_SETTINGS);
if (System.getProperty("os.name").contains("Linux")) {
checkContains(tr, SYSTEM_SETTINGS);
@@ -119,6 +121,7 @@ static void containsDefaultOptions(TestResult tr) {
checkContains(tr, SEC_SUMMARY_PROPS_SETTINGS);
checkContains(tr, SEC_PROVIDER_SETTINGS);
checkContains(tr, SEC_TLS_SETTINGS);
+ checkContains(tr, TIMEZONE_SETTINGS);
checkContains(tr, TZDATA_SETTINGS);
if (System.getProperty("os.name").contains("Linux")) {
checkContains(tr, SYSTEM_SETTINGS);
@@ -190,6 +193,7 @@ static void runTestOptionLocale() throws IOException {
checkContains(tr, LOCALE_SETTINGS);
checkContains(tr, AVAILABLE_LOCALES);
checkNotContains(tr, LOCALE_SUMMARY_SETTINGS);
+ checkContains(tr, TIMEZONE_SETTINGS);
checkContains(tr, TZDATA_SETTINGS);
}
diff --git a/test/jdk/tools/sincechecker/TEST.properties b/test/jdk/tools/sincechecker/TEST.properties
new file mode 100644
index 00000000000..27f669ef4ca
--- /dev/null
+++ b/test/jdk/tools/sincechecker/TEST.properties
@@ -0,0 +1,4 @@
+modules = \
+ jdk.compiler/com.sun.tools.javac.api \
+ jdk.compiler/com.sun.tools.javac.util \
+ jdk.compiler/com.sun.tools.javac.code
diff --git a/test/jdk/tools/sincechecker/modules/java_base/CheckSince_javaBase.java b/test/jdk/tools/sincechecker/modules/java.base/JavaBaseCheckSince.java
similarity index 81%
rename from test/jdk/tools/sincechecker/modules/java_base/CheckSince_javaBase.java
rename to test/jdk/tools/sincechecker/modules/java.base/JavaBaseCheckSince.java
index 6d0b9d0e932..64d5bf2465f 100644
--- a/test/jdk/tools/sincechecker/modules/java_base/CheckSince_javaBase.java
+++ b/test/jdk/tools/sincechecker/modules/java.base/JavaBaseCheckSince.java
@@ -24,11 +24,7 @@
/*
* @test
* @bug 8331051
- * @summary Test for `@since` for java.base module
- * @library /test/lib
- * /test/jdk/tools/sincechecker
- * @modules jdk.compiler/com.sun.tools.javac.api
- * jdk.compiler/com.sun.tools.javac.util
- * jdk.compiler/com.sun.tools.javac.code
+ * @summary Test for `@since` in java.base module
+ * @library /test/lib /test/jdk/tools/sincechecker
* @run main SinceChecker java.base --exclude java.lang.classfile
*/
diff --git a/test/jdk/tools/sincechecker/modules/java.compiler/JavaCompilerCheckSince.java b/test/jdk/tools/sincechecker/modules/java.compiler/JavaCompilerCheckSince.java
new file mode 100644
index 00000000000..c843c962d27
--- /dev/null
+++ b/test/jdk/tools/sincechecker/modules/java.compiler/JavaCompilerCheckSince.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8341399
+ * @summary Test for `@since` in java.compiler module
+ * @library /test/lib /test/jdk/tools/sincechecker
+ * @run main SinceChecker java.compiler
+ */
diff --git a/test/jdk/tools/sincechecker/modules/jdk.compiler/JdkCompilerCheckSince.java b/test/jdk/tools/sincechecker/modules/jdk.compiler/JdkCompilerCheckSince.java
new file mode 100644
index 00000000000..5eb819786e9
--- /dev/null
+++ b/test/jdk/tools/sincechecker/modules/jdk.compiler/JdkCompilerCheckSince.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8341399
+ * @summary Test for `@since` in jdk.compiler module
+ * @library /test/lib /test/jdk/tools/sincechecker
+ * @run main SinceChecker jdk.compiler
+ */
diff --git a/test/jdk/tools/sincechecker/modules/jdk.javadoc/JdkJavadocCheckSince.java b/test/jdk/tools/sincechecker/modules/jdk.javadoc/JdkJavadocCheckSince.java
new file mode 100644
index 00000000000..0e68d8213e9
--- /dev/null
+++ b/test/jdk/tools/sincechecker/modules/jdk.javadoc/JdkJavadocCheckSince.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8341399
+ * @summary Test for `@since` in jdk.javadoc module
+ * @library /test/lib /test/jdk/tools/sincechecker
+ * @run main SinceChecker jdk.javadoc
+ */
diff --git a/test/jdk/tools/sincechecker/modules/jdk.jdeps/JdkJdepsCheckSince.java b/test/jdk/tools/sincechecker/modules/jdk.jdeps/JdkJdepsCheckSince.java
new file mode 100644
index 00000000000..68439c49e24
--- /dev/null
+++ b/test/jdk/tools/sincechecker/modules/jdk.jdeps/JdkJdepsCheckSince.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8341399
+ * @summary Test for `@since` in jdk.jdeps module
+ * @library /test/lib /test/jdk/tools/sincechecker
+ * @run main SinceChecker jdk.jdeps
+ */
diff --git a/test/jdk/tools/sincechecker/modules/jdk.jshell/JdkJshellCheckSince.java b/test/jdk/tools/sincechecker/modules/jdk.jshell/JdkJshellCheckSince.java
new file mode 100644
index 00000000000..09f762cfeba
--- /dev/null
+++ b/test/jdk/tools/sincechecker/modules/jdk.jshell/JdkJshellCheckSince.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8341399
+ * @summary Test for `@since` in jdk.jshell module
+ * @library /test/lib /test/jdk/tools/sincechecker
+ * @run main SinceChecker jdk.jshell
+ */
diff --git a/test/langtools/tools/javac/annotations/ParameterArrayLimit.java b/test/langtools/tools/javac/annotations/ParameterArrayLimit.java
new file mode 100644
index 00000000000..6e782dd0b83
--- /dev/null
+++ b/test/langtools/tools/javac/annotations/ParameterArrayLimit.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Check if error is thrown if annotation array exceeds limit
+ * @library /tools/lib
+ * @run main ParameterArrayLimit
+ */
+
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.net.URI;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.text.MessageFormat;
+import java.util.Collections;
+import java.util.List;
+import javax.tools.*;
+
+import com.sun.source.util.JavacTask;
+
+public class ParameterArrayLimit {
+
+ public static void main(String[] args) throws IOException {
+
+ int[] values = new int[]{65536, 65537, 512000};
+ String[] retPolicies = {"RUNTIME", "CLASS"};
+
+ for (var value : values) {
+ Path tmpDir = Paths.get(System.getProperty("java.io.tmpdir"));
+
+ for (String retPolicy : retPolicies) {
+ String className = MessageFormat.format("ClassAnnotationWithLength_{0,number,#}_{1}.java",
+ value,
+ retPolicy);
+ Path out = tmpDir.resolve(className);
+ createAnnotationFile(out, value, retPolicy, false);
+ checkParamArrayWarning(className, out);
+ }
+
+ for (String retPolicy : retPolicies) {
+ String className = MessageFormat.format("TypeAnnotationWithLength_{0,number,#}_{1}.java",
+ value,
+ retPolicy);
+ Path out = tmpDir.resolve(className);
+ createAnnotationFile(out, value, retPolicy, true);
+ checkParamArrayWarning(className, out);
+ }
+ }
+ }
+
+ private static void checkParamArrayWarning(String className, Path out) throws IOException {
+ JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
+ DiagnosticCollector d = new DiagnosticCollector<>();
+ JavacTask task = (JavacTask) javaCompiler.getTask(
+ null,
+ null,
+ d,
+ null,
+ null,
+ Collections.singletonList(
+ SimpleJavaFileObject.forSource(
+ URI.create("myfo:/" + className),
+ Files.readString(out)
+ )));
+ task.call();
+
+ List> diagnosticList = d.getDiagnostics();
+ if (diagnosticList.isEmpty()) {
+ throw new RuntimeException("No diagnostic found");
+ }
+
+ for (Diagnostic extends JavaFileObject> diagnostic : diagnosticList) {
+ if (!(diagnostic.getKind() == Diagnostic.Kind.ERROR
+ && diagnostic.getCode()
+ .equals("compiler.err.annotation.array.too.large"))) {
+ throw new RuntimeException("Unexpected diagnostic: " + diagnostic.getMessage(null));
+ }
+ }
+ }
+
+ private static void createAnnotationFile(Path out, int value, String retPolicy, boolean isTypeAnnotation) throws IOException {
+ StringBuilder sb = new StringBuilder();
+
+ if (isTypeAnnotation) {
+ sb.append(MessageFormat.format("""
+ import java.lang.annotation.*;
+ @Retention(RetentionPolicy.{0})
+ @Target(ElementType.TYPE_USE)
+ @interface TypeAnno '{'
+ long[] arr();
+ '}'
+ """, retPolicy));
+ sb.append(MessageFormat.format("""
+ public class TypeAnnotationWithLength_{0,number,#}_{1}'{'
+ @TypeAnno(arr = '{'
+ """, value, retPolicy));
+ } else {
+ sb.append(MessageFormat.format("""
+ import java.lang.annotation.*;
+ @Retention(RetentionPolicy.{0})
+ @interface MyCustomAnno '{'
+ String value() default "default value";
+ long[] arr();
+ int count() default 0;
+ '}'
+ """, retPolicy));
+ sb.append(MessageFormat.format("""
+ public class ClassAnnotationWithLength_{0,number,#}_{1}'{'
+ @MyCustomAnno(value = "custom", count = 42, arr = '{'
+ """, value, retPolicy));
+ }
+
+ sb.append("-1,".repeat(Math.max(0, value - 1)));
+ sb.append("-1})");
+
+ sb.append("""
+ static int x = 3;
+
+ public void myAnnotatedMethod() { }
+ }
+ """);
+
+ try (BufferedWriter bufferedWriter = Files.newBufferedWriter(out)) {
+ bufferedWriter.write(sb.toString());
+ }
+ }
+}
diff --git a/test/langtools/tools/javac/diags/examples.not-yet.txt b/test/langtools/tools/javac/diags/examples.not-yet.txt
index 4a7cfa82f60..ce67d10e1e0 100644
--- a/test/langtools/tools/javac/diags/examples.not-yet.txt
+++ b/test/langtools/tools/javac/diags/examples.not-yet.txt
@@ -16,6 +16,7 @@ compiler.err.limit.code # Code
compiler.err.limit.code.too.large.for.try.stmt # Gen
compiler.err.limit.dimensions # Gen
compiler.err.limit.locals # Code
+compiler.err.annotation.array.too.large # Code
compiler.err.limit.parameters # Gen
compiler.err.limit.pool # Gen,JavaCompiler
compiler.err.limit.pool.in.class # UNUSED?
diff --git a/test/langtools/tools/javac/newlines/NewLineTest.java b/test/langtools/tools/javac/newlines/NewLineTest.java
index b1567d363b0..35c60e59653 100644
--- a/test/langtools/tools/javac/newlines/NewLineTest.java
+++ b/test/langtools/tools/javac/newlines/NewLineTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -58,8 +58,9 @@ public static void main(String args[]) throws Exception {
.options("-J-Dline.separator='@'")
.run(Task.Expect.FAIL);
- List lines = Files.readAllLines(javacOutput.toPath(),
- Charset.defaultCharset());
+ String encoding = System.getProperty("native.encoding");
+ Charset cs = (encoding != null) ? Charset.forName(encoding) : Charset.defaultCharset();
+ List lines = Files.readAllLines(javacOutput.toPath(), cs);
if (lines.size() != 1) {
throw new AssertionError("The compiler output should have one line only");
}
diff --git a/test/langtools/tools/javac/options/system/SystemSunProprietary.java b/test/langtools/tools/javac/options/system/SystemSunProprietary.java
new file mode 100644
index 00000000000..0a16305aaba
--- /dev/null
+++ b/test/langtools/tools/javac/options/system/SystemSunProprietary.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2024, Alphabet LLC. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8331081
+ * @summary Verify 'internal proprietary API' diagnostics if --system is configured
+ * @library /tools/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api jdk.compiler/com.sun.tools.javac.main
+ * jdk.compiler/com.sun.tools.javac.jvm jdk.jdeps/com.sun.tools.javap
+ * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask toolbox.JavapTask toolbox.TestRunner
+ * @run main SystemSunProprietary
+ */
+import toolbox.JavacTask;
+import toolbox.Task;
+import toolbox.Task.Expect;
+import toolbox.TestRunner;
+import toolbox.ToolBox;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.List;
+
+public class SystemSunProprietary extends TestRunner {
+
+ private final ToolBox tb = new ToolBox();
+
+ public SystemSunProprietary() {
+ super(System.err);
+ }
+
+ public static void main(String... args) throws Exception {
+ new SystemSunProprietary().runTests();
+ }
+
+ @Test
+ public void testUnsafe(Path base) throws IOException {
+ Path src = base.resolve("src");
+ tb.writeJavaFiles(
+ src,
+ "module m { requires jdk.unsupported; }",
+ "package test; public class Test { sun.misc.Unsafe unsafe; } ");
+ Path classes = base.resolve("classes");
+ tb.createDirectories(classes);
+
+ List log;
+ List expected =
+ Arrays.asList(
+ "Test.java:1:43: compiler.warn.sun.proprietary: sun.misc.Unsafe",
+ "1 warning");
+
+ log =
+ new JavacTask(tb)
+ .options("-XDrawDiagnostics")
+ .outdir(classes)
+ .files(tb.findJavaFiles(src))
+ .run(Expect.SUCCESS)
+ .writeAll()
+ .getOutputLines(Task.OutputKind.DIRECT);
+
+ if (!expected.equals(log)) {
+ throw new AssertionError("Unexpected output: " + log);
+ }
+
+ log =
+ new JavacTask(tb)
+ .options("-XDrawDiagnostics", "--system", System.getProperty("java.home"))
+ .outdir(classes)
+ .files(tb.findJavaFiles(src))
+ .run(Expect.SUCCESS)
+ .writeAll()
+ .getOutputLines(Task.OutputKind.DIRECT);
+
+ if (!expected.equals(log)) {
+ throw new AssertionError("Unexpected output: " + log);
+ }
+
+ // Create a valid argument to system that isn't the current java.home
+ Path originalSystem = Path.of(System.getProperty("java.home"));
+ Path system = base.resolve("system");
+ for (String path : List.of("release", "lib/modules", "lib/jrt-fs.jar")) {
+ Path to = system.resolve(path);
+ Files.createDirectories(to.getParent());
+ Files.copy(originalSystem.resolve(path), to);
+ }
+
+ log =
+ new JavacTask(tb)
+ .options("-XDrawDiagnostics", "--system", system.toString())
+ .outdir(classes)
+ .files(tb.findJavaFiles(src))
+ .run(Expect.SUCCESS)
+ .writeAll()
+ .getOutputLines(Task.OutputKind.DIRECT);
+
+ if (!expected.equals(log)) {
+ throw new AssertionError("Unexpected output: " + log);
+ }
+ }
+
+ protected void runTests() throws Exception {
+ runTests(m -> new Object[] {Paths.get(m.getName())});
+ }
+}
diff --git a/test/langtools/tools/javac/patterns/PrimitiveTypesInTestingContextErasure.java b/test/langtools/tools/javac/patterns/PrimitiveTypesInTestingContextErasure.java
new file mode 100644
index 00000000000..40289f31d56
--- /dev/null
+++ b/test/langtools/tools/javac/patterns/PrimitiveTypesInTestingContextErasure.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+/*
+ * @test
+ * @bug 8341408
+ * @summary Compiler Implementation for Primitive types in patterns, instanceof, and switch (Second Preview)
+ * @enablePreview
+ */
+
+import java.util.List;
+
+public class PrimitiveTypesInTestingContextErasure {
+ public static void main(String[] args) {
+ erasureSwitch();
+ erasureInstanceofTypeComparisonOperator();
+ erasureInstanceofPatternMatchingOperator();
+
+ pollutedInstanceofPatternMatchingOperatorReference();
+ pollutedInstanceofPatternMatchingOperator();
+ pollutedInstanceofTypeComparisonOperator();
+ pollutedSwitch();
+ }
+
+ public static void erasureSwitch() {
+ List ls = List.of((short) 42);
+ Short s = 42;
+
+ assertTrue(switch(ls.get(0)) {
+ case int _ -> true; // Short to int
+ default -> false;
+ });
+ }
+
+ public static void erasureInstanceofTypeComparisonOperator() {
+ List ls = List.of((short) 42);
+
+ assertTrue(ls.get(0) instanceof int); // Short to int
+ }
+
+ public static void erasureInstanceofPatternMatchingOperator() {
+ List ls = List.of((short) 42);
+
+ assertTrue(ls.get(0) instanceof int i); // Short to int
+ }
+
+ public static void pollutedInstanceofPatternMatchingOperator() {
+ List ls = (List) List.of("42");
+
+ assertTrue(!(ls.get(0) instanceof int i));
+ }
+
+ public static void pollutedInstanceofTypeComparisonOperator() {
+ List ls = (List) List.of("42");
+
+ assertTrue(!(ls.get(0) instanceof int));
+ }
+
+ public static void pollutedInstanceofPatternMatchingOperatorReference() {
+ List ls = (List) List.of("42");
+
+ assertTrue(!(ls.get(0) instanceof Short));
+ }
+
+ public static void pollutedSwitch() {
+ List ls = (List) List.of("42");
+
+ try {
+ var res = switch(ls.get(0)) {
+ case int _ -> true;
+ default -> false;
+ };
+ throw new AssertionError("Expected: ClassCastException");
+ } catch (ClassCastException e) {
+ ;
+ }
+ }
+
+ static void assertTrue(boolean actual) {
+ if (!actual) {
+ throw new AssertionError("Expected: true, but got false");
+ }
+ }
+}
diff --git a/test/langtools/tools/javac/sealed/SealedCompilationTests.java b/test/langtools/tools/javac/sealed/SealedCompilationTests.java
index 5ad70d102d6..dee64fd0865 100644
--- a/test/langtools/tools/javac/sealed/SealedCompilationTests.java
+++ b/test/langtools/tools/javac/sealed/SealedCompilationTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1178,6 +1178,39 @@ void test () {
I[] i = (I[]) c;
}
}
+ """,
+ """
+ class Test {
+ sealed interface I permits C1 {}
+ non-sealed class C1 implements I {}
+ class C2 extends C1 {}
+ class C3 {}
+ I m(int s, C3 c3) {
+ I i = (I)c3;
+ }
+ }
+ """,
+ """
+ class Test {
+ sealed interface I permits C1 {}
+ non-sealed class C1 implements I {}
+ class C2 extends C1 {}
+ class C3 {}
+ I m(int s, C3 c3) {
+ I i = (C1)c3;
+ }
+ }
+ """,
+ """
+ class Test {
+ sealed interface I permits C1 {}
+ non-sealed class C1 implements I {}
+ class C2 extends C1 {}
+ class C3 {}
+ I m(int s, C3 c3) {
+ I i = (C2)c3;
+ }
+ }
"""
)) {
assertFail("compiler.err.prob.found.req", s);
diff --git a/test/lib-test/jdk/test/lib/security/SeededSecureRandomTest.java b/test/lib-test/jdk/test/lib/security/SeededSecureRandomTest.java
index f5f74a16f72..2520ac6c5a2 100644
--- a/test/lib-test/jdk/test/lib/security/SeededSecureRandomTest.java
+++ b/test/lib-test/jdk/test/lib/security/SeededSecureRandomTest.java
@@ -20,14 +20,13 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
-package jdk.test.lib.security;
-
import jdk.test.lib.Asserts;
+import jdk.test.lib.security.SeededSecureRandom;
/*
* @test
* @library /test/lib
- * @run main/othervm jdk.test.lib.security.SeededSecureRandomTest
+ * @run main/othervm SeededSecureRandomTest
*/
public class SeededSecureRandomTest {
diff --git a/test/micro/org/openjdk/bench/java/lang/StringBuilders.java b/test/micro/org/openjdk/bench/java/lang/StringBuilders.java
index e7579d72ecb..ed5c0d30db8 100644
--- a/test/micro/org/openjdk/bench/java/lang/StringBuilders.java
+++ b/test/micro/org/openjdk/bench/java/lang/StringBuilders.java
@@ -226,17 +226,66 @@ public String toStringCharWithInt8() {
@Benchmark
- public String toStringCharWithBool8() {
- StringBuilder result = new StringBuilder();
- result.append(true);
- result.append(false);
- result.append(true);
- result.append(true);
- result.append(false);
- result.append(true);
- result.append(false);
- result.append(false);
- return result.toString();
+ public int appendWithBool8Latin1() {
+ StringBuilder buf = sbLatin1;
+ buf.setLength(0);
+ buf.append(true);
+ buf.append(false);
+ buf.append(true);
+ buf.append(true);
+ buf.append(false);
+ buf.append(true);
+ buf.append(false);
+ buf.append(false);
+ return buf.length();
+ }
+
+
+ @Benchmark
+ public int appendWithBool8Utf16() {
+ StringBuilder buf = sbUtf16;
+ buf.setLength(0);
+ buf.append(true);
+ buf.append(false);
+ buf.append(true);
+ buf.append(true);
+ buf.append(false);
+ buf.append(true);
+ buf.append(false);
+ buf.append(false);
+ return buf.length();
+ }
+
+
+ @Benchmark
+ public int appendWithNull8Latin1() {
+ StringBuilder buf = sbLatin1;
+ buf.setLength(0);
+ buf.append((String) null);
+ buf.append((String) null);
+ buf.append((String) null);
+ buf.append((String) null);
+ buf.append((String) null);
+ buf.append((String) null);
+ buf.append((String) null);
+ buf.append((String) null);
+ return buf.length();
+ }
+
+
+ @Benchmark
+ public int appendWithNull8Utf16() {
+ StringBuilder buf = sbUtf16;
+ buf.setLength(0);
+ buf.append((String) null);
+ buf.append((String) null);
+ buf.append((String) null);
+ buf.append((String) null);
+ buf.append((String) null);
+ buf.append((String) null);
+ buf.append((String) null);
+ buf.append((String) null);
+ return buf.length();
}
diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/AllocFromTest.java b/test/micro/org/openjdk/bench/java/lang/foreign/AllocFromTest.java
index 520c1ad5a9b..b627c4de089 100644
--- a/test/micro/org/openjdk/bench/java/lang/foreign/AllocFromTest.java
+++ b/test/micro/org/openjdk/bench/java/lang/foreign/AllocFromTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -48,7 +48,7 @@
@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@State(org.openjdk.jmh.annotations.Scope.Thread)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
-@Fork(value = 3, jvmArgs = { "--enable-native-access=ALL-UNNAMED" })
+@Fork(value = 3, jvmArgs = { "--enable-native-access=ALL-UNNAMED", "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED" })
public class AllocFromTest extends CLayouts {
Arena arena = Arena.ofConfined();
diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/AllocTest.java b/test/micro/org/openjdk/bench/java/lang/foreign/AllocTest.java
index d9b268a1846..a70861a0dda 100644
--- a/test/micro/org/openjdk/bench/java/lang/foreign/AllocTest.java
+++ b/test/micro/org/openjdk/bench/java/lang/foreign/AllocTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -50,7 +50,7 @@
@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@State(org.openjdk.jmh.annotations.Scope.Thread)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
-@Fork(value = 3, jvmArgs = { "--enable-native-access=ALL-UNNAMED" })
+@Fork(value = 3, jvmArgs = { "--enable-native-access=ALL-UNNAMED", "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED" })
public class AllocTest extends CLayouts {
Arena arena = Arena.ofConfined();
diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/BulkOps.java b/test/micro/org/openjdk/bench/java/lang/foreign/BulkOps.java
index 3546fa1cca4..6a1dd05b615 100644
--- a/test/micro/org/openjdk/bench/java/lang/foreign/BulkOps.java
+++ b/test/micro/org/openjdk/bench/java/lang/foreign/BulkOps.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 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
@@ -35,7 +35,7 @@
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.TearDown;
import org.openjdk.jmh.annotations.Warmup;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
import java.lang.foreign.Arena;
import java.lang.foreign.MemorySegment;
@@ -51,7 +51,7 @@
@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@State(org.openjdk.jmh.annotations.Scope.Thread)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
-@Fork(3)
+@Fork(value = 3, jvmArgs = { "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED" })
public class BulkOps {
static final Unsafe unsafe = Utils.unsafe;
diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverConstant.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverConstant.java
index 05e764d7fe3..a725b427038 100644
--- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverConstant.java
+++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverConstant.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 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
@@ -33,7 +33,7 @@
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.TearDown;
import org.openjdk.jmh.annotations.Warmup;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.Arena;
@@ -48,7 +48,7 @@
@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@State(org.openjdk.jmh.annotations.Scope.Thread)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
-@Fork(3)
+@Fork(value = 3, jvmArgs = { "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED" })
public class LoopOverConstant extends JavaLayouts {
static final Unsafe unsafe = Utils.unsafe;
diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNew.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNew.java
index db456f57aaa..c0d16f9818d 100644
--- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNew.java
+++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNew.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -34,7 +34,7 @@
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.TearDown;
import org.openjdk.jmh.annotations.Warmup;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
@@ -47,7 +47,7 @@
@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@State(org.openjdk.jmh.annotations.Scope.Thread)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
-@Fork(3)
+@Fork(value = 3, jvmArgs = { "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED" })
public class LoopOverNew extends JavaLayouts {
static final Unsafe unsafe = Utils.unsafe;
diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNewHeap.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNewHeap.java
index feafb721028..e869a92c4d8 100644
--- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNewHeap.java
+++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNewHeap.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 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
@@ -35,7 +35,7 @@
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.TearDown;
import org.openjdk.jmh.annotations.Warmup;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
import java.nio.IntBuffer;
import java.util.concurrent.TimeUnit;
@@ -47,7 +47,7 @@
@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@State(org.openjdk.jmh.annotations.Scope.Thread)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
-@Fork(3)
+@Fork(value = 3, jvmArgs = { "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED" })
public class LoopOverNewHeap extends JavaLayouts {
static final Unsafe unsafe = Utils.unsafe;
diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstant.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstant.java
index 91ce8faec38..668a6ab8e30 100644
--- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstant.java
+++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstant.java
@@ -36,7 +36,7 @@
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.TearDown;
import org.openjdk.jmh.annotations.Warmup;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
@@ -51,7 +51,7 @@
@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@State(org.openjdk.jmh.annotations.Scope.Thread)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
-@Fork(3)
+@Fork(value = 3, jvmArgs = { "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED" })
public class LoopOverNonConstant extends JavaLayouts {
static final Unsafe unsafe = Utils.unsafe;
diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantAsType.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantAsType.java
index 834d051cff0..e7c08512db3 100644
--- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantAsType.java
+++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantAsType.java
@@ -37,7 +37,7 @@
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.TearDown;
import org.openjdk.jmh.annotations.Warmup;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
@@ -54,7 +54,7 @@
@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@State(org.openjdk.jmh.annotations.Scope.Thread)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
-@Fork(value = 3, jvmArgs = { "-XX:-TieredCompilation" })
+@Fork(value = 3, jvmArgs = { "-XX:-TieredCompilation", "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED" })
public class LoopOverNonConstantAsType extends JavaLayouts {
static final Unsafe unsafe = Utils.unsafe;
diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantFP.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantFP.java
index 251d5621bcf..7bc39f5e372 100644
--- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantFP.java
+++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantFP.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 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
@@ -35,7 +35,7 @@
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.TearDown;
import org.openjdk.jmh.annotations.Warmup;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
@@ -48,7 +48,7 @@
@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@State(org.openjdk.jmh.annotations.Scope.Thread)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
-@Fork(3)
+@Fork(value = 3, jvmArgs = {"--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED" })
public class LoopOverNonConstantFP {
static final Unsafe unsafe = Utils.unsafe;
diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantHeap.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantHeap.java
index 7db3bc14665..baaa1909718 100644
--- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantHeap.java
+++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantHeap.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 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
@@ -36,7 +36,7 @@
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.TearDown;
import org.openjdk.jmh.annotations.Warmup;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
@@ -49,7 +49,7 @@
@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@State(org.openjdk.jmh.annotations.Scope.Thread)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
-@Fork(3)
+@Fork(value = 3, jvmArgs = { "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED" })
public class LoopOverNonConstantHeap extends JavaLayouts {
static final Unsafe unsafe = Utils.unsafe;
diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantMapped.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantMapped.java
index f1b9a81091f..409b837ee8b 100644
--- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantMapped.java
+++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantMapped.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 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
@@ -35,7 +35,7 @@
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.TearDown;
import org.openjdk.jmh.annotations.Warmup;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
import java.io.File;
import java.io.IOException;
@@ -55,7 +55,7 @@
@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@State(org.openjdk.jmh.annotations.Scope.Thread)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
-@Fork(3)
+@Fork(value = 3, jvmArgs = { "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED" })
public class LoopOverNonConstantMapped extends JavaLayouts {
static final Unsafe unsafe = Utils.unsafe;
diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantShared.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantShared.java
index c64391f242b..2c1a5672749 100644
--- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantShared.java
+++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantShared.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 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
@@ -35,7 +35,7 @@
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.TearDown;
import org.openjdk.jmh.annotations.Warmup;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
@@ -48,7 +48,7 @@
@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@State(org.openjdk.jmh.annotations.Scope.Thread)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
-@Fork(3)
+@Fork(value = 3, jvmArgs = { "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED" })
public class LoopOverNonConstantShared extends JavaLayouts {
static final Unsafe unsafe = Utils.unsafe;
diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverPollutedBuffer.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverPollutedBuffer.java
index 434d75bcd84..c9060adc18b 100644
--- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverPollutedBuffer.java
+++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverPollutedBuffer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 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
@@ -33,7 +33,7 @@
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.TearDown;
import org.openjdk.jmh.annotations.Warmup;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
@@ -47,7 +47,7 @@
@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@State(org.openjdk.jmh.annotations.Scope.Thread)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
-@Fork(3)
+@Fork(value = 3, jvmArgs = { "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED" })
public class LoopOverPollutedBuffer {
static final int ELEM_SIZE = 1_000_000;
diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverPollutedSegments.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverPollutedSegments.java
index 2077a47d86a..b0fddeeb8da 100644
--- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverPollutedSegments.java
+++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverPollutedSegments.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 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
@@ -35,7 +35,7 @@
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.TearDown;
import org.openjdk.jmh.annotations.Warmup;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
import java.util.concurrent.TimeUnit;
@@ -46,7 +46,7 @@
@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@State(org.openjdk.jmh.annotations.Scope.Thread)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
-@Fork(3)
+@Fork(value = 3, jvmArgs = { "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED" })
public class LoopOverPollutedSegments extends JavaLayouts {
static final int ELEM_SIZE = 1_000_000;
diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverRandom.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverRandom.java
new file mode 100644
index 00000000000..392ac6d667b
--- /dev/null
+++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverRandom.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.openjdk.bench.java.lang.foreign;
+
+import java.lang.foreign.Arena;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.ValueLayout;
+import java.util.Random;
+import java.util.concurrent.TimeUnit;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.CompilerControl;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.Warmup;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.TearDown;
+import jdk.internal.misc.Unsafe;
+
+@BenchmarkMode(Mode.AverageTime)
+@Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS)
+@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
+@State(org.openjdk.jmh.annotations.Scope.Thread)
+@OutputTimeUnit(TimeUnit.MICROSECONDS)
+@Fork(value = 3, jvmArgsAppend = { "--enable-native-access=ALL-UNNAMED", "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED"})
+public class LoopOverRandom extends JavaLayouts {
+ static final int SEED = 0;
+
+ static final long ELEM_SIZE = ValueLayout.JAVA_INT.byteSize();
+ static final int ELEM_COUNT = 1_000;
+ static final long ALLOC_SIZE = ELEM_COUNT * ELEM_SIZE;
+
+ static final Unsafe unsafe = Utils.unsafe;
+
+ Arena arena;
+ MemorySegment segment;
+ int[] indices;
+
+ static final MemorySegment ALL = MemorySegment.NULL.reinterpret(Long.MAX_VALUE);
+
+ @Setup
+ public void setup() {
+ indices = new Random(SEED).ints(0, ELEM_COUNT).limit(ELEM_COUNT).toArray();
+ arena = Arena.ofConfined();
+ segment = arena.allocate(ALLOC_SIZE);
+ for (int i = 0; i < ELEM_COUNT; i++) {
+ segment.setAtIndex(ValueLayout.JAVA_INT, i, i);
+ }
+ }
+
+ @TearDown
+ public void tearDown() {
+ arena.close();
+ }
+
+ @Benchmark
+ public long segment_loop() {
+ int sum = 0;
+ for (int i = 0; i < ELEM_COUNT; i++) {
+ sum += segment.getAtIndex(ValueLayout.JAVA_INT_UNALIGNED, indices[i]);
+ target_dontInline();
+ }
+ return sum;
+ }
+
+ @Benchmark
+ public long segment_loop_all() {
+ int sum = 0;
+ for (int i = 0; i < ELEM_COUNT; i++) {
+ sum += ALL.get(ValueLayout.JAVA_INT_UNALIGNED, segment.address() + indices[i] * ELEM_SIZE);
+ target_dontInline();
+ }
+ return sum;
+ }
+
+ @Benchmark
+ public long segment_loop_asUnchecked() {
+ int sum = 0;
+ for (int i = 0; i < ELEM_COUNT; i++) {
+ sum += asUnchecked(segment).getAtIndex(ValueLayout.JAVA_INT_UNALIGNED, indices[i]);
+ target_dontInline();
+ }
+ return sum;
+ }
+
+ @Benchmark
+ public long unsafe_loop() {
+ int sum = 0;
+ for (int i = 0; i < ELEM_COUNT; i++) {
+ sum += unsafe.getInt(segment.address() + indices[i] * ELEM_SIZE);
+ target_dontInline();
+ }
+ return sum;
+ }
+
+ MemorySegment asUnchecked(MemorySegment segment) {
+ return MemorySegment.ofAddress(segment.address()).reinterpret(Long.MAX_VALUE);
+ }
+
+ @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+ public void target_dontInline() {
+ // this method was intentionally left blank
+ }
+}
diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/MemorySegmentCopyUnsafe.java b/test/micro/org/openjdk/bench/java/lang/foreign/MemorySegmentCopyUnsafe.java
index c5cdd26016d..a0b57b5662c 100644
--- a/test/micro/org/openjdk/bench/java/lang/foreign/MemorySegmentCopyUnsafe.java
+++ b/test/micro/org/openjdk/bench/java/lang/foreign/MemorySegmentCopyUnsafe.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -34,7 +34,7 @@
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Warmup;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
import java.util.concurrent.TimeUnit;
@@ -45,7 +45,7 @@
@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@State(org.openjdk.jmh.annotations.Scope.Thread)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
-@Fork(value = 3, jvmArgs = {"--enable-native-access=ALL-UNNAMED"})
+@Fork(value = 3, jvmArgs = {"--enable-native-access=ALL-UNNAMED", "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED"})
public class MemorySegmentCopyUnsafe {
static final Unsafe UNSAFE = Utils.unsafe;
diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/MemorySegmentGetUnsafe.java b/test/micro/org/openjdk/bench/java/lang/foreign/MemorySegmentGetUnsafe.java
index 31303e51141..b18696a1424 100644
--- a/test/micro/org/openjdk/bench/java/lang/foreign/MemorySegmentGetUnsafe.java
+++ b/test/micro/org/openjdk/bench/java/lang/foreign/MemorySegmentGetUnsafe.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -39,7 +39,7 @@
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Warmup;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
import java.util.concurrent.TimeUnit;
@@ -50,7 +50,7 @@
@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@State(org.openjdk.jmh.annotations.Scope.Thread)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
-@Fork(value = 3, jvmArgs = {"--enable-native-access=ALL-UNNAMED"})
+@Fork(value = 3, jvmArgs = {"--enable-native-access=ALL-UNNAMED", "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED"})
public class MemorySegmentGetUnsafe {
static final Unsafe UNSAFE = Utils.unsafe;
diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/MemorySegmentZeroUnsafe.java b/test/micro/org/openjdk/bench/java/lang/foreign/MemorySegmentZeroUnsafe.java
index 6a52ed3fc5b..09e5a1e3e77 100644
--- a/test/micro/org/openjdk/bench/java/lang/foreign/MemorySegmentZeroUnsafe.java
+++ b/test/micro/org/openjdk/bench/java/lang/foreign/MemorySegmentZeroUnsafe.java
@@ -23,7 +23,7 @@
package org.openjdk.bench.java.lang.foreign;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Mode;
@@ -44,7 +44,7 @@
@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@State(org.openjdk.jmh.annotations.Scope.Thread)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
-@Fork(value = 3, jvmArgs = {"--enable-native-access=ALL-UNNAMED"})
+@Fork(value = 3, jvmArgs = {"--enable-native-access=ALL-UNNAMED", "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED"})
public class MemorySegmentZeroUnsafe {
static final Unsafe UNSAFE = Utils.unsafe;
diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/ParallelSum.java b/test/micro/org/openjdk/bench/java/lang/foreign/ParallelSum.java
index 2fcd444989f..42c6e481a72 100644
--- a/test/micro/org/openjdk/bench/java/lang/foreign/ParallelSum.java
+++ b/test/micro/org/openjdk/bench/java/lang/foreign/ParallelSum.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
import java.lang.foreign.*;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
@@ -52,7 +52,7 @@
@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@State(org.openjdk.jmh.annotations.Scope.Thread)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
-@Fork(3)
+@Fork(value = 3, jvmArgs = {"--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED"})
public class ParallelSum extends JavaLayouts {
final static int CARRIER_SIZE = 4;
diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/SegmentBulkFill.java b/test/micro/org/openjdk/bench/java/lang/foreign/SegmentBulkFill.java
index eb19fc56ac2..96cf62cc5f6 100644
--- a/test/micro/org/openjdk/bench/java/lang/foreign/SegmentBulkFill.java
+++ b/test/micro/org/openjdk/bench/java/lang/foreign/SegmentBulkFill.java
@@ -38,6 +38,7 @@
import java.lang.foreign.Arena;
import java.lang.foreign.MemorySegment;
+import java.lang.foreign.ValueLayout;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
@@ -74,6 +75,20 @@ public void arraysFill() {
Arrays.fill(array, (byte) 0);
}
+ @Benchmark
+ public void arraysFillLoop() {
+ for (int i = 0; i < array.length; i++) {
+ array[i] = 0;
+ }
+ }
+
+ @Benchmark
+ public void bufferFillLoop() {
+ for (int i = 0; i < array.length; i++) {
+ buffer.put(i, (byte)0);
+ }
+ }
+
@Fork(value = 3, jvmArgs = {"-Djava.lang.foreign.native.threshold.power.fill=31"})
@Benchmark
public void heapSegmentFillJava() {
@@ -86,6 +101,13 @@ public void heapSegmentFillUnsafe() {
heapSegment.fill((byte) 0);
}
+ @Benchmark
+ public void heapSegmentFillLoop() {
+ for (long i = 0; i < heapSegment.byteSize(); i++) {
+ heapSegment.set(ValueLayout.JAVA_BYTE, i, (byte) 0);
+ }
+ }
+
@Fork(value = 3, jvmArgs = {"-Djava.lang.foreign.native.threshold.power.fill=31"})
@Benchmark
public void nativeSegmentFillJava() {
@@ -98,6 +120,13 @@ public void nativeSegmentFillUnsafe() {
nativeSegment.fill((byte) 0);
}
+ @Benchmark
+ public void nativeSegmentFillLoop() {
+ for (long i = 0; i < nativeSegment.byteSize(); i++) {
+ nativeSegment.set(ValueLayout.JAVA_BYTE, i, (byte) 0);
+ }
+ }
+
@Fork(value = 3, jvmArgs = {"-Djava.lang.foreign.native.threshold.power.fill=31"})
@Benchmark
public void unalignedSegmentFillJava() {
@@ -110,4 +139,11 @@ public void unalignedSegmentFillUnsafe() {
unalignedSegment.fill((byte) 0);
}
+ @Benchmark
+ public void unalignedSegmentFillLoop() {
+ for (long i = 0; i < unalignedSegment.byteSize(); i++) {
+ unalignedSegment.set(ValueLayout.JAVA_BYTE, i, (byte) 0);
+ }
+ }
+
}
diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/UnrolledAccess.java b/test/micro/org/openjdk/bench/java/lang/foreign/UnrolledAccess.java
index 36c2ba32887..a52f9181350 100644
--- a/test/micro/org/openjdk/bench/java/lang/foreign/UnrolledAccess.java
+++ b/test/micro/org/openjdk/bench/java/lang/foreign/UnrolledAccess.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 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
@@ -30,7 +30,7 @@
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
import java.util.concurrent.TimeUnit;
import static java.lang.foreign.ValueLayout.*;
@@ -40,7 +40,7 @@
@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@State(org.openjdk.jmh.annotations.Scope.Thread)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
-@Fork(value = 3, jvmArgs = { "--enable-native-access=ALL-UNNAMED" })
+@Fork(value = 3, jvmArgs = {"--enable-native-access=ALL-UNNAMED", "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED"})
public class UnrolledAccess extends JavaLayouts {
static final Unsafe U = Utils.unsafe;
diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/Utils.java b/test/micro/org/openjdk/bench/java/lang/foreign/Utils.java
index 0bb7fa604a6..453025ed929 100644
--- a/test/micro/org/openjdk/bench/java/lang/foreign/Utils.java
+++ b/test/micro/org/openjdk/bench/java/lang/foreign/Utils.java
@@ -22,7 +22,7 @@
*/
package org.openjdk.bench.java.lang.foreign;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
import java.lang.reflect.Field;
diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/xor/GetArrayUnsafeXorOpImpl.java b/test/micro/org/openjdk/bench/java/lang/foreign/xor/GetArrayUnsafeXorOpImpl.java
index ae6869c40d5..0b29f925c7c 100644
--- a/test/micro/org/openjdk/bench/java/lang/foreign/xor/GetArrayUnsafeXorOpImpl.java
+++ b/test/micro/org/openjdk/bench/java/lang/foreign/xor/GetArrayUnsafeXorOpImpl.java
@@ -1,7 +1,31 @@
+/*
+ * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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.lang.foreign.xor;
import org.openjdk.bench.java.lang.foreign.Utils;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
+import org.openjdk.jmh.annotations.Fork;
import java.lang.foreign.Arena;
import java.lang.foreign.FunctionDescriptor;
@@ -14,6 +38,7 @@
import static java.lang.foreign.ValueLayout.JAVA_BYTE;
import static org.openjdk.bench.java.lang.foreign.CLayouts.*;
+@Fork(value = 3, jvmArgs = {"--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED"})
public class GetArrayUnsafeXorOpImpl implements XorOp {
static final Unsafe UNSAFE = Utils.unsafe;
diff --git a/test/micro/org/openjdk/bench/sun/misc/UnsafeOps.java b/test/micro/org/openjdk/bench/sun/misc/UnsafeOps.java
index 1d4a80e43dd..02bd357da93 100644
--- a/test/micro/org/openjdk/bench/sun/misc/UnsafeOps.java
+++ b/test/micro/org/openjdk/bench/sun/misc/UnsafeOps.java
@@ -24,7 +24,7 @@
import java.lang.reflect.Field;
import java.util.concurrent.TimeUnit;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
import org.openjdk.jmh.annotations.*;
@BenchmarkMode(Mode.AverageTime)
diff --git a/test/micro/org/openjdk/bench/vm/compiler/InterfaceCalls.java b/test/micro/org/openjdk/bench/vm/compiler/InterfaceCalls.java
index 30ee9dc53b7..e98a3b37f55 100644
--- a/test/micro/org/openjdk/bench/vm/compiler/InterfaceCalls.java
+++ b/test/micro/org/openjdk/bench/vm/compiler/InterfaceCalls.java
@@ -29,6 +29,7 @@
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Param;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
@@ -45,6 +46,11 @@
@Fork(value = 3)
public class InterfaceCalls {
+ // Whether to step iteratively through the list of interfaces, or
+ // to select one in an unpredictable way.
+ @Param({"false", "true"})
+ private boolean randomized;
+
interface FirstInterface {
public int getIntFirst();
}
@@ -241,44 +247,54 @@ public int testIfaceExtCall(Blackhole bh) {
*/
@Benchmark
public int test1stInt2Types() {
- FirstInterface ai = as[l];
- l = 1 - l;
+ FirstInterface ai = as[step(2)];
return ai.getIntFirst();
}
@Benchmark
public int test1stInt3Types() {
- FirstInterface ai = as[l];
- l = ++ l % 3;
+ FirstInterface ai = as[step(3)];
return ai.getIntFirst();
}
@Benchmark
public int test1stInt5Types() {
- FirstInterface ai = as[l];
- l = ++ l % asLength;
+ FirstInterface ai = as[step(asLength)];
return ai.getIntFirst();
}
@Benchmark
public int test2ndInt2Types() {
- SecondInterface ai = (SecondInterface) as[l];
- l = 1 - l;
+ SecondInterface ai = (SecondInterface) as[step(2)];
return ai.getIntSecond();
}
@Benchmark
public int test2ndInt3Types() {
- SecondInterface ai = (SecondInterface) as[l];
- l = ++ l % 3;
+ SecondInterface ai = (SecondInterface) as[step(3)];
return ai.getIntSecond();
}
@Benchmark
public int test2ndInt5Types() {
- SecondInterface ai = (SecondInterface) as[l];
- l = ++ l % asLength;
+ SecondInterface ai = (SecondInterface) as[step(asLength)];
return ai.getIntSecond();
}
+ int step(int range) {
+ if (randomized) {
+ l = scramble(l);
+ } else {
+ l++;
+ }
+ return (l & Integer.MAX_VALUE) % range;
+ }
+
+ static final int scramble(int n) {
+ int x = n;
+ x ^= x << 13;
+ x ^= x >>> 17;
+ x ^= x << 5;
+ return x == 0 ? 1 : x;
+ }
}
diff --git a/test/micro/org/openjdk/bench/vm/compiler/MergeStores.java b/test/micro/org/openjdk/bench/vm/compiler/MergeStores.java
index 93d98116ecc..809ec01f495 100644
--- a/test/micro/org/openjdk/bench/vm/compiler/MergeStores.java
+++ b/test/micro/org/openjdk/bench/vm/compiler/MergeStores.java
@@ -41,12 +41,12 @@
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
-@Warmup(iterations = 3, time = 3)
-@Measurement(iterations = 3, time = 3)
-@Fork(value = 3, jvmArgs = {
+@Warmup(iterations = 2, time = 1)
+@Measurement(iterations = 3, time = 1)
+@Fork(value = 1, jvmArgs = {
"--add-exports", "java.base/jdk.internal.misc=ALL-UNNAMED",
"--add-exports", "java.base/jdk.internal.util=ALL-UNNAMED"})
-@State(Scope.Benchmark)
+@State(Scope.Thread)
public class MergeStores {
public static final int RANGE = 100;
@@ -66,6 +66,7 @@ public class MergeStores {
public static byte[] aB = new byte[RANGE];
public static short[] aS = new short[RANGE];
public static int[] aI = new int[RANGE];
+ public static long native_adr = UNSAFE.allocateMemory(RANGE * 8);
// -------------------------------------------
// ------- Little-Endian API ----------
@@ -691,4 +692,59 @@ public int[] store_I2_zero_offs_nonalloc_direct() {
aI[offset + 1] = 0;
return aI;
}
+
+ @Benchmark
+ public void store_unsafe_B8_L_offs_noalloc_direct() {
+ UNSAFE.putByte(aB, Unsafe.ARRAY_BYTE_BASE_OFFSET + offset + 0, (byte)(vL >> 0 ));
+ UNSAFE.putByte(aB, Unsafe.ARRAY_BYTE_BASE_OFFSET + offset + 1, (byte)(vL >> 8 ));
+ UNSAFE.putByte(aB, Unsafe.ARRAY_BYTE_BASE_OFFSET + offset + 2, (byte)(vL >> 16));
+ UNSAFE.putByte(aB, Unsafe.ARRAY_BYTE_BASE_OFFSET + offset + 3, (byte)(vL >> 24));
+ UNSAFE.putByte(aB, Unsafe.ARRAY_BYTE_BASE_OFFSET + offset + 4, (byte)(vL >> 32));
+ UNSAFE.putByte(aB, Unsafe.ARRAY_BYTE_BASE_OFFSET + offset + 5, (byte)(vL >> 40));
+ UNSAFE.putByte(aB, Unsafe.ARRAY_BYTE_BASE_OFFSET + offset + 6, (byte)(vL >> 48));
+ UNSAFE.putByte(aB, Unsafe.ARRAY_BYTE_BASE_OFFSET + offset + 7, (byte)(vL >> 56));
+ }
+
+ @Benchmark
+ public void store_unsafe_B8_L_offs_noalloc_unsafe() {
+ UNSAFE.putLongUnaligned(aB, Unsafe.ARRAY_BYTE_BASE_OFFSET + offset + 0, vL);
+ }
+
+ @Benchmark
+ public void store_unsafe_C4_L_offs_noalloc_direct() {
+ UNSAFE.putChar(aB, Unsafe.ARRAY_BYTE_BASE_OFFSET + offset + 0, (char)(vL >> 0 ));
+ UNSAFE.putChar(aB, Unsafe.ARRAY_BYTE_BASE_OFFSET + offset + 2, (char)(vL >> 16));
+ UNSAFE.putChar(aB, Unsafe.ARRAY_BYTE_BASE_OFFSET + offset + 4, (char)(vL >> 32));
+ UNSAFE.putChar(aB, Unsafe.ARRAY_BYTE_BASE_OFFSET + offset + 6, (char)(vL >> 48));
+ }
+
+ @Benchmark
+ public void store_unsafe_native_B8_L_offs_noalloc_direct() {
+ UNSAFE.putByte(null, native_adr + offset + 0, (byte)(vL >> 0 ));
+ UNSAFE.putByte(null, native_adr + offset + 1, (byte)(vL >> 8 ));
+ UNSAFE.putByte(null, native_adr + offset + 2, (byte)(vL >> 16));
+ UNSAFE.putByte(null, native_adr + offset + 3, (byte)(vL >> 24));
+ UNSAFE.putByte(null, native_adr + offset + 4, (byte)(vL >> 32));
+ UNSAFE.putByte(null, native_adr + offset + 5, (byte)(vL >> 40));
+ UNSAFE.putByte(null, native_adr + offset + 6, (byte)(vL >> 48));
+ UNSAFE.putByte(null, native_adr + offset + 7, (byte)(vL >> 56));
+ }
+
+ @Benchmark
+ public void store_unsafe_native_C4_L_offs_noalloc_direct() {
+ UNSAFE.putChar(null, native_adr + offset + 0, (char)(vL >> 0 ));
+ UNSAFE.putChar(null, native_adr + offset + 2, (char)(vL >> 16));
+ UNSAFE.putChar(null, native_adr + offset + 4, (char)(vL >> 32));
+ UNSAFE.putChar(null, native_adr + offset + 6, (char)(vL >> 48));
+ }
+
+ @Benchmark
+ public void store_unsafe_native_B8_L_offs_noalloc_unsafe() {
+ UNSAFE.putLongUnaligned(null, native_adr + offset + 0, vL);
+ }
+
+ @Fork(value = 1, jvmArgsPrepend = {
+ "-XX:+UnlockDiagnosticVMOptions", "-XX:-MergeStores"
+ })
+ public static class MergeStoresDisabled extends MergeStores {}
}